2025-01-04 23:00:19 +08:00

1307 lines
43 KiB
Lua

---@class UGCGameState_C:BP_UGCGameState_C
---@field VehicleClass UClass
---@field ShootWeaponClass UClass
--Edit Below--
UGCGameSystem.UGCRequire('Script.Common.ue_enum_custom')
require('Script.Global.Global')
---@type UGCGameState_C
local UGCGameState = {
CountDownTime = 0.;
ProcessState = 0;
---@type table<PlayerKey, ESoldierType> 队伍兵种类型
PlayerSoldierType = {};
---@type table<PlayerKey, table<TechnologyType, uint32>> 玩家的分数
PlayerScores = {};
---@type table<PlayerKey, ELevelType> 玩家选择的地图
PlayerSelectLevels = {};
---@type table<int32, PlayerDamageItem> 玩家造成的伤害
PlayerDamage = {};
---@type table<int32, ItemId> { [RoundTime] = TeamId } 哪局是哪个队伍赢了
GameRounds = {};
---@type int32 赢取的队伍ID
WinTeamId = -1;
CachedInit = {};
---@type table<int32, table<int32, PlayerKey>> 存在的玩家
ExistPlayerKeys = {};
};
---@type table<PlayerKey, ArchiveData> 玩家的存档数据
UGCGameState.PlayerArchives = {};
--- @type table<PlayerKey, PlayerAccountInfo>
UGCGameState.PlayerAccountInfoMap = {};
---@type table<PlayerKey, PlayerKDAItem>
UGCGameState.TotalPlayerKDA = {};
---@type table<int, table<int, PlayerKey>> { TeamId: { PlayerKey, PlayerKey, ... } }
UGCGameState.PlayerTeams = {};
UGCGameState.ServerTime = 0;
UGCGameState.ServerTimeDiff = 0;
-- 游戏回合相关数据
UGCGameState.RoundInfo = {
-- 当前回合次数
CurrRoundTime = 0;
-- 当前回合状态
RoundState = RoundState.Prepare;
RoundCountTime = 0.;
RoundSettleCountTime = 0.;
};
function UGCGameState:ReceiveBeginPlay()
UGCGameState.SuperClass.ReceiveBeginPlay(self);
self:SetProcessState(EventTypes.GameProcessStates.Prepare);
GlobalInit.InitGlobalVar();
self.bIsOpenShovelingAbility = true
UGCSendRPCSystem.InitUGCSendRPCSystem(self, "UGCSendRPCSystemFunc");
if not self:HasAuthority() then
LocalPlayerController = STExtraGameplayStatics.GetFirstPlayerController(self);
LocalPlayerKey = LocalPlayerController.PlayerKey;
UGCEventSystem.AddListener(EventTypes.PlayerUseBuff, self.OnPlayerUseBuff, self)
end
-- 在游戏开始的时候加载一下 BP_BuffManager
require('Script.Blueprint.BUFF.BP_BuffManager');
if self:HasAuthority() then
local Manager = BP_BuffManager.GetBuffManager();
Manager:Init(function(InPlayerKey, InPlayerKeyList, InBuffType)
self:ClientSendEvent(nil, EventTypes.SkillBenefit, InPlayerKey, InPlayerKeyList, InBuffType);
end);
self.ServerTime = 1;
DOREPONCE(self, "ServerTime");
end
end
function UGCGameState:ReceiveTick(DeltaTime)
self.SuperClass.ReceiveTick(self, DeltaTime);
GlobalTickTool:ReceiveTick(DeltaTime, self:GetServerTime());
end
function UGCGameState:GetReplicatedProperties()
return
"PlayerSoldierType",
{ "CountDownTime", "Lazy" },
{ "PlayerAccountInfoMap", "Lazy" },
{ "PlayerArchives", "Lazy" },
{ "ProcessState", "Lazy" },
{ "PlayerTeams", "Lazy" },
{ "TotalPlayerKDA", "Lazy" },
{ "PlayerSelectLevels", "Lazy" },
{ "PlayerScores", "Lazy" },
{ "PlayerDamage", "Lazy" },
{ "WinTeamId", "Lazy" },
{ "GameRounds", "Lazy" },
{ "RoundInfo", "Lazy" },
{ "ServerTime", "Lazy" },
{ "SelectMapIndex", "Lazy" }
end
function UGCGameState:GetAvailableServerRPCs()
return "RPCDelegationFunc",
"UGCSendRPCSystemFunc",
"CheckServerTime",
"Server_SelectMap"
end
function UGCGameState:UGCSendRPCSystemFunc(...) UGCSendRPCSystem.RPCFunc(...) end
function UGCGameState:OnRep_CountDownTime() UGCEventSystem.SendEvent(EventTypes.UpdateWaitingTime, self.CountDownTime); end
function UGCGameState:OnRep_ProcessState() UGCEventSystem:SendEvent(EventTypes.ChangeProcessState, self.ProcessState); end
function UGCGameState:OnRep_PlayerAccountInfoMap()
if table.isEmpty(self.PlayerAccountInfoMap) then return ; end
UGCEventSystem.SendEvent(EventTypes.UpdatePlayerAccountInfo, self.PlayerAccountInfoMap);
end
-- 同步队伍信息
function UGCGameState:OnRep_PlayerTeams()
if table.getCount(self.PlayerTeams) == 0 then return ; end
UGCEventSystem.SendEvent(EventTypes.UpdateNewTeams, self.PlayerTeams);
-- 获取本地 PlayerKey
if LocalPlayerKey == nil then return ; end
for TeamId, PlayerKeys in pairs(self.PlayerTeams) do
for i, PlayerKey in pairs(PlayerKeys) do
if PlayerKey == LocalPlayerKey then
DefaultSettings.LocalTeamId = TeamId;
break ;
end
end
end
for i, v in pairs(self.PlayerTeams) do
if i ~= DefaultSettings.LocalTeamId and i ~= -1 then
DefaultSettings.EnemyTeamId = i;
break ;
end
end
if DefaultSettings.LocalTeamId == nil then return ; end
local LocalKeys = self.PlayerTeams[DefaultSettings.LocalTeamId];
end
function UGCGameState:OnRep_PlayerSoldierType()
-- 同步一下
if table.isEmpty(self.PlayerSoldierType) then return ; end
-- 检查客户端是否存在
UGCEventSystem.SendEvent(EventTypes.SelectSoldierType, self.PlayerSoldierType);
local Type = self.PlayerSoldierType[LocalPlayerKey];
if Type == nil then return ; end
if LocalPlayerController:GetSoldierBase(Type) == nil then
LocalPlayerController:AddSoldierBase(Type);
end
end
function UGCGameState:OnRep_PlayerSelectLevels()
if table.isEmpty(self.PlayerSelectLevels) then return ; end
UGCEventSystem.SendEvent(EventTypes.UpdateSelectLevels, self.PlayerSelectLevels);
end
function UGCGameState:OnRep_TotalPlayerKDA()
-- 同步 KDA
if LocalPlayerKey == nil or table.isEmpty(self.TotalPlayerKDA) then return ; end
-- 更新玩家的 KDA 信息
UGCEventSystem.SendEvent(EventTypes.UpdatePlayerKDA, self.TotalPlayerKDA);
UGCLogSystem.LogTree("[UGCGameState:OnRep_PlayerKDA] TotalPlayerKDA = ", self.TotalPlayerKDA)
end
function UGCGameState:OnRep_PlayerArchives(OldArchive)
if table.isEmpty(self.PlayerArchives) then return ; end
-- 判断是否有自己的存档
if LocalPlayerKey == nil then return ; end
local OldData = nil
if OldArchive ~= nil then OldData = OldArchive[LocalPlayerKey] end
local LocalArchiveData = self.PlayerArchives[LocalPlayerKey];
if OldData == nil and LocalArchiveData ~= nil then
UGCLogSystem.LogTree(string.format("[UGCGameState:OnRep_PlayerArchives] LocalArchiveData ="), LocalArchiveData)
if self.RoundInfo.RoundState == RoundState.Prepare then
WidgetManager:ShowPanel(WidgetConfig.EUIType.SelectSoldier, false);
if DefaultSettings.EnableLevels then
WidgetManager:ShowPanel(WidgetConfig.EUIType.SelectMap, false);
end
end
if LocalArchiveData ~= nil and LocalArchiveData.LoginTimes ~= nil and LocalArchiveData.LoginTimes <= 3 and not DefaultSettings.HadShowFaceNotice then
DefaultSettings.HadShowFaceNotice = true;
WidgetManager:ShowPanel(WidgetConfig.EUIType.FaceNotice, false);
end
end
UGCEventSystem.SendEvent(EventTypes.UpdatePlayerArchive, LocalArchiveData);
end
function UGCGameState:OnRep_GameRounds()
if table.isEmpty(self.GameRounds) then return ; end
UGCEventSystem.SendEvent(EventTypes.UpdateGameRound, self.GameRounds);
self.CachedGameRounds = self.GameRounds;
end
---------------------------------- 时间 ----------------------------------
function UGCGameState:OnRep_ServerTime()
-- 接收到之后就立刻发送 RPC 到服务器,或者也可以等一会
if self.ServerTime == 1 then
if LocalPlayerKey == nil or LocalPlayerController == nil then
UGCEventSystem.SetTimer(self, function()
self:CheckServerTime(LocalPlayerKey, UE.GetCurrentTime())
end, 1.);
return
end
self:CheckServerTime(LocalPlayerKey, UE.GetCurrentTime())
elseif self.ServerTime == 0 then
else
local Diff = self.ServerTime - UE.GetCurrentTime();
UGCLogSystem.Log("[UGCGameState:CheckClientTime] Diff = %f", Diff)
self:OnClientAlready();
end
end
function UGCGameState:CheckServerTime(InPlayerKey, InTime)
if UGCGameSystem.IsServer() then
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey)
UnrealNetwork.CallUnrealRPC(PC, self, "CheckClientTime", UE.GetCurrentTime());
self:OnClientAlready();
else
UnrealNetwork.CallUnrealRPC(LocalPlayerController, self, "CheckServerTime", InPlayerKey, InTime);
end
end
function UGCGameState:CheckClientTime(InTime)
self.ServerTimeDiff = InTime - UE.GetCurrentTime();
UGCLogSystem.Log("[UGCGameState:CheckClientTime] self.ServerTimeDiff = %f", self.ServerTimeDiff);
self:OnClientAlready();
end
UGCGameState.bInitOnce = false;
function UGCGameState:OnClientAlready()
if self.bInitOnce then return end
UGCEventSystem.SendEvent(EventTypes.ClientAlready)
local ServerTime = self:GetServerTime();
UGCLogSystem.Log("[UGCGameState:OnClientAlready] 执行 ServerTime = %f", ServerTime);
self.bInitOnce = true;
end
--- S & C : 获取服务器时间
---@return float|nil
function UGCGameState:GetServerTime()
if UGCGameSystem.IsServer() then
return UE.GetCurrentTime();
else
if self.ServerTimeDiff == 0 then
return nil;
else
return self.ServerTimeDiff + UE.GetCurrentTime();
end
end
end
----------------------------------
---@param InKey PlayerKey
---@param InData PlayerAccountInfo
function UGCGameState:LoadAccountInfo(InKey, InData)
self.PlayerAccountInfoMap[InKey] = InData;
DOREPONCE(self, "PlayerAccountInfoMap");
end
--- 初始化存档信息
function UGCGameState:InitArchiveData()
local Table = {
-- 登录次数
LoginTimes = 1;
-- 不同兵种选择
SoldierSelect = {};
-- 分数
Scores = {};
-- 已经解锁的类型
UnlockTypes = {};
};
for i, v in pairs(SoldierConfig.InitShowTypes) do Table.UnlockTypes[i] = v; end
return Table;
end
---@param InKey PlayerKey
---@param InData ArchiveData
function UGCGameState:LoadArchiveData(InKey, InData)
if InData == nil or table.getCount(InData) == 0 then
InData = self:InitArchiveData();
else
if type(InData.LoginTimes) == 'number' then
InData.LoginTimes = InData.LoginTimes + 1;
end
end
self.PlayerArchives[InKey] = InData;
self:CheckUnlockType(InKey);
DOREPONCE(self, "PlayerArchives");
end
---@param InKey PlayerKey
function UGCGameState:CheckUnlockType(InKey)
local Scores = self.PlayerArchives[InKey].Scores;
local UnlockTypes = self.PlayerArchives[InKey].UnlockTypes;
local Total = 0;
if not table.isEmpty(Scores) then
for ScoreType, Count in pairs(Scores) do Total = Total + Count; end
end
for i, v in pairs(SoldierConfig.UnlockScore) do
if Total >= v.Score then
if not UnlockTypes[i] then self.PlayerArchives[InKey].UnlockTypes[i] = true; end
end
end
end
---@return PlayerKDAItem
function UGCGameState:InitPlayerKda()
return {
Kill = 0,
Dead = 0,
Assist = 0,
};
end
--- 更新玩家的 KDA
function UGCGameState:UpdateKDA(InPlayerKey, KillerPlayerKey)
if self.TotalPlayerKDA[InPlayerKey] then
self.TotalPlayerKDA[InPlayerKey].Dead = (self.TotalPlayerKDA[InPlayerKey].Dead or 0) + 1;
end
if self.TotalPlayerKDA[KillerPlayerKey] then
self.TotalPlayerKDA[KillerPlayerKey].Kill = (self.TotalPlayerKDA[KillerPlayerKey].Kill or 0) + 1;
end
DOREPONCE(self, "TotalPlayerKDA");
end
function UGCGameState:InitPlayerScore()
return {
[SoldierConfig.TechnologyType.Kill] = 0;
[SoldierConfig.TechnologyType.RoundWin] = 0;
[SoldierConfig.TechnologyType.Survive] = 0;
[SoldierConfig.TechnologyType.Recovery] = 0;
[SoldierConfig.TechnologyType.TrapDamage] = 0;
};
end
-- 添加玩家到队伍信息中
function UGCGameState:AddTeamPlayer(InTeamId, InKey)
if self.PlayerTeams[InTeamId] == nil then self.PlayerTeams[InTeamId] = {}; end
-- 判断当前是否有玩家
if self.PlayerDamage[InKey] ~= nil then return ; end
UGCLogSystem.Log("[UGCGameState:AddTeamPlayer] InTeamId = %d, InPlayerKey = %s", InTeamId, tostring(InKey))
table.insert(self.PlayerTeams[InTeamId], InKey)
UGCLogSystem.LogTree("[UGCGameState:AddTeamPlayer] self.PlayerTeams = ", self.PlayerTeams);
if self.PlayerScores[InKey] == nil then self.PlayerScores[InKey] = self:InitPlayerScore(); end
self.TotalPlayerKDA[InKey] = self:InitPlayerKda();
self.PlayerDamage[InKey] = 0;
-- 检查当前是否有足够的玩家
UnrealNetwork.CallUnrealRPC(self, self, "AllPlayerReady");
self:AllPlayerReady();
DOREPONCE(self, "PlayerTeams");
DOREPONCE(self, "PlayerScores");
DOREPONCE(self, "TotalPlayerKDA");
DOREPONCE(self, "PlayerDamage");
end
-- 添加Round
function UGCGameState:StartRound(InVal)
if self:HasAuthority() then
UGCLogSystem.Log("[UGCGameState:StartRound] 执行服务端")
InVal = InVal == nil and 1 or InVal
UGCEventSystem.SetTimer(self, function()
self:OnFormalStart();
end, DefaultSettings.SelectWeaponShowTime);
self.RoundInfo.CurrRoundTime = self.RoundInfo.CurrRoundTime + InVal
self.RoundInfo.RoundState = RoundState.PreRound;
if self.RoundInfo.CurrRoundTime == 1 then self:FirstRound() end
-- 通知客户端
UnrealNetwork.CallUnrealRPC_Multicast(self, "StartRound", self.RoundInfo);
DOREPONCE(self, "RoundInfo");
local PCs = UGCGameSystem.GetAllPlayerController();
for i, v in pairs(PCs) do v:OnStartRound(); end
-- 检查当前是否有武器
self:CheckPlayerHasSoldierType();
-- 重置玩家是否存活
self:StartPoison(self.SelectMapIndex);
self:LoadVehicles();
else
UGCLogSystem.Log("[UGCGameState:StartRound] 执行客户端")
if InVal.CurrRoundTime == 1 then
WidgetManager:ClosePanel(WidgetConfig.EUIType.FaceNotice);
WidgetManager:ClosePanel(WidgetConfig.EUIType.WaitingTime);
WidgetManager:ShowPanel(WidgetConfig.EUIType.Main, false);
end
WidgetManager:ClosePanel(WidgetConfig.EUIType.SelectSoldier);
WidgetManager:ClosePanel(WidgetConfig.EUIType.RoundWin);
-- 显示一下选择武器
WidgetManager:ShowPanel(WidgetConfig.EUIType.Backpack, false);
-- 显示 控制面板
local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C");
MainControlPanel:SetVisibility(ESlateVisibility.SelfHitTestInvisible);
end
end
--function UGCGameState:GetSelectMapIndex()
-- if self.PoisonManager then
-- return self.PoisonManager:GetSelectMapIndex();
-- end
-- return -1;
--end
UGCGameState.Vehicles = {};
function UGCGameState:GetShootWeaponClass()
return self.ShootWeaponClass;
end
function UGCGameState:LoadVehicles()
if not table.isEmpty(self.Vehicles) then
self:DestroyVehicles();
end
local AllActors = {};
UE.FindActorsByClass(ObjectPath.BP_ActorStart, AllActors, function(InIndex, InActor)
if InActor:ActorHasTag("Vehicle") then
if InActor.Index and not table.isEmpty(VehicleTable.Car[InActor.Index]) then
local Vehicle = UGCVehicleSystem.SpawnVehicleNew(VehicleTable.Car[InActor.Index].Path, InActor:K2_GetActorLocation(), InActor:K2_GetActorRotation(), false, false);
table.insert(self.Vehicles, Vehicle);
return true;
end
return false;
end
return false;
end)
end
function UGCGameState:DestroyVehicles()
if not table.isEmpty(self.Vehicles) then
for i, v in pairs(self.Vehicles) do
UGCVehicleSystem.DestroySelf(v);
end
end
self.Vehicles = {};
end
function UGCGameState:FirstRound()
if self:HasAuthority() then
-- 同步一下
local PCs = UGCGameSystem.GetAllPlayerController();
for i, v in pairs(PCs) do
if UE.IsValid(v) then v:AddSoldierBase(self.PlayerSoldierType[v.PlayerKey]); end
end
end
end
function UGCGameState:FirstFormalStart()
end
--- 正式开始游戏
function UGCGameState:OnFormalStart()
UGCLogSystem.Log("[UGCGameState:OnFormalStart] 执行")
if UGCGameSystem.IsServer() then
self:CheckHasWeapons();
UnrealNetwork.CallUnrealRPC_Multicast(self, "OnFormalStart");
-- 开始打架
self.RoundInfo.RoundState = RoundState.InRound;
-- 所有玩家装上武器
local PCs = UGCGameSystem.GetAllPlayerController(false);
-- 检查是否存在属性
for i, v in pairs(PCs) do v:OnFormalStart(); end
-- 保存一下当前载具的位置,然后之后就重置到该位置
self:ResetGameState();
if self.RoundInfo.CurrRoundTime == 1 then self:FirstFormalStart(); end
-- 检查一下是否有人,
local IsAloneTeam, TeamId = self:CheckExistPlayers();
if IsAloneTeam then self:GotoGameEnd(TeamId) end
DOREPONCE(self, "RoundInfo")
else
local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C");
MainControlPanel:SetVisibility(ESlateVisibility.SelfHitTestInvisible);
end
end
function UGCGameState:CheckHasSoldier()
-- 检查是否有兵种,没有兵种给一个兵种
UGCLogSystem.Log("[UGCGameState:CheckHasSoldier] 开始检查是否有兵种")
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
if self.PlayerSoldierType[v.PlayerKey] == nil then
self.PlayerSoldierType[v.PlayerKey] = math.random(table.getCount(SoldierConfig.ESoldierType));
end
end
UGCLogSystem.LogTree(string.format("[UGCGameState:CheckHasSoldier] self.PlayerSoldierType ="), self.PlayerSoldierType)
end
--- 强制检查是否有枪,没有枪直接添加
function UGCGameState:CheckHasWeapons()
UGCLogSystem.Log("[UGCGameState:CheckHasWeapons] 开始检查是否有武器")
self:CheckHasSoldier();
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(v.PlayerKey);
if Pawn ~= nil and UE.IsValid(Pawn) and Pawn:IsAlive() then
v:CheckHasWeapon();
end
end
end
function UGCGameState:UpdateRoundTime(InTime)
UGCLogSystem.Log("[UGCGameState:UpdateRoundTime] 执行,%s", tostring(InTime));
if InTime == nil then
LuaQuickFireEvent('RoundSettle', self);
else
-- 刷新时间
self.RoundInfo.RoundCountTime = InTime;
DOREPONCE(self, "RoundInfo");
local Time = math.floor(DefaultSettings.RoundInfo.EachRoundTime - InTime)
if Time == DefaultSettings.SelectWeaponShowTime then
UGCLogSystem.Log("[UGCGameState:UpdateRoundTime] 执行一次")
UnrealNetwork.CallUnrealRPC_Multicast(self, "Client_ShowTips", "选择武器页面即将关闭,未选择则会随机选取武器");
end
end
end
function UGCGameState:Client_ShowTips(...)
local Params = { ... };
UGCLogSystem.Log("[UGCGameState:Client_ShowTips] %s", Params[1]);
UITool.ShowTips(...);
end
-- 同步回合数据
function UGCGameState:OnRep_RoundInfo()
-- 检查当前回合状态
if self.RoundInfo == nil then return ; end
-- 说明当前正在准备回合
if self.RoundInfo.RoundState == RoundState.Prepare then return ; end
if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.Main) then
-- 显示这个
if self.RoundInfo.RoundState ~= RoundState.RoundEnd then
WidgetManager:ShowPanel(WidgetConfig.EUIType.Main, false);
-- 检查一下是否有技能
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(LocalPlayerKey);
if PC then
UGCEventSystem.SetTimer(self, function()
PC:OnStartRound(true);
end, 2)
end
end
end
UGCEventSystem.SendEvent(EventTypes.UpdateRound, self.RoundInfo);
end
function UGCGameState:StartRoundSettle(InVal)
UGCLogSystem.Log("[UGCGameState:StartRoundSettle] 执行");
if self:HasAuthority() then
-- 通知客户端结算当前小局
local PCs = UGCGameSystem.GetAllPlayerController(false);
for i, v in pairs(PCs) do
v:OnEnterRoundSettle();
end
self.RoundInfo.RoundState = RoundState.InRoundSettle;
UGCSendRPCSystem.ActorRPCNotify(nil, self, "StartRoundSettle", self.GameRounds);
DOREPONCE(self, "RoundInfo");
--self.PoisonManager:Toggle(false);
-- 检查当前是有什么
if DefaultSettings.RoundInfo.RoundNum <= self.RoundInfo.CurrRoundTime then
LuaQuickFireEvent('GameEnd', self);
end
else
-- 关闭观战
WidgetManager:ClosePanel(WidgetConfig.EUIType.Spectation);
-- 检查当前是谁赢了
if InVal == nil then return end
WidgetManager:ShowPanel(WidgetConfig.EUIType.RoundWin, false, InVal[#InVal]);
end
end
function UGCGameState:UpdateRoundSettleTime(InTime)
UGCLogSystem.Log("[UGCGameState:UpdateRoundSettleTime] 执行")
if InTime == nil then
-- 检查当前一共有多少回合,如果超出了,则退出游戏
LuaQuickFireEvent('RoundStart', self);
else
DOREPONCE(self, "RoundInfo");
end
end
-- 倒计时时间
function UGCGameState:UpdateCountDown(InTime)
if self:HasAuthority() then
self.CountDownTime = InTime;
UGCLogSystem.Log("[UGCGameState:UpdateCountDown] 执行 InTime = %s", tostring(InTime));
if InTime <= 0 then
self.CountDownTime = 0;
LuaQuickFireEvent("RoundStart", self);
elseif InTime <= 1 then
-- 提示关闭页面
UGCLogSystem.Log("[UGCGameState:UpdateCountDown] 随机给予兵种类型");
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
if self.PlayerSoldierType[v.PlayerKey] == nil then v:RandSelectSoldierType(); end
end
elseif InTime <= 2 then
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(v.PlayerKey);
if UE.IsValid(Pawn) then Pawn:K2_DestroyActor(); end
end
-- 加载
local PoisonActor = self:FindPoisonCircle();
if PoisonActor then PoisonActor:RandomSelectCenter(); end
elseif InTime <= DefaultSettings.SelectSoldierTime then
UGCLogSystem.Log("[UGCGameState:UpdateCountDown] 开始加载地图")
self:LoadSelectMap();
end
DOREPONCE(self, "CountDownTime");
end
end
--- 准备开始游戏(因为可能存在等待玩家复活等操作)
function UGCGameState:BeginGameStart()
UGCLogSystem.Log("[UGCGameState:BeginGameStart] 重置玩家");
if self:HasAuthority() then
local PCs = UGCGameSystem.GetAllPlayerController(false);
for i, v in pairs(PCs) do
if UE.IsValid(v) then v:ResetPlayer(); end
end
self:SetProcessState(EventTypes.GameProcessStates.Gaming);
UnrealNetwork.CallUnrealRPC_Multicast(self, "BeginGameStart");
end
end
function UGCGameState:ResetGameState()
end
--- 设置游戏进程
---@param InState int32
function UGCGameState:SetProcessState(InState)
self.ProcessState = InState;
DOREPONCE(self, "ProcessState");
end
function UGCGameState:OnGameEnded(InRes)
UGCLogSystem.LogTree("[UGCGameState:OnGameEnded] InRes = ", InRes);
if self:HasAuthority() then
self:SetProcessState(EventTypes.GameProcessStates.Ended);
for i, v in pairs(UGCGameSystem.GetAllPlayerPawn()) do
if UE.IsValid(v) and v:IsAlive() then
v:K2_DestroyActor();
end
end
UnrealNetwork.CallUnrealRPC_Multicast(self, "OnGameEnded", InRes);
else
WidgetManager:ClosePanel(WidgetConfig.EUIType.Main);
WidgetManager:ShowPanel(WidgetConfig.EUIType.Settlement, true, true);
end
end
function UGCGameState:GetPlayerAccountInfo(InPlayerKey) return self.PlayerAccountInfoMap[InPlayerKey]; end
--- 通过玩家Key获取玩家名字
---@param PlayerKey PlayerKey
---@return string
function UGCGameState:GetPlayerNameByPlayerKey(PlayerKey)
if self.PlayerAccountInfoMap[PlayerKey] then
return self.PlayerAccountInfoMap[PlayerKey].PlayerName;
else
return "";
end
end
--- 通过玩家Key获取玩家 Icon Path
---@param PlayerKey PlayerKey
---@return string
function UGCGameState:GetHeadIconByPlayerKey(PlayerKey)
if self.PlayerAccountInfoMap[PlayerKey] then
return self.PlayerAccountInfoMap[PlayerKey].IconURL
else
return ""
end
end
------------------------------ BUFF 相关 ------------------------------
---@param InDeadKey PlayerKey 死亡玩家的PlayerKey
---@param InKillerKey PlayerKey 击杀者的PlayerKey
function UGCGameState:Multi_PlayerDead(InDeadKey, InKillerKey)
if InDeadKey == LocalPlayerKey then
WidgetManager:ShowPanel(WidgetConfig.EUIType.Spectation, false);
end
end
---@param InPlayerKey PlayerKey
function UGCGameState:Client_PlayerUseBuff(InPlayerKey, BuffID)
UGCEventSystem.SendEvent(EventTypes.TriggerSoldier, InPlayerKey);
end
function UGCGameState:OnRep_PlayerHasBuff()
end
--- 选择兵种
---@param InPlayerKey PlayerKey 玩家 Key
---@param InType int32 类型
function UGCGameState:Server_SelectSoldier(InPlayerKey, InType)
UGCLogSystem.Log("[UGCGameState:Server_SelectSoldier] 执行 PlayerKey = %s, SoldierType = %s", tostring(InPlayerKey), tostring(InType));
-- 所有玩家选择的兵种类型
self.PlayerSoldierType[InPlayerKey] = InType;
DOREPONCE(self, "PlayerSoldierType");
end
--- S
function UGCGameState:Server_SelectMap(InPlayerKey, InType)
-- 判断当前有多少人
self.PlayerSelectLevels[InPlayerKey] = InType;
local AllPlayerSelect = true;
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
local PlayerKey = v.PlayerKey;
if self.PlayerSelectLevels[PlayerKey] == nil then
AllPlayerSelect = false;
break ;
end
end
UGCLogSystem.LogTree(string.format("[UGCGameState:Server_SelectMap] self.PlayerSelectLevels ="), self.PlayerSelectLevels)
DOREPONCE(self, "PlayerSelectLevels");
if AllPlayerSelect then
-- 检测当前时间是多少
if self.CountDownTime > DefaultSettings.SelectSoldierTime + 2 then
-- 直接进入游戏
UGCEventSystem.SendEvent(EventTypes.AllPlayerHadSelectMap, DefaultSettings.SelectSoldierTime + 2);
end
end
end
UGCGameState.SelectMapIndex = 0;
function UGCGameState:GetSelectMap() return self.SelectMapIndex; end
-- 加载地图
function UGCGameState:LoadSelectMap()
if not UGCGameSystem.IsServer() then return ; end
if self.SelectMapIndex ~= 0 then return ; end
if DefaultSettings.EnableLevels then
if table.getCount(LevelTable.LevelInfo) > 2 then
local SelectMaps = {};
-- 检查有多少个 Random
for PlayerKey, LevelType in pairs(self.PlayerSelectLevels) do
if LevelType ~= LevelTable.ELevelType.Random then
if SelectMaps[LevelType] == nil then
SelectMaps[LevelType] = 1;
else
SelectMaps[LevelType] = 1 + SelectMaps[LevelType];
end
end
end
UGCLogSystem.LogTree(string.format("[UGCGameState:LoadSelectMap] SelectMaps ="), SelectMaps)
local MapCount = table.getCount(LevelTable.ELevelType) - 1;
if table.isEmpty(SelectMaps) then
self.SelectMapIndex = math.random(1, MapCount);
else
local MaxCount = 0;
for LevelType, Count in pairs(SelectMaps) do
if Count > MaxCount then
MaxCount = Count;
self.SelectMapIndex = LevelType;
end
end
end
if self.SelectMapIndex == 0 then
for i, v in pairs(SelectMaps) do
if v >= 1 and v <= MapCount then self.SelectMapIndex = i; end
end
end
UGCLogSystem.Log("[UGCGameState:LoadSelectMap] 111 SelectMapIndex = %d", self.SelectMapIndex);
end
end
if self.SelectMapIndex <= 0 then self.SelectMapIndex = 1 end
if self.SelectMapIndex > table.getCount(LevelTable.ELevelType) - 1 then
self.SelectMapIndex = 1;
end
DOREPONCE(self, "SelectMapIndex");
UGCLogSystem.Log("[UGCGameState:LoadSelectMap] self.SelectMapIndex = %d", self.SelectMapIndex);
-- 加载一下地图
LevelStreamTool.LoadStreamLevels({ LevelTable.LevelInfo[self.SelectMapIndex].MapName }, { Object = self, Func = self.LoadMapFinish }, false);
end
function UGCGameState:OnRep_SelectMapIndex()
UGCLogSystem.Log("[UGCGameState:OnRep_SelectMapIndex] self.SelectMapIndex = %d", self.SelectMapIndex);
if self.SelectMapIndex > 0 then
-- 加载两次确保能够加载到
UGCLogSystem.Log("[UGCGameState:OnRep_SelectMapIndex] 开始加载 地图")
self:LoadNowMiniMap(self.SelectMapIndex);
UGCWidgetManagerSystem.ShowTipsUI(string.format("已选择 %s 地图", LevelTable.LevelInfo[self.SelectMapIndex].ShowName));
end
end
function UGCGameState:LoadMapFinish()
UGCLogSystem.Log("[UGCGameState:LoadMapFinish] 地图加载完成");
UGCEventSystem.SendEvent(EventTypes.MapLoadFinish)
end
-- 客户端执行
-- 加载小地图
function UGCGameState:LoadNowMiniMap(InType)
local MiniMapInfo = LevelTable.LevelInfo[InType].MiniMapInfo
if MiniMapInfo then
local bSuccess = UGCWidgetManagerSystem.ChangeMap(MiniMapInfo.MapPath, MiniMapInfo.MapCentre, MiniMapInfo.MapSize, MiniMapInfo.MapScale)
if bSuccess then
UGCLogSystem.Log("[UGCGameState:LoadNowMiniMap] 玩家加载地图成功")
else
UGCLogSystem.Log("[UGCGameState:LoadNowMiniMap] 玩家加载地图失败")
end
else
UGCLogSystem.Log("[UGCGameState:LoadNowMiniMap] 无法加载小地图 %s", tostring(InType));
end
UGCLogSystem.Log("[UGCGameState:LoadNowMiniMap] Finish")
end
-- 检查玩家是否拥有兵种类型
function UGCGameState:CheckPlayerHasSoldierType()
UGCLogSystem.Log("[UGCGameState:CheckPlayerHasWeapon] 执行")
local PCs = UGCGameSystem.GetAllPlayerController(false);
for i, v in pairs(PCs) do
if UE.IsValid(v) then
if v.SelectWeapons == nil then
v.SelectWeapons = {};
end
if table.isEmpty(v.SelectWeapons) == 0 then
-- 说明没有选择武器
-- 查看当前选择的兵种
local SoldierType = self.PlayerSoldierType[v.PlayerKey];
if SoldierType == nil then
self.PlayerSoldierType[v.PlayerKey] = math.random(1, table.getCount(SoldierConfig.ESoldierType));
end
end
end
end
end
function UGCGameState:LogoutPlayer(InPlayerKey)
-- 判断当前是否只有一队玩家了,如果只剩一队玩家那么直接获胜
local AllPlayerKeys = {};
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
table.insert(AllPlayerKeys, v.PlayerKey);
end
self:UpdateAlivePlayer(InPlayerKey, false, nil);
return table.getCount(AllPlayerKeys);
end
---@param InPlayerKey PlayerKey 造成伤害的玩家Key
---@param InDamage float 造成多少伤害
function UGCGameState:UpdateDamage(InPlayerKey, InDamage)
self.PlayerDamage[InPlayerKey] = (self.PlayerDamage[InPlayerKey] or 0) + InDamage;
DOREPONCE(self, "PlayerDamage");
end
function UGCGameState:UpdateScore(InKey, InType, InScore)
if self.PlayerScores[InKey] == nil then self.PlayerScores[InKey] = {}; end
if self.PlayerScores[InKey][InType] == nil then self.PlayerScores[InKey][InType] = 0; end
self.PlayerScores[InKey][InType] = self.PlayerScores[InKey][InType] + InScore;
-- 加载到表中
table.addTableNum(self.PlayerArchives[InKey], InType, InScore);
DOREPONCE(self, "PlayerScores");
end
--- 判断是否仅剩一个队伍
function UGCGameState:IsOneTeamAllDead(InDeadPlayerKey)
local AliveTeamIds = {};
-- 检查这个队伍是否还有人
local DeadTeamId = UGCPlayerStateSystem.GetTeamID(InDeadPlayerKey);
local PlayerList = UGCTeamSystem.GetPlayerKeysByTeamID(DeadTeamId);
UGCLogSystem.Log("[UGCGameState:IsOneTeamAllDead] DeadTeamId = %d", DeadTeamId);
UGCLogSystem.LogTree(string.format("[UGCGameState:IsOneTeamAllDead] PlayerList ="), PlayerList)
for i, v in pairs(PlayerList) do
local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(v)
if Pawn ~= nil and UE.IsValid(Pawn) and Pawn:IsAlive() then return false; end
end
UGCLogSystem.Log("[UGCGameState:IsOneTeamAllDead] 所有玩家都死亡了");
return true;
end
---@param InPlayerKey PlayerKey
---@param InIsAlive bool 玩家是否存活
function UGCGameState:UpdateAlivePlayer(InPlayerKey, InIsAlive, InKillerPlayerKey)
-- 当玩家死亡的时候:
UGCLogSystem.LogTree(string.format("[UGCGameState:UpdateAlivePlayer] self.PlayerTeams ="), self.PlayerTeams)
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] InKillerPlayerKey = %s", tostring(InKillerPlayerKey));
local IsOne = self:IsOneTeamAllDead(InPlayerKey);
if IsOne then
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] 仅剩一支队伍");
end
if not IsOne then return ; end
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] 执行")
if self.RoundInfo.RoundState == RoundState.InRound then
-- 检查一下有几支队伍,如果只有一对,那么直接获胜
-- 找到 WinnerId
local WinTeamId = nil;
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] InKillerPlayerKey = %s", tostring(InKillerPlayerKey));
if InKillerPlayerKey ~= nil and InKillerPlayerKey > 0 then
WinTeamId = UGCPlayerControllerSystem.GetTeamID(UGCGameSystem.GetPlayerControllerByPlayerKey(InKillerPlayerKey));
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] 开始查找 WinTeamId = %s", tostring(WinTeamId));
else
-- 获取还有谁,那么他们队伍获胜了
local AllPlayerPawn = {};
for i, Pawn in pairs(UGCGameSystem.GetAllPlayerPawn()) do
if Pawn ~= nil and UE.IsValid(Pawn) and Pawn:IsAlive() then
AllPlayerPawn[UGCPlayerStateSystem.GetTeamID(Pawn.PlayerKey)] = true;
end
end
-- 保证可以执行
if table.getCount(AllPlayerPawn) == 1 then
for i, v in pairs(AllPlayerPawn) do WinTeamId = i; end
end
end
UGCLogSystem.Log("[UGCGameState:UpdateAlivePlayer] WinTeamId = %d", WinTeamId);
if WinTeamId ~= nil then
table.insert(self.GameRounds, WinTeamId);
DOREPONCE(self, "GameRounds");
end
-- 发一个 RPC
UnrealNetwork.CallUnrealRPC_Multicast(self, "UpdateGameRounds", self.GameRounds);
if self.PlayerTeams[WinTeamId] ~= nil then
for i, v in pairs(self.PlayerTeams[WinTeamId]) do
self:UpdateScore(v, SoldierConfig.TechnologyType.RoundWin, 1);
end
end
if self:CheckGameRounds(WinTeamId) then return ; end
end
--- 如果没有结束游戏,则进入结算部分
self:UpdateRoundTime();
end
function UGCGameState:UpdateGameRounds(InRoundsInfo)
--获取一下
UGCLogSystem.LogTree(string.format("[UGCGameState:UpdateGameRounds] InRoundsInfo ="), InRoundsInfo)
-- 同步过去
self.CachedGameRounds = InRoundsInfo;
UGCEventSystem.SendEvent(EventTypes.UpdateGameRound, self.CachedGameRounds);
end
--- 检查游戏是否结束了,当一个队伍胜利太多就会赢取游戏
---@return bool 当前游戏是否已经结束了
function UGCGameState:CheckGameRounds(InId)
--- 先检查当前哪边赢得多,如果现在只剩下一方的人,那么这一方直接就获取胜利
local IsAloneTeam, WinTeamId = self:CheckExistPlayers();
if IsAloneTeam then
self:GotoGameEnd(InId);
return true;
end
local TeamCount = {};
for i, v in pairs(self.GameRounds) do
if TeamCount[v] == nil then
TeamCount[v] = 1;
else
TeamCount[v] = 1 + TeamCount[v];
end
end
for i, v in pairs(TeamCount) do
if v >= 4 or IsAloneTeam then
-- 说明当前可以执行
self:GotoGameEnd(i);
return true;
end
end
return false;
end
function UGCGameState:GotoGameEnd(InWinTeamId)
self.WinTeamId = InWinTeamId;
self.RoundInfo.RoundState = RoundState.RoundEnd;
-- 再一段时间后再执行
UGCEventSystem.SetTimer(self, function()
LuaQuickFireEvent("GameEnd", self)
end, DefaultSettings.RoundInfo.RoundSettleTime / 2);
-- 客户端显示出来
self:ClientShowUI(WidgetConfig.EUIType.RoundWin, self.WinTeamId)
DOREPONCE(self, "WinTeamId");
end
--- 检查存在的玩家
function UGCGameState:CheckExistPlayers()
local AllTeams = {};
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
local TeamId = UGCPlayerControllerSystem.GetTeamID(v)
if AllTeams[TeamId] == nil then AllTeams[TeamId] = {}; end
table.insert(AllTeams[TeamId], v.PlayerKey);
end
UGCLogSystem.LogTree(string.format("[UGCGameState:CheckExistPlayers] AllTeams ="), AllTeams)
if table.getCount(AllTeams) == 1 then
for i, v in pairs(AllTeams) do return true, i; end
end
return false;
end
function UGCGameState:ClientShowUI(UIType, ...)
if self:HasAuthority() then
UnrealNetwork.CallUnrealRPC_Multicast(self, "ClientShowUI", UIType, ...);
else
WidgetManager:ShowPanel(UIType, false, ...)
end
end
--- 获取本队之外的其他队的队伍ID
function UGCGameState:GetOtherTeamId(InTeamId)
for TeamId, v in pairs(self.PlayerTeams) do
if InTeamId ~= TeamId and TeamId ~= -1 then return TeamId; end
end
return -1;
end
function UGCGameState:CheckPlayerTeams()
self.PlayerTeams = {};
for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do
local TeamID = UGCPlayerControllerSystem.GetTeamID(v);
if self.PlayerTeams[TeamID] == nil then self.PlayerTeams[TeamID] = {}; end
table.insert(self.PlayerTeams[TeamID], v.PlayerKey);
end
DOREPONCE(self, "PlayerTeams");
end
---@param InTeamId TeamId|PlayerKey
function UGCGameState:GetOtherPlayerKeys(InTeamId)
if InTeamId < 1000 then
return self.PlayerTeams[self:GetOtherTeamId(InTeamId)];
end
local TeamId = self:GetPlayerTeamId(InTeamId);
return self:GetOtherPlayerKeys(TeamId);
end
--- 获取队伍的分数
---@param InTeamId int32 队伍Id
function UGCGameState:GetTeamScore(InTeamId)
local Score = 0;
for _, v in pairs(self.GameRounds) do
if v == InTeamId then Score = Score + 1; end
end
return Score;
end
---@param InTeamId TeamId 队伍Id
function UGCGameState:GetOtherTeamScore(InTeamId)
return table.getCount(self.GameRounds) - self:GetTeamScore(InTeamId);
end
--- S & C
---@return table<int32, table<int32, PlayerDamageItem>>
function UGCGameState:GetPlayerRank()
-- 区分一下左队右队
local TeamData = {};
for PlayerKey, Damage in pairs(self.PlayerDamage) do
local Info = self.TotalPlayerKDA[PlayerKey];
table.insert(TeamData, {
PlayerKey = PlayerKey,
Damage = Damage,
KDA = (Info.Kill + Info.Assist) / (Info.Dead == 0 and 1 or Info.Dead),
TeamId = self.PlayerAccountInfoMap[PlayerKey].TeamID,
});
end
table.sort(TeamData, function(a, b)
if a.KDA == b.KDA then return a.Damage > b.Damage; end
return a.KDA > b.KDA;
end);
UGCLogSystem.LogTree(string.format("[UGCGameState:GetPlayerRank] TeamData ="), TeamData)
return TeamData;
end
---@param InPlayerKey PlayerKey
function UGCGameState:GetPlayerTeamId(InPlayerKey)
return self.PlayerAccountInfoMap[InPlayerKey].TeamID;
end
--- 获取玩家当前在队伍中的排名,此时按照伤害进行排名
---@param InPlayerKey PlayerKey
---@return int32 Rank Num
function UGCGameState:GetPlayerRankByPlayerKey(InPlayerKey)
-- 对玩家进行排序
local PlayerDamages = self:GetPlayerRank();
local TeamId = self:GetPlayerTeamId(InPlayerKey);
for i, v in pairs(PlayerDamages[TeamId]) do
if v.PlayerKey == InPlayerKey then return i; end
end
return -1;
end
---@param InPlayerKey PlayerKey
---@return int32
function UGCGameState:GetPlayerDamageByPlayerKey(InPlayerKey)
for Index, Table in pairs(self.PlayerDamage) do
if Table.PlayerKey == InPlayerKey then return math.floor(Table.Damage); end
end
return 0.;
end
---@param InTeamId int
function UGCGameState:GetOtherTeamId(InTeamId)
if InTeamId == nil then return -1; end
for TeamId, PlayerList in pairs(self.PlayerTeams) do
if TeamId ~= InTeamId then return TeamId; end
end
return -1;
end
---@param InPlayerKey PlayerKey
function UGCGameState:GetOtherTeamIdByPlayerKey(InPlayerKey)
return self:GetOtherTeamId(self:GetPlayerTeamId(InPlayerKey));
end
--- 玩家当前获取的分数
---@param InPlayerKey PlayerKey
---@return int32 获取分数
function UGCGameState:GetScoreDataByPlayerKey(InPlayerKey)
local Score = self.PlayerScores[InPlayerKey];
local TotalScore = 0;
for i, v in pairs(Score) do TotalScore = TotalScore + v; end
return TotalScore;
end
--- 获取玩家的兵种类型
---@param InPlayerKey PlayerKey
function UGCGameState:GetSoldierTypeByPlayerKey(InPlayerKey)
return self.PlayerSoldierType[InPlayerKey];
end
-- 验证一下两个 ID 是否正常
function UGCGameState:CheckLocalTeamIds()
if DefaultSettings.LocalTeamId == -1 and DefaultSettings.EnemyTeamId == -1 then
DefaultSettings.LocalTeamId = self:GetPlayerTeamId(LocalPlayerKey);
end
if DefaultSettings.LocalTeamId == -1 then end
end
--- S & C
function UGCGameState:AllPlayerReady()
local BuffManager = BP_BuffManager.GetBuffManager();
BuffManager:Init()
end
---@param Enable bool
---@param TeamId TeamId
---@param BuffType EBuffType
function UGCGameState:ApplyShowEnemyPos(Enable, TeamId, BuffType)
local ShowTable = self.CachedInit[BuffType];
if table.isEmpty(ShowTable) then
if not self:LoadCachedInit(BuffType) then return ; end
ShowTable = self.CachedInit[BuffType];
end
if DefaultSettings.LocalTeamId ~= TeamId then
self:HideEnemyPos(BuffType);
return ;
end
if BuffType ~= nil then
local OtherTeamPlayers = self:GetOtherPlayerKeys(TeamId);
if table.isEmpty(OtherTeamPlayers) then return end
for i = 1, #OtherTeamPlayers do
UGCLogSystem.Log("[UGCGameState:ApplyShowEnemyPos] ActorName = %s", UE.GetName(ShowTable[i]));
ShowTable[i]:SetTrackPlayerKey(Enable and OtherTeamPlayers[i] or nil);
end
end
end
function UGCGameState:LoadCachedInit(InBuffType)
local BuffManager = BP_BuffManager.GetBuffManager()
BuffManager:Init();
if table.isEmpty(self.CachedInit[InBuffType]) then
UGCLogSystem.LogError("[UGCGameState:LoadCachedInit] 当前表中还是没有数据,请检查 BuffType = %s", tostring(InBuffType));
return false;
end
return true;
end
function UGCGameState:HideEnemyPos(BuffType)
UGCLogSystem.Log("[UGCGameState:HideEnemyPos] 隐藏起来敌方玩家");
local ShowTable = self.CachedInit[BuffType];
if table.isEmpty(ShowTable) then
return ;
end
for i = 1, #ShowTable do
ShowTable[i]:SetTrackPlayerKey(nil);
end
end
function UGCGameState:SendSoldierRPC(IsMulti, FuncName, InPlayerKey, InSoldierType, ...)
if self:HasAuthority() then
if IsMulti then
UnrealNetwork.CallUnrealRPC_Multicast(self, "SendSoldierRPC", IsMulti, FuncName, InPlayerKey, InSoldierType, ...)
else
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey);
UnrealNetwork.CallUnrealRPC(PC, self, "SendSoldierRPC", IsMulti, FuncName, InPlayerKey, InSoldierType, ...);
end
else
UGCLogSystem.Log("[UGCGameState:SendSoldierRPC] %s 执行客户端逻辑:%s", tostring(InPlayerKey), FuncName)
if InPlayerKey == LocalPlayerKey then
-- 进行处理
if LocalPlayerController ~= nil then
local SoldierBase = LocalPlayerController:GetSoldierBase(InSoldierType)
if SoldierBase == nil then
-- 创建一个
SoldierBase = LocalPlayerController:AddSoldierBase(InSoldierType);
end
SoldierBase[FuncName](SoldierBase, ...);
end
end
end
end
function UGCGameState:ClientSendEvent(InPlayerKey, InEvent, ...)
if self:HasAuthority() then
if InPlayerKey == nil then
UnrealNetwork.CallUnrealRPC_Multicast(self, "ClientSendEvent", InEvent, ...);
else
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey);
UnrealNetwork.CallUnrealRPC(PC, UGCGameSystem.GameState, "ClientSendEvent", InEvent, ...);
end
else
UGCEventSystem.SendEvent(InPlayerKey, InEvent, ...);
end
end
---@param IsSend bool 是否是自己发送的
function UGCGameState:SendEvent(IsSend, InPlayerKey, InEvent, ...)
if self:HasAuthority() then
-- 检测是否存在 PlayerKey
if IsSend then
if InPlayerKey == nil then
UnrealNetwork.CallUnrealRPC_Multicast(self, "SendEvent", false, nil, InEvent, ...);
else
local PC = UGCGameSystem.GetPlayerControllerByPlayerKey(InPlayerKey);
if UE.IsValid(PC) then
UnrealNetwork.CallUnrealRPC(PC, UGCGameSystem.GameState, "SendEvent", false, InPlayerKey, InEvent, ...);
end
end
else
-- 那么就是接受过来的
UGCEventSystem.SendEvent(InEvent, InPlayerKey, ...)
end
else
-- 从客户端发送出去
if IsSend then
UnrealNetwork.CallUnrealRPC(LocalPlayerController, UGCGameSystem.GameState, "SendEvent", false, LocalPlayerKey, InEvent, ...);
else
UGCEventSystem.SendEvent(InEvent, InPlayerKey, ...);
end
end
end
UGCGameState.PlayerUseBuffs = {};
function UGCGameState:OnPlayerUseBuff(InPlayerKey, InBuffType, InBuffInfo, InServerTime)
local TeamId = self:GetPlayerTeamId(InPlayerKey);
if TeamId == DefaultSettings.LocalTeamId then
local Name = self:GetPlayerNameByPlayerKey(InPlayerKey);
UGCLogSystem.Log("[UGCGameState:OnPlayerUseBuff] Name = %s", Name)
if self.PlayerUseBuffs[InServerTime] == nil then
self.PlayerUseBuffs[InServerTime] = InPlayerKey;
UGCWidgetManagerSystem.ShowTipsUI(string.format('%s 启动了技能:%s', Name, BuffConfig.BuffInfo[InBuffType].Desc));
end
end
end
----------------------------------------- 信号圈 -----------------------------------------
---@type PoisonCircleSystem_C
UGCGameState.PoisonSystemActor = nil;
---@return PoisonCircleSystem_C
function UGCGameState:FindPoisonCircle()
if self.PoisonSystemActor == nil then
self.PoisonSystemActor = UE.FindActorByClass(ObjectPath.PoisonCircleSystem);
end
return self.PoisonSystemActor;
end
--- 配置并启动毒圈
---@param InConfigIndex int32 毒圈配置
function UGCGameState:StartPoison(InConfigIndex)
UGCLogSystem.Log("[UGCGameState:StartPoison] 执行")
local PoisonActor = self:FindPoisonCircle();
if PoisonActor then
PoisonActor:SetConfigIndex(InConfigIndex);
PoisonActor:StartPoison();
end
end
return UGCGameState;