Updated BattleClass to use BattleEvents
Implemented BattleEvents from @austenmc's old branch. Added an empty Buff-Model as well, as well as a BuffList. @ToDo: Add events, and add buff calculations to the battle class. This PR will, however, only introduce the basic battle class, buffs will come in another patch.
This commit is contained in:
+90
-100
@@ -3,6 +3,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
use LotGD\Core\{
|
||||
DiceBag,
|
||||
Exceptions\ArgumentException,
|
||||
@@ -10,6 +12,11 @@ use LotGD\Core\{
|
||||
Exceptions\BattleNotOverException,
|
||||
Models\FighterInterface
|
||||
};
|
||||
use LotGD\Core\Models\BattleEvents\{
|
||||
CriticalHitEvent,
|
||||
DamageEvent,
|
||||
DeathEvent
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for managing and running battles between 2 participants.
|
||||
@@ -22,18 +29,23 @@ class Battle
|
||||
const DAMAGEROUND_MONSTER = 0b10;
|
||||
const DAMAGEROUND_BOTH = 0b11;
|
||||
|
||||
const RESULT_UNDECIDED = 0;
|
||||
const RESULT_PLAYERDEATH = 1;
|
||||
const RESULT_MONSTERDEATH = 2;
|
||||
|
||||
protected $player;
|
||||
protected $monster;
|
||||
protected $diceBag;
|
||||
protected $isOver = false;
|
||||
protected $winner;
|
||||
protected $looser;
|
||||
protected $game;
|
||||
protected $events;
|
||||
protected $result = 0;
|
||||
protected $round = 0;
|
||||
|
||||
public function __construct(FighterInterface $player, FighterInterface $monster)
|
||||
public function __construct(Game $game, FighterInterface $player, FighterInterface $monster)
|
||||
{
|
||||
$this->game = $game;
|
||||
$this->player = $player;
|
||||
$this->monster = $monster;
|
||||
$this->diceBag = new DiceBag();
|
||||
$this->events = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getActions()
|
||||
@@ -52,7 +64,7 @@ class Battle
|
||||
*/
|
||||
public function isOver()
|
||||
{
|
||||
return $this->isOver;
|
||||
return $this->result !== self::RESULT_UNDECIDED;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,22 +73,24 @@ class Battle
|
||||
*/
|
||||
public function getWinner(): FighterInterface
|
||||
{
|
||||
if (is_null($this->winner)) {
|
||||
if ($this->isOver() === false) {
|
||||
throw new BattleNotOverException('There is no winner yet.');
|
||||
}
|
||||
return $this->winner;
|
||||
|
||||
return $this->result === self::RESULT_PLAYERDEATH ? $this->monster : $this->player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the looser of this fight
|
||||
* @return FighterInterface
|
||||
*/
|
||||
public function getLooser(): FighterInterface
|
||||
public function getLoser(): FighterInterface
|
||||
{
|
||||
if (is_null($this->looser)) {
|
||||
throw new BattleNotOverException('There is no looser yet.');
|
||||
if ($this->isOver() === false) {
|
||||
throw new BattleNotOverException('There is no winner yet.');
|
||||
}
|
||||
return $this->looser;
|
||||
|
||||
return $this->result === self::RESULT_PLAYERDEATH ? $this->player : $this->monster;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,20 +106,15 @@ class Battle
|
||||
throw new ArgumentException('$firstDamageRound must not be 0.');
|
||||
}
|
||||
|
||||
if ($this->isOver === true) {
|
||||
if ($this->isOver()) {
|
||||
throw new BattleIsOverException('This battle has already ended. You cannot fight anymore rounds.');
|
||||
}
|
||||
|
||||
for ($count = 0; $count < $n; $count++) {
|
||||
$this->fightOneRound($firstDamageRound);
|
||||
$isSurprised = self::DAMAGEROUND_BOTH;
|
||||
$firstDamageRound = self::DAMAGEROUND_BOTH;
|
||||
|
||||
// If one of the participants is dead, abort.
|
||||
if ($this->player->isAlive() === false || $this->monster->isAlive() === false) {
|
||||
$this->isOver = true;
|
||||
|
||||
$this->winner = $this->player->isAlive() ? $this->player : $this->monster;
|
||||
$this->looser = $this->player->isAlive() ? $this->monster : $this->player;
|
||||
if ($this->isOver()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -119,97 +128,78 @@ class Battle
|
||||
*/
|
||||
protected function fightOneRound(int $firstDamageRound)
|
||||
{
|
||||
// playerDamage is the damage done to the player, to the monster.
|
||||
list($playerDamage, $monsterDamage, $playerAttack) = $this->calculateDamage();
|
||||
$damageHasBeenDone = false;
|
||||
|
||||
// Player does damage to the monster
|
||||
if ($firstDamageRound & self::DAMAGEROUND_PLAYER
|
||||
&& $this->player->isAlive()
|
||||
&& $this->monster->isAlive()
|
||||
) {
|
||||
if ($monsterDamage < 0) {
|
||||
// The damage done to the monster is negative.
|
||||
// This means that the monster counters the player's attack
|
||||
$this->player->damage(0 - $monsterDamage);
|
||||
} elseif ($monsterDamage > 0) {
|
||||
// The damage done to the monster is positive.
|
||||
// This means that this is a normal attack
|
||||
$this->monster->damage($monsterDamage);
|
||||
} else {
|
||||
// The damage done to the monster is 0.
|
||||
// We interpretate this as a miss.
|
||||
do {
|
||||
$offenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_PLAYER ? $this->turn($this->player, $this->monster) : new ArrayCollection();
|
||||
$defenseTurnEvents = $firstDamageRound & self::DAMAGEROUND_MONSTER ? $this->turn($this->monster, $this->player) : new ArrayCollection();
|
||||
|
||||
$events = new ArrayCollection(array_merge($offenseTurnEvents->toArray(), $defenseTurnEvents->toArray()));
|
||||
$eventsToAdd = new ArrayCollection();
|
||||
|
||||
foreach($events as $event) {
|
||||
$event->apply();
|
||||
|
||||
if ($event instanceof DamageEvent && $event->getDamage() !== 0) {
|
||||
$damageHasBeenDone = true;
|
||||
}
|
||||
|
||||
$eventsToAdd->add($event);
|
||||
|
||||
if ($this->player->getHealth() <= 0) {
|
||||
$this->events->add(new DeathEvent($this->player));
|
||||
$this->result = self::RESULT_PLAYERDEATH;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->monster->getHealth() <= 0) {
|
||||
$this->events->add(new DeathEvent($this->monster));
|
||||
$this->result = self::RESULT_MONSTERDEATH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while($damageHasBeenDone === false);
|
||||
|
||||
// Monster does damage to the player
|
||||
if ($firstDamageRound & self::DAMAGEROUND_MONSTER
|
||||
&& $this->player->isAlive()
|
||||
&& $this->monster->isAlive()
|
||||
) {
|
||||
if ($playerDamage > 0) {
|
||||
// The damage done to the player is negative
|
||||
// THis means that the player counters the monster's attack
|
||||
$this->monster->damage(0 - $playerDamage);
|
||||
} elseif($playerDamage > 0) {
|
||||
// The damage done to the player is positive.
|
||||
// This means that this is a normal attack
|
||||
$this->player->damage($playerDamage);
|
||||
}
|
||||
else {
|
||||
// The damage done to the player is 0.
|
||||
// We interpretate this as a miss.
|
||||
}
|
||||
}
|
||||
$this->round++;
|
||||
$this->events = new ArrayCollection(array_merge($this->events->toArray(), $eventsToAdd->toArray()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the damage done to the player and to the monster.
|
||||
* @return array [playerDamage, monsterDamage, playerAttack]
|
||||
* Runs one turn.
|
||||
* @param FighterInterface $attacker
|
||||
* @param FighterInterface $defender
|
||||
*/
|
||||
protected function calculateDamage(): array
|
||||
protected function turn(FighterInterface $attacker, FighterInterface $defender): ArrayCollection
|
||||
{
|
||||
$monsterDefense = $this->monster->getDefense();
|
||||
$monsterAttack = $this->monster->getAttack();
|
||||
$playerDefense = $this->player->getDefense();
|
||||
$playerAttack = $this->player->getAttack();
|
||||
$events = new ArrayCollection();
|
||||
|
||||
$monsterDamage = 0;
|
||||
$playerDamage = 0;
|
||||
$attackersAttack = $attacker->getAttack($this->game);
|
||||
$defendersDefense = $defender->getDefense($this->game);
|
||||
|
||||
while ($monsterDamage === 0 && $playerDamage === 0) {
|
||||
$atk = $playerAttack;
|
||||
|
||||
// Critical hit probablity is derived from the old e_rand() function.
|
||||
// e_rand(1, 3) == 3 has a probablity of ~25%.
|
||||
if ($this->diceBag->chance(0.25)) {
|
||||
$atk *= 3;
|
||||
}
|
||||
|
||||
// Calculate damage done to the monster
|
||||
$playerAtkRoll = $this->diceBag->normal(0, $atk);
|
||||
$monsterDefRoll = $this->diceBag->normal(0, $monsterDefense);
|
||||
$monsterDamage = $playerAtkRoll - $monsterDefRoll;
|
||||
|
||||
if ($monsterDamage < 0) {
|
||||
// Counter attack is only half as hard
|
||||
$monsterDamage /= 2;
|
||||
}
|
||||
|
||||
// Calculate damage done to the player
|
||||
$playerDefRoll = $this->diceBag->normal(0, $playerDefense);
|
||||
$monsterAtkRoll = $this->diceBag->normal(0, $monsterAttack);
|
||||
$playerDamage = $monsterAtkRoll - $playerDefRoll;
|
||||
|
||||
if ($playerDamage < 0) {
|
||||
// Counter attack is only half as hard
|
||||
$playerDamage /= 2;
|
||||
if ($attacker === $this->game->getCharacter()) {
|
||||
// Players can land critical hits
|
||||
if ($this->game->getDiceBag()->chance(0.25)) {
|
||||
$attackersAttack *= 3;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
(int)round($playerDamage, 0),
|
||||
(int)round($monsterDamage, 0),
|
||||
$atk
|
||||
];
|
||||
$attackersAtkRoll = $this->game->getDiceBag()->normal(0, $attackersAttack);
|
||||
$defendersDefRoll = $this->game->getDiceBag()->normal(0, $defendersDefense);
|
||||
$damage = $attackersAtkRoll - $defendersDefRoll;
|
||||
|
||||
if ($attackersAttack > $attacker->getAttack($this->game, true)) {
|
||||
$events->add(new CriticalHitEvent($attacker, $attackersAttack));
|
||||
}
|
||||
|
||||
if ($damage < 0) {
|
||||
// RIPOSTE are only half as damaging than normal attacks
|
||||
$damage /= 2;
|
||||
}
|
||||
|
||||
$damage = (int)round($damage, 0);
|
||||
|
||||
$events->add(new DamageEvent($attacker, $defender, $damage));
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core;
|
||||
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
|
||||
use LotGD\Core\Models\Buff;
|
||||
use LotGD\Core\Models\Character;
|
||||
|
||||
/**
|
||||
* Description of BuffList
|
||||
*/
|
||||
class BuffList
|
||||
{
|
||||
private $buffs;
|
||||
|
||||
public function __construct(Collection $buffs) {
|
||||
$this->buffs = $buffs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Exceptions;
|
||||
|
||||
/**
|
||||
* Exception if a specific, required argument is missing
|
||||
*/
|
||||
class BuffSlotOccupiedException extends CoreException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace LotGD\Core;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use LotGD\Core\Models\Character;
|
||||
|
||||
class Game
|
||||
{
|
||||
private $entityManager;
|
||||
@@ -35,4 +37,22 @@ class Game
|
||||
{
|
||||
return $this->eventManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game's dice bag.
|
||||
* @return DiceBag
|
||||
*/
|
||||
public function getDiceBag(): DiceBag
|
||||
{
|
||||
return $this->diceBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the active character for this game run
|
||||
* @return Character
|
||||
*/
|
||||
public function getCharacter(): Character
|
||||
{
|
||||
return $this->character;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Models\BattleEvents;
|
||||
|
||||
/**
|
||||
* BattleEvent
|
||||
*/
|
||||
class BattleEvent
|
||||
{
|
||||
public function apply()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function decorate(Game $game): string
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Models\BattleEvents;
|
||||
|
||||
use LotGD\Core\Models\FighterInterface;
|
||||
|
||||
/**
|
||||
* Description of CriticalHitEvent
|
||||
*/
|
||||
class CriticalHitEvent extends BattleEvent
|
||||
{
|
||||
/** @var FighterInstance */
|
||||
protected $attacker;
|
||||
/** @var int */
|
||||
protected $criticalAttackValue;
|
||||
|
||||
public function __construct(FighterInterface $attacker, int $criticalAttackValue)
|
||||
{
|
||||
$this->attacker = $attacker;
|
||||
$this->criticalAttackValue = $criticalAttackValue;
|
||||
}
|
||||
|
||||
public function decorate(Game $game): string
|
||||
{
|
||||
$pureAttackersAttack = $this->attacker->getAttack($game, true);
|
||||
|
||||
if ($this->criticalAttackValue > $pureAttackersAttack * 4) {
|
||||
return "You execute a MEGA power move!!!";
|
||||
} elseif ($this->criticalAttackValue > $pureAttackersAttack * 3) {
|
||||
return "You execute a DOUBLE power move!!!";
|
||||
} elseif ($this->criticalAttackValue > $pureAttackersAttack * 2) {
|
||||
return "You execute a power move!!!";
|
||||
} elseif ($this->criticalAttackValue > $pureAttackersAttack * 1.25) {
|
||||
return "You execute a minor power move!";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Models\BattleEvents;
|
||||
|
||||
use LotGD\Core\Models\FighterInterface;
|
||||
|
||||
/**
|
||||
* BattleEvent
|
||||
*/
|
||||
class DamageEvent extends BattleEvent
|
||||
{
|
||||
/** @var FighterInstance */
|
||||
protected $attacker;
|
||||
/** @var FighterInstance */
|
||||
protected $defender;
|
||||
/** @var int Damage applied */
|
||||
protected $damage;
|
||||
|
||||
public function __construct(FighterInterface $attacker, FighterInterface $defender, int $damage)
|
||||
{
|
||||
$this->attacker = $attacker;
|
||||
$this->defender = $defender;
|
||||
$this->damage = $damage;
|
||||
}
|
||||
|
||||
public function getDamage(): int
|
||||
{
|
||||
return $this->damage;
|
||||
}
|
||||
|
||||
public function apply()
|
||||
{
|
||||
if ($this->damage !== 0) {
|
||||
// Only damage the victim if there is an actual effect
|
||||
$victim = $this->damage > 0 ? $this->defender : $this->attacker;
|
||||
$victim->damage(abs($this->damage));
|
||||
}
|
||||
}
|
||||
|
||||
public function decorate(Game $game): string
|
||||
{
|
||||
$attackersName = $this->attacker->getDisplayName();
|
||||
$defendersName = $this->defender->getDisplayName();
|
||||
|
||||
if ($this->damage === 0) {
|
||||
if ($this->attacker === $game->getCharacter()) {
|
||||
return "You try to hit {$defendersName} but MISS!";
|
||||
}
|
||||
else {
|
||||
return "{$attackersName} tries to hit you but they MISS!";
|
||||
}
|
||||
} elseif ($this->damage > 0) {
|
||||
if ($this->attacker === $game->getCharacter()) {
|
||||
return "You hit {$defendersName} for {$this->damage} points of damage!";
|
||||
}
|
||||
else {
|
||||
return "{$attackersName} hits you for {$this->damage} points of damage!";
|
||||
}
|
||||
} else {
|
||||
if ($this->attacker === $game->getCharacter()) {
|
||||
return "You try to hit {$defendersName} but are RIPOSTED for {$this->damage} points of damage";
|
||||
}
|
||||
else {
|
||||
return "{$attackersName} tries to hit you but you RIPOSTE for {$this->damage} points of damage";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Models\BattleEvents;
|
||||
|
||||
use LotGD\Core\Models\FighterInterface;
|
||||
|
||||
/**
|
||||
* BattleEvent
|
||||
*/
|
||||
class DeathEvent extends BattleEvent
|
||||
{
|
||||
protected $victim;
|
||||
|
||||
public function __construct(FighterInterface $victim)
|
||||
{
|
||||
$this->victim = $victim;
|
||||
}
|
||||
|
||||
public function apply()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function decorate(Game $game): string
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
+25
-14
@@ -10,6 +10,8 @@ use Doctrine\Common\Collections\{
|
||||
use Doctrine\ORM\Mapping\Entity;
|
||||
use Doctrine\ORM\Mapping\Table;
|
||||
|
||||
use LotGD\Core\Game;
|
||||
use LotGD\Core\Tools\Exceptions\BuffSlotOccupiedException;
|
||||
use LotGD\Core\Tools\Model\{
|
||||
Creator,
|
||||
PropertyManager,
|
||||
@@ -215,7 +217,7 @@ class Character implements CharacterInterface, CreateableInterface
|
||||
/**
|
||||
* Returns the character's virtual attribute "attack"
|
||||
*/
|
||||
public function getAttack(): int
|
||||
public function getAttack(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
return $this->level * 2;
|
||||
}
|
||||
@@ -223,7 +225,7 @@ class Character implements CharacterInterface, CreateableInterface
|
||||
/**
|
||||
* Returns the character's virtual attribute "defense"
|
||||
*/
|
||||
public function getDefense(): int
|
||||
public function getDefense(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
return $this->level * 2;
|
||||
}
|
||||
@@ -251,6 +253,27 @@ class Character implements CharacterInterface, CreateableInterface
|
||||
return $this->characterViewpoint->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of buffs
|
||||
*/
|
||||
public function getBuffs(): BuffList
|
||||
{
|
||||
$this->buffList ?? new BuffList($this->buffs);
|
||||
return $this->buffList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a buff to the buffList
|
||||
*/
|
||||
public function addBuff(Buff $buff, bool $override = false)
|
||||
{
|
||||
try {
|
||||
$this->getBuffs()->add($buff);
|
||||
} catch(BuffSlotOccupiedException $e) {
|
||||
$this->getBuffs()->renew($buff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of message threads this user has created.
|
||||
* @return Collection
|
||||
@@ -259,16 +282,4 @@ class Character implements CharacterInterface, CreateableInterface
|
||||
{
|
||||
return $this->messageThreads;
|
||||
}
|
||||
|
||||
public function sendMessageTo(Character $recipient)
|
||||
{
|
||||
// ToDo: implement later
|
||||
throw new \LotGD\Core\Exceptions\NotImplementedException;
|
||||
}
|
||||
|
||||
public function receiveMessageFrom(Character $author)
|
||||
{
|
||||
// ToDo: implement later
|
||||
throw new \LotGD\Core\Exceptions\NotImplementedException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Models;
|
||||
|
||||
use LotGD\Core\Game;
|
||||
|
||||
/**
|
||||
* Interface for models that should be able to participate in fights.
|
||||
*/
|
||||
@@ -13,8 +15,8 @@ interface FighterInterface
|
||||
public function getMaxHealth(): int;
|
||||
public function getHealth(): int;
|
||||
public function isAlive(): bool;
|
||||
public function getAttack(): int;
|
||||
public function getDefense(): int;
|
||||
public function getAttack(Game $game, bool $ignoreBuffs = false): int;
|
||||
public function getDefense(Game $game, bool $ignoreBuffs = false): int;
|
||||
public function damage(int $damage);
|
||||
public function heal(int $heal);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace LotGD\Core\Tools\Model;
|
||||
|
||||
use LotGD\Core\Game;
|
||||
|
||||
/**
|
||||
* Automatically calculated values based on the fighter's level
|
||||
*/
|
||||
@@ -22,7 +24,7 @@ trait AutoScaleFighter
|
||||
* Returns the attack value based on the fighter's level
|
||||
* @return int
|
||||
*/
|
||||
public function getAttack(): int
|
||||
public function getAttack(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
$level = $this->getLevel();
|
||||
return (int)$level * 2 - 1;
|
||||
@@ -32,7 +34,7 @@ trait AutoScaleFighter
|
||||
* Returns the defense value based on the fighter's level
|
||||
* @return int
|
||||
*/
|
||||
public function getDefense(): int
|
||||
public function getDefense(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
$level = $this->getlevel();
|
||||
return (int)floor($level*1.45);
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types = 1);
|
||||
|
||||
namespace LotGD\Core\Tools\Model;
|
||||
|
||||
use LotGD\Core\Game;
|
||||
use LotGD\Core\Exceptions\IsNullException;
|
||||
use LotGD\Core\Models\CharacterViewpoint;
|
||||
|
||||
@@ -61,12 +62,12 @@ trait MockCharacter
|
||||
throw new IsNullException();
|
||||
}
|
||||
|
||||
public function getAttack(): int
|
||||
public function getAttack(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
throw new IsNullException();
|
||||
}
|
||||
|
||||
public function getDefense(): int
|
||||
public function getDefense(Game $game, bool $ignoreBuffs = false): int
|
||||
{
|
||||
throw new IsNullException();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace LotGD\Core\Tests\Models;
|
||||
|
||||
use LotGD\Core\{
|
||||
Battle,
|
||||
DiceBag,
|
||||
Game,
|
||||
Models\Character,
|
||||
Models\Monster
|
||||
};
|
||||
@@ -19,6 +21,19 @@ class BattleTest extends ModelTestCase
|
||||
/** @var string default data set */
|
||||
protected $dataset = "battle";
|
||||
|
||||
public function getMockGame(Character $character): Game
|
||||
{
|
||||
$game = $this->getMockBuilder(Game::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$game->method('getEntityManager')->willReturn($this->getEntityManager());
|
||||
$game->method('getDiceBag')->willReturn(new DiceBag());
|
||||
$game->method('getCharacter')->willReturn($character);
|
||||
|
||||
return $game;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests basic monster functionality
|
||||
*/
|
||||
@@ -26,12 +41,13 @@ class BattleTest extends ModelTestCase
|
||||
{
|
||||
$em = $this->getEntityManager();
|
||||
|
||||
$character = $em->getRepository(Character::class)->find(1);
|
||||
$monster = $em->getRepository(Monster::class)->find(1);
|
||||
|
||||
$this->assertSame(5, $monster->getLevel());
|
||||
$this->assertSame(52, $monster->getMaxHealth());
|
||||
$this->assertSame(9, $monster->getAttack());
|
||||
$this->assertSame(7, $monster->getDefense());
|
||||
$this->assertSame(9, $monster->getAttack($this->getMockGame($character)));
|
||||
$this->assertSame(7, $monster->getDefense($this->getMockGame($character)));
|
||||
$this->assertSame($monster->getMaxHealth(), $monster->getHealth());
|
||||
}
|
||||
|
||||
@@ -45,7 +61,7 @@ class BattleTest extends ModelTestCase
|
||||
$character = $em->getRepository(Character::class)->find(1);
|
||||
$monster = $em->getRepository(Monster::class)->find(1);
|
||||
|
||||
$battle = new Battle($character, $monster);
|
||||
$battle = new Battle($this->getMockGame($character), $character, $monster);
|
||||
|
||||
for ($n = 0; $n < 99; $n++) {
|
||||
$oldPlayerHealth = $character->getHealth();
|
||||
@@ -75,7 +91,7 @@ class BattleTest extends ModelTestCase
|
||||
$highLevelPlayer = $em->getRepository(Character::class)->find(2);
|
||||
$lowLevelMonster = $em->getRepository(Monster::class)->find(3);
|
||||
|
||||
$battle = new Battle($highLevelPlayer, $lowLevelMonster);
|
||||
$battle = new Battle($this->getMockGame($highLevelPlayer), $highLevelPlayer, $lowLevelMonster);
|
||||
|
||||
for ($n = 0; $n < 99; $n++) {
|
||||
$oldPlayerHealth = $highLevelPlayer->getHealth();
|
||||
@@ -108,7 +124,7 @@ class BattleTest extends ModelTestCase
|
||||
$lowLevelPlayer = $em->getRepository(Character::class)->find(3);
|
||||
$highLevelMonster = $em->getRepository(Monster::class)->find(2);
|
||||
|
||||
$battle = new Battle($lowLevelPlayer, $highLevelMonster);
|
||||
$battle = new Battle($this->getMockGame($lowLevelPlayer), $lowLevelPlayer, $highLevelMonster);
|
||||
|
||||
for ($n = 0; $n < 99; $n++) {
|
||||
$oldPlayerHealth = $lowLevelPlayer->getHealth();
|
||||
@@ -141,7 +157,7 @@ class BattleTest extends ModelTestCase
|
||||
$character = $em->getRepository(Character::class)->find(1);
|
||||
$monster = $em->getRepository(Monster::class)->find(1);
|
||||
|
||||
$battle = new Battle($character, $monster);
|
||||
$battle = new Battle($this->getMockGame($character), $character, $monster);
|
||||
|
||||
$battle->getWinner();
|
||||
}
|
||||
@@ -156,9 +172,9 @@ class BattleTest extends ModelTestCase
|
||||
$character = $em->getRepository(Character::class)->find(1);
|
||||
$monster = $em->getRepository(Monster::class)->find(1);
|
||||
|
||||
$battle = new Battle($character, $monster);
|
||||
$battle = new Battle($this->getMockGame($character), $character, $monster);
|
||||
|
||||
$battle->getLooser();
|
||||
$battle->getLoser();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,7 +188,7 @@ class BattleTest extends ModelTestCase
|
||||
$character = $em->getRepository(Character::class)->find(1);
|
||||
$monster = $em->getRepository(Monster::class)->find(1);
|
||||
|
||||
$battle = new Battle($character, $monster);
|
||||
$battle = new Battle($this->getMockGame($character), $character, $monster);
|
||||
|
||||
// Fighting for 99 rounds should be enough for determining a looser - and to
|
||||
// throw the exception.
|
||||
|
||||
Reference in New Issue
Block a user