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