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