---@type table ---@private UE.CachedClasses = {}; --- 组件位置 UE.ComponentPath = { Camera = "/Script/Engine.CameraComponent", SpringArm = "/Script/Engine.SpringArmComponent", ChildActor = "/Script/Engine.ChildActorComponent", Scene = "/Script/Engine.SceneComponent", Actor = "/Script/Engine.ActorComponent", } UE.ResetClassPath = { "PlayerTombBox", -- 玩家死亡盒子基类 "PickUpWrapperActor", -- 可拾取物的基类 "EliteProjectile", -- 投掷物的基类 "BurningSpreading", -- 燃烧弹的东西 "TslDamageField", -- 燃烧弹的东西 }; UE.DoorClassBaseName = "PUBGDoor"; UE.HouseClassBaseName = "STExtraHouseActor"; ---@param InInfo PlayerAccountInfo ---@return PlayerAccountInfo function UE.HandleAccountInfo(InInfo) return { UID = InInfo.UID, PlayerName = InInfo.PlayerName, TeamID = InInfo.TeamID, Gender = InInfo.Gender, --PlatformGender = InInfo.PlatformGender, PlayerLevel = InInfo.PlayerLevel, --SegmentLevel = InInfo.SegmentLevel, IconURL = InInfo.IconURL, }; end function UE.GetPlayerUID(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.UID; end return -1; end function UE.GetPlayerName(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.PlayerName; end return ""; end function UE.GetPlayerIconURL(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.IconURL; end return ''; end function UE.GetTeamID(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.TeamID end UGCLogSystem.Log("[UE.GetTeamID] 无法找到 PlayerKey = %s", tostring(PlayerKey)); return nil; end function UE.GetPlayerGender(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.Gender end return nil; end function UE.GetPlayerAvatarBoxId(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.AvatarBoxId; end return nil; end function UE.GetPlayerLevel(PlayerKey) local Info = UE.GetAccountInfo(PlayerKey); if Info then return Info.PlayerLevel; end return nil; end function UE.GetPlayerTeamID(PlayerKey) return UE.GetTeamID(PlayerKey); end ---@class SoloKingArchiveData ---@field TotalGameTimes int32 ---@field GameTimes int32 ---@field Weapons table ---@field Score int32 ---@field WinTimes int32 ---@field GameWinTimes int32 ---@field Kill int32 ---@field Dead int32 ---@field Last10Games table ---@field HideScore int32 ---@field CurSeason int32 ---@field Seasons table ---@field Friends table ---@field IsNewSeason table ---@field LastSelectMap table ---@field Disables ---@field SelectWeapons table 选择的武器 ---@field LastSelectWeapons table 最后选择过的武器 ---@field SelectMaps table 选择过的地图 ---@field sw_version int32 选择武器版本 ---@field PlayerEnableShovel bool 玩家是否可以滑铲 ---@field SeasonInfo table 补分用 ---@field NoSelectMaps table 未选中的地图 ---@return SoloKingArchiveData function UE.InitArchiveData() return { TotalGameTimes = 0; -- 经典模式游玩次数,同步 GameTimes = 0, -- 游玩次数(包含所有模式)不同步 Weapons = {}, -- 武器配件 不同步 Score = DefaultSettings.RankScore, -- 默认 2000分 同步 WinTimes = 0, -- 一共获胜次数 不同步 GameWinTimes = 0, -- 经典模式获胜次数 同步 Kill = 0, -- 总击杀数 同步 Dead = 0, -- 总死亡数 同步 HideScore = 0, -- 隐藏分 同步 Disables = {}; -- 最后十局战绩 Last10Games = {}, -- 历史十局 同步 CurSeason = 0; -- 默认赛季 不同步 --- 赛季信息 Seasons = {}; -- 历史赛季 同步 IsNewSeason = false; -- 是否是新的赛季,在游戏结束的时候 同步 Friends = {}; -- 玩家对战过的玩家 同步 SeasonInfo = {}, -- 赛季信息,现在使用第1槽 sw_version = 1; -- 选择武器的版本 不同步 SelectWeapons = {}; -- 玩家选择过的武器以及胜率 同步 NoSelectMaps = {}; }; end UE.ValidRepNames = { "TotalGameTimes", "Score", }; function UE.MakeSelectWeapon(InList) if InList[7] then return UE.MakeSelectWeapon_Archive(InList); end return { SelectCount = InList[1][1], -- 选择的次数 可以证明喜好程度 UseCount = InList[1][2], -- 使用次数,局数 WinCount = InList[1][3], -- 获胜次数 胜率 = 获胜次数 / 使用次数 ShootCount = InList[2][1], -- 射击数 HitCount = InList[2][2], -- 击中数:击中率 = 击中数 / 射击数 HeavyHit = InList[2][3], -- 暴击数:暴击率 = 暴击数 / 击中数 TotalDamage = InList[3][1], -- 总伤害 } end function UE.MakeSelectWeapon_Archive(InList) return { SelectCount = InList[1] or 0, UseCount = InList[2] or 0, WinCount = InList[3] or 0, ShootCount = InList[4] or 0, HitCount = InList[5] or 0, HeavyHit = InList[6] or 0, TotalDamage = InList[7] or 0, } end function UE.MakeSelectWeapon_Old2New(InList) if InList[7] == nil then return { [1] = InList[1][1] or 0, -- 选择的次数 可以证明喜好程度 [2] = InList[1][2] or 0, -- 使用次数,局数 [3] = InList[1][3] or 0, -- 获胜次数 胜率 = 获胜次数 / 使用次数 [4] = InList[2][1] or 0, -- 射击数 [5] = InList[2][2] or 0, -- 击中数:击中率 = 击中数 / 射击数 [6] = InList[2][3] or 0, -- 暴击数:暴击率 = 暴击数 / 击中数 [7] = InList[3][1] or 0, -- 总伤害 } else return InList; end end function UE.MakeSeason(InList) return { SeasonIndex = InList[1], Score = InList[2][1], -- 分数 HideScore = InList[2][2], GameTimes = InList[3][1], WinTimes = InList[3][2], Kill = InList[4][1], Dead = InList[4][2], --KD = InList[4][1] / (InList[4][2] == 0 and 1 or InList[4][2]); }; end --- 创建朋友属性(怕在局外不能获取,所以才保存的) function UE.MakeFriend(InList) return { PlayerName = InList[1], IconURL = InList[2], } end --- 注意结构不能发生改变,否则会出错 function UE.MakeLastGame(InList) UGCLogSystem.LogTree(string.format("[UE.MakeLastGame] InList ="), InList) local GameInfos = InList[6]; local GameInfo = { }; for i = 1, #GameInfos do local Info = GameInfos[i]; table.insert(GameInfo, { IsWin = Info[1], WeaponID = Info[2], RoundScore = { MyScore = Info[3][1], EnemyScore = Info[3][2], }, }) end return { IsWin = InList[1], UID = InList[2][1], GameScore = { MyScore = InList[3][1], EnemyScore = InList[3][2], }, Score = InList[4][1], AddScore = InList[4][2], KD = InList[5][1] / (InList[5][2] == 0 and 1 or InList[5][2]), GameInfo = GameInfo, } end function UE.MakeLastGame_Archive(InList) local GameInfos = InList[9]; local GameInfo = { }; for i = 1, #GameInfos do local Info = GameInfos[i]; table.insert(GameInfo, { IsWin = Info[1], WeaponID = Info[2], RoundScore = { MyScore = Info[3], EnemyScore = Info[4], }, }) end local Kill = InList[7] local Dead = InList[8] return { IsWin = InList[1], UID = InList[2], GameScore = { MyScore = InList[3], EnemyScore = InList[4], }, Score = InList[5], AddScore = InList[6], KD = (Kill or 0) / (Dead == 0 and 1 or Dead), GameInfo = GameInfo, } end -- 转化为单一数组 function UE.MakeArchive_LastGame(InList) local List = {}; if InList[6] then for i = 1, #(InList[6]) do List[i] = { InList[6][1], InList[6][2], InList[6][3][1], InList[6][3][2], } end end return { [1] = InList[1], [2] = InList[2][1], [3] = InList[3][1], [4] = InList[3][2], [5] = InList[4][1], [6] = InList[4][2], [7] = InList[5][1], [8] = InList[5][2], [9] = List, } end --- 转化回原来的 function UE.MakeList_LastGame(InList) local GameInfo = {}; for i = 1, #(InList[11]) do local Info = InList[11][i]; GameInfo[i] = { [1] = Info[1], [2] = Info[2], [3] = { Info[3], Info[4], } } end return { [1] = InList[1], [2] = { InList[2], InList[3], InList[4], }, [3] = { InList[5], InList[6], }, [4] = { InList[7], InList[8], }, [5] = { InList[9], InList[10], }, [6] = GameInfo, } end ---@param InClass UClass ---@param InTable table 获得的 ---@param InFunc fun(InIndex:int32, InActor:AActor): bool ---@return table function UE.FindActorsByClass(InClass, InTable, InFunc) if InTable == nil then InTable = {}; end local AllActors = {}; GameplayStatics.GetAllActorsOfClass(UGCGameSystem.GameState, InClass, AllActors); for i, v in pairs(AllActors) do if InFunc == nil or InFunc(i, v) then table.insert(InTable, v); end end return InTable; end ---@param InTable table ---@param InTag FName ---@param InFunc fun(InActor: AActor): bool ---@return table function UE.FindActorsByTag(InTag, InTable, InFunc) if table.isEmpty(InTable) then InTable = {}; end local AllActors = {}; GameplayStatics.GetAllActorsWithTag(UGCGameSystem.GameState, InTag, AllActors); for i, v in pairs(AllActors) do if InFunc == nil or InFunc(v) then table.insert(InTable, v); end end return InTable; end ---@param InTag FName ---@param InFunc fun(InActor: AActor): bool ---@return table function UE.FindActorByTag(InTag, InFunc) local AllActors = {}; GameplayStatics.GetAllActorsWithTag(UGCGameSystem.GameState, InTag, AllActors); for i, v in pairs(AllActors) do if InFunc == nil or InFunc(v) then return v; end end return nil; end ---@param InClass UClass ---@param InFunc fun(InIndex:int32, InActor:AActor): bool ---@return AActor function UE.FindActorByClass(InClass, InFunc) local Table = {}; UE.FindActorsByClass(InClass, Table, InFunc); if table.isEmpty(Table) then return nil; end return Table[1]; end ---@type table UE.GlobalCachedActor = {}; ---@param InClass UClass ---@return nil | AActor function UE.FindOrCreateActorByClass(InClass, bDestroyOther) print(string.format('[UE.FindOrCreateActorByClass] 开始执行, ClassName = %s', UE.GetName(InClass))); if InClass == nil then return nil; end local CachedActor = UE.GlobalCachedActor[InClass]; if CachedActor ~= nil and UE.IsValid(CachedActor) then return CachedActor; end local Actors = {} UE.FindActorsByClass(InClass, Actors); local Actor = nil; for i, v in pairs(Actors) do Actor = v; if Actor ~= v and bDestroyOther then v:K2_DestroyActor(); end end if Actor ~= nil then UE.GlobalCachedActor[InClass] = Actor; return Actor; end return UE.CreateActor(InClass); end ---@param ClassPath string 类路径 ---@return UClass | nil function UE.CachedLoadClass(ClassPath) if UE.CachedClasses[ClassPath] == nil then UE.CachedClasses[ClassPath] = UE.LoadClass(ClassPath); end if UE.CachedClasses[ClassPath] == nil then print(string.format('[UE.CachedLoadClass] Error Cant Load Class By Path: %s', ClassPath)); return nil; end return UE.CachedClasses[ClassPath]; end function UE.CreateActor(InClass, InCount, InOuter) if InOuter == nil then InOuter = UGCGameSystem.GameState; end if InCount == nil then InCount = 1 end local Actors = {}; for i = 1, InCount do table.insert(Actors, UE.SpawnActor(InClass, InOuter)) end if InCount == 1 then return Actors[1]; end return Actors; end ---@param InClass UClass ---@param Loc FVector ---@param Rot FRotator ---@param Scale FVector function UE.SpawnActor(InClass, InOuter, Loc, Rot, Scale) Loc = Loc == nil and VectorHelper.MakeVector1(0); Rot = Rot == nil and VectorHelper.MakeRotator(VectorHelper.MakeVector1(0)); Scale = Scale == nil and VectorHelper.MakeVector1(1); if InOuter == nil then InOuter = GameState; end return ScriptGameplayStatics.SpawnActor(InOuter, InClass, Loc, Rot, Scale); end --- 玩家重生 ---@param InPlayerKey PlayerKey ---@param InTime float function UE.RespawnPlayer(InPlayerKey, InTime) if InTime <= 0 then local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InPlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(InPlayerKey); else UGCEventSystem.SetTimer(GameState, function() local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InPlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(InPlayerKey); end, InTime); end end --- 获取当前时间 function UE.GetCurrentTime() return KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState); end ---@param InPlayerKey PlayerKey|nil ---@return PlayerAccountInfo|table function UE.GetAccountInfo(InPlayerKey) if InPlayerKey == nil then return AccountTable; end return AccountTable[InPlayerKey]; end ---@param InPlayerKey PlayerKey | nil ---@return table | PlayerAccountInfo function UE.GetArchiveData(InPlayerKey) if InPlayerKey == nil then return ArchiveTable; end return ArchiveTable[InPlayerKey]; end --- 移动玩家到某个地方 ---@param InPawn UGCPlayerPawn_C ---@param Location FVector ---@param Rotation FRotator function UE.MovePlayerToLocation(InPawn, Location, Rotation) if InPawn == nil then return end InPawn:bShouldDumpCallstackWhenMovingfast_Tofalse() InPawn:SetClientLocationOrRotation(Location, Rotation, true, Rotation ~= nil, false); InPawn:bShouldDumpCallstackWhenMovingfast_ToTrue() end function UE.GetComponentClass(InName) if UE.ComponentClasses[InName] == nil then local Path = UE.ComponentPath[InName] == nil and InName or UE.ComponentPath[InName]; UE.ComponentClasses[InName] = LoadClass(Path); end return UE.ComponentClasses[InName] end UE.ComponentClasses = {}; --- 遍历 Actor 上面的所有组件 ---@param InActor AActor ---@param InComponent UActorComponent ---@param cb fun(c: UActorComponent) function UE.ForeachComponent(InActor, InComponent, cb) local Class = UE.GetComponentClass(InComponent) UGCLogSystem.Log("[UE.ForeachComponent] ClassName = %s", UE.GetName(Class)); for i, v in pairs(InActor:GetComponentsByClass(Class)) do UGCLogSystem.Log("[UE.ForeachComponent] Component Name = %s", UE.GetName(v)) cb(v); end end function UE.GetActorComponents(InActor, InTable) local Components = InActor:GetComponentsByClass(UE.GetComponentClass("Actor")); if InTable == nil then InTable = {}; end for i, Comp in pairs(Components) do UE.GetChildComponents(Comp, InTable); end return InTable; end ---@param InComponent USceneComponent function UE.GetChildComponents(InComponent, InTable) -- 拿到所有 if InTable == nil then InTable = {}; end local Count = InComponent:GetNumChildrenComponents() if Count > 0 then for i = 1, Count do local Comp = InComponent:GetChildComponent(i - 1); table.insert(InTable, Comp); UE.GetChildComponents(Comp, InTable); end end end --- 组件朝向玩家, 如果朝向玩家,那么锁的是 Pitch 轴 ---@param InComponent USceneComponent ---@param InActor AActor ---@param Lock string function UE.ComponentTowardActor(InComponent, InActor, Lock) if InComponent == nil then return ; end local Rot = KismetMathLibrary.Conv_VectorToRotator(VectorHelper.Sub(InActor:K2_GetActorLocation(), InComponent:GetOwner():K2_GetActorLocation())); if Lock ~= nil then if Lock == 'Z' or Lock == 'Yaw' then Rot = { Roll = Rot.Roll, Pitch = Rot.Pitch, Yaw = 0 }; elseif Lock == 'Y' or Lock == 'Pitch' then Rot = { Roll = Rot.Roll, Pitch = 0, Yaw = Rot.Yaw }; elseif Lock == 'X' or Lock == 'Roll' then Rot = { Roll = 0, Pitch = Rot.Pitch, Yaw = Rot.Yaw }; end end InComponent:K2_SetWorldRotation(Rot); end --- 获取服务器时间 function UE.GetServerTime() if UGCGameSystem.GameState then return UGCGameSystem.GameState:GetServerTime(); end return nil end ---@param InTable table ---@param InFunc fun(InActor:AActor):bool function UE.DestroyTable(InTable, InFunc) if table.isEmpty(InTable) then return ; end for i, v in pairs(InTable) do if InFunc == nil or InFunc(v) then v:K2_DestroyActor(); end end InTable = {}; end function UE.IsPlayerPawn(InPawn) return UE.IsA(InPawn, ObjectPath.UGCPlayerPawn) end function UE.ReturnToLobby() NetUtil.SendPkg("giveup_enter_game"); LobbySystem.ReturnToLobby(); end function UE.LoadClass1(Path, cb) local Class UE.LoadClass(Path); if cb ~= nil then cb(Class); end return Class end UE.AsyncCachedItems = {}; ---@param Path string ---@param cb fun(TargetClass: UClass) function UE.AsyncLoadClass(Path, cb) if cb == nil then return end if UE.AsyncCachedItems[Path] then cb(UE.AsyncCachedItems[Path]); return ; end CommonUtils:AsyncLoadClass(UGCGameSystem.GameState, Path, function(TargetClass) if TargetClass and UE.IsValid(TargetClass) then cb(TargetClass); end end) end ---@param Path string ---@param cb fun(TargetClass: UClass) function UE.AsyncLoadClass_Cached(Path, cb) if UE.AsyncCachedItems[Path] ~= nil then if cb then cb(UE.AsyncCachedItems[Path]); end return ; end if cb == nil then return end CommonUtils:AsyncLoadClass(UGCGameSystem.GameState, Path, function(TargetClass) if TargetClass and UE.IsValid(TargetClass) then UE.AsyncCachedItems[Path] = TargetClass; if cb then cb(UE.AsyncCachedItems[Path]); end end end) end ---@param Path string ---@param cb fun(TargetObject: UObject) function UE.AsyncLoadObject(Path, cb) if cb == nil then return end if UE.AsyncCachedItems[Path] then cb(UE.AsyncCachedItems[Path]); return ; end CommonUtils:AsyncLoadObject(UGCGameSystem.GameState, Path, function(TargetObject) if TargetObject and UE.IsValid(TargetObject) then cb(TargetObject); end end) end ---@param Path string ---@param cb fun(TargetObject: UObject) function UE.AsyncLoadObject_Cached(Path, cb) if UE.AsyncCachedItems[Path] ~= nil then if cb then cb(UE.AsyncCachedItems[Path]); end return ; end CommonUtils:AsyncLoadObject(UGCGameSystem.GameState, Path, function(TargetObject) if TargetObject and UE.IsValid(TargetObject) then UE.AsyncCachedItems[Path] = TargetObject; if cb then cb(TargetObject); end end end) end -- New --------------------------------------- -- 20241020写入 ---@param AssetPath:string ---@param CallBackFunc:fun(LoadObject:UObject,resID:int32) ---@param Obj:table CallBackFunc拥有者 ---@param SaveAsset:bool 是否保存 function UE.AsyncLoadAsset_New(AssetPath, CallBackFunc, Obj, SaveAsset) if not UE.IsValid(UE.AsyncCachedItems[AssetPath]) then local softObjPath = KismetSystemLibrary.MakeSoftObjectPath(AssetPath); STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(softObjPath, ObjectExtend.CreateDelegate(UGCGameSystem.GameState, function(LoadObject, resID) if CallBackFunc then if Obj ~= nil then CallBackFunc(Obj, LoadObject) else CallBackFunc(LoadObject) end end if UE.IsValid(LoadObject) and SaveAsset then UE.AsyncCachedItems[AssetPath] = LoadObject end end), true); else if CallBackFunc then if Obj ~= nil then CallBackFunc(Obj, UE.AsyncCachedItems[AssetPath]) else CallBackFunc(UE.AsyncCachedItems[AssetPath]) end end end end ---@param AssetPath:string ---@param SaveAsset:bool 是否保存 function UE.LoadAsset_New(AssetPath, SaveAsset) if SaveAsset == nil then SaveAsset = true end if not UE.IsValid(UE.AsyncCachedItems[AssetPath]) then local TargetAsset = UE.LoadObject(AssetPath) if SaveAsset and UE.IsValid(TargetAsset) then UE.AsyncCachedItems[AssetPath] = TargetAsset end return TargetAsset else return UE.AsyncCachedItems[AssetPath] end end -- New End ------------------------------------- function UE.AsyncLoadObj(Path, cb) CommonUtils:AsyncLoadObject(UGCGameSystem.GameState, Path, function(TargetObject) if TargetObject and UE.IsValid(TargetObject) then if cb then cb(TargetObject); end end end) end --- 移除 function UE.ClearSceneObjects() for i, v in pairs(UE.ResetClassPath) do local Class = ScriptGameplayStatics.FindClass(v); if UE.IsValid(Class) then local Actors = {}; UE.FindActorsByClass(Class, Actors); for c, Actor in pairs(Actors) do Actor:K2_DestroyActor(); end end end end ---@param InFunc fun(Pawn:UGCPlayerPawn_C) function UE.ForeachAllPawns(InFunc) for i, Pawn in pairs(UGCGameSystem.GetAllPlayerPawn()) do if UE.IsValidPawn(Pawn) then InFunc(Pawn); end end end ---@param InPawn UGCPlayerPawn_C function UE.IsValidPawn(InPawn) return InPawn ~= nil and UE.IsValid(InPawn) and InPawn:IsAlive(); end UE.ResetGameTimer = nil; --- 游戏重置 function UE.ResetGame(InTime) UGCLogSystem.Log("[UE.ResetGame] 重置游戏") UE.ClearSceneObjects() if IsServer then -- 检测是否人数够 if GlobalCheckPlayers then GlobalCheckPlayers:OnCheckPlayers(); end UE.RespawnAllPlayer(InTime); end end UE.RespawnPlayersTimer = nil; function UE.RespawnPlayers(InPlayerList, InTime) if InTime <= 0 then -- 立刻重生 for i, v in pairs(InPlayerList) do UE.RespawnPlayer(v, 0); end else UGCEventSystem.SetTimer(GameState, function() for _, PlayerKey in pairs(InPlayerList) do UE.RespawnPlayer(v, 0); end end, InTime); end end ---@param InFunc fun(PC:UGCPlayerController_C) function UE.ForeachAllPCs(InFunc) for i, PC in pairs(UGCGameSystem.GetAllPlayerController(false)) do if PC and UE.IsValid(PC) then InFunc(PC); end end end function UE.RespawnAllPlayer(InTime) if InTime == nil or InTime <= 0 then UE.ForeachAllPCs(function(PC) local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PC.PlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(PC.PlayerKey); end); else UGCEventSystem.SetTimer(GameState, function() UE.ForeachAllPCs(function(PC) local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PC.PlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(PC.PlayerKey); end) end, InTime); end end function UE.HasPlayer(InPlayerKey) return UE.GetAccountInfo(InPlayerKey) ~= nil; end UE.ResetGameTimer = nil; function UE.CanReset() return UE.ResetGameTimer == nil; end function UE.ResetGameInterval(Force, InTime, InFunc) local PawnCount = 0; for i, v in pairs(UGCGameSystem.GetAllPlayerPawn()) do if UE.IsValidPawn(v) then PawnCount = PawnCount + 1; end end if PawnCount < 2 or Force then UGCLogSystem.Log("[UE.ResetGameInterval] 所有玩家重置") -- 检查是否是只有一个玩家 local AlivePawnCount = table.getCount(UGCGameSystem.GetAllPlayerController(false)); if AlivePawnCount <= 1 then -- 关闭 if GlobalCheckPlayers then GlobalCheckPlayers:OnCheckPlayers(); end if UE.ResetGameTimer ~= nil then -- 关闭重置 Timer if InFunc then InFunc(); end UGCLogSystem.Log("[UE.ResetGameInterval] 关闭重置玩家 Timer") UGCEventSystem.StopTimer(UE.ResetGameTimer); UE.ResetGameTimer = nil; end return ; end UE.ResetGame(InTime); -- 检查是否可以复活 if PoisonManager then UGCLogSystem.Log("[UE.ResetGameInterval] 重置毒圈") PoisonManager:Toggle(true); -- 确保没事了再刷新毒圈 end end if PawnCount == 2 and not Force then -- 关闭 if UE.ResetGameTimer ~= nil then -- 关闭重置 Timer if InFunc then InFunc(); end UGCLogSystem.Log("[UE.ResetGameInterval] 关闭重置玩家 Timer") UGCEventSystem.StopTimer(UE.ResetGameTimer); UE.ResetGameTimer = nil; end end end ---@param InFunc fun() 完全重置之后再执行的函数 function UE.ResetGame1(InTime, InFunc) -- 首先执行一遍, UGCLogSystem.Log("[UE.ResetGame1] 开始重置") UE.ResetGameInterval(true, InTime, InFunc); if UE.CanReset() then UGCLogSystem.Log("[UE.ResetGame1] 可以执行重置") UE.ResetGameTimer = UGCEventSystem.SetTimerLoop(GameState, function() UE.ResetGameInterval(false, InTime, InFunc); end, 1); end end function UE.GetMiniRepData(InKey) if not table.isEmpty(GameState.MiniInfo) then return GameState.MiniInfo[InKey]; end return nil; end function UE.CloseServer() -- 检查玩家是否退出了 UGCEventSystem.SetTimer(UGCGameSystem.GameState, function() UGCGameSystem.SendModeCustomEvent("GameOver"); -- 直接关闭 end, 6); end function UE.GetClassByName(InName) local Class = ScriptGameplayStatics.FindClass(InName) if Class and UE.IsValid(Class) then return Class; end return nil; end function UE.OnCloseDS() --停止检测DS连接 if NetUtil then NetUtil.StopCheckDSActive(); end --忽略DS链接报错 if BattleResult then BattleResult.IgnoreDSError = true; end end function UE.GetLocalPawn() return UGCGameSystem.GetPlayerPawnByPlayerKey(LocalPlayerKey); end