CombatLogic.lua 67 KB

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