载入中...
搜索中...
未找到
GuardWindowState.cpp
浏览该文件的文档.
2
3#include "common/Capability.h"
4
5#include <utility>
6
7namespace eve::combat {
8namespace {
9
10Result<GuardMode> parseMode(const std::string& resource) {
11 if (resource == "block") return Result<GuardMode>::success(GuardMode::Block);
12 if (resource == "parry") return Result<GuardMode>::success(GuardMode::Parry);
14 Diagnostic::error(DiagnosticCode::InvalidArgument, "guard mode must be block or parry", "mode"));
15}
16
17} // namespace
18
19GuardWindowState::GuardWindowState(GuardSubjectResolver resolver) : resolver_(std::move(resolver)) {}
20
21GuardWindowState::~GuardWindowState() { cap::removeListener<action::IActionStateWindowSink>(this); }
22
24 for (std::size_t index = 0; index < cap::listenerCount<action::IActionStateWindowSink>(); ++index)
25 if (cap::listenerAt<action::IActionStateWindowSink>(index) == this) return true;
26 return false;
27}
28
30 const bool current = enabled();
31 if (value && !current)
32 cap::addListener<action::IActionStateWindowSink>(this);
33 else if (!value && current)
34 cap::removeListener<action::IActionStateWindowSink>(this);
35}
36
40
42 const action::ActionTimelineEvent& event,
44 if (!supports(binding.kind))
45 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Unsupported, "combat guard does not own this state-window kind", "kind"));
46 if (!resolver_) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "guard subject resolver is unavailable", "resolver"));
47 auto mode = parseMode(binding.resource);
48 if (!mode) return Result<void>::failure(mode.status());
49 std::optional<ecs::EntityHandle> handle;
50 if (binding.targetIndex) {
51 if (*binding.targetIndex >= context.targets.size())
52 return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "guard target index is unavailable", "targetIndex"));
53 handle = context.targets[*binding.targetIndex];
54 } else {
55 handle = context.source;
56 }
57 if (!handle) return Result<void>::failure(Diagnostic::error(DiagnosticCode::NotFound, "guard window has no source or target", "subject"));
58 auto subject = resolver_(*handle);
59 if (!subject) return Result<void>::failure(subject.status());
60 if (!subject.value().isValid())
61 return Result<void>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "guard-window subject is nil", "subject"));
62
63 ActiveKey key{context.executionId, event.itemId.format()};
64 const auto found = active_.find(key);
65 if (found != active_.end()) {
66 const bool same = found->second.subject == subject.value() && found->second.mode == mode.value();
68 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "guard-window key is already active with different data", "itemId"));
69 }
70 active_.emplace(std::move(key), ActiveGuard{binding, subject.value(), mode.value()});
72}
73
75 const action::ActionTimelineEvent& event,
77 if (!supports(binding.kind))
78 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Unsupported, "combat guard does not own this state-window kind", "kind"));
79 const ActiveKey key{context.executionId, event.itemId.format()};
80 const auto found = active_.find(key);
81 if (found == active_.end()) return Result<void>::success(Status::success(StatusCode::NoOp));
82 if (found->second.binding.kind != binding.kind)
83 return Result<void>::failure(Diagnostic::error(DiagnosticCode::Conflict, "guard-window exit kind does not match active key", "kind"));
84 active_.erase(found);
86}
87
89 if (!defender.isValid() || !attacker.isValid())
91 Diagnostic::error(DiagnosticCode::InvalidArgument, "guard subjects must be valid", "subject"));
92 GuardEvaluation evaluation;
93 evaluation.defender = defender;
94 evaluation.attacker = attacker;
95 bool hasBlock = false;
96 bool hasParry = false;
97 for (const auto& [key, window] : active_) {
98 (void)key;
99 if (window.subject != defender) continue;
100 if (window.mode == GuardMode::Parry) hasParry = true;
101 if (window.mode == GuardMode::Block) hasBlock = true;
102 }
103 if (hasParry) {
104 evaluation.result = GuardResult::Parried;
105 evaluation.mode = GuardMode::Parry;
106 } else if (hasBlock) {
107 evaluation.result = GuardResult::Blocked;
108 evaluation.mode = GuardMode::Block;
109 }
110 return Result<GuardEvaluation>::success(evaluation);
111}
112
114 auto evaluation = evaluate(defender, request.source);
115 if (!evaluation) return evaluation;
116 if (evaluation.value().result == GuardResult::None) return evaluation;
117 request.healthDamage = 0.0;
118 request.poiseDamage = 0.0;
119 request.knockback = {};
120 return evaluation;
121}
122
123std::vector<GuardMode> GuardWindowState::activeModes(SubjectRef subject) const {
124 std::vector<GuardMode> modes;
125 for (const auto& [key, window] : active_) {
126 (void)key;
127 if (window.subject == subject) modes.push_back(window.mode);
128 }
129 return modes;
130}
131
132} // namespace eve::combat
double value
int subject
Definition AnimSmr.cpp:163
const GltfImportRequest & request
std::uint32_t key
Block and parry windows projected from Montage state.
TokenKind kind
eve::action::ActionVfxBinding binding
PrimitiveHandle handle
bool found
double current
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
bool isValid() const noexcept
Return whether this reference is valid and non-nil.
Definition SubjectRef.h:38
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.
std::vector< GuardMode > activeModes(SubjectRef subject) const
Return active guard modes for a subject in key order.
~GuardWindowState() override
Guard window state.
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.
Result< GuardEvaluation > evaluate(SubjectRef defender, SubjectRef attacker) const
Evaluate whether a defender currently blocks or parries an attacker.
GuardWindowState(GuardSubjectResolver resolver)
Construct with a synchronous subject resolver.
bool enabled() const
Return whether this exact owner is registered.
void setEnabled(bool enabled)
Opt this owner into or out of Action state-window dispatch.
bool supports(action::ActionStateWindowKind kind) const noexcept override
Whether this sink owns the supplied semantic window kind.
Result< GuardEvaluation > mitigate(SubjectRef defender, DamageRequest &request) const
Mutate a damage request when guard succeeds.
ActionStateWindowKind
Stable semantic kind for one built-in state window.
std::function< Result< SubjectRef >(ecs::EntityHandle)> GuardSubjectResolver
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.
Owning input for one damage transaction.
Definition Damage.h:49
Owning audit of one guard evaluation.