File: GroundMoveType.h

package info (click to toggle)
spring 106.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 55,260 kB
  • sloc: cpp: 543,946; ansic: 44,800; python: 12,575; java: 12,201; awk: 5,889; sh: 1,796; asm: 1,546; xml: 655; perl: 405; php: 211; objc: 194; makefile: 76; sed: 2
file content (225 lines) | stat: -rw-r--r-- 7,688 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef GROUNDMOVETYPE_H
#define GROUNDMOVETYPE_H

#include <array>

#include "MoveType.h"
#include "Sim/Path/IPathController.hpp"
#include "System/Sync/SyncedFloat3.h"

struct UnitDef;
struct MoveDef;
class CSolidObject;

class CGroundMoveType : public AMoveType
{
	CR_DECLARE_DERIVED(CGroundMoveType)

public:
	CGroundMoveType(CUnit* owner);
	~CGroundMoveType();

	struct MemberData {
		std::array<std::pair<unsigned int,  bool*>, 3>  bools;
		std::array<std::pair<unsigned int, short*>, 1> shorts;
		std::array<std::pair<unsigned int, float*>, 9> floats;
	};

	void PostLoad();

	bool Update() override;
	void SlowUpdate() override;

	void StartMovingRaw(const float3 moveGoalPos, float moveGoalRadius) override;
	void StartMoving(float3 pos, float moveGoalRadius) override;
	void StartMoving(float3 pos, float moveGoalRadius, float speed) override { StartMoving(pos, moveGoalRadius); }
	void StopMoving(bool callScript = false, bool hardStop = false, bool cancelRaw = false) override;
	bool IsMovingTowards(const float3& pos, float radius, bool checkProgress) const override {
		return (goalPos == pos * XZVector && goalRadius == radius && (!checkProgress || progressState == Active));
	}

	void KeepPointingTo(float3 pos, float distance, bool aggressive) override;
	void KeepPointingTo(CUnit* unit, float distance, bool aggressive) override;

	void TestNewTerrainSquare();
	bool CanApplyImpulse(const float3&) override;
	void LeaveTransport() override;

	void InitMemberPtrs(MemberData* memberData);
	bool SetMemberValue(unsigned int memberHash, void* memberValue) override;

	bool OnSlope(float minSlideTolerance);
	bool IsReversing() const override { return reversing; }
	bool IsPushResistant() const override { return pushResistant; }
	bool WantToStop() const { return (pathID == 0 && (!useRawMovement || atEndOfPath)); }

	void TriggerSkipWayPoint() {
		currWayPoint.y = -1.0f;
		// nextWayPoint.y = -1.0f;
	}
	void TriggerCallArrived() {
		atEndOfPath = true;
		atGoal = true;
	}


	float GetTurnRate() const { return turnRate; }
	float GetTurnSpeed() const { return turnSpeed; }
	float GetTurnAccel() const { return turnAccel; }

	float GetAccRate() const { return accRate; }
	float GetDecRate() const { return decRate; }
	float GetMyGravity() const { return myGravity; }
	float GetOwnerRadius() const { return ownerRadius; }

	float GetMaxReverseSpeed() const { return maxReverseSpeed; }
	float GetWantedSpeed() const { return wantedSpeed; }
	float GetCurrentSpeed() const { return currentSpeed; }
	float GetDeltaSpeed() const { return deltaSpeed; }

	float GetCurrWayPointDist() const { return currWayPointDist; }
	float GetPrevWayPointDist() const { return prevWayPointDist; }
	float GetGoalRadius(float s = 0.0f) const override { return (goalRadius + extraRadius * s); }

	unsigned int GetPathID() const { return pathID; }

	const SyncedFloat3& GetCurrWayPoint() const { return currWayPoint; }
	const SyncedFloat3& GetNextWayPoint() const { return nextWayPoint; }

	const float3& GetFlatFrontDir() const { return flatFrontDir; }
	const float3& GetGroundNormal(const float3&) const;
	float GetGroundHeight(const float3&) const;

private:
	float3 GetObstacleAvoidanceDir(const float3& desiredDir);
	float3 Here() const;

	#define SQUARE(x) ((x) * (x))
	bool StartSkidding(const float3& vel, const float3& dir) const { return ((SQUARE(vel.dot(dir)) + 0.01f) < (vel.SqLength() * sqSkidSpeedMult)); }
	bool StopSkidding(const float3& vel, const float3& dir) const { return ((SQUARE(vel.dot(dir)) + 0.01f) >= (vel.SqLength() * sqSkidSpeedMult)); }
	bool StartFlying(const float3& vel, const float3& dir) const { return (vel.dot(dir) > 0.2f); }
	bool StopFlying(const float3& vel, const float3& dir) const { return (vel.dot(dir) <= 0.2f); }
	#undef SQUARE

