1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef UNIT_H
4 #define UNIT_H
5 
6 #include <map>
7 #include <list>
8 #include <vector>
9 #include <string>
10 
11 #include "Lua/LuaRulesParams.h"
12 #include "Lua/LuaUnitMaterial.h"
13 #include "Sim/Objects/SolidObject.h"
14 #include "System/Matrix44f.h"
15 #include "System/type2.h"
16 
17 class CPlayer;
18 class CCommandAI;
19 class CGroup;
20 class CMissileProjectile;
21 class AMoveType;
22 class CWeapon;
23 class CUnitScript;
24 struct DamageArray;
25 struct LosInstance;
26 struct LocalModel;
27 struct LocalModelPiece;
28 struct UnitDef;
29 struct UnitTrackStruct;
30 struct UnitLoadParams;
31 
32 namespace icon {
33 	class CIconData;
34 }
35 
36 class CTransportUnit;
37 
38 
39 // LOS state bits
40 #define LOS_INLOS      (1 << 0)  // the unit is currently in the los of the allyteam
41 #define LOS_INRADAR    (1 << 1)  // the unit is currently in radar from the allyteam
42 #define LOS_PREVLOS    (1 << 2)  // the unit has previously been in los from the allyteam
43 #define LOS_CONTRADAR  (1 << 3)  // the unit has continuously been in radar since it was last inlos by the allyteam
44 
45 // LOS mask bits  (masked bits are not automatically updated)
46 #define LOS_INLOS_MASK     (1 << 8)   // do not update LOS_INLOS
47 #define LOS_INRADAR_MASK   (1 << 9)   // do not update LOS_INRADAR
48 #define LOS_PREVLOS_MASK   (1 << 10)  // do not update LOS_PREVLOS
49 #define LOS_CONTRADAR_MASK (1 << 11)  // do not update LOS_CONTRADAR
50 
51 #define LOS_ALL_MASK_BITS \
52 	(LOS_INLOS_MASK | LOS_INRADAR_MASK | LOS_PREVLOS_MASK | LOS_CONTRADAR_MASK)
53 
54 enum ScriptCloakBits { // FIXME -- not implemented
55 	// always set to 0 if not enabled
56 	SCRIPT_CLOAK_ENABLED          = (1 << 0),
57 	SCRIPT_CLOAK_IGNORE_ENERGY    = (1 << 1),
58 	SCRIPT_CLOAK_IGNORE_STUNNED   = (1 << 2),
59 	SCRIPT_CLOAK_IGNORE_PROXIMITY = (1 << 3),
60 	SCRIPT_CLOAK_IGNORE_BUILDING  = (1 << 4),
61 	SCRIPT_CLOAK_IGNORE_RECLAIM   = (1 << 5),
62 	SCRIPT_CLOAK_IGNORE_CAPTURING = (1 << 6),
63 	SCRIPT_CLOAK_IGNORE_TERRAFORM = (1 << 7)
64 };
65 
66 
67 class CUnit : public CSolidObject
68 {
69 public:
70 	CR_DECLARE(CUnit)
71 
72 	CUnit();
73 	virtual ~CUnit();
74 
75 	virtual void PreInit(const UnitLoadParams& params);
76 	virtual void PostInit(const CUnit* builder);
77 
78 	virtual void SlowUpdate();
79 	virtual void SlowUpdateWeapons();
80 	virtual void Update();
81 
82 	virtual void DoDamage(const DamageArray& damages, const float3& impulse, CUnit* attacker, int weaponDefID, int projectileID);
83 	virtual void DoWaterDamage();
84 	virtual void FinishedBuilding(bool postInit);
85 
86 	void ApplyImpulse(const float3& impulse);
87 
88 	bool AttackUnit(CUnit* unit, bool isUserTarget, bool wantManualFire, bool fpsMode = false);
89 	bool AttackGround(const float3& pos, bool isUserTarget, bool wantManualFire, bool fpsMode = false);
90 
GetBlockingMapID()91 	int GetBlockingMapID() const { return id; }
92 
93 	void ChangeLos(int losRad, int airRad);
94 	void ChangeSensorRadius(int* valuePtr, int newValue);
95 	/// negative amount=reclaim, return= true -> build power was successfully applied
96 	bool AddBuildPower(CUnit* builder, float amount);
97 	/// turn the unit on
98 	void Activate();
99 	/// turn the unit off
100 	void Deactivate();
101 
102 	void ForcedMove(const float3& newPos);
103 
104 	void EnableScriptMoveType();
105 	void DisableScriptMoveType();
106 
107 	CMatrix44f GetTransformMatrix(const bool synced = false, const bool error = false) const;
108 
109 	const CollisionVolume* GetCollisionVolume(const LocalModelPiece* lmp) const;
110 
111 	void SetLastAttacker(CUnit* attacker);
SetLastAttackedPiece(LocalModelPiece * p,int f)112 	void SetLastAttackedPiece(LocalModelPiece* p, int f) {
113 		lastAttackedPiece      = p;
114 		lastAttackedPieceFrame = f;
115 	}
GetLastAttackedPiece(int f)116 	LocalModelPiece* GetLastAttackedPiece(int f) const {
117 		if (lastAttackedPieceFrame == f)
118 			return lastAttackedPiece;
119 		return NULL;
120 	}
121 
122 
123 	void DependentDied(CObject* o);
124 
125 	bool SetGroup(CGroup* group, bool fromFactory = false);
126 
127 	bool AllowedReclaim(CUnit* builder) const;
128 	bool UseMetal(float metal);
129 	void AddMetal(float metal, bool useIncomeMultiplier = true);
130 	bool UseEnergy(float energy);
131 	void AddEnergy(float energy, bool useIncomeMultiplier = true);
132 	bool AddHarvestedMetal(float metal);
133 
134 	/// push the new wind to the script
135 	void UpdateWind(float x, float z, float strength);
136 	void SetMetalStorage(float newStorage);
137 	void SetEnergyStorage(float newStorage);
138 
139 	void AddExperience(float exp);
140 
141 	void DoSeismicPing(float pingSize);
142 
143 	void CalculateTerrainType();
144 	void UpdateTerrainType();
145 	void UpdatePhysicalState(float eps);
146 
147 	float3 GetErrorVector(int allyteam) const;
148 	float3 GetErrorPos(int allyteam, bool aiming = false) const { return (aiming? aimPos: midPos) + GetErrorVector(allyteam); }
GetDrawErrorPos(int allyteam)149 	float3 GetDrawErrorPos(int allyteam) const { return (drawMidPos + GetErrorVector(allyteam)); }
150 	void UpdatePosErrorParams(bool updateError, bool updateDelta);
151 
UsingScriptMoveType()152 	bool UsingScriptMoveType() const { return (prevMoveType != NULL); }
UnderFirstPersonControl()153 	bool UnderFirstPersonControl() const { return (fpsControlPlayer != NULL); }
154 
IsNeutral()155 	bool IsNeutral() const { return neutral; }
IsCloaked()156 	bool IsCloaked() const { return isCloaked; }
157 	bool IsIdle() const;
158 
159 	void SetStunned(bool stun);
IsStunned()160 	bool IsStunned() const { return stunned; }
161 
162 	void SetLosStatus(int allyTeam, unsigned short newStatus);
163 	unsigned short CalcLosStatus(int allyTeam);
164 
165 	void SlowUpdateCloak(bool);
166 	void ScriptDecloak(bool);
167 	bool GetNewCloakState(bool checkStun);
168 
169 	enum ChangeType {
170 		ChangeGiven,
171 		ChangeCaptured
172 	};
173 	virtual bool ChangeTeam(int team, ChangeType type);
174 	virtual void StopAttackingAllyTeam(int ally);
175 
SetTransporter(CTransportUnit * trans)176 	void SetTransporter(CTransportUnit* trans) { transporter = trans; }
GetTransporter()177 	inline CTransportUnit* GetTransporter() const {
178 		return transporter;
179 	}
180 
181 public:
182 	virtual void KillUnit(CUnit* attacker, bool selfDestruct, bool reclaimed, bool showDeathSequence = true);
183 	virtual void IncomingMissile(CMissileProjectile* missile);
184 
185 	void TempHoldFire(int cmdID);
ReleaseTempHoldFire()186 	void ReleaseTempHoldFire() { dontFire = false; }
187 
188 	/// start this unit in free fall from parent unit
189 	void Drop(const float3& parentPos, const float3& parentDir, CUnit* parent);
190 	void PostLoad();
191 
192 protected:
193 	void ChangeTeamReset();
194 	void UpdateResources();
195 	void UpdateLosStatus(int allyTeam);
196 	float GetFlankingDamageBonus(const float3& attackDir);
197 
198 public:
SetExpMultiplier(float value)199 	static void  SetExpMultiplier(float value) { expMultiplier = value; }
SetExpPowerScale(float value)200 	static void  SetExpPowerScale(float value) { expPowerScale = value; }
SetExpHealthScale(float value)201 	static void  SetExpHealthScale(float value) { expHealthScale = value; }
SetExpReloadScale(float value)202 	static void  SetExpReloadScale(float value) { expReloadScale = value; }
SetExpGrade(float value)203 	static void  SetExpGrade(float value) { expGrade = value; }
204 
GetExpMultiplier()205 	static float GetExpMultiplier() { return expMultiplier; }
GetExpPowerScale()206 	static float GetExpPowerScale() { return expPowerScale; }
GetExpHealthScale()207 	static float GetExpHealthScale() { return expHealthScale; }
GetExpReloadScale()208 	static float GetExpReloadScale() { return expReloadScale; }
GetExpGrade()209 	static float GetExpGrade() { return expGrade; }
210 
ExperienceScale(const float limExperience,const float experienceWeight)211 	static float ExperienceScale(const float limExperience, const float experienceWeight) {
212 		// limExperience ranges from 0.0 to 0.9999..., experienceWeight
213 		// should be in [0, 1] and have no effect on accuracy when zero
214 		return (1.0f - (limExperience * experienceWeight));
215 	}
216 
SetSpawnFeature(bool b)217 	static void SetSpawnFeature(bool b) { spawnFeature = b; }
218 
219 public:
220 	const UnitDef* unitDef;
221 
222 	CUnit* soloBuilder;
223 	/// last attacker
224 	CUnit* lastAttacker;
225 	/// current attackee
226 	CUnit* attackTarget;
227 
228 	/// transport that the unit is currently in
229 	CTransportUnit* transporter;
230 
231 	AMoveType* moveType;
232 	AMoveType* prevMoveType;
233 
234 	CCommandAI* commandAI;
235 	/// if the unit is part of an group (hotkey group)
236 	CGroup* group;
237 
238 	/// Our shield weapon, NULL if we have none
239 	CWeapon* shieldWeapon;
240 	/// Our weapon with stockpiled ammo, NULL if we have none
241 	CWeapon* stockpileWeapon;
242 
243 	LocalModel* localModel;
244 	CUnitScript* script;
245 
246 	/// piece that was last hit by a projectile
247 	LocalModelPiece* lastAttackedPiece;
248 
249 	/// which squares the unit can currently observe
250 	LosInstance* los;
251 
252 	/// player who is currently FPS'ing this unit
253 	CPlayer* fpsControlPlayer;
254 
255 	UnitTrackStruct* myTrack;
256 	icon::CIconData* myIcon;
257 
258 
259 	std::vector<CWeapon*> weapons;
260 	/// quads the unit is part of
261 	std::vector<int> quads;
262 	std::vector<int> radarSquares;
263 
264 	/// indicate the los/radar status the allyteam has on this unit
265 	std::vector<unsigned short> losStatus;
266 
267 	/// length-per-pixel (UNSYNCED)
268 	std::vector<float> lodLengths;
269 
270 	std::list<CMissileProjectile*> incomingMissiles; //FIXME make std::set?
271 
272 
273 	float3 attackPos;
274 	float3 deathSpeed;
275 	float3 lastMuzzleFlameDir;
276 
277 	/// units takes less damage when attacked from this dir (encourage flanking fire)
278 	float3 flankingBonusDir;
279 
280 	/// used for innacuracy with radars etc
281 	float3 posErrorVector;
282 	float3 posErrorDelta;
283 
284 
285 	int unitDefID;
286 	int featureDefID; // FeatureDef id of the wreck we spawn on death
287 
288 	/**
289 	 * @brief mod controlled parameters
290 	 * This is a set of parameters that is initialized
291 	 * in CreateUnitRulesParams() and may change during the game.
292 	 * Each parameter is uniquely identified only by its id
293 	 * (which is the index in the vector).
294 	 * Parameters may or may not have a name.
295 	 */
296 	LuaRulesParams::Params  modParams;
297 	LuaRulesParams::HashMap modParamsMap; ///< name map for mod parameters
298 
299 	/// if the updir is straight up or align to the ground vector
300 	bool upright;
301 
302 	/// total distance the unit has moved
303 	float travel;
304 	/// 0.0f disables travel accumulation
305 	float travelPeriod;
306 
307 	/// indicate the relative power of the unit, used for experience calulations etc
308 	float power;
309 
310 	float maxHealth;
311 	/// if health-this is negative the unit is stunned
312 	float paralyzeDamage;
313 	/// how close this unit is to being captured
314 	float captureProgress;
315 	float experience;
316 	/// goes ->1 as experience go -> infinite
317 	float limExperience;
318 
319 	/**
320 	 * neutral allegiance, will not be automatically
321 	 * fired upon unless the fireState is set to >
322 	 * FIRESTATE_FIREATWILL
323 	 */
324 	bool neutral;
325 	bool beingBuilt;
326 
327 	/// if we arent built on for a while start decaying
328 	int lastNanoAdd;
329 	int lastFlareDrop;
330 
331 	/// How much reapir power has been added to this recently
332 	float repairAmount;
333 
334 	/// id of transport that the unit is about to be picked up by
335 	int loadingTransportId;
336 	/// 0.0-1.0
337 	float buildProgress;
338 	/// whether the ground below this unit has been terraformed
339 	bool groundLevelled;
340 	/// how much terraforming is left to do
341 	float terraformLeft;
342 	/// set los to this when finished building
343 	int realLosRadius;
344 	int realAirLosRadius;
345 
346 	/// used by constructing units
347 	bool inBuildStance;
348 	/// tells weapons that support it to try to use a high trajectory
349 	bool useHighTrajectory;
350 
351 	/// used by landed gunships to block weapon Update()'s
352 	bool dontUseWeapons;
353 	/// used by builders to prevent weapon SlowUpdate()'s and Attack{Unit,Ground}()'s
354 	bool dontFire;
355 
356 	/// the script has finished exectuting the killed function and the unit can be deleted
357 	bool deathScriptFinished;
358 	/// the wreck level the unit will eventually create when it has died
359 	int delayedWreckLevel;
360 
361 	/// how long the unit has been inactive
362 	unsigned int restTime;
363 	unsigned int outOfMapTime;
364 
365 	float reloadSpeed;
366 	float maxRange;
367 
368 	/// true if at least one weapon has targetType != Target_None
369 	bool haveTarget;
370 	bool haveManualFireRequest;
371 
372 	/// used to determine muzzle flare size
373 	float lastMuzzleFlameSize;
374 
375 	int armorType;
376 	/// what categories the unit is part of (bitfield)
377 	unsigned int category;
378 
379 	int mapSquare;
380 
381 	int losRadius;
382 	int airLosRadius;
383 	int lastLosUpdate;
384 
385 	float losHeight;
386 	float radarHeight;
387 
388 	int radarRadius;
389 	int sonarRadius;
390 	int jammerRadius;
391 	int sonarJamRadius;
392 	int seismicRadius;
393 	float seismicSignature;
394 	bool hasRadarCapacity;
395 	int2 oldRadarPos;
396 	bool hasRadarPos;
397 	bool stealth;
398 	bool sonarStealth;
399 
400 	// only when the unit is active
401 	float condUseMetal;
402 	float condUseEnergy;
403 	float condMakeMetal;
404 	float condMakeEnergy;
405 	// always applied
406 	float uncondUseMetal;
407 	float uncondUseEnergy;
408 	float uncondMakeMetal;
409 	float uncondMakeEnergy;
410 
411 	/// cost per 16 frames
412 	float metalUse;
413 	/// cost per 16 frames
414 	float energyUse;
415 	/// metal income generated by unit
416 	float metalMake;
417 	/// energy income generated by unit
418 	float energyMake;
419 
420 	// variables used for calculating unit resource usage
421 	float metalUseI;
422 	float energyUseI;
423 	float metalMakeI;
424 	float energyMakeI;
425 	float metalUseold;
426 	float energyUseold;
427 	float metalMakeold;
428 	float energyMakeold;
429 	/// energy added each halftick
430 	float energyTickMake;
431 
432 	/// how much metal the unit currently extracts from the ground
433 	float metalExtract;
434 
435 	float metalCost;
436 	float energyCost;
437 	float buildTime;
438 
439 	float metalStorage;
440 	float energyStorage;
441 	/// per unit metal storage (gets filled on reclaim and needs then to be unloaded at some storage building -> 2nd part is lua's job)
442 	float harvestStorage;
443 
444 	/// frame in which lastAttackedPiece was hit
445 	int lastAttackedPieceFrame;
446 	/// last frame unit was attacked by other unit
447 	int lastAttackFrame;
448 	/// last time this unit fired a weapon
449 	int lastFireWeapon;
450 
451 	/// decaying value of how much damage the unit has taken recently (for severity of death)
452 	float recentDamage;
453 
454 	bool userAttackGround;
455 
456 	int fireState;
457 	int moveState;
458 
459 	/// if the unit is in it's 'on'-state
460 	bool activated;
461 	/// prevent damage from hitting an already dead unit (causing multi wreck etc)
462 	bool isDead;
463 
464 	/// for units being dropped from transports (parachute drops)
465 	float fallSpeed;
466 
467 	/**
468 	 * 0 = no flanking bonus
469 	 * 1 = global coords, mobile
470 	 * 2 = unit coords, mobile
471 	 * 3 = unit coords, locked
472 	 */
473 	int flankingBonusMode;
474 	/// how much the lowest damage direction of the flanking bonus can turn upon an attack (zeroed when attacked, slowly increases)
475 	float  flankingBonusMobility;
476 	/// how much ability of the flanking bonus direction to move builds up each frame
477 	float  flankingBonusMobilityAdd;
478 	/// average factor to multiply damage by
479 	float  flankingBonusAvgDamage;
480 	/// (max damage - min damage) / 2
481 	float  flankingBonusDifDamage;
482 
483 	bool armoredState;
484 	float armoredMultiple;
485 	/// multiply all damage the unit take with this
486 	float curArmorMultiple;
487 
488 	int	nextPosErrorUpdate;
489 
490 	/// true if the unit currently wants to be cloaked
491 	bool wantCloak;
492 	/// true if a script currently wants the unit to be cloaked
493 	int scriptCloak;
494 	/// the minimum time between decloaking and cloaking again
495 	int cloakTimeout;
496 	/// the earliest frame the unit can cloak again
497 	int curCloakTimeout;
498 	///true if the unit is currently cloaked (has enough energy etc)
499 	bool isCloaked;
500 	float decloakDistance;
501 
502 	int lastTerrainType;
503 	/// Used for calling setSFXoccupy which TA scripts want
504 	int curTerrainType;
505 
506 	int selfDCountdown;
507 
508 	float currentFuel;
509 
510 	/// minimum alpha value for a texel to be drawn
511 	float alphaThreshold;
512 	/// the damage value passed to CEGs spawned by this unit's script
513 	int cegDamage;
514 
515 
516 	// unsynced vars
517 	bool noDraw;
518 	bool noMinimap;
519 	bool leaveTracks;
520 
521 	bool isSelected;
522 	bool isIcon;
523 	float iconRadius;
524 
525 	unsigned int lodCount;
526 	unsigned int currentLOD;
527 
528 	LuaUnitMaterial luaMats[LUAMAT_TYPE_COUNT];
529 
530 	int lastDrawFrame;
531 	unsigned int lastUnitUpdate;
532 
533 	std::string tooltip;
534 
535 private:
536 	/// if we are stunned by a weapon or for other reason, access via IsStunned/SetStunned(bool)
537 	bool stunned;
538 
539 	static float expMultiplier;
540 	static float expPowerScale;
541 	static float expHealthScale;
542 	static float expReloadScale;
543 	static float expGrade;
544 
545 	static float empDecline;
546 	static bool spawnFeature;
547 };
548 
549 #endif // UNIT_H
550