124 lines
3.4 KiB
PHP
124 lines
3.4 KiB
PHP
<?php
|
|||
|
|
|
||
|
|
namespace App\Services\Game;
|
||
|
|
|
||
|
|
use App\Models\Character;
|
||
|
|
use Illuminate\Support\Carbon;
|
||
|
|
|
||
|
|
class CooldownService
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* Check if a character is on cooldown for a specific action type
|
||
|
|
*/
|
||
|
|
public function isOnCooldown(Character $character, string $actionType): bool
|
||
|
|
{
|
||
|
|
$cooldownSeconds = $this->getCooldownSeconds($actionType);
|
||
|
|
|
||
|
|
if ($cooldownSeconds <= 0) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
$lastActionTime = $this->getLastActionTime($character, $actionType);
|
||
|
|
|
||
|
|
if (!$lastActionTime) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
$secondsSinceAction = now()->diffInSeconds($lastActionTime);
|
||
|
|
return $secondsSinceAction < $cooldownSeconds;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get remaining cooldown time in seconds
|
||
|
|
*/
|
||
|
|
public function getRemainingCooldown(Character $character, string $actionType): int
|
||
|
|
{
|
||
|
|
$cooldownSeconds = $this->getCooldownSeconds($actionType);
|
||
|
|
|
||
|
|
if ($cooldownSeconds <= 0) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
$lastActionTime = $this->getLastActionTime($character, $actionType);
|
||
|
|
|
||
|
|
if (!$lastActionTime) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
$secondsSinceAction = now()->diffInSeconds($lastActionTime);
|
||
|
|
return max(0, $cooldownSeconds - $secondsSinceAction);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get formatted cooldown time (e.g., "2m 30s")
|
||
|
|
*/
|
||
|
|
public function getFormattedCooldown(Character $character, string $actionType): string
|
||
|
|
{
|
||
|
|
$remaining = $this->getRemainingCooldown($character, $actionType);
|
||
|
|
|
||
|
|
if ($remaining <= 0) {
|
||
|
|
return 'Ready';
|
||
|
|
}
|
||
|
|
|
||
|
|
$minutes = (int) ($remaining / 60);
|
||
|
|
$seconds = $remaining % 60;
|
||
|
|
|
||
|
|
if ($minutes > 0) {
|
||
|
|
return "{$minutes}m {$seconds}s";
|
||
|
|
}
|
||
|
|
|
||
|
|
return "{$seconds}s";
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Record an action to start the cooldown
|
||
|
|
*/
|
||
|
|
public function recordAction(Character $character, string $actionType): void
|
||
|
|
{
|
||
|
|
$cooldownModel = $this->getCooldownModel($character, $actionType);
|
||
|
|
|
||
|
|
// Update or create the cooldown record
|
||
|
|
$cooldownModel::updateOrCreate(
|
||
|
|
[
|
||
|
|
'character_id' => $character->id,
|
||
|
|
'action_type' => $actionType,
|
||
|
|
],
|
||
|
|
[
|
||
|
|
'last_action_at' => now(),
|
||
|
|
]
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the cooldown duration in seconds for an action type
|
||
|
|
*/
|
||
|
|
protected function getCooldownSeconds(string $actionType): int
|
||
|
|
{
|
||
|
|
return config("game.cooldowns.{$actionType}", config('game.cooldowns.default', 60));
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the last action time for a character and action type
|
||
|
|
*/
|
||
|
|
protected function getLastActionTime(Character $character, string $actionType): ?Carbon
|
||
|
|
{
|
||
|
|
$cooldownModel = $this->getCooldownModel($character, $actionType);
|
||
|
|
|
||
|
|
$cooldown = $cooldownModel::where('character_id', $character->id)
|
||
|
|
->where('action_type', $actionType)
|
||
|
|
->first();
|
||
|
|
|
||
|
|
return $cooldown?->last_action_at;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the cooldown model class for an action type
|
||
|
|
*/
|
||
|
|
protected function getCooldownModel(Character $character, string $actionType): string
|
||
|
|
{
|
||
|
|
// For now, we'll use a simple approach with a cooldowns table
|
||
|
|
// In the future, this could be extended to support different cooldown types
|
||
|
|
return \App\Models\Cooldown::class;
|
||
|
|
}
|
||
|
|
}
|