---@class BP_LaunchFloorManager_C:AActor ---@field DefaultSceneRoot USceneComponent ---@field FloorClass UClass ---@field FloorHealth float ---@field FloorPointClass UClass --Edit Below-- local BP_LaunchFloorManager = { AllFloors = {}; LastNotifyHealthTime = 0; NotifyHealthDelayTime = 0.1; NeedNotifyHealth = false; UpdateFloorHealthList = {} }; function BP_LaunchFloorManager:ReceiveBeginPlay() self.SuperClass.ReceiveBeginPlay(self); if UGCGameSystem.IsServer() then local FloorPoints = GameplayStatics.GetAllActorsOfClass(self, self.FloorPointClass, {}) for i, v in pairs(FloorPoints) do self:SpawnFloors(v) end end end function BP_LaunchFloorManager:ReceiveTick(DeltaTime) self.SuperClass.ReceiveTick(self, DeltaTime); if UGCGameSystem.IsServer() then self.LastNotifyHealthTime = self.LastNotifyHealthTime + DeltaTime if self.NeedNotifyHealth and self.LastNotifyHealthTime > self.NotifyHealthDelayTime then self.LastNotifyHealthTime = 0 self.NeedNotifyHealth = false UGCSendRPCSystem.ActorRPCNotify(nil, self, "ClientUpdateFloorHealth", self.UpdateFloorHealthList) self.UpdateFloorHealthList = {} end end end function BP_LaunchFloorManager:SpawnFloors(SpawnPoint) if SpawnPoint.Layer <= 0 then return end -- 获取两六边形地板间隔 local FloorWidth = SpawnPoint.Radius * math.sqrt(3) local ActorForward = self:GetActorForwardVector() local ActorPos = SpawnPoint:K2_GetActorLocation() local ActorRot = SpawnPoint:K2_GetActorRotation() -- 中心生成一个 self:SpawnFloorFromPos(ActorPos, ActorRot, SpawnPoint.ResetTime) -- 循环生成 for NowLayer = 1, SpawnPoint.Layer - 1 do -- 6个边 for side = 0, 5 do local NowDir = KismetMathLibrary.GreaterGreater_VectorRotator(ActorForward, {Roll = 0, Pitch = 0, Yaw = side * 60}) local MoveDir = KismetMathLibrary.GreaterGreater_VectorRotator(NowDir, {Roll = 0, Pitch = 0, Yaw = 120}) local NowSpawnPos = VectorHelper.MulNumber(NowDir, NowLayer * FloorWidth) for MoveSpawnIndex = 0, NowLayer - 1 do local TargetPos = VectorHelper.Add(VectorHelper.Add(NowSpawnPos, VectorHelper.MulNumber(MoveDir, MoveSpawnIndex * FloorWidth)), ActorPos) self:SpawnFloorFromPos(TargetPos, ActorRot, SpawnPoint.ResetTime) end end end end function BP_LaunchFloorManager:SpawnFloorFromPos(Pos, ActorRot, ResetTime) local Floor = UGCGameSystem.SpawnActor(self, self.FloorClass, Pos, ActorRot, VectorHelper.ScaleOne(), nil) self.AllFloors[#self.AllFloors + 1] = Floor Floor:SetID(#self.AllFloors) Floor:SetResetFloorTime(ResetTime) Floor:SetMaxHealth(self.FloorHealth) Floor:BindDamageCallBack(self.FloorDamageCallBack, self) return Floor end function BP_LaunchFloorManager:FloorDamageCallBack(FloorID, Health) if self.UpdateFloorHealthList[FloorID] and Health == 0 then self.UpdateFloorHealthList[FloorID] = nil else self.UpdateFloorHealthList[FloorID] = Health self.NeedNotifyHealth = true end end function BP_LaunchFloorManager:ClientUpdateFloorHealth(InUpdateFloorHealthList) UGCLogSystem.LogTree("[BP_LaunchFloorManager_ClientUpdateFloorHealth]", InUpdateFloorHealthList) for FloorID, Health in pairs(InUpdateFloorHealthList) do if self.AllFloors[FloorID] then self.AllFloors[FloorID]:UpdateClientHealth(self.FloorHealth, Health) end end end function BP_LaunchFloorManager:SetAllFloorActive(IsActivate) for i, v in pairs(self.AllFloors) do v:SetIsActivate(IsActivate, true) end end function BP_LaunchFloorManager:ReceiveEndPlay() if UGCGameSystem.IsServer() then for i, v in pairs(self.AllFloors) do if UE.IsValid(v) then v:K2_DestroyActor() end end end self.SuperClass.ReceiveEndPlay(self); end function BP_LaunchFloorManager:GetReplicatedProperties() return "AllFloors" end --[[ function BP_LaunchFloorManager:GetAvailableServerRPCs() return end --]] return BP_LaunchFloorManager;