UGCProjects/GZJ/Script/SimpleSkill/SkillSystemComponent.lua
2025-01-08 22:46:12 +08:00

263 lines
9.0 KiB
Lua

---@class SkillSystemComponent
local SkillSystemComponent = LuaClass("SkillSystemComponent")
SkillSystemComponent.OwnerChatacter = nil
--- 存储所有玩家拥有过的技能实例
---@type table<ESkillName, SimpleSkill[]>
SkillSystemComponent.SkillsMap = {}
--- 记录技能与槽位间的匹配信息
---@type table<ESkillSlot, SimpleSkill>
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;