---@type table ---@private UE.CachedClasses = {}; --- 组件位置 UE.ComponentPath = { Camera = "/Script/Engine.CameraComponent", SpringArm = "/Script/Engine.SpringArmComponent", } ---@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 ---@return table function UE.InitArchiveData() return { GameTimes = 0, } 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 == nil or InTime <= 0 then local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InPlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(InPlayerKey); return; end UGCEventSystem.SetTimer(GameState, function() local Pawn = UGCGameSystem.GetPlayerPawnByPlayerKey(InPlayerKey); if Pawn then Pawn:K2_DestroyActor(); end UGCGameSystem.RespawnPlayer(InPlayerKey); end, InTime); end --- 获取当前时间 function UE.GetCurrentTime() return KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState); end ---@param InPlayerKey PlayerKey ---@return PlayerAccountInfo function UE.GetAccountInfo(InPlayerKey) return GameState.PlayerDatas.AccountInfo[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 --- 激活对应的 Camera ---@param InPawn UGCPlayerPawn_C ---@param InCamera UCameraComponent ---@param InArm USpringArmComponent function UE.ActiveCamera(InPawn, InCamera, InArm) if InPawn == nil then return end UE.ForeachComponent(InPawn, UE.ComponentPath.Camera, function(c) c:Deactivate() end) UE.ForeachComponent(InPawn, UE.ComponentPath.SpringArm, function(c) c:Deactivate() end) InCamera:Activate(); InArm:Activate(); table.func(InPawn, "SetCurrentCamera", InCamera, InArm); end --- 遍历 Actor 上面的所有组件 ---@param InActor AActor ---@param InComponent UActorComponent ---@param cb fun(c: UActorComponent) function UE.ForeachComponent(InActor, InComponent, cb) local Path = UE.ComponentPath[InComponent] == nil and InComponent or UE.ComponentPath[InComponent]; for i, v in pairs(InActor:GetComponentsByClass(LoadClass(Path))) do cb(v); end end ---清空地图上的 Wrapper function UE.ClearWrappers(bWeapon, bPart, bBullet, bEquipment, bSkin, bSupplies) local AllActors = {}; local Func = function(b) if b == nil then return true end return b; end bWeapon = Func(bWeapon); bPart = Func(bPart); bBullet = Func(bBullet); bEquipment = Func(bEquipment); bSkin = Func(bSkin); bSupplies = Func(bSupplies); UE.FindActorsByClass(GameState:GetWrapperClass(), AllActors, function(InIndex, InActor) if InActor.DefineID == nil then return true; end local ItemId = InActor.DefineID.TypeSpecificID; if ItemId == nil or (not InActor.DefineID.bValidItem) then return true; end UGCLogSystem.Log("[UE.ClearWrappers] ItemId = %s", tostring(ItemId)); local Type = GetCustomItemType(ItemId); if (bWeapon and Type == ECustomItemType.Weapon) or (bPart and Type == ECustomItemType.Part) or (bBullet and Type == ECustomItemType.Bullet) or (bEquipment and Type == ECustomItemType.Equipment) or (bSkin and Type == ECustomItemType.Skin) or (bSupplies and Type == ECustomItemType.Supplies) then InActor:K2_DestroyActor() end end); end --- 组件朝向玩家 ---@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