From 54da589f45cdc61ea2a2df9d0271eae12ce3d6d8 Mon Sep 17 00:00:00 2001 From: "Igor Barkov (iwork)" Date: Thu, 27 Jan 2022 17:16:01 +0200 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D0=B0=D1=81=D1=81=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D1=87=D1=91=D1=82=D0=B0=20=D0=BD=D0=B0=D0=BD=D0=B5?= =?UTF-8?q?=D1=81=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=84=D0=B8=D0=B7=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D1=81=D1=82=D0=BE=D0=B3=D0=BE=20=D1=83=D1=80=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0.=20#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- classes/Battles/Fight/PhysicalDamage.php | 127 +++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 classes/Battles/Fight/PhysicalDamage.php diff --git a/classes/Battles/Fight/PhysicalDamage.php b/classes/Battles/Fight/PhysicalDamage.php new file mode 100644 index 0000000..b67e7e9 --- /dev/null +++ b/classes/Battles/Fight/PhysicalDamage.php @@ -0,0 +1,127 @@ + $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; + } +} \ No newline at end of file