Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

842 lines
21 KiB

9 years ago
/***
*
* Copyright (c) 1996-2002, 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 "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 "physcallback.h"
extern CGraph WorldGraph;
extern CSoundEnt *pSoundEnt;
extern CBaseEntity *g_pLastSpawn;
DLL_GLOBAL edict_t *g_pBodyQueueHead;
CGlobalState gGlobalState;
8 years ago
extern DLL_GLOBAL int gDisplayTitle;
9 years ago
8 years ago
extern void W_Precache( void );
9 years ago
//
// This must match the list in util.h
//
DLL_DECALLIST gDecals[] = {
8 years ago
{ "{shot1", 0 }, // DECAL_GUNSHOT1
{ "{shot2", 0 }, // DECAL_GUNSHOT2
{ "{shot3", 0 }, // DECAL_GUNSHOT3
{ "{shot4", 0 }, // DECAL_GUNSHOT4
{ "{shot5", 0 }, // DECAL_GUNSHOT5
9 years ago
{ "{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
8 years ago
{ "{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
9 years ago
};
/*
==============================================================================
BODY QUE
==============================================================================
*/
#define SF_DECAL_NOTINDEATHMATCH 2048
class CDecal : public CBaseEntity
{
public:
8 years ago
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
void EXPORT StaticDecal( void );
void EXPORT TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
9 years ago
};
LINK_ENTITY_TO_CLASS( infodecal, CDecal )
9 years ago
// UNDONE: These won't get sent to joining players in multi-player
8 years ago
void CDecal::Spawn( void )
9 years ago
{
8 years ago
if( pev->skin < 0 || ( gpGlobals->deathmatch && FBitSet( pev->spawnflags, SF_DECAL_NOTINDEATHMATCH ) ) )
9 years ago
{
8 years ago
REMOVE_ENTITY( ENT( pev ) );
9 years ago
return;
}
8 years ago
if( FStringNull( pev->targetname ) )
9 years ago
{
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( &CBaseEntity::SUB_DoNothing );
8 years ago
SetUse( &CDecal::TriggerDecal );
9 years ago
}
}
8 years ago
void CDecal::TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
9 years ago
{
// 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;
8 years ago
int entityIndex;
9 years ago
8 years ago
UTIL_TraceLine( pev->origin - Vector( 5, 5, 5 ), pev->origin + Vector( 5, 5, 5 ), ignore_monsters, ENT( pev ), &trace );
9 years ago
8 years ago
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
9 years ago
WRITE_BYTE( TE_BSPDECAL );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( (int)pev->skin );
8 years ago
entityIndex = (short)ENTINDEX( trace.pHit );
9 years ago
WRITE_SHORT( entityIndex );
8 years ago
if( entityIndex )
WRITE_SHORT( (int)VARS( trace.pHit )->modelindex );
9 years ago
MESSAGE_END();
SetThink( &CBaseEntity::SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1f;
9 years ago
}
8 years ago
void CDecal::StaticDecal( void )
9 years ago
{
TraceResult trace;
8 years ago
int entityIndex, modelIndex;
9 years ago
8 years ago
UTIL_TraceLine( pev->origin - Vector( 5, 5, 5 ), pev->origin + Vector( 5, 5, 5 ), ignore_monsters, ENT( pev ), &trace );
9 years ago
8 years ago
entityIndex = (short)ENTINDEX( trace.pHit );
if( entityIndex )
modelIndex = (int)VARS( trace.pHit )->modelindex;
9 years ago
else
modelIndex = 0;
g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
SUB_Remove();
}
8 years ago
void CDecal::KeyValue( KeyValueData *pkvd )
9 years ago
{
8 years ago
if( FStrEq( pkvd->szKeyName, "texture" ) )
9 years ago
{
pev->skin = DECAL_INDEX( pkvd->szValue );
9 years ago
// Found
8 years ago
if( pev->skin >= 0 )
9 years ago
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 )
9 years ago
8 years ago
static void InitBodyQue( void )
9 years ago
{
8 years ago
string_t istrClassname = MAKE_STRING( "bodyque" );
9 years ago
g_pBodyQueueHead = CREATE_NAMED_ENTITY( istrClassname );
8 years ago
entvars_t *pev = VARS( g_pBodyQueueHead );
9 years ago
// Reserve 3 more slots for dead bodies
8 years ago
for( int i = 0; i < 3; i++ )
9 years ago
{
pev->owner = CREATE_NAMED_ENTITY( istrClassname );
8 years ago
pev = VARS( pev->owner );
9 years ago
}
9 years ago
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
//
8 years ago
void CopyToBodyQue( entvars_t *pev )
9 years ago
{
8 years ago
if( pev->effects & EF_NODRAW )
9 years ago
return;
8 years ago
entvars_t *pevHead = VARS( g_pBodyQueueHead );
9 years ago
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 ) );
8 years ago
pevHead->effects = pev->effects | EF_NOINTERP;
9 years ago
//pevHead->goalstarttime = pev->goalstarttime;
8 years ago
//pevHead->goalframe = pev->goalframe;
9 years ago
//pevHead->goalendtime = pev->goalendtime ;
9 years ago
pevHead->sequence = pev->sequence;
pevHead->animtime = pev->animtime;
8 years ago
UTIL_SetOrigin( pevHead, pev->origin );
UTIL_SetSize( pevHead, pev->mins, pev->maxs );
9 years ago
g_pBodyQueueHead = pevHead->owner;
}
CGlobalState::CGlobalState( void )
{
Reset();
}
void CGlobalState::Reset( void )
{
m_pList = NULL;
m_listCount = 0;
}
8 years ago
globalentity_t *CGlobalState::Find( string_t globalname )
9 years ago
{
8 years ago
if( !globalname )
9 years ago
return NULL;
globalentity_t *pTest;
8 years ago
const char *pEntityName = STRING( globalname );
9 years ago
pTest = m_pList;
8 years ago
while( pTest )
9 years ago
{
8 years ago
if( FStrEq( pEntityName, pTest->name ) )
9 years ago
break;
9 years ago
pTest = pTest->pNext;
}
return pTest;
}
// This is available all the time now on impulse 104, remove later
//#ifdef _DEBUG
8 years ago
void CGlobalState::DumpGlobals( void )
9 years ago
{
static const char *estates[] = { "Off", "On", "Dead" };
9 years ago
globalentity_t *pTest;
ALERT( at_console, "-- Globals --\n" );
pTest = m_pList;
8 years ago
while( pTest )
9 years ago
{
ALERT( at_console, "%s: %s (%s)\n", pTest->name, pTest->levelName, estates[pTest->state] );
pTest = pTest->pNext;
}
}
//#endif
8 years ago
void CGlobalState::EntityAdd( string_t globalname, string_t mapName, GLOBALESTATE state )
9 years ago
{
8 years ago
ASSERT( !Find( globalname ) );
9 years ago
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 ) );
8 years ago
strcpy( pNewEntity->levelName, STRING( mapName ) );
9 years ago
pNewEntity->state = state;
m_listCount++;
}
8 years ago
void CGlobalState::EntitySetState( string_t globalname, GLOBALESTATE state )
9 years ago
{
globalentity_t *pEnt = Find( globalname );
8 years ago
if( pEnt )
9 years ago
pEnt->state = state;
}
const globalentity_t *CGlobalState :: EntityFromTable( string_t globalname )
{
globalentity_t *pEnt = Find( globalname );
return pEnt;
}
8 years ago
GLOBALESTATE CGlobalState::EntityGetState( string_t globalname )
9 years ago
{
globalentity_t *pEnt = Find( globalname );
8 years ago
if( pEnt )
9 years ago
return pEnt->state;
return GLOBAL_OFF;
}
// Global Savedata for Delay
TYPEDESCRIPTION CGlobalState::m_SaveData[] =
9 years ago
{
DEFINE_FIELD( CGlobalState, m_listCount, FIELD_INTEGER ),
};
// Global Savedata for Delay
TYPEDESCRIPTION gGlobalEntitySaveData[] =
9 years ago
{
DEFINE_ARRAY( globalentity_t, name, FIELD_CHARACTER, 64 ),
DEFINE_ARRAY( globalentity_t, levelName, FIELD_CHARACTER, 32 ),
DEFINE_FIELD( globalentity_t, state, FIELD_INTEGER ),
};
int CGlobalState::Save( CSave &save )
{
int i;
globalentity_t *pEntity;
8 years ago
if( !save.WriteFields( "GLOBAL", this, m_SaveData, ARRAYSIZE( m_SaveData ) ) )
9 years ago
return 0;
pEntity = m_pList;
8 years ago
for( i = 0; i < m_listCount && pEntity; i++ )
9 years ago
{
8 years ago
if( !save.WriteFields( "GENT", pEntity, gGlobalEntitySaveData, ARRAYSIZE( gGlobalEntitySaveData ) ) )
9 years ago
return 0;
pEntity = pEntity->pNext;
}
return 1;
}
int CGlobalState::Restore( CRestore &restore )
{
int i, listCount;
globalentity_t tmpEntity;
ClearStates();
8 years ago
if( !restore.ReadFields( "GLOBAL", this, m_SaveData, ARRAYSIZE( m_SaveData ) ) )
9 years ago
return 0;
9 years ago
listCount = m_listCount; // Get new list count
m_listCount = 0; // Clear loaded data
8 years ago
for( i = 0; i < listCount; i++ )
9 years ago
{
8 years ago
if( !restore.ReadFields( "GENT", &tmpEntity, gGlobalEntitySaveData, ARRAYSIZE( gGlobalEntitySaveData ) ) )
9 years ago
return 0;
8 years ago
EntityAdd( MAKE_STRING( tmpEntity.name ), MAKE_STRING( tmpEntity.levelName ), tmpEntity.state );
9 years ago
}
return 1;
}
void CGlobalState::EntityUpdate( string_t globalname, string_t mapname )
{
globalentity_t *pEnt = Find( globalname );
8 years ago
if( pEnt )
strcpy( pEnt->levelName, STRING( mapname ) );
9 years ago
}
void CGlobalState::ClearStates( void )
{
globalentity_t *pFree = m_pList;
8 years ago
while( pFree )
9 years ago
{
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 )
9 years ago
#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;
8 years ago
void CWorld::Spawn( void )
9 years ago
{
g_fGameOver = FALSE;
8 years ago
Precache();
9 years ago
}
8 years ago
void CWorld::Precache( void )
9 years ago
{
g_pLastSpawn = NULL;
#if 1
8 years ago
CVAR_SET_STRING( "sv_gravity", "800" ); // 67ft/sec
CVAR_SET_STRING( "sv_stepsize", "18" );
9 years ago
#else
8 years ago
CVAR_SET_STRING( "sv_gravity", "384" ); // 32ft/sec
CVAR_SET_STRING( "sv_stepsize", "24" );
9 years ago
#endif
8 years ago
CVAR_SET_STRING( "room_type", "0" );// clear DSP
9 years ago
// Set up game rules
8 years ago
if( g_pGameRules )
9 years ago
{
delete g_pGameRules;
8 years ago
g_pGameRules = NULL;
9 years ago
}
8 years ago
g_pGameRules = InstallGameRules();
9 years ago
//!!!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 );
if( pSoundEnt )
{
pSoundEnt->Spawn();
}
else
9 years ago
{
ALERT ( at_console, "**COULD NOT CREATE SOUNDENT**\n" );
}
InitBodyQue();
8 years ago
// init sentence group playback stuff from sentences.txt.
// ok to call this multiple times, calls after first are ignored.
9 years ago
SENTENCEG_Init();
// the area based ambient sounds MUST be the first precache_sounds
// player precaches
8 years ago
W_Precache(); // get weapon precaches
9 years ago
ClientPrecache();
// sounds used from C physics code
8 years ago
PRECACHE_SOUND( "common/null.wav" );// clears sound channels
9 years ago
PRECACHE_SOUND( "items/suitchargeok1.wav" );//!!! temporary sound for respawning weapons.
PRECACHE_SOUND( "items/gunpickup2.wav" );// player picks up a gun.
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" );
8 years ago
if( g_Language == LANGUAGE_GERMAN )
9 years ago
{
PRECACHE_MODEL( "models/germangibs.mdl" );
}
else
{
PRECACHE_MODEL( "models/hgibs.mdl" );
PRECACHE_MODEL( "models/agibs.mdl" );
}
8 years ago
PRECACHE_SOUND( "weapons/ric1.wav" );
PRECACHE_SOUND( "weapons/ric2.wav" );
PRECACHE_SOUND( "weapons/ric3.wav" );
PRECACHE_SOUND( "weapons/ric4.wav" );
PRECACHE_SOUND( "weapons/ric5.wav" );
//
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
//
9 years ago
// 0 normal
8 years ago
LIGHT_STYLE( 0, "m" );
9 years ago
// 1 FLICKER (first variety)
8 years ago
LIGHT_STYLE( 1, "mmnmmommommnonmmonqnmmo" );
9 years ago
// 2 SLOW STRONG PULSE
8 years ago
LIGHT_STYLE( 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba" );
9 years ago
// 3 CANDLE (first variety)
8 years ago
LIGHT_STYLE( 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg" );
9 years ago
// 4 FAST STROBE
8 years ago
LIGHT_STYLE( 4, "mamamamamama" );
9 years ago
// 5 GENTLE PULSE 1
8 years ago
LIGHT_STYLE( 5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj" );
9 years ago
// 6 FLICKER (second variety)
8 years ago
LIGHT_STYLE( 6, "nmonqnmomnmomomno" );
9 years ago
// 7 CANDLE (second variety)
8 years ago
LIGHT_STYLE( 7, "mmmaaaabcdefgmmmmaaaammmaamm" );
9 years ago
// 8 CANDLE (third variety)
8 years ago
LIGHT_STYLE( 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa" );
9 years ago
// 9 SLOW STROBE (fourth variety)
8 years ago
LIGHT_STYLE( 9, "aaaaaaaazzzzzzzz" );
9 years ago
// 10 FLUORESCENT FLICKER
8 years ago
LIGHT_STYLE( 10, "mmamammmmammamamaaamammma" );
9 years ago
// 11 SLOW PULSE NOT FADE TO BLACK
8 years ago
LIGHT_STYLE( 11, "abcdefghijklmnopqrrqponmlkjihgfedcba" );
9 years ago
// 12 UNDERWATER LIGHT MUTATION
// this light only distorts the lightmap - no contribution
// is made to the brightness of affected surfaces
8 years ago
LIGHT_STYLE( 12, "mmnnmmnnnmmnn" );
9 years ago
// styles 32-62 are assigned by the light program for switchable lights
// 63 testing
8 years ago
LIGHT_STYLE( 63, "a" );
9 years ago
for( int i = 0; i < (int)ARRAYSIZE( gDecals ); i++ )
9 years ago
gDecals[i].index = DECAL_INDEX( gDecals[i].name );
// init the WorldGraph.
9 years ago
WorldGraph.InitGraph();
// make sure the .NOD file is newer than the .BSP file.
if( !WorldGraph.CheckNODFile( STRING( gpGlobals->mapname ) ) )
{
// NOD file is not present, or is older than the BSP file.
8 years ago
WorldGraph.AllocNodes();
9 years ago
}
else
{
// Load the node graph for this level
if( !WorldGraph.FLoadGraph( STRING( gpGlobals->mapname ) ) )
{
// couldn't load, so alloc and prepare to build a graph.
8 years ago
ALERT( at_console, "*Error opening .NOD file\n" );
WorldGraph.AllocNodes();
9 years ago
}
else
{
8 years ago
ALERT( at_console, "\n*Graph Loaded!\n" );
9 years ago
}
}
8 years ago
if( pev->speed > 0 )
9 years ago
CVAR_SET_FLOAT( "sv_zmax", pev->speed );
else
CVAR_SET_FLOAT( "sv_zmax", 4096 );
// g-cont. moved here to right restore global WaveHeight on save\restore level
CVAR_SET_FLOAT( "sv_wateramp", pev->scale );
8 years ago
if( pev->netname )
9 years ago
{
8 years ago
ALERT( at_aiconsole, "Chapter title: %s\n", STRING( pev->netname ) );
9 years ago
CBaseEntity *pEntity = CBaseEntity::Create( "env_message", g_vecZero, g_vecZero, NULL );
8 years ago
if( pEntity )
9 years ago
{
pEntity->SetThink( &CBaseEntity::SUB_CallUseToggle );
pEntity->pev->message = pev->netname;
pev->netname = 0;
pEntity->pev->nextthink = gpGlobals->time + 0.3f;
9 years ago
pEntity->pev->spawnflags = SF_MESSAGE_ONCE;
}
}
8 years ago
if( pev->spawnflags & SF_WORLD_DARK )
CVAR_SET_FLOAT( "v_dark", 1.0f );
9 years ago
else
CVAR_SET_FLOAT( "v_dark", 0.0f );
9 years ago
pev->spawnflags &= ~SF_WORLD_DARK; // g-cont. don't apply fade after save\restore
8 years ago
if( pev->spawnflags & SF_WORLD_TITLE )
9 years ago
gDisplayTitle = TRUE; // display the game title if this key is set
else
gDisplayTitle = FALSE;
pev->spawnflags &= ~SF_WORLD_TITLE; // g-cont. don't show logo after save\restore
8 years ago
if( pev->spawnflags & SF_WORLD_FORCETEAM )
9 years ago
{
CVAR_SET_FLOAT( "mp_defaultteam", 1.0f );
9 years ago
}
else
{
CVAR_SET_FLOAT( "mp_defaultteam", 0.0f );
9 years ago
}
// g-cont. moved here so cheats will working on restore level
g_flWeaponCheat = CVAR_GET_FLOAT( "sv_cheats" ); // Is the impulse 101 command allowed?
}
//
// Just to ignore the "wad" field.
//
8 years ago
void CWorld::KeyValue( KeyValueData *pkvd )
9 years ago
{
8 years ago
if( FStrEq( pkvd->szKeyName, "skyname" ) )
9 years ago
{
// Sent over net now.
CVAR_SET_STRING( "sv_skyname", pkvd->szValue );
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "sounds" ) )
9 years ago
{
8 years ago
gpGlobals->cdAudioTrack = atoi( pkvd->szValue );
9 years ago
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq(pkvd->szKeyName, "WaveHeight" ) )
9 years ago
{
// Sent over net now.
pev->scale = atof( pkvd->szValue ) * ( 1.0f / 8.0f );
9 years ago
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "MaxRange" ) )
9 years ago
{
8 years ago
pev->speed = atof( pkvd->szValue );
9 years ago
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "chaptertitle" ) )
9 years ago
{
8 years ago
pev->netname = ALLOC_STRING( pkvd->szValue );
9 years ago
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "startdark" ) )
9 years ago
{
// UNDONE: This is a gross hack!!! The CVAR is NOT sent over the client/sever link
// but it will work for single player
8 years ago
int flag = atoi( pkvd->szValue );
9 years ago
pkvd->fHandled = TRUE;
8 years ago
if( flag )
9 years ago
pev->spawnflags |= SF_WORLD_DARK;
}
8 years ago
else if( FStrEq(pkvd->szKeyName, "newunit") )
9 years ago
{
// Single player only. Clear save directory if set
8 years ago
if( atoi( pkvd->szValue ) )
9 years ago
CVAR_SET_FLOAT( "sv_newunit", 1 );
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq(pkvd->szKeyName, "gametitle" ) )
9 years ago
{
8 years ago
if( atoi( pkvd->szValue ) )
9 years ago
pev->spawnflags |= SF_WORLD_TITLE;
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "mapteams" ) )
9 years ago
{
pev->team = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
8 years ago
else if( FStrEq( pkvd->szKeyName, "defaultteam" ) )
9 years ago
{
8 years ago
if( atoi( pkvd->szValue ) )
9 years ago
{
pev->spawnflags |= SF_WORLD_FORCETEAM;
}
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
//
// Xash3D physics interface
//
8 years ago
typedef void (*LINK_ENTITY_FN)( entvars_t *pev );
9 years ago
//
// attempt to create custom entity when default method is failed
// 0 - attempt to create, -1 - reject to create
//
int DispatchCreateEntity( edict_t *pent, const char *szName )
{
/*
#ifdef CREATE_ENTITY_TEST
// quake armor entities. we just replaced it with item_battery...
8 years ago
if( !strcmp( szName, "item_armor1" ) || !strcmp( szName, "item_armor2" ) )
9 years ago
{
LINK_ENTITY_FN SpawnEdict;
// ugly method to get acess with himself exports
SpawnEdict = (LINK_ENTITY_FN)GetProcAddress( GetModuleHandle( "hl" ), "item_battery" );
if( SpawnEdict != NULL ) // found the valid spawn
{
// BUGBUG: old classname hanging in memory
pent->v.classname = ALLOC_STRING( "item_battery" );
8 years ago
//ALERT( at_console, "DispatchCreateEntity: replace %s with %s\n", szName, STRING( pent->v.classname ) );
9 years ago
SpawnEdict( &pent->v );
return 0; // handled
}
8 years ago
}
9 years ago
#endif
*/
return -1;
}
//
// run custom physics for each entity
// return 0 to use built-in engine physic
//
int DispatchPhysicsEntity( edict_t *pEdict )
{
8 years ago
CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE( pEdict );
9 years ago
if( !pEntity )
{
8 years ago
//ALERT( at_console, "skip %s [%i] without private data\n", STRING( pEdict->v.classname ), ENTINDEX( pEdict ) );
9 years ago
return 0; // not initialized
}
// NOTE: at this point pEntity assume to be valid
/*
#ifdef CUSTOM_PHYSICS_TEST
// test alien controller without physics, thinking only
8 years ago
if( FClassnameIs( pEntity->pev, "monster_alien_controller" ) )
9 years ago
{
8 years ago
float thinktime;
9 years ago
thinktime = pEntity->pev->nextthink;
if( thinktime <= 0.0f || thinktime > PHYSICS_TIME() + gpGlobals->frametime )
return 1;
8 years ago
if( thinktime < PHYSICS_TIME() )
9 years ago
thinktime = PHYSICS_TIME(); // don't let things stay in the past.
// it is possible to start that way
// by a trigger with a local time.
9 years ago
pEntity->pev->nextthink = 0.0f;
gpGlobals->time = thinktime;
DispatchThink( pEdict );
#ifdef GRAVITY_TEST
// stupid fake gravity test
pEntity->pev->origin.z -= 1;
LINK_ENTITY( pEdict, true );
#endif
return 1; // handled
}
#endif
*/
return 0;
}
8 years ago
static physics_interface_t gPhysicsInterface =
9 years ago
{
SV_PHYSICS_INTERFACE_VERSION,
DispatchCreateEntity,
DispatchPhysicsEntity,
};
BOOL gPhysicsInterfaceInitialized = FALSE;
9 years ago
int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable )
{
8 years ago
if( !pFunctionTable || !pfuncsFromEngine || iVersion != SV_PHYSICS_INTERFACE_VERSION )
9 years ago
{
return FALSE;
}
// copy new physics interface
8 years ago
memcpy( &g_physfuncs, pfuncsFromEngine, sizeof(server_physics_api_t) );
9 years ago
// fill engine callbacks
8 years ago
memcpy( pFunctionTable, &gPhysicsInterface, sizeof(physics_interface_t) );
gPhysicsInterfaceInitialized = TRUE;
9 years ago
return TRUE;
}