From 6e6954eddae8c325e8c00a77d3ef46855f23b02b Mon Sep 17 00:00:00 2001 From: Daniel Maixner Date: Tue, 28 Mar 2023 17:11:01 +0200 Subject: [PATCH] Add player shot movement slowdown aka tagging --- server/src/Core/Player.php | 9 ++++++--- server/src/Event/TimeoutEvent.php | 8 +++++--- server/src/Traits/Player/MovementTrait.php | 3 +++ test/og/Movement/MovementTest.php | 21 +++++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/server/src/Core/Player.php b/server/src/Core/Player.php index 14e9d6c..2ab3ddd 100644 --- a/server/src/Core/Player.php +++ b/server/src/Core/Player.php @@ -6,6 +6,7 @@ use cs\Enum\Color; use cs\Enum\InventorySlot; use cs\Event\Event; +use cs\Event\TimeoutEvent; use cs\Traits\Player as PlayerTrait; use cs\Weapon\AmmoBasedWeapon; @@ -38,9 +39,10 @@ final class Player private int $eventIdPrimary = 0; private int $eventIdJump = 1; private int $eventIdCrouch = 2; - private int $eventIdMovement = 3; - private int $eventIdGravity = 4; - private int $eventIdOther = 5; // last + private int $eventIdShotSlowdown = 3; + private int $eventIdMovement = 4; + private int $eventIdGravity = 5; + private int $eventIdOther = 6; // last public function __construct( private int $id, @@ -195,6 +197,7 @@ public function lowerArmor(int $armorDamage): void public function lowerHealth(int $healthDamage): void { + $this->addEvent(new TimeoutEvent(null, 70), $this->eventIdShotSlowdown); $this->health -= abs($healthDamage); if ($this->health <= 0) { $this->health = 0; diff --git a/server/src/Event/TimeoutEvent.php b/server/src/Event/TimeoutEvent.php index 8d85a05..53fb50a 100644 --- a/server/src/Event/TimeoutEvent.php +++ b/server/src/Event/TimeoutEvent.php @@ -7,9 +7,9 @@ class TimeoutEvent extends Event { protected int $tickCountTimeout = 0; - protected Closure $callback; + protected ?Closure $callback = null; - public function __construct(Closure $callback, protected int $timeoutMs) + public function __construct(?Closure $callback, protected int $timeoutMs) { $this->callback = $callback; $this->tickCountTimeout = $this->timeMsToTick($this->timeoutMs); @@ -21,7 +21,9 @@ final public function process(int $tick): void return; } - call_user_func($this->callback, $this, $tick); + if ($this->callback) { + call_user_func($this->callback, $this, $tick); + } if ($this->onComplete !== []) { foreach ($this->onComplete as $func) { call_user_func($func, $this); diff --git a/server/src/Traits/Player/MovementTrait.php b/server/src/Traits/Player/MovementTrait.php index b44c694..2b2c0b4 100644 --- a/server/src/Traits/Player/MovementTrait.php +++ b/server/src/Traits/Player/MovementTrait.php @@ -153,6 +153,9 @@ private function getMoveSpeed(): int } elseif ($this->isFlying()) { $speed *= Setting::flyingMovementSpeedMultiplier(); } + if (isset($this->events[$this->eventIdShotSlowdown])) { + $speed *= .4; + } return (int)ceil($speed); } diff --git a/test/og/Movement/MovementTest.php b/test/og/Movement/MovementTest.php index 7659e1e..6af0be5 100644 --- a/test/og/Movement/MovementTest.php +++ b/test/og/Movement/MovementTest.php @@ -142,6 +142,27 @@ public function testPlayerSlowMovementWhenHaveGun(): void $this->assertLessThan(Setting::moveDistancePerTick(), $game->getPlayer(1)->getPositionClone()->z); } + public function testPlayerSlowMovementWhenShot(): void + { + $tickMax = 5; + $game = $this->createTestGame($tickMax); + $p2 = new Player(2, Color::YELLOW, false); + $game->addPlayer($p2); + $p2->getSight()->look(180, -10); + $p2->setPosition($p2->getPositionClone()->addZ(Setting::moveDistancePerTick() * 10)); + $game->onTick(function (GameState $state) { + $state->getPlayer(1)->moveForward(); + if ($state->getTickId() === 2) { + $this->assertNotNull($state->getPlayer(2)->attack()); + $this->assertLessThan(100, $state->getPlayer(1)->getHealth()); + $this->assertTrue($state->getPlayer(1)->isAlive()); + } + }); + $game->start(); + $this->assertGreaterThan(Setting::moveDistancePerTick() * 3, $game->getPlayer(1)->getPositionClone()->z); + $this->assertLessThan(Setting::moveDistancePerTick() * $tickMax, $game->getPlayer(1)->getPositionClone()->z); + } + public function testPlayerSlowMovementWhenFlying(): void { $game = $this->createOneRoundGame();