---@class SkillSystemComponent local SkillSystemComponent = LuaClass("SkillSystemComponent") SkillSystemComponent.OwnerChatacter = nil --- 存储所有玩家拥有过的技能实例 ---@type table SkillSystemComponent.SkillsMap = {} --- 记录技能与槽位间的匹配信息 ---@type table SkillSystemComponent.SlotToSkillList = {} function SkillSystemComponent:ctor(OwnerActor) self.Owner = OwnerActor end function SkillSystemComponent:OnTick(DeltaTime) --- Skill的Tick for _, SimpleSkill in pairs(self.SlotToSkillList) do if SimpleSkill ~= nil then SimpleSkill:OnTick(DeltaTime) end end end ------------------------------------------------ Skill 相关 ------------------------------------------------ ---@param SkillNameList ESkillName[] function SkillSystemComponent:GiveSkillWithList(SkillNameList) for k, SkillName in pairs(SkillNameList) do self:GiveSkill(SkillName) end end ---@param SkillName ESkillName ---@param SkillSlot ESkillSlot ---@param SkillLevel int ---@return SkillItemID function SkillSystemComponent:GiveSkill(SkillName, SkillSlot, SkillLevel) if not UGCGameSystem.IsServer() then UE.Log("[SkillSystemComponent:GiveSkill] 未在服务端调用") return -1 end local SkillDat = GameDataManager.GetSkillData(SkillName) if SkillDat == nil then UE.Log("[SkillSystemComponent:GiveSkill] 配置表中无此技能: %s", tostring(SkillName)) return -1 end if SkillSlot == nil then local AvaliableSlot = self:GetSkillAvaliableSlot(SkillDat.SkillAccess) if AvaliableSlot == nil then UE.Log("[SkillSystemComponent:GiveSkill] 无可用技能插槽,需指定") return -1 else SkillSlot = AvaliableSlot end elseif SkillSlot < ESkillSlot.Slot0 or SkillSlot > ESkillSlot.Slot4 then UE.Log("[SkillSystemComponent:GiveSkill] 技能插槽非法: %s", tostring(SkillSlot)) return -1 end ---无指定技能等级则默认为1级技能 if SkillLevel == nil or SkillLevel <= 0 then SkillLevel = 1 end ---验证是否有相同的技能,即名字相同且等级相同,此时插槽视为无效 local OwnedSkills = self.SkillsMap[SkillName] if OwnedSkills ~= nil and table.getCount(OwnedSkills) > 0 then for _, SimpleSkill in pairs(OwnedSkills) do if SimpleSkill.SkillLevel == SkillLevel then UE.Log("[SkillSystemComponent:GiveSkill] 相同技能已存在: Skill=%d, Level=%d", SkillName, SkillLevel) return -1 end end end for Slot, SkillInfo in pairs(self.Owner.Controller.ActiveSkillNameList) do if SkillInfo.SkillName == SkillName then if Slot == SkillSlot then if SkillLevel ~= SkillInfo.SkillLevel then ---同名技能若在同一插槽且等级不同,则进行替换操作 local CurSkill = self.SlotToSkillList[Slot] local CurSkillItemID = CurSkill:GetSkillItemID() CurSkill:SetSkillLevel(SkillLevel) self.Owner.Controller.ActiveSkillNameList[Slot] = {SkillName = SkillName, SkillLevel = SkillLevel} UnrealNetwork.CallUnrealRPC(self.Owner.Controller, self.Owner.Controller, "ClientRPC_SetupSkillButton", SkillName, SkillSlot, SkillLevel) --TODO:后期还需加上等级 UE.Log("[SkillSystemComponent:GiveSkill] 更新技能slot=%d", SkillSlot) ---返回已有技能的ID return CurSkillItemID else ---同名技能不在同一插槽且等级不同,则进行普通添加技能流程 end end end end local CurSkillItemID = 0 local CurSkill = self:GetSkillBySlot(SkillSlot) if CurSkill ~= nil then CurSkillItemID = CurSkill:GetSkillItemID() self:RemoveSkillBySlot(SkillSlot) --TODO:移除流程 end -- 新的技能实例 local SimpleSkill = require("Script.SimpleSkill.SimpleSkill") local Skill = SimpleSkill.New(self.Owner) Skill.SkillName = SkillName Skill:SetSkillLevel(SkillLevel) Skill:InitConfig(SkillDat) self:AddSkillToMap(SkillName, Skill) self.SlotToSkillList[SkillSlot] = Skill --将Slot-SkillName对应关系写入PlayerController self.Owner.Controller.ActiveSkillNameList[SkillSlot] = {SkillName = SkillName, SkillLevel = SkillLevel} UnrealNetwork.CallUnrealRPC(self.Owner.Controller, self.Owner.Controller, "ClientRPC_SetupSkillButton", SkillName, SkillSlot, SkillLevel) UnrealNetwork.CallUnrealRPC(self.Owner.Controller, self.Owner.Controller, "ClientRPC_SetSkillCD", SkillSlot, 0.1) UE.Log("[SkillSystemComponent:GiveSkill] AddSimpleSkill OwnerPawn:%d SkillName:%d", self.Owner.PlayerKey, SkillName) return CurSkillItemID end ---@param SkillAccessType ESkillAccessType function SkillSystemComponent:GetSkillAvaliableSlot(SkillAccessType) if SkillAccessType == ESkillAccessType.Acquired then for i = ESkillSlot.Slot1, ESkillSlot.Slot3 do if self:GetSkillBySlot(i) == nil then return i end end elseif SkillAccessType == ESkillAccessType.Talented then return ESkillSlot.Slot0 elseif SkillAccessType == ESkillAccessType.BuiltIn then return ESkillSlot.Slot4 end return nil end ---@param SkillSlot ESkillSlot ---@return SimpleSkill function SkillSystemComponent:GetSkillBySlot(SkillSlot) return self.SlotToSkillList[SkillSlot] end ---@param SkillName ESkillName ---@param SimpleSkill SimpleSkill function SkillSystemComponent:AddSkillToMap(SkillName, SimpleSkill) if self.SkillsMap[SkillName] == nil then self.SkillsMap[SkillName] = {} end table.insert(self.SkillsMap[SkillName], SimpleSkill) end ---@param SimpleSkill SimpleSkill function SkillSystemComponent:RemoveSkill(SimpleSkill) if SimpleSkill == nil then UE.Log("[SkillSystemComponent:RemoveSkill] invalid Skill!") return -1 end SimpleSkill:EndSkill() for SkillName, Skills in pairs(self.SkillsMap) do for index, SkillInst in pairs(Skills) do if SkillInst == SimpleSkill then self.SkillsMap[SkillName][index] = nil break end end end for Slot, SkillInst in pairs(self.SlotToSkillList) do if SkillInst == SimpleSkill then self.SlotToSkillList[Slot] = nil end end local RemovedSkillItemID = SimpleSkill:GetSkillItemID() SimpleSkill = nil UE.Log("[SkillSystemComponent:RemoveSkillBySlot] Remove Success!") return RemovedSkillItemID end ---@param SkillName ESkillName function SkillSystemComponent:RemoveSkillBySlot(SkillSlot) local CurSkill = self.SlotToSkillList[SkillSlot] if CurSkill == nil then UE.Log("[SkillSystemComponent:RemoveSkillBySlot] invalid SkillSlot! OwnerPawn:%d SkillSlot:%d", self.Owner.PlayerKey, SkillSlot) return -1 end local RemovedSkillItemID = CurSkill:GetSkillItemID() CurSkill:EndSkill() for SkillName, Skills in pairs(self.SkillsMap) do for index, SkillInst in pairs(Skills) do if SkillInst == CurSkill then self.SkillsMap[SkillName][index] = nil break end end end self.SlotToSkillList[SkillSlot] = nil UE.Log("[SkillSystemComponent:RemoveSkillBySlot] RemoveSimpleSkill OwnerPawn:%d SkillSlot:%d", self.Owner.PlayerKey, SkillSlot) return RemovedSkillItemID end function SkillSystemComponent:RemoveAllSkill() for _, SimpleSkill in pairs(self.SlotToSkillList) do SimpleSkill:EndSkill() end self.SkillsMap = nil self.SlotToSkillList = nil end ---@param SkillSlot ESkillSlot function SkillSystemComponent:TryActiveSkillBySlot(SkillSlot) local SkillInst = self.SlotToSkillList[SkillSlot] if SkillInst == nil then UE.Log("[SkillSystemComponent:TryActiveSkillBySlot] invalid SkillSlot[%d]", SkillSlot) return end if not SkillInst:IsReadyToCastSkill() then UE.Log("[SkillSystemComponent:TryActiveSkillBySlot] Skill[%d] is not ready", SkillInst.SkillName) return end UnrealNetwork.CallUnrealRPC(self.Owner.Controller, self.Owner.Controller, "ClientRPC_SetSkillCD", SkillSlot, SkillInst.CoolDownDuration) SkillInst:CastSkill() UE.Log("[SkillSystemComponent:TryActiveSkillBySlot] ActiveSimpleSkill SkillSlot:%d, SkillName:%d", SkillSlot, SkillInst.SkillName) end --- 外部传入技能目标 ---@param SkillName ESkillName ---@param TargetPawnsList UGCPlayerPawn[] function SkillSystemComponent:SetTargetPawnsToSkill(SkillName, TargetPawnsList) local CurSkill = self.SkillsMap[SkillName] if SkillName ~= nil and CurSkill ~= nil then CurSkill.TargetActors = {} CurSkill.TargetPawns = TargetPawnsList end end return SkillSystemComponent;