1 
2 #include "g_local.h"
3 
4 game_locals_t	game;
5 level_locals_t	level;
6 game_import_t	gi;
7 game_export_t	globals;
8 spawn_temp_t	st;
9 
10 int	sm_meat_index;
11 int	snd_fry;
12 int meansOfDeath;
13 
14 edict_t		*g_edicts;
15 
16 cvar_t	*deathmatch;
17 cvar_t	*coop;
18 cvar_t	*dmflags;
19 cvar_t	*skill;
20 cvar_t	*fraglimit;
21 cvar_t	*timelimit;
22 cvar_t	*password;
23 cvar_t	*spectator_password;
24 cvar_t	*maxclients;
25 cvar_t	*maxspectators;
26 cvar_t	*maxentities;
27 cvar_t	*g_select_empty;
28 cvar_t	*dedicated;
29 
30 cvar_t	*filterban;
31 
32 cvar_t	*sv_maxvelocity;
33 cvar_t	*sv_gravity;
34 
35 cvar_t	*sv_rollspeed;
36 cvar_t	*sv_rollangle;
37 cvar_t	*gun_x;
38 cvar_t	*gun_y;
39 cvar_t	*gun_z;
40 
41 cvar_t	*run_pitch;
42 cvar_t	*run_roll;
43 cvar_t	*bob_up;
44 cvar_t	*bob_pitch;
45 cvar_t	*bob_roll;
46 
47 cvar_t	*sv_cheats;
48 
49 cvar_t	*flood_msgs;
50 cvar_t	*flood_persecond;
51 cvar_t	*flood_waitdelay;
52 
53 cvar_t	*sv_maplist;
54 
55 cvar_t	*sv_stopspeed;	//PGM	 (this was a define in g_phys.c)
56 
57 //ROGUE cvars
58 cvar_t	*g_showlogic;
59 cvar_t	*gamerules;
60 cvar_t	*huntercam;
61 cvar_t	*strong_mines;
62 cvar_t	*randomrespawn;
63 //ROGUE
64 #ifdef WITH_ACEBOT
65 cvar_t	*botchat; //<-------botchat
66 cvar_t *botauto_respawn;
67 #endif
68 #ifdef GAME_MOD
69 cvar_t	*weap_shell;
70 cvar_t 	*alt_fire_blaster;
71 cvar_t	*eject_bullets;
72 cvar_t	*eject_bullets_dm_coop;
73 cvar_t  *opt_dm_scoreboard;
74 cvar_t  *help_min;
75 cvar_t  *camoffset;
76 #endif
77 
78 void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
79 void ClientThink (edict_t *ent, usercmd_t *cmd);
80 qboolean ClientConnect (edict_t *ent, char *userinfo);
81 void ClientUserinfoChanged (edict_t *ent, char *userinfo);
82 void ClientDisconnect (edict_t *ent);
83 void ClientBegin (edict_t *ent);
84 void ClientCommand (edict_t *ent);
85 void RunEntity (edict_t *ent);
86 void WriteGame (char *filename, qboolean autosave);
87 void ReadGame (char *filename);
88 void WriteLevel (char *filename);
89 void ReadLevel (char *filename);
90 void InitGame (void);
91 void G_RunFrame (void);
92 
93 
94 //===================================================================
95 
96 
ShutdownGame(void)97 void ShutdownGame (void)
98 {
99 	gi.dprintf ("==== ShutdownGame ====\n");
100 
101 	gi.FreeTags (TAG_LEVEL);
102 	gi.FreeTags (TAG_GAME);
103 }
104 
105 
106 /*
107 =================
108 GetGameAPI
109 
110 Returns a pointer to the structure with all entry points
111 and global variables
112 =================
113 */
GetGameAPI(game_import_t * import)114 game_export_t *GetGameAPI (game_import_t *import)
115 {
116 	gi = *import;
117 
118 	globals.apiversion = GAME_API_VERSION;
119 	globals.Init = InitGame;
120 	globals.Shutdown = ShutdownGame;
121 	globals.SpawnEntities = SpawnEntities;
122 
123 	globals.WriteGame = WriteGame;
124 	globals.ReadGame = ReadGame;
125 	globals.WriteLevel = WriteLevel;
126 	globals.ReadLevel = ReadLevel;
127 
128 	globals.ClientThink = ClientThink;
129 	globals.ClientConnect = ClientConnect;
130 	globals.ClientUserinfoChanged = ClientUserinfoChanged;
131 	globals.ClientDisconnect = ClientDisconnect;
132 	globals.ClientBegin = ClientBegin;
133 	globals.ClientCommand = ClientCommand;
134 
135 	globals.RunFrame = G_RunFrame;
136 
137 	globals.ServerCommand = ServerCommand;
138 
139 	globals.edict_size = sizeof(edict_t);
140 
141 	return &globals;
142 }
143 
144 #ifndef GAME_HARD_LINKED
145 // this is only here so the functions in q_shared.c and q_shwin.c can link
Sys_Error(char * error,...)146 void Sys_Error (char *error, ...)
147 {
148 	va_list		argptr;
149 	char		text[1024];
150 
151 	va_start (argptr, error);
152 	vsprintf (text, error, argptr);
153 	va_end (argptr);
154 
155 	gi.error (ERR_FATAL, "%s", text);
156 }
157 
Com_Printf(char * msg,...)158 void Com_Printf (char *msg, ...)
159 {
160 	va_list		argptr;
161 	char		text[1024];
162 
163 	va_start (argptr, msg);
164 	vsprintf (text, msg, argptr);
165 	va_end (argptr);
166 
167 	gi.dprintf ("%s", text);
168 }
169 
170 #endif
171 
172 //======================================================================
173 
174 
175 /*
176 =================
177 ClientEndServerFrames
178 =================
179 */
ClientEndServerFrames(void)180 void ClientEndServerFrames (void)
181 {
182 	int		i;
183 	edict_t	*ent;
184 
185 	// calc the player views now that all pushing
186 	// and damage has been added
187 	for (i=0 ; i<maxclients->value ; i++)
188 	{
189 		ent = g_edicts + 1 + i;
190 		if (!ent->inuse || !ent->client)
191 			continue;
192 		ClientEndServerFrame (ent);
193 	}
194 
195 }
196 
197 /*
198 =================
199 CreateTargetChangeLevel
200 
201 Returns the created target changelevel
202 =================
203 */
CreateTargetChangeLevel(char * map)204 edict_t *CreateTargetChangeLevel(char *map)
205 {
206 	edict_t *ent;
207 
208 	ent = G_Spawn ();
209 	ent->classname = "target_changelevel";
210 	Com_sprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
211 	ent->map = level.nextmap;
212 	return ent;
213 }
214 
215 /*
216 =================
217 EndDMLevel
218 
219 The timelimit or fraglimit has been exceeded
220 =================
221 */
EndDMLevel(void)222 void EndDMLevel (void)
223 {
224 	edict_t		*ent;
225 	char *s, *t, *f;
226 	static const char *seps = " ,\n\r";
227 
228 	// stay on same level flag
229 	if ((int)dmflags->value & DF_SAME_LEVEL)
230 	{
231 		BeginIntermission (CreateTargetChangeLevel (level.mapname) );
232 		return;
233 	}
234 
235 	// see if it's in the map list
236 	if (*sv_maplist->string) {
237 		s = strdup(sv_maplist->string);
238 		f = NULL;
239 		t = strtok(s, seps);
240 		while (t != NULL) {
241 			if (Q_stricmp(t, level.mapname) == 0) {
242 				// it's in the list, go to the next one
243 				t = strtok(NULL, seps);
244 				if (t == NULL) { // end of list, go to first one
245 					if (f == NULL) // there isn't a first one, same level
246 						BeginIntermission (CreateTargetChangeLevel (level.mapname) );
247 					else
248 						BeginIntermission (CreateTargetChangeLevel (f) );
249 				} else
250 					BeginIntermission (CreateTargetChangeLevel (t) );
251 				free(s);
252 				return;
253 			}
254 			if (!f)
255 				f = t;
256 			t = strtok(NULL, seps);
257 		}
258 		free(s);
259 	}
260 
261 	if (level.nextmap[0]) // go to a specific map
262 		BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
263 	else {	// search for a changelevel
264 		ent = G_Find (NULL, FOFS(classname), "target_changelevel");
265 		if (!ent)
266 		{	// the map designer didn't include a changelevel,
267 			// so create a fake ent that goes back to the same level
268 			BeginIntermission (CreateTargetChangeLevel (level.mapname) );
269 			return;
270 		}
271 		BeginIntermission (ent);
272 	}
273 }
274 
275 /*
276 =================
277 CheckDMRules
278 =================
279 */
CheckDMRules(void)280 void CheckDMRules (void)
281 {
282 	int			i;
283 	gclient_t	*cl;
284 
285 	if (level.intermissiontime)
286 		return;
287 
288 	if (!deathmatch->value)
289 		return;
290 
291 //=======
292 //ROGUE
293 	if (gamerules && gamerules->value && DMGame.CheckDMRules)
294 	{
295 		if(DMGame.CheckDMRules())
296 			return;
297 	}
298 //ROGUE
299 //=======
300 
301 	if (timelimit->value)
302 	{
303 		if (level.time >= timelimit->value*60)
304 		{
305 #ifdef WITH_ACEBOT
306 		safe_bprintf
307 #else
308 		gi.bprintf
309 #endif
310 			 (PRINT_HIGH, "Timelimit hit.\n");
311 			EndDMLevel ();
312 			return;
313 		}
314 	}
315 
316 	if (fraglimit->value)
317 	{
318 		for (i=0 ; i<maxclients->value ; i++)
319 		{
320 			cl = game.clients + i;
321 			if (!g_edicts[i+1].inuse)
322 				continue;
323 
324 			if (cl->resp.score >= fraglimit->value)
325 			{
326 #ifdef WITH_ACEBOT
327 		safe_bprintf
328 #else
329 		gi.bprintf
330 #endif
331 				 (PRINT_HIGH, "Fraglimit hit.\n");
332 				EndDMLevel ();
333 				return;
334 			}
335 		}
336 	}
337 }
338 
339 
340 /*
341 =============
342 ExitLevel
343 =============
344 */
ExitLevel(void)345 void ExitLevel (void)
346 {
347 	int		i;
348 	edict_t	*ent;
349 	char	command [256];
350 
351 	Com_sprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
352 	gi.AddCommandString (command);
353 	level.changemap = NULL;
354 	level.exitintermission = 0;
355 	level.intermissiontime = 0;
356 	ClientEndServerFrames ();
357 
358 	// clear some things before going to next level
359 	for (i=0 ; i<maxclients->value ; i++)
360 	{
361 		ent = g_edicts + 1 + i;
362 		if (!ent->inuse)
363 			continue;
364 		if (ent->health > ent->client->pers.max_health)
365 			ent->health = ent->client->pers.max_health;
366 	}
367 
368 }
369 
370 /*
371 ================
372 G_RunFrame
373 
374 Advances the world by 0.1 seconds
375 ================
376 */
G_RunFrame(void)377 void G_RunFrame (void)
378 {
379 	int		i;
380 	edict_t	*ent;
381 
382 #ifdef GAME_MOD
383 	Blinky_BeginRunFrame();
384 #endif
385 
386 	level.framenum++;
387 	level.time = level.framenum*FRAMETIME;
388 
389 	// choose a client for monsters to target this frame
390 	AI_SetSightClient ();
391 
392 	// exit intermissions
393 
394 	if (level.exitintermission)
395 	{
396 		ExitLevel ();
397 		return;
398 	}
399 
400 	//
401 	// treat each object in turn
402 	// even the world gets a chance to think
403 	//
404 	ent = &g_edicts[0];
405 	for (i=0 ; i<globals.num_edicts ; i++, ent++)
406 	{
407 		if (!ent->inuse)
408 			continue;
409 
410 		level.current_entity = ent;
411 
412 		VectorCopy (ent->s.origin, ent->s.old_origin);
413 
414 		// if the ground entity moved, make sure we are still on it
415 		if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
416 		{
417 			ent->groundentity = NULL;
418 			if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
419 			{
420 				M_CheckGround (ent);
421 			}
422 		}
423 
424 		if (i > 0 && i <= maxclients->value)
425 		{
426 			ClientBeginServerFrame (ent);
427 #ifdef WITH_ACEBOT
428 //ACEBOT
429 //			continue;
430 //ACEBOT
431 #else
432 			continue;
433 #endif
434 		}
435 
436 		G_RunEntity (ent);
437 	}
438 
439 	// see if it is time to end a deathmatch
440 	CheckDMRules ();
441 
442 	// build the playerstate_t structures for all players
443 	ClientEndServerFrames ();
444 }
445 
446