sin-sdk/worldspawn.cpp

637 lines
15 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Quake 2 Engine/Sin/code/game/worldspawn.cpp $
// $Revision:: 97 $
// $Author:: Jimdose $
// $Date:: 11/08/98 10:49p $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/worldspawn.cpp $
//
// 97 11/08/98 10:49p Jimdose
// moved earthquake to level struct
//
// 96 10/27/98 9:46p Aldie
// Changed training cvar to level.training
//
// 95 10/27/98 6:28a Jimdose
// set model to "*1"
//
// 94 10/27/98 5:43a Jimdose
// World wasn't calling Entity::Archive or Unarchive!
// Added FreeTargetList
//
// 93 10/27/98 4:36a Markd
// reset the earthquake in worldspawn
//
// 92 10/26/98 2:16p Aldie
// Added AirClamp
//
// 91 10/21/98 2:17a Jimdose
// Fixed bug where world wiped out configstrings during loadgame
//
// 90 10/19/98 9:53p Jimdose
// changed slime variables to lightvolume
//
// 89 10/10/98 1:31a Jimdose
// moved precache scripts to G_Precache in G_Utils
// some things are no longer initialized during loadgames
//
// 88 10/08/98 12:37a Jimdose
// Made savegames work
//
// 87 9/30/98 4:36p Aldie
// Reset gravpaths when worldspawn is destroyed
//
// 86 9/27/98 6:27p Aldie
// Added water, slime, and lava colors to worldspawn
//
// 85 9/17/98 5:53p Jimdose
// create level.total_secrets and level.found_secrets on startup
//
// 84 9/02/98 7:48p Aldie
// Added support for multiple global scripts
//
// 83 8/29/98 9:48p Jimdose
// included deadbody.h
//
// 82 8/24/98 11:32a Markd
// Added Start method to threads, repladed all ProcessEvent(
// EV_ScriptThread_execute) with thread->Start( -1 )
//
// 81 8/22/98 6:34p Markd
// Revamped player readiness for scripting
//
// 80 8/21/98 5:26p Markd
// Added sv_precache and cl_precache
//
// 79 8/17/98 7:33p Jimdose
// skipthread is now initialized with G_GetStringArg since G_GetSpawnArg can
// return NULL, which the str class doesn't like
//
// 78 8/17/98 4:35p Markd
// Added skipthread and cinematic stuff to worldspawn
//
// 77 8/08/98 7:51p Jimdose
// changed realWorld to world
//
// 76 7/26/98 12:35p Jimdose
// Got rid of backslash in filename
//
// 75 7/24/98 6:22p Jimdose
// Set config string CS_MAXCLIENTS
// removed unused layout stuff
//
// 74 7/15/98 12:14a Aldie
// Updated worldspawn to send over a deathmatch flag
//
// 73 7/13/98 5:57p Markd
// Added SetGameScript call
//
// 72 7/13/98 5:01p Aldie
// Added dead player bodies with gibbing
//
// 71 7/01/98 7:04p Aldie
// Mission computer stuff
//
// 70 6/27/98 7:58p Aldie
// Moved status bar to client
//
// 69 6/27/98 2:15p Aldie
// New status bar stuff
//
// 68 6/25/98 7:33p Aldie
// New HUD
//
// 67 6/24/98 1:38p Aldie
// Implementation of inventory system and picking stuff up
//
// 66 6/20/98 7:06p Aldie
// Updated HUD for inventory
//
// 65 6/20/98 2:23p Aldie
// Added Inventory to statusbar
//
// 64 6/19/98 6:38p Aldie
// Updated status bar for inventory
//
// 63 6/10/98 2:10p Aldie
// Updated damage function.
//
// 62 6/09/98 4:24p Jimdose
// Added multi-file scripting, so hacks to load multifiles were removed.
//
// 61 6/05/98 6:26p Aldie
// Updated stats bar for armor.
//
// 60 5/26/98 4:21p Markd
// Added TargetList stuff
//
// 59 5/25/98 2:28p Aldie
// Fixed issues with not loading game dll
//
// 58 5/24/98 2:46p Markd
// Made char *'s into const char *'s
//
// 57 5/19/98 11:13p Aldie
// Fixed statusbars for higher res
//
// 56 5/18/98 6:15p Aldie
// Updated ammo bar.
//
// 55 5/14/98 10:20p Jimdose
// world is now an EntityPtr
//
// 54 5/04/98 8:32p Markd
// Removed setlightstyle stuff
//
// 53 5/04/98 11:31a Markd
// Moved lightstyles into global.scr
//
// 52 5/02/98 9:39p Markd
// Fixed the gunsmoke lightstyle
//
// 51 5/02/98 8:47p Markd
// Took out a lot of precache stuff
//
// 50 5/01/98 5:07p Jimdose
// Changed *world to an Entity *
//
// 49 5/01/98 10:42a Markd
// Put in global.scr and precache.scr parsing
//
// 48 4/18/98 8:20p Markd
// Fixed sniperrifle precache
//
// 47 4/18/98 7:43p Markd
// Added correct weapon names to precache section
//
// 46 4/18/98 6:35p Aldie
// Updated sbar layout
//
// 45 4/18/98 6:12p Aldie
// Updated ammo stats bar.
//
// 44 4/16/98 8:40p Aldie
// Added DM status bar to new system
//
// 43 4/16/98 7:46p Aldie
// Added new status bar
//
// 42 4/10/98 1:24a Markd
// Added FL_SPARKS and FL_BLASTMARK flags
//
// 41 4/07/98 8:00p Markd
// removed defhandle, changed all SINMDL calls to modelindex calls, removed
// SINMDL prefix
//
// 40 4/03/98 3:37p Jimdose
// Got rid of disabled status bar
//
// 39 4/03/98 2:30p Jimdose
// Temporarily turned off status bar
//
// 38 4/02/98 4:52p Jimdose
// Changed stat bar layouts
//
// 37 3/31/98 4:21p Jimdose
// added precaches
//
// 36 3/31/98 1:19p Jimdose
// Precached footsteps
//
// 35 3/30/98 11:39p Markd
// Added modelIndex stuff
//
// 34 3/27/98 11:04p Jimdose
// changed explode.def to explode.spr
//
// 33 3/26/98 7:15p Aldie
// Added console type vars.
//
// 32 3/23/98 1:31p Jimdose
// Revamped event and command system
//
// 31 3/18/98 7:21p Jimdose
// Added precache for explosion sprite
//
// 30 3/02/98 8:49p Jimdose
// Changed the classid parameter of CLASS_DECLARATION to a quoted string so
// that you could have a NULL classid.
//
// 29 2/23/98 6:38p Jimdose
//
// 28 2/17/98 7:00p Jimdose
// levelVars are cleared upon spawning the world
//
// 27 2/16/98 2:06p Jimdose
// Changed movetype from MOVETYPE_PUSH to MOVETYPE_NONE, since the world
// shouldn't be moving around.
//
// 26 2/10/98 11:44a Jimdose
// Changed color of worldspawn in Sined
//
// 25 2/06/98 5:48p Jimdose
// Moved sined header to .cpp file.
// Prepended "maps/" to script file name
//
// 24 2/03/98 10:56a Jimdose
// Updated to work with Quake 2 engine
// Moved initialization to constructor and removed Init function
// Removed precache stuff (it was all out of date anyway).
//
// 22 12/15/97 4:32p Jimdose
// Precached new shotgun sounds
//
// 21 12/15/97 2:51p Markd
// Added speargun firing sounds
//
// 20 12/15/97 11:56a Markd
// Added speargun sounds
//
// 19 12/14/97 5:54p Jimdose
// Removed wrong check-in comment #18: " Added BettySpike"
// Changed precache of spear\spear.def to spear.def.
//
// 17 12/14/97 5:34p Markd
// Put in precaches for rocket launcher stuff
//
// 16 12/13/97 7:42p Markd
// Added RocketLauncher sound
//
// 15 12/13/97 6:52p Aldie
// Added precache for shotgun
//
// 14 12/12/97 1:19p Markd
// Added rocket launcher precache
//
// 13 12/06/97 12:35p Aldie
// Added tracer sprite to precache
//
// 12 11/18/97 5:26p Markd
// Changed model from sub-directory to parent directory for magnum.def
//
// 11 11/10/97 8:38p Jimdose
// Removed getMapTitle. Map name is now stored in netname.
// Made StartFrame get called indirectly through EVENT_PRETHINK.
// Added event function.
//
// 10 11/07/97 6:00p Markd
// Removed QUAKE specific sound effects prespawns
//
// 9 10/31/97 7:19p Markd
// Added precache for sprites
//
// 8 10/28/97 8:36p Jimdose
// Moved magnum model
//
// 7 10/28/97 8:20p Jimdose
// Added precache for bubble and spear
//
// 6 10/28/97 6:54p Markd
// Added precache for darkcaptain sound
//
// 5 10/27/97 3:29p Jimdose
// Removed dependency on quakedef.h
//
// 4 10/24/97 8:13p Jimdose
// Added precache for magnum
//
// 3 9/26/97 6:14p Jimdose
// Added standard Ritual headers
//
// DESCRIPTION:
// Base class for worldspawn objects. This should be subclassed whenever
// a DLL has new game behaviour that needs to be initialized before any other
// entities are created, or before any entity thinks each frame. Also controls
// spawning of clients.
//
#include "g_local.h"
#include "entity.h"
#include "scriptmaster.h"
#include "worldspawn.h"
#include "surface.h"
#include "console.h"
#include "deadbody.h"
#include "gravpath.h"
#include "earthquake.h"
extern void CreateMissionComputer( void );
WorldPtr world;
/*****************************************************************************/
/*SINED worldspawn (0 0 0) ? CINEMATIC
Only used for the world.
"sky" environment map name
"skyaxis" vector axis for rotating sky
"skyrotate" speed of rotation in degrees/second
"cdtrack" music cd track number
"gravity" 800 is default gravity
"message" text to print at user logon
"skipthread" thread that is activated to skip this level (if cinematic)
/*****************************************************************************/
#define CINEMATIC 1
CLASS_DECLARATION( Entity, World, "worldspawn" );
ResponseDef World::Responses[] =
{
{ NULL, NULL }
};
World::World()
{
const char *text;
str mapname;
int i;
Vector water_color;
Vector lightvolume_color;
Vector lava_color;
world = this;
setMoveType( MOVETYPE_NONE );
setSolidType( SOLID_BSP );
// world model is always index 1
edict->s.modelindex = 1;
model = "*1";
// Anything that modifies configstrings, or spawns things is ignored when loading savegames
if ( LoadingSavegame )
{
return;
}
// inform the client that this is deathmatch, and we should
// draw deathmatch stats. This goes around what the CS_STATUSBAR
// used to be used for since we moved all HUDS to the client.
if ( deathmatch->value )
{
gi.configstring( CS_STATUSBAR, "DEATHMATCH" );
}
else
{
gi.configstring( CS_STATUSBAR, "SINGLE_PLAYER" );
}
//
// see if the level has a soundtrack associated withit
//
text = G_GetSpawnArg( "soundtrack" );
if ( text )
{
gi.configstring( CS_SOUNDTRACK, text );
}
text = G_GetSpawnArg( "sky" );
if ( text )
{
gi.configstring( CS_SKY, text );
}
else
{
gi.configstring( CS_SKY, "sky_" );
}
text = G_GetSpawnArg( "skyrotate" );
gi.configstring( CS_SKYROTATE, text ? text : "0" );
text = G_GetSpawnArg( "skyaxis" );
gi.configstring( CS_SKYAXIS, text ? text : "0 0 0" );
text = G_GetSpawnArg( "cdtrack" );
gi.configstring( CS_CDTRACK, text ? text : "0" );
gi.configstring (CS_MAXCLIENTS, va("%i", (int)(maxclients->value) ) );
text = G_GetSpawnArg( "gravity" );
if ( !text )
{
gi.cvar_set( "sv_gravity", "800" );
}
else
{
gi.cvar_set( "sv_gravity", text );
}
// get skipthread
skipthread = G_GetStringArg( "skipthread" );
// the world takes blast marks and sparks by default
flags |= FL_BLASTMARK;
flags |= FL_SPARKS;
// Reserve some space for dead bodies
InitializeBodyQueue();
//
// see if this is a cinematic level
//
if ( spawnflags & CINEMATIC )
{
level.cinematic = true;
}
else
{
level.cinematic = false;
}
level.nextmap = G_GetStringArg( "nextmap" );
// make some data visible to the server
text = G_GetSpawnArg( "message" );
if ( text )
{
gi.configstring( CS_NAME, text );
level.level_name = text;
}
else
{
level.level_name = level.mapname;
}
// Set up script
text = G_GetSpawnArg( "script" );
if ( !text )
{
// No script specified. Try using the mapname as the script name
mapname = "maps/";
mapname += level.mapname;
for( i = mapname.length() - 1; i >= 0; i-- )
{
if ( mapname[ i ] == '.' )
{
mapname[ i ] = 0;
break;
}
}
mapname += ".scr";
text = &mapname[ 5 ];
// If there isn't a script with the same name as the map, then don't try to load script
if ( gi.LoadFile( mapname.c_str(), NULL, 0 ) == -1 )
{
text = NULL;
}
}
if ( text )
{
gi.dprintf( "Adding script: '%s'\n", text );
mapname = va( "maps/%s", text );
// just set the script, we will start it in G_Spawn
ScriptLib.SetGameScript( mapname.c_str() );
}
// Set the color for the blends.
water_color = G_GetVectorArg("watercolor",Vector(0,0,1));
level.water_alpha = G_GetFloatArg("wateralpha",0.1);
lightvolume_color = G_GetVectorArg("lightcolor",Vector(1,1,1));
level.lightvolume_alpha = G_GetFloatArg("lightalpha",0.5);
lava_color = G_GetVectorArg("lavacolor",Vector(1.0,0.3,0));
level.lava_alpha = G_GetFloatArg("lavaalpha",0.6);
level.water_color = water_color;
level.lightvolume_color = lightvolume_color;
level.lava_color = lava_color;
//
// reset the earthquake
//
level.earthquake = 0;
}
TargetList * World::GetTargetList( str &targetname )
{
TargetList * targetlist;
int i;
for( i = 1; i <= targetList.NumObjects(); i++ )
{
targetlist = targetList.ObjectAt( i );
if ( targetname == targetlist->targetname)
return targetlist;
}
targetlist = new TargetList( targetname );
targetList.AddObject( targetlist );
return targetlist;
}
void World::AddTargetEntity( str &targetname, Entity * ent )
{
TargetList * targetlist;
targetlist = GetTargetList( targetname );
targetlist->AddEntity( ent );
}
void World::RemoveTargetEntity( str &targetname, Entity * ent )
{
TargetList * targetlist;
targetlist = GetTargetList( targetname );
targetlist->RemoveEntity( ent );
}
Entity * World::GetNextEntity( str &targetname, Entity * ent )
{
TargetList * targetlist;
targetlist = GetTargetList( targetname );
return targetlist->GetNextEntity( ent );
}
World::~World()
{
FreeTargetList();
}
void World::FreeTargetList
(
void
)
{
int i;
int num;
num = targetList.NumObjects();
for( i = 1; i <= num; i++ )
{
delete targetList.ObjectAt( i );
}
targetList.FreeObjectList();
}
//
// List stuff for targets
//
CLASS_DECLARATION( Class, TargetList, NULL );
ResponseDef TargetList::Responses[] =
{
{ NULL, NULL }
};
TargetList::TargetList()
{
}
TargetList::TargetList( str &tname )
{
targetname = tname;
}
TargetList::~TargetList()
{
}
void TargetList::AddEntity( Entity * ent )
{
if ( !list.ObjectInList( ent ) )
{
list.AddObject( ent );
}
}
void TargetList::RemoveEntity( Entity * ent )
{
if ( list.ObjectInList( ent ) )
{
list.RemoveObject( ent );
}
}
Entity * TargetList::GetNextEntity( Entity * ent )
{
int index;
index = 0;
if ( ent )
index = list.IndexOfObject( ent );
index++;
if ( index > list.NumObjects() )
return NULL;
else
return list.ObjectAt( index );
}