Skip to content

Копьё: урон и встревание от скорости движения (Momentum Melee)#950

Open
Grom1halo wants to merge 1 commit into
space-syndicate:masterfrom
Grom1halo:feature/momentum-melee-spear
Open

Копьё: урон и встревание от скорости движения (Momentum Melee)#950
Grom1halo wants to merge 1 commit into
space-syndicate:masterfrom
Grom1halo:feature/momentum-melee-spear

Conversation

@Grom1halo

Copy link
Copy Markdown

Описание

Добавляет копью (и любому оружию через новый переиспользуемый компонент) механику урона от скорости в духе Minecraft: пока предмет держат в руке и владелец движется быстрее порога, набегание остриём вперёд наносит цели урон, пропорциональный скорости. На достаточной скорости копьё втыкается в цель.

Как это работает

Предмет в руке лежит в контейнере руки — у него нет активного физического тела, поэтому событий коллизии он не генерирует. К тому же обычные мобы проходят друг сквозь друга (жёсткие фикстуры не пересекаются, расталкивание — отдельная «мягкая» система). Поэтому механика реализована проактивной проверкой на стороне владельца:

  • Каждый тик для предметов с MomentumMelee, которые реально держат в руке (IsHolding), берём скорость владельца в мировых координатах через GetMapLinearVelocity — она суммирует скорость по цепочке родителей, так что механика корректно работает и когда игрок движется на транспорте / стоит на движущейся платформе (запарентен к ней).
  • Если скорость ≥ minimumSpeed, ищем живых мобов в радиусе range в конусе по направлению движения (ArcDegrees) и наносим урон по формуле damage * speedDamageFactor * speed / minimumSpeed (та же логика, что в существующем DamageOnHighSpeedImpactSystem) — с покадровым эффектом (красная вспышка + звук) и кулдауном на цель.
  • При включённом embedOnHit и наличии EmbeddableProjectile успешный удар роняет предмет из руки и втыкает его в цель через существующий EmbedAttach (вытаскивается как обычное воткнутое копьё).

Формула, эффекты и вытаскивание переиспользуют уже имеющиеся системы (DamageableSystem, SharedColorFlashEffectSystem, SharedProjectileSystem), новой «магии» не вводится.

Изменения

  • Новый компонент MomentumMeleeComponent (Content.Shared/Weapons/Melee/) — переиспользуемый, настраивается в YAML.
  • Новая система MomentumMeleeSystem (shared).
  • EmbedAttach в SharedProjectileSystem сделан public, чтобы встревание можно было вызвать из других систем.
  • Компонент MomentumMelee добавлен на базовый Spear (варианты наследуют).

Медиа

Проверка

  • Стоя рядом с мобом — урона нет; на бегу остриём вперёд — Piercing-урон + вспышка + звук, растёт со скоростью.
  • Мобы сбоку/сзади не задеваются (конус спереди).
  • Копьё не в руке (в сумке/на спине) — механика молчит.
  • Обычный ближний удар и бросок копья не изменились.

🆑 Grom1halo

  • add: Копьё теперь наносит урон при столкновении на скорости (в руке) и втыкается в цель — как в Minecraft.

Добавляет переиспользуемый компонент MomentumMelee: пока предмет держат в
руке и владелец движется быстрее порога, набегание остриём вперёд наносит
цели урон, пропорциональный скорости (учитывается движение на движущейся
платформе через GetMapLinearVelocity). На достаточной скорости копьё
втыкается в цель.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Grom1halo
Grom1halo requested a review from KillanGenifer as a code owner July 8, 2026 13:42
@github-actions github-actions Bot added the C# label Jul 8, 2026
@ArZarLordOfMango

Copy link
Copy Markdown

бля а можно буковки циферки в плане баланаса? вот тоже копье телескпическое и прыжок ниана.

@Grom1halo

Copy link
Copy Markdown
Author

бля а можно буковки циферки в плане баланаса? вот тоже копье телескпическое и прыжок ниана.

Формула

урон = base × speedDamageFactor × (скорость / minimumSpeed)
Текущие значения на копье (Goob/Monolith): base = 12 Piercing, speedDamageFactor = 1.0, minimumSpeed = 4.5.
Базовый спринт в игре = 4.5 м/с (DefaultBaseSprintSpeed), базовый шаг ~2.5 м/с. То есть порог = ровно полный спринт.

