CombatLogic.lua 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087
  1. ----------------------------------
  2. -- 战斗逻辑
  3. -- combatBegin 开始战斗
  4. -- createCombatFakeHuman 根据uuid创角战斗human
  5. -- fight 战斗开始前各模块自己的判断函数,成功调用CombatLogic.combatBegin()
  6. -- onFightBegin 战斗帧计算前的属性重新计算
  7. -- onFightEnd 战斗结束回调,发送GC_COMBAT_FINISH前
  8. -- checkCombatPos 可否打开上阵界面(默认可打开)
  9. -- 获取双方上阵对象信息
  10. -- getCombatMonsterOutID 获取上阵怪物组id
  11. -- getCombatTarget 获取上阵human信息
  12. -- getCombatObjList 获取上阵队伍列表
  13. ----------------------------------
  14. local CombatExcel = require("excel.combat")
  15. local MonsterExcel = require("excel.monster")
  16. local BattleMonsterExcel = require("excel.battlemonster")
  17. local BattleMonsterExcel2 = require("excel.battlemonster2")
  18. local HeroExcel = require("excel.hero")
  19. local SkillExcel = require("excel.skill")
  20. local BufferExcel = require("excel.buffer")
  21. local Config = require("Config")
  22. local Util = require("common.Util")
  23. local Lang = require("common.Lang")
  24. local Log = require("common.Log")
  25. local Msg = require("core.Msg")
  26. local ObjHuman = require("core.ObjHuman")
  27. local Grid = require("bag.Grid")
  28. -- local Broadcast = require("broadcast.Broadcast")
  29. local BeSkill = require("combat.BeSkill")
  30. local CombatObj = require("combat.CombatObj")
  31. local CombatImpl = require("combat.CombatImpl")
  32. local CombatDefine = require("combat.CombatDefine")
  33. local CombatPosLogic = require("combat.CombatPosLogic")
  34. local CombatPetCalc = require("combat.CombatPetCalc")
  35. local CombatBuff = require("combat.CombatBuff")
  36. local MoshouLogic = require("moshou.MoshouLogic")
  37. local RoleDBLogic = require("role.RoleDBLogic")
  38. local RoleAttr = require("role.RoleAttr")
  39. local RoleDefine = require("role.RoleDefine")
  40. local RoleLogic = require("role.RoleLogic")
  41. local HeroGrid = require("hero.HeroGrid")
  42. local DrillLogic = require("drill.DrillLogic")
  43. local SkinLogic = require("skin.SkinLogic")
  44. local BeginStory = require("scene.BeginStory")
  45. local Skill = require("combat.Skill")
  46. local CombatPosExcel = require("excel.combatPos")
  47. local ValleyLogic = require("valley.ValleyLogic")
  48. local LianyuLogic = require("lianyu.LianyuLogic")
  49. local TheStarsLogic = require("theStars.TheStarsLogic")
  50. local HeroDefine = require("hero.HeroDefine")
  51. local JibanLogic = require("combat.JibanLogic")
  52. local EquipLogic = require("equip.EquipLogic")
  53. local ItemDefine = require("bag.ItemDefine")
  54. local HeroLogic = require("hero.HeroLogic")
  55. local XingYaoGongMing = require("xingYaoMen.XingYaoGongMing")
  56. -- local MoshouLogic = require("moshou.MoshouLogic")
  57. local LostTempleCombatLogic = require("lostTemple.lostTempleCombatLogic")
  58. local SkinExcel = require("excel.skin")
  59. local BattleLogic = require("battle.BattleLogic")
  60. local HeroExclusiveWeapon = require("hero.HeroExclusiveWeapon")
  61. local ItemConfig = require("excel.item").item
  62. local ElfLogic = require("elf.ElfLogic")
  63. local HeroArtifacts = require("hero.HeroArtifacts")
  64. -- 用于在切磋时取目标玩家db数据中的计算属性数据, 如果在 RoleAttr.calcHeroGrid中用到了,需要加到这个里面
  65. FieldsCombat = {
  66. lv = 1, name = 1, head = 1, headFrame = 1, unionUuid = 1, lastLogoutTime = 1,
  67. combatHero = 1, heroBag = 1, moshou = 1, technology=1, chengjiu=1, realmLv = 1, talismanData = 1,
  68. headList = 1, headFrameList = 1, bodyList = 1, chenghaoList = 1,animationList =1,backgroundList =1,
  69. skinBag = 1, relic = 1, heroPubData = 1, elfData = 1, anotherWorlBattle = 1,
  70. }
  71. COMBAT_CACHE = COMBAT_CACHE or {}
  72. local AnotherWorldBattleNS
  73. ------------------------------------------- 模块相关 start -------------------------------------------------
  74. -- 初始
  75. COMBATTYPE_2_MODULE = COMBATTYPE_2_MODULE or {}
  76. function init()
  77. for combatType, cf in pairs(CombatExcel.combat) do
  78. if cf.moduleFn ~= "" then
  79. local moduleFn = load("return require(\""..cf.moduleFn.."\")")()
  80. COMBATTYPE_2_MODULE[combatType] = moduleFn
  81. end
  82. end
  83. end
  84. -- 获取模块
  85. function getModule(combatType)
  86. if not combatType then return end
  87. return COMBATTYPE_2_MODULE[combatType]
  88. end
  89. -- 获取攻/守方怪物组id
  90. local function getCombatMonsterOutID(human, side, combatType, args)
  91. local moduleFn = getModule(combatType)
  92. if moduleFn and moduleFn.getCombatMonsterOutID then
  93. return moduleFn.getCombatMonsterOutID(human, side, args, combatType)
  94. end
  95. end
  96. -- 获取攻/守方怪物组id
  97. function getMapID(human, combatType, param)
  98. local moduleFn = getModule(combatType)
  99. local mapID = nil
  100. if moduleFn and moduleFn.getMapID then
  101. mapID = moduleFn.getMapID(human, param)
  102. end
  103. if not mapID then
  104. local config = CombatExcel.combat[combatType]
  105. mapID = config.mapID == 0 and 1001 or config.mapID
  106. end
  107. return mapID
  108. end
  109. -- 获取是否跳过
  110. function getQuick(human, combatType)
  111. local config = CombatExcel.combat[combatType]
  112. local moduleFn = getModule(combatType)
  113. local quick = nil
  114. if moduleFn and moduleFn.getQuick then
  115. quick = moduleFn.getQuick(human, combatType)
  116. end
  117. if quick ~= nil and quick >= 0 then
  118. return quick
  119. end
  120. if human.db.combatQuick[combatType] and human.db.combatQuick[combatType] ~= 0 then
  121. if config.isQuick == 0 then
  122. human.db.combatQuick[combatType] = 0
  123. end
  124. end
  125. return config.isQuick
  126. end
  127. -- 获取攻/守方对象
  128. local function getCombatTarget(human, side, combatType, args)
  129. local moduleFn = getModule(combatType)
  130. if moduleFn and moduleFn.getCombatTarget then
  131. return moduleFn.getCombatTarget(human, side, args, combatType)
  132. end
  133. end
  134. --更新上阵信息回调
  135. function onUpdatePos(human,combatType)
  136. local moduleFn = getModule(combatType)
  137. if moduleFn and moduleFn.onUpdatePos then
  138. return moduleFn.onUpdatePos(human)
  139. end
  140. end
  141. -- 获取攻/守方上阵信息
  142. function getCombatObjList(human, side, combatType, args)
  143. if type(args) == "table" then
  144. if side == CombatDefine.ATTACK_SIDE then
  145. if args.attacker then
  146. return args.attacker, args.atkHelp, args.atkRBase, args.atkFormation,args.atkJiban,args.atkElfList
  147. end
  148. else
  149. if args.defender then
  150. return args.defender, args.defHelp, args.defRBase, args.defFormation,args.defJiban, args.defElfList
  151. end
  152. end
  153. end
  154. local moduleFn = getModule(combatType)
  155. if not moduleFn then return end
  156. if moduleFn.getCombatObjList then
  157. local objList, helpList, rolebase, formation,jiban, elfList = moduleFn.getCombatObjList(human, side, args, combatType)
  158. if objList then
  159. return objList, helpList, rolebase ,formation,jiban, elfList
  160. end
  161. end
  162. local monsterOutID, zhandouli = getCombatMonsterOutID(human, side, combatType, args)
  163. if monsterOutID then
  164. local objList, helpList, rolebase, formation, jiban, elfList = getMonsterObjList(monsterOutID, nil, args)
  165. if zhandouli then
  166. rolebase.zhandouli = zhandouli
  167. end
  168. return objList, helpList, rolebase,formation,jiban, elfList
  169. end
  170. if moduleFn.getHumanObjList then
  171. return moduleFn.getHumanObjList(human, combatType)
  172. end
  173. local target = getCombatTarget(human, side, combatType, args)
  174. if target then
  175. return getHumanObjList(target, combatType)
  176. end
  177. if side == CombatDefine.ATTACK_SIDE then -- 没有模块没有特写,攻防默认取自身上阵信息
  178. return getHumanObjList(human, combatType)
  179. end
  180. end
  181. --获取战斗最大回合数
  182. local function getMaxRound(human,combatType)
  183. local config = CombatExcel.combat[combatType]
  184. if config and config.maxRound and config.maxRound > 0 then
  185. return config.maxRound
  186. end
  187. return CombatDefine.COMBAT_ROUND_MAX
  188. end
  189. --获取战斗模式
  190. local function getFightMode(combatType)
  191. local config = CombatExcel.combat[combatType]
  192. if config.fightMode[1] == CombatDefine.FIGHT_MODE1 or config.fightMode[1] == CombatDefine.FIGHT_MODE3 then
  193. return config.fightMode
  194. end
  195. end
  196. -- 尝试战斗
  197. function tryCombatBegin(human, combatType, param)
  198. local moduleFn = getModule(combatType)
  199. if moduleFn and moduleFn.fight then
  200. local args = Util.split(param, "|")
  201. return moduleFn.fight(human, args, combatType)
  202. end
  203. end
  204. -- 可否打开上阵界面
  205. function checkCombatPos(human, combatType, args)
  206. local moduleFn = getModule(combatType)
  207. if moduleFn and moduleFn.checkCombatPos then
  208. return moduleFn.checkCombatPos(human, args, combatType)
  209. end
  210. return true
  211. end
  212. -- 战斗结束回调 在发送GC_COMBAT_FINISH前
  213. local function onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang)
  214. local moduleFn = getModule(combatType)
  215. if not moduleFn then return end
  216. if not moduleFn.onFightEnd then return end
  217. moduleFn.onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang)
  218. end
  219. -- 战斗名称
  220. function getCombatName(human, combatType, args)
  221. local moduleFn = getModule(combatType)
  222. if not moduleFn then return "" end
  223. if not moduleFn.getCombatName then return "" end
  224. return moduleFn.getCombatName(human, args, combatType) or ""
  225. end
  226. ------------------------------------------- 模块相关 end -------------------------------------------------
  227. -- 判断阵容是不是为空
  228. function isCombatHeroEmpty(combatHero)
  229. if not combatHero then return true end
  230. local isEmpty = true
  231. for _, heroUuid in pairs(combatHero) do
  232. if heroUuid and heroUuid ~= "" and heroUuid ~= "0" then
  233. isEmpty = nil
  234. break
  235. end
  236. end
  237. return isEmpty
  238. end
  239. -- 根据阵营和下标获取对战位置
  240. function getPos(side, index)
  241. if side == CombatDefine.ATTACK_SIDE then
  242. return index
  243. elseif side == CombatDefine.DEFEND_SIDE then
  244. return index + CombatDefine.COMBAT_HERO_CNT
  245. else
  246. assert()
  247. end
  248. end
  249. -- 通过位置确定阵营
  250. function getSideByPos(helpType, pos)
  251. if helpType == CombatDefine.HELP_TYPE0 then
  252. return pos > CombatDefine.COMBAT_HERO_CNT and CombatDefine.DEFEND_SIDE or CombatDefine.ATTACK_SIDE
  253. elseif helpType == CombatDefine.HELP_TYPE1 then
  254. return pos >= CombatDefine.PET_DEFPOS and CombatDefine.DEFEND_SIDE or CombatDefine.ATTACK_SIDE
  255. elseif helpType == CombatDefine.HELP_TYPE2 then
  256. local atkElfMaxPos = CombatDefine.COMBAT_HERO_ALL_CNT + CombatDefine.COMBAT_HELP_ALL_CNT + CombatDefine.COMBAT_ELF_CNT
  257. return pos > atkElfMaxPos and CombatDefine.DEFEND_SIDE or CombatDefine.ATTACK_SIDE
  258. else
  259. assert(false, "helpType 错误")
  260. end
  261. end
  262. function getIndexByPos(side, pos)
  263. if side == CombatDefine.ATTACK_SIDE then
  264. return pos
  265. elseif side == CombatDefine.DEFEND_SIDE then
  266. return pos - CombatDefine.COMBAT_HERO_CNT
  267. end
  268. end
  269. -- 获取对象配置
  270. function getConfigByObj(obj)
  271. if not obj then return end
  272. local id = obj.id or obj.heroID
  273. if obj.type == CombatDefine.COMBAT_OBJ_TYPE1 then
  274. return HeroExcel.hero[id]
  275. end
  276. return MonsterExcel.monster[id] or BattleMonsterExcel.monster[id] or BattleMonsterExcel2.monster[id]
  277. end
  278. -- 创建战斗Human
  279. function createCombatFakeHuman(uuid)
  280. if not uuid then return end
  281. local db = RoleDBLogic.getDb(uuid, FieldsCombat)
  282. if not db then return end
  283. local fakeHuman = {}
  284. fakeHuman.db = db
  285. return fakeHuman
  286. end
  287. -- 创建初始角色信息
  288. function createRoleBaseDefault()
  289. local rolebase = {}
  290. RoleLogic.makeRoleBase(nil, rolebase, nil, true)
  291. rolebase.name = Lang.COMBAT_DEFEND_NAME
  292. return rolebase
  293. end
  294. -- 根据怪物信息创建角色信息
  295. function createRoleBaseByMOutID(monsterOutID, zhandouli, args)
  296. local _, monsterConfig, monsterLv = getMonsterIDByOutID(monsterOutID, args)
  297. local rolebase = createRoleBaseDefault()
  298. if monsterConfig then
  299. rolebase.name = monsterConfig.name
  300. rolebase.lv = monsterLv or 1
  301. rolebase.head = monsterConfig.head
  302. rolebase.zhandouli = zhandouli or 0
  303. end
  304. return rolebase
  305. end
  306. -- 创建角色信息
  307. function createRoleBaseByDB(db, zhandouli)
  308. local rolebase = {}
  309. RoleLogic.makeRoleBase(db, rolebase, nil, true)
  310. rolebase.zhandouli = zhandouli or 0
  311. return rolebase
  312. end
  313. -- 根据怪物表信息创建临时对象
  314. function createMonsterObj(id, lv, attrID, index, objType, monsterOutConfig, attrInput)
  315. local monsterConfig = MonsterExcel.monster[id] or BattleMonsterExcel.monster[id] or BattleMonsterExcel2.monster[id]
  316. if not monsterConfig then return end
  317. local obj = {}
  318. obj.type = objType or CombatDefine.COMBAT_OBJ_TYPE2
  319. obj.bagIndex = index
  320. obj.id = id
  321. obj.lv = lv
  322. obj.job = monsterConfig.job
  323. obj.quality = 6
  324. obj.star = monsterConfig.star
  325. obj.head = monsterConfig.head
  326. obj.body = monsterConfig.body
  327. obj.camp = monsterConfig.camp
  328. obj.sex = monsterConfig.sex
  329. BeSkill.initBeSkill(obj)
  330. BeSkill.setBeSkill(obj, monsterConfig, nil, monsterOutConfig)
  331. Skill.setSkill(obj, monsterConfig)
  332. obj.attrs = RoleAttr.calcMonsterConf(id, attrID, attrInput)
  333. return obj
  334. end
  335. -- 根据英雄ID信息创建临时对象
  336. function createHeroObjByID(heroId, lv, star, quality, index)
  337. local heroConfig = HeroExcel.hero[heroId]
  338. if not heroConfig then return end
  339. local obj = {}
  340. obj.type = CombatDefine.COMBAT_OBJ_TYPE1
  341. obj.bagIndex = index
  342. obj.id = heroId
  343. obj.lv = lv
  344. obj.job = heroConfig.job
  345. obj.quality = quality and quality or HeroGrid.getMaxQuality(star)
  346. obj.star = star
  347. obj.body = heroConfig.body
  348. obj.head = heroConfig.head
  349. local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star)
  350. BeSkill.initBeSkill(obj)
  351. Skill.setSkill(obj, attrConfig)
  352. BeSkill.setBeSkill(obj, attrConfig)
  353. obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, index))
  354. obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI]
  355. return obj
  356. end
  357. -- 根据英雄表信息创建临时对象
  358. function createHeroObj(human, heroId, lv, star, index, skin, attrsChange)
  359. local heroConfig = HeroExcel.hero[heroId]
  360. local skinCfg = skin and SkinExcel.skin[skin]
  361. if not heroConfig then return end
  362. local obj = {}
  363. obj.type = CombatDefine.COMBAT_OBJ_TYPE1
  364. obj.bagIndex = index
  365. obj.id = heroId
  366. obj.lv = lv
  367. obj.job = heroConfig.job
  368. obj.quality = HeroGrid.getMaxQuality(star)
  369. obj.star = star
  370. obj.body = skinCfg and skinCfg.body --or heroConfig.body
  371. obj.head = skinCfg and skinCfg.head --or heroConfig.head
  372. if not obj.body or obj.body == 0 then
  373. obj.body = heroConfig.body
  374. end
  375. if not obj.head or obj.head == 0 then
  376. obj.head = heroConfig.head
  377. end
  378. local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star)
  379. BeSkill.initBeSkill(obj)
  380. if not SkinLogic.setSkill(human,index,attrConfig,obj) then
  381. Skill.setSkill(obj, attrConfig)
  382. BeSkill.setBeSkill(obj, attrConfig)
  383. end
  384. obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, index, human))
  385. if attrsChange then
  386. for attrId, valMul in pairs(attrsChange) do
  387. if obj.attrs[attrId] then
  388. obj.attrs[attrId] = math.max(obj.attrs[attrId] * valMul, 0)
  389. end
  390. end
  391. end
  392. obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI]
  393. return obj
  394. end
  395. function createHeroObjByHeroGrid(human, heroGrid)
  396. local heroConfig = HeroExcel.hero[heroGrid.id]
  397. if not heroConfig then return end
  398. local obj = {}
  399. obj.type = CombatDefine.COMBAT_OBJ_TYPE1
  400. obj.bagIndex = heroGrid.bagIndex
  401. obj.uuid = heroGrid.uuid
  402. obj.id = heroGrid.id
  403. obj.lv = heroGrid.lv
  404. obj.job = heroConfig.job
  405. obj.quality = heroGrid.quality
  406. obj.star = heroGrid.star -- dxzeng 取db star
  407. obj.fuwen = Util.copyTable(heroGrid.fuwen)
  408. obj.bingshu = Util.copyTable(heroGrid.bingshu)
  409. obj.body, obj.head = SkinLogic.getBody(human, obj.bagIndex)
  410. obj.camp = heroConfig.camp
  411. obj.isGongMing = XingYaoGongMing.isGongMing(human, heroGrid.bagIndex)
  412. obj.weaponEffectIdList = HeroExclusiveWeapon.GetweaponEffectIdList(heroGrid)
  413. obj.fuwenStrengthenSkillList = HeroArtifacts.GetFuwenStrengthenSkillList(heroGrid)
  414. obj.artifactsBeSkillList = HeroArtifacts.GetArtifactsBeSkillList(heroGrid)
  415. obj.skinOn = heroGrid.skinOn
  416. obj.sex = heroConfig.sex
  417. obj.relic = heroGrid.relic or {}
  418. local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star)
  419. BeSkill.initBeSkill(obj)
  420. if not SkinLogic.setSkill(human,obj.bagIndex,attrConfig,obj) then
  421. Skill.setSkill(obj, attrConfig)
  422. BeSkill.setBeSkill(obj, attrConfig)
  423. end
  424. if heroGrid.isLostTemple then
  425. obj.attrs = Util.copyTable(LostTempleCombatLogic.getHeroAttrs(human, heroGrid.bagIndex))
  426. else
  427. obj.attrs = Util.copyTable(ObjHuman.getHeroAttrs(human, obj.bagIndex))
  428. --obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, obj.bagIndex, human))
  429. end
  430. obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI]
  431. return obj
  432. end
  433. -- 根据英雄背包创建临时对象
  434. function createHumanObj(human, uuid)
  435. if not uuid then return end
  436. local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
  437. if not heroGrid or type(heroGrid) ~= "table" then return end
  438. return createHeroObjByHeroGrid(human, heroGrid)
  439. end
  440. -- 根据怪物组id获取出战英雄列表
  441. function getMonsterObjList(monsterOutID, objType, args)
  442. if not monsterOutID then return end
  443. local monsterOutConfig = MonsterExcel.monsterOut[monsterOutID] or BattleMonsterExcel.monsterOut[monsterOutID] or BattleMonsterExcel2.monsterOut[monsterOutID]
  444. if not monsterOutConfig then return end
  445. local formation = monsterOutConfig.formation
  446. if formation == 0 then
  447. formation = 1
  448. end
  449. local mationConfig = CombatPosExcel.formation[formation]
  450. local posList = mationConfig.pos
  451. if not posList then return end
  452. local objList = nil
  453. local zhandouli = 0
  454. for i, member in ipairs(monsterOutConfig.member) do
  455. local monsterID = member[1]
  456. -- local monsterConfig = MonsterExcel.monster[monsterID]
  457. if posList[i] then
  458. local monsterLv = member[2]
  459. local attrID = monsterOutConfig.attrID[i]
  460. local attrInput = nil
  461. if monsterOutConfig.combatType == CombatDefine.COMBAT_TYPE5 then
  462. if args then
  463. local throneID = args[1]
  464. local evolveCnt = args[2]
  465. monsterLv, attrInput = TheStarsLogic.getMonsterLvAttr(i, throneID, evolveCnt)
  466. end
  467. end
  468. local obj = createMonsterObj(monsterID, monsterLv, attrID, i, objType, monsterOutConfig.beSkill[i], attrInput)
  469. if obj then
  470. zhandouli = zhandouli + obj.attrs[RoleDefine.ZHANDOULI]
  471. objList = objList or {}
  472. local pos = posList[i]
  473. if monsterOutConfig.combatType == CombatDefine.COMBAT_TYPE10 then
  474. pos = 5
  475. end
  476. objList[pos] = obj
  477. end
  478. end
  479. end
  480. if not objList then
  481. assert(nil, "getMonsterObjList is nil, monsterOutID = " .. monsterOutID)
  482. end
  483. local rolebase = createRoleBaseByMOutID(monsterOutID, zhandouli, args)
  484. local jiban = nil -- todo 怪物的羁绊
  485. return objList, nil, rolebase,formation,jiban
  486. end
  487. -- 创建战斗精灵对象
  488. function createElfObj(human, elfId, pos)
  489. local itemCfg = ItemConfig[elfId]
  490. local elfObj = {}
  491. elfObj.id = elfId
  492. elfObj.type = CombatDefine.COMBAT_OBJ_TYPE99
  493. elfObj.isElf = true
  494. elfObj.head = itemCfg and itemCfg.icon or 0
  495. elfObj.body = itemCfg and itemCfg.icon or 0
  496. elfObj.attrs = {}
  497. local skillId = ElfLogic.GetElfSkill(human, elfId)
  498. local skillCfg = Skill.GetSkillConfig(skillId)
  499. if not skillCfg then
  500. return
  501. end
  502. elfObj.skillList = {
  503. [1] = {skillId, pos, skillCfg.cd[2] or 0 }
  504. }
  505. return elfObj
  506. end
  507. -- 获取human出战英雄列表 objList, helpList, rolebase, formation
  508. function getHumanObjList(human, combatType, extraArgs)
  509. local teamType = CombatPosLogic.getTeamType(combatType)
  510. if not teamType then return end
  511. local combatHero, formation,combatHeroDB
  512. if combatType == CombatDefine.COMBAT_TYPE35 and (extraArgs and extraArgs.useDef) then
  513. AnotherWorldBattleNS = AnotherWorldBattleNS or require("anotherWorldBattle.AnotherWorldBattleNS")
  514. combatHero, _, formation,combatHeroDB = AnotherWorldBattleNS.getCombatHeros(human, combatType, extraArgs)
  515. else
  516. combatHero, _, formation,combatHeroDB = CombatPosLogic.getCombatHeros(human, combatType)
  517. end
  518. if not combatHero then return end
  519. if formation == 0 then
  520. formation = 1
  521. end
  522. local jiban = JibanLogic.getJibanHero(human,combatHeroDB)
  523. local objList = {}
  524. local zhandouli = 0
  525. for i = 1, CombatDefine.COMBAT_HERO_CNT do
  526. local uuid = combatHero[i]
  527. local obj = createHumanObj(human, uuid)
  528. if obj then
  529. zhandouli = zhandouli + obj.attrs[RoleDefine.ZHANDOULI]
  530. objList[i] = obj
  531. end
  532. end
  533. local helpList = {}
  534. local pet = MoshouLogic.createCombatMoshow(human, combatType, combatHeroDB and combatHeroDB.helpList)
  535. helpList[CombatDefine.HELP_TYPE1] = pet
  536. local rolebase = createRoleBaseByDB(human.db, zhandouli)
  537. -- 精灵
  538. local combatElf = combatHeroDB.elfList
  539. local elfList = {}
  540. if combatElf then
  541. for i=1, CombatDefine.COMBAT_ELF_CNT do
  542. local elfId = combatElf[i]
  543. local elfObj = createElfObj(human, elfId, i)
  544. if elfObj then
  545. elfList[i] = elfObj
  546. end
  547. end
  548. end
  549. return objList, helpList, rolebase,formation,jiban, elfList
  550. end
  551. ---------------------------------------------- msg -----------------------------------------------
  552. -- 封装对战英雄信息
  553. local function fontCombatHeroNet(net, obj)
  554. local config = getConfigByObj(obj)
  555. if not config then return end
  556. net.pos = obj.pos
  557. net.heroID = obj.id
  558. net.star = obj.star
  559. net.lv = obj.lv or 0
  560. net.body = obj.body or config.body
  561. if obj.body and config.body then
  562. if obj.body ~= config.body then
  563. local tSkinCof = SkinExcel.skin[obj.body]
  564. if tSkinCof and tSkinCof.heroId ~= net.heroID then
  565. net.body = config.body
  566. print("[fontCombatHeroNet] 下发时修改英雄的身体数据 heroID = "..net.heroID .." body1 = "..obj.body.." conBody = "..config.body)
  567. end
  568. end
  569. if obj.skinOn then
  570. local tSkinCof = SkinExcel.skin[obj.skinOn]
  571. if tSkinCof and tSkinCof.heroId == net.heroID then
  572. print("[fontCombatHeroNet] 穿戴了皮肤 修改为皮肤对应的身体数据 heroID = "..net.heroID .." body1 = "..net.body.." body2 = "..tSkinCof.body)
  573. net.body = tSkinCof.body
  574. end
  575. else
  576. print("[fontCombatHeroNet] 没有穿戴皮肤 heroID = "..net.heroID)
  577. end
  578. end
  579. net.hpMax = obj.hpMax --CombatObj.getHpMax(obj)
  580. net.hpNow = obj.initHp
  581. net.icon = config.head
  582. net.width = config.width
  583. net.height = config.height
  584. net.camp = config.camp
  585. net.name = config.name
  586. net.posX = CombatDefine.DEFAULT_POS_SIZE[obj.pos][1]
  587. net.posY = CombatDefine.DEFAULT_POS_SIZE[obj.pos][2]
  588. net.size = CombatDefine.DEFAULT_POS_SIZE[obj.pos][3]
  589. net.isBoss = config.isboss or 0
  590. net.isGongMing = obj.isGongMing or 0
  591. net.grade = config.grade or 0
  592. local len = 0
  593. for _,v in pairs(obj.skillList) do
  594. -- if SkillExcel.skill[v[1]].contentType == 3 then
  595. -- len = len + 1
  596. -- net.sayList[len] = v[1]
  597. -- end
  598. local skillConfig = Skill.GetSkillConfig(v[1])
  599. if skillConfig.contentType == 3 then
  600. len = len + 1
  601. net.sayList[len] = v1[1]
  602. end
  603. end
  604. for _,v in pairs(obj.beSkillList) do
  605. for _,v1 in ipairs(v) do
  606. -- if SkillExcel.skill[v1[1]].contentType == 3 then
  607. -- len = len + 1
  608. -- net.sayList[len] = v1[1]
  609. -- end
  610. local skillConfig = Skill.GetSkillConfig(v1[1])
  611. if skillConfig.contentType == 3 then
  612. len = len + 1
  613. net.sayList[len] = v1[1]
  614. end
  615. end
  616. end
  617. net.sayList[0] = len
  618. return true
  619. end
  620. -- 封装辅助对象
  621. function fontCombatHelpNet(net, help)
  622. net.pos = help.pos
  623. net.id = help.id or 0
  624. net.head = help.head or 0
  625. net.body = help.body or 0
  626. net.skill[0] = 0
  627. --local skillConfig = SkillExcel.skill[help.icon]
  628. local skillConfig = Skill.GetSkillConfig(help.icon)
  629. if skillConfig then
  630. net.skill[1].id = help.icon
  631. net.skill[1].icon = skillConfig.icon
  632. net.skill[1].name = skillConfig.name
  633. net.skill[1].desc = skillConfig.desc
  634. net.skill[1].lv = help.skillLV or 0
  635. net.skill[1].index = 0
  636. net.skill[1].state = 2
  637. net.skill[0] = 1
  638. end
  639. net.args[0] = 0
  640. if help.clientArgs then
  641. local len = 0
  642. for k,v in ipairs(help.clientArgs) do
  643. len = len + 1
  644. net.args[len] = v
  645. end
  646. net.args[0] = len
  647. end
  648. return true
  649. end
  650. -- 封装辅助对象
  651. function fontCombatElfpNet(net, elf)
  652. net.pos = elf.pos
  653. net.id = elf.id or 0
  654. net.head = elf.head or 0
  655. net.body = elf.body or 0
  656. net.skill[0] = 0
  657. local skillId = elf.skillList[1][1]
  658. local skillConfig = Skill.GetSkillConfig(skillId)
  659. if skillConfig then
  660. net.skill[1].id = skillId
  661. net.skill[1].icon = skillConfig.icon
  662. net.skill[1].name = skillConfig.name
  663. net.skill[1].desc = skillConfig.desc
  664. net.skill[1].lv = skillConfig.skillLV or 0
  665. net.skill[1].index = 0
  666. net.skill[1].state = 2
  667. net.skill[0] = 1
  668. end
  669. net.args[0] = 0
  670. return true
  671. end
  672. -- 封装战斗技能信息
  673. function fontCombatSkillNet(skillNet, skillID)
  674. --local skillConfig = SkillExcel.skill[skillID]
  675. local skillConfig = Skill.GetSkillConfig(skillID)
  676. if not skillConfig then return end
  677. skillNet.skillID = skillID
  678. skillNet.fireType = skillConfig.fireType
  679. skillNet.readyAction = skillConfig.readyAction
  680. skillNet.attackPart = skillConfig.attackPart
  681. skillNet.attackAction = skillConfig.attackAction
  682. skillNet.readyEffect = skillConfig.readyEffect
  683. skillNet.attackEffect = skillConfig.attackEffect
  684. skillNet.hitEffect = skillConfig.hitEffect
  685. skillNet.flyEffect = skillConfig.flyEffect
  686. skillNet.flyCoords = skillConfig.flyCoords
  687. skillNet.hitBack = skillConfig.hitBack
  688. skillNet.effectTime = skillConfig.effectTime
  689. skillNet.contentType = skillConfig.contentType
  690. skillNet.content = skillConfig.content
  691. skillNet.movieEffect = skillConfig.movieEffect
  692. skillNet.quake = skillConfig.quake
  693. skillNet.flySound = skillConfig.flySound
  694. skillNet.fireSound = skillConfig.fireSound
  695. skillNet.hitSound = skillConfig.hitSound
  696. skillNet.cvSound = skillConfig.cvSound
  697. skillNet.screenMask = skillConfig.screenMask
  698. skillNet.screenCam = skillConfig.screenCam
  699. skillNet.largeEffect = skillConfig.largeEffect
  700. skillNet.lie = skillConfig.lie
  701. skillNet.cuoZhen = skillConfig.cuoZhen
  702. skillNet.skillDelay = skillConfig.skillDelay
  703. skillNet.isFraming = skillConfig.isFraming
  704. return true
  705. end
  706. -- 封装技能cmd
  707. local function fontSkillCmd(cmdNet, cmd)
  708. local cmdConfig = SkillExcel.cmd[cmd]
  709. if not cmdConfig then return end
  710. cmdNet.cmd = cmd
  711. cmdNet.hitEffect = cmdConfig.hitEffect
  712. cmdNet.hitSound = cmdConfig.hitSound
  713. return true
  714. end
  715. -- 封装buff
  716. local function fontBufferNet(bufferNet, bufferID)
  717. --local bufferConf = BufferExcel.buffer[bufferID]
  718. local bufferConf = CombatBuff.GetBuffConfig(bufferID)
  719. if not bufferConf then return end
  720. bufferNet.bufferID = bufferID
  721. bufferNet.name = bufferConf.name
  722. bufferNet.desc = bufferConf.desc
  723. bufferNet.icon = bufferConf.icon
  724. bufferNet.keepEffect = bufferConf.keepEffect
  725. bufferNet.hitEffect = bufferConf.hitEffect
  726. bufferNet.validateEffect = bufferConf.validateEffect
  727. bufferNet.dieEffect = bufferConf.dieEffect
  728. bufferNet.cmd = bufferConf.cmd
  729. bufferNet.hitSound = bufferConf.hitSound
  730. bufferNet.holdOnDie = bufferConf.holdOnDie
  731. bufferNet.effectOffset = bufferConf.effectOffset
  732. bufferNet.canAppend = bufferConf.canAppend
  733. bufferNet.appendCnt = bufferConf.appendCnt
  734. return true
  735. end
  736. -- 封装阵法属性
  737. local function fontCombatPosAttr(attrNets, attrs)
  738. attrNets[0] = 0
  739. if type(attrs) ~= "table" then return end
  740. for key, value in pairs(attrs) do
  741. attrNets[0] = attrNets[0] + 1
  742. local attrNet = attrNets[attrNets[0]]
  743. attrNet.key = key
  744. attrNet.value = value
  745. end
  746. end
  747. -- 发送战斗开始
  748. local function sendCombatBegin(human, combatInfo, isLogin)
  749. combatInfo = combatInfo or human.combat
  750. if not combatInfo then return end
  751. local msgRet = Msg.gc.GC_COMBAT_BEGIN
  752. msgRet.isLogin = isLogin == true and 1 or 0
  753. msgRet.combatType = combatInfo.type
  754. local keepTime = os.time() - combatInfo.time
  755. if combatInfo.passTime < keepTime then
  756. combatInfo.passTime = keepTime
  757. end
  758. msgRet.keepTime = combatInfo.passTime
  759. if combatInfo.isVideo then -- 录像回放
  760. msgRet.keepTime = 0
  761. end
  762. local isCanQuick = getQuick(human, combatInfo.type)
  763. msgRet.isQuick = isCanQuick or 0
  764. msgRet.isVideo = combatInfo.isVideo == true and 1 or 0
  765. msgRet.mapID = combatInfo.mapID
  766. msgRet.speed = human.db and human.db.combatSpeed or 1
  767. msgRet.atkName = combatInfo.attacker and combatInfo.attacker.name or ""
  768. msgRet.defName = combatInfo.defender and combatInfo.defender.name or ""
  769. msgRet.atkUuid = combatInfo.attacker and combatInfo.attacker.uuid or ""
  770. msgRet.defUuid = combatInfo.defender and combatInfo.defender.uuid or ""
  771. msgRet.maxRound = combatInfo.maxRound
  772. -- msgRet.petCD = CombatDefine.PET_CD
  773. msgRet.heros[0] = 0
  774. msgRet.atkFormation = combatInfo.atkFormation
  775. msgRet.defFormation = combatInfo.defFormation
  776. -- msgRet.backup[0] = 2
  777. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  778. local obj = combatInfo.objList[i]
  779. if fontCombatHeroNet(msgRet.heros[msgRet.heros[0] + 1], obj) then
  780. msgRet.heros[0] = msgRet.heros[0] + 1
  781. end
  782. -- if i % CombatDefine.COMBAT_HERO_CNT == 0 then
  783. -- msgRet.backup[i/CombatDefine.COMBAT_HERO_CNT] = obj and obj.backupPos or 0
  784. -- end
  785. end
  786. msgRet.helps[0] = 0
  787. for _, help in pairs(combatInfo.helpList) do
  788. if fontCombatHelpNet(msgRet.helps[msgRet.helps[0] + 1], help) then
  789. msgRet.helps[0] = msgRet.helps[0] + 1
  790. end
  791. end
  792. for _, elf in pairs(combatInfo.elfList or {}) do
  793. if fontCombatElfpNet(msgRet.helps[msgRet.helps[0] + 1], elf) then
  794. msgRet.helps[0] = msgRet.helps[0] + 1
  795. end
  796. end
  797. msgRet.skillList[0] = 0
  798. for skillID in pairs(combatInfo.skillUseList) do
  799. if fontCombatSkillNet(msgRet.skillList[msgRet.skillList[0] + 1], skillID) then
  800. msgRet.skillList[0] = msgRet.skillList[0] + 1
  801. end
  802. end
  803. msgRet.cmdList[0] = 0
  804. if combatInfo.cmdUseList then
  805. for cmd in pairs(combatInfo.cmdUseList) do
  806. if fontSkillCmd(msgRet.cmdList[msgRet.cmdList[0] + 1], cmd) then
  807. msgRet.cmdList[0] = msgRet.cmdList[0] + 1
  808. end
  809. end
  810. end
  811. msgRet.bufferList[0] = 0
  812. for bufferID in pairs(combatInfo.bufferUseList) do
  813. if fontBufferNet(msgRet.bufferList[msgRet.bufferList[0] + 1], bufferID) then
  814. msgRet.bufferList[0] = msgRet.bufferList[0] + 1
  815. end
  816. end
  817. -- fontCombatPosAttr(msgRet.attrsAtk, combatInfo.posAttr[1])
  818. -- fontCombatPosAttr(msgRet.attrsDef, combatInfo.posAttr[2])
  819. -- msgRet.atkJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.ATTACK_SIDE])
  820. -- msgRet.defJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.DEFEND_SIDE])
  821. Msg.send(msgRet, human.fd)
  822. end
  823. -- 发送羁绊描述
  824. local function sendJibanDesc(human, combatInfo)
  825. local msgRet = Msg.gc.GC_COMBAT_JiBan_DESC
  826. msgRet.atkJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.ATTACK_SIDE])
  827. msgRet.defJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.DEFEND_SIDE])
  828. Msg.send(msgRet, human.fd)
  829. end
  830. -- 封装战斗帧技能信息
  831. local function fontFrameSkillNet(skillNet, skillData)
  832. skillNet.attackPos = skillData.attackPos
  833. skillNet.skillID = skillData.skillID
  834. skillNet.hitList[0] = 0
  835. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  836. local skillHitData = skillData.hitList[i]
  837. if skillHitData then
  838. skillNet.hitList[0] = skillNet.hitList[0] + 1
  839. local skillHitNet = skillNet.hitList[skillNet.hitList[0]]
  840. skillHitNet.pos = i
  841. skillHitNet.flag = skillHitData.flag
  842. skillHitNet.cmd = 0
  843. skillHitNet.hpNow = skillHitData.hpNow
  844. local frameAttrs = skillHitData.attrs
  845. skillHitNet.attrs[0] = frameAttrs and #frameAttrs or 0
  846. for j = 1, #frameAttrs do
  847. skillHitNet.attrs[j].key = frameAttrs[j][1]
  848. skillHitNet.attrs[j].value = frameAttrs[j][2]
  849. end
  850. end
  851. end
  852. skillNet.helpList[0] = 0
  853. --for i = CombatDefine.PET_POS_ATTACK, CombatDefine.PET_POS_DEFEND do
  854. -- local helpHitData = skillData.helpList and skillData.helpList[i]
  855. -- if helpHitData then
  856. -- skillNet.helpList[0] = skillNet.helpList[0] + 1
  857. -- local helpHitNet = skillNet.helpList[skillNet.helpList[0]]
  858. -- helpHitNet.pos = i
  859. -- end
  860. --end
  861. skillNet.extraList[0] = 0
  862. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  863. local extraHitData = skillData.extraList[i]
  864. if extraHitData then
  865. skillNet.extraList[0] = skillNet.extraList[0] + 1
  866. local extraHitNet = skillNet.extraList[skillNet.extraList[0]]
  867. extraHitNet.pos = i
  868. extraHitNet.flag = extraHitData.flag
  869. extraHitNet.cmd = extraHitData.cmd
  870. extraHitNet.hpNow = extraHitData.hpNow
  871. local frameAttrs = extraHitData.attrs
  872. local attrsLen = math.min(frameAttrs and #frameAttrs or 0, #extraHitNet.attrs)
  873. extraHitNet.attrs[0] = attrsLen
  874. for j = 1, attrsLen do
  875. extraHitNet.attrs[j].key = frameAttrs[j][1]
  876. extraHitNet.attrs[j].value = frameAttrs[j][2]
  877. end
  878. end
  879. end
  880. end
  881. -- 封装战斗帧buff信息
  882. local function fontFrameBuff(net, buffers)
  883. net[0] = #buffers
  884. for i = 1, net[0] do
  885. local bufferNet = net[i]
  886. local bufferData = buffers[i]
  887. bufferNet.bufferID = bufferData.id
  888. bufferNet.op = bufferData.op
  889. bufferNet.cnt = bufferData.cnt
  890. bufferNet.round = bufferData.round or -1
  891. bufferNet.hpNow = bufferData.hpNow
  892. bufferNet.attrs[0] = bufferData.attrs and #bufferData.attrs or 0
  893. for j = 1, bufferNet.attrs[0] do
  894. bufferNet.attrs[j].key = bufferData.attrs[j][1]
  895. bufferNet.attrs[j].value = bufferData.attrs[j][2]
  896. end
  897. end
  898. end
  899. -- 封装战斗帧
  900. local function fontFrameNet(net, frame)
  901. net.round = frame.round
  902. net.petCD = frame.petCD
  903. net.skillList[0] = #frame.skillList
  904. for i = 1, net.skillList[0] do
  905. local skillNet = net.skillList[i]
  906. local skillData = frame.skillList[i]
  907. fontFrameSkillNet(skillNet, skillData)
  908. end
  909. net.bufferList[0] = 0
  910. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  911. local bufferData = frame.bufferList[i]
  912. if bufferData then
  913. net.bufferList[0] = net.bufferList[0] + 1
  914. local bufferNet = net.bufferList[net.bufferList[0]]
  915. bufferNet.pos = i
  916. fontFrameBuff(bufferNet.list, bufferData)
  917. end
  918. end
  919. net.sayList[0] = 0
  920. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  921. if frame.sayList[i] then
  922. for _,saySkillID in ipairs(frame.sayList[i]) do
  923. net.sayList[0] = net.sayList[0] + 1
  924. local sayNet = net.sayList[net.sayList[0]]
  925. sayNet.pos = i
  926. sayNet.skillID = saySkillID
  927. end
  928. end
  929. end
  930. return net.skillList[0] > 0 or net.bufferList[0] > 0 or net.sayList[0] > 0
  931. end
  932. -- 发送战斗帧
  933. local function sendCombatFrame(human, combatInfo, isLogin)
  934. combatInfo = combatInfo or human.combat
  935. if not combatInfo then return end
  936. local result = combatInfo.result
  937. local msgFrame = Msg.gc.GC_COMBAT_FRAME
  938. msgFrame.isLogin = isLogin == true and 1 or 0
  939. msgFrame.isEnd = 0
  940. msgFrame.combatType = combatInfo.type
  941. msgFrame.frames[0] = 0
  942. local frameCnt = result.frames and #result.frames or 0
  943. local len = 1
  944. for i = 1, frameCnt do
  945. local frame = result.frames[i]
  946. msgFrame.frames[0] = len
  947. local frameNet = msgFrame.frames[msgFrame.frames[0]]
  948. if fontFrameNet(frameNet, frame) then
  949. if len >= CombatDefine.COMBAT_FRAME_MAXCNT then
  950. msgFrame.isEnd = (i == frameCnt) and 1 or 0
  951. Msg.send(msgFrame, human.fd)
  952. msgFrame.frames[0] = 0
  953. len = 1
  954. else
  955. len = len + 1
  956. end
  957. end
  958. end
  959. if msgFrame.isEnd == 0 or msgFrame.frames[0] > 0 then
  960. msgFrame.isEnd = 1
  961. Msg.send(msgFrame, human.fd)
  962. end
  963. end
  964. -- 发送战斗开始
  965. function sendCombatData(human, combatInfo, isLogin)
  966. sendCombatBegin(human, combatInfo, isLogin)
  967. sendJibanDesc(human, combatInfo)
  968. sendCombatFrame(human, combatInfo, isLogin)
  969. end
  970. -- 封装战斗统计
  971. function fontFinishResultNet(net, obj)
  972. net.pos = obj.pos
  973. net.hurt = obj.result[1]
  974. net.hp = obj.result[2]
  975. net.beHurt = obj.result[3]
  976. net.bout = obj.result[4]
  977. net.isDie = obj.hp == 0 and 1 or 0
  978. net.heroID = obj.id or 0
  979. net.head = obj.head or 0
  980. net.lv = obj.lv or 0
  981. net.star = obj.star or 0
  982. local heroConfig = HeroExcel.hero[net.heroID]
  983. local monsterConfig = MonsterExcel.monster[net.heroID] or BattleMonsterExcel.monster[net.heroID] or BattleMonsterExcel2.monster[net.heroID]
  984. if obj.type == CombatDefine.COMBAT_OBJ_TYPE1 then
  985. net.name = heroConfig and heroConfig.name or ""
  986. net.body = heroConfig and heroConfig.body.."" or ""
  987. net.head = heroConfig and heroConfig.head or 0
  988. net.grade = heroConfig and heroConfig.grade or 0
  989. elseif obj.type == CombatDefine.COMBAT_OBJ_TYPE99 then
  990. local itemCfg = ItemConfig[obj.id]
  991. net.name = itemCfg and itemCfg.name or ""
  992. net.body = itemCfg and itemCfg.icon.."" or ""
  993. net.head = itemCfg and itemCfg.icon or 0
  994. net.grade = 0
  995. else
  996. net.name = monsterConfig and monsterConfig.name or ""
  997. net.body = monsterConfig and monsterConfig.body.."" or ""
  998. net.head = monsterConfig and monsterConfig.head or 0
  999. net.grade = monsterConfig and monsterConfig.grade or 0
  1000. end
  1001. net.camp = heroConfig and heroConfig.camp or 0
  1002. end
  1003. -- 封装战斗结束魔兽信息
  1004. local function fontFinishPetNet(net, pet)
  1005. net.pos = pet.pos
  1006. net.side = pet.side
  1007. net.lv = pet.lv or 0
  1008. net.head = pet.head
  1009. end
  1010. function fontCombatFinish(dataNet, combatInfo, isQuick)
  1011. if not combatInfo then return end
  1012. local combatConfig = CombatExcel.combat[combatInfo.type]
  1013. if not combatConfig then return end
  1014. dataNet.nBattleType = 0
  1015. dataNet.ret = combatInfo.isWin and 1 or 2
  1016. dataNet.type = combatInfo.type
  1017. dataNet.param = combatInfo.endParam or "0"
  1018. dataNet.isVideo = (combatInfo.isVideo == true) and 1 or 0
  1019. dataNet.lookType = combatInfo.lookType or 0
  1020. dataNet.isQuick = isQuick or 0
  1021. dataNet.combatTime = getCombatUseTime(combatInfo)
  1022. dataNet.double = combatInfo.double or 0
  1023. dataNet.oldLv = combatInfo.attacker.oldLv or 0
  1024. dataNet.nextCombatType = combatInfo.nextCombatType or 0
  1025. dataNet.panelIDs[0] = #combatConfig.panelIDs
  1026. for i, panelID in ipairs(combatConfig.panelIDs) do
  1027. dataNet.panelIDs[i] = tonumber(panelID)
  1028. end
  1029. if combatInfo.panelID then
  1030. dataNet.panelIDs[0] = dataNet.panelIDs[0] + 1
  1031. dataNet.panelIDs[dataNet.panelIDs[0]] = tonumber(combatInfo.panelID)
  1032. end
  1033. -- 攻守方基本信息
  1034. RoleLogic.makeRoleBase(combatInfo.defender, dataNet.target)
  1035. RoleLogic.makeRoleBase(combatInfo.attacker, dataNet.self)
  1036. -- 每个出战单位的战斗统计
  1037. dataNet.result[0] = 0
  1038. for pos = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  1039. local obj = combatInfo.objList and combatInfo.objList[pos]
  1040. if obj then
  1041. dataNet.result[0] = dataNet.result[0] + 1
  1042. local net = dataNet.result[dataNet.result[0]]
  1043. fontFinishResultNet(net, obj)
  1044. end
  1045. end
  1046. -- 出战魔兽
  1047. for _,pos in ipairs(CombatDefine.SIDE2HELPPOS[0]) do
  1048. local pet = combatInfo.helpList and combatInfo.helpList[pos]
  1049. if pet and pet.isPet then
  1050. dataNet.result[0] = dataNet.result[0] + 1
  1051. local net = dataNet.result[dataNet.result[0]]
  1052. fontFinishResultNet(net, pet)
  1053. end
  1054. end
  1055. -- 出战精灵
  1056. for _,pos in ipairs(CombatDefine.SIDE2ELFPOS[0]) do
  1057. local elfObj = combatInfo.elfList and combatInfo.elfList[pos]
  1058. if elfObj then
  1059. dataNet.result[0] = dataNet.result[0] + 1
  1060. local net = dataNet.result[dataNet.result[0]]
  1061. fontFinishResultNet(net, elfObj)
  1062. end
  1063. end
  1064. -- 奖励
  1065. local rewardItem = combatInfo.rewardItem
  1066. local len = 0
  1067. for k, v in pairs(rewardItem) do
  1068. if not ItemDefine.isEquip(v[1]) then
  1069. len = len + 1
  1070. Grid.makeItem(dataNet.items[len], v[1], v[2])
  1071. end
  1072. end
  1073. dataNet.items[0] = EquipLogic.makeEquipItem(combatInfo, dataNet.items, len)
  1074. return true
  1075. end
  1076. -- 发送战斗结束
  1077. function sendCombatFinish(human, combatInfo)
  1078. local msgRet = Msg.gc.GC_COMBAT_FINISH
  1079. msgRet.data.nBattleType = 0
  1080. local dataNet = msgRet.data
  1081. local isQuick = human.db.combatQuick[combatInfo.type] or 0
  1082. if not fontCombatFinish(dataNet, combatInfo, isQuick) then
  1083. return
  1084. end
  1085. BeginStory.handleBattleFail(human, combatInfo.isWin, combatInfo.type, combatInfo.isVideo, msgRet)
  1086. BeginStory.handleBattle8End(human, combatInfo.isWin, combatInfo.isVideo, combatInfo.type, msgRet)
  1087. BeginStory.handleBattle12End(human, combatInfo.isWin, combatInfo.isVideo, combatInfo.type, msgRet)
  1088. if CombatDefine.COMBAT_TYPE1 == combatInfo.type or CombatDefine.COMBAT_TYPE30 == combatInfo.type or CombatDefine.COMBAT_TYPE38 == combatInfo.type then
  1089. msgRet.data.nBattleType = human.db.battleType
  1090. if true == combatInfo.isWin and BattleLogic.BattleLogic_IsLastLevels(human, human.db.battleType) then
  1091. msgRet.data.param = "0|0|0"
  1092. end
  1093. end
  1094. Msg.send(msgRet,human.fd)
  1095. end
  1096. ---------------------------------------- 下面是战斗各种设置逻辑 ------------------------------------------------
  1097. local function getMonsterBossName(param)
  1098. local monsterOutID = param.monsterOutID
  1099. local posList = param.posList
  1100. for i,member in ipairs(MonsterExcel.monsterOut[monsterOutID].member) do
  1101. local monsterID = member[1]
  1102. local monsterConfig = MonsterExcel.monster[monsterID]
  1103. if monsterConfig and posList[monsterID] ~= nil then
  1104. return monsterConfig.name
  1105. end
  1106. end
  1107. end
  1108. -- 从某方战斗英雄阵容中获取某个属性的最大值
  1109. local function getHeroAttrMaxVal(side, attrId)
  1110. local maxVal = 0
  1111. for _, pos in ipairs(CombatDefine.SIDE2POS[side]) do
  1112. local obj = CombatImpl.objList[pos]
  1113. if obj then
  1114. local attrVal = CombatObj.getValue(obj,attrId)
  1115. if attrVal > maxVal then
  1116. maxVal = attrVal
  1117. end
  1118. end
  1119. end
  1120. return maxVal
  1121. end
  1122. -- 在各种战前加成后,重新设置血量
  1123. function recalcHpFightBegin(human, combatType, cbParam)
  1124. for i = 1,CombatDefine.COMBAT_HERO_CNT do
  1125. local atkPos = getPos(CombatDefine.ATTACK_SIDE, i)
  1126. local atkObj = CombatImpl.objList[atkPos]
  1127. if atkObj then
  1128. if atkObj.isSysAttrChange then
  1129. CombatObj.calcAttr(atkObj)
  1130. -- 重新计算血量
  1131. if combatType == CombatDefine.COMBAT_TYPE9 then
  1132. DrillLogic.calcAttrAtk(human, i, atkObj, cbParam)
  1133. elseif combatType == CombatDefine.COMBAT_TYPE17 then
  1134. ValleyLogic.calcAttr(CombatDefine.ATTACK_SIDE, i, atkObj, cbParam)
  1135. elseif combatType == CombatDefine.COMBAT_TYPE8 then
  1136. LianyuLogic.recalcHpFightBegin(human, i, atkObj)
  1137. end
  1138. end
  1139. atkObj.hpMax = CombatObj.getHpMax(atkObj)
  1140. atkObj.hp = atkObj.hp or CombatObj.getHpMax(atkObj)
  1141. atkObj.mp = atkObj.mp or atkObj.attr[RoleDefine.INIT_MP]
  1142. atkObj.initHp = atkObj.hp
  1143. atkObj.initMp = atkObj.mp
  1144. end
  1145. local defPos = getPos(CombatDefine.DEFEND_SIDE, i)
  1146. local defObj = CombatImpl.objList[defPos]
  1147. if defObj then
  1148. if defObj.isSysAttrChange then
  1149. CombatObj.calcAttr(defObj)
  1150. if combatType == CombatDefine.COMBAT_TYPE9 then
  1151. DrillLogic.calcAttrDef(human, i, defObj, cbParam)
  1152. elseif combatType == CombatDefine.COMBAT_TYPE17 then
  1153. ValleyLogic.calcAttr(CombatDefine.DEFEND_SIDE, i, defObj, cbParam)
  1154. end
  1155. end
  1156. defObj.hpMax = CombatObj.getHpMax(defObj)
  1157. defObj.hp = defObj.hp or CombatObj.getHpMax(defObj)
  1158. defObj.mp = defObj.mp or defObj.attr[RoleDefine.INIT_MP]
  1159. defObj.initHp = defObj.hp
  1160. defObj.initMp = defObj.mp
  1161. end
  1162. end
  1163. end
  1164. -- 精灵继承英雄属性列表, key为属性Id, value为继承属性值的倍数
  1165. local inheritAttrList = {
  1166. [RoleDefine.ATK] = 1,
  1167. }
  1168. -- 精灵继承英雄部分属性
  1169. function ElfInheritHeroAttr()
  1170. local attrList = {}
  1171. local function genAttrVal()
  1172. for attrId, mul in pairs(inheritAttrList) do
  1173. attrList[attrId] = { [CombatDefine.ATTACK_SIDE] = 0, [CombatDefine.DEFEND_SIDE] = 0,}
  1174. local atkMaxVal = getHeroAttrMaxVal(CombatDefine.ATTACK_SIDE, attrId)
  1175. local defMaxVal = getHeroAttrMaxVal(CombatDefine.DEFEND_SIDE, attrId)
  1176. attrList[attrId][CombatDefine.ATTACK_SIDE] = atkMaxVal * mul
  1177. attrList[attrId][CombatDefine.DEFEND_SIDE] = defMaxVal * mul
  1178. end
  1179. end
  1180. local function updateELfAttr(elfObj, side)
  1181. for attrId, valData in pairs(attrList) do
  1182. CombatObj.updateValue(elfObj, attrId, valData[side] or 0)
  1183. end
  1184. end
  1185. for _, pos in ipairs(CombatDefine.SIDE2ELFPOS[CombatDefine.ALL]) do
  1186. local elfObj = CombatImpl.elfList[pos]
  1187. if elfObj then
  1188. if next(inheritAttrList) and not next(attrList) then
  1189. genAttrVal()
  1190. end
  1191. local elfSide = getSideByPos(CombatDefine.HELP_TYPE2, pos)
  1192. updateELfAttr(elfObj, elfSide)
  1193. end
  1194. end
  1195. end
  1196. --战前加属性(包括各系统,被动技能,阵营光环)
  1197. function onFightBegin(human, combatType, cbParam, param)
  1198. local moduleFn = getModule(combatType)
  1199. if moduleFn and moduleFn.onFightBegin then
  1200. moduleFn.onFightBegin(human, cbParam, combatType, param)
  1201. end
  1202. BeSkill.onFightBegin(human)
  1203. SkinLogic.onFightBegin(human) -- 处理皮肤属性
  1204. CombatPosLogic.onFightBegin(human)
  1205. recalcHpFightBegin(human, combatType, cbParam)
  1206. ElfInheritHeroAttr()
  1207. end
  1208. function getHumanHeroList(human,combatType, cbParam)
  1209. return getHumanObjList(human, combatType)
  1210. end
  1211. -- 设置英雄出战
  1212. local function setCombatInfo(formation,objList, side)
  1213. for index = 1, CombatDefine.COMBAT_HERO_CNT do
  1214. local obj = objList[index]
  1215. if obj then
  1216. -- 出战英雄站位
  1217. if CombatPosLogic.checkPos(formation,index, side) then
  1218. local pos = CombatDefine.SIDE2POS[side][index]
  1219. obj.formationPos = index
  1220. CombatImpl.setData(pos, obj)
  1221. end
  1222. end
  1223. end
  1224. end
  1225. -- 设置辅助对象出战
  1226. local function setHelp(helpList, side)
  1227. if not helpList then return end
  1228. for k,v in pairs(helpList) do
  1229. if k == CombatDefine.HELP_TYPE1 then
  1230. CombatPetCalc.calcGrowArgs(v)
  1231. CombatPetCalc.clacBuffArgs(v)
  1232. end
  1233. CombatImpl.setHelp(side,k,v)
  1234. end
  1235. end
  1236. -- 设置精灵出战
  1237. local function setElf(elfList, side)
  1238. if not elfList or not next(elfList) then
  1239. return
  1240. end
  1241. for index = 1, CombatDefine.COMBAT_ELF_CNT do
  1242. local elfObj = elfList[index]
  1243. if elfObj then
  1244. local pos = CombatDefine.SIDE2ELFPOS[side][index]
  1245. CombatImpl.setElf(pos, elfObj)
  1246. end
  1247. end
  1248. end
  1249. -- 初始combatInfo
  1250. local function initCombatInfo(human, combatType, mapID)
  1251. local combatInfo = {}
  1252. combatInfo.time = os.time() -- 战斗时间
  1253. combatInfo.passTime = 0 -- 客户端经过的时间
  1254. combatInfo.type = combatType -- 战斗类型
  1255. combatInfo.mapID = mapID -- 地图
  1256. combatInfo.posAttr = {} -- 阵法属性
  1257. combatInfo.jiban = {} -- 阵法属性
  1258. combatInfo.attacker = nil -- 攻方基础角色信息 roleBase
  1259. combatInfo.defender = nil -- 守方基础角色信息 roleBase
  1260. combatInfo.atkJiban = nil -- 攻方羁绊英雄
  1261. combatInfo.defJiban = nil -- 守方羁绊英雄
  1262. combatInfo.isWin = nil -- 战斗结果
  1263. combatInfo.result = nil -- 战斗帧
  1264. combatInfo.skillUseList = nil -- 战斗技能
  1265. combatInfo.cmdUseList = nil -- 战斗技能命令
  1266. combatInfo.bufferUseList = nil -- 战斗buff
  1267. combatInfo.objList = nil -- 战斗英雄列表
  1268. combatInfo.helpList = nil -- 战斗魔兽列表
  1269. combatInfo.elfList = nil -- 战斗精灵列表
  1270. combatInfo.rewardItem = {} -- 奖励
  1271. combatInfo.endParam = nil -- 额外参数
  1272. combatInfo.isVideo = nil -- 是否录像
  1273. combatInfo.videoUuid = nil -- 录像uuid
  1274. combatInfo.panelID = nil -- 返回界面(特殊)
  1275. combatInfo.maxRound = nil -- 最大会合数
  1276. combatInfo.fightMode = nil -- 战斗模式
  1277. human.combat = combatInfo
  1278. return combatInfo
  1279. end
  1280. -- 为了战斗回放,某些数据需要保存
  1281. local function copyToCombatInfo(combatInfo)
  1282. combatInfo.isWin = CombatImpl.result.isWin
  1283. combatInfo.result = Util.copyTable(CombatImpl.result)
  1284. combatInfo.result.round = CombatImpl.round
  1285. combatInfo.skillUseList = Util.copyTable(CombatImpl.skillUseList)
  1286. combatInfo.cmdUseList = Util.copyTable(CombatImpl.cmdUseList)
  1287. combatInfo.bufferUseList = Util.copyTable(CombatImpl.bufferUseList)
  1288. combatInfo.objList = Util.copyTable(CombatImpl.objList)
  1289. combatInfo.helpList = Util.copyTable(CombatImpl.helpList)
  1290. combatInfo.elfList = Util.copyTable(CombatImpl.elfList)
  1291. combatInfo.totalAtkCnt = CombatImpl.totalAtkCnt
  1292. end
  1293. function setSkillAndBeskill(human,combatInfo)
  1294. local combatType = combatInfo.type
  1295. local moduleFn = getModule(combatType)
  1296. if moduleFn and moduleFn.setSkillAndBeskill then
  1297. moduleFn.setSkillAndBeskill(human,combatInfo)
  1298. end
  1299. end
  1300. function combatBegin(human, mapID, param, combatType, cbParam, isSaodang)
  1301. if COMBAT_CACHE[human.db._id] and COMBAT_CACHE[human.db._id][combatType] then
  1302. --assert(nil, "has combat cache "..combatType .. " " .. human.db.account) -- reyes test
  1303. human.combat = COMBAT_CACHE[human.db._id][combatType].combatInfo
  1304. sendCombatData(human, human.combat)
  1305. return
  1306. end
  1307. -- 获得地图ID
  1308. CombatImpl.init(combatType)
  1309. mapID = getMapID(human, combatType, param)
  1310. local defender, defHelp, defRBase,defFormation,defJiban, defElfList = getCombatObjList(human, CombatDefine.DEFEND_SIDE, combatType, param)
  1311. local attacker, atkHelp, atkRBase, atkFormation,atkJiban, atkElfList
  1312. if defender then
  1313. attacker, atkHelp, atkRBase, atkFormation,atkJiban, atkElfList = getCombatObjList(human, CombatDefine.ATTACK_SIDE, combatType, param)
  1314. end
  1315. if not (attacker and next(attacker)) then
  1316. return
  1317. end
  1318. if not defender then
  1319. return
  1320. end
  1321. local combatInfo = initCombatInfo(human, combatType, mapID)
  1322. combatInfo.attacker = atkRBase or {}
  1323. combatInfo.atkHelp = atkHelp or {}
  1324. combatInfo.atkFormation = atkFormation
  1325. combatInfo.atkJiban = atkJiban
  1326. combatInfo.defender = defRBase or {}
  1327. combatInfo.defHelp = defHelp or {}
  1328. combatInfo.defFormation = defFormation
  1329. combatInfo.defJiban = defJiban
  1330. combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker)
  1331. combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender)
  1332. combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker,atkJiban)
  1333. combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender,defJiban)
  1334. combatInfo.maxRound = getMaxRound(human,combatType)
  1335. combatInfo.fightMode = getFightMode(combatType)
  1336. --战役第五关特殊处理
  1337. BeginStory.handleBattle5(human, combatType, defender)
  1338. JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE])
  1339. JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE])
  1340. local changePos = nil
  1341. if combatType == CombatDefine.COMBAT_TYPE10 then
  1342. for k,v in pairs(attacker) do
  1343. changePos = k
  1344. attacker[k] = nil
  1345. attacker[5] = v
  1346. break
  1347. end
  1348. end
  1349. setCombatInfo(atkFormation, attacker, CombatDefine.ATTACK_SIDE)
  1350. setCombatInfo(defFormation, defender, CombatDefine.DEFEND_SIDE)
  1351. setHelp(atkHelp, CombatDefine.ATTACK_SIDE)
  1352. setHelp(defHelp, CombatDefine.DEFEND_SIDE)
  1353. setElf(atkElfList, CombatDefine.ATTACK_SIDE)
  1354. setElf(defElfList, CombatDefine.DEFEND_SIDE)
  1355. CombatImpl.setMaxRound(combatInfo.maxRound)
  1356. CombatImpl.setFightMode(combatInfo.fightMode)
  1357. --需要对技能特殊处理的(比如不重置cd)
  1358. setSkillAndBeskill(human,combatInfo)
  1359. -- 战前属性/血量重算
  1360. local tempParam = cbParam
  1361. if combatType == CombatDefine.COMBAT_TYPE10 then
  1362. tempParam = {}
  1363. tempParam.cbParam = cbParam
  1364. tempParam.changePos = changePos
  1365. end
  1366. onFightBegin(human, combatType, tempParam, param)
  1367. makeAttrLogStr(human)
  1368. while CombatImpl.calcFrame() do end
  1369. copyToCombatInfo(combatInfo)
  1370. combatInfo.changePos = changePos
  1371. local result = combatInfo.isWin and CombatDefine.RESULT_WIN or CombatDefine.RESULT_FAIL
  1372. local isQuick = human.db.combatQuick[combatType] == 1-- 是否跳过战斗
  1373. if isSaodang or isQuick then
  1374. -- 扫荡/跳过战斗需要立刻出结果
  1375. onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang)
  1376. sendCombatFinish(human, combatInfo)
  1377. else
  1378. -- 发送战斗开始+战斗帧
  1379. sendCombatData(human, combatInfo)
  1380. addCombatCache(human.db._id, combatInfo, cbParam,param)
  1381. end
  1382. makeLogStr(human) -- 写战斗日志
  1383. end
  1384. function getCombatUseTime(combatInfo)
  1385. local combatUseTime = CombatDefine.COMBAT_ATK_TIME * (combatInfo.totalAtkCnt or 0) -- 1.2秒1次行动
  1386. combatUseTime = combatUseTime + 10 --带上出场时间
  1387. return combatUseTime
  1388. end
  1389. function combatGm(human,mapID,atkFormation,attacker,defFormation,defender,atkPet,defPet,rewardItem)
  1390. local combatType = 0
  1391. local config = CombatExcel.combat[combatType]
  1392. local combatInfo = initCombatInfo(human, combatType, mapID)
  1393. combatInfo.attacker = {}
  1394. combatInfo.defender = {}
  1395. combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker)
  1396. combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender)
  1397. combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker)
  1398. combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender)
  1399. combatInfo.rewardItem = rewardItem or combatInfo.rewardItem
  1400. combatInfo.atkFormation = atkFormation
  1401. combatInfo.defFormation = defFormation
  1402. combatInfo.fightMode = config.fightMode
  1403. CombatImpl.init(combatType)
  1404. setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE)
  1405. setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE)
  1406. setHelp({atkPet}, CombatDefine.ATTACK_SIDE)
  1407. setHelp({defPet}, CombatDefine.DEFEND_SIDE)
  1408. setElf({}, CombatDefine.ATTACK_SIDE)
  1409. setElf({}, CombatDefine.DEFEND_SIDE)
  1410. combatInfo.maxRound = getMaxRound(human,combatType)
  1411. CombatImpl.setMaxRound(combatInfo.maxRound)
  1412. CombatImpl.setFightMode(combatInfo.fightMode)
  1413. -- 战前属性/血量重算
  1414. onFightBegin(human, combatType, nil, {}, {})
  1415. makeAttrLogStr(human)
  1416. while CombatImpl.calcFrame() do end
  1417. copyToCombatInfo(combatInfo)
  1418. sendCombatData(human, combatInfo)
  1419. -- 方便调试不做缓存
  1420. addCombatCache(human.db._id, combatInfo)
  1421. makeLogStr(human) -- 写战斗日志
  1422. end
  1423. function combatGuide(human, atkFormation,attacker,defFormation,defender,atkPet,defPet)
  1424. local combatType = CombatDefine.COMBAT_TYPE18
  1425. local config = CombatExcel.combat[combatType]
  1426. local combatInfo = initCombatInfo(human, combatType, config.mapID)
  1427. combatInfo.attacker = {}
  1428. combatInfo.defender = {}
  1429. combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker)
  1430. combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender)
  1431. combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker)
  1432. combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender)
  1433. combatInfo.rewardItem = rewardItem or combatInfo.rewardItem
  1434. combatInfo.atkFormation = atkFormation
  1435. combatInfo.defFormation = defFormation
  1436. combatInfo.fightMode = config.fightMode
  1437. CombatImpl.init(combatType)
  1438. setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE)
  1439. setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE)
  1440. setHelp({atkPet}, CombatDefine.ATTACK_SIDE)
  1441. setHelp({defPet}, CombatDefine.DEFEND_SIDE)
  1442. setElf({}, CombatDefine.ATTACK_SIDE)
  1443. setElf({}, CombatDefine.DEFEND_SIDE)
  1444. combatInfo.maxRound = getMaxRound(human, combatType)
  1445. CombatImpl.setMaxRound(combatInfo.maxRound)
  1446. CombatImpl.setFightMode(combatInfo.fightMode)
  1447. JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE])
  1448. JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE])
  1449. -- 战前属性/血量重算
  1450. onFightBegin(human, combatType, nil, {}, {})
  1451. human.combat = combatInfo
  1452. while CombatImpl.calcFrame() do end
  1453. copyToCombatInfo(human.combat)
  1454. end
  1455. --
  1456. function combatVedio(human, atkFormation, attacker,defFormation,defender,atkPet,defPet, fakeHuman)
  1457. local combatType = CombatDefine.COMBAT_TYPE22
  1458. local config = CombatExcel.combat[combatType]
  1459. local combatInfo = initCombatInfo(human, combatType, config.mapID)
  1460. combatInfo.attacker = {}
  1461. combatInfo.defender = {}
  1462. combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker)
  1463. combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender)
  1464. combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker)
  1465. combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender)
  1466. combatInfo.rewardItem = rewardItem or combatInfo.rewardItem
  1467. combatInfo.atkFormation = atkFormation
  1468. combatInfo.defFormation = defFormation
  1469. combatInfo.fightMode = config.fightMode
  1470. CombatImpl.init(combatType)
  1471. setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE)
  1472. setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE)
  1473. setHelp({atkPet}, CombatDefine.ATTACK_SIDE)
  1474. setHelp({defPet}, CombatDefine.DEFEND_SIDE)
  1475. setElf({}, CombatDefine.ATTACK_SIDE)
  1476. setElf({}, CombatDefine.DEFEND_SIDE)
  1477. combatInfo.maxRound = getMaxRound(human, combatType)
  1478. CombatImpl.setMaxRound(combatInfo.maxRound)
  1479. CombatImpl.setFightMode(combatInfo.fightMode)
  1480. JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE])
  1481. JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE])
  1482. -- 战前属性/血量重算
  1483. onFightBegin(human, combatType, nil, {}, {})
  1484. human.combat = combatInfo
  1485. while CombatImpl.calcFrame() do end
  1486. copyToCombatInfo(human.combat)
  1487. sendCombatData(fakeHuman, combatInfo)
  1488. end
  1489. -- 战斗录像
  1490. local VEDIO_COMBAT_INFO = VEDIO_COMBAT_INFO or { db = {} }
  1491. function combatFightVedio(human, heroID)
  1492. local heroConfig = HeroExcel.hero[heroID]
  1493. if not heroConfig then return end
  1494. local combatConf = CombatExcel.gm[heroConfig.gm]
  1495. if not combatConf then return end
  1496. VEDIO_COMBAT_INFO.attacker = {}
  1497. VEDIO_COMBAT_INFO.defender = {}
  1498. VEDIO_COMBAT_INFO.atkFormation = combatConf.atkF
  1499. VEDIO_COMBAT_INFO.defFormation = combatConf.defF
  1500. local atkConf = nil
  1501. for i = 1, CombatDefine.COMBAT_HERO_CNT do
  1502. atkConf = nil
  1503. for k, v in ipairs(combatConf.atk) do
  1504. if i == v[2] then
  1505. atkConf = v
  1506. break
  1507. end
  1508. end
  1509. if atkConf then
  1510. VEDIO_COMBAT_INFO.attacker[i] = createHeroObj(VEDIO_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i,atkConf[5])
  1511. end
  1512. atkConf = nil
  1513. for k, v in ipairs(combatConf.def) do
  1514. if i == v[2] then
  1515. atkConf = v
  1516. break
  1517. end
  1518. end
  1519. if atkConf then
  1520. VEDIO_COMBAT_INFO.defender[i] = createHeroObj(VEDIO_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i,atkConf[5])
  1521. end
  1522. end
  1523. combatVedio(VEDIO_COMBAT_INFO, VEDIO_COMBAT_INFO.atkFormation, VEDIO_COMBAT_INFO.attacker,
  1524. VEDIO_COMBAT_INFO.defFormation, VEDIO_COMBAT_INFO.defender, nil, nil, human)
  1525. end
  1526. function repeatCombat(human, combatInfo)
  1527. if not combatInfo then
  1528. return
  1529. end
  1530. -- if isCombating(human) then
  1531. -- return Broadcast.sendErr(human, Lang.COMBAT_VIDEO_LOOK_ERR_ING)
  1532. -- end
  1533. combatInfo.isVideo = true
  1534. human.combat = combatInfo
  1535. sendCombatData(human, combatInfo)
  1536. sendCombatFinish(human, combatInfo)
  1537. end
  1538. -- 初始属性数据写日志
  1539. function makeAttrLogStr(human)
  1540. if not Config.IS_DEBUG then
  1541. return
  1542. end
  1543. local logStr = "\n初始属性数据:\n"
  1544. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  1545. data = CombatImpl.objList[i]
  1546. if data then
  1547. logStr = logStr .. "\n\t" .. "{pos:"..data.pos.." heroID:"..data.id.."}\n\t"
  1548. for k,v in pairs(data.attr) do
  1549. if v ~= 0 then
  1550. logStr = logStr .."{key:"..k..",value:"..v.."},"
  1551. end
  1552. end
  1553. end
  1554. end
  1555. logStr = logStr .."\n"
  1556. local f = io.open("./log/fight_log.log", "w+")
  1557. f:write(logStr)
  1558. assert(io.close(f))
  1559. end
  1560. function makeLogStr(human)
  1561. if not Config.IS_DEBUG then
  1562. return
  1563. end
  1564. local logStr = "\n战斗开始数据:\n"
  1565. for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
  1566. data = CombatImpl.objList[i]
  1567. if data then
  1568. logStr = logStr .. "\t" .. "{pos:"..data.pos.." heroID:"..data.id.."}"
  1569. end
  1570. end
  1571. logStr = logStr .. "\n"
  1572. logStr = logStr .. "战斗帧数据:\n"
  1573. local result = CombatImpl.result
  1574. local frameCnt = result.frames and #result.frames or 0
  1575. for i = 1,frameCnt do
  1576. local data = result.frames[i]
  1577. logStr = logStr .. "\t" .. i .."帧\n"
  1578. for j = 1,#data.skillList do
  1579. local skillData = data.skillList[j]
  1580. logStr = logStr .. "\t\t技能释放 attackPos:"..skillData.attackPos.." skillID:"..skillData.skillID.."\n"
  1581. local hitLen = 0
  1582. for k = 1,CombatDefine.COMBAT_HERO_ALL_CNT do
  1583. if skillData.hitList[k] then
  1584. hitLen = hitLen + 1
  1585. local skillHitData = skillData.hitList[k]
  1586. logStr = logStr .. "\t\t\t技能对象"..hitLen.." pos:"..k.." hpNow:"..skillHitData.hpNow.." attrs:"
  1587. local frameAttrs = skillHitData.attrs
  1588. local attrsLen = 0
  1589. if frameAttrs then
  1590. for m = 1,#frameAttrs do
  1591. logStr = logStr .. " {key:"..frameAttrs[m][1].." value:"..frameAttrs[m][2].."}"
  1592. end
  1593. end
  1594. logStr = logStr .. "\n"
  1595. end
  1596. end
  1597. local extraLen = 0
  1598. for k = 1,CombatDefine.COMBAT_HERO_ALL_CNT do
  1599. if skillData.extraList[k] then
  1600. extraLen = extraLen + 1
  1601. local extraHitData = skillData.extraList[k]
  1602. logStr = logStr .. "\t\t\t额外作用对象"..extraLen.." pos:"..k.." cmd:"..extraHitData.cmd.." hpNow:"..extraHitData.hpNow.." attrs:"
  1603. local frameAttrs = extraHitData.attrs
  1604. if frameAttrs then
  1605. for m = 1,#frameAttrs do
  1606. logStr = logStr .. " {key:"..frameAttrs[m][1].." value:"..frameAttrs[m][2].."}"
  1607. end
  1608. end
  1609. logStr = logStr .. "\n"
  1610. end
  1611. end
  1612. end
  1613. local bufferLen = 0
  1614. for j = 1,CombatDefine.COMBAT_HERO_ALL_CNT do
  1615. if data.bufferList[j] then
  1616. bufferLen = bufferLen + 1
  1617. logStr = logStr .. "\t\tbuffer更新 pos:"..j.."\n"
  1618. local bufferDataList = data.bufferList[j]
  1619. for i = 1,#bufferDataList do
  1620. local bufferData = bufferDataList[i]
  1621. logStr = logStr .. "\t\t\t bufferID:"..bufferData.id.." op:"..bufferData.op.." cnt:"..bufferData.cnt.." round:"..(bufferData.round or -1).." hpNow:"..bufferData.hpNow.." attrs:"
  1622. local attrsLen = 0
  1623. if bufferData.attrs then
  1624. for k,v in ipairs(bufferData.attrs) do
  1625. logStr = logStr .. " {key:"..v[1].." value:"..v[2].."}"
  1626. end
  1627. end
  1628. end
  1629. logStr = logStr .. "\n"
  1630. end
  1631. end
  1632. end
  1633. local f = io.open("./log/fight_log.log", "a+")
  1634. f:write(logStr)
  1635. assert(io.close(f))
  1636. end
  1637. -- 获取角色上阵的形象
  1638. function getRoleBody(human, combatType)
  1639. local teamType = CombatPosLogic.getTeamType(combatType)
  1640. local combatHero = teamType and human.db.combatHero[teamType]
  1641. if not combatHero then return end
  1642. local zhandouli = 0
  1643. local maxGrid = nil
  1644. for i = 1, CombatDefine.COMBAT_HERO_CNT do
  1645. local uuid = combatHero.list[i]
  1646. local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
  1647. if heroGrid and type(heroGrid) == "table" and
  1648. zhandouli < heroGrid.zhandouli then
  1649. zhandouli = heroGrid.zhandouli
  1650. maxGrid = heroGrid
  1651. end
  1652. end
  1653. if not maxGrid then return end
  1654. return HeroGrid.getHeroBodyById(maxGrid.id)
  1655. end
  1656. -- 根据怪物组id获取外显
  1657. function getMonsterIDByOutID(monsterOutID, args)
  1658. local mocf = MonsterExcel.monsterOut[monsterOutID] or BattleMonsterExcel.monsterOut[monsterOutID] or BattleMonsterExcel2.monsterOut[monsterOutID]
  1659. if not mocf then return end
  1660. local memberCnt = #mocf.member
  1661. local index = (monsterOutID % 1000) % memberCnt
  1662. if index == 0 then index = memberCnt - 1 end
  1663. local minfo = mocf.member[index]
  1664. if not minfo then
  1665. for _, minfo0 in ipairs(mocf.member) do
  1666. if minfo0[1] > 0 then
  1667. minfo = minfo0
  1668. break
  1669. end
  1670. end
  1671. end
  1672. if not minfo then return end
  1673. local monsterID = minfo[1]
  1674. local monsterLv = minfo[2]
  1675. local mcf = monsterID and MonsterExcel.monster[monsterID]
  1676. if not mcf then
  1677. mcf = BattleMonsterExcel.monster[monsterID] or BattleMonsterExcel2.monster[monsterID]
  1678. end
  1679. if not mcf then return end
  1680. if mocf.combatType == CombatDefine.COMBAT_TYPE5 then
  1681. if args then
  1682. local throneID = args[1]
  1683. local evolveCnt = args[2]
  1684. monsterLv = TheStarsLogic.getMonsterLvAttr(1, throneID, evolveCnt)
  1685. end
  1686. end
  1687. return monsterID, mcf, monsterLv
  1688. end
  1689. -- 根据伤害计算胜负
  1690. function calcWinByHurt(combatInfo)
  1691. if not combatInfo.isWin then return end
  1692. if not combatInfo.objList then return end
  1693. local atkHurt = 0
  1694. local defHurt = 0
  1695. local atkLive = 0
  1696. local defLive = 0
  1697. for i = 1,CombatDefine.COMBAT_HERO_CNT do
  1698. local atkPos = getPos(CombatDefine.ATTACK_SIDE, i)
  1699. local atkObj = combatInfo.objList[atkPos]
  1700. if atkObj then
  1701. atkHurt = atkHurt + atkObj.result[1]
  1702. if atkObj.hp > 0 and not atkLive then
  1703. atkLive = 1
  1704. end
  1705. end
  1706. local defPos = getPos(CombatDefine.DEFEND_SIDE, i)
  1707. local defObj = combatInfo.objList[defPos]
  1708. if defObj then
  1709. defHurt = defHurt + defObj.result[1]
  1710. if atkObj.hp > 0 and not defLive then
  1711. defLive = 1
  1712. end
  1713. end
  1714. end
  1715. if atkLive == 0 then
  1716. atkHurt = 0
  1717. elseif defLive == 0 then
  1718. defLive = 0
  1719. end
  1720. combatInfo.isWin = atkHurt > defHurt and true or false
  1721. return combatInfo.isWin
  1722. end
  1723. ------------- reyes test ---------------------
  1724. function isCombating(human)
  1725. local list = COMBAT_CACHE[human.db._id]
  1726. if not list then return end
  1727. for combatType, combatCache in pairs(list) do
  1728. if not combatCache.combatInfo.isVideo then
  1729. return true
  1730. end
  1731. end
  1732. end
  1733. function getCombatCache(uuid, type)
  1734. return COMBAT_CACHE[uuid] and COMBAT_CACHE[uuid][type]
  1735. end
  1736. function addCombatCache(uuid, combatInfo, cbParam,param)
  1737. COMBAT_CACHE[uuid] = COMBAT_CACHE[uuid] or {} -- reyes test
  1738. local tempCache = {}
  1739. local result = combatInfo.isWin and CombatDefine.RESULT_WIN or CombatDefine.RESULT_FAIL
  1740. tempCache.result = result
  1741. tempCache.combatType = combatInfo.type
  1742. tempCache.cbParam = cbParam
  1743. tempCache.combatInfo = combatInfo
  1744. tempCache.param = param
  1745. tempCache.ts = os.time() + getCombatUseTime(combatInfo)
  1746. COMBAT_CACHE[uuid][combatInfo.type] = tempCache
  1747. end
  1748. function cleanCombatCache(uuid, type)
  1749. if not COMBAT_CACHE[uuid] then return end
  1750. COMBAT_CACHE[uuid][type] = nil
  1751. if Util.getTableCount(COMBAT_CACHE[uuid]) == 0 then
  1752. COMBAT_CACHE[uuid] = nil
  1753. end
  1754. end
  1755. function clientFinish(human, type, noSend)
  1756. if COMBAT_CACHE[human.db._id] == nil or COMBAT_CACHE[human.db._id][type] == nil then
  1757. return
  1758. end
  1759. local combatCache = COMBAT_CACHE[human.db._id][type]
  1760. cleanCombatCache(human.db._id, type)
  1761. --print("onend-=----------------------")
  1762. if not combatCache.combatInfo.isVideo then
  1763. onFightEnd(human, combatCache.result, combatCache.combatType, combatCache.cbParam, combatCache.combatInfo,combatCache.param)
  1764. end
  1765. -- 绝望深渊 非失败 不发
  1766. -- 冰龙 次元魔珠 失落神庙 不走默认结算协议
  1767. if type ~= CombatDefine.COMBAT_TYPE8 and
  1768. type ~= CombatDefine.COMABT_TYPE23 and
  1769. type ~= CombatDefine.COMBAT_TYPE20 and
  1770. type ~= CombatDefine.COMBAT_TYPE24
  1771. and not noSend then
  1772. sendCombatFinish(human, combatCache.combatInfo)
  1773. end
  1774. end
  1775. function clientPassTime(human, type, passTime)
  1776. if COMBAT_CACHE[human.db._id] == nil or COMBAT_CACHE[human.db._id][type] == nil then
  1777. return
  1778. end
  1779. local combatInfo = COMBAT_CACHE[human.db._id][type].combatInfo
  1780. combatInfo.passTime = passTime
  1781. end
  1782. function onLogin(human)
  1783. checkFinish(human)
  1784. -- 这里要先check才判断cache 因为check完cache可能就空了
  1785. if COMBAT_CACHE[human.db._id] == nil then
  1786. return
  1787. end
  1788. for k, v in pairs(COMBAT_CACHE[human.db._id]) do
  1789. --assert(nil, "has combat cache "..combatType .. " " .. human.db.account) -- reyes test
  1790. human.combat = v.combatInfo
  1791. sendCombatData(human, human.combat, true)
  1792. end
  1793. end
  1794. function checkFinish(human)
  1795. if COMBAT_CACHE[human.db._id] == nil then
  1796. return
  1797. end
  1798. local now = os.time()
  1799. for k, v in pairs(COMBAT_CACHE[human.db._id]) do
  1800. if now >= v.ts then
  1801. clientFinish(human, k)
  1802. if COMBAT_CACHE[human.db._id] == nil then
  1803. return
  1804. end
  1805. end
  1806. end
  1807. end
  1808. -- 不管时间立刻结算 目前只有踢人等非正常下线会用到
  1809. function forceFinish(human)
  1810. if COMBAT_CACHE[human.db._id] == nil then
  1811. return
  1812. end
  1813. local now = os.time()
  1814. for k, v in pairs(COMBAT_CACHE[human.db._id]) do
  1815. clientFinish(human, k)
  1816. if COMBAT_CACHE[human.db._id] == nil then
  1817. return
  1818. end
  1819. end
  1820. end
  1821. function killFrames(combatInfo)
  1822. --60帧2倍速情况下大概1分半。限制录像时长再3-5分钟。节省包量
  1823. if combatInfo.result.frames and #combatInfo.result.frames > 200 then
  1824. for i = 201,#combatInfo.result.frames do
  1825. combatInfo.result.frames[i] = nil
  1826. end
  1827. end
  1828. end