UGCSystemLibrary = UGCSystemLibrary or {} UGCSystemLibrary.IsServer = nil -- 缓存的资产 UGCSystemLibrary.CacheAsset = {} ------------------------------------------------ 获取本地信息 ------------------------------------------------ function UGCSystemLibrary.GetLocalPlayerController() if not UE.IsValid(UGCSystemLibrary.LocalController) and UGCGameSystem.GameState then UGCSystemLibrary.LocalController = STExtraGameplayStatics.GetFirstPlayerController(UGCGameSystem.GameState) end return UGCSystemLibrary.LocalController end function UGCSystemLibrary.GetLocalPlayerKey() return UGCSystemLibrary.GetLocalPlayerController().PlayerKey end function UGCSystemLibrary.GetLocalPlayerPawn() return UGCGameSystem.GetPlayerPawnByPlayerKey(UGCSystemLibrary.GetLocalPlayerKey()) end function UGCSystemLibrary.GetGameTime() if UGCGameSystem.GameState then return KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState) else return 0. end end ---------------------------------------------- 获取本地信息 End ---------------------------------------------- --- 通过资产路径去获取场景唯一实例 ---@param AssetPath string function UGCSystemLibrary.GetUniqueInstanceFromPath(AssetPath) local ObjClass = UE.LoadClass(AssetPath) if UE.IsValid(ObjClass) then local AllActor = ScriptGameplayStatics.GetActorsOfClass(UGCGameSystem.GameState, ObjClass) for i, v in pairs(AllActor) do return v end end return nil end local RootPackagePath = UGCMapInfoLib.GetRootLongPackagePath() function UGCSystemLibrary.GetFullPath(InPath) if type(InPath) ~= "string" then return "" end if #RootPackagePath > #InPath or string.sub(InPath, 1, #RootPackagePath) ~= RootPackagePath then InPath = RootPackagePath..InPath end return InPath end ------------------------------------------ Load ------------------------------------------ --- {URL = Asset} UGCSystemLibrary.DownloadImageAsset = {} --- 下载图像 function UGCSystemLibrary.DownloadImage(URL, bSaveAsset, CallBackFunc, Obj) if UE.IsValid(UGCSystemLibrary.DownloadImageAsset[URL]) then if Obj then CallBackFunc(Obj, UGCSystemLibrary.DownloadImageAsset[URL]) else CallBackFunc(UGCSystemLibrary.DownloadImageAsset[URL]) end else local ResHandle = AsyncTaskDownloadImage.DownloadImage(URL) --ResHandle.OnSuccess:Add(CallBackFunc, Obj) --ResHandle.OnFail:Add(CallBackFunc, Obj) ResHandle.OnSuccess:Add(CallBackFunc) ResHandle.OnFail:Add(CallBackFunc) if bSaveAsset then ResHandle.OnSuccess:Add( function(Texture) UGCSystemLibrary.DownloadImageAsset[URL] = Texture end ) end end end --- 下载图像至UImage ---@param Image UImage* ---@param URL string function UGCSystemLibrary.DownloadImageToUImage(Image, URL) UGCSystemLibrary.DownloadImage(URL, true, function(Texture) if UE.IsValid(Texture) then Image:SetBrushFromTextureDynamic(Texture) else UGCLogSystem.LogError("[UGCSystemLibrary_DownloadImageToUImage] Download Texture Failure. URL: %s", URL) end end ) end ---------------------------------------- Load End ---------------------------------------- function UGCSystemLibrary.BindBeginOverlapFunc(CollisionComponent, Func, Obj) CollisionComponent.OnComponentBeginOverlap:Add(Func, Obj) end function UGCSystemLibrary.BindEndOverlapFunc(CollisionComponent, Func, Obj) CollisionComponent.OnComponentEndOverlap:Add(Func, Obj) end function UGCSystemLibrary.formatTime(seconds, ShowMinutes, ShowHours, ShowRemainingSeconds) if ShowMinutes == nil then ShowMinutes = false end if ShowHours == nil then ShowHours = false end if ShowRemainingSeconds == nil then ShowRemainingSeconds = false end local hours = math.floor(seconds / 3600) local minutes = math.floor((seconds - hours * 3600) / 60) local remainingSeconds = seconds - hours * 3600 - minutes * 60 local ResTime = "" ResTime = ResTime .. ((hours > 0 or ShowHours) and string.format("%02d:", hours) or "") ResTime = ResTime .. ((minutes > 0 or hours > 0 or ShowHours or ShowMinutes) and string.format("%02d:", minutes) or "") ResTime = ResTime .. (ShowRemainingSeconds and string.format("%02.3f", remainingSeconds) or string.format("%02.0f", remainingSeconds)) return ResTime end ---@param AssetPath:string ---@param CallBackFunc:fun(LoadObject:UObject,resID:int32) ---@param Obj:table CallBackFunc拥有者 ---@param SaveAsset:bool 是否保存 function UGCSystemLibrary.AsyncLoadAsset(AssetPath, CallBackFunc, Obj, SaveAsset) if not UE.IsValid(UGCSystemLibrary.CacheAsset[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 UGCSystemLibrary.CacheAsset[AssetPath] = LoadObject end end), true); else if CallBackFunc then if Obj ~= nil then CallBackFunc(Obj, UGCSystemLibrary.CacheAsset[AssetPath]) else CallBackFunc(UGCSystemLibrary.CacheAsset[AssetPath]) end end end end ---@param AssetPath:string ---@param SaveAsset:bool 是否保存 function UGCSystemLibrary.LoadAsset(AssetPath, SaveAsset) if SaveAsset == nil then SaveAsset = true end if not UE.IsValid(UGCSystemLibrary.CacheAsset[AssetPath]) then local TargetAsset = UE.LoadObject(AssetPath) if SaveAsset and UE.IsValid(TargetAsset) then UGCSystemLibrary.CacheAsset[AssetPath] = TargetAsset end return TargetAsset else return UGCSystemLibrary.CacheAsset[AssetPath] end end --- 通过ItemID获取item类型 ---@param ItemID int ---@return int function UGCSystemLibrary.GetItemTypeID(ItemID) return ItemID // 1000 end --- 输入PlayerKey获取活着的玩家,若玩家已死亡或者不存在PlayerKey对应的Pawn时则返回nil ---@param PlayerKey uint ---@return PlayerPawn function UGCSystemLibrary.GetAlivePlayerPawnByPlayerKey(PlayerKey) local PlayerPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey) return (UE.IsValid(PlayerPawn) and PlayerPawn:IsAlive()) and PlayerPawn or nil end --- 最多循环加50次 UGCSystemLibrary.LoopAddItemCountMax = 50 UGCSystemLibrary.LoopAddItemHandle = nil UGCSystemLibrary.PlayerAddItemInfo = {} -- PlayerKey = {ItemID, Count, LoopNum} ---添加道具 ---生效范围:服务器 ---@return bool ---@param PlayerPawn UGCPlayerPawn_C* @玩家角色 ---@param ItemID int32 @物品ID ---@param Count int32 @数量 function UGCSystemLibrary.AddItem(PlayerPawn, ItemID, Count) if UE.IsValid(PlayerPawn) then local bSucceed = UGCBackPackSystem.AddItem(PlayerPawn, ItemID, Count) if not bSucceed then UGCLogSystem.Log("[UGCSystemLibrary_AddItem]") if UGCSystemLibrary.PlayerAddItemInfo[PlayerPawn.PlayerKey] == nil then UGCSystemLibrary.PlayerAddItemInfo[PlayerPawn.PlayerKey] = {} end UGCSystemLibrary.PlayerAddItemInfo[PlayerPawn.PlayerKey][#UGCSystemLibrary.PlayerAddItemInfo[PlayerPawn.PlayerKey] + 1] = {ItemID = ItemID, Count = Count, LoopNum = 0} if UGCSystemLibrary.LoopAddItemHandle == nil then UGCSystemLibrary.LoopAddItemHandle = UGCEventSystem.SetTimerLoop(UGCGameSystem.GameState, function() local PlayerKeys = table.getKeys(UGCSystemLibrary.PlayerAddItemInfo) for _, PlayerKey in PlayerKeys do local ItemInfos = table.DeepCopy(UGCSystemLibrary.PlayerAddItemInfo[PlayerKey]) local TargetPawn = UGCGameSystem.GetPlayerPawnByPlayerKey(PlayerKey) if UE.IsValid(TargetPawn) then for i = #ItemInfos, 1, 1 do bSucceed = UGCBackPackSystem.AddItem(TargetPawn, ItemInfos[i].ItemID, ItemInfos[i].Count) -- 成功加入或者超过添加次数则移除 if bSucceed then UGCSystemLibrary.PlayerAddItemInfo[PlayerKey][i] = nil else if ItemInfos[i].LoopNum >= UGCSystemLibrary.LoopAddItemCountMax then UGCLogSystem.LogError("[UGCSystemLibrary_AddItem] PlayerKey:%s,AddItem:%s Failue", tostring(PlayerKey), tostring(ItemInfos[i].ItemID)) else ItemInfos[i].LoopNum = ItemInfos[i].LoopNum + 1 end end end if #UGCSystemLibrary.PlayerAddItemInfo[PlayerKey] == 0 then UGCSystemLibrary.PlayerAddItemInfo[PlayerKey] = nil end else UGCSystemLibrary.PlayerAddItemInfo[PlayerKey] = nil end end if table.getCount(UGCSystemLibrary.PlayerAddItemInfo) == 0 then UGCEventSystem.StopTimer(UGCSystemLibrary.LoopAddItemHandle) end UGCLogSystem.Log("[UGCSystemLibrary_AddItem] Finish") end, 0.1 ) end end else UGCLogSystem.LogError("[UGCSystemLibrary_AddItem] PlayerPawn is nil") end end --- 判断物体是否可以看到玩家 ---@param ObjectContext UObject 目标物体 ---@param EyePos FVector 物体开始检测的位置 ---@param TargetPlayerPawn PlayerPawn 目标玩家 ---@param LineTraceChannels table 检测的通道,默认为{ECollisionChannel.ECC_WorldStatic, ECollisionChannel.ECC_WorldDynamic, ECollisionChannel.ECC_Pawn} function UGCSystemLibrary.CanSeePlayer(ObjectContext, EyePos, TargetPlayerPawn, LineTraceChannels) if not (UE.IsValid(ObjectContext) and UE.IsValid(TargetPlayerPawn)) then return end if LineTraceChannels == nil then LineTraceChannels = {ECollisionChannel.ECC_WorldStatic, ECollisionChannel.ECC_WorldDynamic, ECollisionChannel.ECC_Pawn} end -- UGCLogSystem.Log("[UGCSystemLibrary_CanSeePlayer] TargetPlayerPawn:%s", KismetSystemLibrary.GetObjectName(TargetPlayerPawn)) --local SkeletonSocketNames = {"head", "spine_01", "hand_l", "hand_r", "foot_r", "foot_l"} local PawnPos = TargetPlayerPawn:K2_GetActorLocation() local UpPawnPos = table.DeepCopy(PawnPos) local DownPawnPos = table.DeepCopy(PawnPos) UpPawnPos.Z = UpPawnPos.Z + 80 DownPawnPos.Z = DownPawnPos.Z - 80 --for i, SocketName in pairs(SkeletonSocketNames) do for i, EndPos in pairs({UpPawnPos, PawnPos, DownPawnPos}) do -- local BornSocketPos = TargetPlayerPawn.Mesh:GetSocketLocation(SocketName) --if BornSocketPos then ---@field LineTraceSingleForObjects fun(WorldContextObject:UObject,Start:FVector,End:FVector,ObjectTypes:ULuaArrayHelper,bTraceComplex:bool,ActorsToIgnore:ULuaArrayHelper,DrawDebugType:EDrawDebugTrace,OutHit:FHitResult,bIgnoreSelf:bool,TraceColor:FLinearColor,TraceHitColor:FLinearColor,DrawTime:float):bool,FHitResult local bSucceed, HitResult = KismetSystemLibrary.LineTraceSingleForObjects(ObjectContext, EyePos, EndPos, LineTraceChannels, false, {ObjectContext, }) if bSucceed then local HitActor = HitResult.Actor:Get() if HitActor == TargetPlayerPawn then return true else UGCLogSystem.Log("[UGCSystemLibrary_CanSeePlayer]HitActorName:%s", KismetSystemLibrary.GetObjectName(HitActor)) end end --else -- UGCLogSystem.LogError("[UGCSystemLibrary_CanSeePlayer] BornSocketPos is nil") --end end return false end --- 获取其他队伍的ID ---@param TeamID uint 忽略的队伍ID ---@return table 其他队伍ID function UGCTeamSystem.GetOtherTeamIDs(TeamID) local TeamIDs = UGCTeamSystem.GetTeamIDs() local Res = {} for i, v in pairs(TeamIDs) do if v ~= TeamID then Res[#Res + 1] = v end end return Res end --- 获取其他队伍的玩家 ---@param TeamID uint 忽略的队伍ID ---@return table 其他玩家PlayerKey function UGCTeamSystem.GetOtherTeamPlayerKeys(TeamID) local OtherTeamIDs = UGCTeamSystem.GetOtherTeamIDs(TeamID) local Res = {} for i, v in pairs(OtherTeamIDs) do local OtherPlayerKeys = UGCTeamSystem.GetPlayerKeysByTeamID(v) for _, PlayerKey in pairs(OtherPlayerKeys) do Res[#Res + 1] = PlayerKey end end return Res end --- 获取队伍成员PlayerKey ---@return PlayerKeys table 队伍玩家PlayerKey function UGCTeamSystem.GetTeammates(PlayerKey) local Res = {} local TeamID = UGCPlayerStateSystem.GetTeamID(PlayerKey) UGCLogSystem.Log("[UGCTeamSystem_GetTeammates] TeamID:%s", tostring(TeamID)) local Teammates = UGCTeamSystem.GetPlayerKeysByTeamID(TeamID) for i, v in pairs(Teammates) do Res[#Res + 1] = v end return Res end