Created
July 8, 2026 11:20
-
-
Save elementbound/3d147c6bce74cc254fc5fbfd07b9f7c7 to your computer and use it in GitHub Desktop.
netfox spawning alternative
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Input Node | |
| var input: PlayerInput | |
| # Record-only property in RBS | |
| var projectile: Node3D | |
| # Manual display tracking | |
| var has_fired: bool | |
| # Convenience class for display tracking | |
| var has_fired_observer := EventObserver.new() | |
| func _rollback_tick(dt: float, t: int, _is_fresh: bool) -> void: | |
| # Retrieve the projectile we've recorded for the next tick; `null` is the default value | |
| var recorded_projectile := NetworkHistoryServer.get_value_at(self, "projectile", t + 1, null) | |
| if input.is_firing and can_fire(): | |
| if not is_instance_valid(recorded_projectile): | |
| # We are firing, but haven't spawned a projectile yet | |
| # This projectile will be recorded for the next tick | |
| projectile = spawn_projectile() | |
| # Keep a reference in `recorded_projectile` so we can set it up | |
| recorded_projectile = projectile | |
| # We've fired a brand new projectile, play the animation and such | |
| has_fired = true | |
| # Same as above but with convenience class - mark the event as happened | |
| has_fired_observer.mark() | |
| # Whether the projectile existed already or if it's brand new, align it to our current aim | |
| # This is important in case the server corrects our position or orientation | |
| recorded_projectile.position = position | |
| recorded_projectile.quaternion = quaternion | |
| # Do additional bookkeeping here, e.g. deducing ammo, hitscanning, etc. | |
| else: | |
| if is_instance_valid(recorded_projectile): | |
| # We are not firing, yet we have a projectile | |
| # Probably we've predicted we can fire, then the server told us no | |
| recorded_projectile.queue_free() | |
| projectile = null | |
| func _after_tick_loop() -> void: | |
| if has_fired: | |
| # We've fired our gun, play animation | |
| animation_player.play("fire") | |
| # Reset flag for next tick loop | |
| has_fired = false | |
| func _process(_dt: float) -> void: | |
| # Same display check as above, but with convenience class | |
| # You could put this piece of code in `_process()`, `_physics_process()`, | |
| # or anywhere your animation code resides | |
| if has_fired_observer.check(): | |
| animation_player.play("fire") | |
| # Resetting is not needed, it's handled by the class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment