Files
Main/Assets/GameAssets/Resources/Lua/Logic/PlayerSkill/PlayerSkillSystem.lua
2025-01-25 04:38:09 +08:00

717 lines
22 KiB
Lua

------------------------------------------------
--作者: 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