thirtyflightsofloving/3zb2/g_main.c

650 lines
12 KiB
C
Raw Normal View History

#include "g_local.h"
#include "bot.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 *filterban;
//ZOID
cvar_t *capturelimit;
//ZOID
cvar_t *password;
cvar_t *spectator_password;
cvar_t *maxclients;
cvar_t *maxspectators;
cvar_t *maxentities;
cvar_t *g_select_empty;
cvar_t *dedicated;
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;
//ponpoko
cvar_t *gamepath;
cvar_t *chedit;
cvar_t *vwep;
cvar_t *maplist;
cvar_t *botlist;
cvar_t *autospawn;
cvar_t *zigmode;
cvar_t *mega_gibs; // Knightmare- Octavian's modified gibs
float spawncycle;
float ctfjob_update;
//ponpoko
cvar_t *turn_rider; // Knightmare added
void SpawnEntities (char *mapname, char *entities, char *spawnpoint);
void ClientThink (edict_t *ent, usercmd_t *cmd);
qboolean ClientConnect (edict_t *ent, char *userinfo, qboolean loadgame);
void ClientUserinfoChanged (edict_t *ent, char *userinfo);
void ClientDisconnect (edict_t *ent);
void ClientBegin (edict_t *ent, qboolean loadgame);
void ClientCommand (edict_t *ent);
void RunEntity (edict_t *ent);
void WriteGame (char *filename);
void ReadGame (char *filename);
void WriteLevel (char *filename);
void ReadLevel (char *filename);
void InitGame (void);
void G_RunFrame (void);
void SetBotFlag1(edict_t *ent); //<2F>`<60>[<5B><>1<EFBFBD>ÌŠ<EFBFBD>
void SetBotFlag2(edict_t *ent); //<2F>`<60>[<5B><>2<EFBFBD>ÌŠ<EFBFBD>
//===================================================================
/*
=================
GetGameAPI
Returns a pointer to the structure with all entry points
and global variables
=================
*/
void ShutdownGame (void)
{
gi.dprintf ("==== ShutdownGame ====\n");
// Bot_LevelChange();
gi.FreeTags (TAG_LEVEL);
gi.FreeTags (TAG_GAME);
SetBotFlag1(NULL);
SetBotFlag2(NULL);
}
//void Dummy (void) {};
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 and q_shwin.c can link
void Sys_Error (char *error, ...)
{
va_list argptr;
char text[1024];
va_start (argptr, error);
// vsprintf (text, error, argptr);
Q_vsnprintf (text, sizeof(text), error, argptr);
va_end (argptr);
gi.error (ERR_FATAL, "%s", text);
}
void Com_Printf (char *msg, ...)
{
va_list argptr;
char text[1024];
va_start (argptr, msg);
// vsprintf (text, msg, argptr);
Q_vsnprintf (text, sizeof(text), msg, argptr);
va_end (argptr);
gi.dprintf ("%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;
if (!(ent->svflags & SVF_MONSTER))
ClientEndServerFrame (ent);
}
}
/*
=================
GetNextMap
get next map's file name
=================
*/
void Get_NextMap (void)
{
FILE *fp;
qboolean firstflag = false;
char Buff[MAX_QPATH];
char top[MAX_QPATH];
char nextmap[MAX_QPATH];
int i;
if (!maplist->string) return;
Com_sprintf (Buff, sizeof(Buff), ".\\%s\\3ZBMAPS.LST", gamepath->string);
fp = fopen(Buff,"r");
if (fp == NULL) return;
//search section
while(1)
{
if (fgets( Buff, sizeof(Buff), fp ) == NULL) goto NONEXTMAP;
if (Buff[0] != '[') continue;
i = 0;
while(1)
{
if (Buff[i] == ']') Buff[i] = 0;
if (Buff[i] == 0) break;
if (++i >= sizeof(Buff))
{
Buff[i - 1] = 0;
break;
}
}
//compare map section name
if (Q_stricmp (&Buff[1], maplist->string) == 0) break;
}
// search current mapname
while (1)
{
if (fgets( Buff, sizeof(Buff), fp ) == NULL) goto NONEXTMAP;
if (Buff[0] == '[')
{
if ( firstflag )
{
Com_strcpy (nextmap, sizeof(nextmap),top);
goto SETNEXTMAP;
}
else goto NONEXTMAP;
}
if (Buff[0] == '\n') continue;
// sscanf(Buff, "%s", nextmap);
if (sscanf(Buff, "%s", nextmap) == EOF) {
gi.dprintf ("Get_NextMap: invalid mapname '%s'.\n", Buff);
}
if (!firstflag)
{
firstflag = true;
Com_strcpy (top, sizeof(top), nextmap);
}
if (Q_stricmp (level.mapname, nextmap) == 0) break;
}
// search nextmap
while (1)
{
if (fgets( Buff, sizeof(Buff), fp ) == NULL)
{
if ( firstflag )
{
Com_strcpy (nextmap, sizeof(nextmap) ,top);
goto SETNEXTMAP;
}
else goto NONEXTMAP;
}
if (Buff[0] == '[')
{
if ( firstflag )
{
Com_strcpy (nextmap, sizeof(nextmap), top);
goto SETNEXTMAP;
}
else goto NONEXTMAP;
}
if (Buff[0] == '\n') continue;
// sscanf(Buff, "%s", nextmap);
if (sscanf(Buff, "%s" ,nextmap) == EOF) {
gi.dprintf ("Get_NextMap: invalid nextmap '%s'.\n", Buff);
}
break;
}
SETNEXTMAP:
Com_strcpy (level.nextmap, sizeof(level.nextmap), nextmap);
NONEXTMAP:
fclose(fp);
}
/*
=================
EndDMLevel
The timelimit or fraglimit has been exceeded
=================
*/
void EndDMLevel (void)
{
edict_t *ent;
Get_NextMap();
// stay on same level flag
if ((int)dmflags->value & DF_SAME_LEVEL)
{
ent = G_Spawn ();
ent->classname = "target_changelevel";
ent->map = level.mapname;
}
else if (level.nextmap)
{ // go to a specific map
ent = G_Spawn ();
ent->classname = "target_changelevel";
ent->map = level.nextmap;
}
else
{ // search for a changeleve
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
ent = G_Spawn ();
ent->classname = "target_changelevel";
ent->map = level.mapname;
}
}
BeginIntermission (ent);
//PONKO
Bot_LevelChange();
//PONKO
}
/*
=================
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 = false;
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;
}
}
// Fix by Bouman- allow capturelimit without fraglimit set
if ( ctf->value && CTFCheckRules() ) {
EndDMLevel ();
return;
}
// end Bouman fix
if (fraglimit->value)
{
//ZOID
/* if (ctf->value) {
if (CTFCheckRules()) {
EndDMLevel ();
}
}*/
//ZOID
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];
Com_sprintf (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;
}
SetBotFlag1(NULL);
SetBotFlag2(NULL);
//ZOID
CTFInit();
//ZOID
}
/*
================
G_RunFrame
Advances the world by 0.1 seconds
================
*/
void G_InitEdict (edict_t *e);
void G_RunFrame (void)
{
int i,j;
static int ofs;
static float next_fragadd = 0;
edict_t *ent;
vec3_t v,vv;
qboolean haveflag;
// gitem_t *item;
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;
}
#if 0
if ( use_techs->value || (ctf->value && !((int)dmflags->value & DF_CTF_NO_TECH)) )
CheckNumTechs ();
#endif
//
// Bot Spawning
//
if (SpawnWaitingBots && !level.intermissiontime)
{
if (spawncycle < level.time)
{
Bot_SpawnCall();
spawncycle = level.time + FRAMETIME * 10 + 0.01 * SpawnWaitingBots;
}
}
else
{
if (spawncycle < level.time) spawncycle = level.time + FRAMETIME * 10;
}
//
// treat each object in turn
// even the world gets a chance to think
//
haveflag = false;
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);
}
}
//ctf job assign
if (ctf->value)
{
if (ctfjob_update < level.time)
{
//gi.bprintf(PRINT_HIGH,"Assigned!!!\n");
CTFJobAssign();
ctfjob_update = level.time + FRAMETIME * 2;
}
}
//////////<2F><><EFBFBD>̃X<CC83>R<EFBFBD>A<EFBFBD>`<60>F<EFBFBD>b<EFBFBD>N
if (zigmode->value == 1)
{
if (next_fragadd < level.time)
{
if (i > 0 && i <= maxclients->value && g_edicts[i].client)
{
if (g_edicts[i].client->pers.inventory[ITEM_INDEX(zflag_item)])
{
zflag_ent = NULL;
haveflag = true;
gi.sound(ent, CHAN_VOICE, gi.soundindex("misc/secret.wav"), 1, ATTN_NORM, 0);
if (!((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
g_edicts[i].client->resp.score += 1;
else
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>ƃt<C683><74><EFBFBD>b<EFBFBD>O<EFBFBD>𑫂<EFBFBD>
for ( j = 1 ; j <= maxclients->value ; j++)
{
if (g_edicts[j].inuse)
{
if (OnSameTeam(&g_edicts[i],&g_edicts[j]))
g_edicts[j].client->resp.score += 1;
}
}
}
}
}
if (zflag_ent != NULL)
{
if (!zflag_ent->inuse)
{
// item = FindItem("Zig Flag");
SelectSpawnPoint (ent, v, vv);
// VectorCopy (v, ent->s.origin);
if (ZIGDrop_Flag(ent,zflag_item))
{
VectorCopy (v, zflag_ent->s.origin);
}
}
}
}
}
/////////////
if (i > 0 && i <= maxclients->value && !(ent->svflags & SVF_MONSTER))
{
ClientBeginServerFrame (ent);
continue;
}
G_RunEntity (ent);
}
if (next_fragadd < level.time)
{
if (zflag_ent == NULL && !haveflag && !ctf->value
&& zigmode->value == 1 && zigflag_spawn == 2)
{
SelectSpawnPoint (ent, v, vv);
//VectorCopy (v, ent->s.origin);
if (ZIGDrop_Flag(ent,zflag_item))
{
VectorCopy (v, zflag_ent->s.origin);
}
}
next_fragadd = level.time + FRAMETIME * 100;
}
// 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 ();
}