RoleLogic = {} RoleLogic.__index = RoleLogic --local RoleLogic = RoleLogic --local RoleDataName = RoleDataName --local BattleLogic = BattleLogic local Random = Random local floor = math.floor local max = math.max local min = math.min function RoleLogic.New() local instance = {uid=0,roleData=0,data=RoleData.New(),camp=0,name=0,aiIndex=1,position=0,sp=0,spPass=0, shield=BattleList.New(), exCalDmgList=BattleList.New(), proTranList=BattleList.New(), buffFilter=BattleList.New(), Event = BattleEvent:New(),passiveList={},isDead=false,IsDebug=false} setmetatable(instance, RoleLogic) return instance end function RoleLogic:Init(uid, data, position) data.star = data.star or 1 self.uid = uid self.position = position self.roleData = data self.roleId=data.roleId self.data:Init(self, data.property) self.isDead = self:GetRoleData(RoleDataName.Hp) <= 0 self.isRealDead = self.isDead self.killDamage = 0 --致死伤害 self.deadRage = 0 self.teamDamage = data.teamDamage --最高战斗力 self.superSkillDamage = 0 --技能伤害 self.killRole=nil --击杀英雄 self.camp = data.camp --阵营 0:我方 1:敌方 self.name = data.name self.element = data.element self.professionId = data.professionId self.job=data.job self.star = data.star or 1 -- LogError("英雄uid".. self.roleId .." " .. self.star) self.shield:Clear() --护盾列表 self.exCalDmgList:Clear() --额外计算伤害列表 self.buffFilter:Clear() --buff屏蔽列表 self.proTranList:Clear() --属性转换列表 self.isHaveNoDead = false --是否有不灭 self.Event:ClearEvent() self.skill = data.skill if self.skill then self.skill[1] = tonumber(self.skill[1]) else self.skill={} self.skill[1] = 0 end self.superSkill = data.superSkill if self.superSkill then self.superSkill[1] = tonumber(self.superSkill[1]) else self.superSkill={} self.superSkill[1] = 0 end self.superSkill[1] = tonumber(self.superSkill[1]) --首次读条时间=速度/(20*(等级+10) self.sp = 0 local time = self:GetRoleData(RoleDataName.Speed)/(20*(self:GetRoleData(RoleDataName.Level)+10)) self.spPass = floor( BattleUtil.ErrorCorrection(time) * BattleLogic.GameFrameRate) -- 初始化怒气值(默认2) self.Rage = 2 self.RageGrow = 2 -- 普通技能怒气成长 self.SuperSkillRage = 4 -- 技能需要释放的怒气值,默认为4 self.NoRageRate = 0 -- 不消耗怒气值的概率 self.isImmuneReduceRage=false --是否免疫减怒 self.aiOrder = data.ai self.aiIndex = 1 self.aiTempCount = 0 self.RoundMaxSubRage=0 --每回合最多减少怒气 self.AllSubRage =0 -- 每回合减少的怒气 self.IsDebug = false self.enemyType = EnemyType.normal self.lockTarget = nil --嘲讽 self.ctrl_lock = false --是否被嘲讽 self.ctrl_dizzy = false --眩晕 不能释放所有技能 self.ctrl_slient = false --沉默 只能1技能 self.ctrl_palsy = false --麻痹 只能2技能 self.ctrl_noheal = false --禁疗 self.ctrl_blind = false --致盲 self.ctrl_chaos = false --混乱 self.deadFilter = true -- 控制死亡,置为false则角色暂时无法死亡 self.isSuppress = false self.notAction = false --无法行动 self.isExile = false --是否放逐 self.reliveFilter = true -- 控制复活的标志位,置为false角色将不再享受复活效果 self.reliveHPF = 1 self.reliveCaster = nil self.bloodShield = nil self.IsCanAddSkill = true -- 是否可以追加技能 self.mustHit=false --必定命中 self.beMustHit=false --必定被命中 self.mustCrit=false --必定暴击 self.isBanBlood=false --是否禁止上御甲 self.isImmuneAllReduceShield = false --免疫敌方无敌盾(敌方无敌盾对自己无效) self.ignoreShara = false --忽略敌方分摊 self.type = BattleUnitType.Role self.addAttack=0 --添加的攻击 self.isNormalAttackAddRage=true --普攻是否回复怒气 self.curMainTarget=nil --当前主目标 self.isAllBurn = false --是否视敌方全体为燃烧 self.sunTime = 0 --顺风次数 self.sunMaxTime = 0 self.niTime = 0 --逆风次数 self.niMaxTime = 0 self.suppressTime = 0 --被压制的次数 self.passiveList = {} if data.passivity and #data.passivity > 0 then --排序363类型的排在前面 table.sort(data.passivity,function(a,b) if a[3]==b[3] then return a[1] < b[1] else if a[3]==363 then return true end if b[3]==363 then return false end end return a[1] < b[1] end) local coverPass={} for i = 1, #data.passivity do local v = data.passivity[i] local passivityId = tonumber(v[1]) local judge=v[2] local id = tonumber(v[3]) local args = {} for j = 4, #v do args[j-3] = v[j] end --如果时363类型得被动就存起来 if id==363 then if coverPass[args[1]] then table.insert(coverPass[args[1]],args) else coverPass[args[1]]={} table.insert(coverPass[args[1]],args) end else --如果有363修改的被动就修改 if coverPass[passivityId] then local list=coverPass[passivityId] for i = 1, #list do local coverArgs=list[i] local len=floor((#coverArgs-1)/2) for i = 1, len do local id=0 if #coverArgs>i+i then id=coverArgs[i+i] end local value=0 if #coverArgs>=i+i+1 then value=coverArgs[i+i+1] end if id~=0 and #args>=id and args[id] then args[id]=value end end end end end if BattleUtil.Passivity[id] then BattleUtil.Passivity[id](self, args,passivityId,judge) BattleLogManager.Log( "Add Passive", "id", tostring(id), "camp", tostring(self.camp), "pos", tostring(self.position), "passivityId", tostring(passivityId), "judge", tostring(judge) ) -- 加入被动列表 table.insert(self.passiveList, {id, args,passivityId}) end end end -- 初始怒气值放在被动之后计算,使被动对初始怒气的影响生效 self.Rage = self.Rage + self:GetRoleData(RoleDataName.InitRage)-- 当前怒气值 --self.readyAction=data.readAction or (ConfigManager.TryGetConfigData(ConfigName.RoleConfig,self.roleId).ReadyAction or 0) end -- 根据被动id添加被动 function RoleLogic:AddPassiveById(id) local config=ConfigManager.GetConfigData(ConfigName.PassiveSkillLogicConfig,id) if not config then return end local value=config.Value if not value then return end -- 被动生效 BattleUtil.Passivity[config.Type](self,value,id,config.Judge) -- 加入被动列表 table.insert(self.passiveList, {id, value,id,config.judge}) end -- 添加一个被动技能 function RoleLogic:AddPassive(id, args, isRepeat) --判断是否可以叠加 if not isRepeat then -- 不可以叠加, 如果重复则不再加入 for _, pst in ipairs(self.passiveList) do if pst[1] == id then return end end end -- 被动生效 BattleUtil.Passivity[id](self, args) -- 加入被动列表 table.insert(self.passiveList, {id, args}) end -- function RoleLogic:CanCastSkill() return self.sp >= self.spPass and not self.IsDebug end --检测是否有某被动类型 function RoleLogic:CheckHavePassive(id) if self.passiveList then for index, value in ipairs(self.passiveList) do if value and value[1] and value[1]==id then return true end end return false end return false end --检测是否有某被动 function RoleLogic:CheckHavePassiveId(id) if self.passiveList then for index, value in ipairs(self.passiveList) do if value and value[3] and value[3]==id then return true end end return false end return false end -- 废弃的方法 function RoleLogic:GetSkillCD() return max(self.spPass - self.sp, 0) end -- 废弃的方法 function RoleLogic:AddSkillCD(value, type) if value == 0 then --为0直接清CD self.sp = self.spPass return end local cdTotal = self.spPass local delta = 0 if type == 1 then --加算 delta = floor(value * BattleLogic.GameFrameRate) elseif type == 2 then --乘加算(百分比属性加算) delta = floor(value * cdTotal) elseif type == 3 then --减算 delta = -floor(value * BattleLogic.GameFrameRate) elseif type == 4 then --乘减算(百分比属性减算) delta = -floor(value * cdTotal) end if delta > 0 then --加cd加cd最大值 self.spPass = self.spPass + delta else --减cd减cd当前值 delta = -delta self.sp = min(self.sp + delta, self.spPass) end end -- 改变怒气值 function RoleLogic:AddRage(value, type) local delta = 0 if type == 1 then --加算 delta = value elseif type == 2 then --乘加算(百分比属性加算) delta = floor(value * self.SuperSkillRage) elseif type == 3 then --减算 delta = -value elseif type == 4 then --乘减算(百分比属性减算) delta = -floor(value * self.SuperSkillRage) end self.Event:DispatchEvent(BattleEventName.RoleRageChange, delta,self.Rage) --怒气值不可为负值 self.Rage = max(self.Rage + delta, 0) return delta end function RoleLogic:GetRoleData(property) local tarPro = self.data:GetData(property) local item for i=1, self.proTranList.size do item = self.proTranList.buffer[i] if item.proName == property then local value if item.changeType == 1 then --加算 value = item.tranFactor elseif item.changeType == 2 then --乘加算(百分比属性加算) value = BattleUtil.ErrorCorrection(self.data:GetData(item.tranProName) * item.tranFactor) elseif item.changeType == 3 then --减算 value = -item.tranFactor elseif item.changeType == 4 then --乘减算(百分比属性减算) value = -BattleUtil.ErrorCorrection(self.data:GetData(item.tranProName) * item.tranFactor) end tarPro = tarPro + value end end return tarPro end --proA替换的属性,factor系数,proB被替换的属性, duration持续时间 --读取proB属性时,得到的值为proB + proA * factor function RoleLogic:AddPropertyTransfer(proA, factor, proB, ct, duration) local proTran = {proName = proB, tranProName = proA, tranFactor = factor, changeType = ct} self.proTranList:Add(proTran) local index = self.proTranList.size if duration then BattleLogic.WaitForTrigger(duration, function () self:RemovePropertyTransfer(index, proTran) end) end return index, proTran end -- 删除临时属性 function RoleLogic:RemovePropertyTransfer(index, tran) if index <= self.proTranList.size and tran == self.proTranList.buffer[index] then self.proTranList:Remove(index) end end -- 是否为指定id,指定星级的英雄 by:王振兴 2020/07/29 function RoleLogic:IsAssignHeroAndHeroStar(id,star) if self.roleId==id and self.star==star then return true end return false end function RoleLogic:AddBuff(buff,_ignorePro) if self:IsRealDead() then BattleLogic.BuffMgr:PutBuff(buff) return end local isBan=false local function banCallBack(_isBan) isBan=_isBan end BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddBuffCheckBan,banCallBack,self,buff) if isBan then self.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Blood) return end -- buff的miss率 local missF = 0 -- 检测被动对miss概率的影响 local cl = {} local function _CallBack(v, ct) if v then table.insert(cl, {v, ct}) end end BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddBuffMiss, _CallBack, self, buff) missF = BattleUtil.CountChangeList(missF, cl) BattleLogManager.Log( "Add Buff random", "missF", missF) -- 如果概率为0 或者没有miss if missF == 0 or not BattleUtil.RandomAction(missF, function() BattleLogic.BuffMgr:PutBuff(buff) end) then --概率忽略免疫 local ignoreProb=0 if _ignorePro then ignoreProb=_ignorePro end local changeIgnore=function(v1,ct) ignoreProb=BattleUtil.CountValue(ignoreProb,v1,ct) end buff.caster.Event:DispatchEvent(BattleEventName.PassiveChangeIgnoreImmuneValue,changeIgnore,buff) local isIgnor=BattleUtil.RandomAction(ignoreProb,function()end) if not isIgnor then for i=1, self.buffFilter.size do local isImm,immCaster=self.buffFilter.buffer[i](buff,self) if isImm then BattleLogManager.Log( "Buff Filter", "camp", buff.caster.camp, "position", buff.caster.position, "id", buff.id, "type", buff.type) BattleLogic.BuffMgr:PutBuff(buff) self.Event:DispatchEvent(BattleEventName.ShowHintText, BattleArtFontType.Immune) BattleLogic.Event:DispatchEvent(BattleEventName.ImmuneDebuffSuccess,buff,self,immCaster) BattleLogic.Event:DispatchEvent(BattleEventName.RoleAddBuffFail,buff,self) return end end end BattleLogic.BuffMgr:AddBuff(self, buff) BattleLogic.AddRoundTriggerTime() end end function RoleLogic:Dispose() end -- 判断角色是否可以释放技能 function RoleLogic:IsAvailable(skill) if skill and skill.effectCaster then --放技能前判断是否有目标,没有就不会放技能,直接执行技能回调 by 王振兴 2021/09/17 --为解决攻击目标只剩被放逐的单位导致我方不放技能扣除怒气 skill.effectCaster:ChooseTarget() local targets=BattleUtil.LengthOfTable(skill.effectCaster:GetDirectTargetsNoExile()) if targets==0 then return false end end if self.isExile then return false end --角色没有真正死亡 在 被眩晕/沉默的 情况下 任然能释放死亡技能 --(self.ctrl_dizzy or self.ctrl_slient) and if self:IsDead() and skill and skill.type==BattleSkillType.DeadSkill then return true end -- 眩晕 -- 死亡 if self.ctrl_dizzy or self:IsRealDead() then return false end -- 沉默麻痹同时存在 if self.ctrl_palsy and self.ctrl_slient then return false end -- 麻痹同时怒气不足 if self.ctrl_palsy and self.Rage < self.SuperSkillRage then return false end if self.notAction then return false end return true end -- 释放技能 function RoleLogic:SkillCast(skill, func) local _CastDone = function() if func then func() end end -- 角色不可用直接结束技能释放 if not skill or not self:IsAvailable(skill) then self.Event:DispatchEvent(BattleEventName.ActionOperateAngerAfter,self) _CastDone() return end self.Event:DispatchEvent(BattleEventName.ActionOperateAngerBefore,self) -- 没有麻痹,释放普通攻击 if (skill.type == BattleSkillType.Normal or skill.type ==BattleSkillType.ChaosNormal) and not self.ctrl_palsy then local function _CheckRage() -- 后成长怒气 判断普攻是否会回复怒气 if skill.isRage and self.isNormalAttackAddRage then -- 检测被动技能对怒气成长的影响 local grow = self.RageGrow local _RageGrowPassivity = function(finalGrow) grow = finalGrow end self.Event:DispatchEvent(BattleEventName.RoleRageGrow, grow, _RageGrowPassivity) -- self.Rage = self.Rage + grow end -- 释放完成 self.Event:DispatchEvent(BattleEventName.ActionOperateAngerAfter,self) _CastDone() end -- 释放普技 skill:Cast(_CheckRage) -- 没有沉默,释放大技能 elseif (skill.type == BattleSkillType.Special or skill.type==BattleSkillType.Extra or skill.type==BattleSkillType.DeadSkill) and (not self.ctrl_slient or skill.type==BattleSkillType.DeadSkill) then -- 先消耗怒气 if skill.isRage then if self.Rage < self.SuperSkillRage then -- 怒气值不足不能释放技能 self.Event:DispatchEvent(BattleEventName.ActionOperateAngerAfter,self) _CastDone() return end -- 检测被动技能对怒气消耗的影响 local costRage = self.SuperSkillRage local noRageRate = self.NoRageRate local _RageCostPassivity = function(rate, cost) noRageRate = noRageRate + rate costRage = costRage + cost end self.Event:DispatchEvent(BattleEventName.RoleRageCost, costRage, noRageRate, _RageCostPassivity,skill) -- 计算消耗怒气的概率,并消耗怒气 local costRate = 1 - noRageRate costRate = costRate > 1 and 1 or costRate costRate = costRate < 0 and 0 or costRate skill.costRage=0 BattleUtil.RandomAction(costRate, function() self.Rage = self.Rage - costRage self.Event:DispatchEvent(BattleEventName.SkillCastCostRageEnd,costRage) skill.costRage=costRage end) end self.Event:DispatchEvent(BattleEventName.ActionOperateAngerAfter,self) -- 释放绝技 skill:Cast(_CastDone) -- 没有符合条件的技能直接进入下一个技能检测 else self.Event:DispatchEvent(BattleEventName.ActionOperateAngerAfter,self) _CastDone() end end -- 加入一个技能 -- type 加入的技能类型 -- targets 指定目标 -- isAdd 是否是追加技能 -- isRage 是否正常操作怒气值 function RoleLogic:AddSkill(type, isRage, isAdd, targets,isTrigger,isLoop) if not self.IsCanAddSkill and isAdd then return end local effectData = type == BattleSkillType.Normal and self.skill or self.superSkill --角色被混乱后 local isTriggerJudge=true if isTrigger~=nil then isTriggerJudge=isTrigger end if self.ctrl_chaos then type=BattleSkillType.ChaosNormal --混乱普攻使用普攻特效 -- effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4],{100001,{1,1,1}},self.skill[5],self.skill[6]} effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4], self.skill[5] , self.skill[6] ,{200221,{1,1,1}}} isTriggerJudge=false end if self.ctrl_lock then type=BattleSkillType.ChaosNormal --嘲讽普攻使用普攻特效 --effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4],{200221,{1,1,1}},self.skill[5],self.skill[6]} isTriggerJudge=false effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4],self.skill[5] , self.skill[6] ,{200221,{1,1,1}}} end SkillManager.AddSkill(self, effectData, type, targets, isAdd, isRage,isTriggerJudge,isLoop) -- end -- 加入一个技能 -- type 加入的技能类型 -- targets 指定目标 -- isAdd 是否是追加技能 -- isRage 是否正常操作怒气值 function RoleLogic:AddSuperSkill(isRage, isAdd, targets,isTrigger,isLoop,scale) if not self.IsCanAddSkill and isAdd then return end local effectData = self.superSkill --角色被混乱后 local isTriggerJudge=true if isTrigger~=nil then isTriggerJudge=isTrigger end local type=BattleSkillType.Special if self.ctrl_chaos then type=BattleSkillType.ChaosNormal --混乱普攻使用普攻特效 effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4],{100001,{1,1,1}}} isTriggerJudge=false end if self.ctrl_lock then type=BattleSkillType.ChaosNormal --嘲讽普攻使用普攻特效 effectData={self.skill[1],self.skill[2],self.skill[3],self.skill[4],{200221,{1,1,1}}} isTriggerJudge=false end local skill=SkillManager.AddSkill(self, effectData, type, targets, isAdd, isRage,isTriggerJudge,isLoop) skill.AttactScale=scale -- end --加入额外技能,用于额外释放技能 by:王振兴 function RoleLogic:InsertExtraSkill(id,type) local effectData=BattleUtil.GetExtraSkillbyId(id) effectData[1]=self.superSkill[1] effectData[2]=self.superSkill[2] effectData[3]=self.superSkill[3] effectData[4]=self.superSkill[4] -- local effectData2={role.,role.superSkill[2],role.superSkill[3],role.superSkill[4],{targets,{1,f1,f2}}} if effectData then local skillType=BattleSkillType.Extra --如果type为1则按绝技处理,不为1的话按额外技能处理(额外技能因为被动判断会判断是否是绝技类型,所以不会触发) local isTrigger=true if type==1 then skillType=BattleSkillType.Special else isTrigger=false end --和老史,佳琦确认果 附加技能算绝技 被沉默无法释放 可以套娃 递归触发 by:王振兴 SkillManager.InsertSkill(self, effectData, skillType, nil, true, false,isTrigger) end end -- 插入一个技能 function RoleLogic:InsertSkill(type, isRage, isAdd, targets) if not self.IsCanAddSkill and isAdd then return end local effectData = type == BattleSkillType.Normal and self.skill or self.superSkill SkillManager.InsertSkill(self, effectData, type, targets, isAdd, isRage) end -- 设置是否可以追加技能 function RoleLogic:SetIsCanAddSkill(isCan) self.IsCanAddSkill = isCan end -- 正常触发技能 function RoleLogic:CastSkill(func) -- 设置轮转方法 -- SkillManager.SetTurnRoundFunc(func) if not self:IsAvailable() then return end --如果当前怒气不足以释放绝技 if self.Rage= self.SuperSkillRage then -- 释放大技能 self:AddSkill(BattleSkillType.Special, true, false, nil) return end -- 没有麻痹 释放普通技能 if not self.ctrl_palsy then self:AddSkill(BattleSkillType.Normal, true, false, nil) return end end -- 强制释放技能,测试技能时使用 -- type 追加的技能类型 1=普技 2=特殊技 -- targets 追加技能的目标 nil则自动选择目标 -- func 追加技能释放完成回调 function RoleLogic:ForceCastSkill(type, targets, func) -- 清除技能控制 self.ctrl_dizzy = false --眩晕 不能释放技能 self.ctrl_slient = false --沉默 只能1技能 self.ctrl_palsy = false --麻痹 只能2技能 -- 设置轮转方法 SkillManager.SetTurnRoundFunc(func) -- 释放技能 if type == 1 and self.skill then self:AddSkill(BattleSkillType.Normal, true, false, nil) elseif type == 2 and self.superSkill then if self.Rage < self.SuperSkillRage then self.Rage = self.SuperSkillRage end self:AddSkill(BattleSkillType.Special, true, false, nil) end end -- 判断是否可以去死了 function RoleLogic:IsCanDead() -- 暂时不能死 if not self.deadFilter then return false end -- 还有我的技能没有释放,不能死啊 if SkillManager.HaveMySkill(self) then return false end return true end -- 真的去死 function RoleLogic:GoDead() if self:IsCanDead() then self.isRealDead = true self.Rage = 0 self.curMainTarget=nil BattleLogic.BuffMgr:ClearBuff(self) self.Event:DispatchEvent(BattleEventName.RoleRealDead, self) BattleLogic.Event:DispatchEvent(BattleEventName.RoleRealDead, self) return true end return false end -- 设置是否可以死亡 function RoleLogic:SetDeadFilter(filter) self.deadFilter = filter end -- 要死了 function RoleLogic:SetDead(damage) self.isDead = true self.killDamage=damage self.deadRage=self.Rage RoleManager.AddDeadRole(self) end -- 判断是否死亡 function RoleLogic:IsDead() return self.isDead end function RoleLogic:IsRealDead() return self.isRealDead end -- 是否可以复活 function RoleLogic:IsCanRelive() if not self.reliveFilter then return false end if not self.isRealDead then return false end return true end -- 复活吧, 真的去世后才能复活 function RoleLogic:Relive() if self:IsCanRelive() then -- 没有指定血量则满血 self.isDead = false self.isRealDead = false local maxHp = self.data:GetData(RoleDataName.MaxHp) local reHp = floor(self.reliveHPF * maxHp) self.data:SetValue(RoleDataName.Hp, reHp) -- 发送复活事件 self.Event:DispatchEvent(BattleEventName.RoleRelive, self) --BattleLogic.Event:DispatchEvent(BattleEventName.RoleRelive, self) self.reliveCaster.Event:DispatchEvent(BattleEventName.ReliveRole,self) -- 复活的血量算做加血 BattleLogic.Event:DispatchEvent(BattleEventName.RecordTreat, self.reliveCaster or self, self, reHp) return true end return false end -- 设置是否可以死亡 function RoleLogic:SetReliveFilter(filter) self.reliveFilter = filter end --,hpf 复活时拥有的血量的百分比 function RoleLogic:SetRelive(hpf, caster) -- 判断是否可以复活 if self:IsCanRelive() then self.reliveHPF = hpf or 1 self.reliveCaster = caster self.addAttack = 0 RoleManager.AddReliveRole(self) -- local maxHp = self.data:GetData(RoleDataName.MaxHp) -- local reHp = floor(self.reliveHPF * maxHp) -- self.data:SetValue(RoleDataName.Hp, reHp) -- -- 发送复活事件 -- --self.Event:DispatchEvent(BattleEventName.RoleRelive, self) -- --BattleLogic.Event:DispatchEvent(BattleEventName.RoleRelive, self) -- -- 复活的血量算做加血 -- BattleLogic.Event:DispatchEvent(BattleEventName.RecordTreat, self.reliveCaster or self, self, reHp) -- return true end return false end function RoleLogic:Update() end