1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #ifndef PROJECTILE_HANDLER_H
4 #define PROJECTILE_HANDLER_H
5 
6 #include <list>
7 #include <set>
8 #include <vector>
9 #include <stack>
10 
11 #include "lib/gml/ThreadSafeContainers.h"
12 
13 #include "Sim/Projectiles/ProjectileFunctors.h"
14 #include "System/float3.h"
15 #include "System/Platform/Threading.h"
16 
17 // bypass id and event handling for unsynced projectiles (faster)
18 #define UNSYNCED_PROJ_NOEVENT 1
19 
20 class CProjectile;
21 class CUnit;
22 class CFeature;
23 class CGroundFlash;
24 struct UnitDef;
25 struct FlyingPiece;
26 struct S3DOPrimitive;
27 struct S3DOPiece;
28 struct SS3OVertex;
29 
30 
31 
32 typedef std::pair<CProjectile*, int> ProjectileMapValPair;
33 typedef std::pair<int, ProjectileMapValPair> ProjectileMapKeyPair;
34 typedef std::map<int, ProjectileMapValPair> ProjectileMap;
35 
36 typedef ThreadListSim<std::list<CProjectile*>, std::set<CProjectile*>, CProjectile*, ProjectileDetacher> ProjectileContainer;
37 typedef ThreadListSimRender<std::list<CGroundFlash*>, std::set<CGroundFlash*>, CGroundFlash*> GroundFlashContainer;
38 
39 typedef ThreadListSimRender<std::set<FlyingPiece*, FlyingPieceComparator>, void, FlyingPiece*> FlyingPieceContainer;
40 
41 typedef ThreadMapRender<CProjectile*, int, ProjectileMapValPair, ProjectileIndexer> ProjectileRenderMap;
42 
43 
44 class CProjectileHandler
45 {
46 	CR_DECLARE_STRUCT(CProjectileHandler)
47 
48 public:
49 	CProjectileHandler();
50 	~CProjectileHandler();
51 	void Serialize(creg::ISerializer* s);
52 	void PostLoad();
53 
GetMapPairBySyncedID(int id)54 	inline const ProjectileMapValPair* GetMapPairBySyncedID(int id) const {
55 		const ProjectileMap& projectileIDs = syncedProjectileIDs;
56 		const ProjectileMap::const_iterator it = projectileIDs.find(id);
57 
58 		if (it == projectileIDs.end())
59 			return NULL;
60 
61 		return &(it->second);
62 	}
63 
GetMapPairByUnsyncedID(int id)64 	inline const ProjectileMapValPair* GetMapPairByUnsyncedID(int id) const {
65 		if (UNSYNCED_PROJ_NOEVENT)
66 			return NULL; // unsynced projectiles have no IDs if UNSYNCED_PROJ_NOEVENT
67 
68 		const ProjectileMap& projectileIDs = unsyncedProjectileIDs;
69 		const ProjectileMap::const_iterator it = projectileIDs.find(id);
70 
71 		if (it == projectileIDs.end())
72 			return NULL;
73 
74 		return &(it->second);
75 	}
76 
GetSyncedRenderProjectileIDs()77 	ProjectileRenderMap& GetSyncedRenderProjectileIDs() { return syncedRenderProjectileIDs; }
GetUnsyncedRenderProjectileIDs()78 	ProjectileRenderMap& GetUnsyncedRenderProjectileIDs() { return unsyncedRenderProjectileIDs; }
79 
80 	void CheckUnitCollisions(CProjectile*, std::vector<CUnit*>&, const float3&, const float3&);
81 	void CheckFeatureCollisions(CProjectile*, std::vector<CFeature*>&, const float3&, const float3&);
82 	void CheckUnitFeatureCollisions(ProjectileContainer&);
83 	void CheckGroundCollisions(ProjectileContainer&);
84 	void CheckCollisions();
85 
SetMaxParticles(int value)86 	void SetMaxParticles(int value) { maxParticles = value; }
SetMaxNanoParticles(int value)87 	void SetMaxNanoParticles(int value) { maxNanoParticles = value; }
88 
89 	void Update();
UpdateParticleSaturation()90 	void UpdateParticleSaturation() {
91 		particleSaturation = (maxParticles > 0)? (currentParticles / float(maxParticles)): 1.0f;
92 	}
93 
94 	void AddProjectile(CProjectile* p);
95 	void AddGroundFlash(CGroundFlash* flash);
96 	void AddFlyingPiece(const float3& pos, const float3& speed, int team, const S3DOPiece* piece, const S3DOPrimitive* chunk);
97 	void AddFlyingPiece(const float3& pos, const float3& speed, int team, int textureType, const SS3OVertex* chunk);
98 	void AddNanoParticle(const float3&, const float3&, const UnitDef*, int team, bool highPriority);
99 	void AddNanoParticle(const float3&, const float3&, const UnitDef*, int team, float radius, bool inverse, bool highPriority);
100 	bool RenderAccess(const CProjectile *p) const;
101 
102 public:
103 	ProjectileContainer syncedProjectiles;    // contains only projectiles that can change simulation state
104 	ProjectileContainer unsyncedProjectiles;  // contains only projectiles that cannot change simulation state
105 	FlyingPieceContainer flyingPieces3DO;     // unsynced
106 	FlyingPieceContainer flyingPiecesS3O;     // unsynced
107 	GroundFlashContainer groundFlashes;       // unsynced
108 
109 	int maxParticles;              // different effects should start to cut down on unnececary(unsynced) particles when this number is reached
110 	int maxNanoParticles;
111 	int currentParticles;          // number of particles weighted by how complex they are
112 	int currentNanoParticles;
113 	float particleSaturation;      // currentParticles / maxParticles ratio
114 
115 private:
116 	void UpdateProjectileContainer(ProjectileContainer&, bool);
117 
118 	ProjectileRenderMap syncedRenderProjectileIDs;        // same as syncedProjectileIDs, used by render thread
119 	ProjectileRenderMap unsyncedRenderProjectileIDs;      // same as unsyncedProjectileIDs, used by render thread
120 
121 	int maxUsedSyncedID;
122 	int maxUsedUnsyncedID;
123 	std::list<int> freeSyncedIDs;             // available synced (weapon, piece) projectile ID's
124 	std::list<int> freeUnsyncedIDs;           // available unsynced projectile ID's
125 	ProjectileMap syncedProjectileIDs;        // ID ==> <projectile, allyteam> map for living synced projectiles
126 	ProjectileMap unsyncedProjectileIDs;      // ID ==> <projectile, allyteam> map for living unsynced projectiles
127 };
128 
129 
130 extern CProjectileHandler* projectileHandler;
131 
132 #endif /* PROJECTILE_HANDLER_H */
133