Что получается по скорости

┌────────────────────────────┬──────────┬──────────────┬──────────────────────────────┐
│ Ситуация │ Скорость │ Урон момент. │ Примечание │
├────────────────────────────┼──────────┼──────────────┼──────────────────────────────┤
│ Ходьба │ ~2.5 │ 0 │ ниже порога — не срабатывает │
├────────────────────────────┼──────────┼──────────────┼──────────────────────────────┤
│ Спринт │ 4.5 │ 12 │ = один обычный удар копьём │
├────────────────────────────┼──────────┼──────────────┼──────────────────────────────┤
│ Спринт + хайпер/наркота │ ~6 │ 16 │ │
├────────────────────────────┼──────────┼──────────────┼──────────────────────────────┤
│ Квадроцикл/платформа │ ~10 │ ~27 │ ⚠ уже выше броска (24) │
├────────────────────────────┼──────────┼──────────────┼──────────────────────────────┤
│ Очень быстро (флинг/шаттл) │ 15 │ 40 │ ⚠ бесконтрольно растёт │
└────────────────────────────┴──────────┴──────────────┴──────────────────────────────┘

Для сравнения на базовом копье: обычный удар 12 (в две руки 17), бросок 24. При скорости спринта момент-урон = 12 — честно
(это бонусный удар при набегании), плюс копьё втыкается и выпадает из руки (одноразовый таран, кулдаун 1с на цель).

@oldschoolotaku

Copy link
Copy Markdown

вайбкодик

@pheenty

pheenty commented Jul 8, 2026

Copy link
Copy Markdown

This project does not accept low-effort or wholesale AI-generated contributions. Examples include, but are not limited to:

  • Any code (including yaml) generated by tools like GitHub Copilot, ChatGPT, or similar.
  • AI-created artwork, sound files, or other assets.
  • Auto-generated documentation, issue reports or pull request descriptions.

Exceptions to this are simple tools like Rider's single-line completion feature.

@NazrinNya NazrinNya left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ты даже код в неймспейс корвуха не занёс, извини братан но fraude braple 5 не справился с задачей

base.Update(frameTime);

var now = _timing.CurTime;
var query = AllEntityQuery<MomentumMeleeComponent, TransformComponent>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зачем AllEntityQuery

тут впринципе через апдейт делать это хуйня - в идеале юзай ивенты коллизии (а значит код дальше не имеет никакого смысла), ты слишком много ресурсов тратишь на хуйню.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

кароч, я понял, завтра перевайбую

Comment on lines +113 to +119
var damageScale = comp.SpeedDamageFactor * speed / comp.MinimumSpeed;
_damageable.TryChangeDamage(target.Owner, comp.Damage * damageScale, origin: holder);

if (comp.SoundHit != null && _timing.IsFirstTimePredicted)
_audio.PlayPvs(comp.SoundHit, target.Owner, AudioParams.Default.WithVariation(0.125f));

_color.RaiseEffect(Color.Red, new List<EntityUid> { target.Owner }, Filter.Pvs(target.Owner, entityManager: EntityManager));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

эмбедсистема уже всё это делает, в итоге у тебя копьё дважды дамажит цель.

обрабатывай случай с EmbeddableProjectile и обычной милишкой отдельной от друг-друга

Comment on lines +124 to +132
- type: MomentumMelee
damage:
types:
Piercing: 12
minimumSpeed: 4.5
speedDamageFactor: 1.0
embedOnHit: true
soundHit:
path: /Audio/Weapons/bladeslice.ogg

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

комменты

}

private void EmbedAttach(EntityUid uid, EntityUid target, EntityUid? user, EmbeddableProjectileComponent component)
public void EmbedAttach(EntityUid uid, EntityUid target, EntityUid? user, EmbeddableProjectileComponent component)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

комменты

_damageable.TryChangeDamage(target.Owner, comp.Damage * damageScale, origin: holder);

if (comp.SoundHit != null && _timing.IsFirstTimePredicted)
_audio.PlayPvs(comp.SoundHit, target.Owner, AudioParams.Default.WithVariation(0.125f));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlayPredicted

@LuciferEOS

Copy link
Copy Markdown

Назрин по приколу ревьювит код который даже создатель пра не видел

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants