I would like to check if a player has stopped moving after entering a Mutator Zone.
How could I achieve this in Verse? Or is there a simpler solution with devices?
My current idea is to get the player transform and compare it to the previous once inside a loop, but I can’t figure out how to write that. Any help very much appreciated!
Hey Fub, I don’t know of a way to do this with devices and I suspect there might not be one. Doing it with Verse using the method you mentioned does seem to work, but a few things make it quite involved, including:
Handling players leaving the zone before standing still
Handling players joining and leaving matches
Accounting for elapsed time
Ensuring players are only iterated once and calculations aren’t doubled up
I felt like a break from my project so I put together a script for it. It could be a useful as a general example so I’ve made it a snippet here.
Once you have player_standstill_tracker from the snippet, you will be able to detect players entering the zone and standing still like so:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
player_tracker_device := class(creative_device):
@editable
MovementZone: mutator_zone_device = mutator_zone_device{}
@editable
StandstillTrackingDevice: standstill_tracking_device = standstill_tracking_device{}
OnBegin<override>()<suspends>: void =
# Subscribe to mutator_zone_device events
MovementZone.AgentEntersEvent.Subscribe(HandleAgentEntersMovementZone)
HandleAgentEntersMovementZone(Agent: agent): void =
spawn. AwaitAgentStandStillOrExitZone(Agent)
AwaitAgentStandStillOrExitZone(Agent: agent)<suspends>: void =
if. StandstillTrackingData := StandstillTrackingDevice.GetAgentTrackingData[Agent]
then:
race:
# The player leaves the zone before standing still
AwaitAgentExitsZone(Agent)
# The player stands still
StandstillTrackingData.StandStillEvent.Await()
# If the player is standing still here, we know it's inside the zone
if. StandstillTrackingData.IsStandingStill[]
then. Print("We are at our destination 🎉")
else. Print("Left zone without standing still ")
AwaitAgentExitsZone(Agent: agent)<suspends>: void =
# Await exit events until agent matches
loop:
LeavingAgent := MovementZone.AgentExitsEvent.Await()
if. LeavingAgent = Agent then. break
Thanks for such a generous response Rift, I appreciate it.
I had only made it so far as using ‘spawn’ to get my loop running. This setup works but I hadn’t even considered the challenge of other players joining/leaving the match.
player_tracker_device := class(creative_device):
@editable
MovementZone : mutator_zone_device = mutator_zone_device{}
@editable
Teleporter : teleporter_device = teleporter_device{}
# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void =
MovementZone.AgentEntersEvent.Subscribe(HandleAgentEntersMovementZone)
GetTransformPerTick<private>(FortCharacter:fort_character)<suspends>:void =
loop:
OldPosition : vector3 = FortCharacter.GetTransform().Translation
Sleep(1.0)
NewPosition : vector3 = FortCharacter.GetTransform().Translation
if(IsAlmostEqual[OldPosition, NewPosition, 0.0]):
if(Agent := FortCharacter.GetAgent[]):
Teleporter.Teleport(Agent)
break
else:
Print("Player is still moving!")
HandleAgentEntersMovementZone<private>(Agent:agent):void =
if(FortCharacter := Agent.GetFortCharacter[]):
spawn {GetTransformPerTick(FortCharacter)}
I have a formatting question. You use periods in ways I don’t recognize, for example:
Yea, the player leaving the zone before standing still is another thing to think about. In your example I believe it would continue to loop after the player exits the mutator zone volume.
The periods I use are another syntax option instead of parenthesis, yea. I’ve started to prefer it because I find it easier manage multi-line expressions that way. e.g.
Foo: []int = array{}
# Colon = multiline block
for(Bar : Foo):
Print("1")
Print("2")
# Period = single line block
for(Bar : Foo). Print("1")
# Period single line for expression, colon multiline for loop block
for. Bar : Foo
do:
Print("1")
Print("2")
# Period multi line for expression, period single line for loop block
for:
Bar : Foo
true = true
do. Print("1")