---@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;