DuplicateCommon.lua 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. --[[ 副本通用方法尽量走这里,可复用。
  2. 接口:
  3. 1、客户端请求进入副本 DuplicateCommon.ReqEnterDupLicate
  4. 2、客户端请求退出副本 DuplicateCommon.ReqQuitDuplicate
  5. 3、通用创建副本地图 DuplicateCommon.CreateDupMapCommon
  6. 4、多人副本,找一个还在准备阶段的空副本 DuplicateCommon.FindEnterableDupCommon
  7. 5、获取进入副本的x,y坐标 DuplicateCommon.GetEnterPointXYCommon
  8. 6、副本刷怪 DuplicateCommon.DupGenMonsterCommon
  9. 7、创建副本任务通用信息 DuplicateCommon.GenDupTaskInfoCommon
  10. 8、请求修改副本状态 DuplicateCommon.ReqChangeDupState
  11. 9、获取活动剩余次数 DuplicateCommon.ReqGetActivityLeftCount
  12. 10、副本组队通用接口,调用DuplicateCommon.CallTeamMembersPrepare;在DuplicateCommon.DoTeamEnterDup写自己的组队拉人进入逻辑
  13. 事件: 事件转移到QFunction-0.lua文件中了
  14. 1、副本阶段更新 dupstateupdate
  15. 2、怪物死亡掉落经验事件 monsterdieexp
  16. 3、玩家进入副本事件 afterenterduplicate
  17. 4、玩家退出副本事件 afterquitduplicate
  18. 5、玩家进入地图事件(可以是普通地图也可以是副本) entermap
  19. 6、地图怪物死亡事件(可以是普通地图也可以是副本) mapmonsterdie
  20. 9、玩家进入视野 PlayerEnterView
  21. 通用协议:
  22. 请求:
  23. REQ_ENTER_DUPLICATE = 2000021, -- 请求进入副本
  24. REQ_CHANGE_DUPLICATE_STATE = 2000024, -- 修改副本状态
  25. REQ_QUIT_DUPLICATE = 2000034, -- 请求退出副本
  26. 响应:
  27. RES_QUIT_DUPLICATE = 1000039, -- 退出副本回包
  28. ]]
  29. DuplicateCommon = {}
  30. local this = {}
  31. -- @description 请求获取活动剩余次数
  32. -- @param 玩家对象;活动id
  33. -- @return
  34. function DuplicateCommon.ReqGetActivityLeftCount(actor, activityId)
  35. local leftCount = getleftcountofactivity(actor, activityId)
  36. if leftCount < 0 then
  37. leftCount = 0
  38. end
  39. sendluamsg(actor, LuaMessageIdToClient.RES_GET_ACTIVITY_COUNT, { activityId, leftCount })
  40. end
  41. -- @description 客户端请求进入副本
  42. -- @param 玩家对象;cfg_rep的id
  43. -- @return
  44. function DuplicateCommon.ReqEnterDupLicate(actor, configId)
  45. -- 判断活动是否开启
  46. local activityId = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  47. gameDebug.assertNil(activityId, "活动", configId, "配置不存在!")
  48. local activityInfo = getactivityinfo(activityId)
  49. if activityInfo["open"] == nil or activityInfo["open"] == false then
  50. noticeTip.noticeinfo(actor, StringIdConst.TEXT390)
  51. return
  52. end
  53. -- 开服天数判断
  54. local startDay = ConfigDataManager.getTableValue("cfg_rep", "startDay", "id", configId)
  55. startDay = tonumber(startDay)
  56. if startDay ~= nil and startDay ~= "" then
  57. local serverOpenDays = tonumber(getserveropendays(actor))
  58. if serverOpenDays < startDay then
  59. noticeTip.noticeinfo(actor, StringIdConst.TEXT391)
  60. return
  61. end
  62. end
  63. -- 组队限制
  64. local teamType = ConfigDataManager.getTableValue("cfg_rep", "team", "id", configId)
  65. teamType = tonumber(teamType)
  66. local teamId = getbaseinfo(actor, "teamid")
  67. if teamType == DupTeamType.NONE then
  68. --不限制单人或者组队
  69. if teamId ~= 0 then
  70. local check, tip = this.TeamEnterCheck(actor)
  71. if check == false then
  72. tipinfo(actor, tip)
  73. return
  74. end
  75. end
  76. elseif teamType == DupTeamType.PERSONAL then
  77. --限制单人
  78. if teamId ~= 0 then
  79. noticeTip.noticeinfo(actor, StringIdConst.TEXT392)
  80. return
  81. end
  82. elseif teamType == DupTeamType.TEAM then
  83. --限制组队
  84. local check, tip = this.TeamEnterCheck(actor)
  85. if check == false then
  86. tipinfo(actor, tip)
  87. return
  88. end
  89. elseif teamType == DupTeamType.UNION then
  90. --TODO:组队成员必须是战盟成员
  91. end
  92. local dupType = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  93. dupType = tonumber(dupType)
  94. if dupType == DuplicateType.DEVIL_SQUARE then
  95. -- 进入恶魔广场
  96. DevilSquare.ReqEnterDevilSquare(actor, configId)
  97. elseif dupType == DuplicateType.BLOODY_CASTLE then
  98. --进入血色城堡
  99. BloodyCastle.ReqEnterBloodyCastle(actor, configId)
  100. elseif dupType == DuplicateType.BRAVE_TEST then
  101. BraveTest.ReqEnterBraveTest(actor, configId)
  102. elseif dupType == DuplicateType.RED_FORTRESS then
  103. RedFortress.ReqEnterFortress(actor, configId)
  104. elseif dupType == DuplicateType.PRIVILEGE_BOSS then
  105. PrivilegeBoss.ReqEnterPrivilegeBoss(actor, configId)
  106. elseif dupType == DuplicateType.WOLF_SOUL then
  107. WolfSoul.ReqEnterWolfSoul(actor)
  108. elseif dupType == DuplicateType.COMBO_TEST then
  109. ComboTest.ReqEnterComboTest(actor, configId)
  110. elseif dupType == DuplicateType.BIG_SECRET_REALM then
  111. BigSecretRealm.ReqEnterBigSecretRealm(actor, configId)
  112. elseif dupType == DuplicateType.ROLAND_SEIGE then
  113. RolandSeige.ReqEnterDupLicate(actor)
  114. end
  115. end
  116. -- @description 组队限制
  117. -- @param 玩家对象
  118. -- @return true | false ; 提示内容
  119. function this.TeamEnterCheck(actor)
  120. local teamId = getbaseinfo(actor, "teamid")
  121. if teamId == 0 then
  122. return false, "请先创建或加入一个队伍!"
  123. end
  124. local selfId = getbaseinfo(actor, "rid")
  125. local teamInfo = getteaminfo(actor, teamId)
  126. local leaderId = teamInfo["leaderid"]
  127. if tostring(selfId) ~= tostring(leaderId) then
  128. return false, "您不是队长!"
  129. end
  130. local members = teamInfo["allteammemberinfo"]
  131. for index, memberInfo in ipairs(members) do
  132. local memberId = memberInfo["rid"]
  133. local memberActor = getactor(actor, memberId)
  134. local inDup = this.IsInDuplicate(memberActor)
  135. if inDup then
  136. return false, "队员正在副本中!等待队员退出副本!"
  137. end
  138. end
  139. return true, ""
  140. end
  141. -- @description 是否在副本中
  142. -- @param actor
  143. -- @return true-在
  144. function DuplicateCommon.IsInDuplicate(actor)
  145. return this.IsInDuplicate(actor)
  146. end
  147. function this.IsInDuplicate(actor)
  148. local mapId = getbaseinfo(actor, "unimapid")
  149. local mapInfo = getmapinfobyid(mapId)
  150. if mapInfo["isdup"] == true then
  151. return true
  152. else
  153. return false
  154. end
  155. end
  156. -- @description 回蓝回血
  157. -- @param 玩家对象
  158. -- @return
  159. function DuplicateCommon.RecoverHPMP(actor)
  160. --设置血量
  161. local roleInfo = getplayermaininfo(actor)
  162. local maxHp = roleInfo["maxhp"]
  163. sethp(actor, maxHp)
  164. --设置蓝量
  165. local maxMap = roleInfo["maxmp"]
  166. setmp(actor, maxMap)
  167. end
  168. -- @description 通用进入限制条件检查
  169. -- @param 玩家对象,cfg_rep的id
  170. -- @return EnterLimitResultConst
  171. function DuplicateCommon.CheckEnterConditonCommon(actor, configId)
  172. local playerLevel = tonumber(getbaseinfo(actor, "level"))
  173. local levelConfig = ConfigDataManager.getTableValue("cfg_rep", "level", "id", configId)
  174. if not string.isNullOrEmpty(levelConfig) then
  175. local levelList = string.split(levelConfig, "#")
  176. local minLevel = tonumber(levelList[1])
  177. local maxLevel = tonumber(levelList[2])
  178. if playerLevel < minLevel or playerLevel > maxLevel then
  179. return EnterLimitResultConst.LEVEL
  180. end
  181. end
  182. local activityId = tonumber(ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId))
  183. if activityId == nil or activityId <= 0 then
  184. gameDebug.assertPrintTrace(false, actor:toString() .. "进入副本检查, 活动id错误,副本cfgId: " .. configId)
  185. return false
  186. end
  187. local leftCount = getleftcountofactivity(actor, activityId)
  188. if leftCount <= 0 then
  189. return EnterLimitResultConst.COUNT
  190. end
  191. local itemString = ConfigDataManager.getTableValue("cfg_rep", "itemId", "id", configId)
  192. local itemTable = string.toIntIntMap(itemString, "#", "|")
  193. for itemId, count in pairs(itemTable) do
  194. itemId = tonumber(itemId)
  195. count = tonumber(count)
  196. local ownCount = getbagitemcountbyid(actor, itemId)
  197. if ownCount < count then
  198. return EnterLimitResultConst.ITEM
  199. end
  200. end
  201. return EnterLimitResultConst.ALLOW
  202. end
  203. -- @description 通用创建副本地图
  204. -- @param 玩家对象;cfg_rep的id;是否可以离线挂机
  205. -- @return 副本地图唯一id
  206. function DuplicateCommon.CreateDupMapCommon(actor, configId, canHook)
  207. local dupConfigMap = ConfigDataManager.getById("cfg_rep", configId)
  208. local mapCfgId = dupConfigMap.mapid
  209. local type = dupConfigMap.type
  210. local prepareTime = dupConfigMap.preparetime
  211. local continuous = dupConfigMap.continuous
  212. local save = dupConfigMap.save
  213. local mapId = createduplicate(actor, mapCfgId, type, type, configId, prepareTime, continuous, save, canHook)
  214. return mapId
  215. end
  216. -- @description 多人副本,找一个还在准备阶段的空副本
  217. -- @param cfg_rep的id;空余人数
  218. -- @return 副本地图唯一id
  219. function DuplicateCommon.FindEnterableDupCommon(configId, needSize)
  220. local mapId = 0
  221. local maxSize = ConfigDataManager.getTableValue("cfg_rep", "warNumMax", "id", configId)
  222. local type = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  223. local existDupList = getduplicatelist(type)
  224. for index, dupInfo in ipairs(existDupList) do
  225. local players = dupInfo["players"]
  226. local state = dupInfo["state"]
  227. local dupConfig = dupInfo["dupcfgid"]
  228. local leftSize = tonumber(maxSize) - #players
  229. if state == DuplicateState.PREPARE and leftSize >= needSize and tonumber(dupConfig) == tonumber(configId) then
  230. mapId = dupInfo["id"]
  231. break
  232. end
  233. end
  234. return mapId
  235. end
  236. -- @description 获取进入副本的x,y坐标
  237. -- @param configId——cfg_rep的id
  238. -- @return
  239. function DuplicateCommon.GetEnterPointXYCommon(configId)
  240. local mapMoveString = ConfigDataManager.getTableValue("cfg_rep", "mapMove", "id", configId)
  241. local mapMoveIds = string.split(mapMoveString, "#")
  242. local randomIndex = math.random(#mapMoveIds)
  243. local randomId = mapMoveIds[randomIndex]
  244. local x = ConfigDataManager.getTableValue("cfg_mapMove", "mapX", "id", randomId)
  245. local y = ConfigDataManager.getTableValue("cfg_mapMove", "mapY", "id", randomId)
  246. return tonumber(x), tonumber(y)
  247. end
  248. -- @description 通用副本刷怪
  249. -- @param 地图唯一id;刷怪表id(cfg_repMonster)
  250. -- @return
  251. function DuplicateCommon.DupGenMonsterCommon(mapId, configId)
  252. local monsterStr = ConfigDataManager.getTableValue("cfg_repMonster", "monster", "id", configId)
  253. local monsterStrList = string.split(monsterStr, "|")
  254. local monsterActors = {}
  255. for _, value in ipairs(monsterStrList) do
  256. local params = string.split(value, "#")
  257. local monId = params[1]
  258. local count = params[2]
  259. local x = params[3]
  260. local y = params[4]
  261. local range = params[5]
  262. local monsterActor = mongen(mapId, x, y, range, monId, count)
  263. table.insertArray(monsterActors, monsterActor)
  264. --monsterActors[index] = monsterActor
  265. end
  266. return monsterActors
  267. end
  268. -- @description 创建副本任务通用信息
  269. -- @param 任务id
  270. -- @return 任务信息
  271. function DuplicateCommon.GenDupTaskInfoCommon(taskId)
  272. local ret
  273. local taskType = ConfigDataManager.getTableValue("cfg_repTask", "type", "id", taskId)
  274. taskType = tonumber(taskType)
  275. local param = ConfigDataManager.getTableValue("cfg_repTask", "param", "id", taskId)
  276. if taskType == DuplicateTaskType.KILL_MONSTER_COUNT then
  277. ret = { taskId, taskType, tonumber(param), 0 }
  278. elseif taskType == DuplicateTaskType.KILL_TARGET_MONSTER then
  279. local split = string.split(param, "#")
  280. local targetId = tonumber(split[1])
  281. local count = tonumber(split[2])
  282. ret = { taskId, taskType, count, 0, targetId }
  283. elseif taskType == DuplicateTaskType.PICK_TARGET_ITEM then
  284. ret = { taskId, taskType, 1, 0 }
  285. elseif taskType == DuplicateTaskType.ROLAND_SEIGE_OCCUPY then
  286. ret = { taskId, taskType, 1, 0 }
  287. end
  288. return ret
  289. end
  290. -- @description 请求退出副本
  291. -- @param 玩家对象
  292. -- @return
  293. function DuplicateCommon.ReqQuitDuplicate(actor, msgData)
  294. if msgData == nil then
  295. quitduplicate(actor)
  296. return
  297. end
  298. local type = ConfigDataManager.getTableValue("cfg_rep", "type", "id", msgData)
  299. if tonumber(type) == DuplicateType.COMBO_TEST then
  300. ComboTest.quitDuplicate(actor, msgData)
  301. elseif tonumber(type) == DuplicateType.BIG_SECRET_REALM then
  302. BigSecretRealm.quitBigSecretRealm(actor, msgData)
  303. end
  304. quitduplicate(actor)
  305. end
  306. -- @description 请求修改副本状态
  307. -- @param 玩家对象; 下一阶段
  308. -- @return
  309. function DuplicateCommon.ReqChangeDupState(actor, state)
  310. local mapId = getbaseinfo(actor, "unimapid")
  311. local mapInfo = getmapinfobyid(mapId)
  312. if mapInfo["isdup"] == false then
  313. return
  314. end
  315. setduplicatestate(mapId, state)
  316. end
  317. -- @description 玩家进入视野
  318. -- @param 玩家对象;进入视野的玩家对象
  319. -- @return
  320. function DuplicateCommon.PlayerEnterView(actor, target)
  321. local mapId = getbaseinfo(actor, "unimapid")
  322. local dupInfo = getduplicate(mapId)
  323. if dupInfo == false or dupInfo == nil then
  324. return
  325. end
  326. local dupType = dupInfo["type"]
  327. if dupType == DuplicateType.BLOODY_CASTLE then
  328. BloodyCastle.PlayerEnterView(actor, target, mapId)
  329. end
  330. end
  331. -- @description 副本组队准备
  332. -- @param 玩家对象;配置id
  333. -- @return
  334. function DuplicateCommon.CallTeamMembersPrepare(actor, configId)
  335. local teamId = getbaseinfo(actor, "teamid")
  336. local teamInfo = getteaminfo(actor, teamId)
  337. local members = teamInfo["allteammemberinfo"]
  338. for index, memberInfo in ipairs(members) do
  339. local memberId = memberInfo["rid"]
  340. local memberActor = getactor(actor, memberId)
  341. setplaydef(memberActor, PlayerDefKey.DUP_TEAM_BELONG, configId)
  342. setplaydef(memberActor, PlayerDefKey.DUP_TEAM_READY, false)
  343. end
  344. --队长默认准备
  345. setplaydef(actor, PlayerDefKey.DUP_TEAM_READY, true)
  346. DuplicateCommon.ResAllTeamPreparePanel(actor, configId)
  347. end
  348. -- @description 副本组队面板全体回包
  349. -- @param 玩家对象;配置id;除外的玩家id
  350. -- @return
  351. function DuplicateCommon.ResAllTeamPreparePanel(actor, configId, except)
  352. local teamId = getbaseinfo(actor, "teamid")
  353. local msg = DuplicateCommon.BuildTeamPrepareMsg(actor, teamId, configId)
  354. local teamInfo = getteaminfo(actor, teamId)
  355. local members = teamInfo["allteammemberinfo"]
  356. for index, memberInfo in ipairs(members) do
  357. -- todo 给客户端回包
  358. local memberId = memberInfo["rid"]
  359. if tostring(memberId) ~= tostring(except) then
  360. local memberActor = getactor(actor, memberId)
  361. sendluamsg(memberActor, LuaMessageIdToClient.RES_DUPLICATE_TEAM_INFO, msg)
  362. end
  363. end
  364. end
  365. -- @description 副本组队面板回包
  366. -- @param 玩家对象;配置id
  367. -- @return
  368. function DuplicateCommon.ResTeamPreparePanel(actor, configId)
  369. local teamId = getbaseinfo(actor, "teamid")
  370. local msg = DuplicateCommon.BuildTeamPrepareMsg(actor, teamId, configId)
  371. sendluamsg(actor, LuaMessageIdToClient.RES_DUPLICATE_TEAM_INFO, msg)
  372. end
  373. -- @descrip0tion 构建组队准备消息
  374. -- @param 玩家对象;队伍id
  375. -- @return 响应消息
  376. function DuplicateCommon.BuildTeamPrepareMsg(actor, teamId, configId)
  377. local msg = {}
  378. local teamInfo = getteaminfo(actor, teamId)
  379. local members = teamInfo["allteammemberinfo"]
  380. local memberList = {}
  381. for index, memberInfo in ipairs(members) do
  382. local innerData = {}
  383. local memberId = memberInfo["rid"]
  384. local memberActor = getactor(actor, memberId)
  385. --玩家名字
  386. local memberName = getrolefield(memberActor, "role.basic.name")
  387. local check = DuplicateCommon.CheckEnterConditonCommon(memberActor, configId)
  388. if check == EnterLimitResultConst.ALLOW then
  389. local ready = getplaydef(memberActor, PlayerDefKey.DUP_TEAM_READY)
  390. if ready ~= true then
  391. check = EnterLimitResultConst.REFUSE
  392. end
  393. end
  394. --玩家职业
  395. local career = getrolefield(memberActor, "role.basic.career.basecareer")
  396. innerData["rid"] = memberId
  397. innerData["name"] = memberName
  398. innerData["state"] = check
  399. innerData["career"] = career
  400. table.insert(memberList, innerData)
  401. end
  402. msg["members"] = memberList
  403. -- 副本配置id
  404. msg["configId"] = configId
  405. -- 队长id
  406. msg["leaderid"] = teamInfo["leaderid"]
  407. return msg
  408. end
  409. -- @description 修改副本组队状态
  410. -- @param 玩家对象;状态
  411. -- @return
  412. function DuplicateCommon.ChangeTeamPrepareState(actor, state)
  413. local configId = getplaydef(actor, PlayerDefKey.DUP_TEAM_BELONG)
  414. state = tonumber(state)
  415. local teamId = getbaseinfo(actor, "teamid")
  416. local name = getrolefield(actor, "role.basic.name")
  417. if state == DupTeamChangeState.READY then
  418. if DuplicateCommon.CheckEnterConditonCommon(actor, configId) ~= EnterLimitResultConst.ALLOW then
  419. return
  420. end
  421. setplaydef(actor, PlayerDefKey.DUP_TEAM_READY, true)
  422. DuplicateCommon.ResAllTeamPreparePanel(actor, configId)
  423. elseif state == DupTeamChangeState.REFUSE then
  424. setplaydef(actor, PlayerDefKey.DUP_TEAM_READY, false)
  425. DuplicateCommon.ResAllBreakDupTeam(actor, teamId)
  426. DuplicateCommon.ResTipsAllTeam(actor, teamId, name .. "取消进入副本")
  427. elseif state == DupTeamChangeState.BREAK then
  428. local selfId = getbaseinfo(actor, "rid")
  429. local teamInfo = getteaminfo(actor, teamId)
  430. local leaderId = teamInfo["leaderid"]
  431. if tostring(selfId) ~= tostring(leaderId) then
  432. gameDebug.assertPrintTrace(false, selfId .. "不是队长,解散副本组队!")
  433. return
  434. end
  435. DuplicateCommon.ResAllBreakDupTeam(actor, teamId)
  436. DuplicateCommon.ResTipsAllTeam(actor, teamId, name .. "取消进入副本")
  437. end
  438. end
  439. -- @description 副本队伍全体tips
  440. -- @param 玩家对象
  441. -- @return
  442. function DuplicateCommon.ResTipsAllTeam(actor, teamId, tip)
  443. local teamInfo = getteaminfo(actor, teamId)
  444. local members = teamInfo["allteammemberinfo"]
  445. for index, memberInfo in ipairs(members) do
  446. local memberId = memberInfo["rid"]
  447. local memberActor = getactor(actor, memberId)
  448. tipinfo(memberActor, tip)
  449. end
  450. end
  451. -- @description 副本队伍解散全体回包
  452. -- @param 玩家对象
  453. -- @return
  454. function DuplicateCommon.ResAllBreakDupTeam(actor, teamId)
  455. local teamInfo = getteaminfo(actor, teamId)
  456. local members = teamInfo["allteammemberinfo"]
  457. for index, memberInfo in ipairs(members) do
  458. local memberId = memberInfo["rid"]
  459. local memberActor = getactor(actor, memberId)
  460. DuplicateCommon.ResBreakDupTeam(memberActor)
  461. end
  462. end
  463. -- @description 副本队伍解散回包
  464. -- @param 玩家对象
  465. -- @return
  466. function DuplicateCommon.ResBreakDupTeam(actor)
  467. setplaydef(actor, PlayerDefKey.DUP_TEAM_READY, false)
  468. setplaydef(actor, PlayerDefKey.DUP_TEAM_BELONG, 0)
  469. sendluamsg(actor, LuaMessageIdToClient.RES_BREAK_DUPLICATE_TEAM, nil)
  470. end
  471. -- @description 倒计时结束,队长拉人进入
  472. -- @param 玩家对象
  473. -- @return
  474. function DuplicateCommon.DoTeamEnterDup(actor)
  475. local configId = getplaydef(actor, PlayerDefKey.DUP_TEAM_BELONG)
  476. if configId <= 0 or configId == nil then
  477. return
  478. end
  479. local teamId = getbaseinfo(actor, "teamid")
  480. local selfId = getbaseinfo(actor, "rid")
  481. local teamInfo = getteaminfo(actor, teamId)
  482. local leaderId = teamInfo["leaderid"]
  483. if tostring(selfId) ~= tostring(leaderId) then
  484. gameDebug.assertPrintTrace(false, selfId .. "不是队长,组队进入副本!")
  485. return
  486. end
  487. local members = teamInfo["allteammemberinfo"]
  488. for index, memberInfo in ipairs(members) do
  489. local memberId = memberInfo["rid"]
  490. local memberActor = getactor(actor, memberId)
  491. local name = getrolefield(memberActor, "role.basic.name")
  492. local ready = getplaydef(memberActor, PlayerDefKey.DUP_TEAM_READY)
  493. if ready ~= true then
  494. DuplicateCommon.ResTipsAllTeam(actor, teamId, name .. "未准备")
  495. return
  496. end
  497. end
  498. local dupType = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  499. dupType = tonumber(dupType)
  500. if dupType == DuplicateType.DEVIL_SQUARE then
  501. DevilSquare.DoTeamEnter(actor, teamId, configId)
  502. elseif dupType == DuplicateType.BLOODY_CASTLE then
  503. --进入血色城堡
  504. BloodyCastle.DoTeamEnter(actor, teamId, configId)
  505. end
  506. end
  507. ---根据地图信息获取怪物数量
  508. ---@param actor 玩家对象
  509. ---@param msgData 消息对象 mapCfgId:地图configId、line:地图线路、monsterCfgId:怪物configId、state:怪物状态(1:未死亡,0:所有)
  510. function DuplicateCommon.getmonstercountbymap(actor, msgData)
  511. local mapCfgId = msgData.mapCfgId
  512. if not mapCfgId then
  513. error("getmonstercountbymap param mapCfgId is nil")
  514. return
  515. end
  516. local line = msgData.line
  517. if not line then
  518. error("getmonstercountbymap param line is nil")
  519. return
  520. end
  521. local monsterCfgId = msgData.monsterCfgId
  522. if not monsterCfgId then
  523. error("getmonstercountbymap param monsterCfgId is nil")
  524. return
  525. end
  526. local state = msgData.state
  527. if not state then
  528. error("getmonstercountbymap param state is nil")
  529. return
  530. end
  531. local monsterCount = getmapmonstercountbyid(actor, tonumber(mapCfgId), tonumber(line), tonumber(monsterCfgId),
  532. tonumber(state))
  533. sendluamsg(
  534. actor,
  535. LuaMessageIdToClient.MONSTER_COUNT_RESULT,
  536. {
  537. mapCfgId = mapCfgId,
  538. line = line,
  539. monsterCfgId = monsterCfgId,
  540. state = state,
  541. monsterCount = monsterCount
  542. }
  543. )
  544. end
  545. ---根据boss表id获取怪物数量
  546. ---@param actor 玩家对象
  547. ---@param msgData 消息对象 id:cfg_BOSS_challenge表id、state:怪物状态(1:未死亡,0:所有)
  548. function DuplicateCommon.getmonstercountbyid(actor, msgData)
  549. local res = {}
  550. for _, value in pairs(msgData) do
  551. local id = value.id
  552. if not id then
  553. error("getmonstercountbyid param id is nil")
  554. return
  555. end
  556. local state = value.state
  557. if not state then
  558. error("getmonstercountbyid param state is nil")
  559. return
  560. end
  561. local tableResult = ConfigDataManager.getTable("cfg_BOSS_challenge", "id", id)
  562. if not tableResult or not next(tableResult) then
  563. error("getmonstercountbyid tableResult is nil")
  564. return
  565. end
  566. local monsterCfgId = tableResult[1].monsterid
  567. local mapId = tableResult[1].mapid
  568. local dupType = tableResult[1].monstertype
  569. local temp = {}
  570. for _, v in pairs(string.split(mapId, "|")) do
  571. local mapInfo = string.split(v, "#")
  572. for i = 2, #mapInfo, 2 do
  573. local mapCfgId = mapInfo[i - 1]
  574. local line = mapInfo[i]
  575. local monsterCount = this.getMosnterCount(actor, dupType, tonumber(mapCfgId), tonumber(line), tonumber(monsterCfgId), tonumber(state))
  576. table.insert(temp, {
  577. id = tonumber(id),
  578. mapCfgId = tonumber(mapCfgId),
  579. line = tonumber(line),
  580. monsterCfgId = tonumber(monsterCfgId),
  581. state = tonumber(state),
  582. monsterCount = tonumber(monsterCount)
  583. })
  584. end
  585. end
  586. res[id] = temp
  587. end
  588. sendluamsg(actor, LuaMessageIdToClient.MONSTER_COUNT_RESULT_BY_ID, res)
  589. end
  590. -- @description 退出游戏
  591. -- @param 玩家对象
  592. -- @return
  593. function DuplicateCommon.OfflineQuitGame(actor)
  594. local ready = getplaydef(actor, PlayerDefKey.DUP_TEAM_READY)
  595. if ready then
  596. DuplicateCommon.ChangeTeamPrepareState(actor, DupTeamChangeState.REFUSE)
  597. end
  598. end
  599. function this.getMosnterCount(actor, dupType, mapId, line, monsterId, state)
  600. if tonumber(dupType) == 5 then
  601. -- 跨服圣域BOSS, 缓存中获取
  602. return SanctuaryBoss.getMonsterCount(mapId, line, monsterId, state)
  603. end
  604. return getmapmonstercountbyid(actor, tonumber(mapId), tonumber(line), tonumber(monsterId), state)
  605. end
  606. ---更新副本任务进度
  607. function this.UpdateDupTask(actor, reqCfgId, dupType)
  608. TaskHandler.TriggerTaskGoal(actor, TaskTargetType.FINISH_DUPLICATE, dupType)
  609. TaskHandler.TriggerTaskGoal(actor, TaskTargetType.FINISH_GOAL_DUP, reqCfgId)
  610. end
  611. function this.RecordDupCount(actor, reqCfgId, dupType)
  612. this.RecordDupFinishCount(actor, dupType, PlayerDefKey.duplicate.DUP_TYPE_FINISH_COUNT)
  613. this.RecordDupFinishCount(actor, reqCfgId, PlayerDefKey.duplicate.DUP_FLOOR_FINISH_COUNT)
  614. end
  615. function this.RecordDupFinishCount(actor, countKey, varName)
  616. if string.isNullOrEmpty(varName) then
  617. return
  618. end
  619. local countRecord = getplaydef(actor, varName)
  620. if countRecord == nil then
  621. countRecord = {}
  622. end
  623. local oldCount = tonumber(countRecord[countKey])
  624. if oldCount == nil then
  625. oldCount = 0
  626. end
  627. countRecord[countKey] = oldCount + 1
  628. setplaydef(actor, varName, countRecord)
  629. end
  630. ---获取副本完成次数
  631. function DuplicateCommon.GetDupFinishCount(actor, countKey, varName)
  632. if varName == nil or countKey == nil then
  633. return 0
  634. end
  635. local countRecord = getplaydef(actor, varName)
  636. if table.isNullOrEmpty(countRecord) then
  637. return 0
  638. end
  639. local totalCount = countRecord[countKey]
  640. if totalCount == nil then
  641. return 0
  642. end
  643. return tonumber(totalCount)
  644. end
  645. ---@description 完成一次副本活动后调用
  646. ---@param actor table 玩家对象
  647. ---@param reqCfgId number cfg_rep的id
  648. function DuplicateCommon.FinishDupActivity(actor, reqCfgId)
  649. local typeParam = ConfigDataManager.getTableValue("cfg_rep", "type", "id", reqCfgId)
  650. if typeParam == nil then
  651. return
  652. end
  653. local dupType = tonumber(typeParam)
  654. local contains = table.contains(DuplicateType, dupType)
  655. ---未定义的副本类型
  656. if not contains then
  657. return
  658. end
  659. local cfgId = tonumber(reqCfgId)
  660. --更新副本完成次数
  661. this.RecordDupCount(actor, cfgId, dupType)
  662. --更新任务进度
  663. this.UpdateDupTask(actor, cfgId, dupType)
  664. end
  665. ---@description 扫荡副本
  666. ---@param actor 玩家对象
  667. ---@param configId number cfg_rep的id
  668. ---@param count number 扫荡副本次数
  669. function DuplicateCommon.sweepThroughDungeons(actor, configId, count)
  670. if DuplicateCommon.CheckEnterCountConditonCommon(actor, configId, count) ~= EnterLimitResultConst.ALLOW then
  671. return
  672. end
  673. local dupType = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  674. dupType = tonumber(dupType)
  675. if dupType == DuplicateType.COMBO_TEST then
  676. -- 连击试炼
  677. ComboTest.sweepThroughDungeons(actor, configId, count)
  678. end
  679. end
  680. -- @description 通用进入限制条件检查
  681. -- @param 玩家对象,cfg_rep的id
  682. -- @return EnterLimitResultConst
  683. function DuplicateCommon.CheckEnterCountConditonCommon(actor, configId, count)
  684. local playerLevel = tonumber(getbaseinfo(actor, "level"))
  685. local levelConfig = ConfigDataManager.getTableValue("cfg_rep", "level", "id", configId)
  686. if not string.isNullOrEmpty(levelConfig) then
  687. local levelList = string.split(levelConfig, "#")
  688. local minLevel = tonumber(levelList[1])
  689. local maxLevel = tonumber(levelList[2])
  690. if playerLevel < minLevel or playerLevel > maxLevel then
  691. print("等级不足")
  692. return EnterLimitResultConst.LEVEL
  693. end
  694. end
  695. local activityId = ConfigDataManager.getTableValue("cfg_rep", "type", "id", configId)
  696. local leftCount = getleftcountofactivity(actor, activityId)
  697. if leftCount <= 0 or leftCount < count then
  698. print("次数不足")
  699. return EnterLimitResultConst.COUNT
  700. end
  701. local itemString = ConfigDataManager.getTableValue("cfg_rep", "itemId", "id", configId)
  702. local itemTable = string.toIntIntMap(itemString, "#", "|")
  703. for itemId, needCount in pairs(itemTable) do
  704. itemId = tonumber(itemId)
  705. needCount = tonumber(needCount) * count
  706. local ownCount = getbagitemcountbyid(actor, itemId)
  707. if ownCount < needCount then
  708. print("道具不足", itemId, ownCount, needCount)
  709. return EnterLimitResultConst.ITEM
  710. end
  711. end
  712. return EnterLimitResultConst.ALLOW
  713. end