208 lines
8.1 KiB
C
208 lines
8.1 KiB
C
|
|
#pragma once
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
// Каталог оружия: ЧТО такое ствол или клинок, в отрыве от того, кто его держит.
|
|||
|
|
//
|
|||
|
|
// Оружие — отдельная сущность ECS с компонентом WeaponItem. Боец хранит только
|
|||
|
|
// ссылку на неё (Agent::weaponEntity) и рабочее состояние выстрела (патроны,
|
|||
|
|
// откат, увод ствола). Поэтому «дать бойцу пистолет» — это подменить компонент
|
|||
|
|
// на его сущности-оружии, а не править ни агента, ни правила боя.
|
|||
|
|
//
|
|||
|
|
// Где живут числа. Общее правило прототипа — все числа в tuning.h. Здесь оно
|
|||
|
|
// соблюдено с одной оговоркой, записанной в docs/08-decisions.md: КАРАБИН
|
|||
|
|
// (оружие по умолчанию, то самое, на котором меряются критерии приёмки) читает
|
|||
|
|
// свои параметры из g_tune, поэтому все прежние ручки оверлея и --set работают
|
|||
|
|
// как работали. Остальные стволы — записи каталога: у второго ствола не может
|
|||
|
|
// быть «того же самого» weaponRange, иначе он не второй ствол.
|
|||
|
|
//
|
|||
|
|
// Визуальные параметры атаки лежат ЗДЕСЬ ЖЕ, но в нейтральном виде: длины,
|
|||
|
|
// радиусы в пикселях и байты RGB. Ни одного типа рендера в sim/ не появилось —
|
|||
|
|
// цвет собирает render/fx.cpp. Так у пистолета своя вспышка и свой трассер,
|
|||
|
|
// и при этом правило «sim не знает про рендер» не нарушено.
|
|||
|
|
// -----------------------------------------------------------------------------
|
|||
|
|
#include <cstdint>
|
|||
|
|
|
|||
|
|
#include "core/math.h"
|
|||
|
|
#include "tuning.h"
|
|||
|
|
|
|||
|
|
enum class WeaponClass : uint8_t
|
|||
|
|
{
|
|||
|
|
RANGED = 0, // ствол: линия огня, снаряд, правило 6.3
|
|||
|
|
MELEE = 1, // клинок: сектор замаха, то же правило в угловой форме
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
inline const char* WeaponClassName(WeaponClass c)
|
|||
|
|
{
|
|||
|
|
return (c == WeaponClass::MELEE) ? "MELEE" : "RANGED";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
enum class FirearmId : uint8_t
|
|||
|
|
{
|
|||
|
|
RIFLE = 0, // штатный карабин отряда: числа из tuning.h
|
|||
|
|
PISTOL = 1, // короткоствол: ближе, быстрее, мельче магазин
|
|||
|
|
COUNT = 2,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// --- ствол -------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
struct FirearmDef
|
|||
|
|
{
|
|||
|
|
const char* name = "rifle";
|
|||
|
|
|
|||
|
|
// баллистика и урон
|
|||
|
|
float range = 7.2f;
|
|||
|
|
float fireInterval = 0.35f;
|
|||
|
|
float damage = 12.0f;
|
|||
|
|
float laneHalfWidth = 0.10f;
|
|||
|
|
float muzzleOffset = 0.30f;
|
|||
|
|
float bulletSpeed = 22.0f;
|
|||
|
|
float bulletRadius = 0.04f;
|
|||
|
|
float knockback = 0.35f; // импульс мишени от попадания
|
|||
|
|
|
|||
|
|
// разброс: стоя, на полном ходу, и увод ствола за выстрел
|
|||
|
|
float spreadStandDeg = 0.9f;
|
|||
|
|
float spreadMoveDeg = 4.2f;
|
|||
|
|
float spreadRecoilDeg = 0.55f;
|
|||
|
|
float spreadRecoilMax = 3.0f;
|
|||
|
|
float recoilDecay = 3.2f; // 1/сек
|
|||
|
|
|
|||
|
|
// перезарядка
|
|||
|
|
int magazine = 24;
|
|||
|
|
float reloadTime = 1.9f;
|
|||
|
|
|
|||
|
|
// визуал атаки (нейтральные числа: пиксели, секунды, байты RGB)
|
|||
|
|
float tracerLength = 1.30f;
|
|||
|
|
float muzzleRadiusPx = 5.0f;
|
|||
|
|
float muzzleTime = 0.07f;
|
|||
|
|
float muzzleFlamePx = 0.35f; // длина языка пламени, юнитов мира
|
|||
|
|
float flashPower = 0.55f; // как источник света
|
|||
|
|
float flashRadius = 4.0f;
|
|||
|
|
float shakePerShot = 0.55f;
|
|||
|
|
uint8_t tracerR = 255, tracerG = 240, tracerB = 205;
|
|||
|
|
uint8_t muzzleR = 255, muzzleG = 225, muzzleB = 150;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// --- клинок ------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
struct BladeDef
|
|||
|
|
{
|
|||
|
|
const char* name = "blade";
|
|||
|
|
|
|||
|
|
float reach = 1.40f;
|
|||
|
|
float arcDeg = 100.0f;
|
|||
|
|
float windup = 0.17f;
|
|||
|
|
float strike = 0.13f;
|
|||
|
|
float recover = 0.24f;
|
|||
|
|
float interval = 0.60f;
|
|||
|
|
float damage = 130.0f;
|
|||
|
|
float knockback = 2.4f; // импульс мишени, юнитов/сек
|
|||
|
|
float lungeSpeed = 3.4f; // рывок в момент удара
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// --- компонент сущности-оружия ------------------------------------------------
|
|||
|
|
|
|||
|
|
struct WeaponItem
|
|||
|
|
{
|
|||
|
|
WeaponClass cls = WeaponClass::RANGED;
|
|||
|
|
FirearmId gunId = FirearmId::RIFLE;
|
|||
|
|
FirearmDef gun{};
|
|||
|
|
BladeDef blade{};
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// --- каталог ------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
// Карабин: параметры берутся из tuning, чтобы прежние ручки и --set остались
|
|||
|
|
// рабочими (см. шапку файла).
|
|||
|
|
inline FirearmDef RifleDef()
|
|||
|
|
{
|
|||
|
|
FirearmDef d;
|
|||
|
|
d.name = "rifle";
|
|||
|
|
d.range = g_tune.weaponRange;
|
|||
|
|
d.fireInterval = g_tune.fireInterval;
|
|||
|
|
d.damage = g_tune.damage;
|
|||
|
|
d.laneHalfWidth = g_tune.laneHalfWidth;
|
|||
|
|
d.muzzleOffset = g_tune.muzzleOffset;
|
|||
|
|
d.bulletSpeed = g_tune.bulletSpeed;
|
|||
|
|
d.bulletRadius = g_tune.bulletRadius;
|
|||
|
|
d.knockback = g_tune.bulletKnock;
|
|||
|
|
|
|||
|
|
d.spreadStandDeg = g_tune.spreadStandDeg;
|
|||
|
|
d.spreadMoveDeg = g_tune.spreadMoveDeg;
|
|||
|
|
d.spreadRecoilDeg = g_tune.spreadRecoilDeg;
|
|||
|
|
d.spreadRecoilMax = g_tune.spreadRecoilMax;
|
|||
|
|
d.recoilDecay = g_tune.spreadRecoilDecay;
|
|||
|
|
|
|||
|
|
d.magazine = int(g_tune.magazineRifle);
|
|||
|
|
d.reloadTime = g_tune.reloadRifle;
|
|||
|
|
|
|||
|
|
d.tracerLength = g_tune.tracerLength;
|
|||
|
|
d.muzzleRadiusPx = g_tune.muzzleRadiusPx;
|
|||
|
|
d.muzzleTime = g_tune.muzzleTime;
|
|||
|
|
d.flashPower = g_tune.flashPower;
|
|||
|
|
d.flashRadius = g_tune.flashRadius;
|
|||
|
|
d.shakePerShot = g_tune.shakePerShot;
|
|||
|
|
return d;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Пистолет: бьёт ближе и слабее, но чаще; на ходу «гуляет» заметно сильнее
|
|||
|
|
// карабина, зато перезаряжается вдвое быстрее. Вспышка мельче и холоднее,
|
|||
|
|
// трассер короче — ствол должен читаться по картинке, а не только по цифрам.
|
|||
|
|
inline FirearmDef PistolDef()
|
|||
|
|
{
|
|||
|
|
FirearmDef d;
|
|||
|
|
d.name = "pistol";
|
|||
|
|
d.range = 4.6f;
|
|||
|
|
d.fireInterval = 0.22f;
|
|||
|
|
d.damage = 8.0f;
|
|||
|
|
d.laneHalfWidth = 0.10f;
|
|||
|
|
d.muzzleOffset = 0.24f;
|
|||
|
|
d.bulletSpeed = 17.0f;
|
|||
|
|
d.bulletRadius = 0.04f;
|
|||
|
|
d.knockback = 0.22f;
|
|||
|
|
|
|||
|
|
d.spreadStandDeg = 1.6f;
|
|||
|
|
d.spreadMoveDeg = 6.5f;
|
|||
|
|
d.spreadRecoilDeg = 0.9f;
|
|||
|
|
d.spreadRecoilMax = 4.5f;
|
|||
|
|
d.recoilDecay = 4.5f;
|
|||
|
|
|
|||
|
|
d.magazine = 7;
|
|||
|
|
d.reloadTime = 1.15f;
|
|||
|
|
|
|||
|
|
d.tracerLength = 0.85f;
|
|||
|
|
d.muzzleRadiusPx = 3.5f;
|
|||
|
|
d.muzzleTime = 0.055f;
|
|||
|
|
d.muzzleFlamePx = 0.26f;
|
|||
|
|
d.flashPower = 0.42f;
|
|||
|
|
d.flashRadius = 3.2f;
|
|||
|
|
d.shakePerShot = 0.34f;
|
|||
|
|
d.tracerR = 255; d.tracerG = 214; d.tracerB = 170;
|
|||
|
|
d.muzzleR = 255; d.muzzleG = 205; d.muzzleB = 130;
|
|||
|
|
return d;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
inline FirearmDef FirearmDefOf(FirearmId id)
|
|||
|
|
{
|
|||
|
|
return (id == FirearmId::PISTOL) ? PistolDef() : RifleDef();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
inline const char* FirearmName(FirearmId id)
|
|||
|
|
{
|
|||
|
|
return (id == FirearmId::PISTOL) ? "PISTOL" : "RIFLE";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Клинок пока один, и его числа целиком в tuning.
|
|||
|
|
inline BladeDef DefaultBladeDef()
|
|||
|
|
{
|
|||
|
|
BladeDef d;
|
|||
|
|
d.reach = g_tune.meleeReach;
|
|||
|
|
d.arcDeg = g_tune.meleeArcDeg;
|
|||
|
|
d.windup = g_tune.meleeWindup;
|
|||
|
|
d.strike = g_tune.meleeStrike;
|
|||
|
|
d.recover = g_tune.meleeRecover;
|
|||
|
|
d.interval = g_tune.meleeInterval;
|
|||
|
|
d.damage = g_tune.meleeDamage;
|
|||
|
|
d.knockback = g_tune.meleeKnockback;
|
|||
|
|
d.lungeSpeed = g_tune.meleeLungeSpeed;
|
|||
|
|
return d;
|
|||
|
|
}
|