CombatLogic.lua 61 KB

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