	float Distance2D(CSolidObject* object1, CSolidObject* object2, float marginal = 0.0f);

	unsigned int GetNewPath();

	void SetNextWayPoint();
	bool CanSetNextWayPoint();
	void ReRequestPath(bool forceRequest);

	void StartEngine(bool callScript);
	void StopEngine(bool callScript, bool hardStop = false);

	void Arrived(bool callScript);
	void Fail(bool callScript);

	void HandleObjectCollisions();
	bool HandleStaticObjectCollision(
		CUnit* collider,
		CSolidObject* collidee,
		const MoveDef* colliderMD,
		const float colliderRadius,
		const float collideeRadius,
		const float3& separationVector,
		bool canRequestPath,
		bool checkYardMap,
		bool checkTerrain
	);

	void HandleUnitCollisions(
		CUnit* collider,
		const float3& colliderParams,
		const UnitDef* colliderUD,
		const MoveDef* colliderMD
	);
	void HandleFeatureCollisions(
		CUnit* collider,
		const float3& colliderParams,
		const UnitDef* colliderUD,
		const MoveDef* colliderMD
	);

	void SetMainHeading();
	void ChangeSpeed(float, bool, bool = false);
	void ChangeHeading(short newHeading);

	void UpdateSkid();
	void UpdateControlledDrop();
	void CheckCollisionSkid();
	void CalcSkidRot();

	void AdjustPosToWaterLine();
	bool UpdateDirectControl();
	void UpdateOwnerAccelAndHeading();
	void UpdateOwnerPos(const float3&, const float3&);
	bool UpdateOwnerSpeed(float oldSpeedAbs, float newSpeedAbs, float newSpeedRaw);
	bool OwnerMoved(const short, const float3&, const float3&);
	bool FollowPath();
	bool WantReverse(const float3& wpDir, const float3& ffDir) const;

private:
	GMTDefaultPathController pathController;

	SyncedFloat3 currWayPoint;
	SyncedFloat3 nextWayPoint;

	float3 waypointDir;
	float3 flatFrontDir;
	float3 lastAvoidanceDir;
	float3 mainHeadingPos;
	float3 skidRotVector;                   /// vector orthogonal to skidDir

	float turnRate = 0.1f;                  /// maximum angular speed (angular units/frame)
	float turnSpeed = 0.0f;                 /// current angular speed (angular units/frame)
	float turnAccel = 0.0f;                 /// angular acceleration (angular units/frame^2)

	float accRate = 0.01f;
	float decRate = 0.01f;
	float myGravity = 0.0f;

	float maxReverseDist = 0.0f;
	float minReverseAngle = 0.0f;
	float maxReverseSpeed = 0.0f;
	float sqSkidSpeedMult = 0.95f;

	float wantedSpeed = 0.0f;
	float currentSpeed = 0.0f;
	float deltaSpeed = 0.0f;

	float currWayPointDist = 0.0f;
	float prevWayPointDist = 0.0f;

	float goalRadius = 0.0f;                /// original radius passed to StartMoving*
	float ownerRadius = 0.0f;               /// owner MoveDef footprint radius
	float extraRadius = 0.0f;               /// max(0, ownerRadius - goalRadius) if goal-pos is valid, 0 otherwise

	float skidRotSpeed = 0.0f;              /// rotational speed when skidding (radians / (GAME_SPEED frames))
	float skidRotAccel = 0.0f;              /// rotational acceleration when skidding (radians / (GAME_SPEED frames^2))

	unsigned int pathID = 0;
	unsigned int nextObstacleAvoidanceFrame = 0;

	unsigned int numIdlingUpdates = 0;      /// {in, de}creased every Update if idling is true/false and pathId != 0
	unsigned int numIdlingSlowUpdates = 0;  /// {in, de}creased every SlowUpdate if idling is true/false and pathId != 0

	short wantedHeading = 0;
	short minScriptChangeHeading = 0;       /// minimum required turn-angle before script->ChangeHeading is called

	bool atGoal = false;
	bool atEndOfPath = false;
	bool wantRepath = false;

	bool reversing = false;
	bool idling = false;
	bool pushResistant = false;
	bool canReverse = false;
	bool useMainHeading = false;            /// if true, turn toward mainHeadingPos until weapons[0] can TryTarget() it
	bool useRawMovement = false;            /// if true, move towards goal without invoking PFS (unrelated to MoveDef::allowRawMovement)
};

#endif // GROUNDMOVETYPE_H