about summary refs log tree commit diff
path: root/src/game/server/gs_common.hpp
blob: b6c809fa3394f22c4a8e756627335f53d563fe1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
#include "../g_game.hpp"
#include "../generated/gs_data.hpp"


extern TUNING_PARAMS tuning;

void create_sound_global(int sound, int target=-1);

inline int cmask_all() { return -1; }
inline int cmask_one(int cid) { return 1<<cid; }
inline int cmask_all_except_one(int cid) { return 0x7fffffff^cmask_one(cid); }
inline bool cmask_is_set(int mask, int cid) { return (mask&cmask_one(cid)) != 0; }

//
class EVENT_HANDLER
{
	static const int MAX_EVENTS = 128;
	static const int MAX_DATASIZE = 128*64;

	int types[MAX_EVENTS];  // TODO: remove some of these arrays
	int offsets[MAX_EVENTS];
	int sizes[MAX_EVENTS];
	int client_masks[MAX_EVENTS];
	char data[MAX_DATASIZE];
	
	int current_offset;
	int num_events;
public:
	EVENT_HANDLER();
	void *create(int type, int size, int mask = -1);
	void clear();
	void snap(int snapping_client);
};

extern EVENT_HANDLER events;

// a basic entity
class ENTITY
{
private:
	friend class GAMEWORLD; // thy these?
	friend class PLAYER;
	ENTITY *prev_entity;
	ENTITY *next_entity;

	ENTITY *prev_type_entity;
	ENTITY *next_type_entity;
protected:
	int id;
public:
	float proximity_radius;
	unsigned flags;
	int objtype;
	vec2 pos;

	enum
	{
		FLAG_DESTROY=0x00000001,
		FLAG_PHYSICS=0x00000002,
	};
	
	ENTITY(int objtype);
	virtual ~ENTITY();
	
	virtual void reset() {}
	virtual void post_reset() {}
	
	void set_flag(unsigned flag) { flags |= flag; }
	void clear_flag(unsigned flag) { flags &= ~flag; }

	virtual void destroy() { delete this; }
	virtual void tick() {}
	virtual void tick_defered() {}
		
	virtual void snap(int snapping_client) {}
		
	virtual bool take_damage(vec2 force, int dmg, int from, int weapon) { return true; }
};


class GAMEWORLD
{
	void reset();
	void remove_entities();
public:
	enum
	{
		NUM_ENT_TYPES=10, // TODO: are more exact value perhaps? :)
	};

	// TODO: two lists seams kinda not good, shouldn't be needed
	ENTITY *first_entity;
	ENTITY *first_entity_types[NUM_ENT_TYPES];
	bool paused;
	bool reset_requested;
	
	WORLD_CORE core;
	
	GAMEWORLD();
	~GAMEWORLD();
	int find_entities(vec2 pos, float radius, ENTITY **ents, int max);
	int find_entities(vec2 pos, float radius, ENTITY **ents, int max, const int* types, int maxtypes);

	void insert_entity(ENTITY *ent);
	void destroy_entity(ENTITY *ent);
	void remove_entity(ENTITY *ent);
	
	//
	void snap(int snapping_client);
	void tick();
};

extern GAMEWORLD *world;

// game object
// TODO: should change name of this one
class GAMECONTROLLER : public ENTITY
{
protected:
	void cyclemap();
	void resetgame();
	
	int round_start_tick;
	int game_over_tick;
	int sudden_death;
	
	int teamscore[2];
	
	int warmup;
	int round_count;
	
	bool is_teamplay;
	
public:
	int gametype;
	GAMECONTROLLER();

	void do_team_score_wincheck();
	void do_player_score_wincheck();
	
	void do_warmup(int seconds);
	
	void startround();
	void endround();
	
	bool is_friendly_fire(int cid1, int cid2);
	
	virtual bool on_entity(int index, vec2 pos);
	
	virtual void post_reset();
	virtual void tick();
	
	virtual void on_player_spawn(class PLAYER *p) {}
	virtual int on_player_death(class PLAYER *victim, class PLAYER *killer, int weapon);
	
	virtual void on_player_info_change(class PLAYER *p);
	
