2025-01-04 23:00:19 +08:00

176 lines
6.6 KiB
Lua

---@class BP_AvoidingSpikeStick_C:AActor
---@field TrailingFX UParticleSystemComponent
---@field StaticMesh1 UStaticMeshComponent
---@field StaticMesh UStaticMeshComponent
---@field SM_Stick UStaticMeshComponent
---@field RotatorCmp USceneComponent
---@field DefaultSceneRoot USceneComponent
---@field BeginRotSpeed float
---@field EndRotSpeed float
--Edit Below--
local BP_AvoidingSpikeStick = {
PlayMaxTime = 0.;
PlayTime = 0.;
StartTime = 0.;
bIsPlaying = false;
LastRotCmpRight = {X = 1, Y = 1, Z =1};
LastRotCmpForward = {X = 1, Y = 1, Z =1};
CenterPos = {X = 0, Y = 0, Z =0};
StickZ = 0;
};
function BP_AvoidingSpikeStick:ReceiveBeginPlay()
self.SuperClass.ReceiveBeginPlay(self);
self:InitTrap()
end
function BP_AvoidingSpikeStick:InitTrap()
self.PlayMaxTime = MiniGameConfig.MiniGameInfo[MiniGameConfig.MiniGameType.AvoidingSpikeStick].MaxGameTime
self.CenterPos = self.RotatorCmp:K2_GetComponentLocation()
self.StickZ = self.SM_Stick:K2_GetComponentLocation().Z
self.LastRotCmpForward = self.RotatorCmp:GetForwardVector()
self.LastRotCmpRight = self.RotatorCmp:GetRightVector()
if UGCGameSystem.IsServer() then
-- UGCSystemLibrary.BindBeginOverlapFunc(self.SM_Stick, self.StickOverlapPlayer, self)
else
self.HitParticle = UE.LoadObject(MiniGameConfig.MiniGameInfo[MiniGameConfig.MiniGameType.AvoidingSpikeStick].GameParam.HitParticlePath)
end
end
function BP_AvoidingSpikeStick:StartPlay()
if self.bIsPlaying == false then
self.bIsPlaying = true
self.StartTime = UGCGameSystem.GameState:GetServerGameTime()
DOREPONCE(self, "StartTime")
DOREPONCE(self, "bIsPlaying")
end
end
function BP_AvoidingSpikeStick:StopPlay()
self.bIsPlaying = false
end
function BP_AvoidingSpikeStick:ReceiveTick(DeltaTime)
self.SuperClass.ReceiveTick(self, DeltaTime);
if self.bIsPlaying then
local NowServerTime = UGCGameSystem.GameState:GetServerGameTime()
local TimeDifference = NowServerTime - self.StartTime
local NowSpeed = self.BeginRotSpeed + (self.EndRotSpeed - self.BeginRotSpeed) * TimeDifference / self.PlayMaxTime
local RotYaw = TimeDifference * (NowSpeed + self.BeginRotSpeed) / 2
if UGCGameSystem.IsServer() then
self.RotatorCmp:K2_SetRelativeRotation({Roll = 0., Pitch = 0., Yaw = RotYaw})
self:CheckStickHitPlayer()
--local HitResult = self.SM_Stick:K2_SetRelativeRotation({Roll = 0., Pitch = 90., Yaw = RotYaw}, true)
--local HitActor = HitResult.Actor:Get()
--if HitActor then
-- UGCLogSystem.Log("[BP_AvoidingSpikeStick_ReceiveTick] ActorName:%s", KismetSystemLibrary.GetObjectName(HitActor))
-- if HitActor.PlayerKey then
-- UGCEventSystem.SendEvent(EventEnum.StickOverlapPlayer, HitActor.PlayerKey)
-- end
--
--end
else
self:CheckStickCrossingLocalPlayer()
self.RotatorCmp:K2_SetRelativeRotation({Roll = 0., Pitch = 0., Yaw = RotYaw})
end
end
end
--- 检测两帧棍棒扫过的区域内是否有玩家
function BP_AvoidingSpikeStick:CheckStickHitPlayer()
local RotCmpForward = self.RotatorCmp:GetForwardVector()
local RotCmpRight = self.RotatorCmp:GetRightVector()
RotCmpForward.Z = 0.
local AllPawn = UGCGameSystem.GetAllPlayerPawn()
for i, PlayerPawn in pairs(AllPawn) do
if PlayerPawn.PlayerKey then
if self:CheckCrossingPlayer(PlayerPawn, RotCmpForward, RotCmpRight) then
local PawnPos = PlayerPawn:K2_GetActorLocation()
-- 通过判断棍棒高度是否在玩家当前的高度区间内进行判断是否击中
if PawnPos.Z - 88.0 < self.StickZ and PawnPos.Z + 88.0 > self.StickZ then
-- UGCLogSystem.Log("[BP_AvoidingSpikeStick_ReceiveTick] PlayerKey:%s Hit", tostring(PlayerPawn.PlayerKey))
UGCEventSystem.SendEvent(EventEnum.StickOverlapPlayer, PlayerPawn.PlayerKey)
end
end
end
end
self.LastRotCmpForward = RotCmpForward
self.LastRotCmpRight = RotCmpRight
end
--- 判断杆子越过本地玩家
function BP_AvoidingSpikeStick:CheckStickCrossingLocalPlayer()
local RotCmpForward = self.RotatorCmp:GetForwardVector()
local RotCmpRight = self.RotatorCmp:GetRightVector()
RotCmpForward.Z = 0.
local LocalPawn = UGCSystemLibrary.GetLocalPlayerPawn()
if UE.IsValid(LocalPawn) then
if self:CheckCrossingPlayer(LocalPawn, RotCmpForward, RotCmpRight) then
self:ClientStickCrossingLocalPlayerEffect()
end
end
self.LastRotCmpForward = RotCmpForward
self.LastRotCmpRight = RotCmpRight
end
--- 客户端扫过本地玩家触发特效或者音效
function BP_AvoidingSpikeStick:ClientStickCrossingLocalPlayerEffect()
SoundSystem.PlaySound(SoundSystem.ESound.BreakWind)
end
--- 判断杆子越过玩家
function BP_AvoidingSpikeStick:CheckCrossingPlayer(PlayerPawn, RotCmpForward, RotCmpRight)
local PawnPos = PlayerPawn:K2_GetActorLocation()
local ToPlayerDir = VectorHelper.Sub(PawnPos, self.CenterPos)
ToPlayerDir.Z = 0.
-- 判断该玩家是否在两帧划过的扇形内
-- 通过判断到玩家的向量与两帧的向前向量的余弦均为正 并且 该向量与两帧的向右向量的两余弦值的积为负
if VectorHelper.CosineValue(ToPlayerDir, RotCmpForward) > 0
and VectorHelper.CosineValue(ToPlayerDir, self.LastRotCmpForward) > 0
and VectorHelper.CosineValue(ToPlayerDir, RotCmpRight) * VectorHelper.CosineValue(ToPlayerDir, self.LastRotCmpRight) < 0
then
return true
end
return false
end
function BP_AvoidingSpikeStick:StickOverlapPlayer(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult)
if OtherActor and OtherActor.PlayerKey then
-- UGCEventSystem.SendEvent(EventEnum.StickOverlapPlayer, OtherActor.PlayerKey)
end
end
--[[
function BP_AvoidingSpikeStick:ReceiveEndPlay()
self.SuperClass.ReceiveEndPlay(self);
end
--]]
function BP_AvoidingSpikeStick:GetReplicatedProperties()
return
"StartTime",
"bIsPlaying"
end
--[[
function BP_AvoidingSpikeStick:GetAvailableServerRPCs()
return
end
--]]
function BP_AvoidingSpikeStick:ClientHitPlayerEffect(Pos)
UGCLogSystem.Log("[BP_AvoidingSpikeStick_ClientHitPlayerEffect]")
if self.HitParticle then
GameplayStatics.SpawnEmitterAtLocation(self, self.HitParticle,Pos, { Roll = 0, Pitch = 0, Yaw = 0 }, { X = 0.6, Y = 0.6, Z = 0.6 },true)
SoundSystem.PlaySound(SoundSystem.ESound.Impact)
end
end
return BP_AvoidingSpikeStick;