210 lines
6.6 KiB
Lua
Raw Normal View History

2025-01-04 23:00:19 +08:00
---@class SceneObject
---@field InUseTable table<int32, FString>
---@field UnusedTable table<int32, FString>
---@field AllTable table<FString, SceneObjectItem>
---@field RefreshTime float
---@field IsLimit bool
---@field TotalCount int32
---@field InSpawnCount int32
---@field new fun(InTable:SceneObjItem):SceneObject
---@field LoadSceneItem fun(InClass:UClass)
---@field InitSceneItems fun()
---@field OnUseSceneItem fun(InItem:BP_CustomItemBase_C, InPawn:UGCPlayerPawn_C)
---@field SetOneItemToUse fun(IsInit:bool)
---@field SetOneItemToUnused fun()
---@field ChangeItemCount fun(InCount:int32)
---@field GetTotalCount fun():int32
---@field GetAllItemTable fun():table<FString, SceneObjectItem>
---@field GetSetIds fun():table<int32, int32>
---@field GetUnusedCount fun():int32
---@field GetInUseCount fun():int32
---@field GetAllItemCount fun():int32
---@field GetNearItem fun(InPawn:UGCPlayerPawn_C):BP_CustomItemBase_C
local SceneObject = {};
--- 加载地图上的所有 Buff
---@class SceneObjectItem
---@field Item BP_CustomItemBase_C
---@field IsSet bool 是否设置了Buff
---@field LastTime float 最后一次设置 Buff 的时间
---@field DisToCenter float 距离中心点的长度
---@type table<int32, FString> 正在使用的表
SceneObject.InUseTable = {};
---@type table<int32, FString> 未使用的表
SceneObject.UnusedTable = {};
---@type table<FString, SceneObjectItem> 所有物品表
SceneObject.AllTable = {};
SceneObject.RefreshTime = 0;
SceneObject.IsLimit = false;
SceneObject.TotalCount = 0;
SceneObject.EventType = nil;
--- 已经使用但是还未生成的数量
SceneObject.InSpawnCount = 0;
---@param InTable SceneObjItem
function SceneObject:new(InTable)
return setmetatable({
RefreshTime = InTable.RefreshTime,
IsLimit = InTable.IsLimit,
TotalCount = InTable.TotalCount,
EventType = InTable.EventType,
InUseTable = {},
UnusedTable = {},
AllTable = {},
InSpawnCount = 0,
}, {
__metatable = self,
__index = self,
});
end
---@param InClass UClass
---@param InTable table<int32, AActor>
function SceneObject:LoadSceneItem(InClass, InTable)
local CenterLoc = GameState:GetCenterPointLocation();
if table.isEmpty(InTable) then
local AllActors = {};
UE.FindActorsByClass(InClass, AllActors, function(InIndex, InActor)
self:AddOneItemToTableInternal(InActor, CenterLoc);
return true;
end);
else
for i, v in pairs(InTable) do
if UE.IsA(v, InClass) then
self:AddOneItemToTableInternal(v, CenterLoc);
end
end
end
UGCLogSystem.LogTree(string.format("[SceneObject:LoadSceneItem] self.AllTable ="), self.AllTable)
if self.IsLimit then self:InitSceneItems(); end
--- 进行绑定
UGCEventSystem.AddListener(self.EventType, self.OnUseSceneItem, self)
end
---@private
---@param v AActor
---@param CenterLoc FVector
function SceneObject:AddOneItemToTableInternal(v, CenterLoc)
local Name = UE.GetName(v)
self.AllTable[Name] = {
Item = v,
IsSet = false,
LastTime = -1,
DisToCenter = VectorHelper.GetDistance2D(CenterLoc, v:K2_GetActorLocation());
};
table.insert(self.UnusedTable, Name);
end
function SceneObject:InitSceneItems()
if IsServer then
local AllItemCount = self:GetAllItemCount();
self.TotalCount = math.ceil(AllItemCount * self.TotalCount / (self.TotalCount <= 1 and 1 or 100))
if self.TotalCount > AllItemCount then self.TotalCount = AllItemCount; end
UGCLogSystem.Log("[SceneObject:InitSceneItems] self.TotalCount = %s", tostring(self.TotalCount))
for i = 1, self.TotalCount do self:SetOneItemToUse(true); end
UGCLogSystem.LogTree(string.format("[SceneObject:InitSceneItems] self.InUseTable ="), self.InUseTable)
end
end
function SceneObject:OnUseSceneItem(InItem, InPawn)
if IsServer then
UGCLogSystem.Log("[SceneObject:OnUseSceneItem] InItem = %s", UE.GetName(InItem))
if not self.IsLimit then return end
local Name = UE.GetName(InItem);
table.removeValue(self.InUseTable, Name);
self.AllTable[Name].IsSet = false;
table.insert(self.UnusedTable, Name);
UGCEventSystem.SetTimer(GameState, function() self:SetOneItemToUse(false) end, self.RefreshTime);
end
end
function SceneObject:SetOneItemToUse(IsInit)
if IsServer then
if self:GetUnusedCount() == 0 then return; end
table.Shuffle(self.UnusedTable);
local ItemName = self.UnusedTable[1];
table.remove(self.UnusedTable, 1)
local SceneItem = self.AllTable[ItemName];
UGCLogSystem.Log("[SceneObject:SetOneItemToUse] ItemName = %s", ItemName);
SceneItem.Item:PreRandomNewItem();
SceneItem.Item:RandomNewItem();
SceneItem.IsSet = true;
SceneItem.LastTime = UE.GetCurrentTime();
table.insert(self.InUseTable, ItemName)
SceneItem.Item:OnPostRandomNewItem();
if not IsInit then self.InSpawnCount = self.InSpawnCount - 1; end
end
end
---@param InCount int32
function SceneObject:ChangeItemCount(InCount)
if IsServer then
local CurrCount = self:GetInUseCount();
local TotalCount = self.InSpawnCount + CurrCount;
if TotalCount < InCount then
for i = 1, InCount - TotalCount do self:SetOneItemToUse(true) end
elseif TotalCount > InCount then
for i = 1, TotalCount - InCount do self:SetOneItemToUnused(); end
end
self.TotalCount = InCount;
end
end
---@param InNew float
function SceneObject:ChangeItemPercent(InNew)
self:ChangeItemCount(InNew * self:GetAllItemCount());
end
--- 拿出一个来使用
function SceneObject:SetOneItemToUnused()
if IsServer then
table.Shuffle(self.InUseTable)
local Name = self.InUseTable[1];
table.remove(self.InUseTable, 1);
self.AllTable[Name].IsSet = true;
self.AllTable[Name].Item:ResetItem();
table.insert(self.UnusedTable, Name)
end
end
---@param InPawn UGCPlayerPawn_C
function SceneObject:GetNearItem(InPawn)
local TargetDis, Actor = 1000000, nil;
for i, v in pairs(self.InUseTable) do
local Dis = VectorHelper.GetActorDis2D(InPawn, self.AllTable[v].Item)
if TargetDis > Dis then
TargetDis = Dis;
Actor = self.AllTable[v].Item;
end
end
return Actor;
end
---@param InTable table<int32, int32>
---@return table<int32, BP_CustomItemBase_C>
function SceneObject:GetSetIds(InTable)
if InTable == nil then InTable = {}; end
for i, v in pairs(self.InUseTable) do table.insert(InTable, self.AllTable[v].Item:GetItemId()); end
return InTable;
end
---@return int32
function SceneObject:GetTotalCount() return self.TotalCount; end
---@return table<string, SceneObjectItem>
function SceneObject:GetAllItemTable() return self.AllTable; end
---@return int32
function SceneObject:GetUnusedCount() return table.getCount(self.UnusedTable); end
---@return int32
function SceneObject:GetInUseCount() return table.getCount(self.InUseTable); end
---@return int32
function SceneObject:GetAllItemCount() return table.getCount(self.AllTable); end
return SceneObject;