	virtual void snap(int snapping_client);
	virtual int get_auto_team(int notthisid);
	virtual bool can_join_team(int team, int notthisid);
	int clampteam(int team);
};

extern GAMECONTROLLER *gamecontroller;


// TODO: move to seperate file
class PICKUP : public ENTITY
{
public:
	static const int phys_size = 14;
	
	int type;
	int subtype; // weapon type for instance?
	int spawntick;
	PICKUP(int _type, int _subtype = 0);
	
	virtual void reset();
	virtual void tick();
	virtual void snap(int snapping_client);
};

// projectile entity
class PROJECTILE : public ENTITY
{
public:
	enum
	{
		PROJECTILE_FLAGS_EXPLODE = 1 << 0,
	};
	
	vec2 direction;
	ENTITY *powner; // this is nasty, could be removed when client quits
	int lifespan;
	int owner;
	int type;
	int flags;
	int damage;
	int sound_impact;
	int weapon;
	int bounce;
	float force;
	int start_tick;
	
	PROJECTILE(int type, int owner, vec2 pos, vec2 vel, int span, ENTITY* powner,
		int damage, int flags, float force, int sound_impact, int weapon);

	vec2 get_pos(float time);
	void fill_info(NETOBJ_PROJECTILE *proj);

	virtual void reset();
	virtual void tick();
	virtual void snap(int snapping_client);
};

class LASER : public ENTITY
{
	vec2 from;
	vec2 dir;
	float energy;
	int bounces;
	int eval_tick;
	PLAYER *owner;
	
	bool hit_player(vec2 from, vec2 to);
	void do_bounce();
	
public:
	
	LASER(vec2 pos, vec2 direction, float start_energy, PLAYER *owner);
	
	virtual void reset();
	virtual void tick();
	virtual void snap(int snapping_client);
};

// player entity
class PLAYER : public ENTITY
{
public:
	static const int phys_size = 28;

	// weapon info
	ENTITY *hitobjects[10];
	int numobjectshit;
	struct WEAPONSTAT
	{
		int ammoregenstart;
		int ammo;
		int ammocost;
		bool got;
	} weapons[NUM_WEAPONS];
	
	int active_weapon;
	int last_weapon;
	int queued_weapon;
	
	int reload_timer;
	int attack_tick;
	
	int damage_taken;

	int emote_type;
	int emote_stop;

	int last_action; // last tick that the player took any action ie some input
	
	//
	int client_id;
	char skin_name[64];
	int use_custom_color;
	int color_body;
	int color_feet;

	// these are non-heldback inputs
	NETOBJ_PLAYER_INPUT latest_previnput;
	NETOBJ_PLAYER_INPUT latest_input;

	// input	
	NETOBJ_PLAYER_INPUT previnput;
	NETOBJ_PLAYER_INPUT input;
	int num_inputs;
	int jumped;
	
	int damage_taken_tick;

	int health;
	int armor;

	// ninja
	struct
	{
		vec2 activationdir;
		int activationtick;
		int currentcooldown;
		int currentmovetime;
	} ninja;

	//
	int score;
	int team;
	int player_state; // if the client is chatting, accessing a menu or so
	
	bool spawning;
	bool dead;
	int die_tick;
	vec2 die_pos;
	
	// latency calculations
	int latency_accum;
	int latency_accum_min;
	int latency_accum_max;
	int latency_avg;
	int latency_min;
	int latency_max;

	// the player core for the physics	
	PLAYER_CORE core;
	
	//
	int64 last_chat;

	//
	PLAYER();
	void init();
	virtual void reset();
	virtual void destroy();
		
	void try_respawn();
	void respawn();
	
	void set_team(int team);
	
	bool is_grounded();
	
	void set_weapon(int w);
	
	void handle_weaponswitch();
	void do_weaponswitch();
	
	int handle_weapons();
	int handle_ninja();
	
	void on_direct_input(NETOBJ_PLAYER_INPUT *input);
	void fire_weapon();

	virtual void tick();
	virtual void tick_defered();
	
	void die(int killer, int weapon);
	
	virtual bool take_damage(vec2 force, int dmg, int from, int weapon);
	virtual void snap(int snaping_client);
};

extern PLAYER *players;