263 lines
9.0 KiB
Lua
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;
|