------------------------------------------------ --作者: yangqf --日期: 2021-03-26 --文件: PlayerSkillSystem.lua --模块: PlayerSkillSystem --描述: 玩家技能系统 ------------------------------------------------ local L_PlayerSkill = require "Logic.PlayerSkill.PlayerSkill" local L_PlayerSkillCell = require "Logic.PlayerSkill.PlayerSkillCell" local MAX_CELL_COUNT = 5 local MAX_POS_COUNT = 9 local PlayerSkillSystem = { --格子等级 CellLevel = 0, --是否已经初始化了格子数据 IsInitSkillPos = false, --技能位置数据,存储技能所在的格子 SkillPoss = {}, --技能自动释放数据,存储技能自动释放数据 SkillUseState = {}, --经脉激活数据 MeridianDic = Dictionary:New(), --经脉对应的主动技能 MeridianAddSkillDic = nil, --当前选择的心法id CurSelectMerId = 0, --职业心法对应的普攻技能列表 NormalSkillCfg = Dictionary:New(), --当前重置心法的次数 CurResetMerCount = 0, --当前公共CD PublicCD = 0, --当前总公共CD PublicMaxCD = 0, --当前技能列表 SkillList = nil, --技能格子数据 SkillCell = nil, --已经激活的被动技能列表 ActivePassSkills = nil, --当前变身技能列表 ChangeSkillList = nil, --当前的飞剑技能 FlySwordSkill = nil, --经脉激活数量 MeridianCount = 0, --飞剑技能释放自动释放 SkillSwordUseState = false, } function PlayerSkillSystem:Initialize() self.PublicCD = 0 self.SkillCell = Dictionary:New() self.SkillList = List:New() self.ActivePassSkills = List:New() self.ChangeSkillList = List:New() self.NormalSkillCfg:Clear() local _gCfg = DataConfig.DataGlobal[GlobalName.meridian_special_skill] if _gCfg ~= nil then local _gParams = Utils.SplitStrByTableS(_gCfg.Params, {';', '_'}) for i = 1, #_gParams do local _occ = _gParams[i][1] local _merId = _gParams[i][2] local _skillList = List:New() for j = 3, #_gParams[i] do _skillList:Add(_gParams[i][j]) end local _occDic = self.NormalSkillCfg[_occ] if _occDic == nil then _occDic = Dictionary:New() self.NormalSkillCfg:Add(_occ, _occDic) end _occDic:Add(_merId, _skillList) end end for i = 0, MAX_POS_COUNT - 1 do self.SkillPoss[i] = -1 end GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_BEGIN_SKILLCD, self.OnBegionSkillCD, self) GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_END_SKILLCD, self.OEndSkillCD, self) GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_ON_USED_SKILL, self.OnUseSkillCallBack, self) GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_SET_CHANGEMODEL_SKILL, self.OnSetChangeModelSkill, self) GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_CLEAR_CHANGEMODEL_SKILL, self.OnClearChangeModelSkill, self) GameCenter.RegFixEventHandle(LogicEventDefine.EID_EVENT_SETAUTOUSE_FLYSWORD_SKILL, self.OnSetSkillSwordUseState, self) end function PlayerSkillSystem:UnInitialize() GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_BEGIN_SKILLCD, self.OnBegionSkillCD, self) GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_END_SKILLCD, self.OEndSkillCD, self) GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_ON_USED_SKILL, self.OnUseSkillCallBack, self) GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_SET_CHANGEMODEL_SKILL, self.OnSetChangeModelSkill, self) GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_CLEAR_CHANGEMODEL_SKILL, self.OnClearChangeModelSkill, self) GameCenter.UnRegFixEventHandle(LogicEventDefine.EID_EVENT_SETAUTOUSE_FLYSWORD_SKILL, self.OnSetSkillSwordUseState, self) end --技能总等级 function PlayerSkillSystem:GetOverallLevel() return self.CellLevel end function PlayerSkillSystem:OnBegionSkillCD(obj, sender) self:BegionCD(obj) end function PlayerSkillSystem:OEndSkillCD(obj, sender) self:EndCD(obj) end function PlayerSkillSystem:OnUseSkillCallBack(obj, sender) self:OnUsedSkill(obj) end function PlayerSkillSystem:OnSetChangeModelSkill(obj, sender) local _changeCfg = DataConfig.DataChangeModel[obj] if _changeCfg ~= nil then local _changeSkills = Utils.SplitNumber(_changeCfg.Skill, '_') self:SetChangeModelSkill(_changeSkills) end end function PlayerSkillSystem:OnClearChangeModelSkill(obj, sender) self:ClearChangeModelSkill() end function PlayerSkillSystem:OnSetSkillSwordUseState(b, sender) if self.SkillSwordUseState ~= b then self.SkillSwordUseState = b self:SavePosData() end end function PlayerSkillSystem:GetMandateSkillList() local _result = List:New() local _lp = GameCenter.GameSceneSystem:GetLocalPlayer() if _lp == nil then return _result end if _lp.IsChangeModel then --变身状态,使用变身技能列表 for i = 1, #self.ChangeSkillList do _result:Add(self.ChangeSkillList[i].CfgID) end else --添加技能 for i = 1, MAX_POS_COUNT - 1 do if self.SkillUseState[i] then local _skillCell = self:GetSkillPosCell(i) if _skillCell ~= nil then for j = 1, _skillCell.SkillCount do _result:Add(_skillCell.SkillList[j].CfgID) end end end end if self.SkillSwordUseState and GameCenter.MapLogicSwitch.AutoUseXPSkill then if self.FlySwordSkill ~= nil then _result:Add(self.FlySwordSkill.CfgID) end end --添加普攻 local _skillCell = self:GetSkillPosCell(0) if _skillCell ~= nil then for j = 1, _skillCell.SkillCount do _result:Add(_skillCell.SkillList[j].CfgID) end end end return _result end function PlayerSkillSystem:SkillIsSyncServer(skillId) local _skill = self:FindSkill(skillId) if _skill == nil then return false end return _skill.IsSync end function PlayerSkillSystem:SkillIsCD(skillId) local _skill = self:FindSkill(skillId) if _skill == nil then return true end return _skill:IsCDing() end function PlayerSkillSystem:CanUseSkill(skillId) local _skill = self:FindSkill(skillId) if _skill == nil then return false end local _cfg = DataConfig.DataSkill[skillId] if _cfg == nil then return false end local _occ = GameCenter.GameSceneSystem:GetLocalPlayer().Occ --是否是属于角色的技能 local _occRight = false if _cfg.UserType == SkillClass.None then _occRight = true elseif _cfg.UserType == SkillClass.XianJian and _occ == Occupation.XianJian then _occRight = true elseif _cfg.UserType == SkillClass.MoQiang and _occ == Occupation.MoQiang then _occRight = true elseif _cfg.UserType == SkillClass.DiZang and _occ == Occupation.DiZang then _occRight = true elseif _cfg.UserType == SkillClass.LuoCha and _occ == Occupation.LuoCha then _occRight = true else _occRight = false end if not _occRight then return false end --技能CD判断 if _skill:IsCDing() then return false end --公CD判断 if _skill.UsePublicCD and self.PublicCD > 0 then return false end return true end --获取技能格子数据 function PlayerSkillSystem:GetSkillCell(cellId) return self.SkillCell[cellId] end --获取技能位置数据 function PlayerSkillSystem:GetSkillPosCell(posId) if posId >= 0 and posId < MAX_POS_COUNT then return self:GetSkillCell(self.SkillPoss[posId]) end return nil end --获取此位置装备的技能索引 function PlayerSkillSystem:GetSkillPosCellValue(posId) if posId >= 0 and posId < MAX_POS_COUNT then return self.SkillPoss[posId] end return -1 end --获取格子等级 function PlayerSkillSystem:GetCellLevel() return self.CellLevel end function PlayerSkillSystem:FindSkill(skillId) for i = 1, #self.SkillList do if self.SkillList[i].CfgID == skillId then return self.SkillList[i] end end for i = 1, #self.ChangeSkillList do if self.ChangeSkillList[i].CfgID == skillId then return self.ChangeSkillList[i] end end if self.FlySwordSkill ~= nil and self.FlySwordSkill.CfgID == skillId then return self.FlySwordSkill end return nil end function PlayerSkillSystem:Update(dt) if self.PublicCD > 0 then self.PublicCD = self.PublicCD - dt end for _, v in pairs(self.SkillCell) do v:Update(dt) end if self.ChangeSkillList ~= nil then for i = 1, #self.ChangeSkillList do self.ChangeSkillList[i]:Update(dt) end end if self.FlySwordSkill ~= nil then self.FlySwordSkill:Update(dt) end end function PlayerSkillSystem:BegionCD(skillID) local _instSkill = self:FindSkill(skillID) if _instSkill ~= nil then if _instSkill.UsePublicCD and _instSkill.PubilcCD > 0 then self.PublicCD = _instSkill.PubilcCD self.PublicMaxCD = self.PublicCD else self.PublicCD = _instSkill.VisualInfo.FrameCount / 30 self.PublicMaxCD = self.PublicCD end _instSkill:BeginCD() end end function PlayerSkillSystem:EndCD(skillID) local _instSkill = self:FindSkill(skillID) if _instSkill ~= nil then _instSkill:EndCD() end end function PlayerSkillSystem:OnUsedSkill(skillId) for _, v in pairs(self.SkillCell) do v:OnUseSkill(skillId) end if self.FlySwordSkill ~= nil and skillId == self.FlySwordSkill.CfgID then --触发使用飞剑技能 local _lf = GameCenter.GameSceneSystem:GetLocalFlySword() if _lf ~= nil then _lf:UseSkill() end end end --是否激活了被动技能 function PlayerSkillSystem:IsPassSkillActived(id) return self.ActivePassSkills:Contains(id) end --设置变身技能 function PlayerSkillSystem:SetChangeModelSkill(skills) self.ChangeSkillList:Clear() for i = 1, #skills do local _skillCfg = DataConfig.DataSkill[skills[i]] if _skillCfg ~= nil then self.ChangeSkillList:Add(L_PlayerSkill:New(_skillCfg, true)) end end end --清除变身技能 function PlayerSkillSystem:ClearChangeModelSkill() self.ChangeSkillList:Clear() end --设置飞剑技能 function PlayerSkillSystem:SetFlySwordSkill(flySwordSkill, playerSkill) local _oldSkillCD = 0 if self.FlySwordSkill ~= nil then _oldSkillCD = self.FlySwordSkill.CurCD end self.FlySwordSkill = nil if flySwordSkill == nil or playerSkill == nil then return end self.FlySwordSkill = L_PlayerSkill:NewSwordSkill(flySwordSkill, playerSkill, _oldSkillCD) --重置了飞剑技能,重新开始挂机 GameCenter.MandateSystem:ReStart() end --设置技能位置数据 function PlayerSkillSystem:SetSkillPos(posId, skillOder) if posId >= 0 and posId < MAX_POS_COUNT then --交换位置 local _oldPos = -1 for i = 0, MAX_POS_COUNT - 1 do if self.SkillPoss[i] == skillOder then _oldPos = i break end end if _oldPos >= 0 then local _tmpOder = self.SkillPoss[posId] self.SkillPoss[posId] = skillOder self.SkillPoss[_oldPos] = _tmpOder else self.SkillPoss[posId] = skillOder end self:SavePosData() self:CheckRedPoint() --重新开始挂机 GameCenter.MandateSystem:ReStart() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SKILL_LIST_CHANGED) end end --技能是否已经装配 function PlayerSkillSystem:SkillIsEquip(oderValue) for i = 0, MAX_POS_COUNT - 1 do if self.SkillPoss[i] == oderValue then return true end end return false end --获取某个类型的天赋总等级 function PlayerSkillSystem:GetMeridianTypeLevel(type) local _allLevel = 0 for k, v in pairs(self.MeridianDic) do local _typeId = math.floor(v % 1000000 / 10000) if _typeId == type then _allLevel = _allLevel + math.floor(v % 100) end end return _allLevel end --获取某个天赋的激活id function PlayerSkillSystem:GetMeridianActvieID(id) local _result = self.MeridianDic[id] if _result == nil then _result = 0 end return _result end --获取技能是否自动释放 function PlayerSkillSystem:IsAutoUse(posId) if posId >= 0 and posId < MAX_POS_COUNT then return self.SkillUseState[posId] end return false end --设置技能是否自动释放 function PlayerSkillSystem:SetAutoUse(posId, value) if posId >= 0 and posId < MAX_POS_COUNT then self.SkillUseState[posId] = value end end --上线数据 function PlayerSkillSystem:ResSkillOnline(result) self.SkillCell:Clear() --当前心法id self.CurSelectMerId = result.selectMentalType self.CurResetMerCount = result.resetMentalTimes local _occ = GameCenter.GameSceneSystem:GetLocalPlayer().Occ for i = 1, #result.skillIds do local _cfg = DataConfig.DataSkillStarLevelup[result.skillIds[i]] if _cfg ~= nil then local _cellId = math.floor(_cfg.Id % 1000000 / 1000) local _skillList = nil if _cellId == 0 then --普攻特殊处理 local _occDic = self.NormalSkillCfg[_occ] if _occDic ~= nil then _skillList = _occDic[self.CurSelectMerId] end end self.SkillCell:Add(_cellId, L_PlayerSkillCell:New(_cfg, _skillList)) end end self.CellLevel = result.cellLevel if self.CellLevel == nil then self.CellLevel = 1 end self.MeridianDic:Clear() self.MeridianCount = 0 if result.skillMeridianList ~= nil then for i = 1, #result.skillMeridianList do local _id = result.skillMeridianList[i] local _meId = math.floor(_id % 10000 / 100) self.MeridianDic:Add(_meId, _id) self.MeridianCount = self.MeridianCount + 1 end end --初始化位置数据 self:ParsePosData(result.playedSkillStr) self:FillSkillList() self:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SKILL_LIST_CHANGED) GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_SKILL_ONLINE) end --升级格子 function PlayerSkillSystem:ResUpCell(result) self.CellLevel = result.level self:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_SKILL_UPCELL) end --技能升星 function PlayerSkillSystem:ResUpSkillStar(result) local _cfg = DataConfig.DataSkillStarLevelup[result.newSkillID] if _cfg == nil then return end local _cellId = math.floor(_cfg.Id % 1000000 / 1000) local _skillCell = L_PlayerSkillCell:New(_cfg) self.SkillCell[_cellId] = _skillCell local _emptyIndex = nil for i = 0, MAX_POS_COUNT - 1 do if self.SkillPoss[i] == -1 and _emptyIndex == nil then _emptyIndex = i end if self.SkillPoss[i] == _cellId then _emptyIndex = nil break end end if _emptyIndex ~= nil then --新学技能自动放入空位 self.SkillPoss[_emptyIndex] = _cellId self:SavePosData() end self:FillSkillList() self:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SKILL_LIST_CHANGED) GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_SKILL_UPSTAR) --技能获得效果 for i = 1, _skillCell.SkillCount do GameCenter.BlockingUpPromptSystem:AddNewFunction(PromptNewFunctionType.Skill, _skillCell.SkillList[i].CfgID) end end --被动技能列表 function PlayerSkillSystem:ResPassiveSkill(result) self.ActivePassSkills:Clear() if result.skillID ~= nil then for i = 1, #result.skillID do self.ActivePassSkills:Add(result.skillID[i]) end end end --更新被动技能 function PlayerSkillSystem:ResUpdateSkill(result) if result.type == 0 then --增加 if not self.ActivePassSkills:Contains(result.skillID) then self.ActivePassSkills:Add(result.skillID) GameCenter.BlockingUpPromptSystem:AddNewFunction(PromptNewFunctionType.Skill, result.skillID) end elseif result.type == 1 then --删除 self.ActivePassSkills:Remove(result.skillID) end end --经脉更新 function PlayerSkillSystem:ResActivateMeridian(result) local _id = result.meridianID local _meId = math.floor(_id % 10000 / 100) self.MeridianDic[_meId] = _id self.MeridianCount = self.MeridianDic:Count() self:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_SKILL_UPMERIDIAN) end --选择心法返回 function PlayerSkillSystem:ResSelectMentalType(result) self.CurSelectMerId = result.mentalType self.CurResetMerCount = result.resetMentalTimes local _occ = GameCenter.GameSceneSystem:GetLocalPlayer().Occ if self.CurSelectMerId == 0 then if self.MeridianAddSkillDic == nil then --初始化经脉对应技能的数据 self.MeridianAddSkillDic = GameCenter.PlayerSkillLuaSystem:GetAddSkillTable() end local _savePos = false for k, v in pairs(self.MeridianDic) do local _skillId = self.MeridianAddSkillDic[v] if _skillId ~= nil then local _cellId = math.floor(_skillId % 1000000 / 1000) --移除技能 self.SkillCell:Remove(_cellId) for i = 0, MAX_POS_COUNT - 1 do if self.SkillPoss[i] == _cellId then _savePos = true self.SkillPoss[i] = -1 break end end end end self.MeridianDic:Clear() self.MeridianCount = self.MeridianDic:Count() if _savePos then self:SavePosData() end end --重新选择普攻 local _occDic = self.NormalSkillCfg[_occ] local _skillList = nil if _occDic ~= nil then _skillList = _occDic[self.CurSelectMerId] end local _cfg = self.SkillCell[0].Cfg self.SkillCell[0] = L_PlayerSkillCell:New(_cfg, _skillList) self:FillSkillList() self:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SKILL_LIST_CHANGED) GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_SKILL_UPMERIDIAN) --心法改变消息 GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_PLAYER_XINFA_CHANGED) --重新开始挂机 GameCenter.MandateSystem:ReStart() if self.CurSelectMerId == 0 then --重置经脉 GameCenter.PushFixEvent(UIEventDefine.UIOccSkillForm_Close) else --关闭选择心法 GameCenter.PushFixEvent(UILuaEventDefine.UISelectXinFaForm_CLOSE) --打开经脉界面 GameCenter.MainFunctionSystem:DoFunctionCallBack(FunctionStartIdCode.PlayerSkillMeridian) end end --解析技能位置数据 function PlayerSkillSystem:ParsePosData(posText) self.IsInitSkillPos = true local _setNormal = true if posText ~= nil and string.len(posText) > 0 and GameCenter.MainFunctionSystem:FunctionIsEnabled(FunctionStartIdCode.PlayerSkillPos) then local _pramsArray = Utils.SplitStrByTableS(posText, {';', '_'}) if #_pramsArray >= 2 then local _posParams = _pramsArray[1] if #_posParams >= MAX_POS_COUNT then for i = 1, MAX_POS_COUNT do local _cellId = _posParams[i] self.SkillPoss[i - 1] = _cellId end end local _useParams = _pramsArray[2] if #_useParams >= MAX_POS_COUNT then for i = 1, MAX_POS_COUNT do local _state = _useParams[i] if _state == 0 then self.SkillUseState[i - 1] = false else self.SkillUseState[i - 1] = true end end end if #_useParams >= MAX_POS_COUNT + 1 then local _state = _useParams[MAX_POS_COUNT + 1] if _state == 0 then self.SkillSwordUseState = false else self.SkillSwordUseState = true end end _setNormal = false end end if _setNormal then --设置为默认值 for i = 0, MAX_POS_COUNT - 1 do if i <= 4 then self.SkillPoss[i] = i else self.SkillPoss[i] = -1 end self.SkillUseState[i] = true end self.SkillSwordUseState = false self:SavePosData() end end --保存技能位置数据 function PlayerSkillSystem:SavePosData() if not self.IsInitSkillPos then return end local _posText = "" for i = 0, MAX_POS_COUNT - 1 do if i < MAX_POS_COUNT - 1 then _posText = _posText .. string.format("%d_", self.SkillPoss[i]) else _posText = _posText .. string.format("%d", self.SkillPoss[i]) end end _posText = _posText .. ';' for i = 0, MAX_POS_COUNT - 1 do local _value = 0 if self.SkillUseState[i] then _value = 1 end _posText = _posText .. string.format("%d_", _value) end if self.SkillSwordUseState then _posText = _posText .. '1' else _posText = _posText .. '0' end GameCenter.Network.Send("MSG_Skill.ReqSaveFightSkill", {playedSkillStr = _posText}) end --填充技能列表 function PlayerSkillSystem:FillSkillList() local _starVisible = false self.SkillList:Clear() for k, v in pairs(self.SkillCell) do v:FillSkillList(self.SkillList) if k ~= 0 then _starVisible = true end end GameCenter.MainFunctionSystem:SetFunctionVisible(FunctionStartIdCode.PlayerSkillStar, _starVisible) end --检测红点 function PlayerSkillSystem:CheckRedPoint() GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_CHECK_SKILL_REDPOINT) end return PlayerSkillSystem