Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
45 lines
3.2 KiB
C++
45 lines
3.2 KiB
C++
#pragma once
|
||
// -----------------------------------------------------------------------------
|
||
// Поведение тварей. Отдельный файл, потому что здесь единственное место, где
|
||
// противник ЧИТАЕТ бойцов: sim/target.h про Agent не знает и знать не должен.
|
||
//
|
||
// Правила простые и намеренно читаемые с экрана:
|
||
// 1. заметил — идёт;
|
||
// 2. дошёл — замахивается, и замах ВИДНО (windupTimer);
|
||
// 3. довёл замах — бьёт по геометрии СВОЕЙ атаки (AttackKind).
|
||
// Между 2 и 3 у игрока есть время отойти или убить. Без телеграфа удар твари
|
||
// неотличим от случайной потери здоровья, и бой перестаёт быть боем.
|
||
//
|
||
// Пункт 3 — это пять разных задач для игрока, а не один урон:
|
||
// SWIPE — сектор перед тварью: уводи бойца вбок;
|
||
// LUNGE — рывок по прямой: освободи ОСЬ, а не точку;
|
||
// SPIT — снаряд: единственное, что перекрывается стеной;
|
||
// SLAM — круг вокруг твари: не толпитесь возле неё вдвоём;
|
||
// GRAB — захват: боец встал намертво, вытаскивать его придётся огнём.
|
||
// Числа этих форм — в EnemyDef (sim/target.cpp), общие множители — в tuning.h.
|
||
//
|
||
// ИИ не решает, кого атаковать, «по-умному»: ближайший живой боец в радиусе.
|
||
// Прототип проверяет отряд, а не противника, — и цена ошибки здесь должна быть
|
||
// в геометрии, а не в чужой хитрости.
|
||
// -----------------------------------------------------------------------------
|
||
#include <vector>
|
||
|
||
#include "ecs/ecs.h"
|
||
#include "sim/agent.h"
|
||
#include "sim/events.h"
|
||
#include "sim/target.h"
|
||
#include "engine/tilemap.h"
|
||
|
||
// Шевелит всех, у кого kind != DUMMY. Мишени приёмки не трогает вообще:
|
||
// --accept обязан считать ровно то же, что считал.
|
||
// aggroMul — во сколько раз дальше твари замечают отряд прямо сейчас. Больше
|
||
// единицы бывает ровно в одном случае: у отряда сел фонарь (sim/items.h).
|
||
// Радиус ЗАМЕТИЛ — единственное, что темнота меняет на стороне тварей: бьют они
|
||
// так же и ходят так же, просто находят раньше.
|
||
void UpdateEnemies(ecs::World& world, const Tilemap& map, Agent* agents, int agentCount,
|
||
std::vector<Target>& targets, float dt, CombatEventLog* events,
|
||
float aggroMul = 1.0f);
|
||
|
||
// Сколько тварей сейчас идёт к отряду. Для напряжения и HUD.
|
||
int CountAggroEnemies(const std::vector<Target>& targets);
|