1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef WEAPON_H
4 #define WEAPON_H
5 
6 #include <map>
7 
8 #include "System/Object.h"
9 #include "Sim/Misc/DamageArray.h"
10 #include "Sim/Projectiles/ProjectileParams.h"
11 #include "System/float3.h"
12 
13 class CUnit;
14 class CWeaponProjectile;
15 struct WeaponDef;
16 
17 enum TargetType {
18 	Target_None,
19 	Target_Unit,
20 	Target_Pos,
21 	Target_Intercept
22 };
23 
24 class CWeapon : public CObject
25 {
26 	CR_DECLARE(CWeapon)
27 public:
28 	CWeapon(CUnit* owner, const WeaponDef* def);
29 	virtual ~CWeapon();
30 	virtual void Init();
31 
32 	void SetWeaponNum(int);
33 
34 	void DependentDied(CObject* o);
35 
36 
37 	bool CheckTargetAngleConstraint(const float3& worldTargetDir, const float3& worldWeaponDir) const;
38 	bool SetTargetBorderPos(CUnit*, float3&, float3&, float3&);
39 	bool GetTargetBorderPos(const CUnit*, const float3&, float3&, float3&) const;
40 
41 	void AdjustTargetPosToWater(float3& tgtPos, bool attackGround) const;
42 
43 	/// test if the weapon is able to attack an enemy/mapspot just by its properties (no range check, no FreeLineOfFire check, ...)
44 	virtual bool TestTarget(const float3& pos, bool userTarget, const CUnit* unit) const;
45 	/// test if the enemy/mapspot is in range/angle
46 	virtual bool TestRange(const float3& pos, bool userTarget, const CUnit* unit) const;
47 	/// test if something is blocking our LineOfFire
48 	virtual bool HaveFreeLineOfFire(const float3& pos, bool userTarget, const CUnit* unit) const;
49 
50 	virtual bool CanFire(bool ignoreAngleGood, bool ignoreTargetType, bool ignoreRequestedDir) const;
51 
52 	bool TryTarget(const float3& pos, bool userTarget, const CUnit* unit) const;
53 	bool TryTarget(const CUnit* unit, bool userTarget) const;
54 	bool TryTargetRotate(CUnit* unit, bool userTarget);
55 	bool TryTargetRotate(float3 pos, bool userTarget);
56 	bool TryTargetHeading(short heading, float3 pos, bool userTarget, CUnit* unit = 0);
57 
58 	float3 GetUnitPositionWithError( const CUnit* unit ) const;
59 
60 	bool CobBlockShot(const CUnit* unit);
61 	float TargetWeight(const CUnit* unit) const;
62 	void SlowUpdate(bool noAutoTargetOverride);
63 
64 	virtual void SlowUpdate();
65 	virtual void Update();
66 	virtual float GetRange2D(float yDiff) const;
UpdateRange(float val)67 	virtual void UpdateRange(float val) { range = val; }
68 
69 	virtual bool AttackUnit(CUnit* newTargetUnit, bool isUserTarget);
70 	virtual bool AttackGround(float3 newTargetPos, bool isUserTarget);
71 
72 	void AutoTarget();
73 	void AimReady(int value);
74 	void Fire(bool scriptCall);
75 	void HoldFire();
76 
77 	float ExperienceErrorScale() const;
78 	float MoveErrorExperience() const;
AccuracyExperience()79 	float AccuracyExperience() const { return (accuracyError * ExperienceErrorScale()); }
SprayAngleExperience()80 	float SprayAngleExperience() const { return (sprayAngle * ExperienceErrorScale()); }
SalvoErrorExperience()81 	float3 SalvoErrorExperience() const { return (salvoError * ExperienceErrorScale()); }
82 
83 	void StopAttackingAllyTeam(int ally);
84 	void UpdateInterceptTarget();
85 
86 protected:
FireImpl(bool scriptCall)87 	virtual void FireImpl(bool scriptCall) {}
88 
89 	void UpdateTargeting();
90 	void UpdateFire();
91 	bool UpdateStockpile();
92 	void UpdateSalvo();
93 
94 	static bool TargetUnitOrPositionUnderWater(const float3& targetPos, const CUnit* targetUnit, float offset = 0.0f);
95 	static bool TargetUnitOrPositionInWater(const float3& targetPos, const CUnit* targetUnit, float offset = 0.0f);
96 
97 protected:
98 	ProjectileParams GetProjectileParams();
99 
100 private:
101 	inline bool AllowWeaponTargetCheck();
102 
103 	void UpdateRelWeaponPos();
104 
105 public:
106 	CUnit* owner;
107 
108 	const WeaponDef* weaponDef;
109 
110 	int weaponNum;							// the weapons order among the owner weapons
111 	bool haveUserTarget;
112 
113 	float craterAreaOfEffect;
114 	float damageAreaOfEffect;
115 
116 	float muzzleFlareSize;					// size of muzzle flare if drawn
117 	int useWeaponPosForAim;					// sometimes weapon pos is better to use than aimpos
118 	bool hasCloseTarget;					// might need to update weapon pos more often when enemy is near
119 
120 	int reloadTime;							// time between succesive fires in ticks
121 	int reloadStatus;						// next tick the weapon can fire again
122 
123 	float range;
124 	float heightMod;						// how much extra range the weapon gain per height difference
125 
126 	float projectileSpeed;
127 	float accuracyError;					// inaccuracy of whole salvo
128 	float sprayAngle;						// inaccuracy of individual shots inside salvo
129 
130 	int salvoDelay;							// delay between shots in a salvo
131 	int salvoSize;							// number of shots in a salvo
132 	int projectilesPerShot;					// number of projectiles per shot
133 	int nextSalvo;							// when the next shot in the current salvo will fire
134 	int salvoLeft;							// number of shots left in current salvo
135 
136 	TargetType targetType;					// indicated if we have a target and what type
137 	CUnit* targetUnit;						// the targeted unit if targettype=unit
138 
139 	float predict;							// how long time we predict it take for a projectile to reach target
140 	float predictSpeedMod;					// how the weapon predicts the speed of the units goes -> 1 when experience increases
141 
142 	float metalFireCost;
143 	float energyFireCost;
144 
145 	int fireSoundId;
146 	float fireSoundVolume;
147 
148 	bool hasBlockShot;						// set when the script has a BlockShot() function for this weapon
149 	bool hasTargetWeight;					// set when there's a TargetWeight() function for this weapon
150 	bool angleGood;							// set when script indicated ready to fire
151 	bool avoidTarget;						// set when the script wants the weapon to pick a new target, reset once one has been chosen
152 	bool onlyForward;						// can only fire in the forward direction of the unit (for aircrafts mostly?)
153 
154 	unsigned int badTargetCategory;			// targets in this category get a lot lower targetting priority
155 	unsigned int onlyTargetCategory;		// only targets in this category can be targeted (default 0xffffffff)
156 
157 	// projectiles that are on the way to our interception zone
158 	// (eg. nuke toward a repulsor, or missile toward a shield)
159 	std::map<int, CWeaponProjectile*> incomingProjectiles;
160 	// projectile that we currently target for interception
161 	CWeaponProjectile* interceptTarget;
162 
163 	int stockpileTime;            // how long it takes to stockpile 1 missile
164 	float buildPercent;           // how far we have come on building current missile if stockpiling
165 	int numStockpiled;            // how many missiles we have stockpiled
166 	int numStockpileQued;         // how many weapons the user have added to our que
167 
168 	int lastRequest;              // when the last script call was done
169 	int lastTargetRetry;          // when we last recalculated target selection
170 	int lastErrorVectorUpdate;
171 
172 	CWeapon* slavedTo;            // use this weapon to choose target
173 
174 	float maxForwardAngleDif;     // for onlyForward/!turret weapons, max. angle between owner->frontdir and (targetPos - owner->pos) (derived from UnitDefWeapon::maxAngleDif)
175 	float maxMainDirAngleDif;     // for !onlyForward/turret weapons, max. angle from <mainDir> the weapon can aim (derived from WeaponDef::tolerance)
176 
177 	float targetBorder;           // if nonzero, units will TryTarget wrt. edge of scaled collision volume instead of centre
178 	float cylinderTargeting;      // if greater than 0, range will be checked in a cylinder (height=range*cylinderTargeting) instead of a sphere
179 	float minIntensity;           // for beamlasers - always hit with some minimum intensity (a damage coeffcient normally dependent on distance). do not confuse with intensity tag, it's completely unrelated.
180 	float heightBoostFactor;      // controls cannon range height boost. default: -1 -- automatically calculate a more or less sane value
181 
182 	unsigned int avoidFlags;
183 	unsigned int collisionFlags;
184 
185 	float fuelUsage;
186 
187 	float3 relWeaponPos;          // weaponpos relative to the unit
188 	float3 weaponPos;             // absolute weapon pos
189 	float3 relWeaponMuzzlePos;    // position of the firepoint
190 	float3 weaponMuzzlePos;
191 	float3 weaponDir;
192 	float3 mainDir;               // main aiming-direction of weapon
193 	float3 wantedDir;             // the angle we want to aim in, set by the weapon subclass
194 	float3 lastRequestedDir;      // last angle we called the script with
195 	float3 salvoError;            // error vector for the whole salvo
196 	float3 errorVector;
197 	float3 errorVectorAdd;
198 
199 	float3 targetPos;             // the position of the target (even if targettype=unit)
200 	float3 targetBorderPos;       // <targetPos> adjusted for target-border factor
201 };
202 
203 #endif /* WEAPON_H */
204