306 lines
10 KiB
Lua
306 lines
10 KiB
Lua
|
---@class SoldierBase
|
|||
|
---@field Init fun() 初始化兵种信息
|
|||
|
---@field PlayerKey PlayerKey 拥有者的玩家 Key
|
|||
|
---@field Skills table<int32, EBuffType> 拥有的技能
|
|||
|
---@field Features table<ESpecialType, float> 拥有的特性
|
|||
|
---@field SetPlayerKey fun(InPlayerKey:PlayerKey) 设置玩家 Key
|
|||
|
---@field StartPlay fun() 正式开始游戏
|
|||
|
---@field EnableFeature fun(IsEnable:bool) 启用特性
|
|||
|
---@field TriggerSkill fun(InSkillId: EBuffType|nil, ...:vararg) 执行技能
|
|||
|
---@field StopTriggerSkill fun(InSkillId: EBuffType|nil) 停止执行 Skill
|
|||
|
---@field Tick fun(DeltaTime: float) 每帧执行
|
|||
|
---@field HasActiveSkill fun() 是否有主动技能
|
|||
|
|
|||
|
|
|||
|
---@class SoldierBuffInfo
|
|||
|
---@field StartTime float 当前使用的开始时间
|
|||
|
---@field EndTime float 当前使用的开始时间
|
|||
|
---@field IsDefault bool 是否是被动技能
|
|||
|
---@field BuffId int32 当前执行的 Buff ID
|
|||
|
|
|||
|
require('Script.Global.Table.SoldierConfig')
|
|||
|
require('Script.Global.Table.ItemTable')
|
|||
|
-- 兵种类型基类
|
|||
|
local SoldierBase = {
|
|||
|
---@type PlayerKey
|
|||
|
PlayerKey = nil;
|
|||
|
|
|||
|
---@type table<int32, EBuffType>
|
|||
|
Skills = { };
|
|||
|
|
|||
|
---@type table<ESpecialType, float> 当前的特性
|
|||
|
Features = {
|
|||
|
[SoldierConfig.ESpecialType.Health ] = 1, -- 生命
|
|||
|
[SoldierConfig.ESpecialType.Damage ] = 1, -- 伤害
|
|||
|
[SoldierConfig.ESpecialType.Speed ] = 1, -- 移速
|
|||
|
[SoldierConfig.ESpecialType.Poison ] = 1, -- 毒杀
|
|||
|
[SoldierConfig.ESpecialType.Defence ] = 1, -- 防御值
|
|||
|
};
|
|||
|
|
|||
|
---@type ESoldierType 当前的兵种类型
|
|||
|
SoldierType = 0;
|
|||
|
|
|||
|
---@type table<EBuffType, SoldierBuffInfo> 下一次可以使用 Buff 的时间,包含可以使用的 Buff
|
|||
|
BuffInfo = { };
|
|||
|
};
|
|||
|
|
|||
|
--- 初始化,分为客户端和服务器,仅在最开始的时候设置一次;在设置兵种的时候进行初始化
|
|||
|
---@param InPlayerKey PlayerKey
|
|||
|
function SoldierBase:Init(InPlayerKey, InSoldierType)
|
|||
|
|
|||
|
self.PlayerKey = InPlayerKey;
|
|||
|
self.SoldierType = InSoldierType;
|
|||
|
|
|||
|
if UGCGameSystem.IsServer() then
|
|||
|
-- 检查当前数值是否都是 1,如果不是,就改变
|
|||
|
local Feature = SoldierConfig.Features[self.SoldierType]
|
|||
|
for i, v in pairs(SoldierConfig.ESpecialType) do
|
|||
|
if Feature[v] ~= nil then self.Features[v] = Feature[v]; end
|
|||
|
end
|
|||
|
|
|||
|
self:CheckSoldierType();
|
|||
|
self:SendRPC(false, "Init", self.PlayerKey, self.SoldierType);
|
|||
|
else
|
|||
|
-- 执行对应操作
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 检查兵种是否有可执行的技能,如果有,立刻执行;没有就返回
|
|||
|
function SoldierBase:CheckSoldierType(InBuffInfo, InSkill)
|
|||
|
if self:HasAuthority() then
|
|||
|
self.BuffInfo = {};
|
|||
|
self.Skills = {};
|
|||
|
-- 检查是否含有被动
|
|||
|
local Config = SoldierConfig.Skills[self.SoldierType];
|
|||
|
if table.isEmpty(Config) then return; end
|
|||
|
|
|||
|
local Skills = {};
|
|||
|
local CurrTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState);
|
|||
|
|
|||
|
for i, v in pairs(Config.Skills) do
|
|||
|
self.Skills[#self.Skills + 1] = v.BuffType;
|
|||
|
self.BuffInfo[v.BuffType] = {
|
|||
|
StartTime = CurrTime;
|
|||
|
EndTime = CurrTime;
|
|||
|
IsDefault = v.Cooldown == nil;
|
|||
|
BuffId = nil; -- 之后填充
|
|||
|
};
|
|||
|
if v.Cooldown == nil then
|
|||
|
self:TriggerSkill();
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
UGCLogSystem.LogTree("[SoldierBase:CheckSoldierType] self.BuffInfo = self.SoldierType = " .. tostring(self.SoldierType), self.BuffInfo);
|
|||
|
|
|||
|
-- 发送到客户端
|
|||
|
self:SendRPC(false, "CheckSoldierType", self.BuffInfo, self.Skills);
|
|||
|
else
|
|||
|
-- 如果没有的话通知没有技能,就不显示技能图标了
|
|||
|
self.BuffInfo = InBuffInfo;
|
|||
|
self.Skills = InSkill;
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
-- 正式开始游戏
|
|||
|
function SoldierBase:StartPlay()
|
|||
|
if UGCGameSystem.IsServer() then self:EnableFeature(true); end
|
|||
|
end
|
|||
|
|
|||
|
--- S & C
|
|||
|
function SoldierBase:HasSkill()
|
|||
|
return not table.isEmpty(self.BuffInfo);
|
|||
|
end
|
|||
|
|
|||
|
--- 执行对应的技能
|
|||
|
--- S
|
|||
|
---@param InSkillId EBuffType|nil|table<EBuffType>
|
|||
|
---@vararg any|nil 传入技能是否会被改变的参数
|
|||
|
function SoldierBase:TriggerSkill(InSkillId, ...)
|
|||
|
if table.isEmpty(self.Skills) then return false; end
|
|||
|
-- 检查是否存在当前技能
|
|||
|
local UseSkills = {};
|
|||
|
if InSkillId == nil then
|
|||
|
UseSkills = self.Skills;
|
|||
|
else
|
|||
|
if not table.hasValue(InSkillId) then return false; end
|
|||
|
UseSkills[#UseSkills + 1] = InSkillId;
|
|||
|
end
|
|||
|
|
|||
|
-- 开始执行
|
|||
|
local CanUseBuffs = {};
|
|||
|
local CurrTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState);
|
|||
|
|
|||
|
for Index, BuffType in pairs(UseSkills) do
|
|||
|
local Info = self.BuffInfo[BuffType];
|
|||
|
if Info.EndTime <= CurrTime then
|
|||
|
CanUseBuffs[#CanUseBuffs + 1] = BuffType;
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
if table.isEmpty(CanUseBuffs) then
|
|||
|
UGCLogSystem.Log("[SoldierBase:TriggerSkill] 可以使用的时间还未到。");
|
|||
|
return CanUseBuffs;
|
|||
|
end
|
|||
|
|
|||
|
local ConfigSkills = SoldierConfig.Skills[self.SoldierType];
|
|||
|
if table.isEmpty(ConfigSkills) then return CanUseBuffs; end
|
|||
|
|
|||
|
-- 依次执行技能
|
|||
|
for Index, BuffType in pairs(CanUseBuffs) do
|
|||
|
-- 检查是否有参数,先使用默认参数
|
|||
|
for i, v in pairs(ConfigSkills.Skills) do
|
|||
|
if BuffType ~= v.BuffType then return; end
|
|||
|
local BuffManager = BP_BuffManager.GetBuffManager();
|
|||
|
local IsSucceed, BuffId = BuffManager:AddBuff(BuffType, self.PlayerKey, BuffType, table.unpackTable(v.Params));
|
|||
|
|
|||
|
if IsSucceed == BP_BuffManager.EResult.Succeed then
|
|||
|
self.BuffInfo[BuffType].BuffId = BuffId;
|
|||
|
if v.Cooldown == nil then
|
|||
|
self.BuffInfo[BuffType].IsDefault = true;
|
|||
|
else
|
|||
|
self.BuffInfo[BuffType].IsDefault = false;
|
|||
|
local ContinueTime = 0;
|
|||
|
if v.ContinueTime ~= nil and v.ContinueTime > 0 then
|
|||
|
ContinueTime = v.ContinueTime
|
|||
|
BuffManager:SetBuffDuration(BuffId, ContinueTime);
|
|||
|
end
|
|||
|
|
|||
|
if v.Cooldown > 0 then
|
|||
|
self.BuffInfo[BuffType].StartTime = CurrTime;
|
|||
|
CurrTime = CurrTime + v.Cooldown + ContinueTime
|
|||
|
self.BuffInfo[BuffType].EndTime = CurrTime;
|
|||
|
end
|
|||
|
end
|
|||
|
self:PostTriggerSkill(BuffType, self.BuffInfo[BuffType]);
|
|||
|
-- 发送通知
|
|||
|
else
|
|||
|
UGCLogSystem.LogError("[SoldierBase:TriggerSkill] 当前 %d:没有启动 BUFF: %d,报错信息:%s", self.PlayerKey, BuffType, IsSucceed);
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 触发技能之后执行的,子类进行继承,可以实现不同效果,父类默认发送给自身
|
|||
|
function SoldierBase:PostTriggerSkill(InBuffType, InBuffInfo)
|
|||
|
local CurrTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState);
|
|||
|
UGCGameSystem.GameState:ClientSendEvent(nil, EventTypes.PlayerUseBuff, self.PlayerKey, InBuffType, InBuffInfo, CurrTime);
|
|||
|
UGCLogSystem.Log("[SoldierBase:PostTriggerSkill] PlayerKey = %s", tostring(self.PlayerKey));
|
|||
|
self:SendRPC(true, "Client_TriggerSkill", self.PlayerKey, InBuffType, InBuffInfo);
|
|||
|
end
|
|||
|
|
|||
|
---@param InPlayerKey PlayerKey
|
|||
|
---@param InBuffType EBuffType
|
|||
|
---@param InBuffInfo table<EBuffType, SoldierBuffInfo>
|
|||
|
function SoldierBase:Client_TriggerSkill(InPlayerKey, InBuffType, InBuffInfo)
|
|||
|
-- 通知所有客户端xxx的xxx技能已经执行了
|
|||
|
UGCLogSystem.Log("[SoldierBase:Client_TriggerSkill] %s 客户端触发技能:%s", tostring(InPlayerKey), tostring(InBuffType));
|
|||
|
end
|
|||
|
|
|||
|
--- 停止执行技能
|
|||
|
---@param InSkillId EBuffType|nil 传入对应
|
|||
|
function SoldierBase:StopTriggerSkill(InSkillId)
|
|||
|
-- 直接移除即可
|
|||
|
local BuffManager = BP_BuffManager.GetBuffManager();
|
|||
|
local CurrTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState);
|
|||
|
if self.BuffInfo[InSkillId] == nil then return; end
|
|||
|
if self.BuffInfo[InSkillId].EndTime < CurrTime then
|
|||
|
BuffManager:RemoveBuffDuration(self.BuffInfo[InSkillId].BuffId);
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 启用特性
|
|||
|
--- S
|
|||
|
---@param IsEnable bool
|
|||
|
function SoldierBase:EnableFeature(IsEnable)
|
|||
|
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey);
|
|||
|
for i, v in pairs(self.Features) do
|
|||
|
if i == SoldierConfig.ESpecialType.Health then
|
|||
|
UGCPawnAttrSystem.SetHealthMax(Pawn, UGCPawnAttrSystem.GetHealthMax(Pawn) * v);
|
|||
|
UGCPawnAttrSystem.SetHealth(Pawn, UGCPawnAttrSystem.GetHealthMax(Pawn));
|
|||
|
elseif i == SoldierConfig.ESpecialType.Speed then
|
|||
|
UGCPawnAttrSystem.SetSpeedScale(Pawn, UGCPawnAttrSystem.GetSpeedScale(self) * v);
|
|||
|
elseif i == SoldierConfig.ESpecialType.Strong then
|
|||
|
-- 设置对应数据即可
|
|||
|
Pawn:SetParam('Strong', Pawn:GetParam('Strong') * v);
|
|||
|
elseif i == SoldierConfig.ESpecialType.Defence then
|
|||
|
Pawn:SetParam('Defence', Pawn:GetParam('Defence') * v);
|
|||
|
elseif i == SoldierConfig.ESpecialType.Poison then
|
|||
|
-- 设置毒圈属性
|
|||
|
Pawn:SetParam('PoisonDefence', Pawn:GetParam('PoisonDefence') * v);
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 停止特性
|
|||
|
--- S
|
|||
|
function SoldierBase:UnEnableFeature()
|
|||
|
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey);
|
|||
|
for i, v in pairs(self.Features) do
|
|||
|
if i == SoldierConfig.ESpecialType.Health then
|
|||
|
UGCPawnAttrSystem.SetHealthMax(Pawn, UGCPawnAttrSystem.GetHealthMax(Pawn) / v);
|
|||
|
UGCPawnAttrSystem.SetHealth(Pawn, UGCPawnAttrSystem.GetHealthMax(Pawn));
|
|||
|
elseif i == SoldierConfig.ESpecialType.Speed then
|
|||
|
UGCPawnAttrSystem.SetSpeedScale(Pawn, UGCPawnAttrSystem.GetSpeedScale(self) / v);
|
|||
|
elseif i == SoldierConfig.ESpecialType.Strong then
|
|||
|
-- 设置对应数据即可
|
|||
|
Pawn:SetParam('Strong', Pawn:GetParam('Strong') / v);
|
|||
|
elseif i == SoldierConfig.ESpecialType.Defence then
|
|||
|
Pawn:SetParam('Defence', Pawn:GetParam('Defence') / v); -- 永久改变
|
|||
|
elseif i == SoldierConfig.ESpecialType.Poison then
|
|||
|
-- 设置毒
|
|||
|
Pawn:SetParam('PoisonDefence', Pawn:GetParam('PoisonDefence') / v);
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 判断当前是否是服务器
|
|||
|
function SoldierBase:HasAuthority() return UGCGameSystem.IsServer(); end
|
|||
|
|
|||
|
---@param IsMulti bool 是否是 mrpc
|
|||
|
---@param FuncName string 函数名称
|
|||
|
function SoldierBase:SendRPC(IsMulti, FuncName, ...)
|
|||
|
UGCGameSystem.GameState:SendSoldierRPC(IsMulti, FuncName, self.PlayerKey, self.SoldierType, ...)
|
|||
|
end
|
|||
|
|
|||
|
--- tick 函数
|
|||
|
---@param DeltaTime float
|
|||
|
function SoldierBase:Tick(DeltaTime) end
|
|||
|
|
|||
|
--- 获取兵种类型
|
|||
|
---@return ESoldierType
|
|||
|
function SoldierBase:GetSoldierType()
|
|||
|
return self.SoldierType;
|
|||
|
end
|
|||
|
|
|||
|
--- 重置兵种信息
|
|||
|
function SoldierBase:RestSoldier()
|
|||
|
local Curr = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState);
|
|||
|
for i, v in pairs(self.BuffInfo) do
|
|||
|
if v.BuffId ~= nil then
|
|||
|
-- 销毁
|
|||
|
self:StopTriggerSkill(v.BuffId);
|
|||
|
end
|
|||
|
|
|||
|
v.EndTime = Curr;
|
|||
|
v.StartTime = Curr;
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
--- 是否有主动技能
|
|||
|
function SoldierBase:HasActiveSkill()
|
|||
|
UGCLogSystem.LogTree("[SoldierBase:HasActiveSkill] self.BuffInfo = ", self.BuffInfo);
|
|||
|
for i, v in pairs(self.BuffInfo) do
|
|||
|
if v.IsDefault == false then
|
|||
|
return true;
|
|||
|
end
|
|||
|
end
|
|||
|
return false;
|
|||
|
end
|
|||
|
|
|||
|
function SoldierBase:new()
|
|||
|
local newObj = SoldierBase
|
|||
|
self.__index = self;
|
|||
|
return setmetatable(newObj, self);
|
|||
|
end
|
|||
|
|
|||
|
return SoldierBase;
|