载入中...
搜索中...
未找到
RTSMotion.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::rts {
11
13 if (step.delta.nanoseconds() < 0)
15 DiagnosticCode::InvalidArgument, "RTS motion step delta must be non-negative", "step.delta"));
16 const double deltaSeconds = step.delta.seconds();
17 std::size_t processed = 0;
20 for (auto it = view.begin(); it != view.end(); ++it) {
21 auto [identity, motion, navigation, orders, combat, containment, supply, morale, tactics, command, effects] =
22 *it;
23 Unit* unit = identity == nullptr ? nullptr : dynamic_cast<Unit*>(ecs::try_get(identity->self));
24 if (unit == nullptr || &*unit->identity() != identity) continue;
25 if (unit->crowd()->link.isBound() || containment->container.isBound()) continue;
26 if (!std::isfinite(motion->x) || !std::isfinite(motion->y) || !std::isfinite(motion->speed) ||
27 !std::isfinite(motion->arrivalRadius) || motion->speed < 0.0f || motion->arrivalRadius < 0.0f)
30 "RTS motion state must contain finite non-negative values", "unit.motion"));
31
32 auto current = readCurrent(orders->values);
33 if (!current) return Result<std::size_t>::failure(current.status());
34 auto record = std::move(current).takeValue();
35 if (!record) continue;
36 if (!isMovementOrder(record->kind)) {
37 motion->arrived = true;
38 ++processed;
39 continue;
40 }
41 if ((navigation->trafficWaiting && !navigation->trafficRecoveryTarget) || supply->convoyWaiting ||
42 (morale->retreating && tactics->retreatCovering)) {
43 motion->arrived = false;
44 ++processed;
45 continue;
46 }
47 if (record->kind == OrderKind::AttackMove && combat->engagementRange > 0.0f &&
48 !navigation->trafficRecoveryTarget) {
49 auto engaged = entityPosition(combat->target);
50 if (engaged && distanceSquared(motion->x, motion->y, engaged->x, engaged->y) <=
51 combat->engagementRange * combat->engagementRange) {
52 motion->arrived = false;
53 ++processed;
54 continue;
55 }
56 }
57
58 WorldPosition target = record->target;
59 if (record->kind == OrderKind::Attack || record->kind == OrderKind::Resupply ||
60 record->kind == OrderKind::SupplyRelay) {
61 auto liveTarget = entityPosition(record->targetEntity);
62 if (liveTarget) target = *liveTarget;
63 if (record->kind == OrderKind::SupplyRelay && supply->rendezvousActive) target = supply->rendezvousPoint;
64 } else if (record->kind == OrderKind::Escort && tactics->guardSet) {
65 target = {tactics->guardX, tactics->guardY};
66 } else if (record->kind == OrderKind::Patrol && navigation->patrolInitialized &&
67 !navigation->patrolTowardTarget) {
68 target = navigation->patrolOrigin;
69 }
70 if (navigation->plannedOrderId == record->id && !navigation->unreachable &&
71 navigation->waypointIndex < navigation->waypoints.size())
72 target = navigation->waypoints[navigation->waypointIndex];
73 const bool movingSlot = record->kind == OrderKind::Move && navigation->formationTarget.has_value();
74 if (movingSlot) target = *navigation->formationTarget;
75 if (navigation->trafficRecoveryTarget) target = *navigation->trafficRecoveryTarget;
76 const float dx = target.x - motion->x;
77 const float dy = target.y - motion->y;
78 const float distance = std::hypot(dx, dy);
79 if (!std::isfinite(distance))
81 DiagnosticCode::InvariantViolation, "RTS motion target distance is non-finite", "order.target"));
82 float arrivalRadius = motion->arrivalRadius;
83 if (record->kind == OrderKind::Attack)
84 arrivalRadius = std::max(arrivalRadius, combat->engagementRange);
85 else if (record->kind == OrderKind::Resupply || record->kind == OrderKind::SupplyRelay)
86 arrivalRadius = std::max(arrivalRadius, supply->range * 0.8f);
87 if (distance <= arrivalRadius) {
88 if (record->kind != OrderKind::Attack) {
89 motion->x = target.x;
90 motion->y = target.y;
91 }
92 motion->arrived = true;
93 } else if (deltaSeconds > 0.0 && motion->speed > 0.0f) {
94 const float moraleFactor = morale->active ? std::clamp(morale->suppressedSpeedFactor, 0.0f, 1.0f) : 1.0f;
95 const float commandFactor =
96 command->requiresCommand && !command->inCommand ? command->outOfCommandSpeedFactor : 1.0f;
97 const float effectFactor = static_cast<float>(effects->values.multiplier("speedMultiplier"));
98 const float speedFactor = moraleFactor * commandFactor * effectFactor * navigation->formationSpeedFactor;
99 const double travel = static_cast<double>(motion->speed * speedFactor) * deltaSeconds;
100 if (!std::isfinite(travel))
102 DiagnosticCode::InvalidArgument, "RTS motion travel distance is non-finite", "unit.motion.speed"));
103 const float amount = static_cast<float>(std::min<double>(travel, distance));
104 motion->x += dx / distance * amount;
105 motion->y += dy / distance * amount;
106 motion->arrived = static_cast<double>(amount) >= distance - arrivalRadius;
107 if (motion->arrived) {
108 if (record->kind != OrderKind::Attack) {
109 motion->x = target.x;
110 motion->y = target.y;
111 }
112 }
113 } else {
114 motion->arrived = false;
115 }
116 if (movingSlot)
117 motion->arrived = distanceSquared(motion->x, motion->y, record->target.x, record->target.y) <=
118 motion->arrivalRadius * motion->arrivalRadius;
119 if (navigation->trafficRecoveryTarget) motion->arrived = false;
120 ++processed;
121 }
123}
124
125} // namespace eve::rts
LogicalId target
float distance
glm::mat4 view
double current
float dy
float dx
TacticalUnit * unit
float step
Definition TreeMesh.cpp:314
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
static Result< std::size_t > step(const SimulationStep &step)
Advance all Units with Motion and Orders components.
Definition RTSMotion.cpp:12
RTS unit domain root.
Definition RTSTypes.h:495
float distanceSquared(float ax, float ay, float bx, float by)
Result< std::optional< OrderRecord > > readCurrent(OrderComponent &orders)
std::optional< WorldPosition > entityPosition(const ecs::EntityHandle &handle)
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
RTS stance and pursuit limits used by automatic combat policies.
Definition RTSTypes.h:610
Command-network policy and derived connection state for a mobile unit or relay.
Definition RTSTypes.h:655
Unit containment state for transports and building garrisons.
Definition RTSTypes.h:693
Lifecycle-only active effects.
Definition RTSTypes.h:522
Runtime identity and logical unit definition.
Definition RTSTypes.h:504
Suppression, recovery, retreat policy, and friendly morale aura.
Definition RTSTypes.h:724
Authoritative kinematic state used by the phase-one move slice.
Definition RTSTypes.h:560
RTS projection of a canonical map path; the map provider remains the grid authority.
Definition RTSTypes.h:569
Generic command/order state.
Definition RTSTypes.h:526
Tactical ammunition logistics; weapon ammunition remains authoritative in WeaponEntity.
Definition RTSTypes.h:699
Escort geometry and combat-group coordination state.
Definition RTSTypes.h:764
Two-dimensional deterministic RTS world position.
Definition RTSTypes.h:48