1 /*-------------------------------------------------------------------------------
2 
3 	BARONY
4 	File: game.hpp
5 	Desc: header file for the game
6 
7 	Copyright 2013-2016 (c) Turning Wheel LLC, all rights reserved.
8 	See LICENSE for details.
9 
10 -------------------------------------------------------------------------------*/
11 
12 #pragma once
13 
14 #include <vector>
15 #include <random>
16 #include <chrono>
17 
18 #ifdef STEAMWORKS
19 #include <steam/steam_api.h>
20 #include "steam.hpp"
21 #endif
22 
23 // REMEMBER TO CHANGE THIS WITH EVERY NEW OFFICIAL VERSION!!!
24 #define VERSION "v3.3.7"
25 #define GAME_CODE
26 
27 //#define MAX_FPS_LIMIT 60 //TODO: Make this configurable.
28 class Entity;
29 
30 #define DEBUG 1
31 #define ENTITY_PACKET_LENGTH 46
32 #define NET_PACKET_SIZE 512
33 
34 // impulses (bound keystrokes, mousestrokes, and joystick/game controller strokes) //TODO: Player-by-player basis.
35 extern Uint32 impulses[NUMIMPULSES];
36 extern Uint32 joyimpulses[NUM_JOY_IMPULSES]; //Joystick/gamepad only impulses.
37 extern int reversemouse;
38 extern real_t mousespeed;
39 
40 void handleEvents(void);
41 void startMessages();
42 
43 // net packet send
44 typedef struct packetsend_t
45 {
46 	UDPsocket sock;
47 	int channel;
48 	UDPpacket* packet;
49 	int num;
50 	int tries;
51 	int hostnum;
52 } packetsend_t;
53 extern list_t safePacketsSent;
54 extern std::unordered_map<int, Uint32> safePacketsReceivedMap[MAXPLAYERS];
55 extern bool receivedclientnum;
56 
57 extern Entity* hudweapon, *hudarm;
58 
59 extern Uint32 clientplayer;
60 extern Sint32 numplayers;
61 extern Sint32 clientnum;
62 extern bool intro;
63 extern int introstage;
64 extern bool gamePaused;
65 extern bool fadeout, fadefinished;
66 extern int fadealpha;
67 extern Entity* client_selected[MAXPLAYERS];
68 extern bool inrange[MAXPLAYERS];
69 extern bool deleteallbuttons;
70 extern Sint32 client_classes[MAXPLAYERS];
71 extern Uint32 client_keepalive[MAXPLAYERS];
72 extern Uint16 portnumber;
73 extern list_t messages;
74 extern list_t command_history;
75 extern node_t* chosen_command;
76 extern bool command;
77 extern bool noclip, godmode, buddhamode;
78 extern bool everybodyfriendly;
79 extern bool combat, combattoggle;
80 extern bool assailant[MAXPLAYERS];
81 extern bool oassailant[MAXPLAYERS];
82 extern int assailantTimer[MAXPLAYERS];
83 static const int COMBAT_MUSIC_COOLDOWN = 200; // 200 ticks of combat music before it fades away.
84 extern list_t removedEntities;
85 extern list_t entitiesToDelete[MAXPLAYERS];
86 extern char maptoload[256], configtoload[256];
87 extern bool loadingmap, loadingconfig;
88 extern int startfloor;
89 extern bool skipintro;
90 extern Uint32 uniqueGameKey;
91 
92 // definitions
93 extern bool showfps;
94 extern real_t t, ot, frameval[AVERAGEFRAMES];
95 extern Uint32 cycles, pingtime;
96 extern Uint32 timesync;
97 extern real_t fps;
98 extern bool shootmode;
99 static const int NUMCLASSES = 21;
100 #define NUMRACES 13
101 #define NUMPLAYABLERACES 9
102 extern char address[64];
103 extern bool loadnextlevel;
104 extern int skipLevelsOnLoad;
105 extern bool loadingSameLevelAsCurrent;
106 extern std::string loadCustomNextMap;
107 extern Uint32 forceMapSeed;
108 extern int currentlevel;
109 extern bool secretlevel;
110 extern bool darkmap;
111 extern int shaking, bobbing;
112 extern int musvolume;
113 extern SDL_Surface* title_bmp;
114 extern SDL_Surface* titleDefault_bmp;
115 extern SDL_Surface* logo_bmp;
116 extern SDL_Surface* cursor_bmp;
117 extern SDL_Surface* cross_bmp;
118 
119 enum PlayerClasses : int
120 {
121 	CLASS_BARBARIAN,
122 	CLASS_WARRIOR,
123 	CLASS_HEALER,
124 	CLASS_ROGUE,
125 	CLASS_WANDERER,
126 	CLASS_CLERIC,
127 	CLASS_MERCHANT,
128 	CLASS_WIZARD,
129 	CLASS_ARCANIST,
130 	CLASS_JOKER,
131 	CLASS_SEXTON,
132 	CLASS_NINJA,
133 	CLASS_MONK,
134 	CLASS_CONJURER,
135 	CLASS_ACCURSED,
136 	CLASS_MESMER,
137 	CLASS_BREWER,
138 	CLASS_MACHINIST,
139 	CLASS_PUNISHER,
140 	CLASS_SHAMAN,
141 	CLASS_HUNTER
142 };
143 
144 static const int CLASS_SHAMAN_NUM_STARTING_SPELLS = 15;
145 
146 enum PlayerRaces : int
147 {
148 	RACE_HUMAN,
149 	RACE_SKELETON,
150 	RACE_VAMPIRE,
151 	RACE_SUCCUBUS,
152 	RACE_GOATMAN,
153 	RACE_AUTOMATON,
154 	RACE_INCUBUS,
155 	RACE_GOBLIN,
156 	RACE_INSECTOID,
157 	RACE_RAT,
158 	RACE_TROLL,
159 	RACE_SPIDER,
160 	RACE_IMP
161 };
162 
163 enum ESteamLeaderboardTitles : int
164 {
165 	LEADERBOARD_NONE,
166 	LEADERBOARD_NORMAL_TIME,
167 	LEADERBOARD_NORMAL_SCORE,
168 	LEADERBOARD_MULTIPLAYER_TIME,
169 	LEADERBOARD_MULTIPLAYER_SCORE,
170 	LEADERBOARD_HELL_TIME,
171 	LEADERBOARD_HELL_SCORE,
172 	LEADERBOARD_HARDCORE_TIME,
173 	LEADERBOARD_HARDCORE_SCORE,
174 	LEADERBOARD_CLASSIC_TIME,
175 	LEADERBOARD_CLASSIC_SCORE,
176 	LEADERBOARD_CLASSIC_HARDCORE_TIME,
177 	LEADERBOARD_CLASSIC_HARDCORE_SCORE,
178 	LEADERBOARD_MULTIPLAYER_CLASSIC_TIME,
179 	LEADERBOARD_MULTIPLAYER_CLASSIC_SCORE,
180 	LEADERBOARD_MULTIPLAYER_HELL_TIME,
181 	LEADERBOARD_MULTIPLAYER_HELL_SCORE,
182 	LEADERBOARD_DLC_NORMAL_TIME,
183 	LEADERBOARD_DLC_NORMAL_SCORE,
184 	LEADERBOARD_DLC_MULTIPLAYER_TIME,
185 	LEADERBOARD_DLC_MULTIPLAYER_SCORE,
186 	LEADERBOARD_DLC_HELL_TIME,
187 	LEADERBOARD_DLC_HELL_SCORE,
188 	LEADERBOARD_DLC_HARDCORE_TIME,
189 	LEADERBOARD_DLC_HARDCORE_SCORE,
190 	LEADERBOARD_DLC_CLASSIC_TIME,
191 	LEADERBOARD_DLC_CLASSIC_SCORE,
192 	LEADERBOARD_DLC_CLASSIC_HARDCORE_TIME,
193 	LEADERBOARD_DLC_CLASSIC_HARDCORE_SCORE,
194 	LEADERBOARD_DLC_MULTIPLAYER_CLASSIC_TIME,
195 	LEADERBOARD_DLC_MULTIPLAYER_CLASSIC_SCORE,
196 	LEADERBOARD_DLC_MULTIPLAYER_HELL_TIME,
197 	LEADERBOARD_DLC_MULTIPLAYER_HELL_SCORE
198 };
199 
200 bool achievementUnlocked(const char* achName);
201 void steamAchievement(const char* achName);
202 void steamUnsetAchievement(const char* achName);
203 void steamAchievementClient(int player, const char* achName);
204 void steamAchievementEntity(Entity* my, const char* achName); // give steam achievement to an entity, and check for valid player info.
205 void steamStatisticUpdate(int statisticNum, ESteamStatTypes type, int value);
206 void steamStatisticUpdateClient(int player, int statisticNum, ESteamStatTypes type, int value);
207 void steamIndicateStatisticProgress(int statisticNum, ESteamStatTypes type);
208 void freePlayerEquipment(int x);
209 void pauseGame(int mode, int ignoreplayer);
210 int initGame();
211 void deinitGame();
212 Uint32 timerCallback(Uint32 interval, void* param);
213 void handleButtons(void);
214 void gameLogic(void);
215 
216 // behavior function prototypes:
217 void actAnimator(Entity* my);
218 void actRotate(Entity* my);
219 void actLiquid(Entity* my);
220 void actEmpty(Entity* my);
221 void actFurniture(Entity* my);
222 void actMCaxe(Entity* my);
223 void actDoorFrame(Entity* my);
224 void actDeathCam(Entity* my);
225 void actPlayerLimb(Entity* my);
226 void actTorch(Entity* my);
227 void actCrystalShard(Entity* my);
228 void actDoor(Entity* my);
229 void actHudWeapon(Entity* my);
230 void actHudShield(Entity* my);
231 void actHudAdditional(Entity* my);
232 void actHudArrowModel(Entity* my);
233 void actItem(Entity* my);
234 void actGoldBag(Entity* my);
235 void actGib(Entity* my);
236 Entity* spawnGib(Entity* parentent, int customGibSprite = -1);
237 Entity* spawnGibClient(Sint16 x, Sint16 y, Sint16 z, Sint16 sprite);
238 void serverSpawnGibForClient(Entity* gib);
239 void actLadder(Entity* my);
240 void actLadderUp(Entity* my);
241 void actPortal(Entity* my);
242 void actWinningPortal(Entity* my);
243 void actFlame(Entity* my);
244 void actCampfire(Entity* my);
245 Entity* spawnFlame(Entity* parentent, Sint32 sprite);
246 void actMagic(Entity* my);
247 Entity* castMagic(Entity* parentent);
248 void actSprite(Entity* my);
249 void actSpriteNametag(Entity* my);
250 void actSleepZ(Entity* my);
251 Entity* spawnBang(Sint16 x, Sint16 y, Sint16 z);
252 Entity* spawnExplosion(Sint16 x, Sint16 y, Sint16 z);
253 Entity* spawnExplosionFromSprite(Uint16 sprite, Sint16 x, Sint16 y, Sint16 z);
254 Entity* spawnSleepZ(Sint16 x, Sint16 y, Sint16 z);
255 Entity* spawnFloatingSpriteMisc(int sprite, Sint16 x, Sint16 y, Sint16 z);
256 void actArrow(Entity* my);
257 void actBoulder(Entity* my);
258 void actBoulderTrap(Entity* my);
259 void actBoulderTrapEast(Entity* my);
260 void actBoulderTrapWest(Entity* my);
261 void actBoulderTrapSouth(Entity* my);
262 void actBoulderTrapNorth(Entity* my);
263 void actHeadstone(Entity* my);
264 void actThrown(Entity* my);
265 void actBeartrap(Entity* my);
266 void actBeartrapLaunched(Entity* my);
267 void actBomb(Entity* my);
268 void actDecoyBox(Entity* my);
269 void actDecoyBoxCrank(Entity* my);
270 void actSpearTrap(Entity* my);
271 void actWallBuster(Entity* my);
272 void actWallBuilder(Entity* my);
273 void actPowerCrystalBase(Entity* my);
274 void actPowerCrystal(Entity* my);
275 void actPowerCrystalParticleIdle(Entity* my);
276 void actPedestalBase(Entity* my);
277 void actPedestalOrb(Entity* my);
278 void actMidGamePortal(Entity* my);
279 void actCustomPortal(Entity* my);
280 void actTeleporter(Entity* my);
281 void actMagicTrapCeiling(Entity* my);
282 void actExpansionEndGamePortal(Entity* my);
283 void actSoundSource(Entity* my);
284 void actLightSource(Entity* my);
285 void actSignalTimer(Entity* my);
286 
287 void startMessages();
288 bool frameRateLimit(Uint32 maxFrameRate, bool resetAccumulator = true);
289 extern Uint32 networkTickrate;
290 extern bool gameloopFreezeEntities;
291 extern Uint32 serverSchedulePlayerHealthUpdate;
292 
293 #define TOUCHRANGE 32
294 #define STRIKERANGE 24
295 #define XPSHARERANGE 256
296 
297 // function prototypes for charclass.c:
298 void initClass(int player);
299 void initShapeshiftHotbar();
300 void deinitShapeshiftHotbar();
301 bool playerUnlockedShamanSpell(int player, Item* item);
302 
303 extern char last_ip[64];
304 extern char last_port[64];
305 
306 //TODO: Maybe increase with level or something?
307 //TODO: Pause health regen during combat?
308 #define HEAL_TIME 600 //10 seconds. //Original time: 3600 (1 minute)
309 #define MAGIC_REGEN_TIME 300 // 5 seconds
310 
311 #define DEFAULT_HP 30
312 #define DEFAULT_MP 30
313 #define HP_MOD 5
314 #define MP_MOD 5
315 
316 #define SPRITE_FLAME 13
317 #define SPRITE_CRYSTALFLAME 96
318 
319 #define MAXCHARGE 30 // charging up weapons
320 
321 static const int BASE_MELEE_DAMAGE = 8;
322 static const int BASE_RANGED_DAMAGE = 7;
323 static const int BASE_THROWN_DAMAGE = 6;
324 static const int BASE_PLAYER_UNARMED_DAMAGE = 8;
325 
326 extern bool spawn_blood;
327 extern bool capture_mouse; //Useful for debugging when the game refuses to release the mouse when it's crashed.
328 
329 #define LEVELSFILE "maps/levels.txt"
330 #define SECRETLEVELSFILE "maps/secretlevels.txt"
331 #define LENGTH_OF_LEVEL_REGION 5
332 
333 #define TICKS_PER_SECOND 50
334 static const Uint8 TICKS_TO_PROCESS_FIRE = 30; // The amount of ticks needed until the 'BURNING' Status Effect is processed (char_fire % TICKS_TO_PROCESS_FIRE == 0)
335 static const int EFFECT_WITHDRAWAL_BASE_TIME = TICKS_PER_SECOND * 60 * 8; // 8 minutes base withdrawal time.
336 
337 static const std::string PLAYERNAMES_MALE_FILE = "playernames-male.txt";
338 static const std::string PLAYERNAMES_FEMALE_FILE = "playernames-female.txt";
339 extern std::vector<std::string> randomPlayerNamesMale;
340 extern std::vector<std::string> randomPlayerNamesFemale;
341 extern bool enabledDLCPack1;
342 extern bool enabledDLCPack2;
343 extern std::vector<std::string> physFSFilesInDirectory;
344 void loadRandomNames();
345 extern int monsterEmoteGimpTimer;
346 extern int selectedEntityGimpTimer;
347 void mapLevel(int player);
348 void mapFoodOnLevel(int player);
349 
350 class TileEntityListHandler
351 {
352 private:
353 	static const int kMaxMapDimension = 256;
354 public:
355 	list_t gridEntities[kMaxMapDimension][kMaxMapDimension];
356 
357 	void clearTile(int x, int y);
358 	void emptyGridEntities();
359 	list_t* getTileList(int x, int y);
360 	node_t* addEntity(Entity& entity);
361 	node_t* updateEntity(Entity& entity);
362 	std::vector<list_t*> getEntitiesWithinRadius(int u, int v, int radius);
363 	std::vector<list_t*> getEntitiesWithinRadiusAroundEntity(Entity* entity, int radius);
364 
TileEntityListHandler()365 	TileEntityListHandler()
366 	{
367 		for ( int i = 0; i < kMaxMapDimension; ++i )
368 		{
369 			for ( int j = 0; j < kMaxMapDimension; ++j )
370 			{
371 				gridEntities[i][j].first = nullptr;
372 				gridEntities[i][j].last = nullptr;
373 			}
374 		}
375 	};
376 
~TileEntityListHandler()377 	~TileEntityListHandler()
378 	{
379 		for ( int i = 0; i < kMaxMapDimension; ++i )
380 		{
381 			for ( int j = 0; j < kMaxMapDimension; ++j )
382 			{
383 				clearTile(i, j);
384 			}
385 		}
386 	};
387 };
388 extern TileEntityListHandler TileEntityList;
389 
390 extern float framerateAccumulatedTime;
391 
392 class DebugStatsClass
393 {
394 public:
395 	std::chrono::high_resolution_clock::time_point t1StartLoop;
396 	std::chrono::high_resolution_clock::time_point t2PostEvents;
397 	std::chrono::high_resolution_clock::time_point t21PostHandleMessages;
398 	std::chrono::high_resolution_clock::time_point t3SteamCallbacks;
399 	std::chrono::high_resolution_clock::time_point t4Music;
400 	std::chrono::high_resolution_clock::time_point t5MainDraw;
401 	std::chrono::high_resolution_clock::time_point t6Messages;
402 	std::chrono::high_resolution_clock::time_point t7Inputs;
403 	std::chrono::high_resolution_clock::time_point t8Status;
404 	std::chrono::high_resolution_clock::time_point t9GUI;
405 	std::chrono::high_resolution_clock::time_point t10FrameLimiter;
406 	std::chrono::high_resolution_clock::time_point t11End;
407 
408 	std::chrono::high_resolution_clock::time_point eventsT1;
409 	std::chrono::high_resolution_clock::time_point eventsT2;
410 	std::chrono::high_resolution_clock::time_point eventsT3;
411 	std::chrono::high_resolution_clock::time_point eventsT4;
412 	std::chrono::high_resolution_clock::time_point eventsT5;
413 	std::chrono::high_resolution_clock::time_point eventsT6;
414 
415 	std::chrono::high_resolution_clock::time_point messagesT1;
416 
417 	std::chrono::high_resolution_clock::time_point t1Stored;
418 	std::chrono::high_resolution_clock::time_point t2Stored;
419 	std::chrono::high_resolution_clock::time_point t21Stored;
420 	std::chrono::high_resolution_clock::time_point t3Stored;
421 	std::chrono::high_resolution_clock::time_point t4Stored;
422 	std::chrono::high_resolution_clock::time_point t5Stored;
423 	std::chrono::high_resolution_clock::time_point t6Stored;
424 	std::chrono::high_resolution_clock::time_point t7Stored;
425 	std::chrono::high_resolution_clock::time_point t8Stored;
426 	std::chrono::high_resolution_clock::time_point t9Stored;
427 	std::chrono::high_resolution_clock::time_point t10Stored;
428 	std::chrono::high_resolution_clock::time_point t11Stored;
429 
430 	std::chrono::high_resolution_clock::time_point eventsT1stored;
431 	std::chrono::high_resolution_clock::time_point eventsT2stored;
432 	std::chrono::high_resolution_clock::time_point eventsT3stored;
433 	std::chrono::high_resolution_clock::time_point eventsT4stored;
434 	std::chrono::high_resolution_clock::time_point eventsT5stored;
435 	std::chrono::high_resolution_clock::time_point eventsT6stored;
436 
437 	std::chrono::high_resolution_clock::time_point messagesT1stored;
438 
439 	std::chrono::high_resolution_clock::time_point messagesT2WhileLoop;
440 	bool handlePacketStartLoop = false;
441 
442 	std::unordered_map<unsigned long, std::pair<std::string, int>> networkPackets;
443 	std::unordered_map<int, int> entityUpdatePackets;
444 
445 	bool displayStats = false;
446 	char debugOutput[1024];
447 	char debugEventOutput[1024];
448 
DebugStatsClass()449 	DebugStatsClass()
450 	{};
451 
storeOldTimePoints()452 	void inline storeOldTimePoints()
453 	{
454 		t1Stored = t1StartLoop;
455 		t2Stored = t2PostEvents;
456 		t21Stored = t21PostHandleMessages;
457 		t3Stored = t3SteamCallbacks;
458 		t4Stored = t4Music;
459 		t5Stored = t5MainDraw;
460 		t6Stored = t6Messages;
461 		t7Stored = t7Inputs;
462 		t8Stored = t8Status;
463 		t9Stored = t9GUI;
464 		t10Stored = t10FrameLimiter;
465 		t11Stored = t11End;
466 		eventsT1stored = eventsT1;
467 		eventsT2stored = eventsT2;
468 		eventsT3stored = eventsT3;
469 		eventsT4stored = eventsT4;
470 		eventsT5stored = eventsT5;
471 		eventsT6stored = eventsT6;
472 
473 		messagesT1stored = messagesT1;
474 	};
475 
476 	void storeStats();
477 
478 	void storeEventStats();
479 };
480 extern DebugStatsClass DebugStats;
481 
482