BattleWillLogic.lua 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. ------------------------------------------------------
  2. -- 战意逻辑
  3. ------------------------------------------------------
  4. local Lang = require("common.Lang")
  5. local Util = require("common.Util")
  6. local Msg = require("core.Msg")
  7. local ObjHuman = require("core.ObjHuman")
  8. local Broadcast = require("broadcast.Broadcast")
  9. local Grid = require("bag.Grid")
  10. local BagLogic = require("bag.BagLogic")
  11. local ItemDefine = require("bag.ItemDefine")
  12. local HeroLogic = require("hero.HeroLogic")
  13. local Log = require("common.Log")
  14. local FuwenExcel = require("excel.fuwen")
  15. local BingshuLogic = require("fuwen.BingshuLogic")
  16. -- 战意回退配置
  17. local BATTLE_WILL_ROLLBACK_CONFIG = {
  18. [1] = { -- 初级
  19. needItemID = 1050, -- 消耗道具ID
  20. needItemCnt = 1, -- 消耗数量:1个
  21. returnBattleWillCnt = 1, -- 返还战意:1个
  22. returnFragmentID = 177, -- 返还战意碎片道具ID
  23. returnFragmentCnt = 0, -- 返还战意碎片:0
  24. returnAncientSpiritID = 135, -- 返还远古之灵道具ID
  25. returnAncientSpiritCnt = 0 -- 返还远古之灵:0
  26. },
  27. [2] = { -- 中级
  28. needItemID = 1050,
  29. needItemCnt = 5, -- 消耗数量:5个
  30. returnBattleWillCnt = 4, -- 返还战意:4个
  31. returnFragmentID = 177,
  32. returnFragmentCnt = 10000, -- 返还战意碎片:10,000
  33. returnAncientSpiritID = 135,
  34. returnAncientSpiritCnt = 0
  35. },
  36. [3] = { -- 高级
  37. needItemID = 1050,
  38. needItemCnt = 12, -- 消耗数量:12个
  39. returnBattleWillCnt = 9, -- 返还战意:9个
  40. returnFragmentID = 177,
  41. returnFragmentCnt = 40000, -- 返还战意碎片:40,000
  42. returnAncientSpiritID = 135,
  43. returnAncientSpiritCnt = 0
  44. },
  45. [4] = { -- 超级
  46. needItemID = 1050,
  47. needItemCnt = 50, -- 消耗数量:50个
  48. returnBattleWillCnt = 19, -- 返还战意:19个
  49. returnFragmentID = 177,
  50. returnFragmentCnt = 90000, -- 返还战意碎片:90,000
  51. returnAncientSpiritID = 135,
  52. returnAncientSpiritCnt = 100 -- 返还远古之灵:100
  53. }
  54. }
  55. -- 从配置表中动态获取战意技能组ID
  56. -- 配置表中 skill 表的所有技能都是战意技能
  57. local function getBattleWillGroupIDs()
  58. local groupIDs = {}
  59. local groupIDSet = {}
  60. -- 遍历所有兵书技能(isBingshuSkill=1),收集所有 groupID
  61. -- 因为整个 skill 表都是战意,所以所有兵书技能的 groupID 都是战意技能组ID
  62. for skillID, skillConfig in pairs(FuwenExcel.skill) do
  63. if skillConfig and skillConfig.isBingshuSkill == 1 then
  64. local groupID = skillConfig.groupID
  65. if groupID and not groupIDSet[groupID] then
  66. table.insert(groupIDs, groupID)
  67. groupIDSet[groupID] = true
  68. end
  69. end
  70. end
  71. -- 如果没有找到,使用默认值(兼容性处理)
  72. if #groupIDs == 0 then
  73. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGroupIDs] 未找到战意技能,使用默认值: {1001, 1002}")
  74. return {1001, 1002}
  75. end
  76. -- 排序以确保一致性
  77. table.sort(groupIDs)
  78. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGroupIDs] 找到战意技能组ID: "..table.concat(groupIDs, ","))
  79. return groupIDs
  80. end
  81. -- 缓存战意技能组ID列表(在模块加载时初始化)
  82. local BATTLE_WILL_GROUP_IDS = getBattleWillGroupIDs()
  83. -- 判断是否是战意技能
  84. local function isBattleWillSkill(skillConfig)
  85. if not skillConfig or not skillConfig.groupID then
  86. return false
  87. end
  88. for _, groupID in ipairs(BATTLE_WILL_GROUP_IDS) do
  89. if skillConfig.groupID == groupID then
  90. return true
  91. end
  92. end
  93. return false
  94. end
  95. ----------------------------------------- 工具函数 -----------------------------------------
  96. -- 获取战意格子数据(通过索引)
  97. -- 战意数据存储在 heroGrid.bingshu[index] 中,需要判断 groupID == 1002
  98. function getBattleWillGrid(heroGrid, index)
  99. if not heroGrid then
  100. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] heroGrid为nil")
  101. return
  102. end
  103. if not index then
  104. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] index为nil")
  105. return
  106. end
  107. -- 从bingshu中获取战意数据
  108. if not heroGrid.bingshu then
  109. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] heroGrid.bingshu为nil")
  110. return
  111. end
  112. local bingshuGrid = heroGrid.bingshu[index]
  113. if not bingshuGrid then
  114. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] heroGrid.bingshu["..index.."]为nil")
  115. return
  116. end
  117. local skillID = bingshuGrid.skillID
  118. if not skillID then
  119. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] skillID为nil, index="..index)
  120. return
  121. end
  122. -- 检查是否是战意技能(groupID=1001"狂暴"或groupID=1002"战意")
  123. local skillConfig = FuwenExcel.skill[skillID]
  124. if not skillConfig then
  125. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] skillConfig为nil, skillID="..skillID)
  126. return
  127. end
  128. if not isBattleWillSkill(skillConfig) then
  129. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] 不是战意技能, groupID="..(skillConfig.groupID or "nil")..", skillID="..skillID..", index="..index)
  130. return
  131. end
  132. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillGrid] 找到战意技能: index="..index..", skillID="..skillID..", level="..(skillConfig.lv or "nil"))
  133. return bingshuGrid, index
  134. end
  135. -- 查找战意所在的索引(遍历所有bingshu格子)
  136. function findBattleWillIndex(heroGrid)
  137. if not heroGrid or not heroGrid.bingshu then
  138. -- Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] heroGrid或heroGrid.bingshu为nil")
  139. return nil
  140. end
  141. -- Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] 开始遍历所有bingshu格子,查找战意技能(groupID=1001或1002)")
  142. -- Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] BINGSHU_MAXCNT="..BingshuLogic.BINGSHU_MAXCNT)
  143. -- 遍历所有bingshu格子,查找groupID=1001或1002的技能
  144. for i = 1, BingshuLogic.BINGSHU_MAXCNT do
  145. local bingshuGrid = heroGrid.bingshu[i]
  146. if bingshuGrid then
  147. local skillID = bingshuGrid.skillID
  148. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."]存在, skillID="..(skillID or "nil"))
  149. if skillID then
  150. local skillConfig = FuwenExcel.skill[skillID]
  151. if skillConfig then
  152. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."] skillConfig存在, skillID="..skillID..", groupID="..(skillConfig.groupID or "nil")..", lv="..(skillConfig.lv or "nil")..", name="..(skillConfig.name or "nil"))
  153. if isBattleWillSkill(skillConfig) then
  154. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] ✓ 找到战意: index="..i..", skillID="..skillID..", level="..(skillConfig.lv or "nil")..", name="..(skillConfig.name or "nil")..", groupID="..(skillConfig.groupID or "nil"))
  155. return i
  156. else
  157. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."]不是战意, groupID="..(skillConfig.groupID or "nil"))
  158. end
  159. else
  160. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."] skillConfig为nil, skillID="..skillID)
  161. end
  162. else
  163. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."] skillID为nil")
  164. end
  165. else
  166. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] bingshu["..i.."]不存在")
  167. end
  168. end
  169. --Log.write(Log.LOGID_DEBUG, "[findBattleWillIndex] ✗ 未找到战意技能(groupID=1001或1002),已遍历所有"..BingshuLogic.BINGSHU_MAXCNT.."个格子")
  170. return nil
  171. end
  172. -- 获取战意等级
  173. -- 根据skillID判断等级:1002=1级, 2002=2级, 3002=3级, 4002=4级
  174. function getBattleWillLevel(heroGrid, index)
  175. local grid, actualIndex = getBattleWillGrid(heroGrid, index)
  176. if not grid then
  177. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillLevel] grid为nil, index="..(index or "nil"))
  178. return 0
  179. end
  180. local skillID = grid.skillID
  181. if not skillID then
  182. -- Log.write(Log.LOGID_DEBUG, "[getBattleWillLevel] skillID为nil")
  183. return 0
  184. end
  185. -- 通过配置表获取等级
  186. local skillConfig = FuwenExcel.skill[skillID]
  187. if skillConfig and isBattleWillSkill(skillConfig) then
  188. local level = skillConfig.lv or 0
  189. --Log.write(Log.LOGID_DEBUG, "[getBattleWillLevel] 获取到等级: level="..level..", skillID="..skillID..", index="..(index or "nil"))
  190. return level
  191. end
  192. --Log.write(Log.LOGID_DEBUG, "[getBattleWillLevel] 不是战意技能, skillID="..skillID)
  193. return 0
  194. end
  195. -- 获取下一级战意技能ID(参考兵书的getNextSkillID)
  196. function getNextBattleWillSkillID(skillID)
  197. local tconfig = FuwenExcel.skill[skillID]
  198. if not tconfig then return end
  199. if not isBattleWillSkill(tconfig) then return end
  200. for id, config in pairs(FuwenExcel.skill) do
  201. if (config.isBingshuSkill == 1) and
  202. isBattleWillSkill(config) and
  203. (config.groupID == tconfig.groupID) and -- 保持相同的groupID(1001或1002)
  204. (config.lv == tconfig.lv + 1) and
  205. (#config.bingshuUpNeed > 0) then
  206. return id
  207. end
  208. end
  209. end
  210. ----------------------------------------- 协议处理 -----------------------------------------
  211. -- 查询回退信息
  212. function sendRollbackQuery(human, heroID, heroIndex, index)
  213. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 收到查询请求: heroID="..(heroID or "nil")..", heroIndex="..(heroIndex or "nil")..", index="..(index or "nil"))
  214. local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
  215. if not heroGrid then
  216. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 英雄不存在: heroID="..(heroID or "nil")..", heroIndex="..(heroIndex or "nil"))
  217. return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
  218. end
  219. -- 如果传入的index不是战意,尝试查找战意所在的索引
  220. local battleWillIndex = index
  221. local grid = getBattleWillGrid(heroGrid, index)
  222. if not grid then
  223. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] index="..index.."不是战意,尝试查找战意所在位置")
  224. battleWillIndex = findBattleWillIndex(heroGrid)
  225. if not battleWillIndex then
  226. -- Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 未找到战意技能")
  227. return Broadcast.sendErr(human, "当前战意格子为空,无法回退")
  228. end
  229. grid = heroGrid.bingshu[battleWillIndex]
  230. end
  231. local currentLevel = getBattleWillLevel(heroGrid, battleWillIndex)
  232. -- Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 当前战意等级: "..currentLevel..", index="..battleWillIndex)
  233. -- 检查等级是否可回退(等级0为空,不可回退)
  234. if currentLevel == 0 or currentLevel < 1 or currentLevel > 4 then
  235. -- Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 当前等级不可回退: level="..currentLevel)
  236. return Broadcast.sendErr(human, "当前战意格子为空,无法回退")
  237. end
  238. local config = BATTLE_WILL_ROLLBACK_CONFIG[currentLevel]
  239. if not config then
  240. -- Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 配置不存在: level="..currentLevel)
  241. return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
  242. end
  243. local msgRet = Msg.gc.GC_BATTLE_WILL_ROLLBACK_QUERY
  244. msgRet.heroID = heroID
  245. msgRet.heroIndex = heroIndex
  246. msgRet.index = battleWillIndex -- 使用实际找到的索引
  247. msgRet.currentLevel = currentLevel
  248. msgRet.targetLevel = 0 -- 回退后等级固定为0(空)
  249. -- 消耗道具
  250. Grid.makeItem(msgRet.needItem, config.needItemID, config.needItemCnt)
  251. -- 获取当前技能的groupID,确定返还的战意ID
  252. -- 从技能配置的 bingshuUpNeed 中获取第一个道具ID,那就是对应的战意道具ID
  253. local currentSkillID = grid.skillID
  254. local currentSkillConfig = FuwenExcel.skill[currentSkillID]
  255. local returnBattleWillID = nil
  256. if currentSkillConfig and currentSkillConfig.bingshuUpNeed and #currentSkillConfig.bingshuUpNeed > 0 then
  257. -- bingshuUpNeed 格式:{{itemID, count}, ...}
  258. -- 取第一个道具的ID作为战意道具ID
  259. local firstNeed = currentSkillConfig.bingshuUpNeed[1]
  260. if firstNeed and type(firstNeed) == "table" and #firstNeed >= 1 then
  261. returnBattleWillID = firstNeed[1]
  262. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 从bingshuUpNeed获取战意道具ID: "..returnBattleWillID..", groupID="..(currentSkillConfig.groupID or "nil")..", skillID="..currentSkillID)
  263. end
  264. end
  265. if not returnBattleWillID then
  266. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 无法确定返还战意ID: groupID="..(currentSkillConfig and currentSkillConfig.groupID or "nil")..", skillID="..(currentSkillID or "nil")..", bingshuUpNeed="..(currentSkillConfig and currentSkillConfig.bingshuUpNeed and #currentSkillConfig.bingshuUpNeed or "nil"))
  267. end
  268. -- 返还物品列表
  269. msgRet.returnItems[0] = 0
  270. local itemCnt = 0
  271. -- 返还战意
  272. if config.returnBattleWillCnt > 0 and returnBattleWillID then
  273. itemCnt = itemCnt + 1
  274. if itemCnt <= #msgRet.returnItems then
  275. Grid.makeItem(msgRet.returnItems[itemCnt], returnBattleWillID, config.returnBattleWillCnt)
  276. end
  277. end
  278. -- 返还战意碎片
  279. if config.returnFragmentCnt > 0 and config.returnFragmentID > 0 then
  280. itemCnt = itemCnt + 1
  281. if itemCnt <= #msgRet.returnItems then
  282. Grid.makeItem(msgRet.returnItems[itemCnt], config.returnFragmentID, config.returnFragmentCnt)
  283. end
  284. end
  285. -- 返还远古之灵
  286. if config.returnAncientSpiritCnt > 0 and config.returnAncientSpiritID > 0 then
  287. itemCnt = itemCnt + 1
  288. if itemCnt <= #msgRet.returnItems then
  289. Grid.makeItem(msgRet.returnItems[itemCnt], config.returnAncientSpiritID, config.returnAncientSpiritCnt)
  290. end
  291. end
  292. msgRet.returnItems[0] = itemCnt
  293. --Log.write(Log.LOGID_DEBUG, "[sendRollbackQuery] 发送查询结果: currentLevel="..currentLevel..", index="..battleWillIndex..", needItemCnt="..config.needItemCnt..", returnItemsCount="..itemCnt)
  294. Msg.send(msgRet, human.fd)
  295. end
  296. -- 执行回退
  297. function rollback(human, heroID, heroIndex, index)
  298. local heroGrid = HeroLogic.getHeroGrid(human, heroID, heroIndex)
  299. if not heroGrid then
  300. return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
  301. end
  302. -- 检查index范围(1-BINGSHU_MAXCNT)
  303. if index and (index < 1 or index > BingshuLogic.BINGSHU_MAXCNT) then
  304. return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
  305. end
  306. -- 如果传入的index不是战意,尝试查找战意所在的索引
  307. local battleWillIndex = index
  308. local grid = nil
  309. if index then
  310. grid = getBattleWillGrid(heroGrid, index)
  311. end
  312. if not grid then
  313. battleWillIndex = findBattleWillIndex(heroGrid)
  314. if not battleWillIndex then
  315. return Broadcast.sendErr(human, "当前战意格子为空,无法回退")
  316. end
  317. grid = heroGrid.bingshu[battleWillIndex]
  318. end
  319. -- 获取当前技能配置,确定返还的战意ID和等级
  320. local currentSkillID = grid.skillID
  321. local currentSkillConfig = FuwenExcel.skill[currentSkillID]
  322. if not currentSkillConfig then
  323. return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
  324. end
  325. -- 检查是否是战意技能
  326. if not isBattleWillSkill(currentSkillConfig) then
  327. return Broadcast.sendErr(human, "当前格子不是战意技能,无法回退")
  328. end
  329. -- 从技能配置中获取等级(更可靠)
  330. local currentLevel = currentSkillConfig.lv or 0
  331. -- 检查等级是否可回退
  332. if currentLevel == 0 or currentLevel < 1 or currentLevel > 4 then
  333. return Broadcast.sendErr(human, "当前战意格子为空,无法回退")
  334. end
  335. -- 根据技能配置的 bingshuUpNeed 确定返还的战意ID
  336. -- 从 bingshuUpNeed 中获取第一个道具ID,那就是对应的战意道具ID
  337. local returnBattleWillID = nil
  338. if currentSkillConfig.bingshuUpNeed and #currentSkillConfig.bingshuUpNeed > 0 then
  339. -- bingshuUpNeed 格式:{{itemID, count}, ...}
  340. -- 取第一个道具的ID作为战意道具ID
  341. local firstNeed = currentSkillConfig.bingshuUpNeed[1]
  342. if firstNeed and type(firstNeed) == "table" and #firstNeed >= 1 then
  343. returnBattleWillID = firstNeed[1]
  344. end
  345. end
  346. if not returnBattleWillID then
  347. --Log.write(Log.LOGID_DEBUG, "[rollback] 无法确定返还战意ID: groupID="..(currentSkillConfig.groupID or "nil")..", skillID="..(currentSkillID or "nil")..", bingshuUpNeed="..(currentSkillConfig.bingshuUpNeed and #currentSkillConfig.bingshuUpNeed or "nil"))
  348. return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
  349. end
  350. -- 检查消耗道具(回退消耗)
  351. local config = BATTLE_WILL_ROLLBACK_CONFIG[currentLevel]
  352. if not config then
  353. --Log.write(Log.LOGID_DEBUG, "[rollback] 回退配置不存在: level="..currentLevel)
  354. return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
  355. end
  356. if not BagLogic.checkItemCnt(human, config.needItemID, config.needItemCnt) then
  357. return Broadcast.sendErr(human, Lang.COMMON_NO_ITEM)
  358. end
  359. -- 扣除消耗道具
  360. BagLogic.delItem(human, config.needItemID, config.needItemCnt, "bingshu")
  361. -- 收集返还物品(根据配置)
  362. local returnItemList = {}
  363. -- 返还战意
  364. if config.returnBattleWillCnt > 0 and returnBattleWillID then
  365. returnItemList[returnBattleWillID] = config.returnBattleWillCnt
  366. end
  367. -- 返还战意碎片
  368. if config.returnFragmentCnt > 0 and config.returnFragmentID > 0 then
  369. returnItemList[config.returnFragmentID] = config.returnFragmentCnt
  370. end
  371. -- 返还远古之灵
  372. if config.returnAncientSpiritCnt > 0 and config.returnAncientSpiritID > 0 then
  373. returnItemList[config.returnAncientSpiritID] = config.returnAncientSpiritCnt
  374. end
  375. -- 发放返还物品(使用通用道具发放逻辑)
  376. if next(returnItemList) then
  377. BagLogic.addItemList(human, returnItemList, "bingshu")
  378. end
  379. -- 更新战意等级为0(清空)- 删除bingshu中的战意技能
  380. if not heroGrid.bingshu then
  381. heroGrid.bingshu = {}
  382. end
  383. local bingshuGrid = heroGrid.bingshu[battleWillIndex]
  384. if bingshuGrid then
  385. local skillConfig = FuwenExcel.skill[bingshuGrid.skillID]
  386. if skillConfig and isBattleWillSkill(skillConfig) then
  387. -- 这是战意技能,删除它
  388. heroGrid.bingshu[battleWillIndex] = nil
  389. else
  390. --Log.write(Log.LOGID_DEBUG, "[rollback] WARNING: bingshu["..battleWillIndex.."]不是战意技能, skillID="..(bingshuGrid.skillID or "nil"))
  391. end
  392. end
  393. ObjHuman.doCalcHero(human, heroIndex)
  394. -- 发送英雄数据更新(如果需要)
  395. HeroLogic.sendHeroBagDynamic(human, heroID, heroIndex)
  396. -- 发送GC_BINGSHU_QUERY刷新所有兵书状态
  397. BingshuLogic.sendQuery(human, heroID, heroIndex)
  398. end