2018-04-22 15:55:55 +00:00
/***
*
* Copyright ( c ) 1999 , Valve LLC . All rights reserved .
*
* This product contains software technology licensed from Id
* Software , Inc . ( " Id Technology " ) . Id Technology ( c ) 1996 Id Software , Inc .
* All Rights Reserved .
*
* Use , distribution , and modification of this source code and / or resulting
* object code is restricted to non - commercial enhancements to products from
* Valve LLC . All other use , distribution , or modification is prohibited
* without written permission from Valve LLC .
*
* * * */
/*
= = = = = world . cpp = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
precaches and defs for entities and other data that must always be available .
*/
# include "../util/nowarnings.h"
# include "extdll.h"
# include "util.h"
# include "cbase.h"
# include "nodes.h"
# include "soundent.h"
# include "client.h"
# include "decals.h"
# include "skill.h"
# include "effects.h"
# include "player.h"
# include "weapons.h"
# include "gamerules.h"
# include "teamplay_gamerules.h"
# include "../mod/AvHGamerules.h"
# include "../mod/AvHServerVariables.h"
# include "pm_shared/pm_defs.h"
extern CGraph WorldGraph ;
extern CSoundEnt * pSoundEnt ;
DLL_GLOBAL edict_t * g_pBodyQueueHead ;
CGlobalState gGlobalState ;
extern DLL_GLOBAL int gDisplayTitle ;
extern playermove_t * pmove ;
extern void W_Precache ( void ) ;
//
// This must match the list in util.h
//
DLL_DECALLIST gDecals [ ] = {
{ " {shot1 " , 0 } , // DECAL_GUNSHOT1
{ " {shot2 " , 0 } , // DECAL_GUNSHOT2
{ " {shot3 " , 0 } , // DECAL_GUNSHOT3
{ " {shot4 " , 0 } , // DECAL_GUNSHOT4
{ " {shot5 " , 0 } , // DECAL_GUNSHOT5
{ " {lambda01 " , 0 } , // DECAL_LAMBDA1
{ " {lambda02 " , 0 } , // DECAL_LAMBDA2
{ " {lambda03 " , 0 } , // DECAL_LAMBDA3
{ " {lambda04 " , 0 } , // DECAL_LAMBDA4
{ " {lambda05 " , 0 } , // DECAL_LAMBDA5
{ " {lambda06 " , 0 } , // DECAL_LAMBDA6
{ " {scorch1 " , 0 } , // DECAL_SCORCH1
{ " {scorch2 " , 0 } , // DECAL_SCORCH2
{ " {blood1 " , 0 } , // DECAL_BLOOD1
{ " {blood2 " , 0 } , // DECAL_BLOOD2
{ " {blood3 " , 0 } , // DECAL_BLOOD3
{ " {blood4 " , 0 } , // DECAL_BLOOD4
{ " {blood5 " , 0 } , // DECAL_BLOOD5
{ " {blood6 " , 0 } , // DECAL_BLOOD6
{ " {yblood1 " , 0 } , // DECAL_YBLOOD1
{ " {yblood2 " , 0 } , // DECAL_YBLOOD2
{ " {yblood3 " , 0 } , // DECAL_YBLOOD3
{ " {yblood4 " , 0 } , // DECAL_YBLOOD4
{ " {yblood5 " , 0 } , // DECAL_YBLOOD5
{ " {yblood6 " , 0 } , // DECAL_YBLOOD6
{ " {break1 " , 0 } , // DECAL_GLASSBREAK1
{ " {break2 " , 0 } , // DECAL_GLASSBREAK2
{ " {break3 " , 0 } , // DECAL_GLASSBREAK3
{ " {bigshot1 " , 0 } , // DECAL_BIGSHOT1
{ " {bigshot2 " , 0 } , // DECAL_BIGSHOT2
{ " {bigshot3 " , 0 } , // DECAL_BIGSHOT3
{ " {bigshot4 " , 0 } , // DECAL_BIGSHOT4
{ " {bigshot5 " , 0 } , // DECAL_BIGSHOT5
{ " {spit1 " , 0 } , // DECAL_SPIT1
{ " {spit2 " , 0 } , // DECAL_SPIT2
{ " {bproof1 " , 0 } , // DECAL_BPROOF1
{ " {gargstomp " , 0 } , // DECAL_GARGSTOMP1, // Gargantua stomp crack
{ " {smscorch1 " , 0 } , // DECAL_SMALLSCORCH1, // Small scorch mark
{ " {smscorch2 " , 0 } , // DECAL_SMALLSCORCH2, // Small scorch mark
{ " {smscorch3 " , 0 } , // DECAL_SMALLSCORCH3, // Small scorch mark
{ " {mommablob " , 0 } , // DECAL_MOMMABIRTH // BM Birth spray
{ " {mommablob " , 0 } , // DECAL_MOMMASPLAT // BM Mortar spray?? need decal
} ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
BODY QUE
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define SF_DECAL_NOTINDEATHMATCH 2048
class CDecal : public CBaseEntity
{
public :
void Spawn ( void ) ;
void KeyValue ( KeyValueData * pkvd ) ;
void EXPORT StaticDecal ( void ) ;
void EXPORT TriggerDecal ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value ) ;
} ;
LINK_ENTITY_TO_CLASS ( infodecal , CDecal ) ;
// UNDONE: These won't get sent to joining players in multi-player
void CDecal : : Spawn ( void )
{
if ( pev - > skin < 0 | | ( gpGlobals - > deathmatch & & FBitSet ( pev - > spawnflags , SF_DECAL_NOTINDEATHMATCH ) ) )
{
REMOVE_ENTITY ( ENT ( pev ) ) ;
return ;
}
if ( FStringNull ( pev - > targetname ) )
{
SetThink ( & CDecal : : StaticDecal ) ;
// if there's no targetname, the decal will spray itself on as soon as the world is done spawning.
pev - > nextthink = gpGlobals - > time ;
}
else
{
// if there IS a targetname, the decal sprays itself on when it is triggered.
SetThink ( & CDecal : : SUB_DoNothing ) ;
SetUse ( & CDecal : : TriggerDecal ) ;
}
}
void CDecal : : TriggerDecal ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value )
{
// this is set up as a USE function for infodecals that have targetnames, so that the
// decal doesn't get applied until it is fired. (usually by a scripted sequence)
TraceResult trace ;
int entityIndex ;
UTIL_TraceLine ( pev - > origin - Vector ( 5 , 5 , 5 ) , pev - > origin + Vector ( 5 , 5 , 5 ) , ignore_monsters , ENT ( pev ) , & trace ) ;
MESSAGE_BEGIN ( MSG_BROADCAST , SVC_TEMPENTITY ) ;
WRITE_BYTE ( TE_BSPDECAL ) ;
WRITE_COORD ( pev - > origin . x ) ;
WRITE_COORD ( pev - > origin . y ) ;
WRITE_COORD ( pev - > origin . z ) ;
WRITE_SHORT ( ( int ) pev - > skin ) ;
entityIndex = ( short ) ENTINDEX ( trace . pHit ) ;
WRITE_SHORT ( entityIndex ) ;
if ( entityIndex )
WRITE_SHORT ( ( int ) VARS ( trace . pHit ) - > modelindex ) ;
MESSAGE_END ( ) ;
SetThink ( & CDecal : : SUB_Remove ) ;
pev - > nextthink = gpGlobals - > time + 0.1 ;
}
void CDecal : : StaticDecal ( void )
{
TraceResult trace ;
int entityIndex , modelIndex ;
UTIL_TraceLine ( pev - > origin - Vector ( 5 , 5 , 5 ) , pev - > origin + Vector ( 5 , 5 , 5 ) , ignore_monsters , ENT ( pev ) , & trace ) ;
entityIndex = ( short ) ENTINDEX ( trace . pHit ) ;
if ( entityIndex )
modelIndex = ( int ) VARS ( trace . pHit ) - > modelindex ;
else
modelIndex = 0 ;
g_engfuncs . pfnStaticDecal ( pev - > origin , ( int ) pev - > skin , entityIndex , modelIndex ) ;
SUB_Remove ( ) ;
}
void CDecal : : KeyValue ( KeyValueData * pkvd )
{
if ( FStrEq ( pkvd - > szKeyName , " texture " ) )
{
pev - > skin = DECAL_INDEX ( pkvd - > szValue ) ;
// Found
if ( pev - > skin > = 0 )
return ;
ALERT ( at_console , " Can't find decal %s \n " , pkvd - > szValue ) ;
}
else
CBaseEntity : : KeyValue ( pkvd ) ;
}
// Body queue class here.... It's really just CBaseEntity
class CCorpse : public CBaseEntity
{
virtual int ObjectCaps ( void ) { return FCAP_DONT_SAVE ; }
} ;
LINK_ENTITY_TO_CLASS ( bodyque , CCorpse ) ;
static void InitBodyQue ( void )
{
string_t istrClassname = MAKE_STRING ( " bodyque " ) ;
g_pBodyQueueHead = CREATE_NAMED_ENTITY ( istrClassname ) ;
entvars_t * pev = VARS ( g_pBodyQueueHead ) ;
// Reserve 3 more slots for dead bodies
for ( int i = 0 ; i < 3 ; i + + )
{
pev - > owner = CREATE_NAMED_ENTITY ( istrClassname ) ;
pev = VARS ( pev - > owner ) ;
}
pev - > owner = g_pBodyQueueHead ;
}
//
// make a body que entry for the given ent so the ent can be respawned elsewhere
//
// GLOBALS ASSUMED SET: g_eoBodyQueueHead
//
void CopyToBodyQue ( entvars_t * pev )
{
if ( pev - > effects & EF_NODRAW )
return ;
entvars_t * pevHead = VARS ( g_pBodyQueueHead ) ;
pevHead - > angles = pev - > angles ;
pevHead - > model = pev - > model ;
pevHead - > modelindex = pev - > modelindex ;
pevHead - > frame = pev - > frame ;
pevHead - > colormap = pev - > colormap ;
pevHead - > movetype = MOVETYPE_TOSS ;
pevHead - > velocity = pev - > velocity ;
pevHead - > flags = 0 ;
pevHead - > deadflag = pev - > deadflag ;
pevHead - > renderfx = kRenderFxDeadPlayer ;
pevHead - > renderamt = ENTINDEX ( ENT ( pev ) ) ;
pevHead - > effects = pev - > effects | EF_NOINTERP ;
//pevHead->goalstarttime = pev->goalstarttime;
//pevHead->goalframe = pev->goalframe;
//pevHead->goalendtime = pev->goalendtime ;
pevHead - > sequence = pev - > sequence ;
pevHead - > animtime = pev - > animtime ;
UTIL_SetOrigin ( pevHead , pev - > origin ) ;
UTIL_SetSize ( pevHead , pev - > mins , pev - > maxs ) ;
g_pBodyQueueHead = pevHead - > owner ;
}
CGlobalState : : CGlobalState ( void )
{
Reset ( ) ;
}
void CGlobalState : : Reset ( void )
{
m_pList = NULL ;
m_listCount = 0 ;
}
globalentity_t * CGlobalState : : Find ( string_t globalname )
{
if ( ! globalname )
return NULL ;
globalentity_t * pTest ;
const char * pEntityName = STRING ( globalname ) ;
pTest = m_pList ;
while ( pTest )
{
if ( FStrEq ( pEntityName , pTest - > name ) )
break ;
pTest = pTest - > pNext ;
}
return pTest ;
}
// This is available all the time now on impulse 104, remove later
//#ifdef _DEBUG
void CGlobalState : : DumpGlobals ( void )
{
static char * estates [ ] = { " Off " , " On " , " Dead " } ;
globalentity_t * pTest ;
ALERT ( at_console , " -- Globals -- \n " ) ;
pTest = m_pList ;
while ( pTest )
{
ALERT ( at_console , " %s: %s (%s) \n " , pTest - > name , pTest - > levelName , estates [ pTest - > state ] ) ;
pTest = pTest - > pNext ;
}
}
//#endif
void CGlobalState : : EntityAdd ( string_t globalname , string_t mapName , GLOBALESTATE state )
{
ASSERT ( ! Find ( globalname ) ) ;
globalentity_t * pNewEntity = ( globalentity_t * ) calloc ( sizeof ( globalentity_t ) , 1 ) ;
ASSERT ( pNewEntity ! = NULL ) ;
pNewEntity - > pNext = m_pList ;
m_pList = pNewEntity ;
strcpy ( pNewEntity - > name , STRING ( globalname ) ) ;
strcpy ( pNewEntity - > levelName , STRING ( mapName ) ) ;
pNewEntity - > state = state ;
m_listCount + + ;
}
void CGlobalState : : EntitySetState ( string_t globalname , GLOBALESTATE state )
{
globalentity_t * pEnt = Find ( globalname ) ;
if ( pEnt )
pEnt - > state = state ;
}
const globalentity_t * CGlobalState : : EntityFromTable ( string_t globalname )
{
globalentity_t * pEnt = Find ( globalname ) ;
return pEnt ;
}
GLOBALESTATE CGlobalState : : EntityGetState ( string_t globalname )
{
globalentity_t * pEnt = Find ( globalname ) ;
if ( pEnt )
return pEnt - > state ;
return GLOBAL_OFF ;
}
// Global Savedata for Delay
TYPEDESCRIPTION CGlobalState : : m_SaveData [ ] =
{
DEFINE_FIELD ( CGlobalState , m_listCount , FIELD_INTEGER ) ,
} ;
// Global Savedata for Delay
TYPEDESCRIPTION gGlobalEntitySaveData [ ] =
{
DEFINE_ARRAY ( globalentity_t , name , FIELD_CHARACTER , 64 ) ,
DEFINE_ARRAY ( globalentity_t , levelName , FIELD_CHARACTER , 32 ) ,
DEFINE_FIELD ( globalentity_t , state , FIELD_INTEGER ) ,
} ;
const char * CGlobalState : : GetLevelName ( )
{
return STRING ( this - > m_pList - > levelName ) ;
}
int CGlobalState : : Save ( CSave & save )
{
int i ;
globalentity_t * pEntity ;
if ( ! save . WriteFields ( " GLOBAL " , this , m_SaveData , ARRAYSIZE ( m_SaveData ) ) )
return 0 ;
pEntity = m_pList ;
for ( i = 0 ; i < m_listCount & & pEntity ; i + + )
{
if ( ! save . WriteFields ( " GENT " , pEntity , gGlobalEntitySaveData , ARRAYSIZE ( gGlobalEntitySaveData ) ) )
return 0 ;
pEntity = pEntity - > pNext ;
}
return 1 ;
}
int CGlobalState : : Restore ( CRestore & restore )
{
int i , listCount ;
globalentity_t tmpEntity ;
ClearStates ( ) ;
if ( ! restore . ReadFields ( " GLOBAL " , this , m_SaveData , ARRAYSIZE ( m_SaveData ) ) )
return 0 ;
listCount = m_listCount ; // Get new list count
m_listCount = 0 ; // Clear loaded data
for ( i = 0 ; i < listCount ; i + + )
{
if ( ! restore . ReadFields ( " GENT " , & tmpEntity , gGlobalEntitySaveData , ARRAYSIZE ( gGlobalEntitySaveData ) ) )
return 0 ;
EntityAdd ( MAKE_STRING ( tmpEntity . name ) , MAKE_STRING ( tmpEntity . levelName ) , tmpEntity . state ) ;
}
return 1 ;
}
void CGlobalState : : EntityUpdate ( string_t globalname , string_t mapname )
{
globalentity_t * pEnt = Find ( globalname ) ;
if ( pEnt )
strcpy ( pEnt - > levelName , STRING ( mapname ) ) ;
}
void CGlobalState : : ClearStates ( void )
{
globalentity_t * pFree = m_pList ;
while ( pFree )
{
globalentity_t * pNext = pFree - > pNext ;
free ( pFree ) ;
pFree = pNext ;
}
Reset ( ) ;
}
void SaveGlobalState ( SAVERESTOREDATA * pSaveData )
{
CSave saveHelper ( pSaveData ) ;
gGlobalState . Save ( saveHelper ) ;
}
void RestoreGlobalState ( SAVERESTOREDATA * pSaveData )
{
CRestore restoreHelper ( pSaveData ) ;
gGlobalState . Restore ( restoreHelper ) ;
}
void ResetGlobalState ( void )
{
gGlobalState . ClearStates ( ) ;
gInitHUD = TRUE ; // Init the HUD on a new game / load game
}
// moved CWorld class definition to cbase.h
//=======================
// CWorld
//
// This spawns first when each level begins.
//=======================
LINK_ENTITY_TO_CLASS ( worldspawn , CWorld ) ;
# define SF_WORLD_DARK 0x0001 // Fade from black at startup
# define SF_WORLD_TITLE 0x0002 // Display game title at startup
# define SF_WORLD_FORCETEAM 0x0004 // Force teams
extern DLL_GLOBAL BOOL g_fGameOver ;
float g_flWeaponCheat ;
void CWorld : : Spawn ( void )
{
g_fGameOver = FALSE ;
Precache ( ) ;
g_flWeaponCheat = ns_cvar_float ( avh_cheats ) ; // Is the impulse 101 command allowed?
}
void CWorld : : Precache ( void )
{
# if 1
CVAR_SET_STRING ( " sv_gravity " , " 800 " ) ; // 67ft/sec
CVAR_SET_STRING ( " sv_stepsize " , " 18 " ) ;
# else
CVAR_SET_STRING ( " sv_gravity " , " 384 " ) ; // 32ft/sec
CVAR_SET_STRING ( " sv_stepsize " , " 24 " ) ;
# endif
CVAR_SET_STRING ( " room_type " , " 0 " ) ; // clear DSP
// Set up game rules
if ( g_pGameRules )
{
delete g_pGameRules ;
// This is needed because pmove is used by AvHSUGetIsEnoughRoomForHull, and if it isn't set to null, pmove->physents[0].worldmodel is the old map on a changelevel, and invalid
pmove = NULL ;
}
InstallGameRules ( ) ;
GetGameRules ( ) - > PreWorldPrecacheReset ( ) ;
//AvHGamerules* theGameRules = dynamic_cast<AvHGamerules*>(g_pGameRules);
//static const char* sCurrentLevelName = NULL;
//const char* theLevelName = STRING(gpGlobals->mapname);
//bool theNewMap = false;
//if(!sCurrentLevelName || strcmp(theLevelName, sCurrentLevelName))
//{
// theNewMap = true;
//}
// Reset game, but don't send need to send particles if same map (remove this distinction?)
//theGameRules->ResetGame(theNewMap);
//sCurrentLevelName = theLevelName;
// static bool theFirstTime = true;
// if(!theFirstTime)
// {
// theGameRules->ResetGame(true);
// }
// theFirstTime = false;
//!!!UNDONE why is there so much Spawn code in the Precache function? I'll just keep it here
///!!!LATER - do we want a sound ent in deathmatch? (sjb)
//pSoundEnt = CBaseEntity::Create( "soundent", g_vecZero, g_vecZero, edict() );
pSoundEnt = GetClassPtr ( ( CSoundEnt * ) NULL ) ;
pSoundEnt - > Spawn ( ) ;
if ( ! pSoundEnt )
{
ALERT ( at_console , " **COULD NOT CREATE SOUNDENT** \n " ) ;
}
InitBodyQue ( ) ;
// init sentence group playback stuff from sentences.txt.
// ok to call this multiple times, calls after first are ignored.
SENTENCEG_Init ( ) ;
// init texture type array from materials.txt
TEXTURETYPE_Init ( ) ;
// the area based ambient sounds MUST be the first precache_sounds
// player precaches
W_Precache ( ) ; // get weapon precaches
ClientPrecache ( ) ;
// sounds used from C physics code
PRECACHE_SOUND ( " common/null.wav " ) ; // clears sound channels
PRECACHE_SOUND ( " items/suitchargeok1.wav " ) ; //!!! temporary sound for respawning weapons.
PRECACHE_UNMODIFIED_SOUND ( " items/gunpickup2.wav " ) ; // player picks up a gun.
PRECACHE_UNMODIFIED_SOUND ( " items/gunpickup2-a.wav " ) ; // alien is equipped
PRECACHE_SOUND ( " common/bodydrop3.wav " ) ; // dead bodies hitting the ground (animation events)
PRECACHE_SOUND ( " common/bodydrop4.wav " ) ;
g_Language = ( int ) CVAR_GET_FLOAT ( " sv_language " ) ;
if ( g_Language = = LANGUAGE_GERMAN )
{
PRECACHE_UNMODIFIED_MODEL ( " models/germangibs.mdl " ) ;
}
else
{
PRECACHE_UNMODIFIED_MODEL ( " models/hgibs.mdl " ) ;
PRECACHE_UNMODIFIED_MODEL ( " models/agibs.mdl " ) ;
}
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric1.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric2.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric3.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric4.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric5.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric_conc-1.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric_conc-2.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric_metal-1.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/ric_metal-2.wav " ) ;
// Precache alien ricochet sounds
PRECACHE_UNMODIFIED_SOUND ( " weapons/a_ric1.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/a_ric2.wav " ) ;
PRECACHE_UNMODIFIED_SOUND ( " weapons/a_ric3.wav " ) ;
//
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
//
// 0 normal
LIGHT_STYLE ( 0 , " m " ) ;
// 1 FLICKER (first variety)
LIGHT_STYLE ( 1 , " mmnmmommommnonmmonqnmmo " ) ;
// 2 SLOW STRONG PULSE
LIGHT_STYLE ( 2 , " abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba " ) ;
// 3 CANDLE (first variety)
LIGHT_STYLE ( 3 , " mmmmmaaaaammmmmaaaaaabcdefgabcdefg " ) ;
// 4 FAST STROBE
LIGHT_STYLE ( 4 , " mamamamamama " ) ;
// 5 GENTLE PULSE 1
LIGHT_STYLE ( 5 , " jklmnopqrstuvwxyzyxwvutsrqponmlkj " ) ;
// 6 FLICKER (second variety)
LIGHT_STYLE ( 6 , " nmonqnmomnmomomno " ) ;
// 7 CANDLE (second variety)
LIGHT_STYLE ( 7 , " mmmaaaabcdefgmmmmaaaammmaamm " ) ;
// 8 CANDLE (third variety)
LIGHT_STYLE ( 8 , " mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa " ) ;
// 9 SLOW STROBE (fourth variety)
LIGHT_STYLE ( 9 , " aaaaaaaazzzzzzzz " ) ;
// 10 FLUORESCENT FLICKER
LIGHT_STYLE ( 10 , " mmamammmmammamamaaamammma " ) ;
// 11 SLOW PULSE NOT FADE TO BLACK
LIGHT_STYLE ( 11 , " abcdefghijklmnopqrrqponmlkjihgfedcba " ) ;
// 12 UNDERWATER LIGHT MUTATION
// this light only distorts the lightmap - no contribution
// is made to the brightness of affected surfaces
LIGHT_STYLE ( 12 , " mmnnmmnnnmmnn " ) ;
// styles 32-62 are assigned by the light program for switchable lights
// 63 testing
LIGHT_STYLE ( 63 , " a " ) ;
for ( int i = 0 ; i < ARRAYSIZE ( gDecals ) ; i + + )
gDecals [ i ] . index = DECAL_INDEX ( gDecals [ i ] . name ) ;
// init the WorldGraph.
WorldGraph . InitGraph ( ) ;
// make sure the .NOD file is newer than the .BSP file.
if ( ! WorldGraph . CheckNODFile ( ( char * ) STRING ( gpGlobals - > mapname ) ) )
{ // NOD file is not present, or is older than the BSP file.
WorldGraph . AllocNodes ( ) ;
}
else
{ // Load the node graph for this level
if ( ! WorldGraph . FLoadGraph ( ( char * ) STRING ( gpGlobals - > mapname ) ) )
{ // couldn't load, so alloc and prepare to build a graph.
ALERT ( at_console , " *Error opening .NOD file \n " ) ;
WorldGraph . AllocNodes ( ) ;
}
else
{
ALERT ( at_console , " \n *Graph Loaded! \n " ) ;
}
}
if ( pev - > speed > 0 )
CVAR_SET_FLOAT ( " sv_zmax " , pev - > speed ) ;
else
CVAR_SET_FLOAT ( " sv_zmax " , 4096 ) ;
if ( pev - > netname )
{
ALERT ( at_aiconsole , " Chapter title: %s \n " , STRING ( pev - > netname ) ) ;
CBaseEntity * pEntity = CBaseEntity : : Create ( " env_message " , g_vecZero , g_vecZero , NULL ) ;
if ( pEntity )
{
pEntity - > SetThink ( & CBaseEntity : : SUB_CallUseToggle ) ;
pEntity - > pev - > message = pev - > netname ;
pev - > netname = 0 ;
pEntity - > pev - > nextthink = gpGlobals - > time + 0.3 ;
pEntity - > pev - > spawnflags = SF_MESSAGE_ONCE ;
}
}
if ( pev - > spawnflags & SF_WORLD_DARK )
CVAR_SET_FLOAT ( " v_dark " , 1.0 ) ;
else
CVAR_SET_FLOAT ( " v_dark " , 0.0 ) ;
if ( pev - > spawnflags & SF_WORLD_TITLE )
gDisplayTitle = TRUE ; // display the game title if this key is set
else
gDisplayTitle = FALSE ;
if ( pev - > spawnflags & SF_WORLD_FORCETEAM )
{
CVAR_SET_FLOAT ( " mp_defaultteam " , 1 ) ;
}
else
{
CVAR_SET_FLOAT ( " mp_defaultteam " , 0 ) ;
}
}
//
// Just to ignore the "wad" field.
//
void CWorld : : KeyValue ( KeyValueData * pkvd )
{
if ( FStrEq ( pkvd - > szKeyName , " skyname " ) )
{
// Sent over net now.
CVAR_SET_STRING ( " sv_skyname " , pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " sounds " ) )
{
gpGlobals - > cdAudioTrack = atoi ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " WaveHeight " ) )
{
// Sent over net now.
pev - > scale = atof ( pkvd - > szValue ) * ( 1.0 / 8.0 ) ;
pkvd - > fHandled = TRUE ;
CVAR_SET_FLOAT ( " sv_wateramp " , pev - > scale ) ;
}
else if ( FStrEq ( pkvd - > szKeyName , " MaxRange " ) )
{
pev - > speed = atof ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " chaptertitle " ) )
{
pev - > netname = ALLOC_STRING ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " startdark " ) )
{
// UNDONE: This is a gross hack!!! The CVAR is NOT sent over the client/sever link
// but it will work for single player
int flag = atoi ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
if ( flag )
pev - > spawnflags | = SF_WORLD_DARK ;
}
else if ( FStrEq ( pkvd - > szKeyName , " newunit " ) )
{
// Single player only. Clear save directory if set
if ( atoi ( pkvd - > szValue ) )
CVAR_SET_FLOAT ( " sv_newunit " , 1 ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " gametitle " ) )
{
if ( atoi ( pkvd - > szValue ) )
pev - > spawnflags | = SF_WORLD_TITLE ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " mapteams " ) )
{
pev - > team = ALLOC_STRING ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
else if ( FStrEq ( pkvd - > szKeyName , " defaultteam " ) )
{
if ( atoi ( pkvd - > szValue ) )
{
pev - > spawnflags | = SF_WORLD_FORCETEAM ;
}
pkvd - > fHandled = TRUE ;
}
else
CBaseEntity : : KeyValue ( pkvd ) ;
}