载入中...
搜索中...
未找到
ActionDamageBlock.cpp
浏览该文件的文档.
2
3#include "tags/GameplayTag.h"
4
5#include <cmath>
6#include <limits>
7#include <string>
8#include <utility>
9
10namespace eve::action {
11namespace {
12
13Result<double> number(const Value& value, std::string path) {
14 double result = 0.0;
15 if (const auto* integer = value.getIf<std::int64_t>())
16 result = static_cast<double>(*integer);
17 else if (const auto* decimal = value.getIf<double>())
18 result = *decimal;
19 else
21 Diagnostic::error(DiagnosticCode::InvalidArgument, "damage field must be numeric", path));
22 if (!std::isfinite(result))
24 Diagnostic::error(DiagnosticCode::InvalidArgument, "damage field must be finite", path));
25 return Result<double>::success(result);
26}
27
28Result<double> optionalNumber(const Value::Object& payload, const char* field, double fallback) {
29 const auto found = payload.find(field);
30 return found == payload.end() ? Result<double>::success(fallback) : number(found->second, field);
31}
32
33} // namespace
34
36 ActionDamageBinding candidate;
37 const auto foundType = payload.find("damageType");
38 const auto* damageType = foundType == payload.end() ? nullptr : foundType->second.getIf<std::string>();
41 Diagnostic::error(DiagnosticCode::InvalidArgument, "damage type must be a gameplay tag", "damageType"));
42 candidate.damageType = *damageType;
43
44 const auto foundAmount = payload.find("amount");
45 if (foundAmount == payload.end())
47 Diagnostic::error(DiagnosticCode::InvalidArgument, "damage amount is required", "amount"));
48 auto amount = number(foundAmount->second, "amount");
50 auto poise = optionalNumber(payload, "poiseAmount", 0.0);
51 if (!poise) return Result<ActionDamageBinding>::failure(poise.status());
52 if (amount.value() < 0.0)
54 Diagnostic::error(DiagnosticCode::InvalidArgument, "damage amount must be non-negative", "amount"));
55 if (poise.value() < 0.0)
57 Diagnostic::error(DiagnosticCode::InvalidArgument, "poise damage must be non-negative", "poiseAmount"));
58 candidate.amount = amount.value();
59 candidate.poiseAmount = poise.value();
60
61 if (const auto foundTarget = payload.find("targetIndex"); foundTarget != payload.end()) {
62 const auto* target = foundTarget->second.getIf<std::int64_t>();
63 if (!target || *target < 0 || static_cast<std::uint64_t>(*target) > std::numeric_limits<std::uint32_t>::max())
66 "damage target index must be an unsigned 32-bit integer", "targetIndex"));
67 candidate.targetIndex = static_cast<std::size_t>(*target);
68 }
69
70 if (const auto foundKnockback = payload.find("knockback"); foundKnockback != payload.end()) {
71 const auto* values = foundKnockback->second.getIf<Value::Array>();
72 if (!values || values->size() != 3)
74 DiagnosticCode::InvalidArgument, "damage knockback must contain three numbers", "knockback"));
75 auto x = number((*values)[0], "knockback[0]");
76 if (!x) return Result<ActionDamageBinding>::failure(x.status());
77 auto y = number((*values)[1], "knockback[1]");
78 if (!y) return Result<ActionDamageBinding>::failure(y.status());
79 auto z = number((*values)[2], "knockback[2]");
80 if (!z) return Result<ActionDamageBinding>::failure(z.status());
81 candidate.knockback = {x.value(), y.value(), z.value()};
82 }
83 return Result<ActionDamageBinding>::success(std::move(candidate));
84}
85
86} // namespace eve::action
Typed instantaneous combat-damage action contract.
LogicalId target
double value
Value::Object payload
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::map< std::string, Var > values
Stable hierarchical gameplay-tag definitions and registry.
std::int32_t second
std::string path
Definition PlayHost.cpp:110
double number
bool found
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
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
const EditorValue * field(const EditorValue &value, const char *name)
bool isValidGameplayTagName(std::string_view name) noexcept
Returns whether a name is a canonical dot-separated gameplay tag.
Owning validated damage request authored on an action timeline.
double poiseAmount
Non-negative poise damage.
std::size_t targetIndex
Target index into ActionNotifyContext::targets.
ActionDamageImpulse knockback
Optional world-space knockback impulse.
static Result< ActionDamageBinding > fromPayload(const Value::Object &payload)
Decode and validate a damage payload without mutating combat state.
std::string damageType
Gameplay-tag damage classification.
double amount
Non-negative health damage.