using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/SpatialMath } # This is our "Device" — the brain of our trap. # Think of this as the Gamepad that controls the prop. class revenge_trap_device(creative_device): # --- EDITABLES (Things you change in the Editor) --- # The prop that will move (e.g., a Loot Chest) @editable PropToMove: creative_prop = creative_prop{} # The trigger zone. If a player enters this, the trap activates! @editable TriggerZone: trigger_zone = trigger_zone{} # How close does the player have to be to trigger the "panic"? # In-game analogy: The "Damage Radius" of a grenade. panic_distance: float = 500.0 # How long should the panic move take? (Seconds) panic_speed: float = 2.0 # --- VARIABLES (Things that change during the game) --- # We need to remember where the prop started so we can send it back. # This is like your "Last Known Location" on the minimap. home_location: vector = vector{} OnBegin(): void = # 1. SAVE THE STARTING POSITION # Get the prop's current location and save it. # We do this once when the game starts. home_location = PropToMove.GetLocation() # 2. LISTEN FOR THE TRIGGER # Subscribe to the TriggerZone's "OnActorBeginOverlap" event. # This is like setting a mine that explodes when someone steps on it. TriggerZone.OnActorBeginOverlap.Subscribe(HandleTrigger) # 3. LISTEN FOR MOVEMENT COMPLETION # Get the Animation Controller for our prop. # This is the "Stage Manager" we talked about. if (controller := PropToMove.GetAnimationController[]): # Subscribe to the event that fires when a MoveTo finishes. # This is like waiting for the storm timer to hit zero. controller.MovementCompleteEvent.Subscribe(HandleMovementComplete) # --- HANDLERS (Functions that run when events happen) --- HandleTrigger := (other_actor: actor) -> void: # Check if the thing that entered is a Player if (player := other_actor.GetInstigator()?.As[]): # 1. START THE "ATTACK" MOVE # Move the prop toward the player slowly. # We use the player's current location. target_pos := player.GetLocation() # Execute the move. This suspends the code until the move is done. # But wait! We want to be able to interrupt this. # So we run it in a way that allows us to cancel it later. # For simplicity in this beginner example, we'll just start the move. # Note: In a full system, you'd use a task to allow interruption. # Here, we'll just move it to the player. PropToMove.MoveTo(target_pos, 3.0) # 2. CHECK FOR PANIC CONDITION # After the move starts, check if the player is *too* close. # If they are, we interrupt the move and send it home! distance := (PropToMove.GetLocation() - target_pos).Length() # Actually, let's check distance *now* to see if they are already close. # If the player is within panic_distance, send it home immediately. if (distance < panic_distance): SendHome() HandleMovementComplete := (result: move_to_result) -> void: # This runs when a MoveTo finishes. # In our simple trap, we might just want to reset it after it arrives. # Or we can do nothing. For now, let's just log it (mentally). # If you wanted the prop to stay where it landed, you'd do nothing here. pass SendHome := () -> void: # This is the "Interrupt" logic. # Calling MoveTo again on the same object stops the previous one. # It's like switching channels on a TV while a show is playing. # Move the prop back to the saved home location. PropToMove.MoveTo(home_location, panic_speed) # Optional: You could add a sound or effect here!