WorldBossAuction.lua 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. -- 世界BOSS拍卖系统
  2. local this = {}
  3. WorldBossAuction = {}
  4. -- 拍卖状态
  5. local AUCTION_STATUS = {
  6. WAITING = 0, -- 等待开始
  7. BIDDING = 1, -- 竞拍中
  8. FINISHED = 2, -- 已结束
  9. SOLD = 3 -- 已售出
  10. }
  11. -- 拍卖配置
  12. local AUCTION_CONFIG = {
  13. BID_INCREMENT = 0.1, -- 加价比例10%
  14. MIN_BID_INCREMENT = 50, -- 最小加价金额
  15. AUTO_EXTEND_TIME = 30, -- 自动延长时间(秒)
  16. MAX_BID_HISTORY = 20 -- 最大竞拍记录数
  17. }
  18. -- 拍卖物品数据结构
  19. local function createAuctionItem(itemData, startingPrice)
  20. return {
  21. id = itemData.id,
  22. type = itemData.type,
  23. name = itemData.name,
  24. attributes = itemData.attributes,
  25. startingPrice = startingPrice,
  26. currentPrice = startingPrice,
  27. status = AUCTION_STATUS.WAITING,
  28. startTime = 0,
  29. endTime = 0,
  30. bidders = {}, -- 竞拍者列表
  31. bidHistory = {}, -- 竞拍历史
  32. winner = nil, -- 获胜者
  33. finalPrice = 0, -- 最终价格
  34. autoExtendCount = 0 -- 自动延长次数
  35. }
  36. end
  37. -- 开始拍卖
  38. function this.StartAuction()
  39. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  40. local now = os.time()
  41. for _, item in ipairs(auctionItems) do
  42. local auctionItem = createAuctionItem(item, item.startingPrice)
  43. auctionItem.startTime = now
  44. auctionItem.endTime = now + WorldBossDefine.ACTIVITY_CONFIG.AUCTION_DURATION * 60
  45. auctionItem.status = AUCTION_STATUS.BIDDING
  46. -- 保存拍卖物品
  47. this.SaveAuctionItem(auctionItem)
  48. end
  49. -- info("世界BOSS拍卖开始,物品数量:", #auctionItems)
  50. end
  51. -- 保存拍卖物品
  52. function this.SaveAuctionItem(auctionItem)
  53. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  54. for i, item in ipairs(auctionItems) do
  55. if item.id == auctionItem.id then
  56. auctionItems[i] = auctionItem
  57. break
  58. end
  59. end
  60. setsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS, auctionItems)
  61. end
  62. -- 玩家竞拍
  63. function this.PlayerBid(actor, itemId, bidPrice)
  64. -- 检查玩家是否可参与拍卖
  65. if not this.CanPlayerParticipate(actor) then
  66. tipinfo(actor, "您不能参与此次拍卖")
  67. return false
  68. end
  69. -- 获取拍卖物品
  70. local auctionItem = this.GetAuctionItem(itemId)
  71. if not auctionItem then
  72. tipinfo(actor, "拍卖物品不存在")
  73. return false
  74. end
  75. -- 检查拍卖状态
  76. if auctionItem.status ~= AUCTION_STATUS.BIDDING then
  77. tipinfo(actor, "拍卖已结束")
  78. return false
  79. end
  80. -- 检查竞拍价格
  81. if not this.IsValidBid(auctionItem, bidPrice) then
  82. tipinfo(actor, "竞拍价格无效")
  83. return false
  84. end
  85. -- 检查玩家钻石是否足够
  86. local diamondCount = getitemcount(actor, "diamond")
  87. if diamondCount < bidPrice then
  88. tipinfo(actor, "钻石不足")
  89. return false
  90. end
  91. -- 执行竞拍
  92. local success = this.ExecuteBid(actor, auctionItem, bidPrice)
  93. if success then
  94. tipinfo(actor, "竞拍成功!当前价格:" .. bidPrice)
  95. -- 检查是否需要自动延长
  96. this.CheckAutoExtend(auctionItem)
  97. -- 通知其他玩家
  98. this.NotifyOtherBidders(auctionItem, actor, bidPrice)
  99. end
  100. return success
  101. end
  102. -- 检查玩家是否可参与拍卖
  103. function this.CanPlayerParticipate(actor)
  104. local playerDamage = getsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE) or {}
  105. local playerId = actor:toString()
  106. return playerDamage[playerId] and playerDamage[playerId] > 0
  107. end
  108. -- 获取拍卖物品
  109. function this.GetAuctionItem(itemId)
  110. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  111. for _, item in ipairs(auctionItems) do
  112. if item.id == itemId then
  113. return item
  114. end
  115. end
  116. return nil
  117. end
  118. -- 检查竞拍价格是否有效
  119. function this.IsValidBid(auctionItem, bidPrice)
  120. local minBid =
  121. auctionItem.currentPrice +
  122. math.max(math.floor(auctionItem.currentPrice * AUCTION_CONFIG.BID_INCREMENT), AUCTION_CONFIG.MIN_BID_INCREMENT)
  123. return bidPrice >= minBid
  124. end
  125. -- 执行竞拍
  126. function this.ExecuteBid(actor, auctionItem, bidPrice)
  127. local playerId = actor:toString()
  128. -- 扣除钻石
  129. local result = removeitemfrombag(actor, "diamond", bidPrice, 0, 9999, "世界BOSS竞拍")
  130. if not result then
  131. tipinfo(actor, "扣除钻石失败")
  132. return false
  133. end
  134. -- 如果有之前的竞拍者,退还钻石
  135. if auctionItem.winner then
  136. local previousWinner = getactor(tonumber(auctionItem.winner))
  137. if previousWinner then
  138. Bag.addItemToBag(previousWinner, "diamond", auctionItem.currentPrice, 0, 9999, "世界BOSS竞拍退款")
  139. tipinfo(previousWinner, "您的竞拍被超越,钻石已退还")
  140. end
  141. end
  142. -- 更新拍卖物品信息
  143. auctionItem.currentPrice = bidPrice
  144. auctionItem.winner = playerId
  145. auctionItem.finalPrice = bidPrice
  146. -- 记录竞拍历史
  147. this.RecordBidHistory(auctionItem, actor, bidPrice)
  148. -- 保存更新
  149. this.SaveAuctionItem(auctionItem)
  150. return true
  151. end
  152. -- 记录竞拍历史
  153. function this.RecordBidHistory(auctionItem, actor, bidPrice)
  154. local bidRecord = {
  155. playerId = actor:toString(),
  156. playerName = getbaseinfo(actor, "rolename"),
  157. bidPrice = bidPrice,
  158. bidTime = os.time()
  159. }
  160. table.insert(auctionItem.bidHistory, bidRecord)
  161. -- 限制历史记录数量
  162. if #auctionItem.bidHistory > AUCTION_CONFIG.MAX_BID_HISTORY then
  163. table.remove(auctionItem.bidHistory, 1)
  164. end
  165. end
  166. -- 检查是否需要自动延长
  167. function this.CheckAutoExtend(auctionItem)
  168. local now = os.time()
  169. local timeLeft = auctionItem.endTime - now
  170. -- 如果剩余时间少于30秒且有新的竞拍,自动延长
  171. if timeLeft < AUCTION_CONFIG.AUTO_EXTEND_TIME and auctionItem.autoExtendCount < 3 then
  172. auctionItem.endTime = auctionItem.endTime + AUCTION_CONFIG.AUTO_EXTEND_TIME
  173. auctionItem.autoExtendCount = auctionItem.autoExtendCount + 1
  174. this.SaveAuctionItem(auctionItem)
  175. -- 通知所有参与者
  176. this.NotifyAutoExtend(auctionItem)
  177. -- info("拍卖物品自动延长:", auctionItem.name, ",新结束时间:", auctionItem.endTime)
  178. end
  179. end
  180. -- 通知其他竞拍者
  181. function this.NotifyOtherBidders(auctionItem, currentBidder, bidPrice)
  182. local playerId = currentBidder:toString()
  183. -- 这里需要实现具体的通知逻辑
  184. -- 可以发送邮件或系统消息给其他竞拍者
  185. -- info("竞拍通知:玩家", playerId, "竞拍物品", auctionItem.name, ",价格:", bidPrice)
  186. end
  187. -- 通知自动延长
  188. function this.NotifyAutoExtend(auctionItem)
  189. -- 这里需要实现具体的通知逻辑
  190. -- info("拍卖自动延长通知:", auctionItem.name)
  191. end
  192. -- 结束拍卖
  193. function this.EndAuction()
  194. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  195. local now = os.time()
  196. for _, item in ipairs(auctionItems) do
  197. if item.status == AUCTION_STATUS.BIDDING then
  198. if now >= item.endTime then
  199. this.FinalizeAuction(item)
  200. end
  201. end
  202. end
  203. end
  204. -- 完成拍卖
  205. function this.FinalizeAuction(auctionItem)
  206. if auctionItem.winner then
  207. auctionItem.status = AUCTION_STATUS.SOLD
  208. -- info("拍卖物品售出:", auctionItem.name, ",获胜者:", auctionItem.winner, ",价格:", auctionItem.finalPrice)
  209. -- 处理物品交付
  210. this.DeliverItem(auctionItem)
  211. else
  212. auctionItem.status = AUCTION_STATUS.FINISHED
  213. -- info("拍卖物品流拍:", auctionItem.name)
  214. -- 处理流拍物品
  215. this.HandleFailedAuction(auctionItem)
  216. end
  217. this.SaveAuctionItem(auctionItem)
  218. end
  219. -- 交付物品
  220. function this.DeliverItem(auctionItem)
  221. local winner = getactor(tonumber(auctionItem.winner))
  222. if winner then
  223. -- 这里需要实现具体的物品交付逻辑
  224. -- 根据物品类型调用相应的接口
  225. tipinfo(winner, "恭喜您竞拍成功!物品:" .. auctionItem.name)
  226. -- 发送邮件通知
  227. this.SendAuctionSuccessMail(winner, auctionItem)
  228. end
  229. end
  230. -- 处理流拍物品
  231. function this.HandleFailedAuction(auctionItem)
  232. -- 流拍物品可以进入战盟拍卖或其他处理方式
  233. -- 这里可以根据具体需求设计
  234. -- info("处理流拍物品:", auctionItem.name)
  235. end
  236. -- 发送竞拍成功邮件
  237. function this.SendAuctionSuccessMail(actor, auctionItem)
  238. local mailData = {
  239. title = "竞拍成功通知",
  240. content = "恭喜您在世界BOSS拍卖中成功竞拍到物品!\n物品名称:" .. auctionItem.name .. "\n竞拍价格:" .. auctionItem.finalPrice .. " 钻石",
  241. items = {},
  242. diamonds = 0
  243. }
  244. -- 这里需要调用具体的邮件发送接口
  245. -- sendmail(actor, mailData)
  246. end
  247. -- 获取拍卖信息
  248. function this.GetAuctionInfo(actor)
  249. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  250. local now = os.time()
  251. local auctionInfo = {}
  252. for _, item in ipairs(auctionItems) do
  253. local info = {
  254. id = item.id,
  255. name = item.name,
  256. type = item.type,
  257. attributes = item.attributes,
  258. currentPrice = item.currentPrice,
  259. status = item.status,
  260. timeLeft = math.max(0, item.endTime - now),
  261. winner = item.winner,
  262. bidCount = #item.bidHistory
  263. }
  264. table.insert(auctionInfo, info)
  265. end
  266. return auctionInfo
  267. end
  268. -- 获取竞拍历史
  269. function this.GetBidHistory(itemId)
  270. local auctionItem = this.GetAuctionItem(itemId)
  271. if auctionItem then
  272. return auctionItem.bidHistory
  273. end
  274. return {}
  275. end
  276. -- 获取我的竞拍
  277. function this.GetMyBids(actor)
  278. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  279. local playerId = actor:toString()
  280. local myBids = {}
  281. for _, item in ipairs(auctionItems) do
  282. if item.winner == playerId then
  283. table.insert(
  284. myBids,
  285. {
  286. id = item.id,
  287. name = item.name,
  288. currentPrice = item.currentPrice,
  289. status = item.status,
  290. timeLeft = math.max(0, item.endTime - os.time())
  291. }
  292. )
  293. end
  294. end
  295. return myBids
  296. end
  297. -- 取消竞拍
  298. function this.CancelBid(actor, itemId)
  299. local auctionItem = this.GetAuctionItem(itemId)
  300. if not auctionItem then
  301. tipinfo(actor, "拍卖物品不存在")
  302. return false
  303. end
  304. local playerId = actor:toString()
  305. if auctionItem.winner ~= playerId then
  306. tipinfo(actor, "您不是当前最高竞拍者")
  307. return false
  308. end
  309. if auctionItem.status ~= AUCTION_STATUS.BIDDING then
  310. tipinfo(actor, "拍卖已结束,无法取消")
  311. return false
  312. end
  313. -- 退还钻石
  314. Bag.addItemToBag(actor, "diamond", auctionItem.currentPrice, 0, 9999, "世界BOSS竞拍取消退款")
  315. -- 重置竞拍状态
  316. auctionItem.winner = nil
  317. auctionItem.finalPrice = 0
  318. -- 如果有其他竞拍者,恢复之前的最高价
  319. if #auctionItem.bidHistory > 1 then
  320. local previousBid = auctionItem.bidHistory[#auctionItem.bidHistory - 1]
  321. auctionItem.currentPrice = previousBid.bidPrice
  322. auctionItem.winner = previousBid.playerId
  323. auctionItem.finalPrice = previousBid.bidPrice
  324. else
  325. auctionItem.currentPrice = auctionItem.startingPrice
  326. end
  327. this.SaveAuctionItem(auctionItem)
  328. tipinfo(actor, "竞拍已取消,钻石已退还")
  329. return true
  330. end
  331. -- 一口价购买
  332. function this.BuyNow(actor, itemId)
  333. local auctionItem = this.GetAuctionItem(itemId)
  334. if not auctionItem then
  335. tipinfo(actor, "拍卖物品不存在")
  336. return false
  337. end
  338. if auctionItem.status ~= AUCTION_STATUS.BIDDING then
  339. tipinfo(actor, "拍卖已结束")
  340. return false
  341. end
  342. -- 计算一口价(当前价格的2倍)
  343. local buyNowPrice = auctionItem.currentPrice * 2
  344. -- 检查钻石是否足够
  345. local diamondCount = getitemcount(actor, "diamond")
  346. if diamondCount < buyNowPrice then
  347. tipinfo(actor, "钻石不足")
  348. return false
  349. end
  350. -- 执行一口价购买
  351. local success = this.ExecuteBid(actor, auctionItem, buyNowPrice)
  352. if success then
  353. -- 立即结束拍卖
  354. auctionItem.status = AUCTION_STATUS.SOLD
  355. auctionItem.endTime = os.time()
  356. this.SaveAuctionItem(auctionItem)
  357. tipinfo(actor, "一口价购买成功!物品:" .. auctionItem.name)
  358. -- 交付物品
  359. this.DeliverItem(auctionItem)
  360. end
  361. return success
  362. end
  363. -- 获取推荐竞拍价格
  364. function this.GetRecommendedBidPrice(itemId)
  365. local auctionItem = this.GetAuctionItem(itemId)
  366. if not auctionItem then
  367. return 0
  368. end
  369. local minBid =
  370. auctionItem.currentPrice +
  371. math.max(math.floor(auctionItem.currentPrice * AUCTION_CONFIG.BID_INCREMENT), AUCTION_CONFIG.MIN_BID_INCREMENT)
  372. return minBid
  373. end
  374. -- 检查拍卖状态
  375. function this.CheckAuctionStatus()
  376. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  377. local now = os.time()
  378. local hasActiveAuction = false
  379. for _, item in ipairs(auctionItems) do
  380. if item.status == AUCTION_STATUS.BIDDING and now < item.endTime then
  381. hasActiveAuction = true
  382. break
  383. end
  384. end
  385. if not hasActiveAuction then
  386. -- 所有拍卖都结束了
  387. this.FinalizeAllAuctions()
  388. end
  389. end
  390. -- 完成所有拍卖
  391. function this.FinalizeAllAuctions()
  392. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  393. for _, item in ipairs(auctionItems) do
  394. if item.status == AUCTION_STATUS.BIDDING then
  395. this.FinalizeAuction(item)
  396. end
  397. end
  398. -- info("所有拍卖已完成")
  399. end
  400. -- 启动拍卖检查定时器
  401. function this.StartAuctionTimer()
  402. -- 每10秒检查一次拍卖状态
  403. setTimer(
  404. 10000,
  405. function()
  406. this.CheckAuctionStatus()
  407. end
  408. )
  409. end
  410. -- 初始化拍卖系统
  411. function this.Init()
  412. -- info("世界BOSS拍卖系统初始化")
  413. this.StartAuctionTimer()
  414. end
  415. return this