载入中...
搜索中...
未找到
ActionWindowState.cpp
浏览该文件的文档.
2
3#include "combat/MeleeHit.h"
4#include "common/Capability.h"
5
6#include <utility>
7
8namespace eve::combat {
9 // namespace
10
13
14CombatActionWindowState::~CombatActionWindowState() { cap::removeListener<action::IActionStateWindowSink>(this); }
15
17 for (std::size_t index = 0; index < cap::listenerCount<action::IActionStateWindowSink>(); ++index)
18 if (cap::listenerAt<action::IActionStateWindowSink>(index) == this) return true;
19 return false;
20}
21
23 const bool current = enabled();
24 if (value && !current)
25 cap::addListener<action::IActionStateWindowSink>(this);
26 else if (!value && current)
27 cap::removeListener<action::IActionStateWindowSink>(this);
28}
29
30void CombatActionWindowState::setMeleeHitRuntime(MeleeHitRuntime& melee) noexcept { melee_ = &melee; }
31
32void CombatActionWindowState::clearMeleeHitRuntime() noexcept { melee_ = nullptr; }
33
37
39 const action::ActionTimelineEvent& event,
41 if (!supports(binding.kind))
42 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Unsupported, "combat does not own this state-window kind", "kind"));
43 if (!resolver_) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "window subject resolver is unavailable", "resolver"));
44 std::optional<ecs::EntityHandle> handle;
45 if (binding.targetIndex) {
46 if (*binding.targetIndex >= context.targets.size())
47 return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "state-window target index is unavailable", "targetIndex"));
48 handle = context.targets[*binding.targetIndex];
49 } else {
50 handle = context.source;
51 }
52 if (!handle) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "state window has no source or target", "subject"));
53 auto subject = resolver_(*handle);
54 if (!subject) return Result<void>::failure(subject.status());
55 if (!subject.value().isValid())
56 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "state-window subject is nil", "subject"));
57
58 ActiveKey key{context.executionId, event.itemId.format()};
59 const auto found = active_.find(key);
60 if (found != active_.end()) {
61 const bool same = found->second.subject == subject.value() &&
62 found->second.binding.kind == binding.kind &&
63 found->second.binding.resource == binding.resource;
65 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "state-window key is already active with different data", "itemId"));
66 }
67 if (binding.kind == action::ActionStateWindowKind::Hitbox && melee_) {
68 auto armed = melee_->armHitbox(subject.value(), binding.resource, context.executionId);
69 if (!armed) return armed;
70 }
71 active_.emplace(std::move(key), ActiveWindow{binding, subject.value()});
73}
74
76 const action::ActionTimelineEvent& event,
78 if (!supports(binding.kind))
79 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Unsupported, "combat does not own this state-window kind", "kind"));
80 const ActiveKey key{context.executionId, event.itemId.format()};
81 const auto found = active_.find(key);
82 if (found == active_.end()) return Result<void>::success(Status::success(StatusCode::NoOp));
83 if (found->second.binding.kind != binding.kind)
84 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "state-window exit kind does not match active key", "kind"));
85 const auto subject = found->second.subject;
86 const auto resource = found->second.binding.resource;
87 const auto kind = found->second.binding.kind;
88 active_.erase(found);
90 auto disarmed = melee_->disarmHitbox(subject, resource, context.executionId);
91 if (!disarmed) return disarmed;
92 }
94}
95
97 for (const auto& [key, window] : active_) {
98 (void)key;
99 if (window.subject == subject && window.binding.kind == action::ActionStateWindowKind::Invulnerability)
100 return true;
101 }
102 return false;
103}
104
106 std::vector<std::string> result;
107 for (const auto& [key, window] : active_) {
108 (void)key;
109 if (window.subject == subject && window.binding.kind == action::ActionStateWindowKind::Hitbox)
110 result.push_back(window.binding.resource);
111 }
112 return result;
113}
114
115} // namespace eve::combat
double value
Combat-owned active hitbox and invulnerability projections.
int subject
Definition AnimSmr.cpp:163
std::uint32_t key
TokenKind kind
Deterministic bone-agnostic melee hitbox/hurtbox sweep.
eve::action::ActionVfxBinding binding
PrimitiveHandle handle
bool found
double current
std::string resource
uint32_t index
const VegetationPresetContext & context
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Strong, domain-neutral reference to a runtime subject.
Definition SubjectRef.h:26
void clearMeleeHitRuntime() noexcept
Clear the borrowed melee geometry owner.
bool supports(action::ActionStateWindowKind kind) const noexcept override
Whether this sink owns the supplied semantic window kind.
void setEnabled(bool enabled)
Opt this owner into or out of Action state-window dispatch.
Result< void > enter(const action::ActionStateWindowBinding &binding, const action::ActionTimelineEvent &event, const action::ActionNotifyContext &context) override
Enter one validated window or idempotently observe the same active key.
void setMeleeHitRuntime(MeleeHitRuntime &melee) noexcept
Borrow melee geometry so hitbox windows arm and disarm automatically. @lifetime The melee runtime mus...
Result< void > exit(const action::ActionStateWindowBinding &binding, const action::ActionTimelineEvent &event, const action::ActionNotifyContext &context) override
Exit one previously entered window by execution and item identity.
CombatActionWindowState(ActionWindowSubjectResolver resolver)
Construct with a synchronous resolver copied into the state owner.
~CombatActionWindowState() override
Combat action window state.
bool enabled() const
Return whether this exact owner is registered.
bool isInvulnerable(SubjectRef subject) const noexcept
Return whether at least one active Montage window protects this stable subject.
std::vector< std::string > activeHitboxes(SubjectRef subject) const
Return owning hitbox identifiers active for a stable subject in key order.
Owner-thread authority for hurtboxes, hitbox catalogs and sweep hits.
Definition MeleeHit.h:132
Result< void > armHitbox(SubjectRef subject, std::string_view hitboxId, action::ActionExecutionId execution)
Arm one hitbox while a Montage window owns it.
Definition MeleeHit.cpp:214
Result< void > disarmHitbox(SubjectRef subject, std::string_view hitboxId, action::ActionExecutionId execution)
Disarm one hitbox window and forget its per-target hit memory.
Definition MeleeHit.cpp:242
ActionStateWindowKind
Stable semantic kind for one built-in state window.
std::function< Result< SubjectRef >(ecs::EntityHandle)> ActionWindowSubjectResolver
Resolves an owning stable subject from a generation-qualified ECS handle.
Context linking a routed event to its action execution.
Owning validated state-window request authored on an action timeline.
Owning event projection returned by the runtime sampler.