Quake II RTX doxygen  1.0 dev
g_main.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "g_local.h"
20 
23 game_import_t gi;
24 game_export_t globals;
26 
28 int snd_fry;
30 
31 edict_t *g_edicts;
32 
33 cvar_t *deathmatch;
34 cvar_t *coop;
35 cvar_t *dmflags;
36 cvar_t *skill;
37 cvar_t *fraglimit;
38 cvar_t *timelimit;
39 cvar_t *password;
41 cvar_t *needpass;
42 cvar_t *maxclients;
43 cvar_t *maxspectators;
44 cvar_t *maxentities;
46 cvar_t *dedicated;
47 cvar_t *nomonsters;
48 
49 cvar_t *filterban;
50 
52 cvar_t *sv_gravity;
53 
54 cvar_t *sv_rollspeed;
55 cvar_t *sv_rollangle;
56 cvar_t *gun_x;
57 cvar_t *gun_y;
58 cvar_t *gun_z;
59 
60 cvar_t *run_pitch;
61 cvar_t *run_roll;
62 cvar_t *bob_up;
63 cvar_t *bob_pitch;
64 cvar_t *bob_roll;
65 
66 cvar_t *sv_cheats;
67 
68 cvar_t *flood_msgs;
71 
72 cvar_t *sv_maplist;
73 
74 cvar_t *sv_features;
75 
76 cvar_t *sv_flaregun;
77 
78 void SpawnEntities(const char *mapname, const char *entities, const 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(const char *filename, qboolean autosave);
87 void ReadGame(const char *filename);
88 void WriteLevel(const char *filename);
89 void ReadLevel(const char *filename);
90 void InitGame(void);
91 void G_RunFrame(void);
92 
93 
94 //===================================================================
95 
96 
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 InitGame
108 
109 This will be called when the dll is first loaded, which
110 only happens when a new game is started or a save game
111 is loaded.
112 ============
113 */
114 void InitGame(void)
115 {
116  gi.dprintf("==== InitGame ====\n");
117 
118  gun_x = gi.cvar("gun_x", "0", 0);
119  gun_y = gi.cvar("gun_y", "0", 0);
120  gun_z = gi.cvar("gun_z", "0", 0);
121 
122  //FIXME: sv_ prefix is wrong for these
123  sv_rollspeed = gi.cvar("sv_rollspeed", "200", 0);
124  sv_rollangle = gi.cvar("sv_rollangle", "2", 0);
125  sv_maxvelocity = gi.cvar("sv_maxvelocity", "2000", 0);
126  sv_gravity = gi.cvar("sv_gravity", "800", 0);
127 
128  // noset vars
129  dedicated = gi.cvar("dedicated", "0", CVAR_NOSET);
130 
131  nomonsters = gi.cvar("nomonsters", "0", 0);
132 
133  // latched vars
134  sv_cheats = gi.cvar("cheats", "0", CVAR_SERVERINFO | CVAR_LATCH);
135  gi.cvar("gamename", GAMEVERSION , CVAR_SERVERINFO | CVAR_LATCH);
136  gi.cvar("gamedate", __DATE__ , CVAR_SERVERINFO | CVAR_LATCH);
137 
138  maxclients = gi.cvar("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH);
139  maxspectators = gi.cvar("maxspectators", "4", CVAR_SERVERINFO);
140  deathmatch = gi.cvar("deathmatch", "0", CVAR_LATCH);
141  coop = gi.cvar("coop", "0", CVAR_LATCH);
142  skill = gi.cvar("skill", "1", CVAR_LATCH);
143  maxentities = gi.cvar("maxentities", "1024", CVAR_LATCH);
144 
145  // change anytime vars
146  dmflags = gi.cvar("dmflags", "0", CVAR_SERVERINFO);
147  fraglimit = gi.cvar("fraglimit", "0", CVAR_SERVERINFO);
148  timelimit = gi.cvar("timelimit", "0", CVAR_SERVERINFO);
149  password = gi.cvar("password", "", CVAR_USERINFO);
150  spectator_password = gi.cvar("spectator_password", "", CVAR_USERINFO);
151  needpass = gi.cvar("needpass", "0", CVAR_SERVERINFO);
152  filterban = gi.cvar("filterban", "1", 0);
153 
154  g_select_empty = gi.cvar("g_select_empty", "0", CVAR_ARCHIVE);
155 
156  run_pitch = gi.cvar("run_pitch", "0.002", 0);
157  run_roll = gi.cvar("run_roll", "0.005", 0);
158  bob_up = gi.cvar("bob_up", "0.005", 0);
159  bob_pitch = gi.cvar("bob_pitch", "0.002", 0);
160  bob_roll = gi.cvar("bob_roll", "0.002", 0);
161 
162  // flood control
163  flood_msgs = gi.cvar("flood_msgs", "4", 0);
164  flood_persecond = gi.cvar("flood_persecond", "4", 0);
165  flood_waitdelay = gi.cvar("flood_waitdelay", "10", 0);
166 
167  // dm map list
168  sv_maplist = gi.cvar("sv_maplist", "", 0);
169 
170  // obtain server features
171  sv_features = gi.cvar("sv_features", NULL, 0);
172 
173  // flare gun switch:
174  // 0 = no flare gun
175  // 1 = spawn with the flare gun
176  // 2 = spawn with the flare gun and some grenades
177  sv_flaregun = gi.cvar("sv_flaregun", "2", 0);
178 
179  // export our own features
180  gi.cvar_forceset("g_features", va("%d", G_FEATURES));
181 
182  // items
183  InitItems();
184 
185  game.helpmessage1[0] = 0;
186  game.helpmessage2[0] = 0;
187 
188  // initialize all entities for this game
189  game.maxentities = maxentities->value;
190  clamp(game.maxentities, (int)maxclients->value + 1, MAX_EDICTS);
191  g_edicts = gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
192  globals.edicts = g_edicts;
193  globals.max_edicts = game.maxentities;
194 
195  // initialize all clients for this game
196  game.maxclients = maxclients->value;
197  game.clients = gi.TagMalloc(game.maxclients * sizeof(game.clients[0]), TAG_GAME);
198  globals.num_edicts = game.maxclients + 1;
199 }
200 
201 
202 /*
203 =================
204 GetGameAPI
205 
206 Returns a pointer to the structure with all entry points
207 and global variables
208 =================
209 */
210 q_exported game_export_t *GetGameAPI(game_import_t *import)
211 {
212  gi = *import;
213 
214  globals.apiversion = GAME_API_VERSION;
215  globals.Init = InitGame;
216  globals.Shutdown = ShutdownGame;
217  globals.SpawnEntities = SpawnEntities;
218 
219  globals.WriteGame = WriteGame;
220  globals.ReadGame = ReadGame;
221  globals.WriteLevel = WriteLevel;
222  globals.ReadLevel = ReadLevel;
223 
224  globals.ClientThink = ClientThink;
225  globals.ClientConnect = ClientConnect;
226  globals.ClientUserinfoChanged = ClientUserinfoChanged;
227  globals.ClientDisconnect = ClientDisconnect;
228  globals.ClientBegin = ClientBegin;
229  globals.ClientCommand = ClientCommand;
230 
231  globals.RunFrame = G_RunFrame;
232 
233  globals.ServerCommand = ServerCommand;
234 
235  globals.edict_size = sizeof(edict_t);
236 
237  return &globals;
238 }
239 
240 #ifndef GAME_HARD_LINKED
241 // this is only here so the functions in q_shared.c can link
242 void Com_LPrintf(print_type_t type, const char *fmt, ...)
243 {
244  va_list argptr;
245  char text[MAX_STRING_CHARS];
246 
247  if (type == PRINT_DEVELOPER) {
248  return;
249  }
250 
251  va_start(argptr, fmt);
252  Q_vsnprintf(text, sizeof(text), fmt, argptr);
253  va_end(argptr);
254 
255  gi.dprintf("%s", text);
256 }
257 
258 void Com_Error(error_type_t type, const char *fmt, ...)
259 {
260  va_list argptr;
261  char text[MAX_STRING_CHARS];
262 
263  va_start(argptr, fmt);
264  Q_vsnprintf(text, sizeof(text), fmt, argptr);
265  va_end(argptr);
266 
267  gi.error("%s", text);
268 }
269 #endif
270 
271 //======================================================================
272 
273 
274 /*
275 =================
276 ClientEndServerFrames
277 =================
278 */
280 {
281  int i;
282  edict_t *ent;
283 
284  // calc the player views now that all pushing
285  // and damage has been added
286  for (i = 0 ; i < maxclients->value ; i++) {
287  ent = g_edicts + 1 + i;
288  if (!ent->inuse || !ent->client)
289  continue;
291  }
292 
293 }
294 
295 /*
296 =================
297 CreateTargetChangeLevel
298 
299 Returns the created target changelevel
300 =================
301 */
302 edict_t *CreateTargetChangeLevel(char *map)
303 {
304  edict_t *ent;
305 
306  ent = G_Spawn();
307  ent->classname = "target_changelevel";
308  Q_snprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
309  ent->map = level.nextmap;
310  return ent;
311 }
312 
313 /*
314 =================
315 EndDMLevel
316 
317 The timelimit or fraglimit has been exceeded
318 =================
319 */
320 void EndDMLevel(void)
321 {
322  edict_t *ent;
323  char *s, *t, *f;
324  static const char *seps = " ,\n\r";
325 
326  // stay on same level flag
327  if ((int)dmflags->value & DF_SAME_LEVEL) {
329  return;
330  }
331 
332  // see if it's in the map list
333  if (*sv_maplist->string) {
334  s = strdup(sv_maplist->string);
335  f = NULL;
336  t = strtok(s, seps);
337  while (t != NULL) {
338  if (Q_stricmp(t, level.mapname) == 0) {
339  // it's in the list, go to the next one
340  t = strtok(NULL, seps);
341  if (t == NULL) { // end of list, go to first one
342  if (f == NULL) // there isn't a first one, same level
344  else
346  } else
348  free(s);
349  return;
350  }
351  if (!f)
352  f = t;
353  t = strtok(NULL, seps);
354  }
355  free(s);
356  }
357 
358  if (level.nextmap[0]) // go to a specific map
360  else { // search for a changelevel
361  ent = G_Find(NULL, FOFS(classname), "target_changelevel");
362  if (!ent) {
363  // the map designer didn't include a changelevel,
364  // so create a fake ent that goes back to the same level
366  return;
367  }
368  BeginIntermission(ent);
369  }
370 }
371 
372 
373 /*
374 =================
375 CheckNeedPass
376 =================
377 */
378 void CheckNeedPass(void)
379 {
380  int need;
381 
382  // if password or spectator_password has changed, update needpass
383  // as needed
384  if (password->modified || spectator_password->modified) {
385  password->modified = spectator_password->modified = qfalse;
386 
387  need = 0;
388 
389  if (*password->string && Q_stricmp(password->string, "none"))
390  need |= 1;
391  if (*spectator_password->string && Q_stricmp(spectator_password->string, "none"))
392  need |= 2;
393 
394  gi.cvar_set("needpass", va("%d", need));
395  }
396 }
397 
398 /*
399 =================
400 CheckDMRules
401 =================
402 */
403 void CheckDMRules(void)
404 {
405  int i;
406  gclient_t *cl;
407 
409  return;
410 
411  if (!deathmatch->value)
412  return;
413 
414  if (timelimit->value) {
415  if (level.time >= timelimit->value * 60) {
416  gi.bprintf(PRINT_HIGH, "Timelimit hit.\n");
417  EndDMLevel();
418  return;
419  }
420  }
421 
422  if (fraglimit->value) {
423  for (i = 0 ; i < maxclients->value ; i++) {
424  cl = game.clients + i;
425  if (!g_edicts[i + 1].inuse)
426  continue;
427 
428  if (cl->resp.score >= fraglimit->value) {
429  gi.bprintf(PRINT_HIGH, "Fraglimit hit.\n");
430  EndDMLevel();
431  return;
432  }
433  }
434  }
435 }
436 
437 
438 /*
439 =============
440 ExitLevel
441 =============
442 */
443 void ExitLevel(void)
444 {
445  int i;
446  edict_t *ent;
447  char command [256];
448 
449  Q_snprintf(command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
450  gi.AddCommandString(command);
451  level.changemap = NULL;
455 
456  // clear some things before going to next level
457  for (i = 0 ; i < maxclients->value ; i++) {
458  ent = g_edicts + 1 + i;
459  if (!ent->inuse)
460  continue;
461  if (ent->health > ent->client->pers.max_health)
462  ent->health = ent->client->pers.max_health;
463  }
464 
465 }
466 
467 /*
468 ================
469 G_RunFrame
470 
471 Advances the world by 0.1 seconds
472 ================
473 */
474 void G_RunFrame(void)
475 {
476  int i;
477  edict_t *ent;
478 
479  level.framenum++;
481 
482  // choose a client for monsters to target this frame
484 
485  // exit intermissions
486 
487  if (level.exitintermission) {
488  ExitLevel();
489  return;
490  }
491 
492  //
493  // treat each object in turn
494  // even the world gets a chance to think
495  //
496  ent = &g_edicts[0];
497  for (i = 0 ; i < globals.num_edicts ; i++, ent++) {
498  if (!ent->inuse)
499  continue;
500 
501  level.current_entity = ent;
502 
503  VectorCopy(ent->s.origin, ent->s.old_origin);
504 
505  // if the ground entity moved, make sure we are still on it
506  if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount)) {
507  ent->groundentity = NULL;
508  if (!(ent->flags & (FL_SWIM | FL_FLY)) && (ent->svflags & SVF_MONSTER)) {
509  M_CheckGround(ent);
510  }
511  }
512 
513  if (i > 0 && i <= maxclients->value) {
515  continue;
516  }
517 
518  G_RunEntity(ent);
519  }
520 
521  // see if it is time to end a deathmatch
522  CheckDMRules();
523 
524  // see if needpass needs updated
525  CheckNeedPass();
526 
527  // build the playerstate_t structures for all players
529 }
530 
deathmatch
cvar_t * deathmatch
Definition: g_main.c:33
game
game_locals_t game
Definition: g_main.c:21
sm_meat_index
int sm_meat_index
Definition: g_main.c:27
globals
game_export_t globals
Definition: g_main.c:24
RunEntity
void RunEntity(edict_t *ent)
spawn_temp_t
Definition: g_local.h:342
ClientBeginServerFrame
void ClientBeginServerFrame(edict_t *ent)
Definition: p_client.c:1709
ReadLevel
void ReadLevel(const char *filename)
Definition: g_save.c:912
game_locals_t::helpmessage1
char helpmessage1[512]
Definition: g_local.h:268
G_Spawn
edict_t * G_Spawn(void)
Definition: g_utils.c:391
sv_maxvelocity
cvar_t * sv_maxvelocity
Definition: g_main.c:51
sv_rollangle
cvar_t * sv_rollangle
Definition: g_main.c:55
G_RunEntity
void G_RunEntity(edict_t *ent)
Definition: g_phys.c:905
filterban
cvar_t * filterban
Definition: g_main.c:49
bob_roll
cvar_t * bob_roll
Definition: g_main.c:64
level_locals_t
Definition: g_local.h:297
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
CheckNeedPass
void CheckNeedPass(void)
Definition: g_main.c:378
ClientThink
void ClientThink(edict_t *ent, usercmd_t *cmd)
Definition: p_client.c:1534
ClientUserinfoChanged
void ClientUserinfoChanged(edict_t *ent, char *userinfo)
Definition: p_client.c:1325
FRAMETIME
#define FRAMETIME
Definition: g_local.h:75
ClientConnect
qboolean ClientConnect(edict_t *ent, char *userinfo)
Definition: p_client.c:1389
GetGameAPI
q_exported game_export_t * GetGameAPI(game_import_t *import)
Definition: g_main.c:210
sv_gravity
cvar_t * sv_gravity
Definition: g_main.c:52
ClientBegin
void ClientBegin(edict_t *ent)
Definition: p_client.c:1267
ExitLevel
void ExitLevel(void)
Definition: g_main.c:443
meansOfDeath
int meansOfDeath
Definition: g_main.c:29
dedicated
cvar_t * dedicated
Definition: g_main.c:46
ClientEndServerFrames
void ClientEndServerFrames(void)
Definition: g_main.c:279
G_Find
edict_t * G_Find(edict_t *from, int fieldofs, char *match)
Definition: g_utils.c:43
G_FEATURES
#define G_FEATURES
Definition: g_local.h:30
FOFS
#define FOFS(x)
Definition: g_local.h:498
skill
cvar_t * skill
Definition: g_main.c:36
ShutdownGame
void ShutdownGame(void)
Definition: g_main.c:97
TAG_LEVEL
#define TAG_LEVEL
Definition: g_local.h:79
g_select_empty
cvar_t * g_select_empty
Definition: g_main.c:45
Q_vsnprintf
size_t Q_vsnprintf(char *dest, size_t size, const char *fmt, va_list argptr)
Definition: shared.c:791
ReadGame
void ReadGame(const char *filename)
Definition: g_save.c:810
game_locals_t
Definition: g_local.h:267
password
cvar_t * password
Definition: g_main.c:39
BeginIntermission
void BeginIntermission(edict_t *targ)
Definition: p_hud.c:70
FL_SWIM
#define FL_SWIM
Definition: g_local.h:60
ClientDisconnect
void ClientDisconnect(edict_t *ent)
Definition: p_client.c:1462
level_locals_t::current_entity
edict_t * current_entity
Definition: g_local.h:332
game_locals_t::helpmessage2
char helpmessage2[512]
Definition: g_local.h:269
run_roll
cvar_t * run_roll
Definition: g_main.c:61
gi
game_import_t gi
Definition: g_main.c:23
sv_features
cvar_t * sv_features
Definition: g_main.c:74
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
sv_flaregun
cvar_t * sv_flaregun
Definition: g_main.c:76
ServerCommand
void ServerCommand(void)
Definition: g_svcmds.c:275
maxclients
cvar_t * maxclients
Definition: g_main.c:42
va
char * va(const char *format,...)
Definition: shared.c:429
sv_maplist
cvar_t * sv_maplist
Definition: g_main.c:72
nomonsters
cvar_t * nomonsters
Definition: g_main.c:47
game_locals_t::clients
gclient_t * clients
Definition: g_local.h:273
WriteGame
void WriteGame(const char *filename, qboolean autosave)
Definition: g_save.c:784
bob_pitch
cvar_t * bob_pitch
Definition: g_main.c:63
flood_msgs
cvar_t * flood_msgs
Definition: g_main.c:68
level_locals_t::nextmap
char nextmap[MAX_QPATH]
Definition: g_local.h:303
level
level_locals_t level
Definition: g_main.c:22
Com_LPrintf
void Com_LPrintf(print_type_t type, const char *fmt,...)
Definition: g_main.c:242
g_edicts
edict_t * g_edicts
Definition: g_main.c:31
GAMEVERSION
#define GAMEVERSION
Definition: g_local.h:33
gun_y
cvar_t * gun_y
Definition: g_main.c:57
EndDMLevel
void EndDMLevel(void)
Definition: g_main.c:320
snd_fry
int snd_fry
Definition: g_main.c:28
level_locals_t::framenum
int framenum
Definition: g_local.h:298
gun_x
cvar_t * gun_x
Definition: g_main.c:56
M_CheckGround
void M_CheckGround(edict_t *ent)
Definition: g_monster.c:139
level_locals_t::exitintermission
int exitintermission
Definition: g_local.h:308
level_locals_t::time
float time
Definition: g_local.h:299
cl
client_state_t cl
Definition: main.c:99
dmflags
cvar_t * dmflags
Definition: g_main.c:35
CheckDMRules
void CheckDMRules(void)
Definition: g_main.c:403
bob_up
cvar_t * bob_up
Definition: g_main.c:62
G_RunFrame
void G_RunFrame(void)
Definition: g_main.c:474
level_locals_t::intermissiontime
float intermissiontime
Definition: g_local.h:306
timelimit
cvar_t * timelimit
Definition: g_main.c:38
sv_rollspeed
cvar_t * sv_rollspeed
Definition: g_main.c:54
CreateTargetChangeLevel
edict_t * CreateTargetChangeLevel(char *map)
Definition: g_main.c:302
level_locals_t::changemap
char * changemap
Definition: g_local.h:307
InitGame
void InitGame(void)
Definition: g_main.c:114
TAG_GAME
#define TAG_GAME
Definition: g_local.h:78
ClientEndServerFrame
void ClientEndServerFrame(edict_t *ent)
Definition: p_view.c:889
ClientCommand
void ClientCommand(edict_t *ent)
Definition: g_cmds.c:846
maxentities
cvar_t * maxentities
Definition: g_main.c:44
needpass
cvar_t * needpass
Definition: g_main.c:41
fraglimit
cvar_t * fraglimit
Definition: g_main.c:37
coop
cvar_t * coop
Definition: g_main.c:34
InitItems
void InitItems(void)
Definition: g_items.c:2132
FL_FLY
#define FL_FLY
Definition: g_local.h:59
st
spawn_temp_t st
Definition: g_main.c:25
run_pitch
cvar_t * run_pitch
Definition: g_main.c:60
maxspectators
cvar_t * maxspectators
Definition: g_main.c:43
spectator_password
cvar_t * spectator_password
Definition: g_main.c:40
WriteLevel
void WriteLevel(const char *filename)
Definition: g_save.c:866
game_locals_t::maxentities
int maxentities
Definition: g_local.h:281
flood_persecond
cvar_t * flood_persecond
Definition: g_main.c:69
level_locals_t::mapname
char mapname[MAX_QPATH]
Definition: g_local.h:302
flood_waitdelay
cvar_t * flood_waitdelay
Definition: g_main.c:70
sv_cheats
cvar_t * sv_cheats
Definition: g_main.c:66
SpawnEntities
void SpawnEntities(const char *mapname, const char *entities, const char *spawnpoint)
Definition: g_spawn.c:568
AI_SetSightClient
void AI_SetSightClient(void)
Definition: g_ai.c:47
g_local.h
gun_z
cvar_t * gun_z
Definition: g_main.c:58
game_locals_t::maxclients
int maxclients
Definition: g_local.h:280