a bit of progress

This commit is contained in:
2026-07-04 17:09:55 +03:00
parent f6e7d37428
commit 082b532d52
29 changed files with 2734 additions and 47 deletions
+136
View File
@@ -0,0 +1,136 @@
<?php
namespace App\Models;
use App\Enums\AttackResult;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int $id
* @property int $attacker_id
* @property int $defender_id
* @property int $attacker_damage
* @property int $defender_damage
* @property int $attacker_health_after
* @property int $defender_health_after
* @property AttackResult $result
* @property int $money_stolen
* @property int $experience_gained
* @property bool $was_critical
* @property bool $was_mugging
* @property int|null $attacker_weapon_id
* @property int|null $defender_armor_id
* @property \Illuminate\Support\Carbon $attacked_at
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
*/
class Attack extends Model
{
use HasFactory;
protected $fillable = [
'attacker_id',
'defender_id',
'attacker_damage',
'defender_damage',
'attacker_health_after',
'defender_health_after',
'result',
'money_stolen',
'experience_gained',
'was_critical',
'was_mugging',
'attacker_weapon_id',
'defender_armor_id',
'attacked_at',
];
protected $casts = [
'result' => AttackResult::class,
'was_critical' => 'boolean',
'was_mugging' => 'boolean',
'attacked_at' => 'datetime',
];
/**
* Get the attacker character.
*/
public function attacker(): BelongsTo
{
return $this->belongsTo(Character::class, 'attacker_id');
}
/**
* Get the defender character.
*/
public function defender(): BelongsTo
{
return $this->belongsTo(Character::class, 'defender_id');
}
/**
* Get the weapon used by attacker.
*/
public function attackerWeapon(): BelongsTo
{
return $this->belongsTo(Item::class, 'attacker_weapon_id');
}
/**
* Get the armor used by defender.
*/
public function defenderArmor(): BelongsTo
{
return $this->belongsTo(Item::class, 'defender_armor_id');
}
/**
* Check if this was a successful attack (attacker won)
*/
public function isWin(): bool
{
return $this->result === AttackResult::WIN;
}
/**
* Check if this was a loss (attacker lost)
*/
public function isLose(): bool
{
return $this->result === AttackResult::LOSE;
}
/**
* Check if this was a draw
*/
public function isDraw(): bool
{
return $this->result === AttackResult::DRAW;
}
/**
* Check if attacker escaped
*/
public function isEscape(): bool
{
return $this->result === AttackResult::ESCAPE;
}
/**
* Check if this attack resulted in defender's death
*/
public function defenderDied(): bool
{
return $this->defender_health_after <= 0;
}
/**
* Check if this attack resulted in attacker's death
*/
public function attackerDied(): bool
{
return $this->attacker_health_after <= 0;
}
}
+16
View File
@@ -114,6 +114,22 @@ class Character extends Model
return $this->hasMany(CrimeAttempt::class);
}
/**
* Get the attacks made by this character.
*/
public function attacks(): HasMany
{
return $this->hasMany(Attack::class, 'attacker_id');
}
/**
* Get the attacks received by this character.
*/
public function attacksReceived(): HasMany
{
return $this->hasMany(Attack::class, 'defender_id');
}
/**
* Get the activity logs for the character.
*/
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int $id
* @property int $character_id
* @property string $action_type
* @property \Illuminate\Support\Carbon $last_action_at
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
*/
class Cooldown extends Model
{
use HasFactory;
protected $fillable = [
'character_id',
'action_type',
'last_action_at',
];
protected $casts = [
'last_action_at' => 'datetime',
];
/**
* Get the character that owns this cooldown.
*/
public function character(): BelongsTo
{
return $this->belongsTo(Character::class);
}
/**
* Check if this cooldown has expired
*/
public function hasExpired(): bool
{
$cooldownSeconds = config("game.cooldowns.{$this->action_type}", config('game.cooldowns.default', 60));
$secondsSinceAction = now()->diffInSeconds($this->last_action_at);
return $secondsSinceAction >= $cooldownSeconds;
}
/**
* Get remaining cooldown time in seconds
*/
public function getRemainingSecondsAttribute(): int
{
$cooldownSeconds = config("game.cooldowns.{$this->action_type}", config('game.cooldowns.default', 60));
$secondsSinceAction = now()->diffInSeconds($this->last_action_at);
return max(0, $cooldownSeconds - $secondsSinceAction);
}
/**
* Update the cooldown to now
*/
public function refresh(): void
{
$this->last_action_at = now();
$this->save();
}
}