From 799f46a5f260745e8d7a723121b68c48b9ba2101 Mon Sep 17 00:00:00 2001 From: Doar Mihai Date: Sun, 28 Jun 2026 22:42:59 +0300 Subject: [PATCH] feat: add JailService and bust-out config keys Add JailService with bustOut(), sendToJail(), releaseFromJail(), and calculateBustOutChance() methods. Add two config keys (bust_out_stat_multiplier and bust_out_max_chance) to the jail config block. Co-Authored-By: Claude Sonnet 4.6 --- app/Services/Game/JailService.php | 89 +++++++++++++++++++++++++++++++ config/game.php | 10 ++-- 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 app/Services/Game/JailService.php diff --git a/app/Services/Game/JailService.php b/app/Services/Game/JailService.php new file mode 100644 index 0000000..6498f92 --- /dev/null +++ b/app/Services/Game/JailService.php @@ -0,0 +1,89 @@ +dexterity + $character->speed) * $multiplier); + } + + /** + * Attempt to bust out of jail. + * + * Deducts breakout_cost cash regardless of outcome. + * On success: releases character immediately. + * On failure: multiplies remaining sentence by sentence_multiplier. + * + * @return array{success: bool, message: string} + */ + public function bustOut(Character $character): array + { + $cost = config('game.jail.breakout_cost', 1000); + + if ($character->money < $cost) { + return [ + 'success' => false, + 'message' => 'You need $' . number_format($cost) . ' to attempt a bust-out.', + ]; + } + + $character->money -= $cost; + $successRate = $this->calculateBustOutChance($character); + $roll = random_int(0, 9999) / 10000; + + if ($roll <= $successRate) { + $this->releaseFromJail($character); + $character->save(); + + return [ + 'success' => true, + 'message' => "You escaped! You're free.", + ]; + } + + // Failure: extend sentence + $multiplier = config('game.jail.sentence_multiplier', 1.5); + $remaining = max(0, $character->in_jail_until->diffInSeconds(now())); + $extended = (int) ceil($remaining * $multiplier); + + $character->in_jail_until = now()->addSeconds($extended); + $character->save(); + + $newReleaseTime = $character->in_jail_until->diffForHumans(); + + return [ + 'success' => false, + 'message' => "Bust failed — your sentence was extended to {$newReleaseTime}.", + ]; + } + + /** + * Send a character to jail for the given number of seconds. + */ + public function sendToJail(Character $character, int $seconds): void + { + $character->status = 'in_jail'; + $character->in_jail_until = now()->addSeconds($seconds); + $character->save(); + } + + /** + * Release a character from jail immediately. + */ + public function releaseFromJail(Character $character): void + { + $character->status = 'active'; + $character->in_jail_until = null; + } +} \ No newline at end of file diff --git a/config/game.php b/config/game.php index 83b29c8..795f1a6 100644 --- a/config/game.php +++ b/config/game.php @@ -79,10 +79,12 @@ return [ // Jail system configuration 'jail' => [ - 'sentence_length' => 3600, // 1 hour base sentence - 'breakout_chance' => 0.05, // 5% chance to break out per attempt - 'breakout_cost' => 1000, // Cost to attempt breakout - 'sentence_multiplier' => 1.5, // Sentence increases by 50% for repeat offenses + 'sentence_length' => 3600, + 'breakout_chance' => 0.05, + 'breakout_cost' => 1000, + 'sentence_multiplier' => 1.5, + 'bust_out_stat_multiplier' => 0.003, // per combined dex+speed point + 'bust_out_max_chance' => 0.80, // cap at 80% ], // Economy configuration