MonsterLegion.lua 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. -- 怪物军团活动系统
  2. local this = {}
  3. MonsterLegionDefine = this
  4. -- 系统常量
  5. MonsterLegionDefine = {
  6. STATUS = {
  7. NOT_STARTED = 0, -- 未开始
  8. PREPARING = 1, -- 准备中
  9. INVADING = 2, -- 入侵中
  10. FINISHED = 3 -- 已结束
  11. },
  12. PHASE = {
  13. PREPARE = 1, -- 准备阶段
  14. WAVE_1 = 2, -- 第一波
  15. WAVE_2 = 3, -- 第二波
  16. WAVE_3 = 4, -- 第三波
  17. BOSS_WAVE = 5, -- BOSS波
  18. SETTLEMENT = 6 -- 结算阶段
  19. },
  20. ACTIVITY_CONFIG = {
  21. DURATION = 90, -- 活动持续时间(分钟)
  22. PREPARE_TIME = 15, -- 准备时间(分钟)
  23. WAVE_DURATION = 15, -- 每波持续时间(分钟)
  24. BOSS_WAVE_DURATION = 20, -- BOSS波持续时间(分钟)
  25. MIN_PLAYERS = 20, -- 最少参与玩家数
  26. MAX_WAVES = 5 -- 最大波数
  27. },
  28. DB_KEYS = {
  29. ACTIVITY_STATUS = "G$MonsterLegion_ActivityStatus",
  30. CURRENT_PHASE = "G$MonsterLegion_CurrentPhase",
  31. ACTIVITY_START_TIME = "G$MonsterLegion_ActivityStartTime",
  32. PHASE_START_TIME = "G$MonsterLegion_PhaseStartTime",
  33. PARTICIPATING_PLAYERS = "G$MonsterLegion_ParticipatingPlayers",
  34. CURRENT_WAVE = "G$MonsterLegion_CurrentWave",
  35. WAVE_MONSTERS = "G$MonsterLegion_WaveMonsters",
  36. PLAYER_SCORES = "G$MonsterLegion_PlayerScores",
  37. ALLIANCE_SCORES = "G$MonsterLegion_AllianceScores",
  38. TOTAL_KILLS = "G$MonsterLegion_TotalKills",
  39. BOSS_KILLED = "G$MonsterLegion_BossKilled"
  40. }
  41. }
  42. -- 怪物波次配置
  43. local WAVE_CONFIG = {
  44. [1] = {
  45. name = "第一波:小怪入侵",
  46. monsterTypes = {"goblin", "orc", "troll"},
  47. monsterCount = 50,
  48. monsterLevel = 100,
  49. spawnInterval = 3,
  50. difficulty = 1.0
  51. },
  52. [2] = {
  53. name = "第二波:精英怪",
  54. monsterTypes = {"elite_goblin", "elite_orc", "elite_troll"},
  55. monsterCount = 30,
  56. monsterLevel = 150,
  57. spawnInterval = 5,
  58. difficulty = 1.5
  59. },
  60. [3] = {
  61. name = "第三波:混合部队",
  62. monsterTypes = {"goblin", "orc", "troll", "elite_goblin", "elite_orc"},
  63. monsterCount = 40,
  64. monsterLevel = 200,
  65. spawnInterval = 4,
  66. difficulty = 2.0
  67. },
  68. [4] = {
  69. name = "第四波:强力精英",
  70. monsterTypes = {"elite_troll", "veteran_goblin", "veteran_orc"},
  71. monsterCount = 25,
  72. monsterLevel = 250,
  73. spawnInterval = 6,
  74. difficulty = 2.5
  75. },
  76. [5] = {
  77. name = "最终波:军团BOSS",
  78. monsterTypes = {"legion_boss"},
  79. monsterCount = 1,
  80. monsterLevel = 300,
  81. spawnInterval = 0,
  82. difficulty = 3.0
  83. }
  84. }
  85. -- 奖励配置
  86. local REWARD_CONFIG = {
  87. BASE_SCORE = 100,
  88. KILL_MULTIPLIER = 10,
  89. BOSS_KILL_BONUS = 1000,
  90. WAVE_COMPLETE_BONUS = 500,
  91. ALLIANCE_BONUS = 1.2
  92. }
  93. -- 初始化系统
  94. function this.Init()
  95. info("怪物军团活动系统初始化开始")
  96. this.StartTimers()
  97. info("怪物军团活动系统初始化完成")
  98. end
  99. -- 启动定时器
  100. function this.StartTimers()
  101. setTimer(60000, function()
  102. this.CheckAndStartActivity()
  103. end)
  104. end
  105. -- 检查并启动活动
  106. function this.CheckAndStartActivity()
  107. local now = os.time()
  108. local currentStatus = getsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS) or MonsterLegionDefine.STATUS.NOT_STARTED
  109. if currentStatus == MonsterLegionDefine.STATUS.NOT_STARTED and this.IsActivityTime(now) then
  110. this.StartActivity()
  111. elseif currentStatus == MonsterLegionDefine.STATUS.PREPARING then
  112. local startTime = getsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME) or 0
  113. if now - startTime >= MonsterLegionDefine.ACTIVITY_CONFIG.PREPARE_TIME * 60 then
  114. this.StartFirstWave()
  115. end
  116. elseif currentStatus == MonsterLegionDefine.STATUS.INVADING then
  117. local startTime = getsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME) or 0
  118. local currentWave = getsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE) or 1
  119. local waveDuration = this.GetWaveDuration(currentWave)
  120. if now - startTime >= waveDuration * 60 then
  121. this.CompleteWave(currentWave)
  122. end
  123. end
  124. end
  125. -- 检查是否为活动时间
  126. function this.IsActivityTime(now)
  127. local timeInfo = os.date("*t", now)
  128. return (timeInfo.wday == 3 or timeInfo.wday == 5) and timeInfo.hour == 19 and timeInfo.min == 0
  129. end
  130. -- 获取波次持续时间
  131. function this.GetWaveDuration(waveNumber)
  132. if waveNumber == MonsterLegionDefine.PHASE.BOSS_WAVE then
  133. return MonsterLegionDefine.ACTIVITY_CONFIG.BOSS_WAVE_DURATION
  134. else
  135. return MonsterLegionDefine.ACTIVITY_CONFIG.WAVE_DURATION
  136. end
  137. end
  138. -- 开始活动
  139. function this.StartActivity()
  140. info("怪物军团活动开始")
  141. setsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS, MonsterLegionDefine.STATUS.PREPARING)
  142. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_PHASE, MonsterLegionDefine.PHASE.PREPARE)
  143. setsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_START_TIME, os.time())
  144. setsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME, os.time())
  145. setsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS, {})
  146. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE, 0)
  147. setsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS, {})
  148. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, {})
  149. setsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES, {})
  150. setsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS, 0)
  151. setsysvar(MonsterLegionDefine.DB_KEYS.BOSS_KILLED, false)
  152. this.SendWorldNotice("怪物军团活动开始!准备阶段15分钟,所有玩家可参与")
  153. info("怪物军团活动启动完成")
  154. end
  155. -- 开始第一波
  156. function this.StartFirstWave()
  157. info("怪物军团第一波开始")
  158. setsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS, MonsterLegionDefine.STATUS.INVADING)
  159. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_PHASE, MonsterLegionDefine.PHASE.WAVE_1)
  160. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE, 1)
  161. setsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME, os.time())
  162. this.GenerateWaveMonsters(1)
  163. this.SendWorldNotice("怪物军团第一波开始!小怪入侵,请所有玩家准备战斗")
  164. end
  165. -- 生成波次怪物
  166. function this.GenerateWaveMonsters(waveNumber)
  167. local waveConfig = WAVE_CONFIG[waveNumber]
  168. if not waveConfig then return end
  169. local waveMonsters = {}
  170. for i = 1, waveConfig.monsterCount do
  171. local monsterType = waveConfig.monsterTypes[math.random(1, #waveConfig.monsterTypes)]
  172. local monster = {
  173. id = "ML_" .. waveNumber .. "_" .. i,
  174. type = monsterType,
  175. level = waveConfig.monsterLevel,
  176. hp = this.CalculateMonsterHP(waveConfig.monsterLevel, waveConfig.difficulty),
  177. maxHp = this.CalculateMonsterHP(waveConfig.monsterLevel, waveConfig.difficulty),
  178. spawnTime = os.time() + (i - 1) * waveConfig.spawnInterval,
  179. isAlive = true,
  180. waveNumber = waveNumber
  181. }
  182. table.insert(waveMonsters, monster)
  183. end
  184. setsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS, waveMonsters)
  185. info("生成第", waveNumber, "波怪物,数量:", #waveMonsters)
  186. end
  187. -- 计算怪物血量
  188. function this.CalculateMonsterHP(level, difficulty)
  189. local baseHP = level * 100
  190. return math.floor(baseHP * difficulty)
  191. end
  192. -- 完成波次
  193. function this.CompleteWave(waveNumber)
  194. info("怪物军团第", waveNumber, "波完成")
  195. if waveNumber < MonsterLegionDefine.ACTIVITY_CONFIG.MAX_WAVES then
  196. this.StartNextWave(waveNumber + 1)
  197. else
  198. this.EndActivity()
  199. end
  200. end
  201. -- 开始下一波
  202. function this.StartNextWave(waveNumber)
  203. info("怪物军团第", waveNumber, "波开始")
  204. local phase = MonsterLegionDefine.PHASE.WAVE_1 + waveNumber - 1
  205. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_PHASE, phase)
  206. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE, waveNumber)
  207. setsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME, os.time())
  208. this.GenerateWaveMonsters(waveNumber)
  209. local waveConfig = WAVE_CONFIG[waveNumber]
  210. this.SendWorldNotice("怪物军团第" .. waveNumber .. "波开始!" .. waveConfig.name)
  211. this.GiveWaveCompleteReward(waveNumber)
  212. end
  213. -- 给波次完成奖励
  214. function this.GiveWaveCompleteReward(waveNumber)
  215. local participatingPlayers = getsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS) or {}
  216. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  217. for _, playerId in ipairs(participatingPlayers) do
  218. if playerScores[playerId] then
  219. playerScores[playerId] = playerScores[playerId] + REWARD_CONFIG.WAVE_COMPLETE_BONUS
  220. end
  221. end
  222. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, playerScores)
  223. info("第", waveNumber, "波完成奖励发放完成")
  224. end
  225. -- 结束活动
  226. function this.EndActivity()
  227. info("怪物军团活动结束")
  228. setsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS, MonsterLegionDefine.STATUS.FINISHED)
  229. this.CalculateFinalResult()
  230. this.DistributeRewards()
  231. this.CleanupActivityData()
  232. this.SendWorldNotice("怪物军团活动结束!结果已公布,奖励已分配")
  233. end
  234. -- 玩家报名
  235. function this.PlayerRegister(actor)
  236. local currentStatus = getsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS) or MonsterLegionDefine.STATUS.NOT_STARTED
  237. if currentStatus == MonsterLegionDefine.STATUS.NOT_STARTED then
  238. tipinfo(actor, "活动未开始")
  239. return false
  240. end
  241. local playerId = actor:toString()
  242. local participatingPlayers = getsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS) or {}
  243. for _, id in ipairs(participatingPlayers) do
  244. if id == playerId then
  245. tipinfo(actor, "您已经报名了")
  246. return false
  247. end
  248. end
  249. table.insert(participatingPlayers, playerId)
  250. setsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS, participatingPlayers)
  251. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  252. playerScores[playerId] = 0
  253. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, playerScores)
  254. tipinfo(actor, "报名成功!请等待活动开始")
  255. info("玩家报名成功:", playerId, ",当前报名人数:", #participatingPlayers)
  256. return true
  257. end
  258. -- 记录怪物击杀
  259. function this.RecordMonsterKill(actor, monsterId)
  260. local currentStatus = getsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS) or MonsterLegionDefine.STATUS.NOT_STARTED
  261. if currentStatus ~= MonsterLegionDefine.STATUS.INVADING then
  262. return
  263. end
  264. local playerId = actor:toString()
  265. local allianceId = getbaseinfo(actor, "guildid")
  266. local participatingPlayers = getsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS) or {}
  267. local isParticipating = false
  268. for _, id in ipairs(participatingPlayers) do
  269. if id == playerId then
  270. isParticipating = true
  271. break
  272. end
  273. end
  274. if not isParticipating then
  275. return
  276. end
  277. local waveMonsters = getsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS) or {}
  278. local monster = nil
  279. for _, m in ipairs(waveMonsters) do
  280. if m.id == monsterId and m.isAlive then
  281. monster = m
  282. break
  283. end
  284. end
  285. if not monster then
  286. return
  287. end
  288. monster.isAlive = false
  289. local killScore = this.CalculateKillScore(monster)
  290. this.UpdatePlayerScore(actor, killScore)
  291. if allianceId and allianceId > 0 then
  292. this.UpdateAllianceScore(allianceId, killScore)
  293. end
  294. local totalKills = getsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS) or 0
  295. setsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS, totalKills + 1)
  296. if monster.type == "legion_boss" then
  297. setsysvar(MonsterLegionDefine.DB_KEYS.BOSS_KILLED, true)
  298. this.OnBossKilled(actor)
  299. end
  300. this.CheckWaveCompletion()
  301. info("怪物击杀记录:玩家", playerId, "击杀怪物", monsterId, ",获得分数:", killScore)
  302. end
  303. -- 计算击杀分数
  304. function this.CalculateKillScore(monster)
  305. local baseScore = REWARD_CONFIG.BASE_SCORE
  306. local levelMultiplier = monster.level / 100
  307. local difficultyMultiplier = monster.waveNumber
  308. local finalScore = math.floor(baseScore * levelMultiplier * difficultyMultiplier * REWARD_CONFIG.KILL_MULTIPLIER)
  309. if monster.type == "legion_boss" then
  310. finalScore = finalScore + REWARD_CONFIG.BOSS_KILL_BONUS
  311. end
  312. return finalScore
  313. end
  314. -- 更新玩家分数
  315. function this.UpdatePlayerScore(actor, score)
  316. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  317. local playerId = actor:toString()
  318. playerScores[playerId] = (playerScores[playerId] or 0) + score
  319. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, playerScores)
  320. end
  321. -- 更新战盟分数
  322. function this.UpdateAllianceScore(allianceId, score)
  323. local allianceScores = getsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES) or {}
  324. allianceScores[allianceId] = (allianceScores[allianceId] or 0) + score
  325. setsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES, allianceScores)
  326. end
  327. -- BOSS被击杀
  328. function this.OnBossKilled(actor)
  329. local playerId = actor:toString()
  330. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  331. playerScores[playerId] = (playerScores[playerId] or 0) + REWARD_CONFIG.BOSS_KILL_BONUS
  332. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, playerScores)
  333. this.SendWorldNotice("恭喜玩家 " .. getbaseinfo(actor, "rolename") .. " 击杀了军团BOSS!")
  334. info("军团BOSS被击杀,击杀者:", playerId)
  335. end
  336. -- 检查波次是否完成
  337. function this.CheckWaveCompletion()
  338. local waveMonsters = getsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS) or {}
  339. local aliveCount = 0
  340. for _, monster in ipairs(waveMonsters) do
  341. if monster.isAlive then
  342. aliveCount = aliveCount + 1
  343. end
  344. end
  345. if aliveCount == 0 then
  346. local currentWave = getsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE) or 1
  347. this.CompleteWave(currentWave)
  348. end
  349. end
  350. -- 计算最终结果
  351. function this.CalculateFinalResult()
  352. local totalKills = getsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS) or 0
  353. local bossKilled = getsysvar(MonsterLegionDefine.DB_KEYS.BOSS_KILLED) or false
  354. info("怪物军团活动结果:总击杀数:", totalKills, ",BOSS是否击杀:", bossKilled)
  355. end
  356. -- 分配奖励
  357. function this.DistributeRewards()
  358. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  359. local allianceScores = getsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES) or {}
  360. for playerId, score in pairs(playerScores) do
  361. if score > 0 then
  362. this.GivePlayerReward(playerId, score)
  363. end
  364. end
  365. for allianceId, score in pairs(allianceScores) do
  366. if score > 0 then
  367. this.GiveAllianceReward(allianceId, score)
  368. end
  369. end
  370. info("怪物军团活动奖励分配完成")
  371. end
  372. -- 给玩家发放奖励
  373. function this.GivePlayerReward(playerId, score)
  374. local playerActor = getactor(tonumber(playerId))
  375. if playerActor then
  376. info("玩家奖励:", playerId, ",分数:", score)
  377. end
  378. end
  379. -- 给战盟发放奖励
  380. function this.GiveAllianceReward(allianceId, score)
  381. info("战盟奖励:", allianceId, ",分数:", score)
  382. end
  383. -- 清理活动数据
  384. function this.CleanupActivityData()
  385. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_PHASE, nil)
  386. setsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_START_TIME, nil)
  387. setsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME, nil)
  388. setsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS, nil)
  389. setsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE, nil)
  390. setsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS, nil)
  391. setsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES, nil)
  392. setsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES, nil)
  393. setsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS, nil)
  394. setsysvar(MonsterLegionDefine.DB_KEYS.BOSS_KILLED, nil)
  395. info("怪物军团活动数据清理完成")
  396. end
  397. -- 发送全服公告
  398. function this.SendWorldNotice(message)
  399. info("全服公告:", message)
  400. end
  401. -- 获取活动状态
  402. function this.GetActivityStatus()
  403. return getsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_STATUS) or MonsterLegionDefine.STATUS.NOT_STARTED
  404. end
  405. -- 获取当前阶段
  406. function this.GetCurrentPhase()
  407. return getsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_PHASE) or MonsterLegionDefine.PHASE.PREPARE
  408. end
  409. -- 获取当前波次
  410. function this.GetCurrentWave()
  411. return getsysvar(MonsterLegionDefine.DB_KEYS.CURRENT_WAVE) or 0
  412. end
  413. -- 获取玩家分数排名
  414. function this.GetPlayerScoreRanking()
  415. local playerScores = getsysvar(MonsterLegionDefine.DB_KEYS.PLAYER_SCORES) or {}
  416. local playerList = {}
  417. for playerId, score in pairs(playerScores) do
  418. table.insert(playerList, {id = playerId, score = score})
  419. end
  420. table.sort(playerList, function(a, b)
  421. return a.score > b.score
  422. end)
  423. return playerList
  424. end
  425. -- 获取战盟分数排名
  426. function this.GetAllianceScoreRanking()
  427. local allianceScores = getsysvar(MonsterLegionDefine.DB_KEYS.ALLIANCE_SCORES) or {}
  428. local allianceList = {}
  429. for allianceId, score in pairs(allianceScores) do
  430. table.insert(allianceList, {id = allianceId, score = score})
  431. end
  432. table.sort(allianceList, function(a, b)
  433. return a.score > b.score
  434. end)
  435. return allianceList
  436. end
  437. -- 获取活动剩余时间
  438. function this.GetActivityRemainingTime()
  439. local currentStatus = this.GetActivityStatus()
  440. local startTime = getsysvar(MonsterLegionDefine.DB_KEYS.ACTIVITY_START_TIME) or 0
  441. local now = os.time()
  442. if currentStatus == MonsterLegionDefine.STATUS.PREPARING then
  443. return math.max(0, MonsterLegionDefine.ACTIVITY_CONFIG.PREPARE_TIME * 60 - (now - startTime))
  444. elseif currentStatus == MonsterLegionDefine.STATUS.INVADING then
  445. local phaseStartTime = getsysvar(MonsterLegionDefine.DB_KEYS.PHASE_START_TIME) or 0
  446. local currentWave = this.GetCurrentWave()
  447. local waveDuration = this.GetWaveDuration(currentWave)
  448. return math.max(0, waveDuration * 60 - (now - phaseStartTime))
  449. end
  450. return 0
  451. end
  452. -- 检查玩家是否已报名
  453. function this.IsPlayerRegistered(actor)
  454. local playerId = actor:toString()
  455. local participatingPlayers = getsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS) or {}
  456. for _, id in ipairs(participatingPlayers) do
  457. if id == playerId then
  458. return true
  459. end
  460. end
  461. return false
  462. end
  463. -- 检查玩家是否可参与活动
  464. function this.CanPlayerParticipate(actor)
  465. local currentStatus = this.GetActivityStatus()
  466. if currentStatus == MonsterLegionDefine.STATUS.NOT_STARTED then
  467. return false, "活动未开始"
  468. elseif currentStatus == MonsterLegionDefine.STATUS.PREPARING then
  469. return this.IsPlayerRegistered(actor), "请先报名参加活动"
  470. elseif currentStatus == MonsterLegionDefine.STATUS.INVADING then
  471. return this.IsPlayerRegistered(actor), "请先报名参加活动"
  472. end
  473. return false, "活动状态异常"
  474. end
  475. -- 获取当前波次怪物信息
  476. function this.GetCurrentWaveMonsters()
  477. return getsysvar(MonsterLegionDefine.DB_KEYS.WAVE_MONSTERS) or {}
  478. end
  479. -- 获取活动统计信息
  480. function this.GetActivityStats()
  481. local totalKills = getsysvar(MonsterLegionDefine.DB_KEYS.TOTAL_KILLS) or 0
  482. local bossKilled = getsysvar(MonsterLegionDefine.DB_KEYS.BOSS_KILLED) or false
  483. local currentWave = this.GetCurrentWave()
  484. local participatingPlayers = getsysvar(MonsterLegionDefine.DB_KEYS.PARTICIPATING_PLAYERS) or {}
  485. return {
  486. totalKills = totalKills,
  487. bossKilled = bossKilled,
  488. currentWave = currentWave,
  489. participantCount = #participatingPlayers,
  490. timeRemaining = this.GetActivityRemainingTime()
  491. }
  492. end
  493. return this