---@class UGCPlayerController_C:BP_UGCPlayerController_C --Edit Below-- require('Script.Global.Global') ---@type UGCPlayerController_C local UGCPlayerController = {}; --- 默认滑铲 UGCPlayerController.PlayerEnableShovel = false; --- 默认显示飘字 UGCPlayerController.EnableDamageText = true; --- 记录一个 WeaponInfo UGCPlayerController.WeaponInfo = {}; function UGCPlayerController:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); GlobalInit.InitGlobalVar() --- 设置一个默认值 self.EnableDamageText = DefaultSettings.EnableDamageText; if IsClient then WidgetManager:Init(self); if not DefaultSettings.EnableAutoPickUp then UITool.HidePickUpPanel(); end UGCEventSystem.SetTimer(self, function() WidgetManager:ShowPanel(WidgetConfig.EUIType.Main, false); local MiniState = GameState.MiniInfo.State UGCLogSystem.Log("[UGCPlayerController:ReceiveBeginPlay] 执行 MiniState = %s", tostring(MiniState)); if MiniState ~= nil and MiniState <= MiniGameState.ROUND_PREPARE then if LocalIsGlobalSpectator then if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.AllWeapon_Spectator) then UGCLogSystem.Log("[Mini_Solo:ShowSelectWeaponUI] 显示观战界面"); WidgetManager:ShowPanel(WidgetConfig.EUIType.AllWeapon_Spectator, false, self.SelectWeaponCount, self.PlayerSelectMaps); end -- 隐藏一下 OBUI else if not WidgetManager:IsVisiblePanel(WidgetConfig.EUIType.AllWeapon) then UGCLogSystem.Log("[Mini_Solo:ShowSelectWeaponUI] 显示所有武器界面"); WidgetManager:ShowPanel(WidgetConfig.EUIType.AllWeapon, false, self.SelectWeaponCount, self.PlayerSelectMaps); end end else if MiniState == nil then UGCLogSystem.Log("[UGCPlayerController:ReceiveBeginPlay] GlobalMiniState 不存在") else UGCLogSystem.Log("[UGCPlayerController:ReceiveBeginPlay] State = %s", TableHelper.printEnum(MiniGameState, MiniState)); end end end, 1); end UGCEventSystem.AddListener(EventTypes.ClientAlready, self.OnClientAlready, self); -- 添加玩家死亡复活回调 self.OnCharacterDeadDelegate:Add(self.OnCharacterDeath, self) self.PlayerControllerRespawnedDelegate:AddInstance(self.OnRespawnPawn, self) self.OnSpectatorChange:Add(self.OnChangeSpectorActor, self); UGCLogSystem.Log("[UGCPlayerController:ReceiveBeginPlay] 执行") end function UGCPlayerController:GetReplicatedProperties() return { "PlayerEnableShovel", "Lazy" } end function UGCPlayerController:GetAvailableServerRPCs() return "Test_Func" , "SetEnableShovel" , "SetEnableDamageText" , "ResendArchive" end --- 重置游戏 function UGCPlayerController:ResetGame() local PlayerState = UGCGameSystem.GetPlayerStateByPlayerKey(self.PlayerKey) PlayerState:ResetGame(); end function UGCPlayerController:OnRespawnPawn() local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey); table.func(MiniManager, "OnPawnInit", Pawn); UGCLogSystem.Log("[UGCPlayerController:OnRespawnPawn] 执行") if IsServer then Pawn:AddInitItems(); -- 检测当前有多少人 local Pawns = UGCGameSystem.GetAllPlayerPawn() --- 所有玩家重置成功 local PlayerCount = table.getCount(Pawns) if PlayerCount > 1 then -- 说明现在可以改动玩家了 if self:IsFriendObserver() then -- 改变观战人数 local OBKeys = {}; for _, PC in pairs(UGCGameSystem.GetAllPlayerController(false)) do if FriendSystem.IsMyFriend(UE.GetPlayerUID(PC.PlayerKey)) then table.insert(OBKeys, PC.PlayerKey); end end UGCLogSystem.LogTree(string.format("[UGCPlayerController:OnRespawnPawn] OBKeys ="), OBKeys) if not table.isEmpty(OBKeys) then UGCGameSystem.ChangeAllowOBPlayerKeys(self, OBKeys); UGCGameSystem.EnterSpectating(self); end end end else -- if GlobalMiniMode.ModeType ~= GameModeConfig.EGameModeType.DefaultMode then UGCLogSystem.Log("[UGCPlayerController:OnRespawnPawn] 显示按钮") WidgetManager:GetPanel(WidgetConfig.EUIType.Main, function(Widget) table.func(Widget, "ShowCustomSelectWeaponBtn", true); end) -- end end end -- 该方法是客户端就绪 function UGCPlayerController:OnClientAlready() local Archive = ArchiveTable[self.PlayerKey]; if not table.isEmpty(Archive) and not table.isEmpty(Archive.Disables) then self.EnableDamageText = Archive.Disables.DamageText UGCLogSystem.Log("[UGCPlayerController:OnClientAlready] DamageText = %s", tostring(self.EnableDamageText)); UGCEventSystem.SendEvent(EventTypes.UpdateEnableDamageText, self.EnableDamageText) end end ---@param Character UGCPlayerPawn_C function UGCPlayerController:OnCharacterDeath(Character) UGCLogSystem.Log("[UGCPlayerController:OnCharacterDeath] 执行") end -------------------------------- 观战 -------------------------------- ---@param IsEnterSpectate bool function UGCPlayerController:EnterSpectate(IsEnterSpectate) if IsServer then local OBKeys = {}; for _, PC in pairs(UGCGameSystem.GetAllPlayerController(false)) do if FriendSystem.IsMyFriend(UE.GetPlayerUID(PC.PlayerKey)) then table.insert(OBKeys, PC.PlayerKey); end end if table.isEmpty(OBKeys) then return ; end UGCGameSystem.ChangeAllowOBPlayerKeys(self, OBKeys); UGCGameSystem.EnterSpectating(self); end end --- 设置能否移动 function UGCPlayerController:SetCanMove(IsCan) self:SetCinematicMode(not IsCan, false, false, true, false); end --- 设置玩家是否可以滑铲 function UGCPlayerController:SetEnableShovel(IsEnable) UGCLogSystem.Log("[UGCPlayerController:SetEnableShovel] 执行 IsEnable = %s", tostring(IsEnable)); if self.PlayerEnableShovel == IsEnable then return ; end self.PlayerEnableShovel = IsEnable; ArchiveTable[self.PlayerKey].PlayerEnableShovel = IsEnable; local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(self.PlayerKey); if Pawn and UE.IsValid(Pawn) and Pawn:IsAlive() then UGCLogSystem.Log("[UGCPlayerController:SetEnableShovel] 是否可以滑铲 %s", tostring(GameState.EnableShovel)); UGCPawnSystem.DisabledPawnState(Pawn, EPawnState.Shoveling, not GameState.EnableShovel); end -- 记录一下 DOREPONCE(self, "PlayerEnableShovel"); end function UGCPlayerController:OnRep_PlayerEnableShovel() -- 检查一下 if LocalPlayerKey and self.PlayerKey == LocalPlayerKey then -- 不需要设置,因为就是通过它改变的 UGCEventSystem.SendEvent(EventTypes.ChangeShovel, self.PlayerEnableShovel); end end --- 设置是否开启飘字 function UGCPlayerController:SetEnableDamageText(IsEnable) if not self:IsPureSpectator() then if IsServer then -- 保存一下 if ArchiveTable[self.PlayerKey].Disables == nil then ArchiveTable[self.PlayerKey].Disables = {}; end ArchiveTable[self.PlayerKey].Disables.DamageText = IsEnable; else UnrealNetwork.CallUnrealRPC(self, self, "SetEnableDamageText", IsEnable); end self.EnableDamageText = IsEnable; end end function UGCPlayerController:GetEnableDamageText() local Archive = ArchiveTable[self.PlayerKey]; if not table.isEmpty(Archive) and not table.isEmpty(Archive.Disables) and Archive.Disables.DamageText ~= nil then self.EnableDamageText = Archive.Disables.DamageText end end --- 处理切换观战对象 function UGCPlayerController:OnChangeSpectorActor() UGCEventSystem.SendEvent(EventTypes.ChangeSpector, self.IsCurrentSpectatorFreeView, self:GetCurPawn()); end -------------------------------- 测试 -------------------------------- function UGCPlayerController:Test_Func(InFuncName, ...) UGCLogSystem.Log("[UGCPlayerController:Test_Func] 执行 %s", InFuncName) self[InFuncName](self, ...) end function UGCPlayerController:Test_PlayerLeave(PlayerKey) table.func(MiniManager, "Test_PlayerLeave", PlayerKey); end --function UGCPlayerController:ReceiveTick(DeltaTime) -- self.SuperClass.ReceiveTick(self, DeltaTime); --end function UGCPlayerController:ReceiveEndPlay() self:CloseLastGameTimer(); self.SuperClass.ReceiveEndPlay(self); end function UGCPlayerController:CloseLastGameTimer() if self.SendLastGamesTimer then UGCEventSystem.StopTimer(self.SendLastGamesTimer); self.SendLastGamesTime = nil; end end ---------------------------------- 处理存档 ---------------------------------- ---通知重新发送存档 ---@param Array int[] function UGCPlayerController:ResendArchive(Array) if IsServer then self.SendListIndex = Array; self:SendLast10Games(Array); else UnrealNetwork.CallUnrealRPC(self, self, "ResendArchive", Array); end end ---@type int[] UGCPlayerController.SendListIndex = nil; UGCPlayerController.SendLastGamesTimer = nil; --- 直接调用该函数即可 function UGCPlayerController:SendLast10Games(InList) local Total = table.getCount(ArchiveTable[self.PlayerKey].Last10Games) if table.isEmpty(InList) then InList = {}; for i = 1, Total do table.insert(InList, i); end end self.SendListIndex = InList; UGCLogSystem.LogTree(string.format("[UGCPlayerController:SendLast10Games] SendListIndex ="), self.SendListIndex); if not table.isEmpty(InList) then self.SendLastGamesTimer = UGCEventSystem.SetTimerLoop(self, function() local Index = self.SendListIndex[1]; if Index == nil then return self:CloseLastGameTimer(); end table.remove(self.SendListIndex, 1) self:SendArchive(Index); end, 1); end end --- 发送本局历史战绩 function UGCPlayerController:SendNewArchive(Index, Archive, Friend) if IsServer then UnrealNetwork.CallUnrealRPC(self, self, "SendNewArchive", Index, Archive, Friend); else UGCLogSystem.Log("[UGCPlayerController:SendNewArchive] 执行 Index = %d", Index); WidgetManager:GetPanel(WidgetConfig.EUIType.GameRecord, function(Widget) Widget:AddLastGameItem(Index, Archive, Friend); Widget:OnAllLastGamesAlready(Index); end); end end --- 发送存档 ---@param Index int 索引,只发送当前的 function UGCPlayerController:SendArchive(Index, Total, Archive, Friend) if IsServer then UGCLogSystem.Log("[UGCPlayerController:SendArchive] 执行 Index = %d", Index); if table.isEmpty(ArchiveTable[self.PlayerKey]) then return end if table.isEmpty(ArchiveTable[self.PlayerKey].Last10Games) then return ; end local LastGame = ArchiveTable[self.PlayerKey].Last10Games[Index] if table.isEmpty(LastGame) then return ; end Total = table.getCount(ArchiveTable[self.PlayerKey].Last10Games); local UID = nil if LastGame[9] then UID = LastGame[2] else UID = LastGame[2][1]; end UnrealNetwork.CallUnrealRPC(self, self, "SendArchive", Index, Total, ArchiveTable[self.PlayerKey].Last10Games[Index], (UID == nil and nil or ArchiveTable[self.PlayerKey].Friends[UID]) ); else if ArchiveTable[self.PlayerKey] == nil then ArchiveTable[self.PlayerKey] = {}; end if ArchiveTable[self.PlayerKey].Last10Games == nil then ArchiveTable[self.PlayerKey].Last10Games = {}; end ArchiveTable[self.PlayerKey].Last10Games[Index] = Archive; WidgetManager:GetPanel(WidgetConfig.EUIType.GameRecord, function(Widget) Widget:AddLastGameItem(Index, Archive, Friend); end) self:CloseLastGameTimer(); UGCEventSystem.SetTimer(self, function() -- 验证是否完全,不完全发送数据 local Success, List = self:CheckArchiveDataComplete(Total); if not Success then self:ResendArchive(List); end end, 3); -- 判断是否完整 if self:CheckArchiveDataComplete(Total) then -- 数据完整 self:CloseLastGameTimer(); UGCEventSystem.SendEvent(EventTypes.AllLastGamesAlready, Total) end end end --- 检查Last10Games存档数据是否完整 function UGCPlayerController:CheckArchiveDataComplete(Total) if table.isEmpty(ArchiveTable[self.PlayerKey]) then return false; end if table.isEmpty(ArchiveTable[self.PlayerKey].Last10Games) then return false; end local Count = table.getCount(ArchiveTable[self.PlayerKey].Last10Games); if Total <= Count then return true; end local ResendList = {}; for i = 1, Total do if ArchiveTable[self.PlayerKey].Last10Games[i] == nil then table.insert(ResendList, i); end end return false, ResendList; end UGCPlayerController.SelectWeapons = {}; -- 一次发送 RPC 的武器数量 UGCPlayerController.OneSendWeaponCount = 10; function UGCPlayerController:SendSelectWeapons() if table.isEmpty(ArchiveTable[self.PlayerKey]) then return end if table.isEmpty(ArchiveTable[self.PlayerKey].SelectWeapons) then return end UGCLogSystem.Log("[UGCPlayerController:SendSelectWeapons] 执行") UGCEventSystem.SetTimer(self, function() self.SendSelectWeaponsTimer = UGCEventSystem.SetTimerLoop(self, function() self:SendWeapons(); end, 1); end, 0.3); end --- 发送 SelectWeapons function UGCPlayerController:SendWeapons(Total, InList) if IsServer then if table.isEmpty(self.SelectWeapons) then self.SelectWeapons = TableHelper.DeepCopyTable(ArchiveTable[self.PlayerKey].SelectWeapons); end if table.isEmpty(InList) then InList = {}; local ZheList = {}; if table.getCount(self.SelectWeapons) <= self.OneSendWeaponCount then InList = self.SelectWeapons; else local Num = 1; local List = {}; for i, v in pairs(self.SelectWeapons) do InList[i] = v; Num = Num + 1; if Num > self.OneSendWeaponCount then break ; end end for WeaponId, v in pairs(InList) do self.SelectWeapons[WeaponId] = nil; end end if table.isEmpty(self.SelectWeapons) then if self.SendSelectWeaponsTimer then UGCEventSystem.StopTimer(self.SendSelectWeaponsTimer) self.SendSelectWeaponsTimer = nil; end end end if table.isEmpty(InList) then return; end if Total == nil then UnrealNetwork.CallUnrealRPC(self, self, "SendWeapons", table.getCount(ArchiveTable[self.PlayerKey].SelectWeapons), InList); else UnrealNetwork.CallUnrealRPC(self, self, "SendWeapons", Total, InList); end else -- 组装即可 if table.isEmpty(InList) then return ; end if ArchiveTable[self.PlayerKey] == nil then ArchiveTable[self.PlayerKey] = {}; end if table.isEmpty(ArchiveTable[self.PlayerKey].SelectWeapons) then ArchiveTable[self.PlayerKey].SelectWeapons = {}; end for Weapon, List in pairs(InList) do ArchiveTable[self.PlayerKey].SelectWeapons[Weapon] = List; end UGCLogSystem.Log("[UGCPlayerController:SendWeapons] 执行 Total = %d", Total); if Total == table.getCount(ArchiveTable[self.PlayerKey].SelectWeapons) or Total == -1 then UGCEventSystem.SendEvent(EventTypes.AllSelectWeaponsAlready, ArchiveTable[self.PlayerKey].SelectWeapons); end end end --- 一次发送武器配件数量的rpc有多少个 UGCPlayerController.OneSendWeaponPartsCount = 10; UGCPlayerController.SendPartsTimer = nil; --- 正在发送的 IDs UGCPlayerController.InSendWeaponIds = {}; -- 发送武器配件信息 function UGCPlayerController:SendWeaponParts(InList) if table.isEmpty(ArchiveTable[self.PlayerKey]) then return; end local Weapons = ArchiveTable[self.PlayerKey].Weapons; if table.isEmpty(Weapons) then return; end if table.isEmpty(self.InSendWeaponIds) then self.InSendWeaponIds = {}; end if table.isEmpty(InList) then for WeaponID, Parts in pairs(Weapons) do table.insert(self.InSendWeaponIds, WeaponID); end else for i, v in pairs(InList) do table.insert(self.InSendWeaponIds, v); end end UGCLogSystem.LogTree(string.format("[UGCPlayerController:SendWeaponParts] InSendWeaponIds ="), self.InSendWeaponIds) if table.isEmpty(self.InSendWeaponIds) then self:CloseWeaponPartsTimer(); end self.SendPartsTimer = UGCEventSystem.SetTimerLoop(self, function() UGCLogSystem.Log("[UGCPlayerController:SendWeaponParts] 发送 Parts") self:SendPartsRPC(); end, 0.5) end function UGCPlayerController:CloseWeaponPartsTimer() if self.SendPartsTimer ~= nil then UGCEventSystem.StopTimer(self.SendPartsTimer); self.SendPartsTimer = nil; end end -- 发送配件 RPC function UGCPlayerController:SendPartsRPC(InTotal, InList) if IsServer then -- 开始发送 local Weapons = ArchiveTable[self.PlayerKey].Weapons; local Count = table.getCount(self.InSendWeaponIds); local SendTable = {}; if Count <= self.OneSendWeaponPartsCount then for i, WeaponID in pairs(self.InSendWeaponIds) do SendTable[WeaponID] = Weapons[WeaponID]; end self.InSendWeaponIds = {}; self:CloseWeaponPartsTimer(); else for i = 1, self.OneSendWeaponPartsCount do local WeaponID = self.InSendWeaponIds[1]; SendTable[WeaponID] = Weapons[WeaponID]; table.remove(self.InSendWeaponIds, 1); end end UGCLogSystem.LogTree(string.format("[UGCPlayerController:SendPartsRPC] SendTable ="), SendTable) if table.isEmpty(SendTable) then return; end UnrealNetwork.CallUnrealRPC(self, self, "SendPartsRPC", InTotal or table.getCount(SendTable), SendTable); else UGCLogSystem.Log("[UGCPlayerController:SendPartsRPC] 接收到 Total = %s", tostring(InTotal)); table.printTable(InList) if table.isEmpty(ArchiveTable[self.PlayerKey]) then ArchiveTable[self.PlayerKey] = {}; end if table.isEmpty(ArchiveTable[self.PlayerKey].Weapons) then ArchiveTable[self.PlayerKey].Weapons = {}; end for WeaponID, Parts in pairs(InList) do ArchiveTable[self.PlayerKey].Weapons[WeaponID] = Parts; end -- 查看是否完全了 if table.getCount(ArchiveTable[self.PlayerKey].Weapons) == InTotal or InTotal == -1 then -- 更新存档武器 UGCEventSystem.SendEvent(EventTypes.UpdateArchiveData, ArchiveTable); end end end return UGCPlayerController;