WorldBoss.lua 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. -- 世界BOSS争夺战系统
  2. local this = {}
  3. WorldBoss = this
  4. -- 系统常量
  5. WorldBossDefine = {
  6. STATUS = {
  7. NOT_STARTED = 0, -- 未开始
  8. REGISTERING = 1, -- 报名中
  9. FIGHTING = 2, -- 战斗中
  10. FINISHED = 3, -- 已结束
  11. AUCTION = 4 -- 拍卖中
  12. },
  13. BOSS_TYPE = {
  14. CHIYAN_MO = 1, -- 炽焰魔
  15. ZHOUYUAN_MOWANG = 2 -- 咒怨魔王
  16. },
  17. ACTIVITY_CONFIG = {
  18. MIN_PLAYERS = 50, -- 最少报名人数
  19. REGISTER_DURATION = 30, -- 报名持续时间(分钟)
  20. FIGHT_DURATION = 60, -- 战斗持续时间(分钟)
  21. AUCTION_DURATION = 30, -- 拍卖持续时间(分钟)
  22. WEEKLY_DAY = 7, -- 每周几开启(7=周日)
  23. WEEKLY_HOUR = 20, -- 每周几点开启(20=晚上8点)
  24. WEEKLY_MINUTE = 0 -- 每周几分开启
  25. },
  26. DB_KEYS = {
  27. ACTIVITY_STATUS = "G$WorldBoss_ActivityStatus",
  28. CURRENT_BOSS = "G$WorldBoss_CurrentBoss",
  29. ACTIVITY_START_TIME = "G$WorldBoss_ActivityStartTime",
  30. REGISTERED_PLAYERS = "G$WorldBoss_RegisteredPlayers",
  31. BOSS_HP = "G$WorldBoss_BossHP",
  32. BOSS_MAX_HP = "G$WorldBoss_BossMaxHP",
  33. PLAYER_DAMAGE = "G$WorldBoss_PlayerDamage",
  34. ALLIANCE_DAMAGE = "G$WorldBoss_AllianceDamage",
  35. AUCTION_ITEMS = "G$WorldBoss_AuctionItems",
  36. AUCTION_START_TIME = "G$WorldBoss_AuctionStartTime",
  37. PLAYER_REGISTER_TIME = "T$WorldBoss_RegisterTime",
  38. PLAYER_TOTAL_DAMAGE = "T$WorldBoss_TotalDamage",
  39. PLAYER_REVIVE_COUNT = "T$WorldBoss_ReviveCount"
  40. }
  41. }
  42. -- BOSS配置
  43. local BOSS_CONFIG = {
  44. [WorldBossDefine.BOSS_TYPE.CHIYAN_MO] = {
  45. name = "炽焰魔",
  46. level = 380,
  47. baseHP = 100000000,
  48. baseDamage = 50000,
  49. hpMultiplier = 2.0,
  50. damageMultiplier = 0.5,
  51. dropConfig = {
  52. guaranteed = {
  53. {type = "equipment", count = 2, minAttrs = 3, maxAttrs = 4},
  54. {type = "set", count = 1, minAttrs = 3, maxAttrs = 4}
  55. },
  56. chance = {
  57. {type = "mount", itemId = "彩云兽", chance = 0.1},
  58. {type = "necklace", minAttrs = 2, maxAttrs = 3, chance = 0.3}
  59. }
  60. }
  61. },
  62. [WorldBossDefine.BOSS_TYPE.ZHOUYUAN_MOWANG] = {
  63. name = "咒怨魔王",
  64. level = 380,
  65. baseHP = 120000000,
  66. baseDamage = 60000,
  67. hpMultiplier = 2.5,
  68. damageMultiplier = 0.4,
  69. dropConfig = {
  70. guaranteed = {
  71. {type = "equipment", count = 2, minAttrs = 3, maxAttrs = 4},
  72. {type = "set", count = 2, minAttrs = 3, maxAttrs = 4}
  73. },
  74. chance = {
  75. {type = "mount", itemId = "1代坐骑", chance = 0.15},
  76. {type = "pet", itemId = "1代宠物", chance = 0.15},
  77. {type = "necklace", minAttrs = 2, maxAttrs = 3, chance = 0.4}
  78. }
  79. }
  80. }
  81. }
  82. -- 拍卖配置
  83. local AUCTION_CONFIG = {
  84. STARTING_PRICES = {
  85. equipment = 300,
  86. mount = 2000,
  87. pet = 2000,
  88. necklace = 10000,
  89. special = 500
  90. },
  91. COMMISSION_RATE = 0.2,
  92. ALLIANCE_DISTRIBUTION = {[1] = 0.5, [2] = 0.3, [3] = 0.2},
  93. PLAYER_DISTRIBUTION = {[1] = 0.30, [2] = 0.25, [3] = 0.20, [4] = 0.10, [5] = 0.05}
  94. }
  95. -- 初始化系统
  96. function this.Init()
  97. -- info("世界BOSS争夺战系统初始化开始")
  98. this.CheckAndStartActivity()
  99. this.StartTimers()
  100. -- info("世界BOSS争夺战系统初始化完成")
  101. end
  102. -- 检查并启动活动
  103. function this.CheckAndStartActivity()
  104. local now = os.time()
  105. local currentStatus = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS) or WorldBossDefine.STATUS.NOT_STARTED
  106. if currentStatus == WorldBossDefine.STATUS.NOT_STARTED and this.IsActivityTime(now) then
  107. this.StartActivity()
  108. elseif currentStatus == WorldBossDefine.STATUS.REGISTERING then
  109. local startTime = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_START_TIME) or 0
  110. if now - startTime >= WorldBossDefine.ACTIVITY_CONFIG.REGISTER_DURATION * 60 then
  111. this.StartFighting()
  112. end
  113. elseif currentStatus == WorldBossDefine.STATUS.FIGHTING then
  114. local startTime = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_START_TIME) or 0
  115. if now - startTime >= (WorldBossDefine.ACTIVITY_CONFIG.REGISTER_DURATION + WorldBossDefine.ACTIVITY_CONFIG.FIGHT_DURATION) * 60 then
  116. this.EndFighting()
  117. end
  118. elseif currentStatus == WorldBossDefine.STATUS.AUCTION then
  119. local auctionStartTime = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_START_TIME) or 0
  120. if now - auctionStartTime >= WorldBossDefine.ACTIVITY_CONFIG.AUCTION_DURATION * 60 then
  121. this.EndAuction()
  122. end
  123. end
  124. end
  125. -- 检查是否为活动时间
  126. function this.IsActivityTime(now)
  127. local timeInfo = os.date("*t", now)
  128. return timeInfo.wday == WorldBossDefine.ACTIVITY_CONFIG.WEEKLY_DAY and
  129. timeInfo.hour == WorldBossDefine.ACTIVITY_CONFIG.WEEKLY_HOUR and
  130. timeInfo.min == WorldBossDefine.ACTIVITY_CONFIG.WEEKLY_MINUTE
  131. end
  132. -- 启动定时器
  133. function this.StartTimers()
  134. setTimer(60000, function()
  135. this.CheckAndStartActivity()
  136. end)
  137. end
  138. -- 开始活动
  139. function this.StartActivity()
  140. -- info("世界BOSS争夺战活动开始")
  141. local bossType = math.random(1, 2)
  142. local bossConfig = BOSS_CONFIG[bossType]
  143. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.REGISTERING)
  144. setsysvar(WorldBossDefine.DB_KEYS.CURRENT_BOSS, bossType)
  145. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_START_TIME, os.time())
  146. setsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS, {})
  147. setsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE, {})
  148. setsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE, {})
  149. local bossHP = math.floor(bossConfig.baseHP * bossConfig.hpMultiplier)
  150. setsysvar(WorldBossDefine.DB_KEYS.BOSS_HP, bossHP)
  151. setsysvar(WorldBossDefine.DB_KEYS.BOSS_MAX_HP, bossHP)
  152. this.SendWorldNotice("世界BOSS争夺战开始报名!BOSS:" .. bossConfig.name .. ",报名时间30分钟,战斗时间60分钟")
  153. -- info("世界BOSS争夺战活动启动完成,BOSS类型:", bossType, ",血量:", bossHP)
  154. end
  155. -- 开始战斗
  156. function this.StartFighting()
  157. local registeredPlayers = getsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS) or {}
  158. if #registeredPlayers < WorldBossDefine.ACTIVITY_CONFIG.MIN_PLAYERS then
  159. this.CancelActivity("报名人数不足" .. WorldBossDefine.ACTIVITY_CONFIG.MIN_PLAYERS .. "人,活动取消")
  160. return
  161. end
  162. -- info("世界BOSS争夺战战斗开始,参与人数:", #registeredPlayers)
  163. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.FIGHTING)
  164. this.SendWorldNotice("世界BOSS争夺战战斗开始!所有报名玩家可进入战场参与战斗")
  165. this.TeleportPlayersToBattlefield(registeredPlayers)
  166. end
  167. -- 结束战斗
  168. function this.EndFighting()
  169. -- info("世界BOSS争夺战战斗结束")
  170. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.FINISHED)
  171. this.CalculateAllianceRanking()
  172. this.GenerateDropItems()
  173. this.StartAuction()
  174. end
  175. -- 开始拍卖
  176. function this.StartAuction()
  177. -- info("世界BOSS争夺战拍卖开始")
  178. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.AUCTION)
  179. setsysvar(WorldBossDefine.DB_KEYS.AUCTION_START_TIME, os.time())
  180. this.SendWorldNotice("世界BOSS争夺战拍卖开始!拍卖时间30分钟,所有参与战斗的玩家均可参与竞拍")
  181. this.NotifyClientAuctionStart()
  182. end
  183. -- 结束拍卖
  184. function this.EndAuction()
  185. -- info("世界BOSS争夺战拍卖结束")
  186. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.NOT_STARTED)
  187. this.ProcessAuctionResults()
  188. this.DistributeAuctionProfits()
  189. this.CleanupActivityData()
  190. this.SendWorldNotice("世界BOSS争夺战拍卖结束!收益已按规则分配")
  191. end
  192. -- 取消活动
  193. function this.CancelActivity(reason)
  194. -- info("世界BOSS争夺战活动取消,原因:", reason)
  195. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS, WorldBossDefine.STATUS.NOT_STARTED)
  196. this.CleanupActivityData()
  197. this.SendWorldNotice("世界BOSS争夺战活动取消:" .. reason)
  198. end
  199. -- 玩家报名
  200. function this.PlayerRegister(actor)
  201. local currentStatus = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS) or WorldBossDefine.STATUS.NOT_STARTED
  202. if currentStatus ~= WorldBossDefine.STATUS.REGISTERING then
  203. tipinfo(actor, "当前不在报名时间")
  204. return false
  205. end
  206. local registeredPlayers = getsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS) or {}
  207. local playerId = actor:toString()
  208. for _, id in ipairs(registeredPlayers) do
  209. if id == playerId then
  210. tipinfo(actor, "您已经报名了")
  211. return false
  212. end
  213. end
  214. table.insert(registeredPlayers, playerId)
  215. setsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS, registeredPlayers)
  216. setplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_REGISTER_TIME, os.time())
  217. setplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_TOTAL_DAMAGE, 0)
  218. setplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_REVIVE_COUNT, 0)
  219. tipinfo(actor, "报名成功!请等待战斗开始")
  220. -- info("玩家报名成功:", playerId, ",当前报名人数:", #registeredPlayers)
  221. return true
  222. end
  223. -- 记录玩家伤害
  224. function this.RecordPlayerDamage(actor, damage)
  225. local currentStatus = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS) or WorldBossDefine.STATUS.NOT_STARTED
  226. if currentStatus ~= WorldBossDefine.STATUS.FIGHTING then
  227. return
  228. end
  229. local playerId = actor:toString()
  230. local playerDamage = getsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE) or {}
  231. local allianceDamage = getsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE) or {}
  232. playerDamage[playerId] = (playerDamage[playerId] or 0) + damage
  233. setsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE, playerDamage)
  234. local allianceId = getbaseinfo(actor, "guildid")
  235. if allianceId and allianceId > 0 then
  236. allianceDamage[allianceId] = (allianceDamage[allianceId] or 0) + damage
  237. setsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE, allianceDamage)
  238. end
  239. setplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_TOTAL_DAMAGE, playerDamage[playerId])
  240. this.CheckBossDeath(damage)
  241. end
  242. -- 检查BOSS是否死亡
  243. function this.CheckBossDeath(damage)
  244. local currentHP = getsysvar(WorldBossDefine.DB_KEYS.BOSS_HP) or 0
  245. local newHP = math.max(0, currentHP - damage)
  246. setsysvar(WorldBossDefine.DB_KEYS.BOSS_HP, newHP)
  247. if newHP <= 0 then
  248. this.OnBossDeath()
  249. end
  250. end
  251. -- BOSS死亡处理
  252. function this.OnBossDeath()
  253. -- info("世界BOSS死亡")
  254. local bossType = getsysvar(WorldBossDefine.DB_KEYS.CURRENT_BOSS) or 1
  255. local bossConfig = BOSS_CONFIG[bossType]
  256. this.SendWorldNotice("世界BOSS " .. bossConfig.name .. " 已被击败!战斗结束,即将开始拍卖")
  257. setTimer(5000, function()
  258. this.EndFighting()
  259. end)
  260. end
  261. -- 计算战盟排名
  262. function this.CalculateAllianceRanking()
  263. local allianceDamage = getsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE) or {}
  264. local allianceList = {}
  265. for allianceId, damage in pairs(allianceDamage) do
  266. table.insert(allianceList, {id = allianceId, damage = damage})
  267. end
  268. table.sort(allianceList, function(a, b)
  269. return a.damage > b.damage
  270. end)
  271. setsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE, allianceList)
  272. -- info("战盟排名计算完成")
  273. end
  274. -- 生成掉落物品
  275. function this.GenerateDropItems()
  276. local bossType = getsysvar(WorldBossDefine.DB_KEYS.CURRENT_BOSS) or 1
  277. local bossConfig = BOSS_CONFIG[bossType]
  278. local dropItems = {}
  279. for _, dropConfig in ipairs(bossConfig.dropConfig.guaranteed) do
  280. for i = 1, dropConfig.count do
  281. local item = this.GenerateDropItem(dropConfig)
  282. if item then
  283. table.insert(dropItems, item)
  284. end
  285. end
  286. end
  287. for _, dropConfig in ipairs(bossConfig.dropConfig.chance) do
  288. if math.random() < dropConfig.chance then
  289. local item = this.GenerateDropItem(dropConfig)
  290. if item then
  291. table.insert(dropItems, item)
  292. end
  293. end
  294. end
  295. setsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS, dropItems)
  296. -- info("掉落物品生成完成,数量:", #dropItems)
  297. end
  298. -- 生成单个掉落物品
  299. function this.GenerateDropItem(dropConfig)
  300. local item = {
  301. id = "WB_" .. os.time() .. "_" .. math.random(1000, 9999),
  302. type = dropConfig.type,
  303. name = this.GenerateItemName(dropConfig),
  304. attributes = this.GenerateItemAttributes(dropConfig),
  305. startingPrice = AUCTION_CONFIG.STARTING_PRICES[dropConfig.type] or 300
  306. }
  307. return item
  308. end
  309. -- 生成物品名称
  310. function this.GenerateItemName(dropConfig)
  311. if dropConfig.type == "equipment" then
  312. local equipmentTypes = {"红龙", "女神", "传说", "亚特兰蒂斯", "圣魂", "红翼"}
  313. return equipmentTypes[math.random(1, #equipmentTypes)] .. "装备"
  314. elseif dropConfig.type == "set" then
  315. return "卓越套装"
  316. elseif dropConfig.type == "mount" then
  317. return dropConfig.itemId or "坐骑"
  318. elseif dropConfig.type == "pet" then
  319. return dropConfig.itemId or "宠物"
  320. elseif dropConfig.type == "necklace" then
  321. return "卓越项链"
  322. end
  323. return "未知物品"
  324. end
  325. -- 生成物品属性
  326. function this.GenerateItemAttributes(dropConfig)
  327. local attrCount = math.random(dropConfig.minAttrs or 2, dropConfig.maxAttrs or 3)
  328. local attributes = {}
  329. if dropConfig.type == "necklace" then
  330. table.insert(attributes, "卓越一击")
  331. attrCount = attrCount - 1
  332. end
  333. local allAttributes = {"攻击力", "防御力", "生命值", "魔法值", "暴击率", "闪避率", "命中率", "韧性"}
  334. for i = 1, attrCount do
  335. local attr = allAttributes[math.random(1, #allAttributes)]
  336. if not table.contains(attributes, attr) then
  337. table.insert(attributes, attr)
  338. end
  339. end
  340. return attributes
  341. end
  342. -- 处理拍卖结果
  343. function this.ProcessAuctionResults()
  344. local auctionItems = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  345. for _, item in ipairs(auctionItems) do
  346. if item.winner then
  347. this.ProcessSuccessfulAuction(item)
  348. else
  349. this.ProcessFailedAuction(item)
  350. end
  351. end
  352. end
  353. -- 处理成功拍卖
  354. function this.ProcessSuccessfulAuction(item)
  355. local totalPrice = item.finalPrice
  356. local commission = math.floor(totalPrice * AUCTION_CONFIG.COMMISSION_RATE)
  357. local profit = totalPrice - commission
  358. -- info("物品拍卖成功:", item.name, ",最终价格:", totalPrice, ",手续费:", commission, ",收益:", profit)
  359. this.DistributeItemProfit(item, profit)
  360. end
  361. -- 处理流拍物品
  362. function this.ProcessFailedAuction(item)
  363. -- info("物品流拍:", item.name)
  364. end
  365. -- 分配物品收益
  366. function this.DistributeItemProfit(item, profit)
  367. local allianceDamage = getsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE) or {}
  368. for rank = 1, 3 do
  369. if allianceDamage[rank] then
  370. local allianceId = allianceDamage[rank].id
  371. local allianceShare = math.floor(profit * AUCTION_CONFIG.ALLIANCE_DISTRIBUTION[rank])
  372. if allianceShare > 0 then
  373. this.DistributeAllianceProfit(allianceId, allianceShare, rank)
  374. end
  375. end
  376. end
  377. end
  378. -- 分配战盟收益
  379. function this.DistributeAllianceProfit(allianceId, profit, rank)
  380. local playerDamage = getsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE) or {}
  381. local alliancePlayers = {}
  382. for playerId, damage in pairs(playerDamage) do
  383. local playerActor = getactor(tonumber(playerId))
  384. if playerActor then
  385. local playerAllianceId = getbaseinfo(playerActor, "guildid")
  386. if playerAllianceId == allianceId then
  387. table.insert(alliancePlayers, {id = playerId, damage = damage})
  388. end
  389. end
  390. end
  391. table.sort(alliancePlayers, function(a, b)
  392. return a.damage > b.damage
  393. end)
  394. local remainingProfit = profit
  395. local distributedCount = 0
  396. for playerRank = 1, 5 do
  397. if alliancePlayers[playerRank] and remainingProfit > 0 then
  398. local playerShare = math.floor(profit * AUCTION_CONFIG.PLAYER_DISTRIBUTION[playerRank])
  399. if playerShare > 0 then
  400. this.GivePlayerProfit(alliancePlayers[playerRank].id, playerShare)
  401. remainingProfit = remainingProfit - playerShare
  402. distributedCount = distributedCount + 1
  403. end
  404. end
  405. end
  406. if remainingProfit > 0 and #alliancePlayers > distributedCount then
  407. local averageShare = math.floor(remainingProfit / (#alliancePlayers - distributedCount))
  408. for i = distributedCount + 1, #alliancePlayers do
  409. if remainingProfit > 0 then
  410. this.GivePlayerProfit(alliancePlayers[i].id, averageShare)
  411. remainingProfit = remainingProfit - averageShare
  412. end
  413. end
  414. end
  415. -- info("战盟收益分配完成,战盟ID:", allianceId, ",排名:", rank, ",总收益:", profit)
  416. end
  417. -- 给予玩家收益
  418. function this.GivePlayerProfit(playerId, amount)
  419. local playerActor = getactor(tonumber(playerId))
  420. if playerActor then
  421. this.SendProfitMail(playerActor, amount)
  422. -- info("玩家获得分红:", playerId, ",金额:", amount)
  423. end
  424. end
  425. -- 发送分红邮件
  426. function this.SendProfitMail(actor, amount)
  427. local mailData = {
  428. title = "世界BOSS拍卖分红",
  429. content = "恭喜您在世界BOSS争夺战中获得了拍卖分红!\n分红金额:" .. amount .. " 钻石",
  430. items = {},
  431. diamonds = amount
  432. }
  433. end
  434. -- 分配拍卖收益
  435. function this.DistributeAuctionProfits()
  436. -- info("拍卖收益分配完成")
  437. end
  438. -- 清理活动数据
  439. function this.CleanupActivityData()
  440. setsysvar(WorldBossDefine.DB_KEYS.CURRENT_BOSS, nil)
  441. setsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_START_TIME, nil)
  442. setsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS, nil)
  443. setsysvar(WorldBossDefine.DB_KEYS.BOSS_HP, nil)
  444. setsysvar(WorldBossDefine.DB_KEYS.BOSS_MAX_HP, nil)
  445. setsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE, nil)
  446. setsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE, nil)
  447. setsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS, nil)
  448. setsysvar(WorldBossDefine.DB_KEYS.AUCTION_START_TIME, nil)
  449. -- info("活动数据清理完成")
  450. end
  451. -- 传送玩家到战场
  452. function this.TeleportPlayersToBattlefield(players)
  453. -- info("传送玩家到战场,玩家数量:", #players)
  454. end
  455. -- 发送全服公告
  456. function this.SendWorldNotice(message)
  457. -- info("全服公告:", message)
  458. end
  459. -- 通知客户端拍卖开始
  460. function this.NotifyClientAuctionStart()
  461. -- info("通知客户端拍卖开始")
  462. end
  463. -- 获取活动状态
  464. function this.GetActivityStatus()
  465. return getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_STATUS) or WorldBossDefine.STATUS.NOT_STARTED
  466. end
  467. -- 获取当前BOSS信息
  468. function this.GetCurrentBoss()
  469. local bossType = getsysvar(WorldBossDefine.DB_KEYS.CURRENT_BOSS)
  470. if bossType then
  471. return BOSS_CONFIG[bossType]
  472. end
  473. return nil
  474. end
  475. -- 获取BOSS血量信息
  476. function this.GetBossHPInfo()
  477. local currentHP = getsysvar(WorldBossDefine.DB_KEYS.BOSS_HP) or 0
  478. local maxHP = getsysvar(WorldBossDefine.DB_KEYS.BOSS_MAX_HP) or 0
  479. return {
  480. current = currentHP,
  481. max = maxHP,
  482. percentage = maxHP > 0 and (currentHP / maxHP * 100) or 0
  483. }
  484. end
  485. -- 获取玩家伤害排名
  486. function this.GetPlayerDamageRanking()
  487. local playerDamage = getsysvar(WorldBossDefine.DB_KEYS.PLAYER_DAMAGE) or {}
  488. local playerList = {}
  489. for playerId, damage in pairs(playerDamage) do
  490. table.insert(playerList, {id = playerId, damage = damage})
  491. end
  492. table.sort(playerList, function(a, b)
  493. return a.damage > b.damage
  494. end)
  495. return playerList
  496. end
  497. -- 获取战盟伤害排名
  498. function this.GetAllianceDamageRanking()
  499. return getsysvar(WorldBossDefine.DB_KEYS.ALLIANCE_DAMAGE) or {}
  500. end
  501. -- 获取拍卖物品列表
  502. function this.GetAuctionItems()
  503. return getsysvar(WorldBossDefine.DB_KEYS.AUCTION_ITEMS) or {}
  504. end
  505. -- 获取活动剩余时间
  506. function this.GetActivityRemainingTime()
  507. local currentStatus = this.GetActivityStatus()
  508. local startTime = getsysvar(WorldBossDefine.DB_KEYS.ACTIVITY_START_TIME) or 0
  509. local now = os.time()
  510. if currentStatus == WorldBossDefine.STATUS.REGISTERING then
  511. return math.max(0, WorldBossDefine.ACTIVITY_CONFIG.REGISTER_DURATION * 60 - (now - startTime))
  512. elseif currentStatus == WorldBossDefine.STATUS.FIGHTING then
  513. return math.max(0, (WorldBossDefine.ACTIVITY_CONFIG.REGISTER_DURATION + WorldBossDefine.ACTIVITY_CONFIG.FIGHT_DURATION) * 60 - (now - startTime))
  514. elseif currentStatus == WorldBossDefine.STATUS.AUCTION then
  515. local auctionStartTime = getsysvar(WorldBossDefine.DB_KEYS.AUCTION_START_TIME) or 0
  516. return math.max(0, WorldBossDefine.ACTIVITY_CONFIG.AUCTION_DURATION * 60 - (now - auctionStartTime))
  517. end
  518. return 0
  519. end
  520. -- 玩家复活
  521. function this.PlayerRevive(actor, useDiamond)
  522. local currentStatus = this.GetActivityStatus()
  523. if currentStatus ~= WorldBossDefine.STATUS.FIGHTING then
  524. tipinfo(actor, "当前不在战斗时间")
  525. return false
  526. end
  527. if useDiamond then
  528. local diamondCount = getitemcount(actor, "diamond")
  529. if diamondCount < 100 then
  530. tipinfo(actor, "钻石不足,无法复活")
  531. return false
  532. end
  533. removeitemfrombag(actor, "diamond", 100, 0, 9999, '世界BOSS复活')
  534. this.RevivePlayerAtPosition(actor)
  535. else
  536. this.RevivePlayerAtSafeZone(actor)
  537. end
  538. local reviveCount = getplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_REVIVE_COUNT) or 0
  539. setplaydef(actor, WorldBossDefine.DB_KEYS.PLAYER_REVIVE_COUNT, reviveCount + 1)
  540. return true
  541. end
  542. -- 原地复活玩家
  543. function this.RevivePlayerAtPosition(actor)
  544. tipinfo(actor, "原地复活成功!")
  545. end
  546. -- 安全区复活玩家
  547. function this.RevivePlayerAtSafeZone(actor)
  548. tipinfo(actor, "已回到安全区复活")
  549. end
  550. -- 检查玩家是否已报名
  551. function this.IsPlayerRegistered(actor)
  552. local registeredPlayers = getsysvar(WorldBossDefine.DB_KEYS.REGISTERED_PLAYERS) or {}
  553. local playerId = actor:toString()
  554. for _, id in ipairs(registeredPlayers) do
  555. if id == playerId then
  556. return true
  557. end
  558. end
  559. return false
  560. end
  561. -- 检查玩家是否可参与活动
  562. function this.CanPlayerParticipate(actor)
  563. local currentStatus = this.GetActivityStatus()
  564. if currentStatus == WorldBossDefine.STATUS.NOT_STARTED then
  565. return false, "活动未开始"
  566. elseif currentStatus == WorldBossDefine.STATUS.REGISTERING then
  567. return this.IsPlayerRegistered(actor), "请先报名参加活动"
  568. elseif currentStatus == WorldBossDefine.STATUS.FIGHTING then
  569. return this.IsPlayerRegistered(actor), "请先报名参加活动"
  570. elseif currentStatus == WorldBossDefine.STATUS.AUCTION then
  571. return this.IsPlayerRegistered(actor), "请先报名参加活动"
  572. end
  573. return false, "活动状态异常"
  574. end
  575. return this