squad-proto/src/sim/loot.h
z.kirill ef103050b1 Правки по игре: начало, ставка, наёмники (M29)
Семь изменений по итогам игры вживую.

НАЧАЛО. Первый этаж встречал одинокого оперативника с ножом тремя тварями,
из которых одна быстрая: бюджет 3.0 и бегуны с первого этажа. Стало 2.2
(ровно два бредущих), бегуны с четвёртого. Света прибавлено: обзор
начинается с 1.30 вместо 1.0, у этажа появилась своя яркость пройденного
(0.42 наверху против 0.13 на дне). Наверху ещё работает освещение, и
хоррор первого этажа в том, что игрок один, а не в том, что не видно
стен. Темнота это инструмент глубины, и тратить её на первый этаж значит
не иметь запаса дальше.

СТАВКА. Опыт платится за убийства и сразу: выносить надо ВЕЩИ. Вайп
больше не отнимает всё - доезжает около половины добычи, и чем вещь реже,
тем охотнее теряется. Прежнее "вайп не возвращает ничего" делало
единственным разумным поведением уход наверх при первой царапине.

ВЫХОД. Аномалия возврата переехала из точки входа к спуску: развилка
"вниз или наверх" теперь там же, где этаж кончился. Обратный путь через
растревоженный этаж ничего не решал - это был ещё раз тот же этаж.

ЧЕКПОИНТЫ через 50 этажей вместо пяти: забег это долгий спуск, а не
перебежка между сохранениями.

НАЁМНИКИ. Кнопка "нанять за опыт" убрана, оперативники находятся в
капсулах на этажах: в среднем раз в сотню этажей и не чаще раза в
двадцать. У каждого свои три прибавки из одного бюджета - разница в
характере, а не в ранге. Покупка была скучной ровно в том смысле, в каком
скучна любая кнопка "стать сильнее": ничего не рассказывает и никуда не
зовёт.

ЗАМЕРЫ. Вайп на сотне повторов: доезжает 52% (обычное 69%, реликты 25%).
Первая версия проверки считала одну сумку и выдала "обычного доехало
112%" - спасение забирает ещё и надетое. Опыт: банк 558 -> 578 за
убийство без эвакуации. Капсула поднимает отряд до двух и даёт наёмнику
его числа.

Формат профиля 6: строки merc и rescued.

Не сделано и обсуждается: ростер сверх пятерых, задания для свободных,
пассивные бонусы от сидящих на базе.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 04:09:26 +03:00

63 lines
4.2 KiB
C++
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.

#pragma once
// -----------------------------------------------------------------------------
// Предмет, лежащий на полу, и его подбор.
//
// Зачем отдельная сущность, а не «выдать предмет при убийстве»: в игре про
// спуск находка — это МЕСТО, до которого надо дойти. Лут, падающий в инвентарь
// сам, не заставляет никуда идти и превращает «лучше лут глубже» в строку в
// логе. Лежащий предмет виден в темноте плохо, лежит он там, куда отряд ещё не
// заходил, и за ним надо разомкнуть строй — это и есть цена находки.
//
// Подбор ПАССИВНЫЙ: боец, прошедший по предмету, поднимает его. Отдельной
// кнопки нет намеренно — игрок и так не нажимает «огонь» (спек 5), и заводить
// ради лута первое ручное действие в игре значило бы менять её жанр.
//
// FloorItem — компонент ECS в своём пуле, как Target и Bullet. Правила боя про
// него не знают вообще: ни решатель, ни LaneClear, ни клинок его не видят.
// -----------------------------------------------------------------------------
#include <vector>
#include "engine/math.h"
#include "ecs/ecs.h"
#include "sim/events.h"
#include "sim/items.h"
struct Agent;
struct FloorItem
{
ecs::Entity self = ecs::NO_ENTITY;
// Лежит на полу ЭКЗЕМПЛЯР со своими аффиксами: он выкатан при сборке
// этажа и не должен добрасываться заново при подборе (sim/affix.h).
ItemInstance id;
Vec2 pos{};
// Предмет не удаляется в момент подбора: пул перетасовывается swap-remove,
// а по нему в этот момент идёт цикл. Помеченные снимаются одним проходом
// после него.
bool taken = false;
// Сколько секунд предмет НЕ подбирается. Нужно ровно одному случаю: вещь,
// которую боец только что выбросил, лежит у него под ногами, и пассивный
// подбор поднял бы её тем же шагом. Выбросить стало бы невозможно.
float noPickup = 0.0f;
};
// pickupDelay > 0 — предмет полежит, прежде чем его снова можно подобрать.
void SpawnFloorItem(ecs::World& world, const ItemInstance& id, Vec2 pos,
float pickupDelay = 0.0f);
// Подбор за шаг. Возвращает, сколько предметов поднято.
//
// Мёртвый боец ничего не подбирает, полная сумка — тоже: предмет остаётся
// лежать, и это правильно. «Некуда положить» обязано быть видно как лежащий
// под ногами предмет, а не как молча пропавшая находка.
// Подбирают В ОБЩУЮ СУМКУ: кто прошёл по предмету, тот его и поднял, но
// достанется он всему отряду. carriers — на скольких живых делится ноша.
// rescued — сюда пишется индекс бойца, наткнувшегося на капсулу, или -1.
// Саму капсулу подбор не «поднимает»: оперативник встаёт в строй, а это уже
// дело отряда, и знать про него sim/loot.cpp не обязан.
int UpdateLootPickup(ecs::World& world, Agent* agents, int agentCount, SquadBag& bag,
int carriers, float carryBonus, CombatEventLog* events, float dt,
int* rescued = nullptr);