---------------------------------- -- 战斗逻辑 -- combatBegin 开始战斗 -- createCombatFakeHuman 根据uuid创角战斗human -- fight 战斗开始前各模块自己的判断函数,成功调用CombatLogic.combatBegin() -- onFightBegin 战斗帧计算前的属性重新计算 -- onFightEnd 战斗结束回调,发送GC_COMBAT_FINISH前 -- checkCombatPos 可否打开上阵界面(默认可打开) -- 获取双方上阵对象信息 -- getCombatMonsterOutID 获取上阵怪物组id -- getCombatTarget 获取上阵human信息 -- getCombatObjList 获取上阵队伍列表 ---------------------------------- local CombatExcel = require("excel.combat") local MonsterExcel = require("excel.monster") local HeroExcel = require("excel.hero") local SkillExcel = require("excel.skill") local BufferExcel = require("excel.buffer") local Config = require("Config") local Util = require("common.Util") local Lang = require("common.Lang") local Log = require("common.Log") local Msg = require("core.Msg") local ObjHuman = require("core.ObjHuman") local Grid = require("bag.Grid") local Broadcast = require("broadcast.Broadcast") local BeSkill = require("combat.BeSkill") local CombatObj = require("combat.CombatObj") local CombatImpl = require("combat.CombatImpl") local CombatDefine = require("combat.CombatDefine") local CombatPosLogic = require("combat.CombatPosLogic") local CombatPetCalc = require("combat.CombatPetCalc") local MoshouLogic = require("moshou.MoshouLogic") local RoleDBLogic = require("role.RoleDBLogic") local RoleAttr = require("role.RoleAttr") local RoleDefine = require("role.RoleDefine") local RoleLogic = require("role.RoleLogic") local HeroGrid = require("hero.HeroGrid") local DrillLogic = require("drill.DrillLogic") local SkinLogic = require("skin.SkinLogic") local BeginStory = require("scene.BeginStory") local Skill = require("combat.Skill") local CombatPosExcel = require("excel.combatPos") local ValleyLogic = require("valley.ValleyLogic") local LianyuLogic = require("lianyu.LianyuLogic") local TheStarsLogic = require("theStars.TheStarsLogic") local HeroDefine = require("hero.HeroDefine") local JibanLogic = require("combat.JibanLogic") local EquipLogic = require("equip.EquipLogic") local ItemDefine = require("bag.ItemDefine") local HeroLogic = require("hero.HeroLogic") local XingYaoGongMing = require("xingYaoMen.XingYaoGongMing") local MoshouLogic = require("moshou.MoshouLogic") local LostTempleCombatLogic = require("lostTemple.lostTempleCombatLogic") local SkinExcel = require("excel.skin") local BattleLogic = require("battle.BattleLogic") -- 用于在切磋时取目标玩家db数据中的计算属性数据, 如果在 RoleAttr.calcHeroGrid中用到了,需要加到这个里面 FieldsCombat = { lv = 1, name = 1, head = 1, headFrame = 1, unionUuid = 1, lastLogoutTime = 1, combatHero = 1, heroBag = 1, moshou = 1, technology=1, chengjiu=1, realmLv = 1, talismanData = 1, headList = 1, headFrameList = 1, bodyList = 1, chenghaoList = 1,animationList =1,backgroundList =1, } COMBAT_CACHE = COMBAT_CACHE or {} ------------------------------------------- 模块相关 start ------------------------------------------------- -- 初始 COMBATTYPE_2_MODULE = COMBATTYPE_2_MODULE or {} function init() for combatType, cf in pairs(CombatExcel.combat) do if cf.moduleFn ~= "" then local moduleFn = load("return require(\""..cf.moduleFn.."\")")() COMBATTYPE_2_MODULE[combatType] = moduleFn end end end -- 获取模块 function getModule(combatType) if not combatType then return end return COMBATTYPE_2_MODULE[combatType] end -- 获取攻/守方怪物组id local function getCombatMonsterOutID(human, side, combatType, args) local moduleFn = getModule(combatType) if moduleFn and moduleFn.getCombatMonsterOutID then return moduleFn.getCombatMonsterOutID(human, side, args, combatType) end end -- 获取攻/守方怪物组id function getMapID(human, combatType, param) local moduleFn = getModule(combatType) local mapID = nil if moduleFn and moduleFn.getMapID then mapID = moduleFn.getMapID(human, param) end if not mapID then local config = CombatExcel.combat[combatType] mapID = config.mapID == 0 and 1001 or config.mapID end return mapID end -- 获取是否跳过 function getQuick(human, combatType) local config = CombatExcel.combat[combatType] local moduleFn = getModule(combatType) local quick = nil if moduleFn and moduleFn.getQuick then quick = moduleFn.getQuick(human, combatType) end if quick ~= nil and quick >= 0 then return quick end if human.db.combatQuick[combatType] and human.db.combatQuick[combatType] ~= 0 then if config.isQuick == 0 then human.db.combatQuick[combatType] = 0 end end return config.isQuick end -- 获取攻/守方对象 local function getCombatTarget(human, side, combatType, args) local moduleFn = getModule(combatType) if moduleFn and moduleFn.getCombatTarget then return moduleFn.getCombatTarget(human, side, args, combatType) end end --更新上阵信息回调 function onUpdatePos(human,combatType) local moduleFn = getModule(combatType) if moduleFn and moduleFn.onUpdatePos then return moduleFn.onUpdatePos(human) end end -- 获取攻/守方上阵信息 function getCombatObjList(human, side, combatType, args) if type(args) == "table" then if side == CombatDefine.ATTACK_SIDE then if args.attacker then return args.attacker, args.atkHelp, args.atkRBase, args.atkFormation,args.atkJiban end else if args.defender then return args.defender, args.defHelp, args.defRBase, args.defFormation,args.defJiban end end end local moduleFn = getModule(combatType) if not moduleFn then return end if moduleFn.getCombatObjList then local objList, helpList, rolebase, formation,jiban = moduleFn.getCombatObjList(human, side, args, combatType) if objList then return objList, helpList, rolebase ,formation,jiban end end local monsterOutID, zhandouli = getCombatMonsterOutID(human, side, combatType, args) if monsterOutID then local objList, helpList, rolebase, formation, jiban = getMonsterObjList(monsterOutID, nil, args) if zhandouli then rolebase.zhandouli = zhandouli end return objList, helpList, rolebase,formation,jiban end if moduleFn.getHumanObjList then return moduleFn.getHumanObjList(human, combatType) end local target = getCombatTarget(human, side, combatType, args) if target then return getHumanObjList(target, combatType) end if side == CombatDefine.ATTACK_SIDE then -- 没有模块没有特写,攻防默认取自身上阵信息 return getHumanObjList(human, combatType) end end --获取战斗最大回合数 local function getMaxRound(human,combatType) local config = CombatExcel.combat[combatType] if config and config.maxRound and config.maxRound > 0 then return config.maxRound end return CombatDefine.COMBAT_ROUND_MAX end --获取战斗模式 local function getFightMode(combatType) local config = CombatExcel.combat[combatType] if config.fightMode[1] == CombatDefine.FIGHT_MODE1 or config.fightMode[1] == CombatDefine.FIGHT_MODE3 then return config.fightMode end end -- 尝试战斗 function tryCombatBegin(human, combatType, param) local moduleFn = getModule(combatType) if moduleFn and moduleFn.fight then local args = Util.split(param, "|") return moduleFn.fight(human, args, combatType) end end -- 可否打开上阵界面 function checkCombatPos(human, combatType, args) local moduleFn = getModule(combatType) if moduleFn and moduleFn.checkCombatPos then return moduleFn.checkCombatPos(human, args, combatType) end return true end -- 战斗结束回调 在发送GC_COMBAT_FINISH前 local function onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang) local moduleFn = getModule(combatType) if not moduleFn then return end if not moduleFn.onFightEnd then return end moduleFn.onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang) end -- 战斗名称 function getCombatName(human, combatType, args) local moduleFn = getModule(combatType) if not moduleFn then return "" end if not moduleFn.getCombatName then return "" end return moduleFn.getCombatName(human, args, combatType) or "" end ------------------------------------------- 模块相关 end ------------------------------------------------- -- 判断阵容是不是为空 function isCombatHeroEmpty(combatHero) if not combatHero then return true end local isEmpty = true for _, heroUuid in pairs(combatHero) do if heroUuid and heroUuid ~= "" and heroUuid ~= "0" then isEmpty = nil break end end return isEmpty end -- 根据阵营和下标获取对战位置 function getPos(side, index) if side == CombatDefine.ATTACK_SIDE then return index elseif side == CombatDefine.DEFEND_SIDE then return index + CombatDefine.COMBAT_HERO_CNT else assert() end end function getIndexByPos(side, pos) if side == CombatDefine.ATTACK_SIDE then return pos elseif side == CombatDefine.DEFEND_SIDE then return pos - CombatDefine.COMBAT_HERO_CNT end end -- 获取对象配置 function getConfigByObj(obj) if not obj then return end local id = obj.id or obj.heroID if obj.type == CombatDefine.COMBAT_OBJ_TYPE1 then return HeroExcel.hero[id] end return MonsterExcel.monster[id] end -- 创建战斗Human function createCombatFakeHuman(uuid) if not uuid then return end local db = RoleDBLogic.getDb(uuid, FieldsCombat) if not db then return end local fakeHuman = {} fakeHuman.db = db return fakeHuman end -- 创建初始角色信息 function createRoleBaseDefault() local rolebase = {} RoleLogic.makeRoleBase(nil, rolebase, nil, true) rolebase.name = Lang.COMBAT_DEFEND_NAME return rolebase end -- 根据怪物信息创建角色信息 function createRoleBaseByMOutID(monsterOutID, zhandouli, args) local _, monsterConfig, monsterLv = getMonsterIDByOutID(monsterOutID, args) local rolebase = createRoleBaseDefault() if monsterConfig then rolebase.name = monsterConfig.name rolebase.lv = monsterLv or 1 rolebase.head = monsterConfig.head rolebase.zhandouli = zhandouli or 0 end return rolebase end -- 创建角色信息 function createRoleBaseByDB(db, zhandouli) local rolebase = {} RoleLogic.makeRoleBase(db, rolebase, nil, true) rolebase.zhandouli = zhandouli or 0 return rolebase end -- 根据怪物表信息创建临时对象 function createMonsterObj(id, lv, attrID, index, objType, monsterOutConfig, attrInput) local monsterConfig = MonsterExcel.monster[id] if not monsterConfig then return end local obj = {} obj.type = objType or CombatDefine.COMBAT_OBJ_TYPE2 obj.bagIndex = index obj.id = id obj.lv = lv obj.job = monsterConfig.job obj.quality = 6 obj.star = monsterConfig.star obj.head = monsterConfig.head obj.body = monsterConfig.body obj.camp = monsterConfig.camp obj.sex = monsterConfig.sex BeSkill.initBeSkill(obj) BeSkill.setBeSkill(obj, monsterConfig, nil, monsterOutConfig) Skill.setSkill(obj, monsterConfig) obj.attrs = RoleAttr.calcMonsterConf(id, attrID, attrInput) return obj end -- 根据英雄ID信息创建临时对象 function createHeroObjByID(heroId, lv, star, quality, index) local heroConfig = HeroExcel.hero[heroId] if not heroConfig then return end local obj = {} obj.type = CombatDefine.COMBAT_OBJ_TYPE1 obj.bagIndex = index obj.id = heroId obj.lv = lv obj.job = heroConfig.job obj.quality = quality and quality or HeroGrid.getMaxQuality(star) obj.star = star obj.body = heroConfig.body obj.head = heroConfig.head local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star) BeSkill.initBeSkill(obj) Skill.setSkill(obj, attrConfig) BeSkill.setBeSkill(obj, attrConfig) obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, index)) obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI] return obj end -- 根据英雄表信息创建临时对象 function createHeroObj(human, heroId, lv, star, index,skin) local heroConfig = HeroExcel.hero[heroId] local skinCfg = skin and SkinExcel.skin[skin] if not heroConfig then return end local obj = {} obj.type = CombatDefine.COMBAT_OBJ_TYPE1 obj.bagIndex = index obj.id = heroId obj.lv = lv obj.job = heroConfig.job obj.quality = HeroGrid.getMaxQuality(star) obj.star = star obj.body = skinCfg and skinCfg.body --or heroConfig.body obj.head = skinCfg and skinCfg.head --or heroConfig.head if not obj.body or obj.body == 0 then obj.body = heroConfig.body end if not obj.head or obj.head == 0 then obj.head = heroConfig.head end local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star) BeSkill.initBeSkill(obj) if not SkinLogic.setSkill(human,index,attrConfig,obj) then Skill.setSkill(obj, attrConfig) BeSkill.setBeSkill(obj, attrConfig) end obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, index, human)) obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI] return obj end function createHeroObjByHeroGrid(human, heroGrid) local heroConfig = HeroExcel.hero[heroGrid.id] if not heroConfig then return end local obj = {} obj.type = CombatDefine.COMBAT_OBJ_TYPE1 obj.bagIndex = heroGrid.bagIndex obj.uuid = heroGrid.uuid obj.id = heroGrid.id obj.lv = heroGrid.lv obj.job = heroConfig.job obj.quality = heroGrid.quality obj.star = heroGrid.star -- dxzeng 取db star obj.fuwen = Util.copyTable(heroGrid.fuwen) obj.bingshu = Util.copyTable(heroGrid.bingshu) obj.body, obj.head = SkinLogic.getBody(human, obj.bagIndex) obj.camp = heroConfig.camp obj.isGongMing = XingYaoGongMing.isGongMing(human, heroGrid.bagIndex) obj.sex = heroConfig.sex local attrConfig = HeroDefine.getAttrConfig(obj.id, obj.star) BeSkill.initBeSkill(obj) if not SkinLogic.setSkill(human,obj.bagIndex,attrConfig,obj) then Skill.setSkill(obj, attrConfig) BeSkill.setBeSkill(obj, attrConfig) end if heroGrid.isLostTemple then obj.attrs = Util.copyTable(LostTempleCombatLogic.getHeroAttrs(human, heroGrid.bagIndex)) else obj.attrs = Util.copyTable(ObjHuman.getHeroAttrs(human, obj.bagIndex)) --obj.attrs = Util.copyTable(RoleAttr.calcHeroGrid(obj, obj.bagIndex, human)) end obj.zhandouli = obj.attrs[RoleDefine.ZHANDOULI] return obj end -- 根据英雄背包创建临时对象 function createHumanObj(human, uuid) if not uuid then return end local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid) if not heroGrid or type(heroGrid) ~= "table" then return end return createHeroObjByHeroGrid(human, heroGrid) end -- 根据怪物组id获取出战英雄列表 function getMonsterObjList(monsterOutID, objType, args) if not monsterOutID then return end local monsterOutConfig = MonsterExcel.monsterOut[monsterOutID] if not monsterOutConfig then return end local formation = monsterOutConfig.formation if formation == 0 then formation = 1 end local mationConfig = CombatPosExcel.formation[formation] local posList = mationConfig.pos if not posList then return end local objList = nil local zhandouli = 0 for i, member in ipairs(monsterOutConfig.member) do local monsterID = member[1] local monsterConfig = MonsterExcel.monster[monsterID] if posList[i] then local monsterLv = member[2] local attrID = monsterOutConfig.attrID[i] local attrInput = nil if monsterOutConfig.combatType == CombatDefine.COMBAT_TYPE5 then if args then local throneID = args[1] local evolveCnt = args[2] monsterLv, attrInput = TheStarsLogic.getMonsterLvAttr(i, throneID, evolveCnt) end end local obj = createMonsterObj(monsterID, monsterLv, attrID, i, objType, monsterOutConfig.beSkill[i], attrInput) if obj then zhandouli = zhandouli + obj.attrs[RoleDefine.ZHANDOULI] objList = objList or {} local pos = posList[i] if monsterOutConfig.combatType == CombatDefine.COMBAT_TYPE10 then pos = 5 end objList[pos] = obj end end end if not objList then assert(nil, "getMonsterObjList is nil, monsterOutID = " .. monsterOutID) end local rolebase = createRoleBaseByMOutID(monsterOutID, zhandouli, args) local jiban = nil -- todo 怪物的羁绊 return objList, nil, rolebase,formation,jiban end -- 获取human出战英雄列表 objList, helpList, rolebase, formation function getHumanObjList(human, combatType) local teamType = CombatPosLogic.getTeamType(combatType) if not teamType then return end local combatHero, _, formation,combatHeroDB = CombatPosLogic.getCombatHeros(human, combatType) if not combatHero then return end if formation == 0 then formation = 1 end local jiban = JibanLogic.getJibanHero(human,combatHeroDB) local objList = {} local zhandouli = 0 for i = 1, CombatDefine.COMBAT_HERO_CNT do local uuid = combatHero[i] local obj = createHumanObj(human, uuid) if obj then zhandouli = zhandouli + obj.attrs[RoleDefine.ZHANDOULI] objList[i] = obj end end local helpList = {} local pet = MoshouLogic.createCombatMoshow(human,combatType) helpList[CombatDefine.HELP_TYPE1] = pet local rolebase = createRoleBaseByDB(human.db, zhandouli) return objList, helpList, rolebase,formation,jiban end ---------------------------------------------- msg ----------------------------------------------- -- 封装对战英雄信息 local function fontCombatHeroNet(net, obj) local config = getConfigByObj(obj) if not config then return end net.pos = obj.pos net.heroID = obj.id net.star = obj.star net.lv = obj.lv or 0 net.body = obj.body or config.body if obj.body and config.body then if obj.body ~= config.body then local tSkinCof = SkinExcel.skin[obj.body] if tSkinCof and tSkinCof.heroId ~= net.heroID then net.body = config.body print("[fontCombatHeroNet] 下发时修改英雄的身体数据 heroID = "..net.heroID .." body1 = "..obj.body.." conBody = "..config.body) end end end net.hpMax = obj.hpMax --CombatObj.getHpMax(obj) net.hpNow = obj.initHp net.icon = config.head net.width = config.width net.height = config.height net.camp = config.camp net.name = config.name net.posX = CombatDefine.DEFAULT_POS_SIZE[obj.pos][1] net.posY = CombatDefine.DEFAULT_POS_SIZE[obj.pos][2] net.size = CombatDefine.DEFAULT_POS_SIZE[obj.pos][3] net.isBoss = config.isboss or 0 net.isGongMing = obj.isGongMing or 0 net.grade = config.grade or 0 local len = 0 for _,v in pairs(obj.skillList) do if SkillExcel.skill[v[1]].contentType == 3 then len = len + 1 net.sayList[len] = v[1] end end for _,v in pairs(obj.beSkillList) do for _,v1 in ipairs(v) do if SkillExcel.skill[v1[1]].contentType == 3 then len = len + 1 net.sayList[len] = v1[1] end end end net.sayList[0] = len return true end -- 封装辅助对象 function fontCombatHelpNet(net, help) net.pos = help.pos net.id = help.id or 0 net.head = help.head or 0 net.body = help.body or 0 net.skill[0] = 0 local skillConfig = SkillExcel.skill[help.icon] if skillConfig then net.skill[1].id = help.icon net.skill[1].icon = skillConfig.icon net.skill[1].name = skillConfig.name net.skill[1].desc = skillConfig.desc net.skill[1].lv = help.skillLV or 0 net.skill[1].index = 0 net.skill[1].state = 2 net.skill[0] = 1 end net.args[0] = 0 if help.clientArgs then local len = 0 for k,v in ipairs(help.clientArgs) do len = len + 1 net.args[len] = v end net.args[0] = len end return true end -- 封装战斗技能信息 function fontCombatSkillNet(skillNet, skillID) local skillConfig = SkillExcel.skill[skillID] if not skillConfig then return end skillNet.skillID = skillID skillNet.fireType = skillConfig.fireType skillNet.readyAction = skillConfig.readyAction skillNet.attackPart = skillConfig.attackPart skillNet.attackAction = skillConfig.attackAction skillNet.readyEffect = skillConfig.readyEffect skillNet.attackEffect = skillConfig.attackEffect skillNet.hitEffect = skillConfig.hitEffect skillNet.flyEffect = skillConfig.flyEffect skillNet.flyCoords = skillConfig.flyCoords skillNet.hitBack = skillConfig.hitBack skillNet.effectTime = skillConfig.effectTime skillNet.contentType = skillConfig.contentType skillNet.content = skillConfig.content skillNet.movieEffect = skillConfig.movieEffect skillNet.quake = skillConfig.quake skillNet.flySound = skillConfig.flySound skillNet.fireSound = skillConfig.fireSound skillNet.hitSound = skillConfig.hitSound skillNet.cvSound = skillConfig.cvSound skillNet.screenMask = skillConfig.screenMask skillNet.screenCam = skillConfig.screenCam skillNet.largeEffect = skillConfig.largeEffect skillNet.lie = skillConfig.lie skillNet.cuoZhen = skillConfig.cuoZhen skillNet.skillDelay = skillConfig.skillDelay skillNet.isFraming = skillConfig.isFraming return true end -- 封装技能cmd local function fontSkillCmd(cmdNet, cmd) local cmdConfig = SkillExcel.cmd[cmd] if not cmdConfig then return end cmdNet.cmd = cmd cmdNet.hitEffect = cmdConfig.hitEffect cmdNet.hitSound = cmdConfig.hitSound return true end -- 封装buff local function fontBufferNet(bufferNet, bufferID) local bufferConf = BufferExcel.buffer[bufferID] if not bufferConf then return end bufferNet.bufferID = bufferID bufferNet.name = bufferConf.name bufferNet.desc = bufferConf.desc bufferNet.icon = bufferConf.icon bufferNet.keepEffect = bufferConf.keepEffect bufferNet.hitEffect = bufferConf.hitEffect bufferNet.validateEffect = bufferConf.validateEffect bufferNet.dieEffect = bufferConf.dieEffect bufferNet.cmd = bufferConf.cmd bufferNet.hitSound = bufferConf.hitSound bufferNet.holdOnDie = bufferConf.holdOnDie bufferNet.effectOffset = bufferConf.effectOffset bufferNet.canAppend = bufferConf.canAppend bufferNet.appendCnt = bufferConf.appendCnt return true end -- 封装阵法属性 local function fontCombatPosAttr(attrNets, attrs) attrNets[0] = 0 if type(attrs) ~= "table" then return end for key, value in pairs(attrs) do attrNets[0] = attrNets[0] + 1 local attrNet = attrNets[attrNets[0]] attrNet.key = key attrNet.value = value end end -- 发送战斗开始 local function sendCombatBegin(human, combatInfo, isLogin) combatInfo = combatInfo or human.combat if not combatInfo then return end local msgRet = Msg.gc.GC_COMBAT_BEGIN msgRet.isLogin = isLogin == true and 1 or 0 msgRet.combatType = combatInfo.type local keepTime = os.time() - combatInfo.time if combatInfo.passTime < keepTime then combatInfo.passTime = keepTime end msgRet.keepTime = combatInfo.passTime if combatInfo.isVideo then -- 录像回放 msgRet.keepTime = 0 end local isCanQuick = getQuick(human, combatInfo.type) msgRet.isQuick = isCanQuick or 0 msgRet.isVideo = combatInfo.isVideo == true and 1 or 0 msgRet.mapID = combatInfo.mapID msgRet.speed = human.db and human.db.combatSpeed or 1 msgRet.atkName = combatInfo.attacker and combatInfo.attacker.name or "" msgRet.defName = combatInfo.defender and combatInfo.defender.name or "" msgRet.atkUuid = combatInfo.attacker and combatInfo.attacker.uuid or "" msgRet.defUuid = combatInfo.defender and combatInfo.defender.uuid or "" msgRet.maxRound = combatInfo.maxRound msgRet.petCD = CombatDefine.PET_CD msgRet.heros[0] = 0 msgRet.atkFormation = combatInfo.atkFormation msgRet.defFormation = combatInfo.defFormation msgRet.backup[0] = 2 for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do local obj = combatInfo.objList[i] if fontCombatHeroNet(msgRet.heros[msgRet.heros[0] + 1], obj) then msgRet.heros[0] = msgRet.heros[0] + 1 end if i % CombatDefine.COMBAT_HERO_CNT == 0 then msgRet.backup[i/CombatDefine.COMBAT_HERO_CNT] = obj and obj.backupPos or 0 end end msgRet.helps[0] = 0 for _, help in pairs(combatInfo.helpList) do if fontCombatHelpNet(msgRet.helps[msgRet.helps[0] + 1], help) then msgRet.helps[0] = msgRet.helps[0] + 1 end end msgRet.skillList[0] = 0 for skillID in pairs(combatInfo.skillUseList) do if fontCombatSkillNet(msgRet.skillList[msgRet.skillList[0] + 1], skillID) then msgRet.skillList[0] = msgRet.skillList[0] + 1 end end msgRet.cmdList[0] = 0 if combatInfo.cmdUseList then for cmd in pairs(combatInfo.cmdUseList) do if fontSkillCmd(msgRet.cmdList[msgRet.cmdList[0] + 1], cmd) then msgRet.cmdList[0] = msgRet.cmdList[0] + 1 end end end msgRet.bufferList[0] = 0 for bufferID in pairs(combatInfo.bufferUseList) do if fontBufferNet(msgRet.bufferList[msgRet.bufferList[0] + 1], bufferID) then msgRet.bufferList[0] = msgRet.bufferList[0] + 1 end end fontCombatPosAttr(msgRet.attrsAtk, combatInfo.posAttr[1]) fontCombatPosAttr(msgRet.attrsDef, combatInfo.posAttr[2]) msgRet.atkJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.ATTACK_SIDE]) msgRet.defJibanDesc = JibanLogic.getDesc(combatInfo.jiban[CombatDefine.DEFEND_SIDE]) Msg.send(msgRet, human.fd) end -- 封装战斗帧技能信息 local function fontFrameSkillNet(skillNet, skillData) skillNet.attackPos = skillData.attackPos skillNet.skillID = skillData.skillID skillNet.hitList[0] = 0 for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do local skillHitData = skillData.hitList[i] if skillHitData then skillNet.hitList[0] = skillNet.hitList[0] + 1 local skillHitNet = skillNet.hitList[skillNet.hitList[0]] skillHitNet.pos = i skillHitNet.flag = skillHitData.flag skillHitNet.cmd = 0 skillHitNet.hpNow = skillHitData.hpNow local frameAttrs = skillHitData.attrs skillHitNet.attrs[0] = frameAttrs and #frameAttrs or 0 for j = 1, #frameAttrs do skillHitNet.attrs[j].key = frameAttrs[j][1] skillHitNet.attrs[j].value = frameAttrs[j][2] end end end skillNet.helpList[0] = 0 --for i = CombatDefine.PET_POS_ATTACK, CombatDefine.PET_POS_DEFEND do -- local helpHitData = skillData.helpList and skillData.helpList[i] -- if helpHitData then -- skillNet.helpList[0] = skillNet.helpList[0] + 1 -- local helpHitNet = skillNet.helpList[skillNet.helpList[0]] -- helpHitNet.pos = i -- end --end skillNet.extraList[0] = 0 for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do local extraHitData = skillData.extraList[i] if extraHitData then skillNet.extraList[0] = skillNet.extraList[0] + 1 local extraHitNet = skillNet.extraList[skillNet.extraList[0]] extraHitNet.pos = i extraHitNet.flag = extraHitData.flag extraHitNet.cmd = extraHitData.cmd extraHitNet.hpNow = extraHitData.hpNow local frameAttrs = extraHitData.attrs local attrsLen = math.min(frameAttrs and #frameAttrs or 0, #extraHitNet.attrs) extraHitNet.attrs[0] = attrsLen for j = 1, attrsLen do extraHitNet.attrs[j].key = frameAttrs[j][1] extraHitNet.attrs[j].value = frameAttrs[j][2] end end end end -- 封装战斗帧buff信息 local function fontFrameBuff(net, buffers) net[0] = #buffers for i = 1, net[0] do local bufferNet = net[i] local bufferData = buffers[i] bufferNet.bufferID = bufferData.id bufferNet.op = bufferData.op bufferNet.cnt = bufferData.cnt bufferNet.round = bufferData.round or -1 bufferNet.hpNow = bufferData.hpNow bufferNet.attrs[0] = bufferData.attrs and #bufferData.attrs or 0 for j = 1, bufferNet.attrs[0] do bufferNet.attrs[j].key = bufferData.attrs[j][1] bufferNet.attrs[j].value = bufferData.attrs[j][2] end end end -- 封装战斗帧 local function fontFrameNet(net, frame) net.round = frame.round net.petCD = frame.petCD net.skillList[0] = #frame.skillList for i = 1, net.skillList[0] do local skillNet = net.skillList[i] local skillData = frame.skillList[i] fontFrameSkillNet(skillNet, skillData) end net.bufferList[0] = 0 for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do local bufferData = frame.bufferList[i] if bufferData then net.bufferList[0] = net.bufferList[0] + 1 local bufferNet = net.bufferList[net.bufferList[0]] bufferNet.pos = i fontFrameBuff(bufferNet.list, bufferData) end end net.sayList[0] = 0 for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do if frame.sayList[i] then for _,saySkillID in ipairs(frame.sayList[i]) do net.sayList[0] = net.sayList[0] + 1 local sayNet = net.sayList[net.sayList[0]] sayNet.pos = i sayNet.skillID = saySkillID end end end return net.skillList[0] > 0 or net.bufferList[0] > 0 or net.sayList[0] > 0 end -- 发送战斗帧 local function sendCombatFrame(human, combatInfo, isLogin) combatInfo = combatInfo or human.combat if not combatInfo then return end local result = combatInfo.result local msgFrame = Msg.gc.GC_COMBAT_FRAME msgFrame.isLogin = isLogin == true and 1 or 0 msgFrame.isEnd = 0 msgFrame.combatType = combatInfo.type msgFrame.frames[0] = 0 local frameCnt = result.frames and #result.frames or 0 local len = 1 for i = 1, frameCnt do local frame = result.frames[i] msgFrame.frames[0] = len local frameNet = msgFrame.frames[msgFrame.frames[0]] if fontFrameNet(frameNet, frame) then if len >= CombatDefine.COMBAT_FRAME_MAXCNT then msgFrame.isEnd = (i == frameCnt) and 1 or 0 Msg.send(msgFrame, human.fd) msgFrame.frames[0] = 0 len = 1 else len = len + 1 end end end if msgFrame.isEnd == 0 or msgFrame.frames[0] > 0 then msgFrame.isEnd = 1 Msg.send(msgFrame, human.fd) end end -- 发送战斗开始 function sendCombatData(human, combatInfo, isLogin) sendCombatBegin(human, combatInfo, isLogin) sendCombatFrame(human, combatInfo, isLogin) end -- 封装战斗统计 function fontFinishResultNet(net, obj) net.pos = obj.pos net.hurt = obj.result[1] net.hp = obj.result[2] net.beHurt = obj.result[3] net.bout = obj.result[4] net.isDie = obj.hp == 0 and 1 or 0 net.heroID = obj.id or 0 net.head = obj.head or 0 net.lv = obj.lv or 0 net.star = obj.star or 0 local heroConfig = HeroExcel.hero[net.heroID] local monsterConfig = MonsterExcel.monster[net.heroID] if obj.type == CombatDefine.COMBAT_OBJ_TYPE1 then net.name = heroConfig and heroConfig.name or "" net.body = heroConfig and heroConfig.body.."" or "" net.head = heroConfig and heroConfig.head or 0 net.grade = heroConfig and heroConfig.grade or 0 else net.name = monsterConfig and monsterConfig.name or "" net.body = monsterConfig and monsterConfig.body.."" or "" net.head = monsterConfig and monsterConfig.head or 0 net.grade = monsterConfig and monsterConfig.grade or 0 end net.camp = heroConfig and heroConfig.camp or 0 end -- 封装战斗结束魔兽信息 local function fontFinishPetNet(net, pet) net.pos = pet.pos net.side = pet.side net.lv = pet.lv or 0 net.head = pet.head end function fontCombatFinish(dataNet, combatInfo, isQuick) if not combatInfo then return end local combatConfig = CombatExcel.combat[combatInfo.type] if not combatConfig then return end dataNet.nBattleType = 0 dataNet.ret = combatInfo.isWin and 1 or 2 dataNet.type = combatInfo.type dataNet.param = combatInfo.endParam or "0" dataNet.isVideo = (combatInfo.isVideo == true) and 1 or 0 dataNet.lookType = combatInfo.lookType or 0 dataNet.isQuick = isQuick or 0 dataNet.combatTime = getCombatUseTime(combatInfo) dataNet.double = combatInfo.double or 0 dataNet.oldLv = combatInfo.attacker.oldLv or 0 dataNet.panelIDs[0] = #combatConfig.panelIDs for i, panelID in ipairs(combatConfig.panelIDs) do dataNet.panelIDs[i] = tonumber(panelID) end if combatInfo.panelID then dataNet.panelIDs[0] = dataNet.panelIDs[0] + 1 dataNet.panelIDs[dataNet.panelIDs[0]] = tonumber(combatInfo.panelID) end -- 攻守方基本信息 RoleLogic.makeRoleBase(combatInfo.defender, dataNet.target) RoleLogic.makeRoleBase(combatInfo.attacker, dataNet.self) -- 每个出战单位的战斗统计 dataNet.result[0] = 0 for pos = 1, CombatDefine.COMBAT_HERO_ALL_CNT do local obj = combatInfo.objList and combatInfo.objList[pos] if obj then dataNet.result[0] = dataNet.result[0] + 1 local net = dataNet.result[dataNet.result[0]] fontFinishResultNet(net, obj) end end -- 出战魔兽 for _,pos in ipairs(CombatDefine.SIDE2HELPPOS[0]) do local pet = combatInfo.helpList and combatInfo.helpList[pos] if pet and pet.isPet then dataNet.result[0] = dataNet.result[0] + 1 local net = dataNet.result[dataNet.result[0]] fontFinishResultNet(net, pet) end end -- 奖励 local rewardItem = combatInfo.rewardItem local len = 0 for k, v in pairs(rewardItem) do if not ItemDefine.isEquip(v[1]) then len = len + 1 Grid.makeItem(dataNet.items[len], v[1], v[2]) end end dataNet.items[0] = EquipLogic.makeEquipItem(combatInfo, dataNet.items, len) return true end -- 发送战斗结束 function sendCombatFinish(human, combatInfo) local msgRet = Msg.gc.GC_COMBAT_FINISH msgRet.data.nBattleType = 0 local dataNet = msgRet.data local isQuick = human.db.combatQuick[combatInfo.type] or 0 if not fontCombatFinish(dataNet, combatInfo, isQuick) then return end BeginStory.handleBattleFail(human, combatInfo.isWin, combatInfo.type, combatInfo.isVideo, msgRet) BeginStory.handleBattle8End(human, combatInfo.isWin, combatInfo.isVideo, combatInfo.type, msgRet) BeginStory.handleBattle12End(human, combatInfo.isWin, combatInfo.isVideo, combatInfo.type, msgRet) if CombatDefine.COMBAT_TYPE1 == combatInfo.type then msgRet.data.nBattleType = human.db.battleType if true == combatInfo.isWin and BattleLogic.BattleLogic_IsLastLevels(human, human.db.battleType) then msgRet.data.param = "0|0|0" end end Msg.send(msgRet,human.fd) end ---------------------------------------- 下面是战斗各种设置逻辑 ------------------------------------------------ local function getMonsterBossName(param) local monsterOutID = param.monsterOutID local posList = param.posList for i,member in ipairs(MonsterExcel.monsterOut[monsterOutID].member) do local monsterID = member[1] local monsterConfig = MonsterExcel.monster[monsterID] if monsterConfig and posList[monsterID] ~= nil then return monsterConfig.name end end end -- 在各种战前加成后,重新设置血量 function recalcHpFightBegin(human, combatType, cbParam) for i = 1,CombatDefine.COMBAT_HERO_CNT do local atkPos = getPos(CombatDefine.ATTACK_SIDE, i) local atkObj = CombatImpl.objList[atkPos] if atkObj then if atkObj.isSysAttrChange then CombatObj.calcAttr(atkObj) -- 重新计算血量 if combatType == CombatDefine.COMBAT_TYPE9 then DrillLogic.calcAttrAtk(human, i, atkObj, cbParam) elseif combatType == CombatDefine.COMBAT_TYPE17 then ValleyLogic.calcAttr(CombatDefine.ATTACK_SIDE, i, atkObj, cbParam) elseif combatType == CombatDefine.COMBAT_TYPE8 then LianyuLogic.recalcHpFightBegin(human, i, atkObj) end end atkObj.hpMax = CombatObj.getHpMax(atkObj) atkObj.hp = atkObj.hp or CombatObj.getHpMax(atkObj) atkObj.mp = atkObj.mp or atkObj.attr[RoleDefine.INIT_MP] atkObj.initHp = atkObj.hp atkObj.initMp = atkObj.mp end local defPos = getPos(CombatDefine.DEFEND_SIDE, i) local defObj = CombatImpl.objList[defPos] if defObj then if defObj.isSysAttrChange then CombatObj.calcAttr(defObj) if combatType == CombatDefine.COMBAT_TYPE9 then DrillLogic.calcAttrDef(human, i, defObj, cbParam) elseif combatType == CombatDefine.COMBAT_TYPE17 then ValleyLogic.calcAttr(CombatDefine.DEFEND_SIDE, i, defObj, cbParam) end end defObj.hpMax = CombatObj.getHpMax(defObj) defObj.hp = defObj.hp or CombatObj.getHpMax(defObj) defObj.mp = defObj.mp or defObj.attr[RoleDefine.INIT_MP] defObj.initHp = defObj.hp defObj.initMp = defObj.mp end end end --战前加属性(包括各系统,被动技能,阵营光环) function onFightBegin(human, combatType, cbParam, param) local moduleFn = getModule(combatType) if moduleFn and moduleFn.onFightBegin then moduleFn.onFightBegin(human, cbParam, combatType, param) end BeSkill.onFightBegin(human) SkinLogic.onFightBegin(human) -- 处理皮肤属性 CombatPosLogic.onFightBegin(human) recalcHpFightBegin(human, combatType, cbParam) end function getHumanHeroList(human,combatType, cbParam) return getHumanObjList(human, combatType) end -- 设置英雄出战 local function setCombatInfo(formation,objList, side) for index = 1, CombatDefine.COMBAT_HERO_CNT do local obj = objList[index] if obj then -- 出战英雄站位 if CombatPosLogic.checkPos(formation,index, side) then local pos = CombatDefine.SIDE2POS[side][index] CombatImpl.setData(pos, obj) end end end end -- 设置辅助对象出战 local function setHelp(helpList, side) if not helpList then return end for k,v in pairs(helpList) do if k == CombatDefine.HELP_TYPE1 then CombatPetCalc.calcGrowArgs(v) CombatPetCalc.clacBuffArgs(v) end CombatImpl.setHelp(side,k,v) end end -- 初始combatInfo local function initCombatInfo(human, combatType, mapID) local combatInfo = {} combatInfo.time = os.time() -- 战斗时间 combatInfo.passTime = 0 -- 客户端经过的时间 combatInfo.type = combatType -- 战斗类型 combatInfo.mapID = mapID -- 地图 combatInfo.posAttr = {} -- 阵法属性 combatInfo.jiban = {} -- 阵法属性 combatInfo.attacker = nil -- 攻方基础角色信息 roleBase combatInfo.defender = nil -- 守方基础角色信息 roleBase combatInfo.atkJiban = nil -- 攻方羁绊英雄 combatInfo.defJiban = nil -- 守方羁绊英雄 combatInfo.isWin = nil -- 战斗结果 combatInfo.result = nil -- 战斗帧 combatInfo.skillUseList = nil -- 战斗技能 combatInfo.cmdUseList = nil -- 战斗技能命令 combatInfo.bufferUseList = nil -- 战斗buff combatInfo.objList = nil -- 战斗英雄列表 combatInfo.helpList = nil -- 战斗魔兽列表 combatInfo.rewardItem = {} -- 奖励 combatInfo.endParam = nil -- 额外参数 combatInfo.isVideo = nil -- 是否录像 combatInfo.videoUuid = nil -- 录像uuid combatInfo.panelID = nil -- 返回界面(特殊) combatInfo.maxRound = nil -- 最大会合数 combatInfo.fightMode = nil -- 战斗模式 human.combat = combatInfo return combatInfo end -- 为了战斗回放,某些数据需要保存 local function copyToCombatInfo(combatInfo) combatInfo.isWin = CombatImpl.result.isWin combatInfo.result = Util.copyTable(CombatImpl.result) combatInfo.result.round = CombatImpl.round combatInfo.skillUseList = Util.copyTable(CombatImpl.skillUseList) combatInfo.cmdUseList = Util.copyTable(CombatImpl.cmdUseList) combatInfo.bufferUseList = Util.copyTable(CombatImpl.bufferUseList) combatInfo.objList = Util.copyTable(CombatImpl.objList) combatInfo.helpList = Util.copyTable(CombatImpl.helpList) combatInfo.totalAtkCnt = CombatImpl.totalAtkCnt end function setSkillAndBeskill(human,combatInfo) local combatType = combatInfo.type local moduleFn = getModule(combatType) if moduleFn and moduleFn.setSkillAndBeskill then moduleFn.setSkillAndBeskill(human,combatInfo) end end function combatBegin(human, mapID, param, combatType, cbParam, isSaodang) if COMBAT_CACHE[human.db._id] and COMBAT_CACHE[human.db._id][combatType] then --assert(nil, "has combat cache "..combatType .. " " .. human.db.account) -- reyes test human.combat = COMBAT_CACHE[human.db._id][combatType].combatInfo sendCombatData(human, human.combat) return end -- 获得地图ID CombatImpl.init(combatType) mapID = getMapID(human, combatType, param) local defender, defHelp, defRBase,defFormation,defJiban = getCombatObjList(human, CombatDefine.DEFEND_SIDE, combatType, param) local attacker, atkHelp, atkRBase, atkFormation,atkJiban if defender then attacker, atkHelp, atkRBase, atkFormation,atkJiban = getCombatObjList(human, CombatDefine.ATTACK_SIDE, combatType, param) end if not (attacker and next(attacker)) then return end if not defender then return end local combatInfo = initCombatInfo(human, combatType, mapID) combatInfo.attacker = atkRBase or {} combatInfo.atkHelp = atkHelp or {} combatInfo.atkFormation = atkFormation combatInfo.atkJiban = atkJiban combatInfo.defender = defRBase or {} combatInfo.defHelp = defHelp or {} combatInfo.defFormation = defFormation combatInfo.defJiban = defJiban combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker) combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender) combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker,atkJiban) combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender,defJiban) combatInfo.maxRound = getMaxRound(human,combatType) combatInfo.fightMode = getFightMode(combatType) --战役第五关特殊处理 BeginStory.handleBattle5(human, combatType, defender) JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE]) JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE]) local changePos = nil if combatType == CombatDefine.COMBAT_TYPE10 then for k,v in pairs(attacker) do changePos = k attacker[k] = nil attacker[5] = v break end end setCombatInfo(atkFormation, attacker, CombatDefine.ATTACK_SIDE) setCombatInfo(defFormation, defender, CombatDefine.DEFEND_SIDE) setHelp(atkHelp, CombatDefine.ATTACK_SIDE) setHelp(defHelp, CombatDefine.DEFEND_SIDE) CombatImpl.setMaxRound(combatInfo.maxRound) CombatImpl.setFightMode(combatInfo.fightMode) --需要对技能特殊处理的(比如不重置cd) setSkillAndBeskill(human,combatInfo) -- 战前属性/血量重算 local tempParam = cbParam if combatType == CombatDefine.COMBAT_TYPE10 then tempParam = {} tempParam.cbParam = cbParam tempParam.changePos = changePos end onFightBegin(human, combatType, tempParam, param) makeAttrLogStr(human) while CombatImpl.calcFrame() do end copyToCombatInfo(combatInfo) combatInfo.changePos = changePos local result = combatInfo.isWin and CombatDefine.RESULT_WIN or CombatDefine.RESULT_FAIL local isQuick = human.db.combatQuick[combatType] == 1-- 是否跳过战斗 if isSaodang or isQuick then -- 扫荡/跳过战斗需要立刻出结果 onFightEnd(human, result, combatType, cbParam, combatInfo, param, isSaodang) sendCombatFinish(human, combatInfo) else -- 发送战斗开始+战斗帧 sendCombatData(human, combatInfo) addCombatCache(human.db._id, combatInfo, cbParam,param) end makeLogStr(human) -- 写战斗日志 end function getCombatUseTime(combatInfo) local combatUseTime = CombatDefine.COMBAT_ATK_TIME * (combatInfo.totalAtkCnt or 0) -- 1.2秒1次行动 combatUseTime = combatUseTime + 10 --带上出场时间 return combatUseTime end function combatGm(human,mapID,atkFormation,attacker,defFormation,defender,atkPet,defPet,rewardItem) local combatType = 0 local config = CombatExcel.combat[combatType] local combatInfo = initCombatInfo(human, combatType, mapID) combatInfo.attacker = {} combatInfo.defender = {} combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker) combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender) combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker) combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender) combatInfo.rewardItem = rewardItem or combatInfo.rewardItem combatInfo.atkFormation = atkFormation combatInfo.defFormation = defFormation combatInfo.fightMode = config.fightMode CombatImpl.init(combatType) setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE) setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE) setHelp({atkPet}, CombatDefine.ATTACK_SIDE) setHelp({defPet}, CombatDefine.DEFEND_SIDE) combatInfo.maxRound = getMaxRound(human,combatType) CombatImpl.setMaxRound(combatInfo.maxRound) CombatImpl.setFightMode(combatInfo.fightMode) -- 战前属性/血量重算 onFightBegin(human, combatType, nil, {}, {}) makeAttrLogStr(human) while CombatImpl.calcFrame() do end copyToCombatInfo(combatInfo) sendCombatData(human, combatInfo) -- 方便调试不做缓存 addCombatCache(human.db._id, combatInfo) makeLogStr(human) -- 写战斗日志 end function combatGuide(human, atkFormation,attacker,defFormation,defender,atkPet,defPet) local combatType = CombatDefine.COMBAT_TYPE18 local config = CombatExcel.combat[combatType] local combatInfo = initCombatInfo(human, combatType, config.mapID) combatInfo.attacker = {} combatInfo.defender = {} combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker) combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender) combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker) combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender) combatInfo.rewardItem = rewardItem or combatInfo.rewardItem combatInfo.atkFormation = atkFormation combatInfo.defFormation = defFormation combatInfo.fightMode = config.fightMode CombatImpl.init(combatType) setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE) setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE) setHelp({atkPet}, CombatDefine.ATTACK_SIDE) setHelp({defPet}, CombatDefine.DEFEND_SIDE) combatInfo.maxRound = getMaxRound(human, combatType) CombatImpl.setMaxRound(combatInfo.maxRound) CombatImpl.setFightMode(combatInfo.fightMode) JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE]) JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE]) -- 战前属性/血量重算 onFightBegin(human, combatType, nil, {}, {}) human.combat = combatInfo while CombatImpl.calcFrame() do end copyToCombatInfo(human.combat) end -- function combatVedio(human, atkFormation, attacker,defFormation,defender,atkPet,defPet, fakeHuman) local combatType = CombatDefine.COMBAT_TYPE22 local config = CombatExcel.combat[combatType] local combatInfo = initCombatInfo(human, combatType, config.mapID) combatInfo.attacker = {} combatInfo.defender = {} combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker) combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender) combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker) combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender) combatInfo.rewardItem = rewardItem or combatInfo.rewardItem combatInfo.atkFormation = atkFormation combatInfo.defFormation = defFormation combatInfo.fightMode = config.fightMode CombatImpl.init(combatType) setCombatInfo(atkFormation,attacker, CombatDefine.ATTACK_SIDE) setCombatInfo(defFormation,defender, CombatDefine.DEFEND_SIDE) setHelp({atkPet}, CombatDefine.ATTACK_SIDE) setHelp({defPet}, CombatDefine.DEFEND_SIDE) combatInfo.maxRound = getMaxRound(human, combatType) CombatImpl.setMaxRound(combatInfo.maxRound) CombatImpl.setFightMode(combatInfo.fightMode) JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE]) JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE]) -- 战前属性/血量重算 onFightBegin(human, combatType, nil, {}, {}) human.combat = combatInfo while CombatImpl.calcFrame() do end copyToCombatInfo(human.combat) sendCombatData(fakeHuman, combatInfo) end -- 战斗录像 local VEDIO_COMBAT_INFO = VEDIO_COMBAT_INFO or { db = {} } function combatFightVedio(human, heroID) local heroConfig = HeroExcel.hero[heroID] if not heroConfig then return end local combatConf = CombatExcel.gm[heroConfig.gm] if not combatConf then return end VEDIO_COMBAT_INFO.attacker = {} VEDIO_COMBAT_INFO.defender = {} VEDIO_COMBAT_INFO.atkFormation = combatConf.atkF VEDIO_COMBAT_INFO.defFormation = combatConf.defF local atkConf = nil for i = 1, CombatDefine.COMBAT_HERO_CNT do atkConf = nil for k, v in ipairs(combatConf.atk) do if i == v[2] then atkConf = v break end end if atkConf then VEDIO_COMBAT_INFO.attacker[i] = createHeroObj(VEDIO_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i,atkConf[5]) end atkConf = nil for k, v in ipairs(combatConf.def) do if i == v[2] then atkConf = v break end end if atkConf then VEDIO_COMBAT_INFO.defender[i] = createHeroObj(VEDIO_COMBAT_INFO, atkConf[1], atkConf[3], atkConf[4], i,atkConf[5]) end end combatVedio(VEDIO_COMBAT_INFO, VEDIO_COMBAT_INFO.atkFormation, VEDIO_COMBAT_INFO.attacker, VEDIO_COMBAT_INFO.defFormation, VEDIO_COMBAT_INFO.defender, nil, nil, human) end function repeatCombat(human, combatInfo) if not combatInfo then return end -- if isCombating(human) then -- return Broadcast.sendErr(human, Lang.COMBAT_VIDEO_LOOK_ERR_ING) -- end combatInfo.isVideo = true human.combat = combatInfo sendCombatData(human, combatInfo) sendCombatFinish(human, combatInfo) end -- 初始属性数据写日志 function makeAttrLogStr(human) if not Config.IS_DEBUG then return end local logStr = "\n初始属性数据:\n" for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do data = CombatImpl.objList[i] if data then logStr = logStr .. "\n\t" .. "{pos:"..data.pos.." heroID:"..data.id.."}\n\t" for k,v in pairs(data.attr) do if v ~= 0 then logStr = logStr .."{key:"..k..",value:"..v.."}," end end end end logStr = logStr .."\n" local f = io.open("./log/fight_log.log", "w+") f:write(logStr) assert(io.close(f)) end function makeLogStr(human) if not Config.IS_DEBUG then return end local logStr = "\n战斗开始数据:\n" for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do data = CombatImpl.objList[i] if data then logStr = logStr .. "\t" .. "{pos:"..data.pos.." heroID:"..data.id.."}" end end logStr = logStr .. "\n" logStr = logStr .. "战斗帧数据:\n" local result = CombatImpl.result local frameCnt = result.frames and #result.frames or 0 for i = 1,frameCnt do local data = result.frames[i] logStr = logStr .. "\t" .. i .."帧\n" for j = 1,#data.skillList do local skillData = data.skillList[j] logStr = logStr .. "\t\t技能释放 attackPos:"..skillData.attackPos.." skillID:"..skillData.skillID.."\n" local hitLen = 0 for k = 1,CombatDefine.COMBAT_HERO_ALL_CNT do if skillData.hitList[k] then hitLen = hitLen + 1 local skillHitData = skillData.hitList[k] logStr = logStr .. "\t\t\t技能对象"..hitLen.." pos:"..k.." hpNow:"..skillHitData.hpNow.." attrs:" local frameAttrs = skillHitData.attrs local attrsLen = 0 if frameAttrs then for m = 1,#frameAttrs do logStr = logStr .. " {key:"..frameAttrs[m][1].." value:"..frameAttrs[m][2].."}" end end logStr = logStr .. "\n" end end local extraLen = 0 for k = 1,CombatDefine.COMBAT_HERO_ALL_CNT do if skillData.extraList[k] then extraLen = extraLen + 1 local extraHitData = skillData.extraList[k] logStr = logStr .. "\t\t\t额外作用对象"..extraLen.." pos:"..k.." cmd:"..extraHitData.cmd.." hpNow:"..extraHitData.hpNow.." attrs:" local frameAttrs = extraHitData.attrs if frameAttrs then for m = 1,#frameAttrs do logStr = logStr .. " {key:"..frameAttrs[m][1].." value:"..frameAttrs[m][2].."}" end end logStr = logStr .. "\n" end end end local bufferLen = 0 for j = 1,CombatDefine.COMBAT_HERO_ALL_CNT do if data.bufferList[j] then bufferLen = bufferLen + 1 logStr = logStr .. "\t\tbuffer更新 pos:"..j.."\n" local bufferDataList = data.bufferList[j] for i = 1,#bufferDataList do local bufferData = bufferDataList[i] logStr = logStr .. "\t\t\t bufferID:"..bufferData.id.." op:"..bufferData.op.." cnt:"..bufferData.cnt.." round:"..(bufferData.round or -1).." hpNow:"..bufferData.hpNow.." attrs:" local attrsLen = 0 if bufferData.attrs then for k,v in ipairs(bufferData.attrs) do logStr = logStr .. " {key:"..v[1].." value:"..v[2].."}" end end end logStr = logStr .. "\n" end end end local f = io.open("./log/fight_log.log", "a+") f:write(logStr) assert(io.close(f)) end -- 获取角色上阵的形象 function getRoleBody(human, combatType) local teamType = CombatPosLogic.getTeamType(combatType) local combatHero = teamType and human.db.combatHero[teamType] if not combatHero then return end local zhandouli = 0 local maxGrid = nil for i = 1, CombatDefine.COMBAT_HERO_CNT do local uuid = combatHero.list[i] local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid) if heroGrid and type(heroGrid) == "table" and zhandouli < heroGrid.zhandouli then zhandouli = heroGrid.zhandouli maxGrid = heroGrid end end if not maxGrid then return end return HeroGrid.getHeroBodyById(maxGrid.id) end -- 根据怪物组id获取外显 function getMonsterIDByOutID(monsterOutID, args) local mocf = MonsterExcel.monsterOut[monsterOutID] if not mocf then return end local memberCnt = #mocf.member local index = (monsterOutID % 1000) % memberCnt if index == 0 then index = memberCnt - 1 end local minfo = mocf.member[index] if not minfo then for _, minfo0 in ipairs(mocf.member) do if minfo0[1] > 0 then minfo = minfo0 break end end end if not minfo then return end local monsterID = minfo[1] local monsterLv = minfo[2] local mcf = monsterID and MonsterExcel.monster[monsterID] if not mcf then return end if mocf.combatType == CombatDefine.COMBAT_TYPE5 then if args then local throneID = args[1] local evolveCnt = args[2] monsterLv = TheStarsLogic.getMonsterLvAttr(1, throneID, evolveCnt) end end return monsterID, mcf, monsterLv end -- 根据伤害计算胜负 function calcWinByHurt(combatInfo) if not combatInfo.isWin then return end if not combatInfo.objList then return end local atkHurt = 0 local defHurt = 0 local atkLive = 0 local defLive = 0 for i = 1,CombatDefine.COMBAT_HERO_CNT do local atkPos = getPos(CombatDefine.ATTACK_SIDE, i) local atkObj = combatInfo.objList[atkPos] if atkObj then atkHurt = atkHurt + atkObj.result[1] if atkObj.hp > 0 and not atkLive then atkLive = 1 end end local defPos = getPos(CombatDefine.DEFEND_SIDE, i) local defObj = combatInfo.objList[defPos] if defObj then defHurt = defHurt + defObj.result[1] if atkObj.hp > 0 and not defLive then defLive = 1 end end end if atkLive == 0 then atkHurt = 0 elseif defLive == 0 then defLive = 0 end combatInfo.isWin = atkHurt > defHurt and true or false return combatInfo.isWin end ------------- reyes test --------------------- function isCombating(human) local list = COMBAT_CACHE[human.db._id] if not list then return end for combatType, combatCache in pairs(list) do if not combatCache.combatInfo.isVideo then return true end end end function getCombatCache(uuid, type) return COMBAT_CACHE[uuid] and COMBAT_CACHE[uuid][type] end function addCombatCache(uuid, combatInfo, cbParam,param) COMBAT_CACHE[uuid] = COMBAT_CACHE[uuid] or {} -- reyes test local tempCache = {} local result = combatInfo.isWin and CombatDefine.RESULT_WIN or CombatDefine.RESULT_FAIL tempCache.result = result tempCache.combatType = combatInfo.type tempCache.cbParam = cbParam tempCache.combatInfo = combatInfo tempCache.param = param tempCache.ts = os.time() + getCombatUseTime(combatInfo) COMBAT_CACHE[uuid][combatInfo.type] = tempCache end function cleanCombatCache(uuid, type) if not COMBAT_CACHE[uuid] then return end COMBAT_CACHE[uuid][type] = nil if Util.getTableCount(COMBAT_CACHE[uuid]) == 0 then COMBAT_CACHE[uuid] = nil end end function clientFinish(human, type, noSend) if COMBAT_CACHE[human.db._id] == nil or COMBAT_CACHE[human.db._id][type] == nil then return end local combatCache = COMBAT_CACHE[human.db._id][type] cleanCombatCache(human.db._id, type) --print("onend-=----------------------") if not combatCache.combatInfo.isVideo then onFightEnd(human, combatCache.result, combatCache.combatType, combatCache.cbParam, combatCache.combatInfo,combatCache.param) end -- 绝望深渊 非失败 不发 -- 冰龙 次元魔珠 失落神庙 不走默认结算协议 if type ~= CombatDefine.COMBAT_TYPE8 and type ~= CombatDefine.COMABT_TYPE23 and type ~= CombatDefine.COMBAT_TYPE20 and type ~= CombatDefine.COMBAT_TYPE24 and not noSend then sendCombatFinish(human, combatCache.combatInfo) end end function clientPassTime(human, type, passTime) if COMBAT_CACHE[human.db._id] == nil or COMBAT_CACHE[human.db._id][type] == nil then return end local combatInfo = COMBAT_CACHE[human.db._id][type].combatInfo combatInfo.passTime = passTime end function onLogin(human) checkFinish(human) -- 这里要先check才判断cache 因为check完cache可能就空了 if COMBAT_CACHE[human.db._id] == nil then return end for k, v in pairs(COMBAT_CACHE[human.db._id]) do --assert(nil, "has combat cache "..combatType .. " " .. human.db.account) -- reyes test human.combat = v.combatInfo sendCombatData(human, human.combat, true) end end function checkFinish(human) if COMBAT_CACHE[human.db._id] == nil then return end local now = os.time() for k, v in pairs(COMBAT_CACHE[human.db._id]) do if now >= v.ts then clientFinish(human, k) if COMBAT_CACHE[human.db._id] == nil then return end end end end -- 不管时间立刻结算 目前只有踢人等非正常下线会用到 function forceFinish(human) if COMBAT_CACHE[human.db._id] == nil then return end local now = os.time() for k, v in pairs(COMBAT_CACHE[human.db._id]) do clientFinish(human, k) if COMBAT_CACHE[human.db._id] == nil then return end end end function killFrames(combatInfo) --60帧2倍速情况下大概1分半。限制录像时长再3-5分钟。节省包量 if combatInfo.result.frames and #combatInfo.result.frames > 200 then for i = 201,#combatInfo.result.frames do combatInfo.result.frames[i] = nil end end end