Любая магия делится на боевую и небоевую. Боевая применяется строго в поединке, небоевая где угодно и как угодно.
Любая магия выполняет одно из действий: наносит урон или вешает эффект. Если сильно утрировать, то затраты маны на заклинание это магический урон по себе.
Любая магия может быть нацелена: на конкретного игрока, на группу игроков. Если сильно утрировать, "на себя" это подвид "на конкретного игрока", а всякие "на всех врагов" это подвид "на группу игроков". Если прямо глобально утрировать, то "на конкретного игрока" это foreach
из одного элемента.
Любой урон может быть: моментальным, отложенным или циклическим. Либо вообще любое заклинание, просто не использовать некоторые дикие комбинации.
При формировании заклинания нацеленного на урон, проверяется успех каста, потом проверяются защиты цели, потом вызывается наноситель урона.
При формировании заклинания нацеленного на эффект, проверяется успех каста, потом проверяются защиты цели (если применимо), потом вызывается вешатель эффектов.
# Псевдокод
function castDamage($caster, $manaCost, $amountDamage, $target)
{
$this->damageMana($manaCost, $caster);
if ($user->mana < 0 && $manacost !== 0) {
return false; # Да, хардкор.
}
$this->damageHealth($amountDamage, $target);
}
function castEffect($caster, $manaCost, $effectId, $target)
{
$this->damageMana($manaCost, $caster);
if ($user->mana < 0) {
return false; # Да, хардкор.
}
$this->setEffect($effectId, $target)
}
function fireball($caster, ...$targets)
{
$manaCost = 50;
$baseDamage = -10; # Урон отнимается от здоровья.
foreach ($targets as $target) {
$damage = calculateDamage($baseDamage, $target->resists);
castDamage($caster, $manaCost, $damage, $target);
}
}
function heal($caster, ...$targets)
{
$manaCost = 10;
$baseDamage = 4; # Лечение это отрицательный урон.
$damage = calculateDamage($baseDamage, $target->resists);
castDamage($caster, $manaCost, $damage, $target);
}
function smallHealingPotion($caster) # Зелье лечения
{
$manaCost = 0;
$baseDamage = 1
castDamage($caster, $manaCost, $baseDamage, $caster);
}
# Псевдокод
function getUnitForEffect($effect)
{
$aliveUnits = [];
foreach ($this->units as $unit) {
if ($unit->isAlive()) {
$aliveUnits[] = $unit;
}
}
// Если живых юнитов нет - возвращаем null
if (count($aliveUnits) === 0) {
return null;
}
// Чтобы эффект накладывался случайному юниту, а не первому - перемешиваем массив
shuffle($aliveUnits);
// Проходим по юнитам и проверяем, у кого указанного эффекта нет
foreach ($aliveUnits as $unit) {
if (!$unit->getEffects()->exist($effect)) {
return $unit;
}
}
return null;
}