battles/classes/Battles/UserStats.php

200 lines
6.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
# Date: 03.02.2021 (11:05)
namespace Battles;
use Battles\Models\Inventory;
use Battles\Models\User\Effects;
use Battles\Models\User\Stats;
use Exceptions\GameException;
class UserStats extends User
{
protected int $id;
protected int $strength;
protected int $dexterity;
protected int $intuition;
protected int $endurance;
protected int $intelligence;
protected int $wisdom;
protected int $health;
protected int $mana;
protected int $freeStatPoints = 0;
protected int $level;
private const STAT_MAXIMUM_AMOUNT = 40;
private const ERROR_STAT_IS_MAXIMUM = 'Ошибка: Параметр достиг своего лимита!';
private const ERROR_STAT_UNKNOWN = 'Ошибка: Неизвестный параметр!';
private const STAT_NAMES_ARRAY = ['strength', 'dexterity', 'intuition', 'endurance', 'intelligence', 'wisdom'];
//// Неизменяемые для игрока(!) переменные.
// Удар кулаком всегда 1-2.
protected int $minDamage = 1;
protected int $maxDamage = 2;
// Природная броня всегда 0.
// Динамически рассчитываемые
protected int $maxHealth;
protected int $maxMana;
/**
* UserStats constructor.
*
* @param $user
*/
public function __construct($user)
{
$data = Stats::getAll($user);
$this->id = $data->id;
$this->strength = $data->strength;
$this->dexterity = $data->dexterity;
$this->intuition = $data->intuition;
$this->endurance = $data->endurance;
$this->intelligence = $data->intelligence;
$this->wisdom = $data->wisdom;
$this->health = $data->health;
$this->mana = $data->mana;
$this->freeStatPoints = $data->free_stat_points;
$this->level = $data->level;
parent::__construct($user);
$this->maxHealth = round(($this->endurance * 3) + ($this->endurance / 2) * ($this->level - 1) + ($this->endurance / 5) * (($this->level - 1) * ($this->level - 2) / 2));
$this->maxMana = round(($this->wisdom * 3) + ($this->wisdom / 2) * ($this->level - 1) + ($this->wisdom / 5) * (($this->level - 1) * ($this->level - 2) / 2));
}
/**
* Отдаёт информацию о базовом(!) стате.
*
* @param string $statName - имя стата. Может принимать значения 'strength', 'dexterity', 'intuition',
* 'endurance', 'intelligence', 'wisdom'.
* @param int $isMainWindow - переключатель "главного окна". Если включить, дополнительно будет показывать ссылку
* на повышение стата на 1, при условии наличия свободных очков статов.
*
* @return string
* @throws GameException
*/
public function getStat(string $statName, int $isMainWindow = 0): string
{
if (!in_array($statName, self::STAT_NAMES_ARRAY)) {
throw new GameException(self::ERROR_STAT_UNKNOWN);
}
$stat = strval($this->$statName);
if ($this->freeStatPoints && $isMainWindow && $this->$statName < self::STAT_MAXIMUM_AMOUNT) {
$rand = strval(mt_rand());
$stat .= " <a href='/main.php?edit=$rand&ups=$statName'>[+]</a>";
}
return $stat;
}
/**
* Повышает один из выбранных статов на 1, но не выше self::STAT_MAXIMUM_AMOUNT при условии наличия свободных очков
* статов.
*
* @param string $statName - имя стата. Может принимать значения 'strength', 'dexterity', 'intuition',
* 'endurance', 'intelligence', 'wisdom'.
*
* @throws GameException
*/
public function addOnePointToStat(string $statName)
{
if (!in_array($statName, self::STAT_NAMES_ARRAY)) {
throw new GameException(self::ERROR_STAT_UNKNOWN);
}
if ($this->freeStatPoints <= 0 || $this->$statName >= self::STAT_MAXIMUM_AMOUNT) {
throw new GameException(self::ERROR_STAT_IS_MAXIMUM);
} else {
Stats::addOne($statName, $this->id);
}
}
public function getMaxWeight(): int
{
return max($this->strength * 5, 50);
}
/**
* @return mixed
*/
public function getHealth()
{
return $this->health;
}
/**
* @return mixed
*/
public function getMana()
{
return $this->mana;
}
/**
* @return mixed
*/
public function getFreeStatPoints()
{
return $this->freeStatPoints;
}
/**
* @return float
*/
public function getMaxHealth(): float
{
return $this->maxHealth;
}
/**
* @return float
*/
public function getMaxMana(): float
{
return $this->maxMana;
}
public function getFullStats(): object
{
$stats = Stats::getAll($this->id);
$itemBonuses = Inventory::getBonuses($this->id);
$effectBonuses = Effects::getStatMods($this->id);
$obj = (object)[];
foreach (self::STAT_NAMES_ARRAY as $stat) {
$obj->$stat = max(0, $stats->$stat + $itemBonuses->{'item_' . $stat} + $effectBonuses->{'effect_' . $stat});
}
$obj->accuracy = max(0, $itemBonuses->item_accuracy);
$obj->evasion = max(0, $itemBonuses->item_evasion);
$obj->criticals = max(0, $itemBonuses->item_criticals);
$obj->min_physical_damage = max($this->minDamage, $this->minDamage + $itemBonuses->item_min_physical_damage);
$obj->max_physical_damage = max($this->maxDamage, $this->maxDamage + $itemBonuses->item_max_physical_damage);
return $obj;
}
public function levelUp(): string
{
$this->level += 1;
$this->freeStatPoints += 2;
$this->save();
Chat::sendSys('Внимание, вы получили ' . $this->level . 'уровень. Доступны очки распределения параметров.');
return 'Персонаж перешёл на ' . $this->level . 'уровень.';
}
/** Сохраняет в базу актуальные статы, здоровье, ману, свободные очки статов и уровень.
*
*/
private function save()
{
Stats::save([
$this->strength, //set
$this->dexterity,
$this->intuition,
$this->endurance,
$this->intelligence,
$this->wisdom,
$this->health,
$this->mana,
$this->freeStatPoints,
$this->level,
$this->id //where
]);
}
}