CombatLogic.lua 67 KB

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