File: Weapon.h

package info (click to toggle)
spring 106.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,316 kB
  • sloc: cpp: 543,954; 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 (209 lines) | stat: -rw-r--r-- 9,269 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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef WEAPON_H
#define WEAPON_H

#include <functional>
#include <vector>

#include "System/Object.h"
#include "Sim/Misc/DamageArray.h"
#include "Sim/Projectiles/ProjectileParams.h"
#include "Sim/Weapons/WeaponTarget.h"
#include "System/float3.h"

class CUnit;
class CWeaponProjectile;
struct WeaponDef;


class CWeapon : public CObject
{
	CR_DECLARE_DERIVED(CWeapon)

public:
	CWeapon(CUnit* owner = nullptr, const WeaponDef* def = nullptr);
	virtual ~CWeapon();
	virtual void Init();

	void SetWeaponNum(int num) { weaponNum = num; }
	void DependentDied(CObject* o) override;
	virtual void SlowUpdate();
	virtual void Update();

public:
	bool Attack(const SWeaponTarget& newTarget);
	void SetAttackTarget(const SWeaponTarget& newTarget); //< does no validity checks!
	void DropCurrentTarget();
	void AimScriptFinished(bool retCode) { angleGood = retCode; }

	bool HaveTarget() const { return (currentTarget.type != Target_None); }
	bool HaveUnitTarget() const { return (currentTarget.type == Target_Unit); }
	bool HavePosTarget() const { return (currentTarget.type == Target_Pos); }

	const SWeaponTarget& GetCurrentTarget() const { return currentTarget; }
	const float3& GetCurrentTargetPos() const { return currentTargetPos; }

	virtual const float3& GetAimFromPos(bool useMuzzle = false) const { return (useMuzzle? weaponMuzzlePos: aimFromPos); }

	bool HasIncomingProjectile(int projID) const { return (std::find(incomingProjectileIDs.begin(), incomingProjectileIDs.end(), projID) != incomingProjectileIDs.end()); }
	void AddIncomingProjectile(int projID) { incomingProjectileIDs.push_back(projID); }

public:
	/// test if the weapon is able to attack an enemy/mapspot just by its properties (no range check, no FreeLineOfFire check, ...)
	virtual bool TestTarget(const float3 tgtPos, const SWeaponTarget& trg) const;
	/// test if the enemy/mapspot is in range/angle
	virtual bool TestRange(const float3 tgtPos, const SWeaponTarget& trg) const;
	/// test if something is blocking our LineOfFire
	virtual bool HaveFreeLineOfFire(const float3 srcPos, const float3 tgtPos, const SWeaponTarget& trg) const;

	virtual bool CanFire(bool ignoreAngleGood, bool ignoreTargetType, bool ignoreRequestedDir) const;

	bool TryTarget(const SWeaponTarget& trg) const;
	bool TryTargetRotate(const CUnit* unit, bool userTarget, bool manualFire);
	bool TryTargetRotate(float3 tgtPos, bool userTarget, bool manualFire);
	bool TryTargetHeading(short heading, const SWeaponTarget& trg);

public:
	bool CheckTargetAngleConstraint(const float3 worldTargetDir, const float3 worldWeaponDir) const;
	float3 GetTargetBorderPos(const CUnit* targetUnit, const float3 rawTargetPos, const float3 rawTargetDir) const;

	void AdjustTargetPosToWater(float3& tgtPos, bool attackGround) const;
	float3 GetUnitPositionWithError(const CUnit* unit) const;
	float3 GetUnitLeadTargetPos(const CUnit* unit) const;
	float3 GetLeadTargetPos(const SWeaponTarget& target) const;

	float TargetWeight(const CUnit* unit) const;

	static float GetStaticRange2D(const CWeapon* w, const WeaponDef* wd, float modHeightDiff, float modProjGravity);
	static float GetLiveRange2D(const CWeapon* w, const WeaponDef* wd, float modHeightDiff, float modProjGravity) { return (w->GetRange2D(0.0f, modHeightDiff)); }

	virtual float GetRange2D(float boost, float ydiff) const;
	virtual void UpdateProjectileSpeed(const float val) { projectileSpeed = val; }
	virtual void UpdateRange(const float val) { range = val; }

	bool AutoTarget();
	void AimReady(const int value);
	void Fire(const bool scriptCall);

	float ExperienceErrorScale() const;
	float MoveErrorExperience() const;
	float AccuracyExperience() const { return (accuracyError * ExperienceErrorScale()); }
	float SprayAngleExperience() const { return (sprayAngle * ExperienceErrorScale()); }
	float3 SalvoErrorExperience() const { return (salvoError * ExperienceErrorScale()); }

