222 lines
6.4 KiB
Lua
Raw Normal View History

2025-01-04 23:00:19 +08:00
---@class BP_RadiationCircle_C:AActor
---@field Sphere USphereComponent
---@field DefaultSceneRoot USceneComponent
---@field GunClass UClass
---@field BulletClass UClass
---@field GunMaxNum int32
---@field BulletMaxNum int32
---@field BulletLiftTime float
---@field BulletFlySpeed float
---@field SpawnGunSpeedCurve UCurveFloat
---@field MiniYawInterval float
--Edit Below--
---@class GunInfoItem
---@field Gun BP_FireGun_C
---@field bIsInUse boolean
---@field bIsVisible boolean
---@type BP_RadiationCircle_C
local BP_RadiationCircle = {
GunActors = {};
BulletActors = {};
GetGunIndex = 1;
GetBulletIndex = 1;
LastSpawnGunTime = 0;
MiniGameTime = 1;
StartTime = 0.;
bActive = false;
CenterPos = {X = 0, Y = 0, Z = 0};
RangeRadius = 0.;
-- 达标的Yaw旋转其对应的是火炮的Yaw旋转
QualifyYaws = {};
RemoveQualifyYawHandles = {};
RemoveQualifyYawID = 10000;
};
function BP_RadiationCircle:ReceiveBeginPlay()
self.SuperClass.ReceiveBeginPlay(self);
-- 加载一下场景中的东西
if UGCGameSystem.IsServer() then
self.MiniGameTime = MiniGameConfig.MiniGameInfo[MiniGameConfig.MiniGameType.AvoidBall].MaxGameTime
self.CenterPos = self:K2_GetActorLocation()
self.RangeRadius = self.Sphere:GetScaledSphereRadius()
UGCLogSystem.Log("[BP_RadiationCircle_ReceiveBeginPlay] CenterPos:%s, RangeRadius:%s", VectorHelper.ToString(self.CenterPos), tostring(self.RangeRadius))
-- UGCEventSystem.SetTimer(self, self.SpawnGunAndBullet, 5)
self:SpawnGunAndBullet();
end
end
function BP_RadiationCircle:ActiveGame()
self.StartTime = UGCSystemLibrary.GetGameTime()
self.bActive = true
UGCLogSystem.Log("[BP_RadiationCircle_ActiveGame]")
end
function BP_RadiationCircle:StopGame()
self.bActive = false
end
function BP_RadiationCircle:ClearGunAndBullet()
for i, v in pairs(self.GunActors) do
v:K2_DestroyActor()
end
for i, v in pairs(self.BulletActors) do
v:K2_DestroyActor()
end
self.BulletActors = {}
self.GunActors = {}
end
function BP_RadiationCircle:SpawnGunAndBullet()
for i = 1, self.GunMaxNum do
local Gun = UGCGameSystem.SpawnActor(self, self.GunClass, {X = 0, Y = 0, Z = -1000}, VectorHelper.RotZero(), VectorHelper.ScaleOne(), nil)
self.GunActors[#self.GunActors + 1] = Gun
end
for i = 1, self.BulletMaxNum do
local Bullet = UGCGameSystem.SpawnActor(self, self.BulletClass, {X = 0, Y = 0, Z = -1000}, VectorHelper.RotZero(), VectorHelper.ScaleOne(), nil)
self.BulletActors[#self.BulletActors + 1] = Bullet
end
end
function BP_RadiationCircle:GetNextGun()
local Res = self.GunActors[self.GetGunIndex]
self.GetGunIndex = (self.GetGunIndex % #self.GunActors) + 1
return Res
end
function BP_RadiationCircle:GetNextBullet()
local Res = self.BulletActors[self.GetBulletIndex]
self.GetBulletIndex = (self.GetBulletIndex % #self.BulletActors) + 1
return Res
end
function BP_RadiationCircle:GetNextTargetPawn()
local AllPawns = UGCGameSystem.GetAllPlayerPawn()
local Random = math.random(1, #AllPawns)
return AllPawns[Random]
end
function BP_RadiationCircle:ReceiveTick(DeltaTime)
self.SuperClass.ReceiveTick(self, DeltaTime);
-- 这是服务器
if UGCGameSystem.IsServer() and self.bActive then
local NowTime = UGCSystemLibrary.GetGameTime()
local ShotInterval = self.SpawnGunSpeedCurve:GetFloatValue((NowTime - self.StartTime) / self.MiniGameTime)
self.LastSpawnGunTime = self.LastSpawnGunTime + DeltaTime;
if self.LastSpawnGunTime >= ShotInterval then
self.LastSpawnGunTime = 0;
self:ExeGunFire();
end
end
end
-- 激活炮台开炮
function BP_RadiationCircle:ExeGunFire()
local TargetPawn = self:GetNextTargetPawn()
if TargetPawn == nil then
UGCLogSystem.LogError("[BP_RadiationCircle_ExeGunFire] TargetPawn is nil")
return
end
local Gun = self:GetNextGun()
local Bullet = self:GetNextBullet()
local PawnPos = TargetPawn:K2_GetActorLocation()
local GunPos, GunRot = self:GetGunTargetPosAndRot(PawnPos, KismetMathLibrary.RandomBool())
Gun:FireBullet(GunPos, GunRot, Bullet)
end
--- 获取炮台激活点位
---@param IsReverse 是否反向半径
function BP_RadiationCircle:GetGunTargetPosAndRot(PawnPos, IsReverse)
local MulReverseNum = (IsReverse and -1 or 1)
local Dir = VectorHelper.Sub(PawnPos, self.CenterPos)
--Dir.Z = 0
local DirRot = KismetMathLibrary.MakeRotFromX(Dir)
-- 获取合格的Yaw方向为的是防止出现穿模
local TargetYaw = self:GetQualifyYaw(DirRot.Yaw)
self.QualifyYaws[#self.QualifyYaws + 1] = TargetYaw
local HandleID = self:GetNewID()
self.RemoveQualifyYawHandles[HandleID] = UGCEventSystem.SetTimer(self, function()
table.removeValue(self.QualifyYaws, TargetYaw, true)
self.RemoveQualifyYawHandles[HandleID] = nil
end, 3.)
Dir = VectorHelper.MulNumber(KismetMathLibrary.GetForwardVector({Roll = 0, Pitch = 0, Yaw = TargetYaw}), MulReverseNum)
-- Dir = VectorHelper.MulNumber(Dir, 1./ VectorHelper.Length(Dir) * MulReverseNum)
local TargetRot = VectorHelper.RotToLuaTable(KismetMathLibrary.MakeRotFromX(VectorHelper.MulNumber(Dir, -1)))
-- local TargetRot = {Roll = 0, Pitch = 0, Yaw = (IsReverse and TargetYaw or (360 - TargetYaw))}
local TargetPos = VectorHelper.ToLuaTable(VectorHelper.Add(self.CenterPos, VectorHelper.MulNumber(Dir, self.RangeRadius)))
TargetPos.Z = self.CenterPos.Z
return TargetPos, TargetRot
end
function BP_RadiationCircle:GetQualifyYaw(TargetYaw)
local CheckInterval = self.MiniYawInterval / 2
local TempIsQualify
local TempYaw = 0
for i = 0, math.floor(180 / CheckInterval) do
TempIsQualify = true
TempYaw = TargetYaw + i * CheckInterval
for _, Yaw in pairs(self.QualifyYaws) do
if math.abs(Yaw - TempYaw) < self.MiniYawInterval then
TempIsQualify = false
break
end
end
if TempIsQualify then
return TempYaw
end
TempIsQualify = true
TempYaw = TargetYaw - i * CheckInterval
for _, Yaw in pairs(self.QualifyYaws) do
if math.abs(Yaw - TempYaw) < self.MiniYawInterval then
TempIsQualify = false
break
end
end
if TempIsQualify then
return TempYaw
end
end
return TargetYaw
end
function BP_RadiationCircle:GetNewID()
self.RemoveQualifyYawID = self.RemoveQualifyYawID + 1
return self.RemoveQualifyYawID
end
function BP_RadiationCircle:ReceiveEndPlay()
for i, v in pairs(self.RemoveQualifyYawHandles) do
UGCEventSystem.StopTimer(v)
end
if UGCGameSystem.IsServer() then
self:ClearGunAndBullet()
end
self.SuperClass.ReceiveEndPlay(self);
end
function BP_RadiationCircle:GetReplicatedProperties()
return
end
--[[
function BP_RadiationCircle:GetAvailableServerRPCs()
return
end
--]]
return BP_RadiationCircle;