CombatLogic.lua 59 KB

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