---@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 队伍兵种类型 PlayerSoldierType = {}; ---@type table> 玩家的分数 PlayerScores = {}; ---@type table 玩家选择的地图 PlayerSelectLevels = {}; ---@type table 玩家造成的伤害 PlayerDamage = {}; ---@type table { [RoundTime] = TeamId } 哪局是哪个队伍赢了 GameRounds = {}; ---@type int32 赢取的队伍ID WinTeamId = -1; CachedInit = {}; ---@type table> 存在的玩家 ExistPlayerKeys = {}; }; ---@type table 玩家的存档数据 UGCGameState.PlayerArchives = {}; --- @type table UGCGameState.PlayerAccountInfoMap = {}; ---@type table UGCGameState.TotalPlayerKDA = {}; ---@type table> { 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> 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;