1 /************************************************************************************
2 
3 	AstroMenace
4 	Hardcore 3D space scroll-shooter with spaceship upgrade possibilities.
5 	Copyright (c) 2006-2019 Mikhail Kurinnoi, Viewizard
6 
7 
8 	AstroMenace is free software: you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation, either version 3 of the License, or
11 	(at your option) any later version.
12 
13 	AstroMenace is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with AstroMenace. If not, see <https://www.gnu.org/licenses/>.
20 
21 
22 	Website: https://viewizard.com/
23 	Project: https://github.com/viewizard/astromenace
24 	E-mail: viewizard@viewizard.com
25 
26 *************************************************************************************/
27 
28 // TODO as soon, as cSpaceShip will be moved to STL usage with weapon (shared_ptr?),
29 //      switch to eDeleteAfterLeaveScene::enabled by default and remove SetDeleteAfterLeaveScene()
30 //      also explosions creation code should be corrected (remove DeleteAfterLeaveScene setup)
31 
32 // TODO in case DeleteAfterLeaveScene is 'enabled', also should be limited by time
33 //      if object was never shown on the scene (during this time), should be deleted + warning output
34 
35 // TODO check 'virtual' usage here, do we really need this class functions override?
36 
37 #ifndef OBJECT3D_OBJECT3D_H
38 #define OBJECT3D_OBJECT3D_H
39 
40 #include "../core/core.h"
41 #include "../enum.h"
42 #include "../script/script.h"
43 
44 // NOTE switch to nested namespace definition (namespace A::B::C { ... }) (since C++17)
45 namespace viewizard {
46 namespace astromenace {
47 
48 // FIXME should be fixed, don't allow global scope interaction for local variables
49 extern int GameEnemyWeaponPenalty;
50 extern int GameEnemyArmorPenalty;
51 extern int GameEnemyTargetingSpeedPenalty;
52 extern int GameUnlimitedAmmo;
53 extern int GameUndestroyableWeapon;
54 extern int GameWeaponTargetingMode;
55 extern int GameSpaceShipControlMode;
56 extern int GameEngineSystem;
57 extern int GameTargetingSystem;
58 extern int GameAdvancedProtectionSystem;
59 extern int GameTargetingMechanicSystem;
60 
61 enum class eObjectStatus {
62 	none,
63 	Enemy,
64 	Ally,
65 	Player
66 };
67 
ObjectsStatusFoe(eObjectStatus Object1,eObjectStatus Object2)68 inline bool ObjectsStatusFoe(eObjectStatus Object1, eObjectStatus Object2)
69 {
70 	return ((Object1 == eObjectStatus::Enemy) && ((Object2 == eObjectStatus::Ally) || (Object2 == eObjectStatus::Player))) ||
71 	       ((Object2 == eObjectStatus::Enemy) && ((Object1 == eObjectStatus::Ally) || (Object1 == eObjectStatus::Player)));
72 }
73 
74 enum class eObjectType {
75 	none,
76 	EarthFighter,
77 	AlienFighter,
78 	AlienMotherShip,
79 	PirateShip,
80 	PirateVehicle,
81 	PirateBuilding,
82 	SmallAsteroid,
83 	SpaceDebris,
84 	ShipWeapon,
85 	Projectile,
86 	Explosion,
87 	CivilianBuilding,
88 	BasePart,
89 	Planet,
90 	Planetoid,
91 	BigAsteroid
92 	// if you change this enum, make sure that AddBonusForKilledEnemy() also reflect this changes
93 };
94 
95 enum class eDeleteAfterLeaveScene {
96 	disabled,
97 	enabled,	// waiting, object should being shown on the scene first
98 	showed,		// object shown, waiting when it will be out of the scene
99 	need_delete,	// object shown and out of the scene, should be deleted
100 	wait_delay	// will be deleted after delay
101 };
102 // delay before object delete, since object could back to the scene
103 constexpr float DeleteAfterLeaveSceneDelay{1.0f};
104 
105 /*
106 For now we have 2 types of damage:
107 Kinetic - good for armor and shield, stable damage value;
108 EM (electromagnetic) - good for shield (stable damage value), have a chance to kill alien (energy creature)
109    by one hit, have a chance to damage armor (random damage value), have a chance to disable some internal system;
110 */
111 // TODO probably, we also need "Explosion" damage type for shock wave, that now connected to 75% of Kinetic damage
112 class cDamage {
113 private:
114 	float Kinetic_{0.0f};
115 	float EM_{0.0f}; // electromagnetic
116 
117 public:
118 	cDamage() = default;
cDamage(float Value)119 	explicit cDamage(float Value) :
120 		Kinetic_{Value},
121 		EM_{Value}
122 	{}
cDamage(float Kinetic,float EM)123 	explicit cDamage(float Kinetic, float EM) :
124 		Kinetic_{Kinetic},
125 		EM_{EM}
126 	{}
127 
128 	cDamage& operator = (float Value)
129 	{
130 		Kinetic_ = Value;
131 		EM_ = Value;
132 		return *this;
133 	}
134 
135 	cDamage& operator /= (float Value)
136 	{
137 		Kinetic_ /= Value;
138 		EM_ /= Value;
139 		return *this;
140 	}
141 
142 	cDamage& operator *= (float Value)
143 	{
144 		Kinetic_ *= Value;
145 		EM_ *= Value;
146 		return *this;
147 	}
148 
Kinetic()149 	float Kinetic() const
150 	{
151 		return Kinetic_;
152 	}
153 
Kinetic()154 	float &Kinetic()
155 	{
156 		return Kinetic_;
157 	}
158 
EM()159 	float EM() const
160 	{
161 		return EM_;
162 	}
163 
EM()164 	float &EM()
165 	{
166 		return EM_;
167 	}
168 
Full()169 	float Full() const
170 	{
171 		return Kinetic_ + EM_;
172 	}
173 };
174 
175 inline cDamage operator * (const cDamage &Damage, float Value)
176 {
177 	return cDamage{Damage.Kinetic() * Value, Damage.EM() * Value};
178 }
179 
180 class cObject3D : public sModel3D {
181 protected:
182 	// don't allow object of this class creation
183 	cObject3D() = default;
184 	~cObject3D() = default;
185 
186 public:
187 	virtual void Draw(bool VertexOnlyPass, bool ShadowMap = false);
188 	bool NeedCullFaces{true};
189 	bool NeedAlphaTest{false};
190 	virtual bool Update(float Time);
191 
192 	void SetChunkLocation(const sVECTOR3D &NewLocation, unsigned ChunkNum);
193 	void SetChunkRotation(const sVECTOR3D &NewRotation, unsigned ChunkNum);
194 	virtual void SetLocation(const sVECTOR3D &NewLocation);
195 	virtual void SetRotation(const sVECTOR3D &NewRotation);
196 
197 	// in-game object's status relatively to player
198 	eObjectStatus ObjectStatus{eObjectStatus::none};
199 	// global object type
200 	eObjectType ObjectType{eObjectType::none};
201 	// internal object's type for objects with same ObjectType, usually, same as creation type (num)
202 	int InternalType{0};
203 
204 	// in case we need show object and delete after it leave scene (after DeleteAfterLeaveSceneDelay time)
205 	eDeleteAfterLeaveScene DeleteAfterLeaveScene{eDeleteAfterLeaveScene::disabled};
206 	// note, Lifetime could be changed by DeleteAfterLeaveScene settings
207 	float Lifetime{-1.0f};
208 
209 	sVECTOR3D Orientation{0.0f, 0.0f, 1.0f};
210 	sVECTOR3D Rotation{0.0f, 0.0f, 0.0f};
211 	sVECTOR3D OldRotationInv{0.0f, 0.0f, 0.0f};
212 	sVECTOR3D Location{0.0f, 0.0f, 0.0f};
213 	sVECTOR3D PrevLocation{0.0f, 0.0f, 0.0f};
214 
215 	float TimeLastUpdate{-1.0f};
216 	float TimeDelta{0.0f};
217 
218 	std::vector<GLtexture> Texture{};
219 	std::vector<GLtexture> TextureIllum{};
220 	std::vector<GLtexture> NormalMap{};
221 
222 	float PromptDrawDist2{-1.0f}; // LOD related
223 	int InternalLights{0};
224 
225 	// material related
226 	float Diffuse[4]{1.0f, 1.0f, 1.0f, 1.0f};
227 	float Specular[4]{1.0f, 1.0f, 1.0f, 1.0f};
228 	float Ambient[4]{0.1f, 0.1f, 0.1f, 0.1f};
229 	float Power[1]{64.0f};
230 
231 	float ArmorCurrentStatus{0.0f};
232 	float ArmorInitialStatus{0.0f};
233 
234 	float ShieldCurrentStatus{0.0f};
235 	float ShieldInitialStatus{0.0f};
236 	float ShieldRechargeRate{0.0f};
237 
238 	bool ShowStatus{true};
239 	bool ShowStatusAllTime{false};
240 
241 	float CurrentRotationMat[9]{1.0f, 0.0f, 0.0f,
242 				    0.0f, 1.0f, 0.0f,
243 				    0.0f, 0.0f, 1.0f};
244 	float OldInvRotationMat[9]{1.0f, 0.0f, 0.0f,
245 				   0.0f, 1.0f, 0.0f,
246 				   0.0f, 0.0f, 1.0f};
247 
248 	std::u32string ScriptLineNumberUTF32{}; // debug info, line number in script file
249 
250 	std::list<sTimeSheet> TimeSheetList{};
251 };
252 
253 
254 // we need fixed integers here, since we use them in scripts
255 enum class eRenderBoundingBoxes : int {
256 	None = 0,
257 	AABB_Only = 1,
258 	AABB_And_OBB = 2,
259 	All = 3 // AABB, OBB, HitBB
260 };
261 
262 // Set bounding boxes render mode.
263 void SetObjectsBBRenderMode(eRenderBoundingBoxes Mode);
264 
265 
266 /*
267  * object3d_manager
268  */
269 
270 // Draw all oblect3d.
271 void DrawAllObject3D(eDrawType DrawType);
272 // Update all oblect3d.
273 void UpdateAllObject3D(float Time);
274 // Release all oblect3d.
275 void ReleaseAllObject3D();
276 
277 /*
278  * object3d_collision
279  */
280 
281 // Проверяем все объекты на столкновение
282 void DetectCollisionAllObject3D();
283 
284 /*
285  * object3d_functions
286  */
287 
288 // Check for "mortal" objects, that could be used for collision detection.
289 bool NeedCheckCollision(const cObject3D &Object3D);
290 // Load 3D model data.
291 void LoadObjectData(const std::string &FileName, cObject3D &Object3D);
292 // Setup shaders.
293 bool SetupObject3DShaders();
294 
295 } // astromenace namespace
296 } // viewizard namespace
297 
298 #endif // OBJECT3D_OBJECT3D_H
299