CombatLogic.lua 68 KB

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