载入中...
搜索中...
未找到
Weapon.cpp
浏览该文件的文档.
1#include "weapon/Weapon.h"
2
3#include "common/Value.h"
8
9#include <squirrel.h>
10#include <simplesquirrel/simplesquirrel.hpp>
11
12#include <algorithm>
13#include <cmath>
14#include <memory>
15
16namespace eve::weapon {
17
19
20namespace {
21
22template <typename T>
23T* resolve(const ecs::EntityHandle& h) {
24 return static_cast<T*>(ecs::try_get(h));
25}
26
27template <typename T>
28void destroyHandles(std::vector<ecs::EntityHandle>& hs) {
29 for (auto& h : hs) {
30 if (ecs::Entity* e = ecs::try_get(h)) ecs::DestroyEntity(e);
31 }
32 hs.clear();
33}
34
35template <typename T>
36void registerCppEntityClassForScript(const ssq::Class& cls) {
37 eve::registerCppEntityView(cls, [](ssq::Array& out) {
38 HSQUIRRELVM vm = out.getHandle();
39 sq_pushobject(vm, out.getRaw());
40 ecs::Table* table = ecs::current();
41 if (table == nullptr) {
42 sq_pop(vm, 1);
43 return;
44 }
45 ecs::IComponentManager& cm = table->getOrCreateManager<T>();
46 auto* reg = cm.getOrCreateRegistryComponentBuffer<T>();
47 std::vector<ecs::IComponentBuffer*> stack;
48 stack.push_back(reg);
49 while (!stack.empty()) {
50 ecs::IComponentBuffer* buf = stack.back();
51 stack.pop_back();
52 auto* r = dynamic_cast<ecs::IRegistryComponentBuffer*>(buf);
53 if (r != nullptr) {
54 for (uint32_t i = 0; i < r->entity_count(); ++i) {
55 ecs::Entity* ent = r->entity_at(i);
56 if (ent != nullptr && ecs::is_entity_visible(ent)) {
57 ssq::detail::pushByPtr<T>(vm, static_cast<T*>(ent));
58 sq_arrayappend(vm, -2);
59 }
60 }
61 }
62 if (buf->children != nullptr) stack.push_back(buf->children);
63 if (buf->next != nullptr) stack.push_back(buf->next);
64 }
65 sq_pop(vm, 1);
66 });
67}
68
69} // namespace
70
71const char* fireModeName(FireMode mode) {
72 switch (mode) {
73 case FireMode::Single: return "single";
74 case FireMode::Burst: return "burst";
75 case FireMode::Auto: return "auto";
76 }
77 return "single";
78}
79
80FireMode fireModeFromName(const std::string& name) {
81 if (name == "burst") return FireMode::Burst;
82 if (name == "auto") return FireMode::Auto;
83 return FireMode::Single;
84}
85
87 switch (kind) {
88 case WeaponKind::Melee: return "melee";
89 case WeaponKind::Ranged: return "ranged";
90 case WeaponKind::Magic: return "magic";
91 case WeaponKind::Missile: return "missile";
92 case WeaponKind::Custom: return "custom";
93 }
94 return "ranged";
95}
96
97WeaponKind weaponKindFromName(const std::string& name) {
98 if (name == "melee") return WeaponKind::Melee;
99 if (name == "magic") return WeaponKind::Magic;
100 if (name == "missile") return WeaponKind::Missile;
101 if (name == "custom") return WeaponKind::Custom;
102 return WeaponKind::Ranged;
103}
104
105const char* attackStageName(AttackStage stage) {
106 switch (stage) {
107 case AttackStage::Idle: return "idle";
108 case AttackStage::Windup: return "windup";
109 case AttackStage::Active: return "active";
110 case AttackStage::Recover: return "recover";
111 }
112 return "idle";
113}
114
116 switch (type) {
117 case WeaponEventType::Fire: return "fire";
118 case WeaponEventType::ReloadStart: return "reload_start";
119 case WeaponEventType::ReloadEnd: return "reload_end";
120 case WeaponEventType::Empty: return "empty";
121 case WeaponEventType::WindupStart: return "windup_start";
122 case WeaponEventType::AttackEnd: return "attack_end";
123 case WeaponEventType::AimIn: return "aim_in";
124 case WeaponEventType::AimOut: return "aim_out";
125 }
126 return "unknown";
127}
128
130 WeaponEntity* w = WeaponEntity::create();
131 w->identity();
132 w->definition();
133 w->definitionBinding();
134 w->state();
135 w->aim();
136 return w;
137}
138
140 WeaponMountEntity* m = WeaponMountEntity::create();
141 m->identity();
142 m->limits();
143 m->state();
144 return m;
145}
146
148 WeaponRigEntity* r = WeaponRigEntity::create();
149 r->identity();
150 r->held();
151 r->state();
152 return r;
153}
154
156 AmmoPoolEntity* p = AmmoPoolEntity::create();
157 p->identity();
158 p->state();
159 return p;
160}
161
162// ---------------------------------------------------------------------------
163// 模块生命周期
164// ---------------------------------------------------------------------------
165
167 WeaponSystem::setEventSink([this](const WeaponEvent& e) { events_.push_back(e); });
168}
169
171 destroyHandles<WeaponEntity>(weapons_);
172 destroyHandles<WeaponMountEntity>(mounts_);
173 destroyHandles<WeaponRigEntity>(rigs_);
174 destroyHandles<AmmoPoolEntity>(pools_);
176}
177
178// ---------------------------------------------------------------------------
179// 武器模板
180// ---------------------------------------------------------------------------
181
182int Weapon::registerWeaponsFromJson(const std::string& json) {
183 auto canonical = eve::Value::fromJson(json);
184 if (!canonical) {
185 canonical.ignore("weapon definition input could not be parsed as canonical Value");
186 return 0;
187 }
188
189 int n = 0;
190 const auto publish = [this, &n](const eve::Value& value) {
191 const auto* object = value.getIf<eve::Value::Object>();
192 if (object == nullptr) return;
193 const auto id = object->find("id");
194 const auto* name = id == object->end() ? nullptr : id->second.getIf<std::string>();
195 if (name == nullptr || name->empty()) return;
196
197 auto encoded = value.toJson();
198 if (!encoded) {
199 encoded.ignore("weapon definition value could not be serialized canonically");
200 return;
201 }
203 source.type = "weapon";
204 source.id = *name;
205 source.version = eve::SchemaVersion(1);
206 source.json = encoded.value();
207 auto typed = parseWeaponDefinition(source);
208 if (!typed) {
209 typed.ignore("weapon definition failed typed projection validation");
210 return;
211 }
212
213 auto current = definitionRegistry_.resolve("weapon", *name);
214 const bool exists = current.ok();
215 if (!exists && current.status().code() != eve::StatusCode::NotFound) return;
216 auto stored = exists ? definitionRegistry_.replace("weapon", *name, 1, source.json)
217 : definitionRegistry_.insert("weapon", *name, 1, source.json);
218 if (stored) {
219 ++n;
220 } else {
221 stored.ignore("weapon definition registry rejected canonical registration");
222 }
223 };
224 const eve::Value& root = canonical.value();
225 if (const auto* array = root.getIf<eve::Value::Array>()) {
226 for (const auto& value : *array) publish(value);
227 } else {
228 publish(root);
229 }
230 return n;
231}
232
234 while (definitionRegistry_.countType("weapon") > 0) {
235 const auto* definition = definitionRegistry_.atType("weapon", 0);
236 if (definition == nullptr) break;
237 auto result = definitionRegistry_.remove("weapon", definition->id);
238 if (!result) result.ignore("weapon definition registry removal failed");
239 }
240}
241
242int Weapon::getWeaponDefinitionCount() { return definitionRegistry_.countType("weapon"); }
243
244bool Weapon::hasWeaponDefinition(const std::string& id) { return definitionRegistry_.resolve("weapon", id).ok(); }
245
246std::string Weapon::getWeaponDefinitionLogic(const std::string& id) {
247 auto definition = findDef(id);
248 if (!definition) {
249 definition.ignore("legacy scalar query returns empty for an unknown weapon definition");
250 return {};
251 }
252 return definition.value().logic;
253}
254
255float Weapon::getWeaponDefinitionDamage(const std::string& id) {
256 auto definition = findDef(id);
257 if (!definition) {
258 definition.ignore("legacy scalar query returns zero for an unknown weapon definition");
259 return 0.f;
260 }
261 return definition.value().damage;
262}
263
264float Weapon::getWeaponDefinitionRange(const std::string& id) {
265 auto definition = findDef(id);
266 if (!definition) {
267 definition.ignore("legacy scalar query returns zero for an unknown weapon definition");
268 return 0.f;
269 }
270 return definition.value().range;
271}
272
274
276
277eve::Result<WeaponDefinition> Weapon::findDef(const std::string& id) const {
278 auto resolved = definitionRegistry_.resolve("weapon", id);
279 if (!resolved) return eve::Result<WeaponDefinition>::failure(resolved.status());
280 return parseWeaponDefinition(resolved.value().get());
281}
282
283// ---------------------------------------------------------------------------
284// 工厂
285// ---------------------------------------------------------------------------
286
287WeaponEntity* Weapon::newWeapon(const std::string& defId) {
288 auto definition = findDef(defId);
289 if (!definition) {
290 definition.ignore("legacy nullable factory returns null for an unknown weapon definition");
291 return nullptr;
292 }
293 WeaponDefinition d = std::move(definition).takeValue();
294
296 w->identity()->id = defId + "#" + std::to_string(nextInstance_++);
297 w->identity()->defId = defId;
298 w->definition()->owned = std::make_shared<const WeaponDefinition>(std::move(d));
299 w->definition()->def = w->definition()->owned.get();
300 w->state()->stages = &w->definition()->def->stages;
301 const WeaponDefinition& storedDefinition = *w->definition()->def;
302 w->state()->selector = storedDefinition.fireMode;
303 w->state()->currentSpread = storedDefinition.spreadMin;
304
305 // 运行时资源:热武器 ammo 映射到弹匣/备用;其余形态从模板 resource 拷贝。
306 Resource& r = w->state()->resource;
307 r.kind = storedDefinition.resource.kind;
308 r.max = storedDefinition.resource.max;
309 r.regen = storedDefinition.resource.regen;
310 r.cost = storedDefinition.resource.cost;
311 r.infinite = storedDefinition.resource.infinite;
312 if (storedDefinition.kind == WeaponKind::Ranged) {
313 r.kind = ResourceKind::Ammo;
314 r.max = static_cast<float>(storedDefinition.magSize);
315 r.value = static_cast<float>(storedDefinition.magSize);
316 r.cost = 1.f;
317 r.reserve = storedDefinition.reserveSize < 0 ? 0 : storedDefinition.reserveSize;
318 r.infinite = storedDefinition.reserveSize < 0;
319 } else {
320 r.value = r.infinite ? 0.f : r.max;
321 }
322
323 weapons_.push_back(ecs::handle_of(w));
324 return w;
325}
326
327WeaponMountEntity* Weapon::newMount(const std::string& id, const std::string& type) {
329 m->identity()->id = id.empty() ? ("mount#" + std::to_string(nextInstance_++)) : id;
330 m->identity()->type = type;
331 mounts_.push_back(ecs::handle_of(m));
332 return m;
333}
334
335WeaponRigEntity* Weapon::newRig(const std::string& id, const std::string& wield) {
337 r->identity()->id = id.empty() ? ("rig#" + std::to_string(nextInstance_++)) : id;
338 r->identity()->wield = wield;
339 rigs_.push_back(ecs::handle_of(r));
340 return r;
341}
342
343// ---------------------------------------------------------------------------
344// 手持位操作
345// ---------------------------------------------------------------------------
346
348 if (rig == nullptr || w == nullptr) return false;
349 rig->state()->weapon = w;
350 return true;
351}
352
353WeaponEntity* Weapon::rigGetWeapon(WeaponRigEntity* rig) { return rig == nullptr ? nullptr : rig->state()->weapon; }
354
355void Weapon::rigSetPose(WeaponRigEntity* rig, float px, float py, float pz, float rx, float ry, float rz) {
356 if (rig == nullptr) return;
357 rig->held()->posX = px;
358 rig->held()->posY = py;
359 rig->held()->posZ = pz;
360 rig->held()->rotX = rx;
361 rig->held()->rotY = ry;
362 rig->held()->rotZ = rz;
363}
364
365// ---------------------------------------------------------------------------
366// 共享弹药池
367// ---------------------------------------------------------------------------
368
369AmmoPoolEntity* Weapon::newAmmoPool(const std::string& id, const std::string& ammoType, int max) {
371 p->identity()->id = id.empty() ? ("ammo#" + std::to_string(nextInstance_++)) : id;
372 p->identity()->ammoType = ammoType;
373 p->state()->max = max;
374 pools_.push_back(ecs::handle_of(p));
375 return p;
376}
377
379 if (pool == nullptr || n <= 0) return;
380 if (pool->state()->max < 0) {
381 pool->state()->count += n;
382 } else {
383 pool->state()->count = std::min(pool->state()->max, pool->state()->count + n);
384 }
385}
386
387int Weapon::ammoPoolGetCount(AmmoPoolEntity* pool) { return pool == nullptr ? 0 : pool->state()->count; }
388
390 if (w == nullptr || pool == nullptr) return false;
391 w->state()->ammoPool = pool;
392 return true;
393}
394
396 if (w != nullptr) w->state()->ammoPool = nullptr;
397}
398
399AmmoPoolEntity* Weapon::getAmmoPool(WeaponEntity* w) { return w == nullptr ? nullptr : w->state()->ammoPool; }
400
401// ---------------------------------------------------------------------------
402// 挂点操作
403// ---------------------------------------------------------------------------
404
406 if (m == nullptr || w == nullptr || m->state()->destroyed) return false;
407 m->state()->weapon = w;
408 return true;
409}
410
411WeaponEntity* Weapon::mountGetWeapon(WeaponMountEntity* m) { return m == nullptr ? nullptr : m->state()->weapon; }
412
413void Weapon::mountSetLimits(WeaponMountEntity* m, float yawMin, float yawMax, float pitchMin, float pitchMax,
414 float rotSpeed, float firingArc) {
415 if (m == nullptr) return;
416 m->limits()->yawMin = yawMin;
417 m->limits()->yawMax = yawMax;
418 m->limits()->pitchMin = pitchMin;
419 m->limits()->pitchMax = pitchMax;
420 m->limits()->rotSpeed = rotSpeed;
421 m->limits()->firingArc = firingArc;
422}
423
425 if (m == nullptr || m->state()->destroyed) return;
426 const float cyaw = std::clamp(yaw, m->limits()->yawMin, m->limits()->yawMax);
427 const float cpitch = std::clamp(pitch, m->limits()->pitchMin, m->limits()->pitchMax);
428
429 if (WeaponEntity* w = m->state()->weapon) {
430 w->aim()->desiredYaw = cyaw;
431 w->aim()->desiredPitch = cpitch;
432 w->aim()->turnSpeed = m->limits()->rotSpeed;
433 } else {
434 m->state()->yaw = cyaw;
435 m->state()->pitch = cpitch;
436 }
437}
438
440 if (m == nullptr) return;
441 m->state()->destroyed = true;
442}
443
444// ---------------------------------------------------------------------------
445// 武器操作
446// ---------------------------------------------------------------------------
447
448bool Weapon::fire(WeaponEntity* w, const FireRequest& req) { return w != nullptr && WeaponSystem::tryFire(*w, req); }
449
450bool Weapon::fireAt(WeaponEntity* w, float x, float y, float z, int shooterId) {
451 if (w == nullptr) return false;
452 AttackRequest req;
453 req.targetX = x;
454 req.targetY = y;
455 req.targetZ = z;
456 req.hasTarget = true;
457 req.shooterId = shooterId;
458 return WeaponSystem::tryFire(*w, req);
459}
460
461bool Weapon::attack(WeaponEntity* w, float yaw, float pitch, int shooterId) {
462 if (w == nullptr) return false;
463 AttackRequest req;
464 req.yaw = yaw;
465 req.pitch = pitch;
466 req.shooterId = shooterId;
467 if (const WeaponDefinition* d = w->definition()->def) {
468 req.arcAngle = d->arc;
469 req.aoeRadius = d->projectile.aoe;
470 }
471 return WeaponSystem::tryFire(*w, req);
472}
473
474bool Weapon::canFire(WeaponEntity* w) { return w != nullptr && WeaponSystem::canFire(*w); }
475
477 if (w != nullptr) WeaponSystem::startReload(*w);
478}
479
483
484void Weapon::setAim(WeaponEntity* w, float yaw, float pitch) {
485 if (w == nullptr) return;
486 w->aim()->desiredYaw = yaw;
487 w->aim()->desiredPitch = pitch;
488}
489
490bool Weapon::setFireMode(WeaponEntity* w, const std::string& mode) {
491 if (w == nullptr) return false;
492 const WeaponDefinition* d = w->definition()->def;
493 if (d == nullptr) return false;
494 const FireMode m = fireModeFromName(mode);
495 // 无可选模式 = 固定 fireMode,不允许切换。
496 if (d->selectableModes.empty()) return m == d->fireMode;
497 for (const FireMode sm : d->selectableModes)
498 if (sm == m) {
499 w->state()->selector = m;
500 return true;
501 }
502 return false;
503}
504
506 return w != nullptr ? fireModeName(w->state()->selector) : std::string{};
507}
508
510 const WeaponDefinition* d = w != nullptr ? w->definition()->def : nullptr;
511 return d != nullptr ? static_cast<int>(d->selectableModes.size()) : 0;
512}
513
515 const WeaponDefinition* d = w != nullptr ? w->definition()->def : nullptr;
516 if (d == nullptr || index < 0 || index >= static_cast<int>(d->selectableModes.size())) return std::string{};
517 return fireModeName(d->selectableModes[static_cast<size_t>(index)]);
518}
519
520bool Weapon::setAiming(WeaponEntity* w, bool aiming) {
521 if (w == nullptr || w->state()->aiming == aiming) return false;
522 w->state()->aiming = aiming;
523 WeaponEvent e;
525 e.weaponId = w->identity()->id;
526 if (const WeaponDefinition* d = w->definition()->def) e.defId = d->id;
528 return true;
529}
530
531bool Weapon::isAiming(WeaponEntity* w) { return w != nullptr && w->state()->aiming; }
532
534 const WeaponDefinition* d = w != nullptr ? w->definition()->def : nullptr;
535 return d != nullptr ? d->zoomFov : 0.f;
536}
537
538float Weapon::getSpread(WeaponEntity* w) { return w != nullptr ? w->state()->currentSpread : 0.f; }
539
540float Weapon::getRecoilPitch(WeaponEntity* w) { return w != nullptr ? w->state()->recoilPitch : 0.f; }
541
542float Weapon::getRecoilYaw(WeaponEntity* w) { return w != nullptr ? w->state()->recoilYaw : 0.f; }
543
544void Weapon::update(float dt) {
545 for (const ecs::EntityHandle& h : weapons_) {
546 if (WeaponEntity* w = resolve<WeaponEntity>(h)) WeaponSystem::update(*w, dt);
547 }
548 for (const ecs::EntityHandle& h : mounts_) {
549 WeaponMountEntity* m = resolve<WeaponMountEntity>(h);
550 if (m == nullptr || m->state()->destroyed) continue;
551 if (WeaponEntity* w = m->state()->weapon) {
552 m->state()->yaw = w->aim()->yaw;
553 m->state()->pitch = w->aim()->pitch;
554 }
555 }
556}
557
558// ---------------------------------------------------------------------------
559// 事件队列
560// ---------------------------------------------------------------------------
561
562void Weapon::clearEvents() { events_.clear(); }
563
564int Weapon::getEventCount() const { return static_cast<int>(events_.size()); }
565
566std::string Weapon::getEventType(int index) const {
567 return (index >= 0 && index < getEventCount()) ? weaponEventTypeName(events_[index].type) : std::string{};
568}
569
570std::string Weapon::getEventWeaponId(int index) const {
571 return (index >= 0 && index < getEventCount()) ? events_[index].weaponId : std::string{};
572}
573
574std::string Weapon::getEventDefId(int index) const {
575 return (index >= 0 && index < getEventCount()) ? events_[index].defId : std::string{};
576}
577
578std::string Weapon::getEventMountId(int index) const {
579 return (index >= 0 && index < getEventCount()) ? events_[index].mountId : std::string{};
580}
581
583 return (index >= 0 && index < getEventCount()) ? events_[index].ammoLeft : 0;
584}
585
586float Weapon::getEventArc(int index) const {
587 return (index >= 0 && index < getEventCount()) ? events_[index].arc : 0.f;
588}
589
590float Weapon::getEventAoe(int index) const {
591 return (index >= 0 && index < getEventCount()) ? events_[index].aoe : 0.f;
592}
593
595 return (index >= 0 && index < getEventCount()) ? events_[index].spread : 0.f;
596}
597
599 return (index >= 0 && index < getEventCount()) ? events_[index].pellets : 0;
600}
601
603 return (index >= 0 && index < getEventCount()) ? events_[index].recoilPitch : 0.f;
604}
605
607 return (index >= 0 && index < getEventCount()) ? events_[index].recoilYaw : 0.f;
608}
609
610std::string Weapon::getEventDamageType(int index) const {
611 return (index >= 0 && index < getEventCount()) ? events_[index].damageType : std::string{};
612}
613
614std::string Weapon::getEventElement(int index) const {
615 return (index >= 0 && index < getEventCount()) ? events_[index].element : std::string{};
616}
617
618std::string Weapon::getStage(WeaponEntity* w) const {
619 return w != nullptr ? attackStageName(w->state()->stage) : std::string{};
620}
621
622float Weapon::getResourceValue(WeaponEntity* w) const { return w != nullptr ? w->state()->resource.value : 0.f; }
623
624// ---------------------------------------------------------------------------
625// 脚本绑定
626// ---------------------------------------------------------------------------
627
628void Weapon::expose(ssq::Table& table) {
629 auto cls = table.addClass(name, Weapon::create, false);
630 expose(cls);
632
633 auto wCls = table.addClass<WeaponEntity>(
634 "WeaponEntity", std::function<WeaponEntity*()>([]() -> WeaponEntity* { return nullptr; }), false);
635 registerCppEntityClassForScript<WeaponEntity>(wCls);
636 wCls.addFunc("getId", [](WeaponEntity* w) -> std::string { return w ? w->identity()->id : std::string{}; });
637 wCls.addFunc("getDefId", [](WeaponEntity* w) -> std::string { return w ? w->identity()->defId : std::string{}; });
638 wCls.addFunc("getOwnerId", [](WeaponEntity* w) -> int { return w ? w->identity()->ownerId : 0; });
639 wCls.addFunc("setOwnerId", [](WeaponEntity* w, int v) {
640 if (w) w->identity()->ownerId = v;
641 });
642 wCls.addFunc("getMagAmmo", [](WeaponEntity* w) -> int {
643 return w ? static_cast<int>(w->state()->resource.value) : 0;
644 });
645 wCls.addFunc("getReserveAmmo", [](WeaponEntity* w) -> int { return w ? w->state()->resource.reserve : 0; });
646 wCls.addFunc("getResourceValue", [](WeaponEntity* w) -> float { return w ? w->state()->resource.value : 0.f; });
647 wCls.addFunc("getSpread", [](WeaponEntity* w) -> float { return w ? w->state()->currentSpread : 0.f; });
648 wCls.addFunc("getRecoilPitch", [](WeaponEntity* w) -> float { return w ? w->state()->recoilPitch : 0.f; });
649 wCls.addFunc("getRecoilYaw", [](WeaponEntity* w) -> float { return w ? w->state()->recoilYaw : 0.f; });
650 wCls.addFunc("getFireMode", [](WeaponEntity* w) -> std::string {
651 return w ? fireModeName(w->state()->selector) : std::string{};
652 });
653 wCls.addFunc("setFireMode", [](WeaponEntity* w, const std::string& mode) -> bool {
654 if (w == nullptr) return false;
655 const WeaponDefinition* d = w->definition()->def;
656 if (d == nullptr) return false;
657 const FireMode m = fireModeFromName(mode);
658 if (d->selectableModes.empty()) return m == d->fireMode;
659 for (const FireMode sm : d->selectableModes)
660 if (sm == m) {
661 w->state()->selector = m;
662 return true;
663 }
664 return false;
665 });
666 wCls.addFunc("isAiming", [](WeaponEntity* w) -> bool { return w != nullptr && w->state()->aiming; });
667 wCls.addFunc("setAiming", [](WeaponEntity* w, bool aiming) -> bool {
668 if (w == nullptr || w->state()->aiming == aiming) return false;
669 w->state()->aiming = aiming;
670 WeaponEvent e;
672 e.weaponId = w->identity()->id;
673 if (const WeaponDefinition* d = w->definition()->def) e.defId = d->id;
675 return true;
676 });
677 wCls.addFunc("getZoomFov", [](WeaponEntity* w) -> float {
678 const WeaponDefinition* d = w != nullptr ? w->definition()->def : nullptr;
679 return d != nullptr ? d->zoomFov : 0.f;
680 });
681 wCls.addFunc("getAmmoPool",
682 [](WeaponEntity* w) -> AmmoPoolEntity* { return w != nullptr ? w->state()->ammoPool : nullptr; });
683 wCls.addFunc("getStage", [](WeaponEntity* w) -> std::string {
684 return w ? attackStageName(w->state()->stage) : std::string{};
685 });
686 wCls.addFunc("isReloading", [](WeaponEntity* w) -> bool { return w != nullptr && w->state()->resource.reloading; });
687 wCls.addFunc("getCooldown", [](WeaponEntity* w) -> float { return w ? w->state()->cooldown : 0.f; });
688 wCls.addFunc("getYaw", [](WeaponEntity* w) -> float { return w ? w->aim()->yaw : 0.f; });
689 wCls.addFunc("getPitch", [](WeaponEntity* w) -> float { return w ? w->aim()->pitch : 0.f; });
690 wCls.addFunc("canFire", [](WeaponEntity* w) -> bool { return w != nullptr && WeaponSystem::canFire(*w); });
691 wCls.addFunc("fireAt", [](WeaponEntity* w, float x, float y, float z, int shooterId) -> bool {
692 if (w == nullptr) return false;
693 AttackRequest req;
694 req.targetX = x;
695 req.targetY = y;
696 req.targetZ = z;
697 req.hasTarget = true;
698 req.shooterId = shooterId;
699 return WeaponSystem::tryFire(*w, req);
700 });
701 wCls.addFunc("attack", [](WeaponEntity* w, float yaw, float pitch, int shooterId) -> bool {
702 if (w == nullptr) return false;
703 AttackRequest req;
704 req.yaw = yaw;
705 req.pitch = pitch;
706 req.shooterId = shooterId;
707 if (const WeaponDefinition* d = w->definition()->def) {
708 req.arcAngle = d->arc;
709 req.aoeRadius = d->projectile.aoe;
710 }
711 return WeaponSystem::tryFire(*w, req);
712 });
713 wCls.addFunc("startReload", [](WeaponEntity* w) {
715 });
716 wCls.addFunc("cancelReload", [](WeaponEntity* w) {
718 });
719 wCls.addFunc("setAim", [](WeaponEntity* w, float yaw, float pitch) {
720 if (w) {
721 w->aim()->desiredYaw = yaw;
722 w->aim()->desiredPitch = pitch;
723 }
724 });
725
726 auto mCls = table.addClass<WeaponMountEntity>(
727 "WeaponMountEntity", std::function<WeaponMountEntity*()>([]() -> WeaponMountEntity* { return nullptr; }),
728 false);
729 registerCppEntityClassForScript<WeaponMountEntity>(mCls);
730 mCls.addFunc("getId", [](WeaponMountEntity* m) -> std::string { return m ? m->identity()->id : std::string{}; });
731 mCls.addFunc("getType",
732 [](WeaponMountEntity* m) -> std::string { return m ? m->identity()->type : std::string{}; });
733 mCls.addFunc("getNodePath",
734 [](WeaponMountEntity* m) -> std::string { return m ? m->identity()->nodePath : std::string{}; });
735 mCls.addFunc("setNodePath", [](WeaponMountEntity* m, const std::string& v) {
736 if (m) m->identity()->nodePath = v;
737 });
738 mCls.addFunc("getWeapon", [](WeaponMountEntity* m) -> WeaponEntity* { return m ? m->state()->weapon : nullptr; });
739 mCls.addFunc("getYaw", [](WeaponMountEntity* m) -> float { return m ? m->state()->yaw : 0.f; });
740 mCls.addFunc("getPitch", [](WeaponMountEntity* m) -> float { return m ? m->state()->pitch : 0.f; });
741 mCls.addFunc("isDestroyed", [](WeaponMountEntity* m) -> bool { return m != nullptr && m->state()->destroyed; });
742 mCls.addFunc("destroy", [](WeaponMountEntity* m) {
743 if (m) m->state()->destroyed = true;
744 });
745 mCls.addFunc("aimAt", [](WeaponMountEntity* m, float yaw, float pitch) {
746 if (m == nullptr || m->state()->destroyed) return;
747 const float cyaw = std::clamp(yaw, m->limits()->yawMin, m->limits()->yawMax);
748 const float cpitch = std::clamp(pitch, m->limits()->pitchMin, m->limits()->pitchMax);
749 if (WeaponEntity* w = m->state()->weapon) {
750 w->aim()->desiredYaw = cyaw;
751 w->aim()->desiredPitch = cpitch;
752 w->aim()->turnSpeed = m->limits()->rotSpeed;
753 } else {
754 m->state()->yaw = cyaw;
755 m->state()->pitch = cpitch;
756 }
757 });
758
759 auto rCls = table.addClass<WeaponRigEntity>(
760 "WeaponRigEntity", std::function<WeaponRigEntity*()>([]() -> WeaponRigEntity* { return nullptr; }), false);
761 registerCppEntityClassForScript<WeaponRigEntity>(rCls);
762 rCls.addFunc("getId", [](WeaponRigEntity* r) -> std::string { return r ? r->identity()->id : std::string{}; });
763 rCls.addFunc("getWield",
764 [](WeaponRigEntity* r) -> std::string { return r ? r->identity()->wield : std::string{}; });
765 rCls.addFunc("getNodePath",
766 [](WeaponRigEntity* r) -> std::string { return r ? r->identity()->nodePath : std::string{}; });
767 rCls.addFunc("setNodePath", [](WeaponRigEntity* r, const std::string& v) {
768 if (r) r->identity()->nodePath = v;
769 });
770 rCls.addFunc("getWeapon", [](WeaponRigEntity* r) -> WeaponEntity* { return r ? r->state()->weapon : nullptr; });
771 rCls.addFunc("attachWeapon", [](WeaponRigEntity* r, WeaponEntity* w) -> bool {
772 if (r == nullptr || w == nullptr) return false;
773 r->state()->weapon = w;
774 return true;
775 });
776 rCls.addFunc("setPose", [](WeaponRigEntity* r, float px, float py, float pz, float rx, float ry, float rz) {
777 if (r == nullptr) return;
778 r->held()->posX = px;
779 r->held()->posY = py;
780 r->held()->posZ = pz;
781 r->held()->rotX = rx;
782 r->held()->rotY = ry;
783 r->held()->rotZ = rz;
784 });
785
786 auto pCls = table.addClass<AmmoPoolEntity>(
787 "AmmoPoolEntity", std::function<AmmoPoolEntity*()>([]() -> AmmoPoolEntity* { return nullptr; }), false);
788 registerCppEntityClassForScript<AmmoPoolEntity>(pCls);
789 pCls.addFunc("getId", [](AmmoPoolEntity* p) -> std::string { return p ? p->identity()->id : std::string{}; });
790 pCls.addFunc("getAmmoType",
791 [](AmmoPoolEntity* p) -> std::string { return p ? p->identity()->ammoType : std::string{}; });
792 pCls.addFunc("getCount", [](AmmoPoolEntity* p) -> int { return p ? p->state()->count : 0; });
793 pCls.addFunc("addAmmo", [](AmmoPoolEntity* p, int n) {
794 if (p == nullptr || n <= 0) return;
795 if (p->state()->max < 0) {
796 p->state()->count += n;
797 } else {
798 p->state()->count = std::min(p->state()->max, p->state()->count + n);
799 }
800 });
801 pCls.addFunc("setCount", [](AmmoPoolEntity* p, int n) {
802 if (p != nullptr) p->state()->count = n;
803 });
804}
805
806void Weapon::expose(ssq::Class& cls) {
807 cls.addFunc("registerWeaponsFromJson", &Weapon::registerWeaponsFromJson);
808 cls.addFunc("clearWeaponDefinitions", &Weapon::clearWeaponDefinitions);
809 cls.addFunc("getWeaponDefinitionCount", &Weapon::getWeaponDefinitionCount);
810 cls.addFunc("hasWeaponDefinition", &Weapon::hasWeaponDefinition);
811 cls.addFunc("getWeaponDefinitionLogic", &Weapon::getWeaponDefinitionLogic);
812 cls.addFunc("getWeaponDefinitionDamage", &Weapon::getWeaponDefinitionDamage);
813 cls.addFunc("getWeaponDefinitionRange", &Weapon::getWeaponDefinitionRange);
814 cls.addFunc("getLogicCount", [](Weapon*) -> int { return WeaponSystem::logicCount(); });
815 cls.addFunc("newWeapon", &Weapon::newWeapon);
816 cls.addFunc("newMount", &Weapon::newMount);
817 cls.addFunc("newRig", &Weapon::newRig);
818 cls.addFunc("rigAttachWeapon", &Weapon::rigAttachWeapon);
819 cls.addFunc("rigGetWeapon", &Weapon::rigGetWeapon);
820 cls.addFunc("rigSetPose", &Weapon::rigSetPose);
821 cls.addFunc("newAmmoPool", &Weapon::newAmmoPool);
822 cls.addFunc("ammoPoolAdd", &Weapon::ammoPoolAdd);
823 cls.addFunc("ammoPoolGetCount", &Weapon::ammoPoolGetCount);
824 cls.addFunc("bindAmmoPool", &Weapon::bindAmmoPool);
825 cls.addFunc("unbindAmmoPool", &Weapon::unbindAmmoPool);
826 cls.addFunc("getAmmoPool", &Weapon::getAmmoPool);
827 cls.addFunc("setFireMode", &Weapon::setFireMode);
828 cls.addFunc("getFireMode", &Weapon::getFireMode);
829 cls.addFunc("getSelectableModeCount", &Weapon::getSelectableModeCount);
830 cls.addFunc("getSelectableMode", &Weapon::getSelectableMode);
831 cls.addFunc("setAiming", &Weapon::setAiming);
832 cls.addFunc("isAiming", &Weapon::isAiming);
833 cls.addFunc("getZoomFov", &Weapon::getZoomFov);
834 cls.addFunc("getSpread", &Weapon::getSpread);
835 cls.addFunc("getRecoilPitch", &Weapon::getRecoilPitch);
836 cls.addFunc("getRecoilYaw", &Weapon::getRecoilYaw);
837 cls.addFunc("mountAttachWeapon", &Weapon::mountAttachWeapon);
838 cls.addFunc("mountGetWeapon", &Weapon::mountGetWeapon);
839 cls.addFunc("mountSetLimits", &Weapon::mountSetLimits);
840 cls.addFunc("mountAimAt", &Weapon::mountAimAt);
841 cls.addFunc("mountDestroy", &Weapon::mountDestroy);
842 cls.addFunc("fireAt", &Weapon::fireAt);
843 cls.addFunc("attack", &Weapon::attack);
844 cls.addFunc("canFire", &Weapon::canFire);
845 cls.addFunc("startReload", &Weapon::startReload);
846 cls.addFunc("cancelReload", &Weapon::cancelReload);
847 cls.addFunc("setAim", &Weapon::setAim);
848 cls.addFunc("update", &Weapon::update);
849 cls.addFunc("clearEvents", &Weapon::clearEvents);
850 cls.addFunc("getEventCount", &Weapon::getEventCount);
851 cls.addFunc("getEventType", &Weapon::getEventType);
852 cls.addFunc("getEventWeaponId", &Weapon::getEventWeaponId);
853 cls.addFunc("getEventDefId", &Weapon::getEventDefId);
854 cls.addFunc("getEventMountId", &Weapon::getEventMountId);
855 cls.addFunc("getEventAmmoLeft", &Weapon::getEventAmmoLeft);
856 cls.addFunc("getEventArc", &Weapon::getEventArc);
857 cls.addFunc("getEventAoe", &Weapon::getEventAoe);
858 cls.addFunc("getEventSpread", &Weapon::getEventSpread);
859 cls.addFunc("getEventPellets", &Weapon::getEventPellets);
860 cls.addFunc("getEventRecoilPitch", &Weapon::getEventRecoilPitch);
861 cls.addFunc("getEventRecoilYaw", &Weapon::getEventRecoilYaw);
862 cls.addFunc("getEventDamageType", &Weapon::getEventDamageType);
863 cls.addFunc("getEventElement", &Weapon::getEventElement);
864 cls.addFunc("getStage", &Weapon::getStage);
865 cls.addFunc("getResourceValue", &Weapon::getResourceValue);
867}
868
869} // namespace eve::weapon
double value
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
int root
Definition AnimSmr.cpp:119
float py
float pz
struct SQVM * HSQUIRRELVM
glm::vec4 p[6]
HSQUIRRELVM vm
Definition ECS.cpp:20
HSQOBJECT cls
Definition ECS.cpp:21
std::vector< std::uint8_t > stored
Definition Evpack.cpp:171
glm::vec3 n
Definition Grass.cpp:63
double r
float v
int h
std::vector< Colorf > px
TokenKind kind
bool exists
std::string name
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:26
std::string id
Definition PlayHost.cpp:108
float d
double current
std::string string
uint32_t index
const UnitySourceAsset & source
Owning, renderer-independent dynamic values.
float m[16]
Selective canonical mana/stamina adapter for weapons.
Strongly typed Weapon definition/runtime adapter.
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
static Result< Value > fromJson(std::string_view json)
Parse one strict JSON value into an owning Value.
Definition Value.cpp:57
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
eve::ResultRef< const Definition > resolve(const std::string &type, const std::string &id) const
Resolves a definition through the common registry API.
eve::Result< DefinitionHandle > insert(const std::string &type, const std::string &id, int version, const std::string &json)
Inserts a definition using the common generation-qualified registry.
eve::Result< DefinitionHandle > replace(const std::string &type, const std::string &id, int version, const std::string &json)
Replaces a live definition and invalidates its previous handle.
eve::Result< DefinitionHandle > remove(const std::string &type, const std::string &id)
Removes a definition and returns the retained tombstone handle.
int countType(const std::string &type) const
Returns the number of definitions registered for a type.
const Definition * atType(const std::string &type, int index) const
Returns a definition by id order within one type, or nullptr.
共享弹药池实体:多把武器共用的备用弹药,装填时从池中取。
static AmmoPoolEntity * createPool()
创建并触摸全部组件。
Definition Weapon.cpp:155
武器逻辑接口:注册到 WeaponSystem 的可插拔行为。
Definition WeaponLogic.h:22
武器实体:数据全部在组件里,行为在 WeaponSystem。
static WeaponEntity * createWeapon()
创建并触摸全部组件。
Definition Weapon.cpp:129
武器挂点实体:可持有武器并限制旋转(炮塔 / 机枪座 / 固定挂架)。
static WeaponMountEntity * createMount()
创建并触摸全部组件。
Definition Weapon.cpp:139
手持位实体:面向 ARPG/RPG 角色手持武器(剑/法杖/步枪),无炮塔限位。
static WeaponRigEntity * createRig()
创建并触摸全部组件。
Definition Weapon.cpp:147
static void update(WeaponEntity &w, float dt)
每帧推进:冷却 / 连发 / 装填 / 炮口旋转 / 逻辑自身。
static bool canFire(WeaponEntity &w)
是否可开火(未装填/未卡壳/冷却完毕/有弹药/逻辑放行)。
static void registerLogic(IWeaponLogic *logic)
注册武器逻辑实现;同名替换。
static void setEventSink(WeaponEventSink sink)
注册事件汇(替换旧的;传 nullptr 清空)。
static void cancelReload(WeaponEntity &w)
打断装填。
static bool tryFire(WeaponEntity &w, const FireRequest &req)
尝试开火;满足条件时扣弹药、调逻辑、推事件并返回 true。
static void startReload(WeaponEntity &w)
开始装填(有备用弹药且弹匣不满时生效)。
static void emitEvent(const WeaponEvent &e)
向事件汇推一条事件(模块/脚本便捷入口)。
static int logicCount()
已注册逻辑数量。
武器模块(eve.Weapon)。
Definition Weapon.h:24
std::string getEventWeaponId(int index) const
Returns the event weapon id.
Definition Weapon.cpp:570
float getEventSpread(int index) const
P0 手感/伤害事件载荷(仅 fire 事件)。
Definition Weapon.cpp:594
bool fireAt(WeaponEntity *w, float x, float y, float z, int shooterId=0)
向目标点开火(自动生成 FireRequest)。
Definition Weapon.cpp:450
float getEventRecoilYaw(int index) const
Returns the event recoil yaw.
Definition Weapon.cpp:606
WeaponEntity * mountGetWeapon(WeaponMountEntity *m)
Returns the weapon mounted on a mount, or null when empty.
Definition Weapon.cpp:411
bool attack(WeaponEntity *w, float yaw, float pitch, int shooterId=0)
触发展开攻击(近战/法杖/导弹走阶段机;热武器等价 fire)。
Definition Weapon.cpp:461
bool mountAttachWeapon(WeaponMountEntity *m, WeaponEntity *w)
挂点操作:挂武器 / 取武器 / 限位 / 瞄准 / 击毁。
Definition Weapon.cpp:405
bool bindAmmoPool(WeaponEntity *w, AmmoPoolEntity *pool)
Binds ammo pool.
Definition Weapon.cpp:389
void unbindAmmoPool(WeaponEntity *w)
Unbinds ammo pool.
Definition Weapon.cpp:395
AmmoPoolEntity * getAmmoPool(WeaponEntity *w)
Returns the weapon's shared ammunition pool, or null when unbound.
Definition Weapon.cpp:399
void mountSetLimits(WeaponMountEntity *m, float yawMin, float yawMax, float pitchMin, float pitchMax, float rotSpeed, float firingArc)
Mounts set limits.
Definition Weapon.cpp:413
void update(float dt)
每帧推进全部武器与挂点。
Definition Weapon.cpp:544
std::string getStage(WeaponEntity *w) const
武器当前阶段("idle"|"windup"|"active"|"recover")。
Definition Weapon.cpp:618
bool setFireMode(WeaponEntity *w, const std::string &mode)
运行时射击模式切换(safe/semi/auto)。
Definition Weapon.cpp:490
std::string getEventType(int index) const
Returns the event type.
Definition Weapon.cpp:566
std::string getWeaponDefinitionLogic(const std::string &id)
Returns the weapon definition logic.
Definition Weapon.cpp:246
void startReload(WeaponEntity *w)
Starts reload.
Definition Weapon.cpp:476
std::string getFireMode(WeaponEntity *w)
当前射击模式名("single"|"burst"|"auto")。
Definition Weapon.cpp:505
float getWeaponDefinitionRange(const std::string &id)
Returns the weapon definition range.
Definition Weapon.cpp:264
std::string getEventElement(int index) const
Returns the event element.
Definition Weapon.cpp:614
void cancelReload(WeaponEntity *w)
Cancel reload.
Definition Weapon.cpp:480
bool fire(WeaponEntity *w, const FireRequest &req)
武器操作(脚本便捷入口,转发 WeaponSystem)。
Definition Weapon.cpp:448
WeaponRigEntity * newRig(const std::string &id, const std::string &wield="right_hand")
创建一个手持位(ARPG/RPG 角色手持武器)。
Definition Weapon.cpp:335
void clearWeaponDefinitions()
清空全部武器模板。
Definition Weapon.cpp:233
float getZoomFov(WeaponEntity *w)
开镜缩放 FOV(模板 zoomFov)。
Definition Weapon.cpp:533
std::string getSelectableMode(WeaponEntity *w, int index)
Returns the selectable mode.
Definition Weapon.cpp:514
float getSpread(WeaponEntity *w)
手感查询:当前散布 / 未回正后坐。
Definition Weapon.cpp:538
int getWeaponDefinitionCount()
已注册武器模板数量。
Definition Weapon.cpp:242
bool isAiming(WeaponEntity *w)
True when aiming.
Definition Weapon.cpp:531
WeaponMountEntity * newMount(const std::string &id, const std::string &type="turret")
创建一个挂点(炮塔/机枪座等)。
Definition Weapon.cpp:327
bool setAiming(WeaponEntity *w, bool aiming)
开镜(ADS):切换 aiming 状态并推 aim_in/aim_out 事件。
Definition Weapon.cpp:520
float getEventArc(int index) const
近战命中弧(仅 fire 事件)。
Definition Weapon.cpp:586
bool canFire(WeaponEntity *w)
Can fire.
Definition Weapon.cpp:474
WeaponEntity * rigGetWeapon(WeaponRigEntity *rig)
Rig get weapon.
Definition Weapon.cpp:353
int getEventAmmoLeft(int index) const
Returns the event ammo left.
Definition Weapon.cpp:582
float getEventAoe(int index) const
法术/导弹爆炸半径(仅 fire 事件)。
Definition Weapon.cpp:590
std::string getEventMountId(int index) const
Returns the event mount id.
Definition Weapon.cpp:578
float getResourceValue(WeaponEntity *w) const
武器当前资源值(弹药/法力/充能/体力)。
Definition Weapon.cpp:622
int getEventCount() const
Returns the event count.
Definition Weapon.cpp:564
void setAim(WeaponEntity *w, float yaw, float pitch)
Sets the aim.
Definition Weapon.cpp:484
AmmoPoolEntity * newAmmoPool(const std::string &id, const std::string &ammoType, int max=-1)
共享弹药池操作:创建 / 补弹 / 查询 / 绑定武器 / 解绑 / 取绑定池。
Definition Weapon.cpp:369
int getEventPellets(int index) const
Returns the event pellets.
Definition Weapon.cpp:598
float getRecoilYaw(WeaponEntity *w)
Returns the recoil yaw.
Definition Weapon.cpp:542
int registerWeaponsFromJson(const std::string &json)
从 JSON 注册武器模板;返回成功注册数量。
Definition Weapon.cpp:182
int ammoPoolGetCount(AmmoPoolEntity *pool)
Ammo pool get count.
Definition Weapon.cpp:387
bool rigAttachWeapon(WeaponRigEntity *rig, WeaponEntity *w)
手持位操作:挂武器 / 取武器 / 设置持有位姿。
Definition Weapon.cpp:347
~Weapon() override
Weapon.
Definition Weapon.cpp:170
void mountAimAt(WeaponMountEntity *m, float yaw, float pitch)
按限位夹取目标角并写入挂载武器的瞄准目标(角度,度)。
Definition Weapon.cpp:424
bool hasWeaponDefinition(const std::string &id)
武器模板查询。
Definition Weapon.cpp:244
static int getLogicCount()
已注册逻辑数量(内置 hitscan / projectile 起步)。
Definition Weapon.cpp:275
void clearEvents()
事件队列(fire/reload/empty,上一次 update 产生)。
Definition Weapon.cpp:562
float getWeaponDefinitionDamage(const std::string &id)
Returns the weapon definition damage.
Definition Weapon.cpp:255
std::string getEventDefId(int index) const
Returns the event def id.
Definition Weapon.cpp:574
float getEventRecoilPitch(int index) const
Returns the event recoil pitch.
Definition Weapon.cpp:602
WeaponEntity * newWeapon(const std::string &defId)
工厂:对象由 ECS 表持有,脚本持有的是非拥有句柄。
Definition Weapon.cpp:287
float getRecoilPitch(WeaponEntity *w)
Returns the recoil pitch.
Definition Weapon.cpp:540
void rigSetPose(WeaponRigEntity *rig, float px, float py, float pz, float rx, float ry, float rz)
Rig set pose.
Definition Weapon.cpp:355
std::string getEventDamageType(int index) const
Returns the event damage type.
Definition Weapon.cpp:610
static void registerLogic(IWeaponLogic *logic)
注册武器逻辑(C++ 插件/游戏侧扩展点;同名替换)。
Definition Weapon.cpp:273
int getSelectableModeCount(WeaponEntity *w)
可选射击模式数量 / 第 index 个模式名。
Definition Weapon.cpp:509
void mountDestroy(WeaponMountEntity *m)
标记挂点被击毁(炮塔被打掉);已毁挂点不再瞄准/开火。
Definition Weapon.cpp:439
void ammoPoolAdd(AmmoPoolEntity *pool, int n)
Ammo pool add.
Definition Weapon.cpp:378
std::unordered_map< std::string, SkillDefinition > & table()
Definition Skill.cpp:65
载具模块入口(eve.Vehicle):定义注册 / 实体工厂 / RTS 命令 / 帧调度。 设计文档:docs/dev/通用载具系统设计.md
WeaponKind
武器形态。
Definition WeaponTypes.h:34
const char * weaponKindName(WeaponKind kind)
武器形态的字符串名("melee" | "ranged" | "magic" | "missile" | "custom")。
Definition Weapon.cpp:86
eve::Result< WeaponDefinition > parseWeaponDefinition(const eve::definitions::Definition &source)
Parse one canonical registry definition into an owning typed snapshot.
WeaponKind weaponKindFromName(const std::string &name)
从字符串解析武器形态;未知名字回退 Ranged。
Definition Weapon.cpp:97
void exposeCombatCarrierModuleMethods(ssq::Class &cls)
Register Weapon module methods that create owned carrier runtimes.
FireMode fireModeFromName(const std::string &name)
从字符串解析开火模式;未知名字回退 Single。
Definition Weapon.cpp:80
AttackStage
攻击阶段。
Definition WeaponTypes.h:62
void exposeCombatCarrierBindings(ssq::Table &table)
Expose CombatCarrierRuntime class bindings under the shared eve table.
FireMode
开火模式(热武器保留字段)。
Definition WeaponTypes.h:82
const char * weaponEventTypeName(WeaponEventType type)
事件类型的字符串名。
Definition Weapon.cpp:115
const char * fireModeName(FireMode mode)
开火模式的字符串名("single" | "burst" | "auto")。
Definition Weapon.cpp:71
WeaponEventType
武器事件类型。
Definition WeaponTypes.h:98
const char * attackStageName(AttackStage stage)
攻击阶段的字符串名("idle" | "windup" | "active" | "recover")。
Definition Weapon.cpp:105
detail::StrongUint64< detail::SchemaVersionTag > SchemaVersion
Persistent data-format version; not a runtime replacement generation.
void registerCppEntityView(const ssq::Class &cls, CppEntityViewFn fn)
Registers cpp entity view.
Definition ECS.cpp:861
One immutable view of a registered versioned JSON definition.
Definition Definitions.h:31
一次攻击请求(C++ 系统 / 脚本发起)。角度均为度。 旧名 FireRequest 保留为别名,向后兼容。
int shooterId
游戏侧实体/玩家 id。
float yaw
发射方向(度)。
float arcAngle
近战挥击命中弧(度)。
float aoeRadius
法术/导弹爆炸半径。
运行时触发资源(实体组件)。
武器模板(registerWeaponsFromJson 注册,进程级注册表)。
AttackResource resource
触发资源(弹药 / 法力 / 充能 / 体力 / 无)。
float zoomFov
开镜缩放 FOV(0 = 无缩放);State.aiming 时生效。
WeaponKind kind
形态(决定阶段机如何跑)。默认 Ranged。
int magSize
弹匣容量 / 备用弹药(<0 = 无限备用,0 = 无备用)。热武器保留字段。
float spreadMin
散布 bloom:连续射击精度下降,停火回稳。
武器事件(帧缓存,脚本轮询,与 building/rpg 风格一致)。