	bool StopAttackingTargetIf(const std::function<bool(const SWeaponTarget&)>& pred);
	bool StopAttackingAllyTeam(const int ally);

protected:
	virtual void FireImpl(const bool scriptCall) {}
	virtual void UpdateWantedDir();
	virtual float GetPredictedImpactTime(float3 p) const; //< how long time we predict it take for a projectile to reach target

	ProjectileParams GetProjectileParams();
	static bool TargetUnderWater(const float3 tgtPos, const SWeaponTarget&);
	static bool TargetInWater(const float3 tgtPos, const SWeaponTarget&);

	void UpdateWeaponPieces(const bool updateAimFrom = true);
	void UpdateWeaponVectors();
	float3 GetLeadVec(const CUnit* unit) const;

private:
	void UpdateAim();
	void UpdateFire();
	bool UpdateStockpile();
	void UpdateSalvo();

	void UpdateInterceptTarget();
	bool AllowWeaponAutoTarget() const;
	bool CobBlockShot() const;
	bool CheckAimingAngle() const;
	bool CanCallAimingScript(bool validAngle) const;
	bool CallAimingScript(bool waitForAim);
	void HoldIfTargetInvalid();

	bool TryTarget(const float3 tgtPos, const SWeaponTarget& trg, bool preFire = false) const;

public:
	CUnit* owner;
	CWeapon* slavedTo;                      // use this weapon to choose target

	const WeaponDef* weaponDef;

	const DynDamageArray* damages;

	int weaponNum;                          // ordering among owner's weapons

	int aimFromPiece;
	int muzzlePiece;

	int reaimTime;                          // time between successive reaims in ticks

	int reloadTime;                         // time between successive fires in ticks
	int reloadStatus;                       // next tick the weapon can fire again

	int salvoDelay;                         // delay between shots in a salvo
	int salvoSize;                          // number of shots in a salvo
	int projectilesPerShot;                 // number of projectiles per shot
	int nextSalvo;                          // when the next shot in the current salvo will fire
	int salvoLeft;                          // number of shots left in current salvo

	float range;
	float projectileSpeed;
	float accuracyError;                    // inaccuracy of whole salvo
	float sprayAngle;                       // inaccuracy of individual shots inside salvo
	float predictSpeedMod;                  // how the weapon predicts the speed of the units goes -> 1 when experience increases

	bool hasBlockShot;                      // set when the script has a BlockShot() function for this weapon
	bool hasTargetWeight;                   // set when there's a TargetWeight() function for this weapon
	bool angleGood;                         // set when script indicated ready to fire
	bool avoidTarget;                       // set when the script wants the weapon to pick a new target, reset once one has been chosen
	bool onlyForward;                       // can only fire in the forward direction of the unit (for aircrafts mostly?)
	bool doTargetGroundPos;                 // (used for bombers) target the ground pos under the unit instead of the center aimPos
	bool noAutoTarget;
	bool alreadyWarnedAboutMissingPieces;

	unsigned int badTargetCategory;         // targets in this category get a lot lower targetting priority
	unsigned int onlyTargetCategory;        // only targets in this category can be targeted (default 0xffffffff)

	float buildPercent;                     // how far we have come on building current missile if stockpiling
	int numStockpiled;                      // how many missiles we have stockpiled
	int numStockpileQued;                   // how many weapons the user have added to our que

	int lastAimedFrame;                     // when the last AimWeapon script callin was performed
	int lastTargetRetry;                    // when we last recalculated target selection

	float maxForwardAngleDif;               // for onlyForward/!turret weapons, max. angle between owner->frontdir and (targetPos - owner->pos) (derived from UnitDefWeapon::maxAngleDif)
	float maxMainDirAngleDif;               // for !onlyForward/turret weapons, max. angle from <mainDir> the weapon can aim (derived from WeaponDef::tolerance)

	float heightBoostFactor;                // controls cannon range height boost. default: -1 -- automatically calculate a more or less sane value
	float autoTargetRangeBoost;

	unsigned int avoidFlags;
	unsigned int collisionFlags;

	float3 relAimFromPos;                   // aimFromPos relative to the unit
	float3 aimFromPos;                      // absolute weapon pos
	float3 relWeaponMuzzlePos;              // position of the firepoint
	float3 weaponMuzzlePos;
	float3 weaponDir;
	float3 mainDir;                         // main aiming-direction of weapon
	float3 wantedDir;                       // norm(currentTargetPos - weaponMuzzlePos)
	float3 lastRequestedDir;                // last angle we called the script with

	float3 salvoError;                      // error vector for the whole salvo
	float3 errorVector;
	float3 errorVectorAdd;

	float muzzleFlareSize;                  // size of muzzle flare if drawn

protected:
	SWeaponTarget currentTarget;
	float3 currentTargetPos;

	// projectiles that are on the way to our interception zone
	// (eg. nuke toward a repulsor, or missile toward a shield)
	std::vector<int> incomingProjectileIDs;
};

#endif /* WEAPON_H */