CombatLogic.lua 59 KB

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