---关于技能替换的代码梳理: ---替换前的数据 : ---SkillIDData_Table = {s1, s2, s3, s4, s5, s6, s7} -- s4 为pvp才使用 ---replaceSkillIDDataTable = {} ---CurSkillDataList = {s1, s2, s3, s5, s6, s7} ---curModelSkillIDs = CurSkillDataList ---替换后 (s5 变为 s51) : ---SkillIDData_Table = {s1, s2, s3, s4, s5, s6, s7} -- 不变 ---replaceSkillIDDataTable = {[5]=s51} ---CurSkillDataList = {s1, s2, s3, s6, s7, s51} ---CurModelSkillIDs = CurSkillDataList ---应用 :按键变为cmd :GetSkillIndexByKeyPosition 通过keyPos找到skillIndex 。 com->skill : 先 GetSkillDataBySkillIndex 找skillData,返回其ID local SkillBaseComponent = class("SkillBaseComponent") local private = {} local FP=FP local LuaConst=LuaConst function SkillBaseComponent:initialize(entity) self.Entity = entity --当前使用的技能ID self.CurrentSkillID = -1 --缓存在释放技能时,又按了其他技能的按键,到释放点时自动释放技能 self.CacheSkillKeyPos = -1 --进入了后摇 self.CanSwitchAll = true --判断当前技能是被打断的 self.CurSkillInterrupted = LuaConst.SkillInterruptType.None --当前技能的经过时间 -- -1代表还未AttackEnter。 AttackEnter时会被设为0 self.CurPassTime = FP.newV1(-1) --当前技能的上一帧的间 self.CurLastPassTime = FP.newV1(-1) --当前公共CD剩余 self.CurCommonCD = FP.newV1(0) --双摇杆的位置 self.SkillJoystickPos = nil --释放技能时,所有子弹的强制出生点 ;子弹位置 self.MissileAimPos = nil --当前技能攻击的固定点(一般为nil ,给技能释放用);在AI 和 双摇杆设置 ;动作位置 ,(缩放位置时的优先级 > MSAimPos) self.AimPos = nil --当前技能攻击的伸缩固定点,记录的是攻击开始时的target位置; 动作位置 ,它与AimPos类似,但是不要autoskill继承,只用于落点距离 ,且它优先级最低(有AimPos优先使用AimPos) self.MSAimPos = nil -- MS的意思是move scale --当前技能的旋转最终目标朝向 。即旋转缩放完后 ,要朝向这个位置 ;RSAimDir 不用一化 ;如果这个值在自动切换下一个技能时不为nil,则下一个技能需要继承这个值。 self.RSAimDir = nil -- RS的意思是rotate scale self.RecordAttackTargetPos = nil --记录释放技能时目标的位置 ,如果没目标就是nil self.musouDynamicDmgFactor = nil --需要释放入场技 self.NeedReleaseGetInSkill = false --释放技能前是否先索敌 self.IsSearchTargetWhenSkill = nil -- 技能相关的装饰功能() self.DecoratorDic = nil -- 数据为: { [skillID] = {skillDecorator, skillDecorator} } self.DecoratorList = nil -- 遍历用。数据为: {{skillDecorator, skillDecorator} } ---------------------------------------------------- --为了优化加的字段 ,记录这个entity是否需要更新技能CD 【有任何技能cd,或者在连续技过渡期】 self.NeedUpdateSkillCD = false --记录当前的技能存在可输入的控制 self.CurSkillSwitchList = {} --其他技能(非当前技能)存在能生效的可输入的控制 self.SkillSwitchDir = {} --SkillData --当前技能配置 self.CurSkillData = nil self.CurSkillResourcePath = nil --这玩意是个Dic,不是List。key为characterID,value为SkillDataList,就是SkillData的数组。表示对应characterID的技能列表 self.AllSkillDataList = {} --当前模型的所有技能数据skilldata 注意index跟CharacterData的SkillIDData_Table是不匹配的! self.CurSkillDataList = {} -- 统计的当前模型所有技能的id ,(用于判断是否存在可用技能id) self.CurModelSkillIDs = {} --这玩意是个Dic,不是List。key为characterID,value为replaceSkillIDDataTable。就是SkillData的数组。表示对应characterID的技能列表 self.AllReplaceSkillIDDic = {} self.replaceSkillIDDataTable = {} -- 当前的character的替换规则 self.replacedSwitchDic = {} --替换过的switch字典,key为老技能ID,value为新技能ID【注意】不支持二次替换,比如A替换为B,B又替换为C,这种二次替换会导致记录失效 --动态skillSwitchTable,key为skillID,value为这个技能的SwitchTable。初始数据源来自skillData.SkillSwitch_Table,在 TryReplaceSkillByMagicWeapon 时会替换一些数据 --所有技能都会新建动态的 switchTable ,放在 skillSwitchTableDic 里。因为替换技能很普遍,所以不再像以前一样使用静态的 skillData.SkillSwitch_Table self.skillSwitchTableDic = {} self.skillJoystickDataDic = {} --动态skillJoytstick数据字典,key为SkillID,value为skillJoystickData。用于绑定skillJoystick数据和不同的skillID。让不同的skillID可以共享相同的skillJoystick数据。主要是替换技能共享原技能的skillJoystick数据 --SkillUpdateData --当前技能可变的部分 self.CurUpdateData = {} --当前的技能组Update数据,k:skillID,v:skillUpdateData self.CurUpdateDataGroup = {} --所有的技能组Update数据,k:characterID,v:updateDataGroup self.AllUpdateDataGroup = {} --自动战斗的技能列表;已经排好序了 self.AutoFightSkillDataList = {} --追击使用的技能 self.CastSkillID = nil --追击使用的技能是否可用 self.CanUseCastSkill = true -- 记录这个角色的所有连续技能的 各段时间 self.SerialSkillInfo = {} -- { [skillID] = {1.3 , 2 } , } --充能技能最大充能数重写字典,key=SkillID,value=次数 self.SkillMaxChargeCountOverrideDic = {} --能量技能每帧消耗能量 self.EnegySkillCutDic = {} --技能摇杆输入的偏移x self.SkillJoystickOffsetX = FP.newV1(0) --技能摇杆输入的偏移z self.SkillJoystickOffsetZ = FP.newV1(0) -- --技能摇杆输入的角度(废弃) -- self.SkillJoystickDirAngle = FP.newV1(361) -- 技能双摇杆被覆写的数据 key=skillID(即摇杆表ID),value= { } self.skillJoyStickOverrideDic = {} --赋值 self:SetCurrentSkillDataList(entity, entity._logicInitData._characterData) if not entity.isMonster then self:SetMusouSkillDynamicDamageFactor() end end function SkillBaseComponent:SetMusouSkillDynamicDamageFactor() local id = self.Entity:GetCharacterID() for k,v in DataSheetManager.HeroData:GetEnumerator() do if v.FuJiangRelate == id then id = v.ID break end end if self.Entity._logicInitData.WeaponBreak then local isSuccess, data = DataSheetManager.MagicWeaponStar:TryGetDataByMagicWeaponID_Star(id,self.Entity._logicInitData.WeaponBreak) if isSuccess then self.musouDynamicDmgFactor = data.MusouAndViceSkillEfficiency --else --正常现象 end --else --正常现象,目前只有hero有WeaponBreak end end function SkillBaseComponent:OnOverrideSkillDataCell(skillID) for i,skillDataList in pairs(self.AllSkillDataList) do -- pairs safe for j,skillData in ipairs(skillDataList) do if skillData.ID == skillID then skillDataList[j] = self.Entity:GetSkillData(skillID) break end end end end function SkillBaseComponent:SetCurrentSkillDataList(entity,characterData, noMagicWeaponSkill) if not characterData or not characterData.SkillIDData_Table then return end local characterID = characterData.ID self.SkillIDData_Table = characterData.SkillIDData_Table or {} local list = self.AllSkillDataList[characterID] local group = self.AllUpdateDataGroup[characterID] self.replaceSkillIDDataTable = self.AllReplaceSkillIDDic[characterID] or {} local isFirst = false if not list or not group then list = {} group = {} private.InitSkillData(self,entity,characterData,list,group) self.AllSkillDataList[characterID] = list self.AllUpdateDataGroup[characterID] = group self.AllReplaceSkillIDDic[characterID] = self.replaceSkillIDDataTable isFirst = true else self:RecalculateAutoFightSkillDataListAndAnimDistance(list) for i,v in ipairs(characterData.SkillIDData_Table) do local skillData = self.Entity:GetSkillData(v.ID) if skillData then if skillData.Type == LuaConst.SkillType.CastSkill then self.CastSkillID = v.ID end end end end self.CurSkillDataList = list self.CurUpdateDataGroup = group for i,skill in ipairs( self.CurSkillDataList) do self.CurModelSkillIDs[skill.ID] = skill.ID end -- 注意,变身的时候会调用这代码,此时不能再重新替换技能了,否则有出现bug:100642 替换为 100643 ,神兵再替换为 1022309。变身回来,如果再替换一次的话 1022309没删除,但是100643会加进来,重复多次后,技能表中有很多100643 if isFirst and not LevelManager.CurLevelFunc:IsMusouShowOpen(self.Entity) then self:ReplaceMusouSkillToNoShowVersion(entity,characterData) end if not noMagicWeaponSkill then self:TryReplaceSkillByMagicWeapon(characterData) end self:RefreshSkillDecorators() end function SkillBaseComponent:SetBanKeyPosList(sourceEntity, keyPosList) if keyPosList then -- 添加 if self.banKeyPosDic == nil then self.banKeyPosDic = {[sourceEntity.EntityID] = keyPosList} else self.banKeyPosDic[sourceEntity.EntityID] = keyPosList end self.banCount = self.banCount and self.banCount + 1 or 1 else -- 删除 self.banKeyPosDic[sourceEntity.EntityID] = keyPosList self.banCount = self.banCount - 1 if self.banCount == 0 then self.banKeyPosDic = nil end end end function SkillBaseComponent:IsKeyPosBanned(keyPos) if self.banKeyPosDic then for i,list in pairs(self.banKeyPosDic) do -- pairs safe for _,v in ipairs(list) do if v == keyPos then return true end end end end return false end function SkillBaseComponent:SetSkillJoystickInfoByCommand(command, byBuffSkill) if command.SkillIndex > 0 or byBuffSkill then --self.SkillJoystickDirAngle:Reset(command.SkillJoystickDirAngle) if command.SkillJoystickPosX ~= FP.Const.Zero or command.SkillJoystickPosZ ~= FP.Const.Zero then self.SkillJoystickOffsetX:Reset( command.SkillJoystickPosX) self.SkillJoystickOffsetZ:Reset( command.SkillJoystickPosZ) end -- else -- self:ClearSkillJoystickInfo() --因为技能输入有缓存机制,就是点击的技能如果在当前帧无法释放,就缓存起来等N帧后再放,所以技能摇杆的输入也不能清除了,这样缓存的技能的释放方向才是正确的 end end function SkillBaseComponent:ClearSkillJoystickInfo() --self.SkillJoystickDirAngle = FP.newV1(361) self.SkillJoystickOffsetX:Reset() self.SkillJoystickOffsetZ:Reset() end --返回正在释放的技能数据(配置表数据) function SkillBaseComponent:GetCurSkillData() return self.CurSkillData end function SkillBaseComponent:GetCDReduceFactor() local cdrdc = self.Entity:GetAttrValueNum(LuaConst.AttrType.cdrdc) if cdrdc then return 1 - cdrdc -- todo: 改为定点数 else return 1 end end --获取技能的实际冷却时间,是表里配置的SkillCD跟冷却缩减属性相乘后得到的冷却时间 --技能冷却时间指的是从放完一次技能后,到下一次技能ready时经过的时间 -- 传入FP的引用refFp可以节省内存 function SkillBaseComponent:GetFinalSkillCD(skillID, refFp) if refFp then refFp:Reset(self.Entity:GetSkillData(skillID).SkillCD):Mul(self:GetCDReduceFactor()) return refFp else return self.Entity:GetSkillData(skillID).SkillCD * self:GetCDReduceFactor() end end function SkillBaseComponent:SetCurCommonCD(value, skillData) self.CurCommonCDSkillData = skillData --引发公共CD的技能Data(用于让连续技规避公共CD的影响) self.CurCommonCD:Reset(value) end function SkillBaseComponent:ClearCurCommonCD() self.CurCommonCDSkillData = nil self.CurCommonCD:Reset(0) end --返回当前剩余的公共CD function SkillBaseComponent:GetCurCommonCD() return self.CurCommonCD end function SkillBaseComponent:CurCommonCDSub(timeMs) self.CurCommonCD:Sub(timeMs) end function SkillBaseComponent:GetMaxChargeCountOfSkillData(skillData) if self.SkillMaxChargeCountOverrideDic[skillData.ID] and self.SkillMaxChargeCountOverrideDic[skillData.ID] > 0 then return self.SkillMaxChargeCountOverrideDic[skillData.ID] else return skillData.ParamInt1 end end --一定会刷新充能次数到最大 function SkillBaseComponent:SetMaxChargeCountBySkillID(skillID, value) self.SkillMaxChargeCountOverrideDic[skillID] = value local updateData = self.CurUpdateDataGroup[skillID] if updateData then updateData.CD:Reset(0) local skillData = self.Entity:GetSkillData(skillID) if skillData then updateData.ChargeCount = (value and value > 0) and value or skillData.ParamInt1 else logging.error(LTAG.ERROR, "HYW : 试图设置不存在的技能的充能数! 错误的skillID : ", skillID) updateData.ChargeCount = (value and value > 0) and value or 0 end end end --返回FP,禁止修改返回值 function SkillBaseComponent:GetSkillEnegy(skillData) local updateData = self.CurUpdateDataGroup[skillData.BelongTo] if updateData then return updateData.Enegy end return FP.Const.Zero end function SkillBaseComponent:IsSkillEnegyFull(skillData) local belongToSkillData if skillData.BelongTo == skillData.ID then belongToSkillData = skillData else belongToSkillData = self.Entity:GetSkillData(skillData.BelongTo) end return self:GetMaxEnegyOfSkillData(belongToSkillData) == FP.tonumberV1(self:GetSkillEnegy(belongToSkillData)) end function SkillBaseComponent:GetEnegyCutOfSkill(skillData) return self.EnegySkillCutDic[skillData.BelongTo] end function SkillBaseComponent:GetMaxEnegyOfSkillData(skillData) return skillData.ParamInt2 end --获取动态技能伤害系数 --动态技能伤害系数:目前就一种,神兵养成后,会提升无双技的技能伤害系数 --可能返回nil function SkillBaseComponent:GetDynamicSkillDamageFactor(skillData) --无双的伤害系数不再走这个方法,改为走GetMusouDynamicDmgFactor -- if skillData then -- if skillData.Type == LuaConst.SkillType.MusouAttack then -- return self.musouDynamicDmgFactor -- end -- end end function SkillBaseComponent:GetMusouDynamicDmgFactor() local musoueff = self.Entity.components.attr:GetAttrValueNum("musoueff") if self.musouDynamicDmgFactor then if musoueff then return self.musouDynamicDmgFactor + musoueff else return self.musouDynamicDmgFactor end else local masterEntity = self.Entity:GetDirectMasterEntity() if masterEntity then return masterEntity.components.skillBase:GetMusouDynamicDmgFactor() else local value = (self.musouDynamicDmgFactor or 0) + (musoueff or 1) return value > 0 and value or 1 end end end function SkillBaseComponent:ClearCurSkillCacheInfo() self.CacheSkillKeyPos = -1 self.CurSkillSwitchList = {} end function SkillBaseComponent:SetCurSkillID(id) if self.CurSkillData ~= nil then self.LastSkillData = self.CurSkillData if self.LastSkillData then SystemManager.OnDeleteTimeScale(self.Entity, self.LastSkillData.ID, self.LastSkillData.TimeScale) end end self.CurrentSkillID = id self.CacheSkillKeyPos = -1 self.HasMeetTarget = false --是否 if id > 0 then -- 其实这些放入到AttackEnter中也可以的。 self.CurSkillSwitchList = {} self.CurPassTime:Reset(-1) self.CurLastPassTime:Reset(-1) end self.CurSkillInterrupted = LuaConst.SkillInterruptType.None self:UpdateCurSkillDataCache() end --自动连续释放下一技能 ,是否保持朝向 function SkillBaseComponent:SetAutoNextSkillHoldToward(val) self.AutoNextSkillHoldToward = val end -- 是否保持朝向 。非自动连续技能都是false ,自动下一技能且配置了holdToward 才是true function SkillBaseComponent:GetAutoNextSkillHoldToward() return self.AutoNextSkillHoldToward end function SkillBaseComponent:IsAutoNextSkill(skillID) return self.CurSkillData and self.CurSkillData.AutoNextID == skillID or (self.LastSkillData and self.LastSkillData.AutoNextID == skillID) end function SkillBaseComponent:IsMusouSkill(skillData) return skillData.Type == LuaConst.SkillType.MusouAttack end function SkillBaseComponent:IsAdjutantSkill(skillData) return skillData.Type == LuaConst.SkillType.AdjutantMusou end function SkillBaseComponent:IsChargeSkill(skillData) return skillData.Type == LuaConst.SkillType.Charge end function SkillBaseComponent:IsSerialSkill(skillData) return skillData.Type == LuaConst.SkillType.Serial end function SkillBaseComponent:IsEnegySkill(skillData) return skillData.Type == LuaConst.SkillType.Enegy end function SkillBaseComponent:UpdateCurSkillDataCache() self.CurSkillData = self.CurrentSkillID>0 and self.Entity:GetSkillData(self.CurrentSkillID) or nil self:SetCurSkillResource() if self.CurSkillData then self.CurUpdateData = self.CurUpdateDataGroup[self.CurSkillData.BelongTo] local oldCd = self.CurUpdateData and FP.tonumberV1(self.CurUpdateData.CD) or 0 RuntimeDataManager.Reset_SkillUpdate(self.CurUpdateData) if self.CurUpdateData then self.CurUpdateData.CD:Reset(oldCd) --继承老CD else self.CurUpdateData = RuntimeDataManager.New_SkillUpdate() --这句是让异常情况能跑下去的代码,可能会产生异常,但是比没有这句看着会好很多。如果没有这句,则这个技能就打不出伤害了 --logging.error(LTAG.ERROR, "HYW : self.CurUpdateData 为空! BelongTo为", self.CurSkillData.BelongTo, " LevelType : ", LevelManager.GetCurLevelType(), " self.CurUpdateDataGroup : ", self.CurUpdateDataGroup) end --self.CurSkillJoystickData = DataSheetManager.SkillJoyStickData:GetDataByID(self.CurrentSkillID) self.CurSkillJoystickData = self:GetSkillJoystickData(self.CurrentSkillID) else self.CurSkillJoystickData = nil end end function SkillBaseComponent:GetSkillDataBySkillIndex(skillIndex) if skillIndex > 0 then if self.replaceSkillIDDataTable[skillIndex] then --这个需要在最开始,因为replaceSkillIDDataTable的优先级最高 return self.Entity:GetSkillData(self.replaceSkillIDDataTable[skillIndex].ID) elseif self.SkillIDData_Table[skillIndex] then return self.Entity:GetSkillData(self.SkillIDData_Table[skillIndex].ID) else logging.log(LTAG.ERROR, "HYW : 策划注意!! 单位 ", self.Entity:GetCharacterID(), " 没有技能号位为", skillIndex, " 的技能!!但是试图释放或查询!!AI配的有问题!") end end end function SkillBaseComponent:GetSkillIndexByKeyPosition(keyPos) if keyPos > 0 then for i,seg in ipairs(self.SkillIDData_Table) do local skillData = self.Entity:GetSkillData(seg.ID) if skillData.KeyPosition == keyPos then return i end end end return 0 end function SkillBaseComponent:GetSkillIndexBySkillID(skillID) for i,seg in ipairs(self.SkillIDData_Table) do if seg.ID == skillID then return i end end return 0 end function SkillBaseComponent:GetSkillDataByKeyPosition(keyPos) if keyPos > 0 then for i,skillData in ipairs(self.CurSkillDataList) do if skillData.KeyPosition == keyPos then return skillData end end end end function SkillBaseComponent:GetJoystickDataByKeyPosition(keyPos) local skillData = self:GetSkillDataByKeyPosition(keyPos) if skillData then return self:GetSkillJoystickData(skillData.ID) end end function SkillBaseComponent:GetSkillKeyPositionBySkillIndex(skillIndex) if skillIndex > 0 then local skillData = self:GetSkillDataBySkillIndex(skillIndex) if skillData then return skillData.KeyPosition else return -1 end else return -1 end end function SkillBaseComponent:GetSkillJoystickData(skillID) if self.skillJoystickDataDic[skillID] then return self.skillJoystickDataDic[skillID] end local isSuccess, skillJoyData = DataSheetManager.SkillJoyStickData:TryGetDataByID(skillID) return skillJoyData end local EMPTY_TABLE = {} function SkillBaseComponent:GetSkillSwitchTable(skillID) return self.skillSwitchTableDic[skillID] or EMPTY_TABLE end local function _BelongIDSorter(a, b) return a < b end --返回排序过的SkillUpdate数据的key,在某些需要保证一致性的地方使用 --不能频繁调用,因为性能较差。使用的时候一定要注意性能!!! function SkillBaseComponent:GetSortedSkillUpdateDataKeyList() local sortedSkillIDlist = {} for belongID,updateData in pairs(self.CurUpdateDataGroup) do --belongID就是SkillID, 是一组技能的主技能的SkillID, 技能的runtime信息会以主技能ID为key,这个key就是belonID table.insert(sortedSkillIDlist, belongID) end table.sort(sortedSkillIDlist, _BelongIDSorter) return sortedSkillIDlist end function SkillBaseComponent:IsSkillInCDByBelongTo(belongID) if self.CurUpdateDataGroup[belongID] and self.CurUpdateDataGroup[belongID].CD > FP.Const.Zero then return true else return false end end function SkillBaseComponent:CanUseSkill(skillData) --判空 if not skillData or not self.CurUpdateDataGroup[skillData.BelongTo] then return false end if self.DecoratorDic then local decoratorList = self.DecoratorDic[skillData.BelongTo] if decoratorList then for _,decorator in ipairs(decoratorList) do if decorator.CanUseSkill and not decorator:CanUseSkill() then return false end end end end --充能技能 if self:IsChargeSkill(skillData) then local belongToSkillData = self.Entity:GetSkillData(skillData.BelongTo) if self.CurUpdateDataGroup[skillData.BelongTo].ChargeCount then if self.CurUpdateDataGroup[skillData.BelongTo].ChargeCount > 0 and not self:IsKeyPosBanned(belongToSkillData.KeyPosition) then return true else return false end else logging.error(LTAG.ERROR, "HYW : 充能技能的ChargeCount居然为nil,哪里肯定出问题了 skillData.ID : ", skillData.ID) return false end end if (skillData.SkillCD <= FP.Const.Zero or not self.CurUpdateDataGroup[skillData.BelongTo]) and skillData.ID ~= skillData.BelongTo then --这里代表是CD=0的子技能 --CD为0的子技能可释放的条件非常宽泛,所以这里直接返回true return true end --未完成HYW↓ 这里判断主技能CD为0就return false,就要求所有子技能的SkillCD都配0,才能从上面 if (skillData.SkillCD <= FP.Const.Zero or not self.C ... 这个判断中释放出去。很可能会不符合未来的需求 --根本原因是现在不会在CurUpdateDataGroup里创建子技能的所属UpdateData,需要把这个补了,然后在上面再添加一个子技能CD的判定,才能完全解决现在的问题 if self.CurUpdateDataGroup[skillData.BelongTo] and self.CurUpdateDataGroup[skillData.BelongTo].CD > FP.Const.Zero then return false end if self.CurCommonCDSkillData then --说明: skillData.BelongTo ~= self.CurCommonCDSkillData.ID 意思是skillData不是self.CurCommonCDSkillData的连续技的一种情况,另一种情况就是skillData.ID == self.CurCommonCDSkillData.BelongTo --说明2: skillData.BelongTo == skillData.ID, 含义为skillData就是self.CurCommonCDSkillData的初始技,这种情况下不能忽略公共CD if (skillData.BelongTo ~= self.CurCommonCDSkillData.ID or skillData.ID == self.CurCommonCDSkillData.BelongTo) --如果技能是触发公共CD技能的连续技,则忽略这个公共CD and not skillData.IgnoreCommonCD and FP.Greater(self:GetCurCommonCD(), 0) then return false end end --SA if (skillData.Type == LuaConst.SkillType.MusouAttack) and (not self.Entity.components.attr:IsSAFilled()) then return false end --被沉默 if self:IsKeyPosBanned(skillData.KeyPosition) then return false end return true end --region *************** 私有方法 ***************** --计算动画总位移,存在skillData里。只在Init阶段计算一次 local temp_V2 = FP.newV2(0,0) function private.HandleAnimDistance(entity,skillData) local animMoveData = entity.components.anim:GetAnimMoveData(skillData.AnimName) -- 不仅是位移也包括旋转信息 (位移和旋转在一个animMoveData中) --动画水平位移比例 TODO:有时间研究下这能否再数据读取就搞好 if skillData.MSStartTime[1] >= 0 then local startFrame = skillData.MSStartTime / LuaConst.TimeSpanMs local endFrame = skillData.MSEndTime / LuaConst.TimeSpanMs local vec = FP.newV2(0,0) if not animMoveData then logging.error(LTAG.ERROR , "策划 :没有动画信息那么就不要配置缩放了! 怪物ID =" , entity:GetCharacterID(), " ,技能的动画 =", skillData.AnimName ,"技能ID = ", skillData.ID) return end local moveFrame = animMoveData.Count local isLock = animMoveData.IsLock for i = 1,moveFrame do if FP.LessEquals(startFrame ,i) and FP.GreaterEquals(endFrame ,i) then if not isLock then temp_V2:Reset(animMoveData.XArray and animMoveData.XArray[i] or 0,animMoveData.ZArray and animMoveData.ZArray[i] or 0) vec:Add(temp_V2) end end end local totalDis = FP.V2.Magnitude(vec) if totalDis == FP.Const.Zero then logging.error(LTAG.ERROR, "HYW : 致命错误! MSTotalDis为0。 skillID : " .. tostring(skillData.ID) .. " skillData.AnimName : " .. tostring(skillData.AnimName) .. " 是不是该动画没有采集位移信息?") totalDis:Reset(1) --如果totalDis为0,是非法值,重设为1防止后续报错崩溃 end rawset(skillData, "MSTotalDis", totalDis) FP.releaseV2(vec) end --动画的旋转角度统计 if skillData.RSStartTime[1] >= 0 then local startFrame = skillData.RSStartTime / LuaConst.TimeSpanMs local endFrame = skillData.RSEndTime / LuaConst.TimeSpanMs local totalAngle = FP.newV1(0) if animMoveData == nil or animMoveData.AngleArray == nil then logging.error(LTAG.ERROR , "战斗策划 :没有动画信息那么就不要配置旋转缩放了!skillID : " .. tostring(skillData.ID) .. " skillData.AnimName : " , skillData.AnimName) return end local moveFrame = animMoveData.Count for i = 1,moveFrame do if FP.LessEquals(startFrame ,i) and FP.GreaterEquals(endFrame ,i) then totalAngle:Add(animMoveData.AngleArray[i]) end end if totalAngle == FP.Const.Zero then logging.error(LTAG.ERROR, "GWS : 致命错误![战斗策划]: MSTotalAngle为0。 skillID : " .. tostring(skillData.ID) .. " skillData.AnimName : " .. tostring(skillData.AnimName) .. " 旋转缩放,原始角度怎么为0呢 !") end rawset(skillData, "RSTotalAngle", totalAngle) end end -- 连续技能的数据统计 function private.HandleSerialSkill(self,skillData) if self:IsSerialSkill(skillData) then local findSkillSwitch = nil --for i,skillSwitch in ipairs(skillData.SkillSwitch_Table) do --old for i,skillSwitch in ipairs(self.skillSwitchTableDic[skillData.ID]) do --new local nextSkillID = skillData.ParamInt1 if skillSwitch.SwitchPutOut == nextSkillID then findSkillSwitch = skillSwitch break end end if findSkillSwitch then local serialList = self.SerialSkillInfo[skillData.BelongTo] local serialTime = findSkillSwitch.SwitchDuration + findSkillSwitch.SwitchStartTime if serialList then table.insert(serialList, serialTime) else self.SerialSkillInfo[skillData.BelongTo] = {serialTime} end end end end --把静态配置数据转存到动态table,方便动态修改 function SkillBaseComponent:CollectSkillSwitchTable(skillData) if not self.skillSwitchTableDic[skillData.ID] then local dynamicSkillSwitchTable = {} self.skillSwitchTableDic[skillData.ID] = dynamicSkillSwitchTable for i,skillSwitch in ipairs(skillData.SkillSwitch_Table) do --old local dynamicSkillSwitch = {} dynamicSkillSwitchTable[i] = dynamicSkillSwitch for k,v in pairs(skillSwitch) do --pairs safe 复制数据对顺序不敏感 if self.replacedSwitchDic[v] then dynamicSkillSwitch[k] = self.replacedSwitchDic[v] else dynamicSkillSwitch[k] = v end end end end end function private.InitSkillData(self, entity, characterData, list, group) local sceneReplaceType = LuaConst.SkillSceneReplaceType.None if not LevelManager.IsLittleBlackRoomMusouLevel() then sceneReplaceType = LuaConst.SkillSceneReplaceType.PVP end if sceneReplaceType == LuaConst.SkillSceneReplaceType.None then --不再特殊场景中 for i,v in ipairs(characterData.SkillIDData_Table) do local skillData = self.Entity:GetSkillData(v.ID) if skillData == nil then logging.error(LTAG.ERROR, "HYW : skillData nil Error : ", v.ID) else self:CollectSkillSwitchTable(skillData) if skillData.SceneReplace == LuaConst.SkillSceneReplaceType.None then ---不再特殊场景中 table.insert(list,skillData) if group[skillData.BelongTo] == nil then group[skillData.BelongTo] = RuntimeDataManager.New_SkillUpdate() end self:TryInitSkillCount(group, skillData) --new -- old↓ -- if self:IsChargeSkill(skillData) then -- 设置充能技能的能量是满的 -- if self:GetMaxChargeCountOfSkillData(skillData) > 0 then -- group[skillData.BelongTo].ChargeCount = self:GetMaxChargeCountOfSkillData(skillData) -- end -- end -- old↑ --自动战斗优先级为0,则不能自动释放 ;KeyPosition小于0,则为技能的后续段 if (skillData.AutoBattleOrder > 0 and skillData.KeyPosition > 0) then if self.AutoFightSkillDataList[1] == nil then table.insert(self.AutoFightSkillDataList,skillData) else local inserted = false for pos,sd in ipairs(self.AutoFightSkillDataList) do if skillData.AutoBattleOrder > sd.AutoBattleOrder then table.insert(self.AutoFightSkillDataList,pos,skillData) inserted = true break end end if not inserted then table.insert(self.AutoFightSkillDataList,skillData) end end end --追击技能 if skillData.Type == LuaConst.SkillType.CastSkill then self.CastSkillID = v.ID end -- 统计连续技能的数据 private.HandleSerialSkill(self,skillData) private.HandleAnimDistance(entity,skillData) end end end else ---- pvp 特殊技能 --TODO 已经和策划商量过,从属技能也会配上关卡类型,这里考虑是否可以简化 local keyPositionList = {} local idList = characterData.SkillIDData_Table for k,v in ipairs(idList) do local skillData = self.Entity:GetSkillData(v.ID) self:CollectSkillSwitchTable(skillData) if skillData.SceneReplace == sceneReplaceType then keyPositionList[skillData.KeyPosition] = true end end local belongToSkillIDList = {} for k,v in ipairs(idList) do local skillData = self.Entity:GetSkillData(v.ID) if skillData.SceneReplace ~= sceneReplaceType and keyPositionList[skillData.KeyPosition] then belongToSkillIDList[skillData.ID] = true end end for k,v in ipairs(idList) do local skillData = self.Entity:GetSkillData(v.ID) if skillData.SceneReplace == sceneReplaceType or (skillData.SceneReplace == LuaConst.SkillSceneReplaceType.None and not belongToSkillIDList[skillData.BelongTo]) then table.insert(list,skillData) if group[skillData.BelongTo] == nil then group[skillData.BelongTo] = RuntimeDataManager.New_SkillUpdate() end self:TryInitSkillCount(group, skillData) --new -- old↓ -- if self:IsChargeSkill(skillData) then -- 设置充能技能的能量是满的 -- if self:GetMaxChargeCountOfSkillData(skillData) > 0 then -- group[skillData.BelongTo].ChargeCount = self:GetMaxChargeCountOfSkillData(skillData) -- end -- end -- old↑ --自动战斗优先级为0,则不能自动释放 ;KeyPosition小于0,则为技能的后续段 if (skillData.AutoBattleOrder > 0 and skillData.KeyPosition > 0) then if self.AutoFightSkillDataList[1] == nil then table.insert(self.AutoFightSkillDataList,skillData) else local inserted = false for pos,sd in ipairs(self.AutoFightSkillDataList) do if skillData.AutoBattleOrder > sd.AutoBattleOrder then table.insert(self.AutoFightSkillDataList,pos,skillData) inserted = true break end end if not inserted then table.insert(self.AutoFightSkillDataList,skillData) end end end --追击技能 if skillData.Type == LuaConst.SkillType.CastSkill then self.CastSkillID = v.ID end -- 统计连续技能的数据 private.HandleSerialSkill(self,skillData) private.HandleAnimDistance(entity,skillData) end end end end --替换普通技能(非无双技能) function SkillBaseComponent:ReplaceNormalSkillBySkillID(skillID) local replaced = false local replaceSkillData = self.Entity:GetSkillData(skillID) if replaceSkillData then for i,skillData in ipairs(self.CurSkillDataList) do if skillData.KeyPosition == replaceSkillData.KeyPosition and skillData.KeyPosition > 0 then replaced = self:ReplaceSkillDataChain(skillData, replaceSkillData) break end end else logging.error(LTAG.ERROR, "HYW : ReplaceNormalSkillBySkillID 失败,找不到 replaceSkillData , skillID : ", skillID) end return replaced end --endregion 私有方法 --替换技能为神兵突破和神兵锻铸后的技能 function SkillBaseComponent:TryReplaceSkillByMagicWeapon(characterData) if self.Entity:IsHero() or self.Entity:IsAdjutant() or self.Entity:IsIllusion() or self.Entity.isRetinue then local originEntity = self.Entity:GetOriginEntity() local heroArmyData = LevelPlayerManager.GetPlayerArmyData(originEntity:GetPlayerID(), originEntity) local characterID = characterData.ID if self.Entity.isRetinue then heroArmyData = LevelPlayerManager.GetExtraHeroInfo(heroArmyData, self.Entity.retinueData) characterID = self.Entity.retinueData.UseDevelopOfHeroID end if heroArmyData then local heroID = heroArmyData.HeroID or heroArmyData.heroId -- ↓根据神兵突破等级替换无双/副将技 if self.Entity:IsHero() or self.Entity.isRetinue or self.Entity:IsIllusion() then --如果是英雄(主将) —— 需要替换无双技(神兵突破提供)和普通技能(神兵锻铸提供) local replaced = false if heroArmyData.mainHeroMusouSkillId and heroArmyData.mainHeroMusouSkillId > 0 and heroArmyData.mainHeroWeaponLevels and heroArmyData.mainHeroWeaponLevels > 0 then --无双技能有变身机制,所以下面处理替换的规则比较复杂 local mainHeroMagicWeaponStarData = DataSheetManager.MagicWeaponStar:GetDataByMagicWeaponID_Star(heroID, heroArmyData.mainHeroWeaponLevels) local musouSkillID, musouNoTLSkillID = 0, 0 local hasMusouSkill = false if mainHeroMagicWeaponStarData.MusouHeroIDP2 == characterID then musouSkillID = mainHeroMagicWeaponStarData.MusouSkillIDP2 musouNoTLSkillID = mainHeroMagicWeaponStarData.MusouNoTLSkillIDP2 hasMusouSkill = true elseif mainHeroMagicWeaponStarData.MusouHeroID <= 0 or mainHeroMagicWeaponStarData.MusouHeroID == characterID then musouSkillID = mainHeroMagicWeaponStarData.MusouSkillID musouNoTLSkillID = mainHeroMagicWeaponStarData.MusouNoTLSkillID hasMusouSkill = true end if hasMusouSkill then local magicWeaponSkillData local magicWeaponNoTLSkillData local keyPosition if musouSkillID > 0 then magicWeaponSkillData = self.Entity:GetSkillData(musouSkillID) keyPosition = magicWeaponSkillData.KeyPosition -- 潜规则 : magicWeaponSkillData 和 magicWeaponNoTLSkillData的keyPosition 必须是一样的 end if musouNoTLSkillID > 0 then magicWeaponNoTLSkillData = self.Entity:GetSkillData(musouNoTLSkillID) keyPosition = magicWeaponSkillData.KeyPosition -- 潜规则 : magicWeaponSkillData 和 magicWeaponNoTLSkillData的keyPosition 必须是一样的 end if keyPosition then --logging.error(LTAG.ERROR, "HYW : 无双技 等级 :", heroArmyData.mainHeroWeaponLevels, " 技能 : ", mainHeroMagicWeaponStarData.MusouSkillID, " NoTL技能 : ", mainHeroMagicWeaponStarData.MusouNoTLSkillID) for i,skillData in ipairs(self.CurSkillDataList) do if skillData.KeyPosition == keyPosition then local replaceBelongToSkillData if skillData.SceneReplace == LuaConst.SkillSceneReplaceType.None then replaceBelongToSkillData = magicWeaponSkillData else replaceBelongToSkillData = magicWeaponNoTLSkillData end if replaceBelongToSkillData then replaced = self:ReplaceSkillDataChain(skillData, replaceBelongToSkillData) else logging.error(LTAG.ERROR, "HYW : 找不到神兵突破无双技 MagicWeaponID : ", mainHeroMagicWeaponStarData.MagicWeaponID) end break end end end end end --2022年6月24日 新增了 characterID == originEntity:GetCharacterID() 让神兵锻铸仅可替换初始技能,变身后的技能不可替换 --2023年3月7日 新增了 or self.Entity.isRetinue, 让随从可以继承神兵锻铸 -- 2023年5月8日 神兵锻铸新增:变身后的技能也可替换 if heroArmyData.foundryLineInfo then --替换普通技能(神兵锻铸提供) local templateID = DataSheetUtil.GetForgeTemplateID(heroID, heroArmyData.weaponAppearanceId) local originCharacterID = originEntity:GetCharacterID() for i,lineId in ipairs(heroArmyData.foundryLineInfo) do local magicWeaponFoundryData = DataSheetManager.MagicWeaponFoundry:GetDataByID_PointID(templateID, lineId) if magicWeaponFoundryData then local replaceSkillID = 0 if characterID == originCharacterID or self.Entity.isRetinue then replaceSkillID = magicWeaponFoundryData.SkillID elseif characterID == magicWeaponFoundryData.ExtraHeroID then -- ExtraSkillID :即变身的P2 replaceSkillID = magicWeaponFoundryData.ExtraSkillID end if replaceSkillID > 0 then replaced = self:ReplaceNormalSkillBySkillID(replaceSkillID) or replaced --注意别短路了 end if magicWeaponFoundryData.SubSkillIDs and #magicWeaponFoundryData.SubSkillIDs > 0 then -- 郭卫松:子(附属)技能在ReplaceSkillDataChain已替换完毕 ,目前没啥用途 。但是可在一个孔替换多个技能时用。 for j,subSkillID in ipairs(magicWeaponFoundryData.SubSkillIDs) do replaced = self:ReplaceNormalSkillBySkillID(subSkillID) or replaced --注意别短路了 end end else logging.error(LTAG.ERROR, "HYW : MagicWeaponFoundry 获取失败 模板ID : ", templateID, " 点位ID : ", lineId) end end end if replaced then self:RecalculateAutoFightSkillDataListAndAnimDistance(self.CurSkillDataList) self:RefreshCurModelSkillIDs() end elseif self.Entity:IsAdjutant() then --如果是副将 —— 仅需要替换副将技 if heroArmyData.viceHeroMusouSkillId and heroArmyData.viceHeroMusouSkillId > 0 and heroArmyData.viceHeroWeaponLevels and heroArmyData.viceHeroWeaponLevels > 0 then local viceHeroMagicWeaponStarData = DataSheetManager.MagicWeaponStar:GetDataByMagicWeaponID_Star(heroArmyData.AdjutantID, heroArmyData.viceHeroWeaponLevels) --这里的AdjutantID是没有变身前的ID,比如张角副将,这里AdjutantID是6。查询MagicWeaponStar必须用这个ID,不能用变身后的ID if viceHeroMagicWeaponStarData then local replaced = false local replaceSkillID = 0 if viceHeroMagicWeaponStarData.MusouHeroIDP2 == heroArmyData.AdjutantID then replaceSkillID = viceHeroMagicWeaponStarData.ViceSkillIDP2 else replaceSkillID = viceHeroMagicWeaponStarData.ViceSkillID end --logging.error(LTAG.ERROR, "HYW : 副将技 等级 :", heroArmyData.viceHeroWeaponLevels, " 技能 : ", viceHeroMagicWeaponStarData.ViceSkillID, " 副将CharacterID : ", heroArmyData.AdjutantID, " Entity CharID : ", self.Entity:GetCharacterID()) for i,skillData in ipairs(self.CurSkillDataList) do if skillData.KeyPosition == LuaConst.ESkillKeyPosition.AdjutantSkillMain then if replaceSkillID > 0 then local replaceBelongToSkillData = self.Entity:GetSkillData(replaceSkillID) if replaceBelongToSkillData then replaced = self:ReplaceSkillDataChain(skillData, replaceBelongToSkillData) else logging.error(LTAG.ERROR, "HYW : 找不到神兵突破副将技 : ", replaceSkillID) end end break end end if replaced then self:RecalculateAutoFightSkillDataListAndAnimDistance(self.CurSkillDataList) self:RefreshCurModelSkillIDs() end else logging.error(LTAG.ERROR, "HYW : 副将找不到神兵突破数据 HeroID : ", heroArmyData.AdjutantID, " 等级 : ", heroArmyData.viceHeroWeaponLevels) end end end -- ↑根据神兵突破等级替换无双/副将技 end end end -- ReplaceSkillSwitch 做两件事 --1、建立 newSkillData 的动态 switchTable --2、把所有SwitchPutOut为oldSkillData的技能都替换为newSkillData(这个牵扯的是其他技能) --注意: newSkillData 并不会继承 oldSkillData 的 swtichTable。只是把输出为 oldSkillData 的其他技能的 switchTable 替换为输出 newSkillData function SkillBaseComponent:ReplaceSkillSwitch(oldSkillData, newSkillData) self:CollectSkillSwitchTable(newSkillData) for k,skillSwitchTable in pairs(self.skillSwitchTableDic) do -- pairs safe 数据替换对顺序不敏感 for i,skillSwitch in ipairs(skillSwitchTable) do if skillSwitch.SwitchPutOut == oldSkillData.ID then --logging.error(LTAG.ERROR, "HYW : ReplaceSkillSwitch old : ", skillSwitch.SwitchPutOut, " new : ", newSkillData.ID) if self.replacedSwitchDic[skillSwitch.SwitchPutOut] ~= newSkillData.ID then if not self.replacedSwitchDic[skillSwitch.SwitchPutOut] then self.replacedSwitchDic[skillSwitch.SwitchPutOut] = newSkillData.ID --记录一下这个switch的替换,当技能替换时需要继承switch的替换,所以需要记录这个信息 else --目前的需求,应该不会出现二次替换的情况,所以可以用简单方式实现替换信息的记录,如果二次替换了报个错,程序需要去支持! logging.error(LTAG.ERROR, "HYW : Switch尝试二次替换,这是不支持的,会出现switch失效的bug!如果一定要支持,需要跟程序提需求! old SwitchPutOut :", skillSwitch.SwitchPutOut, " new : ", newSkillData.ID) end end --↓ 根据技能ID指定switch时,需要替换SwitchPutIn if skillSwitch.SwitchPutIn < 0 then if skillSwitch.SwitchPutIn == -oldSkillData.ID then skillSwitch.SwitchPutIn = -newSkillData.ID end end --↑ skillSwitch.SwitchPutOut = newSkillData.ID break end end end end --如果newSkillData没有双摇杆数据,就共享oldSkillData的数据 function SkillBaseComponent:TryShareSkillJoystickData(oldSkillData, newSkillData) local isSuccess, skillJoystickData = DataSheetManager.SkillJoyStickData:TryGetDataByID(newSkillData.ID) if not isSuccess then self.skillJoystickDataDic[newSkillData.ID] = self:GetSkillJoystickData(oldSkillData.ID) --策划需求:替换后的技能共享替换前的 end end --把oldSkillData和它的AutoNext链、连续技链上的所有技能都替换为 newSkillData和newSkillData的AutoNext链、连续技链 function SkillBaseComponent:ReplaceSkillDataChain(oldSkillData, newSkillData, ignoreCD) if oldSkillData ~= newSkillData then local group = self.CurUpdateDataGroup local list = self.CurSkillDataList local skillIndex local oldCD if oldSkillData then self:ReplaceSkillSwitch(oldSkillData, newSkillData) self:TryShareSkillJoystickData(oldSkillData, newSkillData) skillIndex = self:GetSkillIndexByKeyPosition(oldSkillData.KeyPosition) if skillIndex == 0 then skillIndex = self:GetSkillIndexBySkillID(oldSkillData.ID) end -- 当替换一些子技能时,由于子技能的 KeyPosition = -1,则skillIndex = 0;replaceSkillIDDataTable 中的 index就是一个错误的值0,若有多个技能有子技能替换,则数据错乱了 for i,v in ipairs(list) do if v == oldSkillData then if not ignoreCD then oldCD = group[v.BelongTo].CD end group[v.BelongTo] = nil table.remove(list, i) --会break,所以可以在遍历里remove if self.replaceSkillIDDataTable[skillIndex] == oldSkillData then self.replaceSkillIDDataTable[skillIndex] = nil end --logging.error(LTAG.ERROR, "HYW : Remove : ", oldSkillData.ID) break end end else logging.error(LTAG.ERROR, "HYW : oldSkillData nil @SkillBaseComponent:ReplaceSkillDataChain characterID : ", self.Entity:GetCharacterID(), " newSkillData.ID : ", newSkillData.ID) end if newSkillData then table.insert(list, newSkillData) --logging.error(LTAG.ERROR, "HYW : Add : ", newSkillData.ID) if skillIndex then self.replaceSkillIDDataTable[skillIndex] = {ID = newSkillData.ID} end if group[newSkillData.BelongTo] == nil then if group[newSkillData.BelongTo] == nil then group[newSkillData.BelongTo] = RuntimeDataManager.New_SkillUpdate() end self:TryInitSkillCount(group, newSkillData) --new -- old↓ -- if self:IsChargeSkill(newSkillData) then -- 设置充能技能的能量是满的 -- if self:GetMaxChargeCountOfSkillData(newSkillData) > 0 then -- group[newSkillData.BelongTo].ChargeCount = self:GetMaxChargeCountOfSkillData(newSkillData) -- end -- end -- old↑ end group[newSkillData.BelongTo].CD:Reset(oldCD) end local nextNewSkillData if newSkillData then nextNewSkillData = self:GetNextSkillData(newSkillData) end if nextNewSkillData then local nextOldSkillData if oldSkillData then nextOldSkillData = self:GetNextSkillData(oldSkillData) end self:ReplaceSkillDataChain(nextOldSkillData, nextNewSkillData, true) end return true else return false end end --设置技能的指数初始值,包括充能技能的充能数、能量技能的能量数等 function SkillBaseComponent:TryInitSkillCount(groupDic, skillData) if skillData.ID == skillData.BelongTo then if self:IsChargeSkill(skillData) then if self:GetMaxChargeCountOfSkillData(skillData) > 0 then groupDic[skillData.BelongTo].ChargeCount = self:GetMaxChargeCountOfSkillData(skillData)-- 设置充能技能的能量是满的 else logging.error(LTAG.ERROR, "HYW : 策划注意!充能技能的次数配置小于等于0了! ID : ", skillData.ID) end elseif skillData.Type == LuaConst.SkillType.Enegy then if self:GetMaxEnegyOfSkillData(skillData) > 0 then groupDic[skillData.BelongTo].Enegy = FP.newV1(self:GetMaxEnegyOfSkillData(skillData)) --设置能量技能的能量是满的 self.EnegySkillCutDic[skillData.BelongTo] = FP.newV1(0) self.EnegySkillCutDic[skillData.BelongTo]:Reset(skillData.ParamInt1):Div(skillData.ParamInt2) else logging.error(LTAG.ERROR, "HYW : 策划注意!能量技能的能量配置小于等于0了! ID : ", skillData.ID) end end end end --如果skillData有AutoNextID,返回AutoNextID的SkillData,否则如果skillData是连续技,返回ParamInt1对应的SkillData,否则返回nil function SkillBaseComponent:GetNextSkillData(skillData) local nextSkillData = nil if skillData then if skillData.AutoNextID and skillData.AutoNextID > 0 then nextSkillData = self.Entity:GetSkillData(skillData.AutoNextID) elseif skillData.Type == LuaConst.SkillType.Serial then nextSkillData = self.Entity:GetSkillData(skillData.ParamInt1) end end return nextSkillData end function SkillBaseComponent:ReplaceMusouSkillToNoShowVersion(entity,characterData) if not characterData or not characterData.SkillIDData_Table then return end local characterID = characterData.ID local list = self.AllSkillDataList[characterID] local group = self.AllUpdateDataGroup[characterID] private._ReplaceMusouSkillDataToPvpVersion(self, entity, characterData, list, group) if list == self.CurSkillDataList then self:RefreshCurModelSkillIDs() end end function SkillBaseComponent:RefreshCurModelSkillIDs() self.CurModelSkillIDs = {} for k,skill in ipairs( self.CurSkillDataList) do self.CurModelSkillIDs[skill.ID] = skill.ID end end --替换技能为pvp版本 function private._ReplaceMusouSkillDataToPvpVersion(self, entity, characterData, list, group) local sceneReplaceType = LuaConst.SkillSceneReplaceType.PVP local idList = characterData.SkillIDData_Table -- ↓从updateGroup里删除掉SceneReplace为LuaConst.SkillSceneReplaceType.None的updateData, 以及从SkillDataList里删除掉SceneReplace为LuaConst.SkillSceneReplaceType.None的skillData local count = #list for k = count, 1, -1 do local v = list[k] local skillData = self.Entity:GetSkillData(v.ID) local belongToSkillData = self.Entity:GetSkillData(skillData.BelongTo) if belongToSkillData.Type == LuaConst.SkillType.MusouAttack and belongToSkillData.KeyPosition == LuaConst.ESkillKeyPosition.MusouNormal and belongToSkillData.SceneReplace == LuaConst.SkillSceneReplaceType.None then table.remove(list, k) group[skillData.BelongTo] = nil end end -- ↑ -- ↓ 把SceneReplace匹配的技能的updateData添加到updateGroup里, 以及SkillData添加到SkillDataList里 for k,v in ipairs(idList) do local skillData = self.Entity:GetSkillData(v.ID) local belongToSkillData = self.Entity:GetSkillData(skillData.BelongTo) if belongToSkillData.Type == LuaConst.SkillType.MusouAttack and belongToSkillData.KeyPosition == LuaConst.ESkillKeyPosition.MusouNormal and belongToSkillData.SceneReplace == sceneReplaceType then local isExist = false for i,_existSkill in ipairs(list) do if _existSkill.ID == skillData.ID then isExist = true break end end if not isExist then table.insert(list,skillData) end if group[skillData.BelongTo] == nil then group[skillData.BelongTo] = RuntimeDataManager.New_SkillUpdate() end self:TryInitSkillCount(group, skillData) --new -- old↓ -- if self:IsChargeSkill(skillData) then -- 设置充能技能的能量是满的 -- if skillData.ParamInt1 > 0 then -- group[skillData.BelongTo].ChargeCount = skillData.ParamInt1 -- end -- end -- old end end -- ↑ --此时list内的SkillData已经被替换过,所以需要用新的list来刷新self.AutoFightSkillDataList和animDistance self:RecalculateAutoFightSkillDataListAndAnimDistance(list) end function SkillBaseComponent:RecalculateAutoFightSkillDataListAndAnimDistance(skillDataList) table.clear(self.AutoFightSkillDataList) for k,skillData in ipairs(skillDataList) do --自动战斗优先级为0,则不能自动释放 ;KeyPosition小于0,则为技能的后续段 if (skillData.AutoBattleOrder > 0 and skillData.KeyPosition > 0) then if self.AutoFightSkillDataList[1] == nil then table.insert(self.AutoFightSkillDataList,skillData) else local inserted = false for pos,sd in ipairs(self.AutoFightSkillDataList) do if skillData.AutoBattleOrder > sd.AutoBattleOrder then table.insert(self.AutoFightSkillDataList,pos,skillData) inserted = true break end end if not inserted then table.insert(self.AutoFightSkillDataList,skillData) end end end private.HandleAnimDistance(self.Entity,skillData) end end function SkillBaseComponent:SetCurSkillResource() if self.CurSkillData then self.CurSkillResourcePath = self.Entity.components.replace:GetReplaceSkillPath(self.CurSkillData.ID, self.CurSkillData.SkillResource) else self.CurSkillResourcePath = nil end end function SkillBaseComponent:GetCurSkillResource() return self.CurSkillResourcePath end function SkillBaseComponent:SetSearchTargetWhenSkill(val) self.IsSearchTargetWhenSkill = val end -- 技能初始化完毕后,添加的技能装饰功能 function SkillBaseComponent:RefreshSkillDecorators() ---SkillIDData_Table = {s1, s2, s3, s4, s5, s6, s7} -- 不变 ---replaceSkillIDDataTable = {[4]=s51} ---CurSkillDataList = {s1, s2, s3, s6, s7} --将现有的技能装饰不启用 self:CallAllSkillDecoratorFunc("SetEnable", false) local count = #self.SkillIDData_Table for index = 1, count do local skillData = self:GetSkillDataBySkillIndex(index) if skillData and self.CurModelSkillIDs[skillData.ID] and #skillData.Decorator_Table > 0 then local skillID = skillData.ID if self.DecoratorDic and self.DecoratorDic[skillID] then --已经初始化过了,则不再创建新的了,启用即可 self:CallSkillDecoratorFuncBySkillID(skillID, "SetEnable", true) else for i,decorator in ipairs(skillData.Decorator_Table) do self:AddSkillDecorator(skillData.ID, decorator.DecoratorType, decorator.DecoratorParam) end end end end end function SkillBaseComponent:AddSkillDecorator(skillID, type, decoratorParam, overrideParamTable) local decoratorClass = SystemManager.GetSkillDecoratorByType(type) local newSkillDecorator if overrideParamTable then -- 这部分代码不要写成 overrideParamTable and unpack(overrideParamTable) or decoratorClass.StringParamToFormat(decoratorParam) ,否则参数只有一个 newSkillDecorator = decoratorClass:new(self.Entity, skillID, unpack(overrideParamTable) or decoratorClass.StringParamToFormat(decoratorParam)) else newSkillDecorator = decoratorClass:new(self.Entity, skillID, decoratorClass.StringParamToFormat(decoratorParam)) end if self.DecoratorDic == nil then self.DecoratorDic = {[skillID] = {newSkillDecorator}} else local decoratorList = self.DecoratorDic[skillID] if decoratorList == nil then self.DecoratorDic[skillID] = {newSkillDecorator} else local find = false for _, decorator in ipairs(decoratorList) do if decorator.type == type then find = true break end end if find then logging.error(LTAG.ERROR, " [gws] : 添加技能额外功能时,发现此技能已有这功能。 skillID =", skillID, " skillDecoratorType =",type) return else table.insert(decoratorList, newSkillDecorator) end end end if self.DecoratorList == nil then self.DecoratorList = {newSkillDecorator} else table.insert(self.DecoratorList, newSkillDecorator) end end -- 调用技能装饰(额外功能)中的方法 function SkillBaseComponent:CallSkillDecoratorFuncBySkillID(skillID, funcName, ...) if self.DecoratorDic then local decoratorList = self.DecoratorDic[skillID] if decoratorList then for _,decorator in ipairs(decoratorList) do if decorator[funcName] then decorator[funcName](decorator, ...) end end end end end function SkillBaseComponent:CallAllSkillDecoratorFunc(funcName, ...) if self.DecoratorList then local decoratorList = self.DecoratorList for _,decorator in ipairs(decoratorList) do if decorator[funcName] then decorator[funcName](decorator, ...) end end end end function SkillBaseComponent:SetCanUseCastSkill(val) self.CanUseCastSkill = val end -- 重写技能摇杆的数据 skillId : 技能ID也是技能摇杆的唯一key值 function SkillBaseComponent:OverrideSkillJoyStickData(skillId, paramName, val) local isSuccess, skillJoyData = DataSheetManager.SkillJoyStickData:TryGetDataByID(skillId) if isSuccess then if self.skillJoyStickOverrideDic[skillId] == nil then self.skillJoyStickOverrideDic[skillId] = { } end self.skillJoyStickOverrideDic[skillId][paramName] = val else logging.error(LTAG.ERROR, "[战斗策划]:注意修改技能摇杆数据时,发现次技能本身就没摇杆数据, skillId = ", skillId) end end -- 获得技能摇杆的重写数据 function SkillBaseComponent:GetSkillJoyStickOverrideData(skillId, paramName) local overrideData = self.skillJoyStickOverrideDic[skillId] return overrideData and overrideData[paramName] end -- 替换自动战斗数据列表的数据 function SkillBaseComponent:RecalculateAutoFightSkillData(newSkillData) for k,skillData in ipairs(self.AutoFightSkillDataList) do --自动战斗优先级为0,则不能自动释放 ;KeyPosition小于0,则为技能的后续段 if skillData.ID == newSkillData.ID then self.AutoFightSkillDataList[k] = newSkillData break end end end -- 替换一些skilldata的数据后,需要刷新初始换的缓存值 -- 不放在 OnOverrideSkillDataCell中的原因:需要等这个技能的全部字段都修改完后再刷新 function SkillBaseComponent:RefreshSkillInitCache(skillId) --这是从 SetCurrentSkillDataList 中抄写的部分逻辑,如果以后策划有修改一些特殊子弹,需要再拿一些逻辑过来 local skillData = self.Entity:GetSkillData(skillId) local groupDic for c,gDic in pairs(self.AllUpdateDataGroup) do if gDic[skillData.BelongTo] then groupDic = gDic break end end self:TryInitSkillCount(groupDic, skillData) self:RecalculateAutoFightSkillData(skillData) private.HandleAnimDistance(self.Entity, skillData) end return SkillBaseComponent