Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/Battle/Actions/AttackAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Ichiloto\Engine\Battle\Actions;

use Ichiloto\Engine\Battle\BattleAction;
use Ichiloto\Engine\Entities\Character;
use Ichiloto\Engine\Entities\Interfaces\CharacterInterface as Actor;

class AttackAction extends BattleAction
Expand All @@ -12,9 +13,20 @@ class AttackAction extends BattleAction
*/
public function execute(Actor $actor, array $targets): void
{
// TODO: Implement execute() method.
if ($actor->isKnockedOut) {
return;
}

$attack = $actor instanceof Character ? $actor->effectiveStats->attack : $actor->stats->attack;

foreach ($targets as $target) {
if (! $target instanceof Actor || $target->isKnockedOut) {
continue;
}

$defence = $target instanceof Character ? $target->effectiveStats->defence : $target->stats->defence;
$damage = max(1, $attack - intval($defence / 2));
$target->stats->currentHp -= $damage;
}
}
}
}
93 changes: 93 additions & 0 deletions src/Battle/BattlePacing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

namespace Ichiloto\Engine\Battle;

use Ichiloto\Engine\Battle\Enumerations\BattleActionCategory;
use Ichiloto\Engine\Battle\Enumerations\BattlePace;
use Ichiloto\Engine\Util\Config\ConfigStore;
use Ichiloto\Engine\Util\Config\ProjectConfig;

/**
* Resolves configurable message and animation pacing for battles.
*
* @package Ichiloto\Engine\Battle
*/
class BattlePacing
{
/**
* Creates a new battle pacing profile.
*
* @param BattlePace $messagePace The preset for battle messages.
* @param BattlePace $animationPace The preset for battle turn timing.
* @param float|null $messageDurationOverride An explicit legacy message duration in seconds.
*/
public function __construct(
protected BattlePace $messagePace = BattlePace::SLOW,
protected BattlePace $animationPace = BattlePace::SLOW,
protected ?float $messageDurationOverride = null,
)
{
}

/**
* Creates a pacing profile from the project config.
*
* @return self
*/
public static function fromConfig(): self
{
if (! ConfigStore::has(ProjectConfig::class)) {
return new self();
}

$battleUiConfig = config(ProjectConfig::class, 'ui.battle', []);

if (! is_array($battleUiConfig)) {
return new self();
}

$messagePaceValue = $battleUiConfig['message_pace'] ?? $battleUiConfig['message_speed'] ?? null;
$legacyInfoDisplaySpeed = $battleUiConfig['info_display_speed'] ?? null;
$resolvedMessagePaceValue = $messagePaceValue ?? $legacyInfoDisplaySpeed;
$animationPaceValue = $battleUiConfig['animation_pace']
?? $battleUiConfig['animation_speed']
?? $resolvedMessagePaceValue;

return new self(
BattlePace::fromMixed($resolvedMessagePaceValue, BattlePace::SLOW),
BattlePace::fromMixed($animationPaceValue, BattlePace::SLOW),
$messagePaceValue === null && is_numeric($legacyInfoDisplaySpeed)
? floatval($legacyInfoDisplaySpeed)
: null,
);
}

/**
* Returns the auto-hide duration for general battle messages.
*
* @return float
*/
public function getMessageDurationSeconds(): float
{
return clamp(
$this->messageDurationOverride ?? $this->messagePace->messageDurationSeconds(),
0.1,
10.0
);
}

/**
* Returns the staged timings for the provided action.
*
* @param BattleAction|null $action The action being resolved.
* @return BattleTurnTimings
*/
public function getTurnTimings(?BattleAction $action): BattleTurnTimings
{
$category = BattleActionCategory::fromAction($action);

return BattleTurnTimings::fromTotalDuration(
$category->totalDurationSeconds($this->animationPace)
);
}
}
30 changes: 30 additions & 0 deletions src/Battle/BattleResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Ichiloto\Engine\Battle;

use Ichiloto\Engine\Entities\Inventory\InventoryItem;

/**
* Represents the outcome of a battle.
*
* @package Ichiloto\Engine\Battle
*/
class BattleResult
{
/**
* Creates a new battle result instance.
*
* @param string $title The result title.
* @param string[] $lines The result summary lines.
* @param InventoryItem[] $items The earned items.
* @param array<int, array{label: string, value: string}> $entries The staged reward entries.
*/
public function __construct(
protected(set) string $title,
protected(set) array $lines = [],
protected(set) array $items = [],
protected(set) array $entries = [],
)
{
}
}
14 changes: 9 additions & 5 deletions src/Battle/BattleRewards.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@ class BattleRewards
/**
* @var DropItem[] $items
*/
protected(set) array $items;
protected(set) array $items = [];

/**
* @var InventoryItem $item
* @var InventoryItem|null $item
*/
public InventoryItem $item {
public ?InventoryItem $item {
get {
if (empty($this->items)) {
return null;
}

foreach ($this->items as $item) {
if (mt_rand() / mt_getrandmax() <= $item->dropRate) {
return $item;
return $item->item;
}
}

Expand Down Expand Up @@ -75,4 +79,4 @@ public function __construct(
}
}
}
}
}
58 changes: 58 additions & 0 deletions src/Battle/BattleTurnTimings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace Ichiloto\Engine\Battle;

/**
* Represents the staged delays for a single battle turn.
*
* @package Ichiloto\Engine\Battle
*/
class BattleTurnTimings
{
public function __construct(
public float $stepForward,
public float $announcement,
public float $actionAnimation,
public float $effectAnimation,
public float $stepBack,
public float $statChanges,
public float $turnOver,
)
{
}

/**
* Creates a timing profile by distributing the given total duration.
*
* @param float $totalDurationSeconds The total action duration in seconds.
* @return self
*/
public static function fromTotalDuration(float $totalDurationSeconds): self
{
return new self(
$totalDurationSeconds * 0.10,
$totalDurationSeconds * 0.30,
$totalDurationSeconds * 0.16,
$totalDurationSeconds * 0.12,
$totalDurationSeconds * 0.10,
$totalDurationSeconds * 0.17,
$totalDurationSeconds * 0.05,
);
}

/**
* Returns the total duration in seconds.
*
* @return float
*/
public function totalDurationSeconds(): float
{
return $this->stepForward
+ $this->announcement
+ $this->actionAnimation
+ $this->effectAnimation
+ $this->stepBack
+ $this->statChanges
+ $this->turnOver;
}
}
Loading
Loading