DivineTradeRoute.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. --- @class DivineTradeRouteInfo
  2. --- @field gameData DivineTradeRouteGameData 副本数据
  3. --- @field score DivineTradeRouteScoreInfo 积分
  4. --- @field rangeData table<number, DivineTradeRouteInRangeData> 商队附近范围数据
  5. --- @field rankData DivineTradeRankData 积分排名
  6. --- @field dieTimes table<number, number> 死亡次数
  7. --- @class DivineTradeRouteGameData
  8. --- @field stage number 行进阶段
  9. --- @field state number 状态 0-准备 1-进行
  10. --- @field teamMonster number 商队怪物ID
  11. --- @field teamMonsterOwner number 商队归属战盟ID
  12. --- @field teamMonsterOwnerName string 商队归属战盟名称
  13. --- @class DivineTradeRouteScoreInfo
  14. --- @field playerScore table<number, DivineTradeRoutePlayerScore> 个人积分
  15. --- @field unionScore table<number, DivineTradeRouteUnionScore> 联盟积分
  16. --- @class DivineTradeRoutePlayerScore
  17. --- @field id number 唯一ID
  18. --- @field name string 玩家名称
  19. --- @field career number 玩家职业
  20. --- @field score number 积分
  21. --- @field time number 变动时间
  22. --- @class DivineTradeRouteUnionScore
  23. --- @field id number 唯一ID
  24. --- @field name string 玩家名称
  25. --- @field killNum number 击杀数量
  26. --- @field successNum number 成功数量
  27. --- @field score number 积分
  28. --- @class DivineTradeRouteInRangeData
  29. --- @field count number 连续次数
  30. --- @field time number 时间数据
  31. --- @class DivineTradeRankData
  32. --- @field playerRank table<number> 玩家排行数据
  33. --- @field unionRank table<number> 联盟排行数据
  34. DivineTradeRoute = {}
  35. DivineTradeRoute.__index = DivineTradeRoute
  36. local this = {}
  37. this.DuplicateId = 22001
  38. this.state = {
  39. PREPARE = 0,
  40. FIGHT = 2,
  41. }
  42. this.faction = {
  43. ATTACK = 1,
  44. DEFEND = 2,
  45. }
  46. local function __globalKey()
  47. return "R$_GLOBAL_DIVINE_TRADE_ROUTE_DATA"
  48. end
  49. -- ----------------------------------------------------------------- --
  50. function DivineTradeRoute.TryEnterDuplicate(actor, duplicateId)
  51. this.tryEnterDuplicate(actor, duplicateId)
  52. end
  53. function DivineTradeRoute.DupStateUpDate(system, id, state, nextStateStartTime, configId)
  54. this.dupStateUpDate(system, id, state, nextStateStartTime, configId)
  55. end
  56. function DivineTradeRoute.AfterPlayerEnter(actor, mapId, state, nextTime, configId)
  57. this.afterPlayerEnter(actor, mapId, state, nextTime, configId)
  58. end
  59. function DivineTradeRoute.DupSecondHeart(mapId, dupConfig, state)
  60. this.dupSecondHeart(mapId, dupConfig, state)
  61. end
  62. function DivineTradeRoute.isInMap(actor)
  63. this.isInMap(actor)
  64. end
  65. function DivineTradeRoute.Attack(actor, fightData)
  66. this.playerAttack(actor, fightData)
  67. end
  68. function DivineTradeRoute.MonsterDie(mapId, killer, monCfgId, monActor)
  69. this.monsterDie(mapId, killer, monCfgId, monActor)
  70. end
  71. -- ----------------------------------------------------------------- --
  72. function this.tryEnterDuplicate(actor, duplicateId)
  73. local unionId = getbaseinfo(actor, "unionid")
  74. if string.tonumber(unionId) < 1 then
  75. this.info(actor, "还没有加入战盟")
  76. return
  77. end
  78. local level = getbaseinfo(actor, "level")
  79. if string.tonumber(level) < 400 then
  80. return
  81. end
  82. local ret = DuplicateCommon.CheckEnterConditonCommon(actor, duplicateId)
  83. if ret ~= EnterLimitResultConst.ALLOW then
  84. return
  85. end
  86. local x, y = DuplicateCommon.GetEnterPointXYCommon(duplicateId)
  87. local mapId = DuplicateCommon.CreateDupMapCommon(actor, duplicateId, true)
  88. -- 进入副本
  89. enterduplicate(actor, mapId, x, y)
  90. end
  91. function this.dupStateUpDate(system, id, state, nextStateStartTime, configId)
  92. if state == DuplicateState.PREPARE then
  93. -- initData
  94. local monsterId = ConfigDataManager.getTableValue("cfg_rep", "monster", "id", configId)
  95. local monsterActors = DuplicateCommon.DupGenMonsterCommon(id, monsterId)
  96. this.print("神域商路开始刷怪", configId, id, state, monsterActors)
  97. this.enterNextStage()
  98. elseif state == DuplicateState.FINISH then
  99. this.print("神域商路活动结束, 关闭活动")
  100. closeactivity(DuplicateType.DIVINE_TRADE_ROUTE)
  101. end
  102. end
  103. function this.afterPlayerEnter(actor, mapId, state, nextTime, configId)
  104. -- 改变攻击模式
  105. -- local dupInfo = getduplicate(mapId)
  106. -- ScriptFightModel.setScriptFightModel(actor)
  107. --
  108. -- local flagId = ScriptFightModel.FlagId.DivineTradeRoute
  109. -- ScriptFightModel.setPlayerFightModelValue(actor, flagId, 1, { 1 })
  110. end
  111. function this.killPlayer(actor, dieActor)
  112. local rid = string.tonumber(actor:toString())
  113. local targetRid = string.tonumber(dieActor:toString())
  114. if rid < 1 or targetRid < 1 then
  115. return
  116. end
  117. -- 改变玩家buff
  118. local data = DivineTradeRoute.GetGlobal()
  119. local actorCount = data.fightData[rid]
  120. data.fightData[rid] = 0
  121. delbuff(actor, 100001110)
  122. local dieActorCount = data.fightData[targetRid]
  123. delbuff(dieActor, 100001110)
  124. dieActorCount = dieActorCount + 1
  125. addbuff(dieActor, 100001110)
  126. data.fightData[targetRid] = dieActorCount
  127. data:SaveGlobal()
  128. end
  129. function this.dupSecondHeart(mapId, dupConfig, state)
  130. if state ~= this.state.FIGHT then
  131. return
  132. end
  133. local monsterId = ConfigDataManager.getTableValue("cfg_rep", "monster", "id", dupConfig)
  134. if string.tonumber(monsterId) < 1 then
  135. return
  136. end
  137. local monsters = mapbossinfo(mapId, -1, monsterId)
  138. if table.isEmpty(monsters) then
  139. return
  140. end
  141. local monster = monsters[1]
  142. local x = monster.x
  143. local y = monster.y
  144. local range = 10
  145. local actorMap = getobjectinmap(mapId, x, y, range, MapObjectType.PLAYER)
  146. if table.isEmpty(actorMap) then
  147. return
  148. end
  149. local now = math.floor(tonumber(getbaseinfo("now")) / 1000)
  150. local countLimit = 5
  151. local addScore = 1
  152. local data = DivineTradeRoute.GetGlobal()
  153. for _, rid in ipairs(actorMap) do
  154. if not data.rangeData[rid] then
  155. data.rangeData[rid] = { time = now, count = 0 }
  156. end
  157. local rangeData = data.rangeData[rid]
  158. local curCount = rangeData.count + 1
  159. if now - rangeData.time == 1 then
  160. if curCount >= countLimit then
  161. local actor = getactor(rid)
  162. data:PlayerModifyScore(actor, addScore)
  163. curCount = 0
  164. end
  165. else
  166. curCount = 1
  167. end
  168. rangeData.time = now
  169. rangeData.count = curCount
  170. end
  171. data:SaveGlobal()
  172. end
  173. function this.playerAttack(actor, fightData)
  174. if not this.isInMap(actor) then
  175. return
  176. end
  177. local targetActor = fightData["target"]
  178. local targetType = fightData["targettype"]
  179. local hurt = string.tonumber(fightData["targethurt"])
  180. if tonumber(targetType) ~= MapObjectType.MONSTER then
  181. return
  182. end
  183. local data = DivineTradeRoute.GetGlobal()
  184. data:PlayerModifyScore(actor, 1)
  185. data:SaveGlobal()
  186. end
  187. function this.isInMap(actor)
  188. local mapCfgId = getbaseinfo(actor, "mapid")
  189. local config = ConfigDataManager.getById("cfg_rep", this.DuplicateId)
  190. if config == nil then
  191. return false
  192. end
  193. if tonumber(config["mapid"]) ~= mapCfgId then
  194. return false
  195. end
  196. return true
  197. end
  198. function this.calculateRank()
  199. local data = DivineTradeRoute.GetGlobal()
  200. local scoreMap = data.score.playerScore
  201. local scoreList = table.values(scoreMap)
  202. table.sort(scoreList, this.scoreSort)
  203. local unionScoreMap = data.score.unionScore
  204. local unionScoreList = table.values(unionScoreMap)
  205. table.sort(unionScoreList, this.scoreSort)
  206. data.rankData.playerRank = scoreList
  207. data.rankData.unionRank = unionScoreList
  208. data:SaveGlobal()
  209. this.debug("------ 排序结果 -------", scoreList, unionScoreList)
  210. return scoreList
  211. end
  212. function this.scoreSort(a, b)
  213. if a.integral ~= b.integral then
  214. return b.score < a.score
  215. else
  216. return b.time < a.time
  217. end
  218. end
  219. function this.monsterDie(mapId, killer, monCfgId, monActor)
  220. if not this.isInMap(monActor) then
  221. return
  222. end
  223. local kunDunMonsterCfgId = ConfigDataManager.getTableValue("cfg_rep", "monster", "id", this.DuplicateId)
  224. if monCfgId ~= tonumber(kunDunMonsterCfgId) then
  225. return
  226. end
  227. -- 怪物死亡 切换归属
  228. local data = DivineTradeRoute.GetGlobal()
  229. local oldUnionId = data.gameData.teamMonsterOwner or 0
  230. if oldUnionId > 0 then
  231. local oldUnion = getunioninfo(oldUnionId)
  232. local memberIds = table.keys(oldUnion.memberinfos)
  233. for _, memberId in ipairs(memberIds) do
  234. --TODO 更改攻击模式为攻方
  235. end
  236. end
  237. local unionId = getbaseinfo(killer, "unionid")
  238. local ownerUnion = getunioninfo(unionId)
  239. local ownerMemberIds = table.keys(ownerUnion.memberinfos)
  240. for _, memberId in ipairs(ownerMemberIds) do
  241. --TODO 更改攻击模式为守方
  242. end
  243. data.gameData.teamMonsterOwner = tonumber(unionId)
  244. data.gameData.teamMonsterOwnerName = ownerUnion.name
  245. data:SaveGlobal()
  246. end
  247. -- ----------------------------------------------------------------- --
  248. -- DB Function --
  249. function DivineTradeRoute:SaveGlobal()
  250. this.setCrossGlobalData(__globalKey(), self)
  251. end
  252. ---@return DivineTradeRouteInfo
  253. function DivineTradeRoute.GetGlobal()
  254. local data = this.getCrossGlobalData(__globalKey())
  255. return setmetatable(data, DivineTradeRoute)
  256. end
  257. function DivineTradeRoute:PlayerModifyScore(actor, scoreChange)
  258. local now = getbaseinfo("now")
  259. local rid = tonumber(actor:toString())
  260. local playerData = self.score.playerScore[rid] or self:buildPlayerData(actor, rid, 0, now)
  261. playerData.score = math.max(0, playerData.score + scoreChange)
  262. local unionId = getbaseinfo(actor, "unionid")
  263. local unionData = self.score.unionScore[unionId] or self:buildPlayerData(unionId, 0, now)
  264. unionData.score = math.max(0, unionData.score + scoreChange)
  265. end
  266. function DivineTradeRoute:buildPlayerData(id, score, time)
  267. return { id = id, score = score, time = time }
  268. end
  269. function this.changeDupState(state)
  270. local data = DivineTradeRoute.GetGlobal()
  271. data.state = state;
  272. data:SaveGlobal()
  273. end
  274. function this.enterNextStage()
  275. local data = DivineTradeRoute.GetGlobal()
  276. data.stage = data.stage + 1;
  277. data:SaveGlobal()
  278. end
  279. function this.getCrossGlobalData(key)
  280. local serverType = string.tonumber(getbaseinfo("servertype"))
  281. local isCross = serverType == 2 and 1 or nil
  282. return getsysvar(key, isCross) or {}
  283. end
  284. function this.setCrossGlobalData(key, value)
  285. setsysvar(key, value, 1)
  286. -- 同步数据到所有主机
  287. local hosts = gethosts()
  288. for _, host in ipairs(hosts) do
  289. setsysvar(host, key, value)
  290. end
  291. end
  292. -- ----------------------------------------------------------------- --
  293. this.log_open = true
  294. this.log_name = "[DivineTradeRoute]"
  295. function this.debug(...)
  296. if not this.log_open then
  297. return
  298. end
  299. gameDebug.print(this.log_name, ...)
  300. end
  301. function this.print(...)
  302. if not this.log_open then
  303. return
  304. end
  305. if param == nil then
  306. param = "error! 输出内容为空. nil"
  307. end
  308. jprint(this.log_name, ...)
  309. end
  310. function this.info(actor, ...)
  311. info(actor, ...)
  312. this.print(...)
  313. end