载入中...
搜索中...
未找到
CarrierRecipeCodec.cpp
浏览该文件的文档.
31Result<std::optional<double>> optionalDouble(const Value::Object& object, const char* name, std::string_view path) {
36 return Result<std::optional<double>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected finite number"), std::string(path), {},
43 return Result<std::optional<double>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected finite number"), std::string(path), {},
47 return Result<std::optional<double>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected number"), std::string(path), {},
51Result<std::optional<int>> optionalInt(const Value::Object& object, const char* name, std::string_view path) {
56 return Result<std::optional<int>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Integer out of range"), std::string(path), {},
62 return Result<std::optional<int>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected integer"), std::string(path), {},
66 return Result<std::optional<int>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Integer out of range"), std::string(path), {},
70 return Result<std::optional<int>>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected integer"), std::string(path), {},
74Result<void> assignOptionalDouble(const Value::Object& object, const char* name, double& dest, std::string_view path) {
81Result<void> assignOptionalInt(const Value::Object& object, const char* name, int& dest, std::string_view path) {
88Result<Duration> readSeconds(const Value::Object& object, const char* name, std::string_view path) {
92 return Result<Duration>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected positive seconds"), std::string(path), {},
99Result<LogicalId> readLogicalId(const Value::Object& object, const char* name, std::string_view path) {
102 return Result<LogicalId>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Expected non-empty logical id"), std::string(path), {},
106 return Result<LogicalId>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Logical id must be namespace:name"), std::string(path), {},
112 if (text == "linear" || text == "IntegrateLinear") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::IntegrateLinear);
113 if (text == "gravity" || text == "ApplyGravity") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::ApplyGravity);
114 if (text == "homing" || text == "SteerHoming") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::SteerHoming);
115 if (text == "accelerate" || text == "Accelerate") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::Accelerate);
116 if (text == "sway" || text == "CurveSway") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::CurveSway);
117 if (text == "helix" || text == "CurveHelix") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::CurveHelix);
118 if (text == "avoidBody" || text == "SteerAvoidBody") return Result<CarrierMotionOpKind>::success(CarrierMotionOpKind::SteerAvoidBody);
119 return Result<CarrierMotionOpKind>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Unknown motion kind"), std::string(path), {},
124 if (text == "onExpire" || text == "OnExpire") return Result<CarrierTriggerKind>::success(CarrierTriggerKind::OnExpire);
125 if (text == "onFuse" || text == "OnFuse") return Result<CarrierTriggerKind>::success(CarrierTriggerKind::OnFuse);
126 if (text == "onInterval" || text == "OnInterval") return Result<CarrierTriggerKind>::success(CarrierTriggerKind::OnInterval);
127 if (text == "onHit" || text == "OnHit") return Result<CarrierTriggerKind>::success(CarrierTriggerKind::OnHit);
128 if (text == "onProximity" || text == "OnProximity") return Result<CarrierTriggerKind>::success(CarrierTriggerKind::OnProximity);
129 return Result<CarrierTriggerKind>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Unknown trigger kind"), std::string(path), {},
134 if (text == "emitHit" || text == "hit" || text == "EmitHit") return Result<CarrierImpactKind>::success(CarrierImpactKind::EmitHit);
135 if (text == "splash" || text == "Splash") return Result<CarrierImpactKind>::success(CarrierImpactKind::Splash);
136 if (text == "pierce" || text == "Pierce") return Result<CarrierImpactKind>::success(CarrierImpactKind::Pierce);
137 if (text == "bounce" || text == "Bounce") return Result<CarrierImpactKind>::success(CarrierImpactKind::Bounce);
138 if (text == "release" || text == "Release") return Result<CarrierImpactKind>::success(CarrierImpactKind::Release);
139 if (text == "spawnChild" || text == "SpawnChild") return Result<CarrierImpactKind>::success(CarrierImpactKind::SpawnChild);
140 return Result<CarrierImpactKind>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Unknown impact kind"), std::string(path), {},
189 if (!object) return Result<CarrierMotionOp>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Motion op must be string or object"), std::string(path), {},
193 return Result<CarrierMotionOp>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Motion op requires kind"), std::string(path + ".kind"), {},
198 if (auto assigned = assignOptionalDouble(*object, "gravity", op.gravity, path + ".gravity"); !assigned)
201 assignOptionalDouble(*object, "maxTurnRateDegrees", op.maxTurnRateDegrees, path + ".maxTurnRateDegrees");
205 if (auto assigned = assignOptionalDouble(*object, "turnRate", op.maxTurnRateDegrees, path + ".turnRate");
209 if (auto assigned = assignOptionalDouble(*object, "acceleration", op.acceleration, path + ".acceleration");
212 if (auto assigned = assignOptionalDouble(*object, "avoidLookAhead", op.avoidLookAhead, path + ".avoidLookAhead");
215 if (auto assigned = assignOptionalDouble(*object, "avoidStrength", op.avoidStrength, path + ".avoidStrength");
219 assignOptionalDouble(*object, "avoidRadiusPadding", op.avoidRadiusPadding, path + ".avoidRadiusPadding");
222 if (auto assigned = assignOptionalDouble(*object, "curveAmplitude", op.curveAmplitude, path + ".curveAmplitude");
226 if (auto assigned = assignOptionalDouble(*object, "amplitude", op.curveAmplitude, path + ".amplitude");
231 assignOptionalDouble(*object, "curveFrequencyHz", op.curveFrequencyHz, path + ".curveFrequencyHz");
235 if (auto assigned = assignOptionalDouble(*object, "frequency", op.curveFrequencyHz, path + ".frequency");
251 if (!object) return Result<CarrierTrigger>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Trigger must be string or object"), std::string(path), {},
255 return Result<CarrierTrigger>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Trigger requires kind"), std::string(path + ".kind"), {},
265 const auto fuseSeconds = fuseField.value().has_value() ? fuseField.value() : secondsField.value();
281 assignOptionalDouble(*object, "proximityRadius", trigger.proximityRadius, path + ".proximityRadius");
285 if (auto assigned = assignOptionalDouble(*object, "radius", trigger.proximityRadius, path + ".radius");
294 if (!object) return Result<CarrierImpact>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Impact must be an object"), std::string(path), {},
299 return Result<CarrierImpact>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Impact requires kind"), std::string(path + ".kind"), {},
310 if (auto assigned = assignOptionalDouble(*object, "damage", impact.damage, path + ".damage"); !assigned)
312 if (auto assigned = assignOptionalDouble(*object, "splashRadius", impact.splashRadius, path + ".splashRadius");
316 if (auto assigned = assignOptionalDouble(*object, "radius", impact.splashRadius, path + ".radius"); !assigned)
319 if (auto assigned = assignOptionalInt(*object, "pierceCount", impact.pierceCount, path + ".pierceCount"); !assigned)
322 if (auto assigned = assignOptionalInt(*object, "count", impact.pierceCount, path + ".count"); !assigned)
325 if (auto assigned = assignOptionalInt(*object, "bounceCount", impact.bounceCount, path + ".bounceCount"); !assigned)
327 if (auto assigned = assignOptionalDouble(*object, "restitution", impact.restitution, path + ".restitution");
336 return Result<CarrierImpact>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Invalid childRecipeId"), std::string(path + ".childRecipeId"), {},
340 return Result<CarrierImpact>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("childRecipeId must be a string"), std::string(path + ".childRecipeId"), {},
360 return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Preset requires positive speed"), std::string("speed"), {},
380 if (auto assigned = assignOptionalDouble(object, "maxTurnRateDegrees", homing, "maxTurnRateDegrees"); !assigned)
383 if (auto assigned = assignOptionalDouble(object, "accelerate", accelerate, "accelerate"); !assigned)
501 return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Recipe requires positive speed"), std::string("speed"), {},
508 return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Full recipe requires motion array"), std::string("motion"), {},
518 return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Full recipe requires triggers array"), std::string("triggers"), {},
528 return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Full recipe requires impacts array"), std::string("impacts"), {},
545 if (!object) return Result<CarrierRecipe>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, std::string("Carrier recipe must be an object"), std::string(""), {},
552 if (field(*object, "motionOps") || (field(*object, "motion") && field(*object, "motion")->isArray()))
575 if (op.maxTurnRateDegrees != 0.0) entry.emplace("maxTurnRateDegrees", Value(op.maxTurnRateDegrees));
579 if (op.avoidRadiusPadding != 0.0) entry.emplace("avoidRadiusPadding", Value(op.avoidRadiusPadding));
591 if (trigger.interval > Duration::zero()) entry.emplace("interval", Value(trigger.interval.seconds()));
592 if (trigger.proximityRadius > 0.0) entry.emplace("proximityRadius", Value(trigger.proximityRadius));
604 if (impact.pierceCount != 0) entry.emplace("pierceCount", Value(static_cast<std::int64_t>(impact.pierceCount)));
605 if (impact.bounceCount != 0) entry.emplace("bounceCount", Value(static_cast<std::int64_t>(impact.bounceCount)));
609 if (impact.childRecipeId.isValid()) entry.emplace("childRecipeId", Value(impact.childRecipeId.format()));
Decode/encode CombatCarrier recipes from canonical eve::Value trees.
Stable, structured diagnostics shared by engine modules.
Common time values and an injectable deterministic simulation clock.
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
static Result< Duration > fromSeconds(double seconds)
Convert finite seconds to the nearest nanosecond.
Definition Time.cpp:16
double seconds() const noexcept
Return this duration as seconds for legacy/presentation APIs.
Definition Time.cpp:28
const std::string & format() const noexcept
Returns the canonical namespace:name representation.
Definition Identity.h:436
static std::optional< LogicalId > parse(std::string_view text)
Parses a scoped logical name.
Definition Identity.cpp:36
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
std::variant< std::monostate, std::int64_t, double, std::string, bool > Value
Definition Database.h:26
bool readString(const eve::Value::Object &object, const char *name, std::string &output)
Definition ArtifactProvider.cpp:20
const EditorValue * field(const EditorValue &value, const char *name)
Definition RoadNetworkEditTarget.cpp:15
WidgetDesc child(std::string id, std::vector< WidgetDesc > children, float width, float height)
Scrollable child region with an explicit size.
Definition Widget.cpp:635
载具模块入口(eve.Vehicle):定义注册 / 实体工厂 / RTS 命令 / 帧调度。 设计文档:docs/dev/通用载具系统设计.md
Definition RTSArchetype.h:10
@ SpawnChild
CarrierMotionOpKind
Ordered ballistic operators applied each simulation step.
Definition CombatCarrier.h:31
@ ApplyGravity
@ SteerHoming
@ CurveHelix
@ IntegrateLinear
@ CurveSway
@ Accelerate
@ SteerAvoidBody
Result< Value > encodeCarrierRecipe(const CarrierRecipe &recipe)
Encode one CarrierRecipe into an owning Value object (full form).
Definition CarrierRecipeCodec.cpp:561
Result< CarrierRecipe > decodeCarrierRecipe(const Value &value)
Decode one CarrierRecipe from an owning Value object.
Definition CarrierRecipeCodec.cpp:543
@ OnProximity
@ OnInterval
@ InvalidArgument
Data-driven composition recipe for one carrier family.
Definition CombatCarrier.h:107
std::vector< CarrierTrigger > triggers
Definition CombatCarrier.h:112
Result< void > validate() const
Validate finite parameters and composition constraints.
Definition CombatCarrier.cpp:145
std::vector< CarrierMotionOp > motionOps
Definition CombatCarrier.h:111
std::vector< CarrierImpact > impacts
Definition CombatCarrier.h:113