summaryrefslogtreecommitdiff
path: root/source/baseq2/g_main.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2009-05-30 11:46:41 +0000
committerAndrey Nazarov <skuller@skuller.net>2009-05-30 11:46:41 +0000
commit629da4a589f507bc1f193f5901d1679f307efc62 (patch)
treeb45e726e181f9f67196dd4f9f08be3228736a0d6 /source/baseq2/g_main.c
parent3ef036028a652f979a4197dd4a2ddd779e437597 (diff)
Imported baseq2 game source.
Replaced ‘--enable-openffa’ configure script option with ‘--enable-baseq2’. Changed Debian package description.
Diffstat (limited to 'source/baseq2/g_main.c')
-rw-r--r--source/baseq2/g_main.c464
1 files changed, 464 insertions, 0 deletions
diff --git a/source/baseq2/g_main.c b/source/baseq2/g_main.c
new file mode 100644
index 0000000..fd20f24
--- /dev/null
+++ b/source/baseq2/g_main.c
@@ -0,0 +1,464 @@
+/*
+Copyright (C) 1997-2001 Id Software, Inc.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "g_local.h"
+
+game_locals_t game;
+level_locals_t level;
+game_import_t gi;
+game_export_t globals;
+spawn_temp_t st;
+
+int sm_meat_index;
+int snd_fry;
+int meansOfDeath;
+
+edict_t *g_edicts;
+
+cvar_t *deathmatch;
+cvar_t *coop;
+cvar_t *dmflags;
+cvar_t *skill;
+cvar_t *fraglimit;
+cvar_t *timelimit;
+cvar_t *password;
+cvar_t *spectator_password;
+cvar_t *needpass;
+cvar_t *maxclients;
+cvar_t *maxspectators;
+cvar_t *maxentities;
+cvar_t *g_select_empty;
+cvar_t *dedicated;
+
+cvar_t *filterban;
+
+cvar_t *sv_maxvelocity;
+cvar_t *sv_gravity;
+
+cvar_t *sv_rollspeed;
+cvar_t *sv_rollangle;
+cvar_t *gun_x;
+cvar_t *gun_y;
+cvar_t *gun_z;
+
+cvar_t *run_pitch;
+cvar_t *run_roll;
+cvar_t *bob_up;
+cvar_t *bob_pitch;
+cvar_t *bob_roll;
+
+cvar_t *sv_cheats;
+
+cvar_t *flood_msgs;
+cvar_t *flood_persecond;
+cvar_t *flood_waitdelay;
+
+cvar_t *sv_maplist;
+
+void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
+void ClientThink (edict_t *ent, usercmd_t *cmd);
+qboolean ClientConnect (edict_t *ent, char *userinfo);
+void ClientUserinfoChanged (edict_t *ent, char *userinfo);
+void ClientDisconnect (edict_t *ent);
+void ClientBegin (edict_t *ent);
+void ClientCommand (edict_t *ent);
+void RunEntity (edict_t *ent);
+void WriteGame (char *filename, qboolean autosave);
+void ReadGame (char *filename);
+void WriteLevel (char *filename);
+void ReadLevel (char *filename);
+void InitGame (void);
+void G_RunFrame (void);
+
+
+//===================================================================
+
+
+void ShutdownGame (void)
+{
+ gi.dprintf ("==== ShutdownGame ====\n");
+
+ gi.FreeTags (TAG_LEVEL);
+ gi.FreeTags (TAG_GAME);
+}
+
+
+/*
+=================
+GetGameAPI
+
+Returns a pointer to the structure with all entry points
+and global variables
+=================
+*/
+EXPORTED game_export_t *GetGameAPI (game_import_t *import)
+{
+ gi = *import;
+
+ globals.apiversion = GAME_API_VERSION;
+ globals.Init = InitGame;
+ globals.Shutdown = ShutdownGame;
+ globals.SpawnEntities = SpawnEntities;
+
+ globals.WriteGame = WriteGame;
+ globals.ReadGame = ReadGame;
+ globals.WriteLevel = WriteLevel;
+ globals.ReadLevel = ReadLevel;
+
+ globals.ClientThink = ClientThink;
+ globals.ClientConnect = ClientConnect;
+ globals.ClientUserinfoChanged = ClientUserinfoChanged;
+ globals.ClientDisconnect = ClientDisconnect;
+ globals.ClientBegin = ClientBegin;
+ globals.ClientCommand = ClientCommand;
+
+ globals.RunFrame = G_RunFrame;
+
+ globals.ServerCommand = ServerCommand;
+
+ globals.edict_size = sizeof(edict_t);
+
+ return &globals;
+}
+
+#ifndef GAME_HARD_LINKED
+// this is only here so the functions in q_shared.c can link
+void Com_Printf( const char *fmt, ... ) {
+ va_list argptr;
+ char text[MAX_STRING_CHARS];
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( text, sizeof( text ), fmt, argptr );
+ va_end( argptr );
+
+ gi.dprintf( "%s", text );
+}
+
+void Com_DPrintf( const char *fmt, ... ) {
+}
+
+void Com_WPrintf( const char *fmt, ... ) {
+ va_list argptr;
+ char text[MAX_STRING_CHARS];
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( text, sizeof( text ), fmt, argptr );
+ va_end( argptr );
+
+ gi.dprintf( "WARNING: %s", text );
+}
+
+void Com_EPrintf( const char *fmt, ... ) {
+ va_list argptr;
+ char text[MAX_STRING_CHARS];
+
+ va_start( argptr, fmt );
+ Q_vsnprintf( text, sizeof( text ), fmt, argptr );
+ va_end( argptr );
+
+ gi.dprintf( "ERROR: %s", text );
+}
+
+void Com_Error( comErrorType_t err_level, const char *error, ... ) {
+ va_list argptr;
+ char text[MAX_STRING_CHARS];
+
+ va_start( argptr, error );
+ Q_vsnprintf( text, sizeof( text ), error, argptr );
+ va_end( argptr );
+
+ gi.error( "%s", text );
+}
+#endif
+
+//======================================================================
+
+
+/*
+=================
+ClientEndServerFrames
+=================
+*/
+void ClientEndServerFrames (void)
+{
+ int i;
+ edict_t *ent;
+
+ // calc the player views now that all pushing
+ // and damage has been added
+ for (i=0 ; i<maxclients->value ; i++)
+ {
+ ent = g_edicts + 1 + i;
+ if (!ent->inuse || !ent->client)
+ continue;
+ ClientEndServerFrame (ent);
+ }
+
+}
+
+/*
+=================
+CreateTargetChangeLevel
+
+Returns the created target changelevel
+=================
+*/
+edict_t *CreateTargetChangeLevel(char *map)
+{
+ edict_t *ent;
+
+ ent = G_Spawn ();
+ ent->classname = "target_changelevel";
+ Q_snprintf(level.nextmap, sizeof(level.nextmap), "%s", map);
+ ent->map = level.nextmap;
+ return ent;
+}
+
+/*
+=================
+EndDMLevel
+
+The timelimit or fraglimit has been exceeded
+=================
+*/
+void EndDMLevel (void)
+{
+ edict_t *ent;
+ char *s, *t, *f;
+ static const char *seps = " ,\n\r";
+
+ // stay on same level flag
+ if ((int)dmflags->value & DF_SAME_LEVEL)
+ {
+ BeginIntermission (CreateTargetChangeLevel (level.mapname) );
+ return;
+ }
+
+ // see if it's in the map list
+ if (*sv_maplist->string) {
+ s = strdup(sv_maplist->string);
+ f = NULL;
+ t = strtok(s, seps);
+ while (t != NULL) {
+ if (Q_stricmp(t, level.mapname) == 0) {
+ // it's in the list, go to the next one
+ t = strtok(NULL, seps);
+ if (t == NULL) { // end of list, go to first one
+ if (f == NULL) // there isn't a first one, same level
+ BeginIntermission (CreateTargetChangeLevel (level.mapname) );
+ else
+ BeginIntermission (CreateTargetChangeLevel (f) );
+ } else
+ BeginIntermission (CreateTargetChangeLevel (t) );
+ free(s);
+ return;
+ }
+ if (!f)
+ f = t;
+ t = strtok(NULL, seps);
+ }
+ free(s);
+ }
+
+ if (level.nextmap[0]) // go to a specific map
+ BeginIntermission (CreateTargetChangeLevel (level.nextmap) );
+ else { // search for a changelevel
+ ent = G_Find (NULL, FOFS(classname), "target_changelevel");
+ if (!ent)
+ { // the map designer didn't include a changelevel,
+ // so create a fake ent that goes back to the same level
+ BeginIntermission (CreateTargetChangeLevel (level.mapname) );
+ return;
+ }
+ BeginIntermission (ent);
+ }
+}
+
+
+/*
+=================
+CheckNeedPass
+=================
+*/
+void CheckNeedPass (void)
+{
+ int need;
+
+ // if password or spectator_password has changed, update needpass
+ // as needed
+ if (password->modified || spectator_password->modified)
+ {
+ password->modified = spectator_password->modified = qfalse;
+
+ need = 0;
+
+ if (*password->string && Q_stricmp(password->string, "none"))
+ need |= 1;
+ if (*spectator_password->string && Q_stricmp(spectator_password->string, "none"))
+ need |= 2;
+
+ gi.cvar_set("needpass", va("%d", need));
+ }
+}
+
+/*
+=================
+CheckDMRules
+=================
+*/
+void CheckDMRules (void)
+{
+ int i;
+ gclient_t *cl;
+
+ if (level.intermissiontime)
+ return;
+
+ if (!deathmatch->value)
+ return;
+
+ if (timelimit->value)
+ {
+ if (level.time >= timelimit->value*60)
+ {
+ gi.bprintf (PRINT_HIGH, "Timelimit hit.\n");
+ EndDMLevel ();
+ return;
+ }
+ }
+
+ if (fraglimit->value)
+ {
+ for (i=0 ; i<maxclients->value ; i++)
+ {
+ cl = game.clients + i;
+ if (!g_edicts[i+1].inuse)
+ continue;
+
+ if (cl->resp.score >= fraglimit->value)
+ {
+ gi.bprintf (PRINT_HIGH, "Fraglimit hit.\n");
+ EndDMLevel ();
+ return;
+ }
+ }
+ }
+}
+
+
+/*
+=============
+ExitLevel
+=============
+*/
+void ExitLevel (void)
+{
+ int i;
+ edict_t *ent;
+ char command [256];
+
+ Q_snprintf (command, sizeof(command), "gamemap \"%s\"\n", level.changemap);
+ gi.AddCommandString (command);
+ level.changemap = NULL;
+ level.exitintermission = 0;
+ level.intermissiontime = 0;
+ ClientEndServerFrames ();
+
+ // clear some things before going to next level
+ for (i=0 ; i<maxclients->value ; i++)
+ {
+ ent = g_edicts + 1 + i;
+ if (!ent->inuse)
+ continue;
+ if (ent->health > ent->client->pers.max_health)
+ ent->health = ent->client->pers.max_health;
+ }
+
+}
+
+/*
+================
+G_RunFrame
+
+Advances the world by 0.1 seconds
+================
+*/
+void G_RunFrame (void)
+{
+ int i;
+ edict_t *ent;
+
+ level.framenum++;
+ level.time = level.framenum*FRAMETIME;
+
+ // choose a client for monsters to target this frame
+ AI_SetSightClient ();
+
+ // exit intermissions
+
+ if (level.exitintermission)
+ {
+ ExitLevel ();
+ return;
+ }
+
+ //
+ // treat each object in turn
+ // even the world gets a chance to think
+ //
+ ent = &g_edicts[0];
+ for (i=0 ; i<globals.num_edicts ; i++, ent++)
+ {
+ if (!ent->inuse)
+ continue;
+
+ level.current_entity = ent;
+
+ VectorCopy (ent->s.origin, ent->s.old_origin);
+
+ // if the ground entity moved, make sure we are still on it
+ if ((ent->groundentity) && (ent->groundentity->linkcount != ent->groundentity_linkcount))
+ {
+ ent->groundentity = NULL;
+ if ( !(ent->flags & (FL_SWIM|FL_FLY)) && (ent->svflags & SVF_MONSTER) )
+ {
+ M_CheckGround (ent);
+ }
+ }
+
+ if (i > 0 && i <= maxclients->value)
+ {
+ ClientBeginServerFrame (ent);
+ continue;
+ }
+
+ G_RunEntity (ent);
+ }
+
+ // see if it is time to end a deathmatch
+ CheckDMRules ();
+
+ // see if needpass needs updated
+ CheckNeedPass ();
+
+ // build the playerstate_t structures for all players
+ ClientEndServerFrames ();
+}
+