SecretRealm.lua 27 KB

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