CombatLogic.lua 61 KB

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