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 <noreply@anthropic.com>
89 lines
2.6 KiB
PHP
89 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Game;
|
|
|
|
use App\Models\Character;
|
|
|
|
class JailService
|
|
{
|
|
/**
|
|
* Calculate bust-out success chance for a character (0.0 to 1.0).
|
|
*/
|
|
public function calculateBustOutChance(Character $character): float
|
|
{
|
|
$base = config('game.jail.breakout_chance', 0.05);
|
|
$multiplier = config('game.jail.bust_out_stat_multiplier', 0.003);
|
|
$cap = config('game.jail.bust_out_max_chance', 0.80);
|
|
|
|
return min($cap, $base + ($character->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;
|
|
}
|
|
} |