SecretRealm.lua 29 KB

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