SecretRealm_1.lua 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. -- 秘境副本 由于秘境副本比较特殊,无法复用副本大多数通用方法,所以没有使用通用方法,单独开发
  2. SecretRealm = {}
  3. local this = {}
  4. function SecretRealm.isSecretRealmMap(mapCfgId)
  5. local type = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "monstertype", "repId", mapCfgId)
  6. return tonumber(type) == 3
  7. end
  8. function SecretRealm.UpdateHurtTopRank(uniqueMapId, mapCfgId)
  9. if not SecretRealm.isSecretRealmMap(mapCfgId) then
  10. return
  11. end
  12. local monActors = getmapmon(uniqueMapId)
  13. local playActors = getmapplayer(uniqueMapId)
  14. for _, playerActor in ipairs(playActors) do
  15. for _, monsterActor in pairs(monActors) do
  16. SecretRealm.getTop1HurtInfo0(playerActor, monsterActor:toString())
  17. end
  18. end
  19. end
  20. --- 请求进入秘境副本
  21. ---@param actor 玩家对象
  22. ---@param repId cfg_repfairyland表id
  23. function SecretRealm.reqEnterSecretRealm(actor, msgData)
  24. local repId = msgData["repId"]
  25. local tableValue = ConfigDataManager.getTable("cfg_repfairyland", "id", repId)
  26. if not tableValue then
  27. gameDebug.print("reqEnterSecretRealm cfg_repfairyland is nil")
  28. return
  29. end
  30. -- 检查进入秘境副本的条件
  31. if not this.checkEnterSecretRealmCondition(actor, tableValue[1]) then
  32. return
  33. end
  34. setplaydef(actor, PlayerDefKey.secretRealm.LAST_MAP_ID, getbaseinfo(actor, "mapid"))
  35. -- 满足条件执行传送进副本操作
  36. local mapId = tableValue[1]["mapid"]
  37. local mapMove = tableValue[1]["mapmove"]
  38. local x = ConfigDataManager.getTableValue("cfg_mapMove", "mapX", "id", mapMove)
  39. local y = ConfigDataManager.getTableValue("cfg_mapMove", "mapY", "id", mapMove)
  40. maptransfer(actor, x, y, mapId, 1)
  41. end
  42. --- 获取剩余挑战次数
  43. ---@param actor 玩家对象
  44. function SecretRealm.sendRemainingChallenges(actor)
  45. local secretRealmCount = getplaydef(actor, PlayerDefKey.secretRealm.COUNT)
  46. sendluamsg(actor, LuaMessageIdToClient.SECRET_REALM_COUNT, {
  47. count = secretRealmCount and secretRealmCount or 0
  48. })
  49. end
  50. --- 进入地图后处理
  51. ---@param actor 玩家对象
  52. ---@param lastMapCfgId 上一个地图id
  53. ---@param mapCfgId 当前地图id
  54. function SecretRealm.afterEnterSecretRealm(actor, lastMapCfgId, mapCfgId)
  55. lastMapCfgId = tonumber(lastMapCfgId)
  56. mapCfgId = tonumber(mapCfgId)
  57. if lastMapCfgId == mapCfgId then
  58. gameDebug.print("afterEnterSecretRealm lastMapCfgId == mapCfgId")
  59. return
  60. end
  61. if this.isSecretRealmMap(mapCfgId) then
  62. -- 如果次数为0踢出副本
  63. if getplaydef(actor, PlayerDefKey.secretRealm.COUNT) <= 0 then
  64. SecretRealm.reqExitSecretRealm(actor)
  65. return
  66. end
  67. -- 清除自身所有buff,并将血量和蓝量补满,刷新回血、技能的冷却时间
  68. -- 清除自身所有buff
  69. clearallbuff(actor)
  70. -- 血量和蓝量补满
  71. sethp(actor, getattrinfo(actor, "maxHP"))
  72. setmp(actor, getattrinfo(actor, "maxMP"))
  73. -- 刷新技能的冷却时间
  74. clearallskillcd(actor)
  75. -- 获取当前地图的boss信息
  76. local monsterId = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "monsterid", "repid", mapCfgId)
  77. local mapId = gamemap.getMapKey(mapCfgId, 1)
  78. local monsterInfo = mapbossinfo(actor, mapId, 3, monsterId)
  79. sendluamsg(actor, LuaMessageIdToClient.AFTER_ENTER_SECRET_REALM, {
  80. mapId = mapCfgId,
  81. monsterInfo = monsterInfo,
  82. time = 0,
  83. })
  84. end
  85. end
  86. --- 退出秘境副本
  87. ---@param actor 玩家对象
  88. function SecretRealm.reqExitSecretRealm(actor)
  89. -- 请求退出副本
  90. local mapId = getplaydef(actor, PlayerDefKey.secretRealm.LAST_MAP_ID)
  91. local x
  92. local y
  93. if mapId then
  94. x, y = CustomTransmit.GetPointFromMapMove(mapId)
  95. else
  96. local career = tonumber(getbaseinfo(actor, "getbasecareer"))
  97. local set = ConfigDataManager.getTableValue("cfg_character_create", "set", "id", career)
  98. local set_split = string.split(set, "#")
  99. mapId = set_split[1]
  100. x = set_split[2]
  101. y = set_split[3]
  102. end
  103. maptransfer(actor, x, y, mapId)
  104. -- 删除该玩家的对怪物的伤害信息
  105. SecretRealm.removePlayerHurt(actor, 0)
  106. sendluamsg(actor, LuaMessageIdToClient.RES_QUIT_SECRET_REALM, {})
  107. end
  108. --- 首次登录初始化秘境挑战次数
  109. ---@param actor 玩家对象
  110. function SecretRealm.login(actor)
  111. local count = getplaydef(actor, PlayerDefKey.secretRealm.COUNT)
  112. if not count then
  113. local secretRealmCountInit = ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.SECRET_REALM_INIT)
  114. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, tonumber(secretRealmCountInit))
  115. end
  116. local refreshTime = getplaydef(actor, PlayerDefKey.secretRealm.COUNT_REFRESH_TIME)
  117. if string.isNullOrEmpty(refreshTime) then
  118. setplaydef(actor, PlayerDefKey.secretRealm.COUNT_REFRESH_TIME, getbaseinfo("nowsec"))
  119. else
  120. local diff = TimeUtil.diffDays(refreshTime, getbaseinfo("nowsec"))
  121. if diff ~= 0 then
  122. -- 次数刷新
  123. local activityRule = ConfigDataManager.getTable("cfg_activity_rule", "id", DuplicateType.SECRET_REALM_BOSS)
  124. local numberAdd = activityRule[1]["numberadd"]
  125. if not string.isNullOrEmpty(numberAdd) then
  126. local numSplit = string.split(numberAdd, "#")
  127. local secretRealmCountStep = tonumber(numSplit[1])
  128. local secretRealmMaxCount = tonumber(numSplit[2])
  129. for i = 1, diff do
  130. SecretRealm.incrementedSecretRealmCount(actor, secretRealmCountStep, secretRealmMaxCount)
  131. end
  132. end
  133. end
  134. end
  135. -- 判断重新登录后玩家是否在秘境地图中,在秘境地图中并且没有超时发送消息给客户端
  136. local currentMapId = getbaseinfo(actor, "mapid")
  137. local countZeroTime = getplaydef(actor, PlayerDefKey.secretRealm.COUNT_ZERO_TIME)
  138. if this.isSecretRealmMap(currentMapId) and not string.isNullOrEmpty(countZeroTime) then
  139. local timeDiff = getbaseinfo(actor, "nowsec") - countZeroTime
  140. if countZeroTime and timeDiff > 30 then
  141. -- 退出秘境地图
  142. SecretRealm.reqExitSecretRealm(actor)
  143. else
  144. -- 获取当前地图的boss信息
  145. local monsterId = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "monsterid", "repid", currentMapId)
  146. local mapCfgId = gamemap.getMapKey(currentMapId, 1)
  147. local monsterInfo = mapbossinfo(actor, mapCfgId, 3, monsterId)
  148. sendluamsg(actor, LuaMessageIdToClient.AFTER_ENTER_SECRET_REALM, {
  149. mapId = currentMapId,
  150. monsterInfo = monsterInfo,
  151. time = 30 - timeDiff,
  152. })
  153. end
  154. end
  155. end
  156. --- 减少秘境副本挑战次数
  157. ---@param actor 玩家对象
  158. ---@param monsterId 怪物配置id
  159. ---@param mapId 地图唯一id
  160. function SecretRealm.reduceCount(actor, monsterId, mapId)
  161. local mapCfgId, _ = gamemap.parseMapKey(mapId)
  162. if this.isSecretRealmBoss(monsterId) and this.isSecretRealmMap(mapCfgId) then
  163. local passCount = getplaydef(actor, PlayerDefKey.secretRealm.PASS_COUNT)
  164. if string.isNullOrEmpty(passCount) then
  165. passCount = 0
  166. end
  167. setplaydef(actor, PlayerDefKey.secretRealm.PASS_COUNT, passCount + 1)
  168. info(actor, getbaseinfo(actor, "rolename") .. "玩家通关秘境次数=====================>" .. passCount + 1)
  169. local count = tonumber(getplaydef(actor, PlayerDefKey.secretRealm.COUNT))
  170. if count == 0 then
  171. return
  172. elseif count == 1 then
  173. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, 0)
  174. sendluamsg(actor, LuaMessageIdToClient.SECRET_REALM_COUNT_ZEROED, {
  175. secretRealmCount = 0
  176. })
  177. -- 记录玩家挑战次数为0的时间
  178. setplaydef(actor, PlayerDefKey.secretRealm.COUNT_ZERO_TIME, getbaseinfo(actor, "nowsec"))
  179. if isofflineplay(actor) then
  180. local exitMapId = getplaydef(actor, PlayerDefKey.secretRealm.LAST_MAP_ID)
  181. local x
  182. local y
  183. if exitMapId then
  184. x, y = CustomTransmit.GetPointFromMapMove(exitMapId)
  185. else
  186. local career = tonumber(getbaseinfo(actor, "getbasecareer"))
  187. local set = ConfigDataManager.getTableValue("cfg_character_create", "set", "id", career)
  188. local set_split = string.split(set, "#")
  189. exitMapId = set_split[1]
  190. x = set_split[2]
  191. y = set_split[3]
  192. end
  193. maptransfer(actor, x, y, exitMapId)
  194. end
  195. -- 删除该玩家的对怪物的伤害信息
  196. SecretRealm.removePlayerHurt(actor, 0)
  197. elseif count > 1 then
  198. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, count - 1)
  199. else
  200. return
  201. end
  202. -- 宝箱直接发放到背包中
  203. local repId = ConfigDataManager.getTableValue("cfg_repfairyland", "id", "mapid", mapCfgId)
  204. local boxDrop = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "boxdrop", "repid", repId, "monsterid", monsterId)
  205. if not boxDrop then
  206. gameDebug.printTraceback("cfg_BOSS_challenge boxdrop is nil repId:[" .. repId .. "] monsterId:[" .. monsterId)
  207. return
  208. end
  209. local boxDropTable = string.split(boxDrop, "#")
  210. -- 专属奖励只有一个,所以此处没有循环遍历
  211. additemtobag(actor, boxDropTable[1], boxDropTable[2], 0, 9999, '秘境boss')
  212. -- 刷新任务进度
  213. TaskHandler.TriggerTaskGoal(actor, TaskTargetType.FINISH_SECRET_REALM_DUPLICATE, repId)
  214. end
  215. end
  216. --- 增加秘境副本挑战次数
  217. ---@param actor table 玩家对象
  218. ---@param secretRealmCountStep number 每日增加次数
  219. ---@param secretRealmMaxCount number 最大次数
  220. function SecretRealm.incrementedSecretRealmCount(actor, secretRealmCountStep, secretRealmMaxCount)
  221. local count = getplaydef(actor, PlayerDefKey.secretRealm.COUNT)
  222. -- 初始化玩家通关秘境次数
  223. setplaydef(actor, PlayerDefKey.secretRealm.PASS_COUNT, 0)
  224. -- 重置玩家挑战次数为0的时间
  225. setplaydef(actor, PlayerDefKey.secretRealm.COUNT_ZERO_TIME, "")
  226. -- 设置玩家挑战次数刷新的时间
  227. setplaydef(actor, PlayerDefKey.secretRealm.COUNT_REFRESH_TIME, getbaseinfo("nowsec"))
  228. if count then
  229. info(actor, actor:toString() .. getbaseinfo(actor,"rolename") .. "玩家秘境副本次数刷新 count:" .. count)
  230. if tonumber(count) + secretRealmCountStep > secretRealmMaxCount then
  231. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, secretRealmMaxCount)
  232. else
  233. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, tonumber(count) + secretRealmCountStep)
  234. end
  235. else
  236. info(actor, actor:toString() .. getbaseinfo(actor,"rolename") .. "玩家秘境副本次数刷新")
  237. local secretRealmCountInit = ConfigDataManager.getTableValue("cfg_global", "value", "id", GlobalConfigId.SECRET_REALM_INIT)
  238. setplaydef(actor, PlayerDefKey.secretRealm.COUNT, tonumber(secretRealmCountInit))
  239. end
  240. end
  241. --- 获取秘境副本怪物数量
  242. ---@param actor 玩家对象
  243. ---@param msgData 请求参数
  244. function SecretRealm.getMonsterCount(actor, msgData)
  245. local repId = msgData["repId"]
  246. if not repId then
  247. gameDebug.print("SecretRealm.getMonsterCount repId is nil")
  248. return
  249. end
  250. local res = {}
  251. local monsterInfo = ConfigDataManager.getTableValue("cfg_repfairyland_monster", "monster1", "id", repId)
  252. if not monsterInfo then
  253. return
  254. end
  255. local monsterList = string.split(monsterInfo, "|")
  256. for _, value in pairs(monsterList) do
  257. local splitString = string.split(value, "#")
  258. local monsterId = splitString[1]
  259. local x = splitString[3]
  260. local y = splitString[4]
  261. local range = splitString[5]
  262. local aiId = ConfigDataManager.getTableValue("cfg_monster", "ai", "id", monsterId)
  263. local maxMove = ConfigDataManager.getTableValue("cfg_monster_ai", "leavebasedistance", "id", aiId)
  264. local mapId = gamemap.getMapKey(repId, 1)
  265. local maxRange = range + tonumber(maxMove) + 1
  266. local monsterCount = getalivemonsterinmap(actor, mapId, x, y, maxRange)
  267. if monsterCount and table.count(monsterCount) > 0 then
  268. table.insert(res, {
  269. repId = tonumber(repId),
  270. x = tonumber(x),
  271. y = tonumber(y),
  272. range = tonumber(range),
  273. monsterId = tonumber(monsterId),
  274. count = table.count(monsterCount),
  275. time = 0
  276. })
  277. else
  278. local monInfo = mapbossinfo(actor, mapId, 3)
  279. if not table.isNullOrEmpty(monInfo) then
  280. for _, v in pairs(monInfo) do
  281. local minX = x - maxRange
  282. local maxX = x + maxRange
  283. local minY = y - maxRange
  284. local maxY = y + maxRange
  285. if v.isdead and v.x >= minX and v.x <= maxX and v.y >= minY and v.y <= maxY then
  286. local monId = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "monsterid", "repid", repId)
  287. local ai = ConfigDataManager.getTableValue("cfg_monster", "ai", "id", monId)
  288. local reliveDelay, reliveServiceTime = this.getMonsterReliveTime(ai)
  289. local dieTime = getsysvar(actor, string.format(PlayerDefKey.secretRealm.BOSS_TIME_BY_ID, v.id))
  290. if not string.isNullOrEmpty(dieTime) then
  291. dieTime = tonumber(dieTime) + tonumber(reliveDelay) + tonumber(reliveServiceTime)
  292. end
  293. table.insert(res, {
  294. repId = tonumber(repId),
  295. x = tonumber(x),
  296. y = tonumber(y),
  297. range = tonumber(range),
  298. monsterId = tonumber(monId),
  299. count = 0,
  300. time = tostring(dieTime and dieTime or 0),
  301. id = v.id
  302. })
  303. end
  304. end
  305. end
  306. end
  307. end
  308. sendluamsg(actor, LuaMessageIdToClient.SEND_SECRET_REALM_MONSTER_COUNT, res)
  309. end
  310. --- 保存玩家实时伤害信息
  311. ---@param actor 玩家对象
  312. ---@param target 攻击怪物id
  313. ---@param hurt 造成的伤害
  314. function SecretRealm.savePlayerHurtInfo(actor, target, hurt)
  315. local hurtTable = getsysvar(actor, PlayerDefKey.secretRealm.HURT)
  316. if not hurtTable then
  317. hurtTable = {}
  318. end
  319. local roleName = getbaseinfo(actor, "rolename")
  320. local exist = false
  321. if hurtTable then
  322. for k, _ in pairs(hurtTable) do
  323. if tostring(k) == target:toString() then
  324. exist = true
  325. end
  326. end
  327. end
  328. if not exist then
  329. local temp = {}
  330. temp[roleName] = hurt
  331. hurtTable[target:toString()] = temp
  332. setsysvar(actor, PlayerDefKey.secretRealm.HURT, hurtTable)
  333. else
  334. for k, v in pairs(hurtTable) do
  335. if tostring(k) == target:toString() then
  336. if v[roleName] then
  337. v[roleName] = v[roleName] + hurt
  338. else
  339. v[roleName] = hurt
  340. end
  341. end
  342. end
  343. setsysvar(actor, PlayerDefKey.secretRealm.HURT, hurtTable)
  344. end
  345. this.sendSecretRealmHurt(actor, target)
  346. end
  347. --- 删除对应玩家存储的实时伤害
  348. ---@param actor 玩家对象
  349. function SecretRealm.removePlayerHurt(actor, monsterId)
  350. local hurtTable = getsysvar(actor, PlayerDefKey.secretRealm.HURT)
  351. local roleName = getbaseinfo(actor, "rolename")
  352. if table.isNullOrEmpty(hurtTable) then
  353. return
  354. end
  355. if monsterId == 0 then
  356. -- 删除该玩家所有伤害信息
  357. for _, value in pairs(hurtTable) do
  358. for k, v in pairs(value) do
  359. if k == roleName then
  360. value[roleName] = nil
  361. end
  362. end
  363. end
  364. setsysvar(actor, PlayerDefKey.secretRealm.HURT, hurtTable)
  365. else
  366. -- 清空对应怪物的伤害记录
  367. hurtTable[tostring(monsterId)] = nil
  368. setsysvar(actor, PlayerDefKey.secretRealm.HURT, hurtTable)
  369. end
  370. end
  371. --- boss死亡删除伤害信息与发送怪物列表信息
  372. ---@param actor 玩家对象
  373. ---@param mapId 地图唯一id
  374. ---@param monCfgId 怪物配置id
  375. ---@param monsterId 怪物id
  376. function SecretRealm.recordMonsterDie(actor, mapId, monCfgId, monsterId)
  377. local mapCfgId, _ = gamemap.parseMapKey(mapId)
  378. if this.isSecretRealmBoss(monCfgId) and this.isSecretRealmMap(mapCfgId) then
  379. setsysvar(actor, string.format(PlayerDefKey.secretRealm.BOSS_TIME_BY_ID, monsterId), getbaseinfo("now"))
  380. this.sendMonsterListInfo(actor, mapId)
  381. SecretRealm.removePlayerHurt(actor, monsterId)
  382. end
  383. end
  384. --- 发送怪物列表信息
  385. ---@param actor 玩家对象
  386. ---@param msgData 客户端数据——地图id
  387. function SecretRealm.ReqBossList(actor, msgData)
  388. local mapId = msgData["mapId"]
  389. if not mapId then
  390. gameDebug.print("SecretRealm.ReqBossList mapId is nil")
  391. return
  392. end
  393. mapId = gamemap.getMapKey(mapId, 1)
  394. this.sendMonsterListInfo(actor, mapId)
  395. end
  396. --- 请求获取对制定怪物造成伤害的第一名信息
  397. function SecretRealm.getTop1HurtInfo(actor, msgData)
  398. local monsterId = msgData["monsterId"]
  399. SecretRealm.getTop1HurtInfo0(actor, monsterId)
  400. end
  401. function SecretRealm.getTop1HurtInfo0(actor, monsterId)
  402. local hurtInfo = getsysvar(actor, PlayerDefKey.secretRealm.HURT)
  403. local info = {}
  404. if hurtInfo then
  405. for _, v in pairs(hurtInfo) do
  406. for key, value in pairs(v) do
  407. if tostring(key) == tostring(monsterId) then
  408. info = value
  409. end
  410. end
  411. end
  412. end
  413. if table.isNullOrEmpty(info) then
  414. return
  415. end
  416. local message = {}
  417. local top1 = this.getTopN(info, 1)
  418. if table.isNullOrEmpty(top1) then
  419. message["monsterId"] = tonumber(monsterId)
  420. else
  421. message["monsterId"] = tonumber(monsterId)
  422. message["name"] = top1[1].name
  423. message["hurt"] = top1[1].hurt
  424. end
  425. sendluamsg(actor, LuaMessageIdToClient.SECRET_REALM_HURT_TOP1, message)
  426. end
  427. --- 判断是否满足进入秘境副本的要求
  428. ---@param actor 玩家对象
  429. ---@param tableValue cfg_repfairyland表单行记录
  430. ---@return boolean 是否可以进入秘境副本,true-可以进入,false-不能进入
  431. function this.checkEnterSecretRealmCondition(actor, tableValue)
  432. -- 判断当前地图是否是在秘境地图中,如果在秘境地图先退出再进入
  433. local mapId = getbaseinfo(actor, "mapid")
  434. if this.isSecretRealmMap(mapId) then
  435. noticeTip.noticeinfo(actor, StringIdConst.DUPLICATE_CAN_NOT_TRANSMIT)
  436. return false
  437. end
  438. -- 等级判断
  439. local level = tableValue["level"]
  440. if string.isNullOrEmpty(level) then
  441. gameDebug.print("checkEnterSecretRealmCondition cfg_repfairyland level is nil")
  442. else
  443. local actorLevel = getbaseinfo(actor, "level")
  444. if tonumber(level) > tonumber(actorLevel) then
  445. tipinfo(actor, string.format("等级不满足,%s等级后开启", level))
  446. return false
  447. end
  448. end
  449. -- 进入次数判断
  450. local secretRealmCount = getplaydef(actor, PlayerDefKey.secretRealm.COUNT)
  451. if string.isNullOrEmpty(secretRealmCount) or tonumber(secretRealmCount) <= 0 then
  452. tipinfo(actor, "今日次数不足")
  453. return false
  454. end
  455. -- 全身穿戴装备强化等级判断
  456. local strengthenLevel = tableValue["strengthenlevel"]
  457. if string.isNullOrEmpty(strengthenLevel) then
  458. gameDebug.print("checkEnterSecretRealmCondition cfg_repfairyland strengthenLevel is nil")
  459. else
  460. if not string.isNullOrEmpty(strengthenLevel) then
  461. -- 获取全身强化等级
  462. local allStrengthLevel = EquipAndAppear.allequipstrengthlv(actor)
  463. if tonumber(allStrengthLevel) < tonumber(strengthenLevel) then
  464. tipinfo(actor, string.format("强化等级不满足,需要全身穿戴装备强化等级到达%s级",
  465. strengthenLevel))
  466. return false
  467. end
  468. end
  469. end
  470. -- 开服天数限制
  471. local startDay = tableValue["startday"]
  472. if string.isNullOrEmpty(startDay) then
  473. gameDebug.print("checkEnterSecretRealmCondition cfg_repfairyland startDay is nil")
  474. else
  475. if not string.isNullOrEmpty(startDay) then
  476. local serverOpenDays = tonumber(getserveropendays(actor))
  477. return tonumber(startDay) <= serverOpenDays
  478. end
  479. end
  480. return true
  481. end
  482. --- 判断怪物类型是否是秘境副本中的怪物类型
  483. ---@param monCfgId 怪物id
  484. ---@return boolean true——是,false——否
  485. function this.isSecretRealmBoss(monCfgId)
  486. local bossChallenge = ConfigDataManager.getTable("cfg_BOSS_challenge", "monsterType", BossType.SECRET_REALM_BOSS)
  487. for i = 1, #bossChallenge do
  488. if tonumber(monCfgId) == tonumber(bossChallenge[i].monsterid) then
  489. return true
  490. end
  491. end
  492. return false
  493. end
  494. --- 判断指定地图是否为秘境副本地图
  495. ---@param mapId 地图id
  496. ---@return boolean 是否为秘境副本地图
  497. function this.isSecretRealmMap(mapId)
  498. local tableValue = ConfigDataManager.getList("cfg_repfairyland")
  499. for _, value in pairs(tableValue) do
  500. if tostring(value.id) == tostring(mapId) then
  501. return true
  502. end
  503. end
  504. return false
  505. end
  506. --- 发送秘境副本玩家实时伤害消息
  507. ---@param actor 玩家对象
  508. ---@param monsterId 怪物id
  509. function this.sendSecretRealmHurt(actor, monsterId)
  510. local roleName = getbaseinfo(actor, "rolename")
  511. local hurtInfo = getsysvar(actor, PlayerDefKey.secretRealm.HURT)
  512. local info = {}
  513. if hurtInfo then
  514. for k, v in pairs(hurtInfo) do
  515. if tostring(k) == monsterId:toString() then
  516. info = v
  517. end
  518. end
  519. end
  520. if table.isNullOrEmpty(info) then
  521. gameDebug.print("sendSecretRealmHurt hurtInfo is nil")
  522. return
  523. end
  524. local message = {}
  525. message["monsterId"] = monsterId:toString()
  526. local top3 = this.getTopN(info, 3)
  527. message["top3"] = top3
  528. local rank = 0
  529. for key, value in pairs(info) do
  530. rank = rank + 1
  531. if key == roleName then
  532. message["my"] = {
  533. name = roleName,
  534. hurt = value,
  535. rank = this.getRank(info, roleName)
  536. }
  537. end
  538. end
  539. sendluamsg(actor, LuaMessageIdToClient.SECRET_REALM_DAMAGE, message)
  540. end
  541. --- 发送秘境boss列表信息
  542. ---@param actor 玩家对象
  543. ---@param mapId 地图id
  544. function this.sendMonsterListInfo(actor, mapId)
  545. local mapCfgId = gamemap.parseMapKey(mapId)
  546. local monsterId = ConfigDataManager.getTableValue("cfg_BOSS_challenge", "monsterid", "repid", mapCfgId)
  547. local ai = ConfigDataManager.getTableValue("cfg_monster", "ai", "id", monsterId)
  548. local reliveDelayTime, reliveServiceTime = this.getMonsterReliveTime(ai)
  549. local monsterInfo = mapbossinfo(actor, mapId, 3)
  550. local message = {}
  551. if not table.isNullOrEmpty(monsterInfo) then
  552. for _, value in pairs(monsterInfo) do
  553. local dieTime = getsysvar(actor, string.format(PlayerDefKey.secretRealm.BOSS_TIME_BY_ID, value.id))
  554. if not string.isNullOrEmpty(dieTime) then
  555. dieTime = tonumber(dieTime) + tonumber(reliveDelayTime) + tonumber(reliveServiceTime)
  556. end
  557. table.insert(message, {
  558. monsterId = value.id,
  559. monsterName = value.name,
  560. x = value.x,
  561. y = value.y,
  562. reviveTime = tostring(dieTime and dieTime or 0)
  563. })
  564. end
  565. end
  566. sendluamsg(actor, LuaMessageIdToClient.SECRET_REALM_BOSS_LIST, message)
  567. end
  568. --- 获取boss复活时间
  569. ---@param id 怪物id
  570. function this.getMonsterReliveTime(id)
  571. local aiConfig = ConfigDataManager.getById("cfg_monster_ai", id)
  572. if aiConfig == nil then
  573. gameDebug.print("cfg_monster_ai为nil id:" .. id)
  574. return 0, 0
  575. end
  576. local reliveType = tonumber(aiConfig['relivetype'])
  577. local reliveDelay = aiConfig['relivedelay']
  578. local reliveServiceTime = 0
  579. if reliveType == 4 then
  580. local str = aiConfig['reliveservicetime']
  581. if string.isNullOrEmpty(str) then
  582. return 0, 0
  583. end
  584. local strShuXian = string.split(str, "|")
  585. local serverOpenDays = tonumber(getbaseinfo("serveropendays"))
  586. local cfg = {}
  587. for _, v in pairs(strShuXian) do
  588. local strJinHao = string.split(v, "#")
  589. local day = tonumber(strJinHao[1])
  590. if serverOpenDays >= day then
  591. cfg = strJinHao
  592. end
  593. end
  594. if table.isNullOrEmpty(cfg) then
  595. gameDebug.print("updateMonsterReliveTime 未找到匹配的数据 开服天数:" .. tostring(serverOpenDays) .. ",reliveDelay字段内容:" .. str)
  596. return
  597. end
  598. reliveServiceTime = tonumber(cfg[2])
  599. end
  600. if string.isNullOrEmpty(reliveDelay) then
  601. reliveDelay = 0
  602. end
  603. return reliveDelay, reliveServiceTime
  604. end
  605. --- 获取指定数据中的前N个数据
  606. ---@param info table 数据
  607. ---@param N number 前N个
  608. ---@return table 前N个数据
  609. function this.getTopN(info, N)
  610. local temp = {}
  611. for k, _ in pairs(info) do
  612. table.insert(temp, k)
  613. end
  614. table.sort(temp, function(a, b)
  615. return info[a] > info[b]
  616. end)
  617. local topNKey = table.getTopN(N, temp)
  618. local topN = {}
  619. for _, key in ipairs(topNKey) do
  620. table.insert(topN, {
  621. name = key,
  622. hurt = info[key]
  623. })
  624. end
  625. return topN
  626. end
  627. function this.getRank(info, key)
  628. local temp = {}
  629. for k, _ in pairs(info) do
  630. table.insert(temp, k)
  631. end
  632. table.sort(temp, function(a, b)
  633. return info[a] > info[b]
  634. end)
  635. for index, k in ipairs(temp) do
  636. if k == key then
  637. return index
  638. end
  639. end
  640. end
  641. --- 玩家死亡清空该玩家伤害
  642. --- @param actor table 玩家对象
  643. function SecretRealm.playerDie(actor)
  644. local mapId = getbaseinfo(actor, "mapid")
  645. if this.isSecretRealmMap(mapId) then
  646. SecretRealm.removePlayerHurt(actor, 0)
  647. end
  648. end
  649. --- 秘境副本次数刷新
  650. function SecretRealm.refreshCount(actor)
  651. local serverType = getbaseinfo("servertype")
  652. if serverType == 2 then
  653. return
  654. end
  655. local seconds = getbaseinfo("nowsec")
  656. local now = TimeUtil.timeToDate(seconds)
  657. if now.min == 0 then
  658. local activityRule = ConfigDataManager.getTable("cfg_activity_rule", "id", DuplicateType.SECRET_REALM_BOSS)
  659. local numberTime = activityRule[1]["numbertime"]
  660. local numberAdd = activityRule[1]["numberadd"]
  661. if not string.isNullOrEmpty(numberTime) and not string.isNullOrEmpty(numberAdd) then
  662. local split = string.split(numberTime, "#")
  663. local type = tonumber(split[1])
  664. local numberTime1 = tonumber(split[2])
  665. local numSplit = string.split(numberAdd, "#")
  666. local secretRealmCountStep = tonumber(numSplit[1])
  667. local secretRealmMaxCount = tonumber(numSplit[2])
  668. if type == 1 then
  669. if numberTime1 == now.hour then
  670. SecretRealm.incrementedSecretRealmCount(actor, secretRealmCountStep, secretRealmMaxCount)
  671. end
  672. else
  673. local numberTime2 = tonumber(split[3])
  674. if numberTime1 == now.wday and numberTime2 == now.hour then
  675. SecretRealm.incrementedSecretRealmCount(actor, secretRealmCountStep, secretRealmMaxCount)
  676. end
  677. end
  678. end
  679. end
  680. end
  681. --- 初始化所有玩家的秘境刷新时间变量值
  682. function SecretRealm.initPlayerVar()
  683. local init = getsysvar("R$_SecretRealmInitVar")
  684. if string.isNullOrEmpty(init) then
  685. local allRoleInfos = getallrolesummaryinfos()
  686. if table.isNullOrEmpty(allRoleInfos) then
  687. return
  688. end
  689. for _, roleInfo in pairs(allRoleInfos) do
  690. local actor = roleInfo["actor"]
  691. setplaydef(actor, PlayerDefKey.secretRealm.COUNT_REFRESH_TIME, getbaseinfo("nowsec"))
  692. end
  693. setsysvar("R$_SecretRealmInitVar", 1)
  694. end
  695. end
  696. ZeroEventListerTable:eventLister("0", "秘境副本次数刷新", SecretRealm.refreshCount)