Класс рассчёта нанесения физичестого урона. #2
This commit is contained in:
parent
7596d115fa
commit
54da589f45
127
classes/Battles/Fight/PhysicalDamage.php
Normal file
127
classes/Battles/Fight/PhysicalDamage.php
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Battles\Fight;
|
||||||
|
|
||||||
|
class PhysicalDamage
|
||||||
|
{
|
||||||
|
const BASE_STAT = 10;
|
||||||
|
|
||||||
|
private function rangeCheck(int $var, int $min, int $max = null): bool
|
||||||
|
{
|
||||||
|
if (is_null($max)) {
|
||||||
|
if ($var > $min) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($var > $min && $var <= $max) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Бонус 1 очко выше 10: +5% профильного урона.
|
||||||
|
* Штраф 1 очко ниже 10: -10% профильного урона.
|
||||||
|
* @param int $stat
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function statDamageModificator(int $stat): int
|
||||||
|
{
|
||||||
|
$bonus = ($stat - self::BASE_STAT) * 5;
|
||||||
|
if ($bonus < 0) {
|
||||||
|
$bonus *= 2;
|
||||||
|
}
|
||||||
|
return $bonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Бонус 1 очко выше 10: +1% шанса крита.
|
||||||
|
* Штраф 1 очко ниже 10: -2% шанса крита.
|
||||||
|
* @param int $stat
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function statCriticalsModificator(int $stat): int
|
||||||
|
{
|
||||||
|
$bonus = ($stat - self::BASE_STAT);
|
||||||
|
if ($bonus < 0) {
|
||||||
|
$bonus *= 2;
|
||||||
|
}
|
||||||
|
return $bonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рассчёт типа удара в зависимости от параметров.
|
||||||
|
* Значения проверок смещаются в зависимости от разницы двух параметров.
|
||||||
|
* @param int $player_accuracy
|
||||||
|
* @param int $enemy_evasion
|
||||||
|
* @param int $player_criticals
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function attack(int $player_accuracy, int $enemy_evasion, int $player_criticals): string
|
||||||
|
{
|
||||||
|
$result = '';
|
||||||
|
$d100 = mt_rand(0, 100);
|
||||||
|
$mf = $player_accuracy - $enemy_evasion;
|
||||||
|
if ($this->rangeCheck($d100, min(1, 0 - $mf), 15 - $mf)) {
|
||||||
|
$result = 'selfharm';
|
||||||
|
}
|
||||||
|
if ($this->rangeCheck($d100, min(1, 16 - $mf), 50 - $mf)) {
|
||||||
|
$result = 'miss';
|
||||||
|
}
|
||||||
|
if ($this->rangeCheck($d100, 51 - $mf, 100 - $mf - $player_criticals)) {
|
||||||
|
$result = 'hit';
|
||||||
|
}
|
||||||
|
if ($this->rangeCheck($d100, 101 - $mf - $player_criticals)) {
|
||||||
|
$result = 'crit';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рассчёт базового урона до применения модификаторов.
|
||||||
|
* Если урон меньше равно нулю, получается удар в 20% от минималки.
|
||||||
|
* Учитывая удар кулака 1-2, значения прибавляются к $min и $max в формуле.
|
||||||
|
* @param int $min минимальный урон
|
||||||
|
* @param int $max максимальный урон
|
||||||
|
* @param int $enemyDefence защита противника
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function baseDamage(int $min, int $max, int $enemyDefence): int
|
||||||
|
{
|
||||||
|
return max(mt_rand(1 + $min, 2 + $max) - $enemyDefence, intval(round((1 + $min) * (20 / 100))));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object $attacker [str,dex,intu,accuracy,crit,min_dmg,max_dmg]
|
||||||
|
* @param object $defender [evasion,defence]
|
||||||
|
* @param int $type тип удара: ближний бой (1), дальний бой (2).
|
||||||
|
* @return object
|
||||||
|
*/
|
||||||
|
public function hit(object $attacker, object $defender, int $type): object
|
||||||
|
{
|
||||||
|
$result = (object)[];
|
||||||
|
$attackType = $this->attack($attacker->accuracy, $defender->evasion, $attacker->criticals + $this->statCriticalsModificator($attacker->intuition));
|
||||||
|
if ($attackType === 'miss') {
|
||||||
|
$result->damage = 0;
|
||||||
|
$result->attackType = $attackType;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
$damage = $this->baseDamage($attacker->min_damage, $attacker->max_damage, $defender->defence);
|
||||||
|
$critDamageMultiplier = $attackType === 'crit' ? 2 : 1;
|
||||||
|
if ($type === 1) {
|
||||||
|
$damage = $damage * ($this->statDamageModificator($attacker->strength) / 100);
|
||||||
|
}
|
||||||
|
if ($type === 2) {
|
||||||
|
$damage = $damage * ($this->statDamageModificator($attacker->dexterity) / 100);
|
||||||
|
}
|
||||||
|
$damage = $damage * $critDamageMultiplier;
|
||||||
|
|
||||||
|
$result->damage = $damage;
|
||||||
|
$result->attackType = $attackType;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user