---@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): int32|bool|string|any ---@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 then local val = InFunc(i, v) if val then if type(val) == 'boolean' then table.insert(InTable, v); else InTable[val] = v; end end else table.insert(InTable, v); end end return InTable; 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) local Count = table.getCount(Actors); print(string.format('[UE.FindOrCreateActorByClass] 查找完毕,一共找到 %d 个元素', Count)); if Count > 0 then log_tree('[UE.FindOrCreateActorByClass] Actors = ', Actors); end 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, InOuter, InCount) if InOuter == nil then InOuter = UGCGameSystem.GameState; end if InCount == nil then InCount = 1 end local Actors = {}; for i = 1, InCount do local Actor = UGCGameSystem.SpawnActor(InOuter, InClass, VectorHelper.VectorZero(), VectorHelper.RotZero(), VectorHelper.ScaleOne(), InOuter); Actors[#Actors + 1] = Actor; end if InCount == 1 then return Actors[1]; end return Actors; end --- 玩家重生 ---@param InPlayerKey PlayerKey ---@param InTime float function UE.RespawnPlayer(InPlayerKey, InTime) 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 UGCGameSystem.GameState.PlayerDatas.AccountInfo[InPlayerKey]; end --- 移动玩家到某个地方 ---@param InPawn UGCPlayerPawn_C ---@param Location FVector ---@param Rotation FRotator function UE.MovePlayerToLocation(InPawn, Location, Rotation) 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) -- 关闭所有其他的相机,然后开启 默认 相机 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(UGCGameSystem.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 Type == ECustomItemType.Weapon then if bWeapon then return true; end elseif Type == ECustomItemType.Part then if bPart then return true; end elseif Type == ECustomItemType.Bullet then if bBullet then return true; end elseif Type == ECustomItemType.Equipment then if bEquipment then return true; end elseif Type == ECustomItemType.Skin then if bSkin then return true; end elseif Type == ECustomItemType.Supplies then if bSupplies then return true; end end return false; end); for i, v in pairs(AllActors) do v:K2_DestroyActor(); end end --- 组件朝向玩家 ---@param InComponent USceneComponent ---@param InActor AActor function UE.ComponentTowardActor(InComponent, InActor) if LocalPlayerKey == nil then return; end local Vec = VectorHelper.Sub(InActor:K2_GetActorLocation(), InComponent:GetOwner():K2_GetActorLocation()); Vec = VectorHelper.Normalize(Vec) InComponent:K2_SetWorldRotation(VectorHelper.VecToRot(Vec)); 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 and InFunc(v)) or InFunc == nil then v:K2_DestroyActor() end end InTable = {}; end function UE.RespawnAllPlayer(InTime) 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 if InTime == nil or InTime <= 0 then for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do UGCGameSystem.RespawnPlayer(v.PlayerKey); end else UGCEventSystem.SetTimer(UGCGameSystem.GameState, function() for i, v in pairs(UGCGameSystem.GetAllPlayerController(false)) do UGCGameSystem.RespawnPlayer(v.PlayerKey); end end, InTime); end end ---@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 UE.AsyncCachedItems = {}; ---@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