21 Mar 2010

This commit is contained in:
g-cont 2010-03-21 00:00:00 +03:00 committed by Alibek Omarov
parent c48cdf25e0
commit 7f005e320a
48 changed files with 6263 additions and 4504 deletions

View File

@ -165,7 +165,7 @@ void TE_ParseExplosion( void )
char szDecal[32];
sprintf( szDecal, "{scorch%i", RANDOM_LONG( 1, 3 ));
g_pTempEnts->PlaceDecal( pos2, 48.0f, szDecal );
g_pTempEnts->PlaceDecal( pos, 48.0f, szDecal );
if( !( flags & TE_EXPLFLAG_NOSOUND ))
{

View File

@ -316,12 +316,9 @@ void CParticleSystem :: Clear( void )
m_pParticles[MAX_PARTICLES-1].next = NULL;
// loading TE shaders
m_hDefaultParticle = TEX_Load( "textures/particles/default" );
m_hGlowParticle = TEX_Load( "textures/particles/glow" );
m_hDroplet = TEX_Load( "textures/particles/droplet" );
m_hBubble = TEX_Load( "textures/particles/bubble" );
m_hSparks = TEX_Load( "textures/particles/spark" );
m_hSmoke = TEX_Load( "textures/particles/smoke" );
m_hDefaultParticle = TEX_Load( "$defaultParticle" );
m_hSparks = TEX_Load( "gfx/hud/spark" );
m_hSmoke = TEX_Load( "gfx/hud/smoke" );
}
void CParticleSystem :: FreeParticle( CParticle *pCur )
@ -492,41 +489,6 @@ void CParticleSystem :: ExplosionParticles( const Vector pos )
}
}
/*
=================
CL_BubbleParticles
=================
*/
void CParticleSystem :: BubbleParticles( const Vector org, int count, float magnitude )
{
CParticle src;
if( !cl_particles->integer ) return;
for( int i = 0; i < count; i++ )
{
src.origin.x = org[0] + RANDOM_FLOAT( -magnitude, magnitude );
src.origin.y = org[1] + RANDOM_FLOAT( -magnitude, magnitude );
src.origin.z = org[2] + RANDOM_FLOAT( -magnitude, magnitude );
src.velocity.x = RANDOM_FLOAT( -5, 5 );
src.velocity.y = RANDOM_FLOAT( -5, 5 );
src.velocity.z = RANDOM_FLOAT( -5, 5 ) + (25 + RANDOM_FLOAT( -5, 5 ));
src.accel = Vector( 0, 0, 0 );
src.color = Vector( 1, 1, 1 );
src.colorVelocity = Vector( 0, 0, 0 );
src.alpha = 1.0;
src.alphaVelocity = -(0.4 + RANDOM_FLOAT( 0, 0.2 ));
src.radius = 1 + RANDOM_FLOAT( -0.5, 0.5 );
src.radiusVelocity = 0;
src.length = 1;
src.lengthVelocity = 0;
src.rotation = 0;
if( !AddParticle( &src, m_hBubble, FPART_UNDERWATER ))
return;
}
}
/*
=================
CL_BulletParticles
@ -656,10 +618,7 @@ void CParticleSystem :: BulletParticles( const Vector org, const Vector dir )
cnt = POINT_CONTENTS( org );
if( cnt == CONTENTS_WATER )
{
BubbleParticles( org, count, 0 );
return;
}
// sparks
int flags = (FPART_STRETCH|FPART_BOUNCE|FPART_FRICTION);

View File

@ -53,9 +53,6 @@ class CParticleSystem
// private partsystem shaders
HSPRITE m_hDefaultParticle;
HSPRITE m_hGlowParticle;
HSPRITE m_hDroplet;
HSPRITE m_hBubble;
HSPRITE m_hSparks;
HSPRITE m_hSmoke;
public:

View File

@ -553,12 +553,11 @@ void DrawScreenFade( void )
numFades++;
}
// Divide colors
// divide colors
if( numFades ) gHUD.m_vecFadeColor /= numFades;
else return;
if( gHUD.m_vecFadeColor == Vector( 0, 0, 0 )) return;
const float *RGB = gHUD.m_vecFadeColor;
FillRGBA( 0, 0, ScreenWidth, ScreenHeight, RGB[0], RGB[1], RGB[2], gHUD.m_flFadeAlpha );
}

View File

@ -94,8 +94,6 @@ typedef struct dllfunction_s
#define XRES(x) ((int)(float(x) * ((float)ScreenWidth / 640.0f) + 0.5f))
#define YRES(y) ((int)(float(y) * ((float)ScreenHeight / 480.0f) + 0.5f))
#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
// ScreenHeight returns the virtual height of the screen, in pixels
#define ScreenHeight (gHUD.m_scrinfo.iHeight)
// ScreenWidth returns the virtual width of the screen, in pixels

View File

@ -48,6 +48,7 @@ cvar_t *scr_ofsy;
cvar_t *scr_ofsz;
cvar_t *cl_vsmoothing;
cvar_t *cl_stairsmooth;
cvar_t *cl_weaponlag;
cvar_t *cl_bobcycle;
cvar_t *cl_bob;
@ -140,6 +141,7 @@ void V_Init( void )
v_iroll_level = g_engfuncs.pfnRegisterVariable( "v_iroll_level", "0.1", 0, "viewing inverse roll level" );
v_ipitch_level = g_engfuncs.pfnRegisterVariable( "v_iyaw_level", "0.3", 0, "viewing inverse pitch level" );
cl_weaponlag = g_engfuncs.pfnRegisterVariable( "v_viewmodel_lag", "0.0", FCVAR_ARCHIVE, "add some lag to viewmodel like in HL2" );
cl_bobcycle = g_engfuncs.pfnRegisterVariable( "cl_bobcycle","0.8", 0, "bob full cycle" );
cl_bob = g_engfuncs.pfnRegisterVariable( "cl_bob", "0.01", 0, "bob value" );
cl_bobup = g_engfuncs.pfnRegisterVariable( "cl_bobup", "0.5", 0, "bob upper limit" );
@ -263,6 +265,70 @@ void V_DropPunchAngle( float frametime, Vector &ev_punchangle )
ev_punchangle *= len;
}
void V_CalcViewModelLag( Vector& origin, Vector& angles, Vector& original_angles )
{
static Vector m_vecLastFacing;
Vector vOriginalOrigin = origin;
Vector vOriginalAngles = angles;
// Calculate our drift
Vector forward;
AngleVectors( angles, forward, NULL, NULL );
if ( gpGlobals->frametime != 0.0f )
{
Vector vDifference;
vDifference = forward - m_vecLastFacing;
float flSpeed = 5.0f;
// If we start to lag too far behind, we'll increase the "catch up" speed.
// Solves the problem with fast cl_yawspeed, m_yaw or joysticks rotating quickly.
// The old code would slam lastfacing with origin causing the viewmodel to pop to a new position
float flDiff = vDifference.Length();
if (( flDiff > cl_weaponlag->value ) && ( cl_weaponlag->value > 0.0f ))
{
float flScale = flDiff / cl_weaponlag->value;
flSpeed *= flScale;
}
// FIXME: Needs to be predictable?
m_vecLastFacing = m_vecLastFacing + vDifference * ( flSpeed * gpGlobals->frametime );
// Make sure it doesn't grow out of control!!!
m_vecLastFacing = m_vecLastFacing.Normalize();
origin = origin + (vDifference * -1.0f) * 5.0f;
ASSERT( m_vecLastFacing.IsValid() );
}
Vector right, up;
AngleVectors( original_angles, forward, right, up );
float pitch = original_angles[PITCH];
if ( pitch > 180.0f )
{
pitch -= 360.0f;
}
else if ( pitch < -180.0f )
{
pitch += 360.0f;
}
if ( cl_weaponlag->value <= 0.0f )
{
origin = vOriginalOrigin;
angles = vOriginalAngles;
}
else
{
// FIXME: These are the old settings that caused too many exposed polys on some models
origin = origin + forward * ( -pitch * 0.035f );
origin = origin + right * ( -pitch * 0.03f );
origin = origin + up * ( -pitch * 0.02f );
}
}
//==========================
// V_CalcGunAngle
//==========================
@ -900,7 +966,9 @@ void V_CalcFirstPersonRefdef( ref_params_t *pparams )
AngleVectors( angles, pparams->forward, pparams->right, pparams->up );
V_CalcScrOffset( pparams );
view->v.angles = pparams->cl_viewangles;
Vector lastAngles;
lastAngles = view->v.angles = pparams->cl_viewangles;
V_CalcGunAngle( pparams );
// use predicted origin as view origin.
@ -911,7 +979,8 @@ void V_CalcFirstPersonRefdef( ref_params_t *pparams )
// Let the viewmodel shake at about 10% of the amplitude
V_ApplyShake( view->v.origin, view->v.angles, 0.9 );
for( i = 0; i < 3; i++ ) view->v.origin[i] += bob * 0.4 * pparams->forward[i];
for( i = 0; i < 3; i++ )
view->v.origin[i] += bob * 0.4 * pparams->forward[i];
view->v.origin[2] += bob;
view->v.angles[YAW] -= bob * 0.5;
@ -919,6 +988,9 @@ void V_CalcFirstPersonRefdef( ref_params_t *pparams )
view->v.angles[PITCH] -= bob * 0.3;
view->v.origin[2] -= 1;
// add lag
V_CalcViewModelLag( view->v.origin, view->v.angles, lastAngles );
// fudge position around to keep amount of weapon visible
// roughly equal with different FOV
if( pparams->viewsize == 110 ) view->v.origin[2] += 1;

View File

@ -436,7 +436,7 @@ int CHud :: MsgFunc_ScreenFade( const char *pszName, int iSize, void *pbuf )
float fadeTime = READ_FLOAT();
float holdTime = READ_FLOAT();
int fadeFlags = READ_SHORT();
int fadeFlags = READ_BYTE();
Vector m_FadeColor;

View File

@ -22,8 +22,9 @@ typedef enum
ED_VIEWMODEL, // client or bot viewmodel (for spectating)
ED_RIGIDBODY, // simulated physic
ED_TRIGGER, // just for sorting on a server
ED_PORTAL, // realtime display, portal or mirror brush or model
ED_PORTAL, // realtime portal or mirror brush or model
ED_SKYPORTAL, // realtime 3D-sky camera
ED_SCREEN, // realtime monitor (like portal but without perspective)
ED_MAXTYPES,
} edtype_t;

View File

@ -12,7 +12,8 @@
#pragma warning( disable : 4244 ) // int or float down-conversion
#define NUMVERTEXNORMALS 162
#define NUMVERTEXNORMALS 162
#define bound( min, num, max ) ((num) >= (min) ? ((num) < (max) ? (num) : (max)) : (min))
#ifndef M_PI
#define M_PI (float)3.14159265358979323846

View File

@ -15,7 +15,7 @@ const char *CL_LevelshotType( void )
{
// reinstall loadformats by magic keyword :)
if( !com.stricmp( GI->texmode, "Xash3D" ) || !com.stricmp( GI->texmode, "Xash" ))
return "png";
return "jpg";
else if( !com.stricmp( GI->texmode, "stalker" ) || !com.stricmp( GI->texmode, "S.T.A.L.K.E.R" ))
return "dds";
else if( !com.stricmp( GI->texmode, "Doom1" ) || !com.stricmp( GI->texmode, "Doom2" ))

View File

@ -1080,7 +1080,6 @@ int CL_SpawnDecal( HSPRITE m_hDecal, edict_t *pEnt, const vec3_t pos, int colorI
int i, j, numfragments;
vec3_t dir, verts[MAX_DECAL_VERTS];
fragment_t *fr, fragments[MAX_DECAL_FRAGMENTS];
float radius = 32.0f; // search radius
rgba_t color;
// invalid decal

View File

@ -639,7 +639,6 @@ void SV_PutClientInServer( edict_t *ent )
svgame.globals->time = sv.time * 0.001f;
ent->pvServerData->s.ed_type = ED_CLIENT; // init edict type
ent->free = false;
if( !sv.changelevel && !sv.loadgame )
{
@ -666,8 +665,6 @@ void SV_PutClientInServer( edict_t *ent )
// fisrt entering
svgame.dllFuncs.pfnClientPutInServer( ent );
ent->v.origin[2] -= GI->client_mins[2][2]; // FIXME: make sure off ground
SV_BaselineForEntity( ent );
}
}

View File

@ -642,7 +642,8 @@ edict_t* SV_AllocPrivateData( edict_t *ent, string_t className )
ent->v.classname = className;
ent->v.pContainingEntity = ent; // re-link
VectorSet( ent->v.rendercolor, 255, 255, 255 ); // assume default color
// allocate edict private memory (passed by dlls)
SpawnEdict = (LINK_ENTITY_FUNC)Com_GetProcAddress( svgame.hInstance, pszClassName );
if( !SpawnEdict )
@ -739,12 +740,13 @@ sv_client_t *SV_ClientFromEdict( const edict_t *pEdict, bool spawned_only )
if( svs.clients[i].state != cs_spawned )
return NULL;
}
#if 0
else
{
if( svs.clients[i].state < cs_connected )
return NULL;
}
#endif
client = svs.clients + i;
return client;
@ -3690,10 +3692,6 @@ bool SV_ParseEdict( script_t *script, edict_t *ent )
pkvd[i].szClassName = (char *)classname;
svgame.dllFuncs.pfnKeyValue( ent, &pkvd[i] );
}
// check for rendercolor
if( VectorIsNull( ent->v.rendercolor )) VectorSet( ent->v.rendercolor, 255, 255, 255 );
return true;
}
@ -3813,6 +3811,7 @@ void SV_SpawnEntities( const char *mapname, script_t *entities )
// setup all clients
ent = EDICT_NUM( i + 1 );
SV_InitEdict( ent );
SV_AllocPrivateData( ent, MAKE_STRING( "player" ));
ent->pvServerData->client = svs.clients + i;
ent->pvServerData->client->edict = ent;
}

View File

@ -171,13 +171,13 @@ static const loadformat_t load_quake4[] =
// wad files not requires path
static const loadformat_t load_hl1[] =
{
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // hl skyboxes
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_HL }, // hl textures from wad or buffer
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_HL }, // hl menu images (cached.wad etc)
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl menu images (cached.wad etc)
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // hl skyboxes
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio palette
{ NULL, NULL, NULL, IL_HINT_NO }
};

View File

@ -360,7 +360,7 @@ void CBaseBrush::Precache( void )
default:
if( pev->health > 0 ) // mapmaker forget set material ?
{
DevMsg("\n======/Xash SmartFiled System/======\n\n");
DevMsg("\n======/Xash SmartField System/======\n\n");
DevMsg("Please set material for %s,\n", STRING(pev->classname));
DevMsg("if we want make this breakable\n");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -44,104 +44,31 @@ STATE CBaseDMStart::GetState( CBaseEntity *pEntity )
else return STATE_OFF;
}
class CWallTorch : public CBaseEntity
{
public:
void Precache( void )
{
// if sound is missing just reset soundindex
pev->impulse = PRECACHE_SOUND( "ambience/fire1.wav" );
UTIL_PrecacheModel( "models/props/torch1.mdl" );
}
void Spawn( void )
{
Precache ();
if( !pev->impulse )
{
UTIL_Remove( this );
return;
}
// SetObjectClass( ED_NORMAL );
pev->flags |= FL_PHS_FILTER; // allow phs filter instead pvs
// setup attenuation radius
pev->armorvalue = 384.0f * ATTN_STATIC;
pev->soundindex = pev->impulse;
UTIL_SetModel( ENT( pev ), "models/props/torch1.mdl" );
UTIL_SetSize(pev, g_vecZero, g_vecZero);
SetBits( pev->flags, FL_POINTENTITY );
pev->animtime = gpGlobals->time + 0.2; // enable animation
pev->framerate = 0.5f;
}
};
//=========================================================
// static infodecal
//=========================================================
class CDecal : public CBaseEntity
{
public:
void KeyValue( KeyValueData *pkvd )
void KeyValue( KeyValueData *pkvd )
{
if( FStrEq( pkvd->szKeyName, "texture" ))
if (FStrEq(pkvd->szKeyName, "texture"))
{
pkvd->fHandled = TRUE;
pev->skin = DECAL_INDEX( pkvd->szValue );
if( pev->skin >= 0 ) return;
if ( pev->skin >= 0 ) return;
Msg( "Can't find decal %s\n", pkvd->szValue );
}
}
void PostSpawn( void )
void PostSpawn( void )
{
if ( FStringNull( pev->targetname ))
MakeDecal();
}
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
MakeDecal();
}
void MakeDecal( void )
{
if ( pev->skin < 0 )
{
REMOVE_ENTITY( ENT( pev ));
return;
}
if ( pev->skin < 0 ) { REMOVE_ENTITY(ENT(pev)); return; }
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 > 0 )
modelIndex = VARS( trace.pHit )->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;
if ( FStringNull( pev->targetname ))
{
g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
}
else
{
MESSAGE_BEGIN( MSG_BROADCAST, gmsg.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 );
WRITE_SHORT( entityIndex );
if( entityIndex > 0 )
WRITE_SHORT( modelIndex );
MESSAGE_END();
}
g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
SetThink( Remove );
SetNextThink( 0.3 );
}
@ -285,114 +212,206 @@ void CPortalSurface :: PostActivate( void )
}
}
//====================================================================
// multisource
//====================================================================
TYPEDESCRIPTION CMultiSource::m_SaveData[] =
//=========================================================
// info_path - train node path.
//=========================================================
void CInfoPath :: KeyValue( KeyValueData *pkvd )
{
DEFINE_ARRAY( CMultiSource, m_rgEntities, FIELD_EHANDLE, MAX_MULTI_TARGETS ),
DEFINE_ARRAY( CMultiSource, m_rgTriggered, FIELD_INTEGER, MAX_MULTI_TARGETS ),
DEFINE_FIELD( CMultiSource, m_iTotal, FIELD_INTEGER ),
}; IMPLEMENT_SAVERESTORE( CMultiSource, CBaseLogic );
LINK_ENTITY_TO_CLASS( multisource, CMultiSource );
void CMultiSource::Spawn()
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
SetNextThink( 0.1 );
pev->spawnflags |= SF_START_ON;
SetThink( Register );
}
void CMultiSource::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int i = 0;
// Find the entity in our list
while (i < m_iTotal) if ( m_rgEntities[i++] == pCaller ) break;
// if we didn't find it, report error and leave
if (i > m_iTotal) return;
STATE s = GetState();
m_rgTriggered[i-1] ^= 1;
if ( s == GetState()) return;
if ( s == STATE_OFF )
if ( FStrEq( pkvd->szKeyName, "wait" ))
{
USE_TYPE useType = USE_TOGGLE;
if ( m_globalstate ) useType = USE_ON;
UTIL_FireTargets( pev->target, NULL, this, useType, value );
UTIL_FireTargets( m_iszKillTarget, NULL, this, USE_REMOVE );
m_flDelay = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if ( FStrEq (pkvd->szKeyName, "newspeed" ))
{
if ( pkvd->szValue[0] == '+' ) pev->button = SPEED_INCREMENT; //increase speed
else if ( pkvd->szValue[0] == '-' ) pev->button = SPEED_DECREMENT; //decrease speed
else if ( pkvd->szValue[0] == '*' ) pev->button = SPEED_MULTIPLY; //multiply speed by
else if ( pkvd->szValue[0] == ':' ) pev->button = SPEED_DIVIDE; //divide speed by
else pev->button = SPEED_MASTER; // just set new speed
if( pev->button ) pkvd->szValue++;
pev->speed = atof( pkvd->szValue );
ALERT( at_console, "pev->button %d, pev->speed %g\n", pev->button, pev->speed );
pkvd->fHandled = TRUE;
}
else if ( !FClassnameIs( pev, "path_corner" ) && m_cPaths < MAX_MULTI_TARGETS )
{
char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp );
m_iPathName[m_cPaths] = ALLOC_STRING( tmp );
m_iPathWeight[m_cPaths] = atof( pkvd->szValue );
m_cPaths++;
pkvd->fHandled = TRUE;
}
else CBaseEntity::KeyValue( pkvd );
}
STATE CMultiSource::GetState( void )
TYPEDESCRIPTION CInfoPath::m_SaveData[] =
{ DEFINE_FIELD( CInfoPath, m_cPaths, FIELD_INTEGER ),
DEFINE_FIELD( CInfoPath, m_index, FIELD_INTEGER ),
DEFINE_ARRAY( CInfoPath, m_iPathName, FIELD_STRING, MAX_MULTI_TARGETS ),
DEFINE_ARRAY( CInfoPath, m_iPathWeight, FIELD_INTEGER, MAX_MULTI_TARGETS ),
DEFINE_ARRAY( CInfoPath, m_pNextPath, FIELD_CLASSPTR, MAX_MULTI_TARGETS ),
DEFINE_FIELD( CInfoPath, m_pPrevPath, FIELD_CLASSPTR ),
};IMPLEMENT_SAVERESTORE( CInfoPath, CBaseLogic );
LINK_ENTITY_TO_CLASS( info_path, CInfoPath );
LINK_ENTITY_TO_CLASS( path_corner, CInfoPath );
void CInfoPath :: Spawn( void )
{
// Is everything triggered?
int i = 0;
// Still initializing?
if ( pev->spawnflags & SF_START_ON ) return STATE_OFF;
while (i < m_iTotal)
if( FClassnameIs( pev, "path_corner" ))
{
if (m_rgTriggered[i] == 0) break;
i++;
// compatible mode
m_iPathName[m_cPaths] = pev->target;
m_iPathWeight[m_cPaths] = 0;
m_cPaths++;
}
if (i == m_iTotal)
int r_index = 0;
int w_index = m_cPaths - 1;
while( r_index < w_index )
{
if ( !m_globalstate || gGlobalState.EntityGetState( m_globalstate ) == GLOBAL_ON )
return STATE_ON;
// we store target with right index in tempname
int name = m_iPathName [r_index];
int weight = m_iPathWeight[r_index];
// target with right name is free, record new value from wrong name
m_iPathName [r_index] = m_iPathName [w_index];
m_iPathWeight[r_index] = m_iPathWeight[w_index];
// ok, we can swap targets
m_iPathName [w_index] = name;
m_iPathWeight[w_index] = weight;
r_index++;
w_index--;
}
return STATE_OFF;
m_iState = STATE_ON;
m_index = 0;
SetBits( pev->flags, FL_POINTENTITY );
UTIL_SetModel( ENT( pev ), "blabla.mdl");
pev->scale = 0.1f;
}
void CMultiSource::Register(void)
{
m_iTotal = 0;
memset( m_rgEntities, 0, MAX_MULTI_TARGETS * sizeof(EHANDLE) );
SetThink(NULL);
// search for all entities which target this multisource (pev->targetname)
CBaseEntity *pTarget = UTIL_FindEntityByTarget( NULL, STRING(pev->targetname) );
while (pTarget && (m_iTotal < MAX_MULTI_TARGETS))
void CInfoPath :: PostActivate( void )
{
// find all paths and save into array
for(int i = 0; i < m_cPaths; i++ )
{
m_rgEntities[m_iTotal++] = pTarget;
pTarget = UTIL_FindEntityByTarget( pTarget, STRING(pev->targetname));
CBaseEntity *pNext = UTIL_FindEntityByTargetname( NULL, STRING( m_iPathName[i] ));
if( pNext ) // found path
{
m_pNextPath[i] = (CInfoPath*)pNext; // valid path
m_pNextPath[i]->SetPrev( this );
}
}
pTarget = UTIL_FindEntityByClassname(NULL, "multi_manager");
while (pTarget && (m_iTotal < MAX_MULTI_TARGETS))
{
if ( pTarget->HasTarget(pev->targetname) ) m_rgEntities[m_iTotal++] = pTarget;
pTarget = UTIL_FindEntityByClassname( pTarget, "multi_manager" );
}
pev->spawnflags &= ~SF_START_ON;
}
CBaseEntity *CInfoPath::GetNext( void )
{
int total = 0;
for ( int i = 0; i < m_cPaths; i++ )
{
total += m_iPathWeight[i];
}
if ( total ) // weighted random choose
{
int chosen = RANDOM_LONG( 0, total );
int curpos = 0;
for ( i = 0; i < m_cPaths; i++ )
{
curpos += m_iPathWeight[i];
if ( curpos >= chosen )
{
m_index = i;
break;
}
}
}
// validate path
ASSERTSZ( m_pNextPath[m_index] != this, "GetNext: self path!\n");
if( m_pNextPath[m_index] && m_pNextPath[m_index]->edict() && m_pNextPath[m_index] != this && m_pNextPath[m_index]->m_iState == STATE_ON )
return m_pNextPath[m_index];
return NULL;
}
CBaseEntity *CInfoPath::GetPrev( void )
{
// validate path
ASSERTSZ( m_pPrevPath != this, "GetPrev: self path!\n");
if(m_pPrevPath && m_pPrevPath->edict() && m_pPrevPath != this && m_pPrevPath->m_iState == STATE_ON )
return m_pPrevPath;
return NULL;
}
void CInfoPath::SetPrev( CInfoPath *pPrev )
{
if( pPrev && pPrev->edict() && pPrev != this )
m_pPrevPath = pPrev;
}
void CInfoPath :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
m_hActivator = pActivator;
if ( useType == USE_TOGGLE )
{
if( m_iState == STATE_ON )
useType = USE_OFF;
else useType = USE_ON;
}
if ( useType == USE_ON )
{
m_iState = STATE_ON;
}
else if ( useType == USE_OFF )
{
m_iState = STATE_OFF;
}
if ( useType == USE_SET ) // set new path
{
if( value > 0.0f )
{
m_index = (value - 1);
if( m_index >= m_cPaths )
m_index = 0;
}
}
else if ( useType == USE_RESET )
{
m_index = 0;
}
else if ( useType == USE_SHOWINFO )
{
ALERT( at_console, "======/Xash Debug System/======\n");
ALERT( at_console, "classname: %s\n", STRING(pev->classname));
ALERT( at_console, "State: %s, number of targets %d, path weight %d\n", GetStringForState( GetState()), m_cPaths- 1, m_iPathWeight[m_index]);
if( m_pPrevPath && m_pPrevPath->edict( ))
ALERT( at_console, "Prev path %s", STRING( m_pPrevPath->pev->targetname ));
if( m_pNextPath[m_index] && m_pNextPath[m_index]->edict( ))
ALERT( at_console, "Prev path %s", STRING( m_pNextPath[m_index]->pev->targetname ));
ALERT( at_console, "\n" );
}
}
LINK_ENTITY_TO_CLASS( infodecal, CDecal );
LINK_ENTITY_TO_CLASS( info_target, CInfoTarget );
LINK_ENTITY_TO_CLASS( target_position, CPointEntity );
LINK_ENTITY_TO_CLASS( target_location, CPointEntity );
LINK_ENTITY_TO_CLASS( light_torch_small_walltorch, CWallTorch );
LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity );
LINK_ENTITY_TO_CLASS( misc_teleporter_dest, CPointEntity );
LINK_ENTITY_TO_CLASS( misc_portal_surface, CPortalSurface );
LINK_ENTITY_TO_CLASS( info_portal, CPortalSurface );
LINK_ENTITY_TO_CLASS( info_player_intermission, CPointEntity );
LINK_ENTITY_TO_CLASS( info_notnull, CPointEntity );
LINK_ENTITY_TO_CLASS( info_null, CNullEntity );
LINK_ENTITY_TO_CLASS( misc_model, CNullEntity );
LINK_ENTITY_TO_CLASS( info_texlights, CNullEntity);
LINK_ENTITY_TO_CLASS( info_compile_parameters, CNullEntity);
LINK_ENTITY_TO_CLASS( info_intermission, CInfoIntermission );
LINK_ENTITY_TO_CLASS( misc_portal_camera, CInfoIntermission);
LINK_ENTITY_TO_CLASS( info_player_deathmatch, CBaseDMStart);
LINK_ENTITY_TO_CLASS( info_player_start, CPointEntity);
LINK_ENTITY_TO_CLASS( info_landmark, CPointEntity);
LINK_ENTITY_TO_CLASS( info_camera, CInfoIntermission );
LINK_ENTITY_TO_CLASS( info_player_deathmatch, CBaseDMStart );
LINK_ENTITY_TO_CLASS( info_player_start, CPointEntity );
LINK_ENTITY_TO_CLASS( info_landmark, CPointEntity );

View File

@ -15,7 +15,7 @@ public:
class CNullEntity : public CBaseEntity
{
public:
void Spawn( void ){ REMOVE_ENTITY(ENT(pev)); }
void Spawn( void ){ REMOVE_ENTITY( ENT( pev )); }
};
class CBaseDMStart : public CPointEntity
@ -27,7 +27,68 @@ public:
private:
};
class CLaserSpot : public CBaseEntity//laser spot for different weapons
#define SPEED_MASTER 0
#define SPEED_INCREMENT 1
#define SPEED_DECREMENT 2
#define SPEED_MULTIPLY 3
#define SPEED_DIVIDE 4
#define SF_TELEPORT_TONEXT 0x1
class CInfoPath : public CBaseLogic
{
public:
void Spawn( );
void KeyValue( KeyValueData* pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void PostActivate( void );
float GetDelay( void ) { return m_flDelay; }
void GetSpeed( float *speed )
{
if( !pev->speed ) return;
float curspeed = *speed; // save our speed
// operate
if( pev->button == SPEED_INCREMENT ) curspeed += pev->speed;
if( pev->button == SPEED_DECREMENT ) curspeed -= pev->speed;
if( pev->button == SPEED_MULTIPLY ) curspeed *= pev->speed;
if( pev->button == SPEED_DIVIDE ) curspeed /= pev->speed;
if( pev->button == SPEED_MASTER ) curspeed = pev->speed;
// check validate speed
if( curspeed <= -MAX_VELOCITY || curspeed >= MAX_VELOCITY )
{
curspeed = *speed; // set old value
ALERT( at_console, "\n======/Xash SmartField System/======\n\n" );
ALERT( at_console, "%s: %s contains invalid speed operation! Check it!\n Speed not changed!\n", STRING( pev->classname ), STRING( pev->targetname ));
}
*speed = curspeed;
}
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_cPaths; // the total number of targets in this manager's fire list.
int m_index; // Current target
int m_iPathName[MAX_MULTI_TARGETS]; // list if indexes into global string array
int m_iPathWeight[MAX_MULTI_TARGETS]; // list if weight into global string array
CInfoPath *Instance( edict_t *pent )
{
if ( FClassnameIs( pent, "info_path" ))
return (CInfoPath *)GET_PRIVATE( pent );
return NULL;
}
CInfoPath *m_pNextPath[MAX_MULTI_TARGETS];
CInfoPath *m_pPrevPath;
CBaseEntity *GetNext( void );
CBaseEntity *GetPrev( void );
void SetPrev( CInfoPath *pPrev );
};
class CLaserSpot : public CBaseEntity // laser spot for different weapons
{
void Spawn( void );
void Precache( void );

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,6 @@ public:
BOOL IsLockedByMaster( void );
BOOL IsLockedByMaster( USE_TYPE useType );
BOOL IsLockedByMaster( CBaseEntity *pActivator );
void FireTargets( USE_TYPE useType = USE_TOGGLE, float value = 0 );
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
virtual void KeyValue( KeyValueData* pkvd);
virtual int Save( CSave &save );
@ -27,105 +26,14 @@ public:
EHANDLE m_hTarget;
STATE m_iState;
string_t m_sMaster;
string_t m_iszKillTarget; //evil stuff. agrhh
string_t m_sSet;//used for logic_usetype
string_t m_sReset;//used for logic_usetype
string_t m_globalstate;
string_t m_sSet; // used for logic_usetype
string_t m_sReset; // used for logic_usetype
float m_flMin, m_flMax;
};
#define SF_CORNER_WAITTRIG 0x001
#define SF_CORNER_TELEPORT 0x002
#define SF_CORNER_FIREONCE 0x004
class CPathCorner : public CBaseLogic
{
public:
void Spawn( );
void KeyValue( KeyValueData* pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
float GetDelay( void ){ return pev->spawnflags & SF_CORNER_WAITTRIG ? -1 : m_flWait; }
void GetSpeed( float *speed ) { if(pev->speed != 0) *speed = pev->speed; }
void UpdateTargets( void );
void Link( void );
void PostActivate( void ){ Link(); }
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
CPathCorner *Instance( edict_t *pent )
{
if ( FClassnameIs( pent, "path_corner" ) )
return (CPathCorner *)GET_PRIVATE(pent);
return NULL;
}
CPathCorner *m_pNextPath1;
CPathCorner *m_pNextPath2;
CPathCorner *m_pPrevPath;
CBaseEntity *ValidPath( CBaseEntity *m_pPath );
CBaseEntity *GetNext( void );
CBaseEntity *GetPrev( void ){ return ValidPath( m_pPrevPath ); }
void SetPrev( CPathCorner *pPrev ) { m_pPrevPath = (CPathCorner *)ValidPath((CPathCorner *)pPrev); }
};
class CPathTrack : public CBaseLogic
{
public:
void Spawn( void );
void Activate( void );
void KeyValue( KeyValueData* pkvd);
void SetPrevious( CPathTrack *pprevious );
void Link( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
CBaseEntity *ValidPath( CBaseEntity *ppath, int testFlag ); // Returns ppath if enabled, NULL otherwise
void Project( CBaseEntity *pstart, CBaseEntity *pend, Vector *origin, float dist );
static CPathTrack *Instance( edict_t *pent );
CBaseEntity *LookAhead( Vector *origin, float dist, int move );
CBaseEntity *Nearest( Vector origin ); //notused
CBaseEntity *GetNext( void );
CBaseEntity *GetPrev( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
#if PATH_SPARKLE_DEBUG
void EXPORT Sparkle(void);
#endif
float m_length;
string_t m_altName;
CPathTrack *m_pnext;
CPathTrack *m_pprevious;
CPathTrack *m_paltpath;
};
class CMultiSource : public CBaseLogic
{
public:
void Spawn( );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
STATE GetState( void );
void EXPORT Register( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
EHANDLE m_rgEntities[MAX_MULTI_TARGETS];
int m_rgTriggered[MAX_MULTI_TARGETS];
int m_iTotal;
};
#include "baseinfo.h"
class CUtilRainModify : public CPointEntity
class CEnvRainModify : public CPointEntity
{
public:
void Spawn( void );

File diff suppressed because it is too large Load Diff

View File

@ -4,69 +4,33 @@
#ifndef BASEMOVER_H
#define BASEMOVER_H
//rotating brush flags
#define SF_BRUSH_ROTATE_Z_AXIS 4
#define SF_BRUSH_ROTATE_X_AXIS 8
//door flags
#define SF_DOOR_START_OPEN 1
#define SF_DOOR_ROTATE_BACKWARDS 2
#define SF_DOOR_PASSABLE 8
#define SF_DOOR_ONEWAY 16
#define SF_DOOR_NO_AUTO_RETURN 32
#define SF_DOOR_ROTATE_Z 64
#define SF_DOOR_ROTATE_X 128
#define SF_DOOR_USE_ONLY 256
#define SF_DOOR_NOMONSTERS 512
// Tracktrain spawn flags
#define SF_TRACKTRAIN_NOPITCH 0x0001
#define SF_TRACKTRAIN_NOCONTROL 0x0002
#define SF_TRACKTRAIN_FORWARDONLY 0x0004
#define SF_TRACKTRAIN_PASSABLE 0x0008
#define SF_TRACKTRAIN_NOYAW 0x0010 //LRC
#define SF_TRACKTRAIN_AVELOCITY 0x800000 //LRC - avelocity has been set manually, don't turn.
#define SF_TRACKTRAIN_AVEL_GEARS 0x400000 //LRC - avelocity should be scaled up/down when the train changes gear.
// Spawnflag for CPathTrack
#define SF_PATH_DISABLED 0x00000001
#define SF_PATH_FIREONCE 0x00000002
#define SF_PATH_ALTREVERSE 0x00000004
#define SF_PATH_DISABLE_TRAIN 0x00000008
#define SF_PATH_ALTERNATE 0x00008000
#define SF_PATH_AVELOCITY 0x00080000 //LRC
//LRC - values in 'armortype'
#define PATHSPEED_SET 0
#define PATHSPEED_ACCEL 1
#define PATHSPEED_TIME 2
#define PATHSPEED_SET_MASTER 3
class CBaseMover : public CBaseBrush
{
public:
void KeyValue( KeyValueData *pkvd );
virtual void AxisDir( void );
void (CBaseMover::*m_pfnCallWhenMoveDone)(void); //custom movedone function
void (CBaseMover::*m_pfnCallWhenMoveDone)(void); // custom movedone function
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
virtual int IsWater( void ){ return pev->skin != 0; };
static TYPEDESCRIPTION m_SaveData[];
float m_flMoveDistance;//rotating distance
float m_flBlockedTime; //set blocked refresh time
int m_iMode;//style of working
float m_flValue;//value to send
float m_flMoveDistance; // rotating distance
float m_flBlockedTime; // set blocked refresh time
int m_iMode; // style of working
float m_flValue; // value to send
float m_flHeight;
float m_flWait;
float m_flLip;
Vector m_vecPosition1; //startpos
Vector m_vecPosition2; //endpos
Vector m_vecAngle1; //startangle
Vector m_vecAngle2; //endangle
Vector m_vecFinalDest; //basemover finalpos
Vector m_vecFinalAngle; //basemover finalangle
Vector m_vecFloor; //basemover dest floor
float m_flLinearMoveSpeed;//member linear speed
float m_flAngularMoveSpeed;//member angular speed
Vector m_vecPosition1; // startpos
Vector m_vecPosition2; // endpos
Vector m_vecAngle1; // startangle
Vector m_vecAngle2; // endangle
Vector m_vecFinalDest; // basemover finalpos
Vector m_vecFinalAngle; // basemover finalangle
Vector m_vecFloor; // basemover dest floor
float m_flLinearMoveSpeed; // member linear speed
float m_flAngularMoveSpeed; // member angular speed
// common member functions
void LinearMove ( Vector vecInput, float flSpeed );
@ -89,15 +53,16 @@ public:
void Spawn( void );
void Precache( void );
virtual void PostSpawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
BOOL IsWater( void ){ return pev->skin != 0; };
void EXPORT DoorUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT ShowInfo( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT DoorTouch( CBaseEntity *pOther );
virtual void Blocked( CBaseEntity *pOther );
virtual int ObjectCaps( void )
virtual void SetToggleState( int state );
virtual int ObjectCaps( void )
{
if ( FBitSet ( pev->spawnflags, SF_DOOR_USE_ONLY ))//door without name player can direct using
return (CBaseMover::ObjectCaps() & ~FCAP_ACROSS_TRANSITION | FCAP_IMPULSE_USE );
else return (CBaseMover::ObjectCaps() & ~FCAP_ACROSS_TRANSITION);
if ( FStringNull( pev->targetname ) && m_iMode != 1 ) // door without name player can direct using
return (CBaseMover::ObjectCaps() & ~FCAP_ACROSS_TRANSITION | FCAP_IMPULSE_USE | FCAP_ONLYDIRECT_USE);
return (CBaseMover::ObjectCaps() & ~FCAP_ACROSS_TRANSITION);
};
// local functions
@ -111,7 +76,9 @@ public:
class CRotDoor : public CBaseDoor
{
public:
void Spawn( void );
virtual void PostSpawn( void ) {}
virtual void SetToggleState( int state );
virtual BOOL IsRotatingDoor( void ){ return TRUE; };
};
@ -134,6 +101,7 @@ public:
void PostSpawn( void );
void Setup( void );
void PostActivate( void );
virtual void Blocked( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
float CalcFloor( void )
@ -168,7 +136,6 @@ public:
BOOL Stop( float flWait = -1 );
BOOL Teleport( void );
void Blocked( CBaseEntity *pOther );
BOOL IsWater( void ){ return pev->skin != 0; };
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
Vector TrainOrg( void ) { return (pev->mins + pev->maxs) * 0.5; }
@ -177,76 +144,16 @@ public:
void EXPORT Next( void );
//path operations
CBaseEntity *FindPath( void );
CBaseEntity *FindNextPath( void );
void Reverse( void );
BOOL FindPath( void );
BOOL FindNextPath( void );
void UpdateTargets( void );
void UpdateSpeed( float value = 0 );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
CBaseEntity *pCurPath, *pNextPath;
};
class CFuncTrackTrain : public CBaseMover
{
public:
void Spawn( void );
void Precache( void );
void Blocked( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData* pkvd );
void EXPORT DesiredAction( void ); //LRC - used to be called Next!
void PostActivate( void );
void ClearPointers( void );
// void EXPORT Next( void );
void EXPORT PostponeNext( void );
void EXPORT Find( void );
void EXPORT NearestPath( void );
void EXPORT DeadEnd( void );
void NextThink( float thinkTime, BOOL alwaysThink );
void SetTrack( CBaseEntity *track ) { pPath = ((CPathTrack *)track)->Nearest(pev->origin); }
void SetControls( entvars_t *pevControls );
BOOL OnControls( entvars_t *pev );
void StopSound ( void );
void UpdateSound ( void );
static CFuncTrackTrain *Instance( edict_t *pent )
{
if ( FClassnameIs( pent, "func_tracktrain" ) )
return (CFuncTrackTrain *)GET_PRIVATE(pent);
return NULL;
}
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
virtual int ObjectCaps( void ) { return CBaseMover :: ObjectCaps() | FCAP_DIRECTIONAL_USE; }
virtual void OverrideReset( void );
CBaseEntity *pPath;
float m_length;
float m_height;
// I get it... this records the train's max speed (as set by the level designer), whereas
// pev->speed records the current speed (as set by the player). --LRC
// m_speed is also stored, as an int, in pev->impulse.
float m_speed;
float m_dir;
float m_startSpeed;
Vector m_controlMins;
Vector m_controlMaxs;
int m_soundPlaying;
float m_flBank;
float m_oldSpeed;
Vector m_vecBaseAvel; // LRC - the underlying avelocity, superceded by normal turning behaviour where applicable
CBaseEntity *pPath, *pNextPath;
};
#endif //BASEMOVER_H

View File

@ -66,10 +66,11 @@ void CEnvShower::Touch( CBaseEntity *pOther )
class ChangeLevelFire : public CBaseLogic
{
public:
void PostActivate( void ) { FireTargets(); UTIL_Remove( this ); }
void PostActivate( void ) { UTIL_FireTargets( pev->target, this, this, USE_TOGGLE ); UTIL_Remove( this ); }
int ObjectCaps( void ) { return CBaseEntity::ObjectCaps() | FCAP_FORCE_TRANSITION; }
};
LINK_ENTITY_TO_CLASS( fireent, ChangeLevelFire );
//=======================================================================
// faderent - rendering time effects
//=======================================================================

View File

@ -1,427 +0,0 @@
//=======================================================================
// Copyright (C) XashXT Group 2006
//=======================================================================
#include "extdll.h"
#include "utils.h"
#include "cbase.h"
//atoi(g_engfuncs.pfnInfoKeyValue(g_engfuncs.pfnGetInfoKeyBuffer(edict()), "skin"));
//use this for custom change speed
//=========================================================
// path_corner - train node path.
//=========================================================
TYPEDESCRIPTION CPathCorner::m_SaveData[] =
{ DEFINE_FIELD( CPathCorner, m_pNextPath1, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathCorner, m_pNextPath2, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathCorner, m_pPrevPath, FIELD_CLASSPTR ),
};IMPLEMENT_SAVERESTORE(CPathCorner, CBaseLogic);
void CPathCorner :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "altpath"))
{
pev->netname = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
LINK_ENTITY_TO_CLASS( path_corner, CPathCorner );
void CPathCorner :: Spawn( void )
{
m_iState = STATE_ON;
SetBits( pev->flags, FL_POINTENTITY );
}
void CPathCorner :: Link( void )
{
CBaseEntity *pTarget;
if ( FStringNull( pev->targetname ) ) return;
if ( !FStringNull(pev->target) )
{
pTarget = UTIL_FindEntityByTargetname( NULL, STRING(pev->target));
if(pTarget)
{
m_pNextPath1 = (CPathCorner*)pTarget;//valid path
m_pNextPath1->SetPrev( this );
}
else DevMsg( "Dead end link %s\n", STRING(pev->target) );
}
if ( !FStringNull(pev->netname) )
{
pTarget = UTIL_FindEntityByTargetname( NULL, STRING(pev->netname));
if(pTarget)
{
m_pNextPath2 = (CPathCorner*)pTarget;//valid path
m_pNextPath2->SetPrev( this );
}
else DevMsg( "Dead end link %s\n", STRING(pev->netname) );
}
}
void CPathCorner::UpdateTargets( void )
{
UTIL_FireTargets(pev->message, this, this, USE_TOGGLE );
if(pev->spawnflags & SF_CORNER_FIREONCE)
{
pev->message = iStringNull;
ClearBits( pev->spawnflags, SF_CORNER_FIREONCE );
}
}
CBaseEntity *CPathCorner::ValidPath( CBaseEntity *m_pPath )
{
ASSERTSZ( m_pPath != this, "ValidPath: self path!\n");
if(m_pPath && m_pPath->edict() && m_pPath != this && ((CPathCorner *)m_pPath)->m_iState == STATE_ON)
return m_pPath;
return this;
}
CBaseEntity *CPathCorner::GetNext( void )
{
if(pev->team) return ValidPath( m_pNextPath2 );
return ValidPath( m_pNextPath1 );
}
void CPathCorner :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
m_hActivator = pActivator;
if (useType == USE_TOGGLE)
{
if(m_iState == STATE_ON) useType = USE_OFF;
else useType = USE_ON;
}
if (useType == USE_ON) m_iState = STATE_ON;
else if(useType == USE_OFF) m_iState = STATE_OFF;
else if(useType == USE_SET) pev->team = !pev->team; //change path
else if (useType == USE_SHOWINFO)
{
ALERT(at_console, "======/Xash Debug System/======\n");
ALERT(at_console, "classname: %s\n", STRING(pev->classname));
ALERT(at_console, "State: %s, wait %g\n", GetStringForState( GetState()), m_flWait);
if(ValidPath(m_pPrevPath)) Msg("Prev path %s", STRING(m_pPrevPath->pev->targetname));
if(ValidPath(m_pNextPath1))Msg("Next path %s", STRING(m_pNextPath1->pev->targetname));
if(ValidPath(m_pNextPath2))Msg("Alt path %s", STRING(m_pNextPath2->pev->targetname));
SHIFT;
}
}
//=========================================================
// path_track - tracktrain node path.
//=========================================================
TYPEDESCRIPTION CPathTrack::m_SaveData[] =
{
DEFINE_FIELD( CPathTrack, m_length, FIELD_FLOAT ),
DEFINE_FIELD( CPathTrack, m_pnext, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_paltpath, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_pprevious, FIELD_CLASSPTR ),
DEFINE_FIELD( CPathTrack, m_altName, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CPathTrack, CBaseEntity );
LINK_ENTITY_TO_CLASS( path_track, CPathTrack );
//
// Cache user-entity-field values until spawn is called.
//
void CPathTrack :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "altpath"))
{
m_altName = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "turnspeed")) //LRC
{
if (pkvd->szValue[0]) // if the field is blank, don't set the spawnflag.
{
pev->spawnflags |= SF_PATH_AVELOCITY;
UTIL_StringToVector( (float*)pev->avelocity, pkvd->szValue);
}
pkvd->fHandled = TRUE;
}
else
CBaseLogic::KeyValue( pkvd );
}
void CPathTrack :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int on;
// Use toggles between two paths
if ( m_paltpath )
{
on = !FBitSet( pev->spawnflags, SF_PATH_ALTERNATE );
if (useType == USE_TOGGLE)
{
if(on) useType = USE_OFF;
else useType = USE_ON;
}
if (useType == USE_ON)ClearBits( pev->spawnflags, SF_PATH_ALTERNATE );
else if(useType == USE_OFF)SetBits( pev->spawnflags, SF_PATH_ALTERNATE );
}
else // Use toggles between enabled/disabled
{
on = !FBitSet( pev->spawnflags, SF_PATH_DISABLED );
if (useType == USE_TOGGLE)
{
if(on) useType = USE_OFF;
else useType = USE_ON;
}
if (useType == USE_ON)ClearBits( pev->spawnflags, SF_PATH_DISABLED );
else if(useType == USE_OFF)SetBits( pev->spawnflags, SF_PATH_DISABLED );
}
}
void CPathTrack :: Link( void )
{
CBaseEntity *pTarget;
if( !FStringNull( pev->target ))
{
pTarget = UTIL_FindEntityByTargetname( NULL, STRING(pev->target) );
if( pTarget )
{
m_pnext = (CPathTrack*)pTarget;
m_pnext->SetPrevious( this );
}
else ALERT( at_console, "Dead end link %s\n", STRING(pev->target) );
}
// Find "alternate" path
if ( m_altName )
{
pTarget = UTIL_FindEntityByTargetname( NULL, STRING(m_altName) );
if ( pTarget ) // If no next pointer, this is the end of a path
{
m_paltpath = (CPathTrack*)pTarget;
m_paltpath->SetPrevious( this );
}
}
}
void CPathTrack :: Spawn( void )
{
pev->solid = SOLID_TRIGGER;
UTIL_SetSize(pev, Vector(-8, -8, -8), Vector(8, 8, 8));
m_pnext = NULL;
m_pprevious = NULL;
// DEBUGGING CODE
#if PATH_SPARKLE_DEBUG
SetThink( Sparkle );
SetNextThink( 0.5 );
#endif
}
void CPathTrack::Activate( void )
{
if ( !FStringNull( pev->targetname ) ) // Link to next, and back-link
Link();
CBaseLogic::Activate();
}
CBaseEntity *CPathTrack :: ValidPath( CBaseEntity *ppath, int testFlag )
{
if ( !ppath )
return NULL;
if ( testFlag && FBitSet( ppath->pev->spawnflags, SF_PATH_DISABLED ) )
return NULL;
return ppath;
}
void CPathTrack :: Project( CBaseEntity *pstart, CBaseEntity *pend, Vector *origin, float dist )
{
if ( pstart && pend )
{
Vector dir = (pend->pev->origin - pstart->pev->origin);
dir = dir.Normalize();
*origin = pend->pev->origin + dir * dist;
}
}
CBaseEntity *CPathTrack::GetNext( void )
{
if ( m_paltpath && FBitSet( pev->spawnflags, SF_PATH_ALTERNATE ) && !FBitSet( pev->spawnflags, SF_PATH_ALTREVERSE ) )
return m_paltpath;
return m_pnext;
}
CBaseEntity *CPathTrack::GetPrev( void )
{
if ( m_paltpath && FBitSet( pev->spawnflags, SF_PATH_ALTERNATE ) && FBitSet( pev->spawnflags, SF_PATH_ALTREVERSE ) )
return m_paltpath;
return m_pprevious;
}
void CPathTrack::SetPrevious( CPathTrack *pprev )
{
// Only set previous if this isn't my alternate path
if ( pprev && !FStrEq( STRING(pprev->pev->targetname), STRING(m_altName) ) )
m_pprevious = pprev;
}
// Assumes this is ALWAYS enabled
CBaseEntity *CPathTrack :: LookAhead( Vector *origin, float dist, int move )
{
CBaseEntity *pcurrent;
float originalDist = dist;
pcurrent = this;
Vector currentPos = *origin;
if ( dist < 0 ) // Travelling backwards through path
{
dist = -dist;
while ( dist > 0 )
{
Vector dir = pcurrent->pev->origin - currentPos;
float length = dir.Length();
if ( !length )
{
if ( !ValidPath(pcurrent->GetPrev(), move) ) // If there is no previous node, or it's disabled, return now.
{
if ( !move )
Project( pcurrent->GetNext(), pcurrent, origin, dist );
return NULL;
}
pcurrent = pcurrent->GetPrev();
}
else if ( length > dist ) // enough left in this path to move
{
*origin = currentPos + (dir * (dist / length));
return pcurrent;
}
else
{
dist -= length;
currentPos = pcurrent->pev->origin;
*origin = currentPos;
if ( !ValidPath(pcurrent->GetPrev(), move) ) // If there is no previous node, or it's disabled, return now.
return NULL;
pcurrent = pcurrent->GetPrev();
}
}
*origin = currentPos;
return pcurrent;
}
else
{
while ( dist > 0 )
{
if ( !ValidPath(pcurrent->GetNext(), move) ) // If there is no next node, or it's disabled, return now.
{
if ( !move )
Project( pcurrent->GetPrev(), pcurrent, origin, dist );
return NULL;
}
Vector dir = pcurrent->GetNext()->pev->origin - currentPos;
float length = dir.Length();
if ( !length && !ValidPath( pcurrent->GetNext()->GetNext(), move ) )
{
if ( dist == originalDist ) // HACK -- up against a dead end
return NULL;
return pcurrent;
}
if ( length > dist ) // enough left in this path to move
{
*origin = currentPos + (dir * (dist / length));
return pcurrent;
}
else
{
dist -= length;
currentPos = pcurrent->GetNext()->pev->origin;
pcurrent = pcurrent->GetNext();
*origin = currentPos;
}
}
*origin = currentPos;
}
return pcurrent;
}
// Assumes this is ALWAYS enabled
CBaseEntity *CPathTrack :: Nearest( Vector origin )
{
int deadCount;
float minDist, dist;
Vector delta;
CBaseEntity *ppath, *pnearest;
delta = origin - pev->origin;
delta.z = 0;
minDist = delta.Length();
pnearest = this;
ppath = GetNext();
// Hey, I could use the old 2 racing pointers solution to this, but I'm lazy :)
deadCount = 0;
while ( ppath && ppath != this )
{
deadCount++;
if ( deadCount > 9999 )
{
ALERT( at_error, "Bad sequence of path_tracks from %s", STRING(pev->targetname) );
return NULL;
}
delta = origin - ppath->pev->origin;
delta.z = 0;
dist = delta.Length();
if ( dist < minDist )
{
minDist = dist;
pnearest = ppath;
}
ppath = ppath->GetNext();
}
return pnearest;
}
CPathTrack *CPathTrack::Instance( edict_t *pent )
{
if ( FClassnameIs( pent, "path_track" ) )
return (CPathTrack *)GET_PRIVATE(pent);
return NULL;
}
// DEBUGGING CODE
#if PATH_SPARKLE_DEBUG
void CPathTrack :: Sparkle( void )
{
SetNextThink( 0.2 );
if ( FBitSet( pev->spawnflags, SF_PATH_DISABLED ) )
UTIL_ParticleEffect(pev->origin, Vector(0,0,100), 210, 10);
else
UTIL_ParticleEffect(pev->origin, Vector(0,0,100), 84, 10);
}
#endif

View File

@ -605,7 +605,7 @@ void CNukeExplode :: Spawn( void )
// create first explode sprite
SFX_Explode( m_usExplodeSprite, pev->origin, 70, TE_EXPLFLAG_NOPARTICLES|TE_EXPLFLAG_NOSOUND|TE_EXPLFLAG_NODLIGHTS );
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/warhead/whexplode.wav", 1, ATTN_NONE );
EMIT_SOUND( edict(), CHAN_VOICE, "weapons/warhead/whexplode.wav", 1, ATTN_NONE );
pev->movetype = MOVETYPE_NONE;
pev->solid = SOLID_NOT;

1074
server/ents/basetrain.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -144,11 +144,16 @@ void CBaseTrigger::KeyValue( KeyValueData *pkvd )
pev->armorvalue = atof(pkvd->szValue) / 100.0;
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "roomtype")) //for soundfx
else if (FStrEq( pkvd->szKeyName, "roomtype" )) //for soundfx
{
pev->button = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq( pkvd->szKeyName, "wait" )) // for trigger_push
{
m_flDelay = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
@ -214,7 +219,8 @@ class CTriggerMulti : public CBaseTrigger
{
void FireOnEntry( CBaseEntity *pOther )
{
if(!IsLockedByMaster(pOther)) FireTargets();
if(!IsLockedByMaster(pOther))
UTIL_FireTargets(pev->target, pOther, this, USE_TOGGLE );
}
void FireOnLeave( CBaseEntity *pOther )
{
@ -233,7 +239,7 @@ class CTriggerOnce : public CBaseTrigger
{
if ( !IsLockedByMaster(pOther))
{
FireTargets();
UTIL_FireTargets( pev->target, pOther, this, USE_TOGGLE );
SetThink( Remove );
SetNextThink( 0 );
}
@ -375,7 +381,7 @@ class CTriggerPush : public CBaseTrigger
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "world/jumppad.wav", VOL_NORM, ATTN_IDLE );
m_flWait = gpGlobals->time + (2.0f * gpGlobals->frametime);
m_flWait = gpGlobals->time + ( 2.0f * gpGlobals->frametime );
if( FBitSet( pev->spawnflags, SF_PUSH_ONCE ))
UTIL_Remove( this );
@ -433,507 +439,7 @@ class CTriggerSound : public CBaseTrigger
}
};
LINK_ENTITY_TO_CLASS( trigger_sound, CTriggerSound );
//=======================================================================
// trigger_relay
//=======================================================================
class CTriggerRelay : public CBaseLogic
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void Spawn( void ){ m_iState = STATE_OFF; }
void Think ( void );
};
LINK_ENTITY_TO_CLASS( trigger_relay, CTriggerRelay );
void CTriggerRelay::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "triggerstate"))
{
int type = atoi( pkvd->szValue );
switch( type )
{
case 0: pev->impulse = USE_OFF; break;
case 2: pev->impulse = USE_TOGGLE; break;
case 3: pev->impulse = USE_SET; break;
default: pev->impulse = USE_ON; break;
}
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "locktarget"))
{
pev->message = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
void CTriggerRelay::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
m_hActivator = pActivator; //save activator
if(pev->impulse) pev->button = pev->impulse;
else pev->button = (int)useType; //save use type
pev->frags = value; //save our value
if (useType == USE_SHOWINFO)
{
DEBUGHEAD;
Msg( "target is %s, locktarget %s\n", STRING(pev->target), STRING(pev->message));
Msg( "new value %g\n", pev->frags );
}
else //activate target
{
m_iState = STATE_ON;
SetNextThink(m_flDelay);
}
}
void CTriggerRelay::Think ( void )
{
if (IsLockedByMaster()) UTIL_FireTargets( pev->message, m_hActivator, this, (USE_TYPE)pev->button, pev->frags );
else
{
UTIL_FireTargets( pev->target, m_hActivator, this, (USE_TYPE)pev->button, pev->frags );
UTIL_FireTargets( m_iszKillTarget, m_hActivator, this, USE_REMOVE );
}
//suhtdown
m_iState = STATE_OFF;
DontThink();//just in case
if ( pev->spawnflags & 1 ) UTIL_Remove( this );
}
//=======================================================================
// trigger_auto
//=======================================================================
class CAutoTrigger : public CBaseLogic
{
public:
void KeyValue( KeyValueData *pkvd );
void PostActivate( void );
};
LINK_ENTITY_TO_CLASS( trigger_auto, CAutoTrigger );
void CAutoTrigger::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "triggerstate"))
{
int type = atoi( pkvd->szValue );
switch( type )
{
case 0: pev->impulse = USE_OFF; break;
case 2: pev->impulse = USE_TOGGLE; break;
case 3: pev->impulse = USE_SET; break;
default: pev->impulse = USE_ON; break;
}
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
void CAutoTrigger::PostActivate( void )
{
if ( !m_globalstate || gGlobalState.EntityGetState( m_globalstate ) == GLOBAL_ON )
{
FireTargets( (USE_TYPE)pev->impulse );
if ( pev->spawnflags & 1 ) UTIL_Remove( this );
}
}
//=======================================================================
// trigger_changetarget
//=======================================================================
class CChangeTarget : public CBaseLogic
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
};
LINK_ENTITY_TO_CLASS( trigger_changetarget, CChangeTarget );
void CChangeTarget::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "newtarget") || FStrEq(pkvd->szKeyName, "m_iszNewTarget"))
{
pev->message = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
void CChangeTarget::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBaseEntity *pTarget = UTIL_FindEntityByTargetname( NULL, STRING( pev->target ), pActivator );
if (useType == USE_SHOWINFO)
{
DEBUGHEAD;
Msg( "Current target %s, new target %s\n", STRING(pev->target), STRING(pev->message) );
Msg( "target entity is: %s, current target: %s\n", STRING(pTarget->pev->classname), STRING(pTarget->pev->target));
}
else
{
if (pTarget)
{
if (FStrEq(STRING(pev->message), "*this"))
{
if (pActivator) pTarget->pev->target = pActivator->pev->targetname;
else ALERT(at_error, "util_settarget \"%s\" requires a self pointer!\n", STRING(pev->targetname));
}
else
{
if(pTarget->IsFuncScreen()) pTarget->ChangeCamera( pev->message );
else pTarget->pev->target = pev->message;
}
CBaseMonster *pMonster = pTarget->MyMonsterPointer( );
if (pMonster) pMonster->m_pGoalEnt = NULL;
}
}
}
//=======================================================================
// multi_manager
//=======================================================================
#define FL_CLONE 0x80000000
class CMultiManager : public CBaseLogic
{
public:
void KeyValue( KeyValueData *pkvd );
void Spawn ( void );
void Think ( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
BOOL HasTarget( string_t targetname );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_cTargets; // the total number of targets in this manager's fire list.
int m_index; // Current target
float m_startTime; // Time we started firing
int m_iTargetName [ MAX_MULTI_TARGETS ];// list if indexes into global string array
float m_flTargetDelay [ MAX_MULTI_TARGETS ];// delay (in seconds)
private:
inline BOOL IsClone( void ) { return (pev->spawnflags & FL_CLONE) ? TRUE : FALSE; }
inline BOOL ShouldClone( void )
{
if ( IsClone() )return FALSE;
//work in progress and calling again ?
return (m_iState == STATE_ON) ? TRUE : FALSE;
}
CMultiManager *Clone( void );
};
LINK_ENTITY_TO_CLASS( multi_manager, CMultiManager );
// Global Savedata for multi_manager
TYPEDESCRIPTION CMultiManager::m_SaveData[] =
{ DEFINE_FIELD( CMultiManager, m_cTargets, FIELD_INTEGER ),
DEFINE_FIELD( CMultiManager, m_index, FIELD_INTEGER ),
DEFINE_FIELD( CMultiManager, m_startTime, FIELD_TIME ),
DEFINE_ARRAY( CMultiManager, m_iTargetName, FIELD_STRING, MAX_MULTI_TARGETS ),
DEFINE_ARRAY( CMultiManager, m_flTargetDelay, FIELD_FLOAT, MAX_MULTI_TARGETS ),
};IMPLEMENT_SAVERESTORE(CMultiManager, CBaseLogic);
void CMultiManager :: KeyValue( KeyValueData *pkvd )
{
if ( m_cTargets < MAX_MULTI_TARGETS )
{
char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp );
m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp );
m_flTargetDelay [ m_cTargets ] = RandomRange((char *)STRING(ALLOC_STRING(pkvd->szValue))).Random();
m_cTargets++;
pkvd->fHandled = TRUE;
}
}
void CMultiManager :: Spawn( void )
{
// Sort targets
// Quick and dirty bubble sort
int swapped = 1;
while ( swapped )
{
swapped = 0;
for ( int i = 1; i < m_cTargets; i++ )
{
if ( m_flTargetDelay[i] < m_flTargetDelay[i-1] )
{
// Swap out of order elements
int name = m_iTargetName[i];
float delay = m_flTargetDelay[i];
m_iTargetName[i] = m_iTargetName[i-1];
m_flTargetDelay[i] = m_flTargetDelay[i-1];
m_iTargetName[i-1] = name;
m_flTargetDelay[i-1] = delay;
swapped = 1;
}
}
}
m_iState = STATE_OFF;
m_index = 0;
}
BOOL CMultiManager::HasTarget( string_t targetname )
{
for ( int i = 0; i < m_cTargets; i++ )
if ( FStrEq(STRING(targetname), STRING(m_iTargetName[i])) ) return TRUE;
return FALSE;
}
void CMultiManager :: Think ( void )
{
float time;
time = gpGlobals->time - m_startTime;
while ( m_index < m_cTargets && m_flTargetDelay[ m_index ] <= time )
{
UTIL_FireTargets( m_iTargetName[ m_index ], m_hActivator, this, USE_TOGGLE, pev->frags );
m_index++;
}
if ( m_index >= m_cTargets )// have we fired all targets?
{
if ( IsClone() )
{
UTIL_Remove( this );
return;
}
//stop manager
m_iState = STATE_OFF;
DontThink();
return;
}
m_iState = STATE_ON; //continue firing targets
pev->nextthink = m_startTime + m_flTargetDelay[ m_index ];
}
CMultiManager *CMultiManager::Clone( void )
{
CMultiManager *pMulti = GetClassPtr( (CMultiManager *)NULL );
edict_t *pEdict = pMulti->pev->pContainingEntity;
memcpy( pMulti->pev, pev, sizeof(*pev) );
pMulti->pev->pContainingEntity = pEdict;
pMulti->pev->spawnflags |= FL_CLONE;
pMulti->m_cTargets = m_cTargets;
pMulti->m_flWait = m_flWait;
pMulti->m_iState = m_iState;
memcpy( pMulti->m_iTargetName, m_iTargetName, sizeof( m_iTargetName ) );
memcpy( pMulti->m_flTargetDelay, m_flTargetDelay, sizeof( m_flTargetDelay ) );
return pMulti;
}
void CMultiManager :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
m_hActivator = pActivator;
if(IsLockedByMaster( useType )) return;
pev->frags = value;//save our value
if (useType == USE_TOGGLE || useType == USE_ON)
{
if ( ShouldClone() )//create clone if needed
{
CMultiManager *pClone = Clone();
pClone->Use( pActivator, pCaller, useType, value );
return;
}
if(m_iState == STATE_OFF)
{
m_startTime = m_flWait + gpGlobals->time;
m_iState = STATE_TURN_ON;
m_index = 0;
SetNextThink( m_flWait );
}
}
else if (useType == USE_OFF)
{
m_iState = STATE_OFF;
DontThink();
}
else if (useType == USE_SHOWINFO)//only show info if locked by master
{
DEBUGHEAD;
Msg("State: %s, number of targets %d\n", GetStringForState( GetState()), m_cTargets);
if(m_iState == STATE_ON) Msg("Current target %s, delay time %f\n", STRING(m_iTargetName[ m_index ]), m_flTargetDelay[ m_index ]);
else Msg("No targets for firing.\n");
}
}
//=======================================================================
// multi_master
//=======================================================================
#define LOGIC_AND 0 // fire if all objects active
#define LOGIC_OR 1 // fire if any object active
#define LOGIC_NAND 2 // fire if not all objects active
#define LOGIC_NOR 3 // fire if all objects disable
#define LOGIC_XOR 4 // fire if only one (any) object active
#define LOGIC_XNOR 5 // fire if active any number objects, but < then all
#define ST_ON 0
#define ST_OFF 1
#define ST_TURNON 2
#define ST_TURNOFF 3
#define ST_IN_USE 4
class CMultiMaster : public CBaseLogic
{
public:
void Spawn ( void ){ SetNextThink( 0.1 ); }
void Think ( void );
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual STATE GetState( void ) { return m_iState; };
virtual STATE GetState( CBaseEntity *pActivator ) { return EvalLogic(pActivator)?STATE_ON:STATE_OFF; };
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int m_cTargets;// the total number of targets in this manager's fire list.
int m_iTargetName[ MAX_MULTI_TARGETS ];// list of indexes into global string array
int m_iTargetState[ MAX_MULTI_TARGETS ];//list of wishstate targets
BOOL EvalLogic ( CBaseEntity *pEntity );
};
LINK_ENTITY_TO_CLASS( multi_watcher, CMultiMaster );
TYPEDESCRIPTION CMultiMaster::m_SaveData[] =
{
DEFINE_FIELD( CMultiMaster, m_cTargets, FIELD_INTEGER ),
DEFINE_ARRAY( CMultiMaster, m_iTargetName, FIELD_STRING, MAX_MULTI_TARGETS ),
DEFINE_ARRAY( CMultiMaster, m_iTargetState, FIELD_INTEGER, MAX_MULTI_TARGETS ),
};IMPLEMENT_SAVERESTORE(CMultiMaster,CBaseLogic);
void CMultiMaster :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "mode"))
{
pev->button = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
if (FStrEq(pkvd->szKeyName, "offtarget"))
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else // add this field to the target list
{
// this assumes that additional fields are targetnames and their values are delay values.
if ( m_cTargets < MAX_MULTI_TARGETS )
{
char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp );
m_iTargetName [ m_cTargets ] = ALLOC_STRING( tmp );
m_iTargetState [ m_cTargets ] = atoi (pkvd->szValue);
m_cTargets++;
pkvd->fHandled = TRUE;
}
}
}
void CMultiMaster :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (useType == USE_SHOWINFO)
{
DEBUGHEAD;
Msg("State: %s, Number of targets %d\n", GetStringForState( GetState()), m_cTargets);
Msg("Limit is %d entities\n", MAX_MULTI_TARGETS);
}
}
void CMultiMaster :: Think ( void )
{
if(EvalLogic(NULL))
{
if(m_iState == STATE_OFF)
{
m_iState = STATE_ON;
UTIL_FireTargets( pev->target, this, this, USE_ON );
}
}
else
{
if(m_iState == STATE_ON)
{
m_iState = STATE_OFF;
UTIL_FireTargets( pev->netname, this, this, USE_OFF );
}
}
SetNextThink( 0.05 );
}
BOOL CMultiMaster :: EvalLogic ( CBaseEntity *pActivator )
{
int i;
BOOL b;
BOOL xorgot = FALSE;
CBaseEntity* pEntity;
for (i = 0; i < m_cTargets; i++)
{
pEntity = UTIL_FindEntityByTargetname(NULL,STRING(m_iTargetName[i]), pActivator);
if (pEntity != NULL);
else continue;
b = FALSE;
switch (pEntity->GetState())
{
case STATE_ON: if(m_iTargetState[i] == ST_ON) b = TRUE; break;
case STATE_OFF: if(m_iTargetState[i] == ST_OFF) b = TRUE; break;
case STATE_TURN_ON: if(m_iTargetState[i] == ST_TURNON) b = TRUE; break;
case STATE_TURN_OFF: if(m_iTargetState[i] == ST_TURNOFF) b = TRUE; break;
case STATE_IN_USE: if(m_iTargetState[i] == ST_IN_USE) b = TRUE; break;
}
// handle the states for this logic mode
if (b)
{
switch (pev->button)
{
case LOGIC_OR: return TRUE;
case LOGIC_NOR: return FALSE;
case LOGIC_XOR:
if(xorgot) return FALSE;
xorgot = TRUE;
break;
case LOGIC_XNOR:
if(xorgot) return TRUE;
xorgot = TRUE;
break;
}
}
else // b is false
{
switch (pev->button)
{
case LOGIC_AND: return FALSE;
case LOGIC_NAND: return TRUE;
}
}
}
// handle the default cases for each logic mode
switch (pev->button)
{
case LOGIC_AND:
case LOGIC_NOR: return TRUE;
case LOGIC_XOR: return xorgot;
case LOGIC_XNOR: return !xorgot;
default: return FALSE;
}
}
LINK_ENTITY_TO_CLASS( func_soundfx, CTriggerSound ); // Xash 0.4 compatibility
//=======================================================================
// trigger_changelevel - classic HALF_LIFE changelevel
@ -1131,10 +637,14 @@ void CTriggerHurt :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYP
{
pev->dmg = value;//set dmg level
}
else if (useType == USE_RESET)
{
pev->dmg = 0;//reset dmg level
}
else if (useType == USE_SHOWINFO)
{
DEBUGHEAD;
Msg( "State: %s, Dmg value %g\n", GetStringForState( GetState()), pev->dmg);
ALERT( at_console, "State: %s, Dmg value %g\n", GetStringForState( GetState()), pev->dmg );
PrintStringForDamage( pev->button );
}
@ -1222,19 +732,18 @@ void CTriggerHurt :: Think( void )
//=======================================================================
// trigger_transition - area that moving all entities inside across level
//=======================================================================
class CVolumeTransition : public CPointEntity // Don't change this!
class CTriggerTransition : public CPointEntity // Don't change this!
{
public:
void Spawn( void )
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
UTIL_SetModel(ENT(pev), pev->model);
pev->model = NULL;
pev->modelindex = 0;
UTIL_SetModel( ENT( pev ), pev->model );
pev->model = pev->modelindex = 0;
}
};
LINK_ENTITY_TO_CLASS( trigger_transition, CVolumeTransition );
LINK_ENTITY_TO_CLASS( trigger_transition, CTriggerTransition );
//=======================================================================
// trigger_camera - generic camera
@ -1258,23 +767,23 @@ class CTriggerCamera : public CBaseLogic
LINK_ENTITY_TO_CLASS( trigger_camera, CTriggerCamera );
#define SF_CAMERA_PLAYER_POSITION 1 //start from player eyes
#define SF_CAMERA_PLAYER_TARGET 2 //player it's camera target
#define SF_CAMERA_PLAYER_TAKECONTROL 4 //freeze player
#define SF_CAMERA_PLAYER_POSITION 1 // start from player eyes
#define SF_CAMERA_PLAYER_TARGET 2 // player it's camera target
#define SF_CAMERA_PLAYER_TAKECONTROL 4 // freeze player
void CTriggerCamera :: KeyValue( KeyValueData* pkvd )
{
if (FStrEq(pkvd->szKeyName, "viewentity"))
if (FStrEq( pkvd->szKeyName, "viewentity" ))
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "moveto"))
else if (FStrEq( pkvd->szKeyName, "moveto" ))
{
pev->message = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
else CBaseLogic::KeyValue( pkvd );
}
void CTriggerCamera :: Spawn (void )
@ -1284,29 +793,29 @@ void CTriggerCamera :: Spawn (void )
m_iState = STATE_OFF;
UTIL_SetModel(ENT(pev),"models/common/null.mdl");
UTIL_SetSize(pev, g_vecZero, g_vecZero);
UTIL_SetModel( ENT( pev ), "models/common/null.mdl" );
UTIL_SetSize( pev, g_vecZero, g_vecZero );
SetBits( pev->flags, FL_POINTENTITY );
}
void CTriggerCamera::PostSpawn( void )
{
m_pGoalEnt = UTIL_FindEntityByTargetname (NULL, STRING(pev->message));
if(m_pGoalEnt) UTIL_SetOrigin( this, m_pGoalEnt->pev->origin );
m_pGoalEnt = UTIL_FindEntityByTargetname( NULL, STRING( pev->message ));
if ( m_pGoalEnt ) UTIL_SetOrigin( this, m_pGoalEnt->pev->origin );
}
void CTriggerCamera::OverrideReset( void )
{
//find path_corner on a next level
m_pGoalEnt = UTIL_FindEntityByTargetname (NULL, STRING(pev->message));
if(m_pGoalEnt) UTIL_SetOrigin( this, m_pGoalEnt->pev->origin );
// find path_corner on a next level
m_pGoalEnt = UTIL_FindEntityByTargetname( NULL, STRING( pev->message ));
if( m_pGoalEnt ) UTIL_SetOrigin( this, m_pGoalEnt->pev->origin );
}
void CTriggerCamera::PostActivate( void )
{
if (FStrEq(STRING(pev->target), "player") || (pev->spawnflags & SF_CAMERA_PLAYER_TARGET))
if (FStrEq( STRING( pev->target ), "player" ) || ( pev->spawnflags & SF_CAMERA_PLAYER_TARGET ))
pTarget = UTIL_PlayerByIndex( 1 );
else pTarget = UTIL_FindEntityByTargetname( NULL, STRING(pev->target) );
else pTarget = UTIL_FindEntityByTargetname( NULL, STRING( pev->target ));
}
void CTriggerCamera::Think( void )
@ -1316,50 +825,88 @@ void CTriggerCamera::Think( void )
Move();
pev->dmgtime = gpGlobals->time;
if ( pTarget ) UTIL_WatchTarget( this, pTarget );
if(m_flWait && pev->teleport_time < gpGlobals->time) TurnOff();
if( m_flWait && pev->health < gpGlobals->time )
{
TurnOff();
}
}
void CTriggerCamera :: UpdatePlayerView( void )
{
int flags;
int flags = 0;
if(pev->spawnflags & SF_CAMERA_PLAYER_TAKECONTROL) //freeze player
((CBasePlayer *)((CBaseEntity *)m_hActivator))->EnableControl(GetState() ? FALSE : TRUE );
if(GetState() == STATE_OFF) flags = 0;
else flags |= CAMERA_ON;
CBaseEntity *pCamera = UTIL_FindEntityByTargetname( NULL, STRING(pev->netname) );
if(pCamera && !pCamera->IsBSPModel()) UTIL_SetView( (CBaseEntity *)m_hActivator, pCamera, flags );
else UTIL_SetView( (CBaseEntity *)m_hActivator, this, flags );
if( m_hActivator == NULL || !m_hActivator->edict() || !( m_hActivator->pev->flags & FL_CLIENT ))
{
ALERT( at_error, "Camera: No Client!\n" );
return;
}
if( pev->spawnflags & SF_CAMERA_PLAYER_TAKECONTROL )
{
int state;
if( GetState() == STATE_ON )
state = TRUE;
else state = FALSE;
// freeze player
((CBasePlayer *)((CBaseEntity *)m_hActivator))->EnableControl( state );
}
if( GetState() == STATE_OFF )
flags |= CAMERA_ON;
else flags = 0;
CBaseEntity *pCamera = UTIL_FindEntityByTargetname( NULL, STRING( pev->netname ));
if( pCamera && !pCamera->IsBSPModel( ))
UTIL_SetView( m_hActivator, pCamera, flags );
else UTIL_SetView( m_hActivator, this, flags );
}
void CTriggerCamera :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if(pActivator && pActivator->IsPlayer())//only at player
if( pActivator && pActivator->IsPlayer( ))
{
m_hActivator = pActivator;//save activator
// only at player
m_hActivator = pActivator;
}
else m_hActivator = UTIL_PlayerByIndex( 1 );
if (useType == USE_TOGGLE)
else if( !IsMultiplayer( ))
{
if(m_iState == STATE_OFF) useType = USE_ON;
m_hActivator = UTIL_PlayerByIndex( 1 );
}
else
{
ALERT( at_warning, "%s: %s activator not player. Ignored.\n", STRING( pev->classname ), STRING( pev->targetname ));
return;
}
if ( useType == USE_TOGGLE )
{
if ( m_iState == STATE_OFF )
useType = USE_ON;
else useType = USE_OFF;
}
if (useType == USE_ON ) TurnOn();
else if (useType == USE_OFF) TurnOff();
else if (useType == USE_SHOWINFO)
if ( useType == USE_ON )
{
Msg("======/Xash Debug System/======\n");
Msg("classname: %s\n", STRING(pev->classname));
Msg("State: %s, Look at %s\n", GetStringForState( GetState()), pev->netname ? STRING(pev->netname) : STRING(pev->targetname));
Msg("Speed: %g Camera target: %s\n", pev->speed, pTarget ? STRING(pTarget->pev->targetname) : "None" );
TurnOn();
}
else if ( useType == USE_OFF )
{
TurnOff();
}
else if ( useType == USE_SHOWINFO )
{
ALERT( at_console, "======/Xash Debug System/======\n");
ALERT( at_console, "classname: %s\n", STRING( pev->classname ));
ALERT( at_console, "State: %s, Look at %s\n", GetStringForState( GetState()), pev->netname ? STRING( pev->netname ) : STRING( pev->targetname ));
ALERT( at_console, "Speed: %g Camera target: %s\n", pev->speed, pTarget ? STRING(pTarget->pev->targetname) : "None" );
}
}
void CTriggerCamera::Move( void )
{
// Not moving on a path, return
if (!m_pGoalEnt) return;
if ( !m_pGoalEnt ) return;
// Subtract movement from the previous frame
pev->frags -= pev->speed * gpGlobals->frametime;
@ -1368,17 +915,13 @@ void CTriggerCamera::Move( void )
if ( pev->frags <= 0 )
{
// Fire the passtarget if there is one
UTIL_FireTargets(m_pGoalEnt->pev->message, this, this, USE_TOGGLE );
if ( FBitSet( m_pGoalEnt->pev->spawnflags, SF_CORNER_FIREONCE ) ) m_pGoalEnt->pev->message = iStringNull;
if ( FBitSet( m_pGoalEnt->pev->spawnflags, SF_CORNER_TELEPORT ) )
UTIL_FireTargets(m_pGoalEnt->pev->target, this, this, USE_TOGGLE );
if ( FBitSet( m_pGoalEnt->pev->spawnflags, SF_FIREONCE ) ) m_pGoalEnt->pev->target = iStringNull;
if ( FBitSet( m_pGoalEnt->pev->spawnflags, SF_TELEPORT_TONEXT ) )
{
m_pGoalEnt = m_pGoalEnt->GetNext();
if ( m_pGoalEnt ) UTIL_AssignOrigin( this, m_pGoalEnt->pev->origin);
}
if ( FBitSet( m_pGoalEnt->pev->spawnflags, SF_CORNER_WAITTRIG ) )
{
//strange feature...
}
// Time to go to the next target
m_pGoalEnt = m_pGoalEnt->GetNext();
@ -1387,48 +930,44 @@ void CTriggerCamera::Move( void )
if ( !m_pGoalEnt ) UTIL_SetVelocity( this, g_vecZero );
else
{
pev->message = m_pGoalEnt->pev->targetname; //save last corner
((CPathCorner *)m_pGoalEnt)->GetSpeed( &pev->armorvalue );
pev->target = m_pGoalEnt->pev->targetname; //save last corner
((CInfoPath *)m_pGoalEnt)->GetSpeed( &pev->armorvalue );
Vector delta = m_pGoalEnt->pev->origin - pev->origin;
pev->frags = delta.Length();
pev->movedir = delta.Normalize();
m_flDelay = gpGlobals->time + m_pGoalEnt->GetDelay();
m_flDelay = gpGlobals->time + ((CInfoPath *)m_pGoalEnt)->GetDelay();
}
}
if ( m_flDelay > gpGlobals->time )
pev->speed = UTIL_Approach( 0, pev->speed, 500 * gpGlobals->frametime );
else pev->speed = UTIL_Approach( pev->armorvalue, pev->speed, 500 * gpGlobals->frametime );
else pev->speed = UTIL_Approach( pev->armorvalue, pev->speed, 500 * gpGlobals->frametime );
if(!pTarget)UTIL_WatchTarget( this, m_pGoalEnt );//watch for track
if( !pTarget ) UTIL_WatchTarget( this, m_pGoalEnt ); // watch for track
float fraction = 2 * gpGlobals->frametime;
UTIL_SetVelocity( this, ((pev->movedir * pev->speed) * fraction) + (pev->velocity * (1-fraction)));
UTIL_SetVelocity( this, ((pev->movedir * pev->speed) * fraction) + (pev->velocity * ( 1.0f - fraction )));
}
void CTriggerCamera::TurnOff( void )
{
m_iState = STATE_OFF;
if(m_pGoalEnt) m_pGoalEnt = m_pGoalEnt->GetPrev();
if( m_pGoalEnt ) m_pGoalEnt = m_pGoalEnt->GetPrev();
UTIL_SetVelocity( this, g_vecZero );
UTIL_SetAvelocity( this, g_vecZero );
UpdatePlayerView();
FireTargets();
m_iState = STATE_OFF;
DontThink();
}
void CTriggerCamera::TurnOn( void )
{
pev->dmgtime = gpGlobals->time;
m_iState = STATE_ON;
pev->armorvalue = pev->speed;
m_flDelay = gpGlobals->time;
pev->frags = 0;
// copy over player information
if (pev->spawnflags & SF_CAMERA_PLAYER_POSITION )
if ( pev->spawnflags & SF_CAMERA_PLAYER_POSITION )
{
UTIL_SetOrigin( this, m_hActivator->pev->origin + m_hActivator->pev->view_ofs );
pev->angles.x = -m_hActivator->pev->angles.x;
@ -1438,10 +977,11 @@ void CTriggerCamera::TurnOn( void )
ClearBits( pev->spawnflags, SF_CAMERA_PLAYER_POSITION );
}
//time-based camera
if(m_flWait)pev->teleport_time = gpGlobals->time + m_flWait;
// time-based camera
if( m_flWait ) pev->health = gpGlobals->time + m_flWait;
Move();
UpdatePlayerView();
m_iState = STATE_ON;
SetNextThink( 0 );
}

View File

@ -1,405 +0,0 @@
//=======================================================================
// Copyright (C) Shambler Team 2004
// util_.cpp - utility entities: util_fade,
// util_shake, util_changehud etc
//=======================================================================
#include "extdll.h"
#include "utils.h"
#include "cbase.h"
#include "saverestore.h"
#include "player.h"
#include "defaults.h"
#include "shake.h"
//=====================================================
// util_changehud: change player hud
//=====================================================
class CUtilChangeHUD : public CBaseLogic
{
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData* );
void SetHUD( int hud_num );
void ResetHUD( void );
char* GetStringForMode( void );
};
void CUtilChangeHUD :: KeyValue( KeyValueData* pkvd )
{
if (FStrEq(pkvd->szKeyName, "hud"))
{
pev->skin = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else CBaseEntity::KeyValue( pkvd );
}
void CUtilChangeHUD :: SetHUD( int hud_num )
{
m_iState = STATE_ON;
((CBasePlayer *)((CBaseEntity *)m_hActivator))->m_iWarHUD = pev->skin = hud_num;
}
void CUtilChangeHUD :: ResetHUD( void )
{
m_iState = STATE_OFF;
((CBasePlayer *)((CBaseEntity *)m_hActivator))->m_iWarHUD = 0;
((CBasePlayer *)((CBaseEntity *)m_hActivator))->fadeNeedsUpdate = 1;
}
void CUtilChangeHUD :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if(pActivator && pActivator->IsPlayer())//only at player
{
m_hActivator = pActivator;//save activator
}
else m_hActivator = UTIL_PlayerByIndex( 1 );
if (useType == USE_TOGGLE)
{
if(m_iState == STATE_OFF) useType = USE_ON;
else useType = USE_OFF;
}
if (useType == USE_ON ) SetHUD( pev->skin );
else if (useType == USE_OFF) ResetHUD();
else if (useType == USE_SET)
{
if(value) SetHUD( value );
else ResetHUD();
}
else if (useType == USE_RESET) ResetHUD();
else if (useType == USE_SHOWINFO)
{
ALERT(at_console, "======/Xash Debug System/======\n");
ALERT(at_console, "classname: %s\n", STRING(pev->classname));
ALERT(at_console, "State: %s, HUD Mode: %s\n", GetStringForState( GetState()), GetStringForMode());
SHIFT;
}
}
char* CUtilChangeHUD :: GetStringForMode( void )
{
switch(pev->skin)
{
case 0: return "Disable Custom HUD";
case 1: return "Draw Redeemer HUD";
case 2: return "Draw Redeemer Underwater HUD";
case 3: return "Draw Redeemer Noise Screen";
case 4: return "Draw Security Camera Screen";
default: return "Draw None";
}
}
LINK_ENTITY_TO_CLASS( util_changehud, CUtilChangeHUD );
//=====================================================
// util_command: activate a console command
//=====================================================
class CUtilCommand : public CBaseEntity
{
public:
void PostActvaite( void )
{
if(pev->spawnflags & SF_START_ON) Use( this, this, USE_ON, 0 );
}
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
char szCommand[256];
if (useType == USE_SHOWINFO)
{
ALERT(at_console, "======/Xash Debug System/======\n");
ALERT(at_console, "classname: %s\n", STRING(pev->classname));
ALERT(at_console, "Command: %s\n", STRING(pev->netname));
SHIFT;
}
else if (pev->netname)
{
const char *pString = (char *)STRING( pev->netname );
int command, namelen = strlen(pString) - 1;
if( namelen > 2) command = pev->netname;//command name
else command = atoi( pString );
switch( command )
{
case 0: strcpy( szCommand, "pause\n" ); break; //pause level
case 1: strcpy( szCommand, "reload\n" ); break; //revert to saved game
case 2: strcpy( szCommand, "game_over\n" ); break;//turn to menu
case 3: strcpy( szCommand, "autosave\n" ); break; //autosave game
case 4: strcpy( szCommand, "restart\n" ); break; //restart level
case 5: strcpy( szCommand, "save quick\n" ); break; //emaulate F6
case 6: strcpy( szCommand, "load quick\n" ); break; //emulate F7
case 7: strcpy( szCommand, "exit\n" ); break; //return to windows
case 8: strcpy( szCommand, "gametitle\n" ); break; //show game title
case 9: strcpy( szCommand, "intermission\n" ); break; //show intermission
default: sprintf( szCommand, "%s\n", STRING(pev->netname) ); break; //custom command
}
SERVER_COMMAND( szCommand );
if ( pev->spawnflags & SF_FIREONCE ) UTIL_Remove( this );
}
}
};
LINK_ENTITY_TO_CLASS( util_command, CUtilCommand );
//=========================================================
// display message text
//=========================================================
class CGameText : public CBaseLogic
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
private:
hudtextparms_t m_textParms;
};
LINK_ENTITY_TO_CLASS( util_msgtext, CGameText );
TYPEDESCRIPTION CGameText::m_SaveData[] =
{ DEFINE_ARRAY( CGameText, m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
};IMPLEMENT_SAVERESTORE( CGameText, CBaseLogic );
void CGameText::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "channel"))
{
m_textParms.channel = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "x"))
{
m_textParms.x = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "y"))
{
m_textParms.y = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "effect"))
{
m_textParms.effect = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r1 = color[0];
m_textParms.g1 = color[1];
m_textParms.b1 = color[2];
m_textParms.a1 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color2"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r2 = color[0];
m_textParms.g2 = color[1];
m_textParms.b2 = color[2];
m_textParms.a2 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadein"))
{
m_textParms.fadeinTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadeout"))
{
m_textParms.fadeoutTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "holdtime"))
{
m_textParms.holdTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fxtime"))
{
m_textParms.fxTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else CBaseLogic::KeyValue( pkvd );
}
void CGameText::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBaseEntity *pPlayer = NULL;
if ( IsMultiplayer())UTIL_HudMessageAll( m_textParms, STRING(pev->message) );
else
{
if ( pActivator && pActivator->IsPlayer() ) pPlayer = pActivator;
else pPlayer = UTIL_PlayerByIndex( 1 );
}
if ( pPlayer ) UTIL_HudMessage( pPlayer, m_textParms, STRING(pev->message));
if ( pev->spawnflags & SF_FIREONCE ) UTIL_Remove( this );
}
//=========================================================
// remove all items
//=========================================================
#define SF_REMOVE_SUIT 1
class CUtilStripWeapons : public CPointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBasePlayer *pPlayer = NULL;
if ( pActivator && pActivator->IsPlayer() ) pPlayer = (CBasePlayer *)pActivator;
else pPlayer = (CBasePlayer *)UTIL_PlayerByIndex( 1 );
if ( pPlayer ) pPlayer->RemoveAllItems( pev->spawnflags & SF_REMOVE_SUIT );
if ( pev->spawnflags & SF_FIREONCE ) UTIL_Remove( this );
}
};
LINK_ENTITY_TO_CLASS( util_weaponstrip, CUtilStripWeapons );
//=========================================================
// set global fog on a map
//=========================================================
class CUtilSetFog : public CBaseLogic
{
public:
void PostActivate( void );
void KeyValue( KeyValueData *pkvd );
void TurnOn( void );
void TurnOff( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
};
LINK_ENTITY_TO_CLASS( util_setfog, CUtilSetFog );
void CUtilSetFog :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "startdist"))
{
pev->dmg_take = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "enddist"))
{
pev->dmg_save = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadetime"))
{
m_flDelay = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else CBaseEntity::KeyValue( pkvd );
}
void CUtilSetFog :: PostActivate ( void )
{
pev->effects |= EF_NODRAW;
if (pev->spawnflags & SF_START_ON)
{
TurnOn();
ClearBits(pev->spawnflags, SF_START_ON);
}
}
void CUtilSetFog :: TurnOn ( void )
{
m_iState = STATE_ON;
UTIL_SetFogAll(pev->rendercolor, m_flDelay, pev->dmg_take, pev->dmg_save );
}
void CUtilSetFog :: TurnOff ( void )
{
m_iState = STATE_OFF;
UTIL_SetFogAll(pev->rendercolor, -m_flDelay, pev->dmg_take, pev->dmg_save );
}
void CUtilSetFog :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (useType == USE_TOGGLE)
{
if(m_iState == STATE_ON) useType = USE_OFF;
else useType = USE_ON;
}
if (useType == USE_ON) TurnOn();
else if ( useType == USE_OFF ) TurnOff();
}
//=========================================================
// UTIL_RainModify (set new rain or snow)
//=========================================================
void CUtilRainModify::Spawn()
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
pev->effects |= EF_NODRAW;
if (IsMultiplayer() || FStringNull( pev->targetname))
SetBits( pev->spawnflags, SF_START_ON );
}
TYPEDESCRIPTION CUtilRainModify::m_SaveData[] =
{
DEFINE_FIELD( CUtilRainModify, randXY, FIELD_RANGE ),
DEFINE_FIELD( CUtilRainModify, windXY, FIELD_RANGE ),
};
IMPLEMENT_SAVERESTORE( CUtilRainModify, CPointEntity );
void CUtilRainModify::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "drips"))
{
pev->button = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadetime"))
{
pev->dmg = atof(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "rand"))
{
randXY = RandomRange(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "wind"))
{
windXY = RandomRange(pkvd->szValue);
pkvd->fHandled = TRUE;
}
}
void CUtilRainModify::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if(useType == USE_SHOWINFO)
{
DEBUGHEAD;
Msg("Wind X: %g Y: %g. Rand X: %g Y: %g\n", windXY[1], windXY[0], randXY[1], randXY[0] );
Msg("Fade time %g. Drips per second %d\n", pev->dmg, pev->button );
}
else if(!pev->spawnflags & SF_START_ON)
{
CBasePlayer *pPlayer = (CBasePlayer *)UTIL_PlayerByIndex(1);
if (pev->dmg)
{
pPlayer->Rain_ideal_dripsPerSecond = pev->button;
pPlayer->Rain_ideal_randX = randXY[1];
pPlayer->Rain_ideal_randY = randXY[0];
pPlayer->Rain_ideal_windX = windXY[1];
pPlayer->Rain_ideal_windY = windXY[0];
pPlayer->Rain_endFade = gpGlobals->time + pev->dmg;
pPlayer->Rain_nextFadeUpdate = gpGlobals->time + 1;
}
else
{
pPlayer->Rain_dripsPerSecond = pev->button;
pPlayer->Rain_randX = randXY[1];
pPlayer->Rain_randY = randXY[0];
pPlayer->Rain_windX = windXY[1];
pPlayer->Rain_windY = windXY[0];
pPlayer->rainNeedsUpdate = 1;
}
}
}
LINK_ENTITY_TO_CLASS( util_rainmodify, CUtilRainModify );

View File

@ -19,8 +19,7 @@ void CWorld :: KeyValue( KeyValueData *pkvd )
{
if( FStrEq( pkvd->szKeyName, "skyname" ))
{
// Sent over net now.
SET_SKYBOX( pkvd->szValue );
pev->target = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "chaptertitle") )
@ -44,16 +43,28 @@ void CWorld :: Spawn( void )
void CWorld :: PostActivate( void )
{
//run post messages
// run post messages
if ( pev->netname )
{
UTIL_ShowMessageAll( STRING(pev->netname) );
pev->netname = iStringNull;
}
if ( pev->spawnflags & SF_START_ON )
{
SERVER_COMMAND( "gametitle\n" );
ClearBits( pev->spawnflags, SF_START_ON );
}
if ( pev->target )
{
// Sent over net now.
SET_SKYBOX( STRING( pev->target ));
}
else
{
// tell engine there is no skybox set
SET_SKYBOX( "<skybox>" );
}
}
LINK_ENTITY_TO_CLASS( worldspawn, CWorld );

961
server/game/maprules.cpp Normal file
View File

@ -0,0 +1,961 @@
/***
*
* 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.
*
****/
// -------------------------------------------
//
// maprules.cpp
//
// This module contains entities for implementing/changing game
// rules dynamically within each map (.BSP)
//
// -------------------------------------------
#include "extdll.h"
#include "utils.h"
#include "gamerules.h"
#include "cbase.h"
#include "player.h"
class CRuleEntity : public CBaseEntity
{
public:
void Spawn( void );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void SetMaster( int iszMaster ) { m_iszMaster = iszMaster; }
protected:
BOOL CanFireForActivator( CBaseEntity *pActivator );
private:
string_t m_iszMaster;
};
TYPEDESCRIPTION CRuleEntity::m_SaveData[] =
{
DEFINE_FIELD( CRuleEntity, m_iszMaster, FIELD_STRING),
};
IMPLEMENT_SAVERESTORE( CRuleEntity, CBaseEntity );
void CRuleEntity::Spawn( void )
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NONE;
pev->effects = EF_NODRAW;
}
void CRuleEntity::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "master"))
{
SetMaster( ALLOC_STRING(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else
CBaseEntity::KeyValue( pkvd );
}
BOOL CRuleEntity::CanFireForActivator( CBaseEntity *pActivator )
{
if (!pActivator)
{
return TRUE;
}
else if ( m_iszMaster )
{
if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) )
return TRUE;
else
return FALSE;
}
return TRUE;
}
//
// CRulePointEntity -- base class for all rule "point" entities (not brushes)
//
class CRulePointEntity : public CRuleEntity
{
public:
void Spawn( void );
};
void CRulePointEntity::Spawn( void )
{
CRuleEntity::Spawn();
pev->frame = 0;
pev->model = 0;
}
//
// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes)
// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing
//
class CRuleBrushEntity : public CRuleEntity
{
public:
void Spawn( void );
private:
};
void CRuleBrushEntity::Spawn( void )
{
SET_MODEL( edict(), STRING(pev->model) );
CRuleEntity::Spawn();
}
// CGameScore / game_score -- award points to player / team
// Points +/- total
// Flag: Allow negative scores SF_SCORE_NEGATIVE
// Flag: Award points to team in teamplay SF_SCORE_TEAM
#define SF_SCORE_NEGATIVE 0x0001
#define SF_SCORE_TEAM 0x0002
class CGameScore : public CRulePointEntity
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData *pkvd );
inline int Points( void ) { return pev->frags; }
inline BOOL AllowNegativeScore( void ) { return pev->spawnflags & SF_SCORE_NEGATIVE; }
inline BOOL AwardToTeam( void ) { return pev->spawnflags & SF_SCORE_TEAM; }
inline void SetPoints( int points ) { pev->frags = points; }
private:
};
LINK_ENTITY_TO_CLASS( game_score, CGameScore );
void CGameScore::Spawn( void )
{
CRulePointEntity::Spawn();
}
void CGameScore::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "points"))
{
SetPoints( atoi(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
// Only players can use this
if ( pActivator->IsPlayer() )
{
if ( AwardToTeam() )
{
pActivator->AddPointsToTeam( Points(), AllowNegativeScore() );
}
else
{
pActivator->AddPoints( Points(), AllowNegativeScore() );
}
}
}
// CGameEnd / game_end -- Ends the game in MP
class CGameEnd : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
private:
};
LINK_ENTITY_TO_CLASS( game_end, CGameEnd );
void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
g_pGameRules->EndMultiplayerGame();
}
//
// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message)
// Flag: All players SF_ENVTEXT_ALLPLAYERS
//
#define SF_ENVTEXT_ALLPLAYERS 0x0001
#define SF_ENVTEXT_ONLY_ONCE 0x0002
class CGameText : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
inline BOOL MessageToAll( void ) { return (pev->spawnflags & SF_ENVTEXT_ALLPLAYERS); }
inline void MessageSet( const char *pMessage ) { pev->message = ALLOC_STRING( pMessage ); }
inline const char *MessageGet( void ) { return STRING(pev->message); }
void EXPORT TriggerThink( void );
private:
hudtextparms_t m_textParms;
CBaseEntity *m_pActivator;
};
LINK_ENTITY_TO_CLASS( game_text, CGameText );
// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so
// it can't impact saved Half-Life games.
TYPEDESCRIPTION CGameText::m_SaveData[] =
{
DEFINE_ARRAY( CGameText, m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ),
DEFINE_FIELD( CGameText, m_pActivator, FIELD_CLASSPTR ),
};
IMPLEMENT_SAVERESTORE( CGameText, CRulePointEntity );
void CGameText::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "channel"))
{
m_textParms.channel = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "x"))
{
m_textParms.x = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "y"))
{
m_textParms.y = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "effect"))
{
m_textParms.effect = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r1 = color[0];
m_textParms.g1 = color[1];
m_textParms.b1 = color[2];
m_textParms.a1 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "color2"))
{
int color[4];
UTIL_StringToIntArray( color, 4, pkvd->szValue );
m_textParms.r2 = color[0];
m_textParms.g2 = color[1];
m_textParms.b2 = color[2];
m_textParms.a2 = color[3];
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadein"))
{
m_textParms.fadeinTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fadeout"))
{
m_textParms.fadeoutTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "holdtime"))
{
m_textParms.holdTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "fxtime"))
{
m_textParms.fxTime = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameText::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( MessageToAll() )
{
UTIL_HudMessageAll( m_textParms, MessageGet() );
}
else
{
if ( pActivator && pActivator->IsNetClient() )
{
UTIL_HudMessage( pActivator, m_textParms, MessageGet() );
}
}
if ( pev->target )
{
m_pActivator = pActivator;
SetThink( TriggerThink );
SetNextThink( m_textParms.fadeinTime + m_textParms.holdTime + m_textParms.fadeoutTime );
}
else if ( pev->spawnflags & SF_ENVTEXT_ONLY_ONCE )
{
SetThink( Remove );
SetNextThink( 0.1 );
}
}
void CGameText::TriggerThink( void )
{
UTIL_FireTargets( pev->target, m_pActivator, this, USE_TOGGLE, 0 );
if ( pev->spawnflags & SF_ENVTEXT_ONLY_ONCE )
{
SetThink( Remove );
SetNextThink( 0.1 );
}
}
//
// CGameTeamMaster / game_team_master -- "Masters" like multisource, but based on the team of the activator
// Only allows mastered entity to fire if the team matches my team
//
// team index (pulled from server team list "mp_teamlist"
// Flag: Remove on Fire
// Flag: Any team until set? -- Any team can use this until the team is set (otherwise no teams can use it)
//
#define SF_TEAMMASTER_FIREONCE 0x0001
#define SF_TEAMMASTER_ANYTEAM 0x0002
class CGameTeamMaster : public CRulePointEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
// int ObjectCaps( void ) { return CRulePointEntity:: ObjectCaps() | FCAP_MASTER; }
BOOL IsTriggered( CBaseEntity *pActivator );
const char *TeamID( void );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMMASTER_FIREONCE) ? TRUE : FALSE; }
inline BOOL AnyTeam( void ) { return (pev->spawnflags & SF_TEAMMASTER_ANYTEAM) ? TRUE : FALSE; }
private:
BOOL TeamMatch( CBaseEntity *pActivator );
int m_teamIndex;
USE_TYPE triggerType;
};
LINK_ENTITY_TO_CLASS( game_team_master, CGameTeamMaster );
void CGameTeamMaster::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "teamindex"))
{
m_teamIndex = atoi( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "triggerstate"))
{
int type = atoi( pkvd->szValue );
switch( type )
{
case 0:
triggerType = USE_OFF;
break;
case 2:
triggerType = USE_TOGGLE;
break;
default:
triggerType = USE_ON;
break;
}
pkvd->fHandled = TRUE;
}
else
CRulePointEntity::KeyValue( pkvd );
}
void CGameTeamMaster::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( useType == USE_SET )
{
if ( value < 0 )
{
m_teamIndex = -1;
}
else
{
m_teamIndex = g_pGameRules->GetTeamIndex( pActivator->TeamID() );
}
return;
}
if ( TeamMatch( pActivator ) )
{
UTIL_FireTargets( pev->target, pActivator, this, triggerType, value );
if ( RemoveOnFire() )
UTIL_Remove( this );
}
}
BOOL CGameTeamMaster::IsTriggered( CBaseEntity *pActivator )
{
return TeamMatch( pActivator );
}
const char *CGameTeamMaster::TeamID( void )
{
if ( m_teamIndex < 0 ) // Currently set to "no team"
return "";
return g_pGameRules->GetIndexedTeamName( m_teamIndex ); // UNDONE: Fill this in with the team from the "teamlist"
}
BOOL CGameTeamMaster::TeamMatch( CBaseEntity *pActivator )
{
if ( m_teamIndex < 0 && AnyTeam() )
return TRUE;
if ( !pActivator )
return FALSE;
return UTIL_TeamsMatch( pActivator->TeamID(), TeamID() );
}
//
// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team
// Flag: Fire once
// Flag: Clear team -- Sets the team to "NONE" instead of activator
#define SF_TEAMSET_FIREONCE 0x0001
#define SF_TEAMSET_CLEARTEAM 0x0002
class CGameTeamSet : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_TEAMSET_FIREONCE) ? TRUE : FALSE; }
inline BOOL ShouldClearTeam( void ) { return (pev->spawnflags & SF_TEAMSET_CLEARTEAM) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet );
void CGameTeamSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( ShouldClearTeam() )
{
UTIL_FireTargets( pev->target, pActivator, this, USE_SET, -1 );
}
else
{
UTIL_FireTargets( pev->target, pActivator, this, USE_SET, 0 );
}
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired
//
// Needs master?
class CGamePlayerZone : public CRuleBrushEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
private:
string_t m_iszInTarget;
string_t m_iszOutTarget;
string_t m_iszInCount;
string_t m_iszOutCount;
};
LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone );
TYPEDESCRIPTION CGamePlayerZone::m_SaveData[] =
{
DEFINE_FIELD( CGamePlayerZone, m_iszInTarget, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszOutTarget, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszInCount, FIELD_STRING ),
DEFINE_FIELD( CGamePlayerZone, m_iszOutCount, FIELD_STRING ),
};
IMPLEMENT_SAVERESTORE( CGamePlayerZone, CRuleBrushEntity );
void CGamePlayerZone::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "intarget"))
{
m_iszInTarget = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "outtarget"))
{
m_iszOutTarget = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "incount"))
{
m_iszInCount = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "outcount"))
{
m_iszOutCount = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CRuleBrushEntity::KeyValue( pkvd );
}
void CGamePlayerZone::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
int playersInCount = 0;
int playersOutCount = 0;
if ( !CanFireForActivator( pActivator ) )
return;
CBaseEntity *pPlayer = NULL;
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
pPlayer = UTIL_PlayerByIndex( i );
if ( pPlayer )
{
TraceResult trace;
int hullNumber;
BOOL inside = FALSE;
if (pev->origin == g_vecZero) //LRC - to support movewith
{
hullNumber = human_hull;
if ( pPlayer->pev->flags & FL_DUCKING )
{
hullNumber = head_hull;
}
UTIL_TraceModel( pPlayer->pev->origin, pPlayer->pev->origin, hullNumber, edict(), &trace );
inside = trace.fStartSolid;
}
else
{
// LIMITATION: this doesn't allow for non-cuboid game_zone_player entities.
// (is that a problem?)
inside = this->Intersects(pPlayer);
}
if ( inside )
{
playersInCount++;
if ( m_iszInTarget )
{
UTIL_FireTargets( m_iszInTarget, pPlayer, pActivator, useType, value );
}
}
else
{
playersOutCount++;
if ( m_iszOutTarget )
{
UTIL_FireTargets( m_iszOutTarget, pPlayer, pActivator, useType, value );
}
}
}
}
if ( m_iszInCount )
{
UTIL_FireTargets( m_iszInCount, pActivator, this, USE_SET, playersInCount );
}
if ( m_iszOutCount )
{
UTIL_FireTargets( m_iszOutCount, pActivator, this, USE_SET, playersOutCount );
}
}
//
// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it
// Flag: Fire once
#define SF_PKILL_FIREONCE 0x0001
class CGamePlayerHurt : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PKILL_FIREONCE) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt );
void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( pActivator->IsPlayer() )
{
if ( pev->dmg < 0 )
pActivator->TakeHealth( -pev->dmg, DMG_GENERIC );
else
pActivator->TakeDamage( pev, pev, pev->dmg, DMG_GENERIC );
}
UTIL_FireTargets( pev->target, pActivator, this, useType, value );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGameCounter / game_counter -- Counts events and fires target
// Flag: Fire once
// Flag: Reset on Fire
#define SF_GAMECOUNT_FIREONCE 0x0001
#define SF_GAMECOUNT_RESET 0x0002
class CGameCounter : public CRulePointEntity
{
public:
void Spawn( void );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_FIREONCE) ? TRUE : FALSE; }
inline BOOL ResetOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNT_RESET) ? TRUE : FALSE; }
inline void CountUp( void ) { pev->frags++; }
inline void CountDown( void ) { pev->frags--; }
inline void ResetCount( void ) { pev->frags = pev->dmg; }
inline int CountValue( void ) { return pev->frags; }
inline int LimitValue( void ) { return pev->health; }
inline BOOL HitLimit( void ) { return CountValue() == LimitValue(); }
private:
inline void SetCountValue( int value ) { pev->frags = value; }
inline void SetInitialValue( int value ) { pev->dmg = value; }
};
LINK_ENTITY_TO_CLASS( game_counter, CGameCounter );
void CGameCounter::Spawn( void )
{
// Save off the initial count
SetInitialValue( CountValue() );
CRulePointEntity::Spawn();
}
void CGameCounter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
switch( useType )
{
case USE_ON:
case USE_TOGGLE:
CountUp();
break;
case USE_OFF:
CountDown();
break;
case USE_SET:
SetCountValue( (int)value );
break;
}
if ( HitLimit() )
{
UTIL_FireTargets( pev->target, pActivator, this, USE_TOGGLE, 0 );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
if ( ResetOnFire() )
{
ResetCount();
}
}
}
//
// CGameCounterSet / game_counter_set -- Sets the counter's value
// Flag: Fire once
#define SF_GAMECOUNTSET_FIREONCE 0x0001
class CGameCounterSet : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_GAMECOUNTSET_FIREONCE) ? TRUE : FALSE; }
private:
};
LINK_ENTITY_TO_CLASS( game_counter_set, CGameCounterSet );
void CGameCounterSet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
UTIL_FireTargets( pev->target, pActivator, this, USE_SET, pev->frags );
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}
//
// CGamePlayerEquip / game_playerequip -- Sets the default player equipment
// Flag: USE Only
#define SF_PLAYEREQUIP_USEONLY 0x0001
#define MAX_EQUIP 32
class CGamePlayerEquip : public CRulePointEntity
{
public:
void KeyValue( KeyValueData *pkvd );
void Touch( CBaseEntity *pOther );
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
inline BOOL UseOnly( void ) { return (pev->spawnflags & SF_PLAYEREQUIP_USEONLY) ? TRUE : FALSE; }
private:
void EquipPlayer( CBaseEntity *pPlayer );
string_t m_weaponNames[MAX_EQUIP];
int m_weaponCount[MAX_EQUIP];
};
LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip );
void CGamePlayerEquip::KeyValue( KeyValueData *pkvd )
{
CRulePointEntity::KeyValue( pkvd );
if ( !pkvd->fHandled )
{
for ( int i = 0; i < MAX_EQUIP; i++ )
{
if ( !m_weaponNames[i] )
{
char tmp[128];
UTIL_StripToken( pkvd->szKeyName, tmp );
m_weaponNames[i] = ALLOC_STRING(tmp);
m_weaponCount[i] = atoi(pkvd->szValue);
m_weaponCount[i] = max(1,m_weaponCount[i]);
pkvd->fHandled = TRUE;
break;
}
}
}
}
void CGamePlayerEquip::Touch( CBaseEntity *pOther )
{
if ( !CanFireForActivator( pOther ) )
return;
if ( UseOnly() )
return;
EquipPlayer( pOther );
}
void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity )
{
CBasePlayer *pPlayer = NULL;
if ( pEntity->IsPlayer() )
{
pPlayer = (CBasePlayer *)pEntity;
}
if ( !pPlayer )
return;
for ( int i = 0; i < MAX_EQUIP; i++ )
{
if ( !m_weaponNames[i] )
break;
for ( int j = 0; j < m_weaponCount[i]; j++ )
{
pPlayer->GiveNamedItem( STRING(m_weaponNames[i]) );
}
}
}
void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
EquipPlayer( pActivator );
}
//
// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it
// Flag: Fire once
// Flag: Kill Player
// Flag: Gib Player
#define SF_PTEAM_FIREONCE 0x0001
#define SF_PTEAM_KILL 0x0002
#define SF_PTEAM_GIB 0x0004
class CGamePlayerTeam : public CRulePointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
private:
inline BOOL RemoveOnFire( void ) { return (pev->spawnflags & SF_PTEAM_FIREONCE) ? TRUE : FALSE; }
inline BOOL ShouldKillPlayer( void ) { return (pev->spawnflags & SF_PTEAM_KILL) ? TRUE : FALSE; }
inline BOOL ShouldGibPlayer( void ) { return (pev->spawnflags & SF_PTEAM_GIB) ? TRUE : FALSE; }
const char *TargetTeamName( const char *pszTargetName );
};
LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam );
const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName )
{
CBaseEntity *pTeamEntity = NULL;
while ((pTeamEntity = UTIL_FindEntityByTargetname( pTeamEntity, pszTargetName )) != NULL)
{
if ( FClassnameIs( pTeamEntity->pev, "game_team_master" ) )
return pTeamEntity->TeamID();
}
return NULL;
}
void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( !CanFireForActivator( pActivator ) )
return;
if ( pActivator->IsPlayer() )
{
const char *pszTargetTeam = TargetTeamName( STRING(pev->target) );
if ( pszTargetTeam )
{
CBasePlayer *pPlayer = (CBasePlayer *)pActivator;
g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() );
}
}
if ( RemoveOnFire() )
{
UTIL_Remove( this );
}
}

View File

@ -1227,7 +1227,12 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
{
to->body = DirToBits( pNet->pev->movedir );
// FIXME: send mins\maxs for sound spatialization and entity prediction ?
if( pNet->pev->movetype == MOVETYPE_CONVEYOR || pNet->pev->flags & FL_CONVEYOR )
{
// this is conveyor - send speed to render for right texture scrolling
to->framerate = pNet->pev->speed;
}
else to->framerate = 0.0f; // don't let texture moving
}
else if( to->ed_type == ED_BEAM )
{
@ -1647,31 +1652,27 @@ void LinkUserMessages( void )
gmsg.WeaponAnim = REG_USER_MSG( "WeaponAnim", 3 );
gmsg.ShowMenu = REG_USER_MSG( "ShowMenu", -1 );
gmsg.Shake = REG_USER_MSG( "ScreenShake", 13 );
gmsg.Fade = REG_USER_MSG( "ScreenFade", 14 );
gmsg.AmmoX = REG_USER_MSG("AmmoX", 2);
gmsg.Fade = REG_USER_MSG( "ScreenFade", 13 );
gmsg.AmmoX = REG_USER_MSG( "AmmoX", 2 );
gmsg.TeamNames = REG_USER_MSG( "TeamNames", -1 );
gmsg.StatusText = REG_USER_MSG("StatusText", -1);
gmsg.StatusValue = REG_USER_MSG("StatusValue", 3);
gmsg.SetBody = REG_USER_MSG("SetBody", 1);
gmsg.SetSkin = REG_USER_MSG("SetSkin", 1);
gmsg.ZoomHUD = REG_USER_MSG("ZoomHUD", 1);
gmsg.WarHUD = REG_USER_MSG("WarHUD", 1);
gmsg.StatusText = REG_USER_MSG( "StatusText", -1 );
gmsg.StatusValue = REG_USER_MSG( "StatusValue", 3 );
gmsg.SetBody = REG_USER_MSG( "SetBody", 1 );
gmsg.SetSkin = REG_USER_MSG( "SetSkin", 1 );
gmsg.ZoomHUD = REG_USER_MSG( "ZoomHUD", 1 );
gmsg.WarHUD = REG_USER_MSG( "WarHUD", 1 );
// entity messages
gmsg.StatusIcon = REG_USER_MSG("StatusIcon", -1);
gmsg.CamData = REG_USER_MSG("CamData", -1);
gmsg.Fsound = REG_USER_MSG("Fsound", -1);
gmsg.RainData = REG_USER_MSG( "RainData", 28 );
gmsg.AddScreen = REG_USER_MSG( "AddScreen", 2);
gmsg.AddPortal = REG_USER_MSG( "AddPortal", 2);
gmsg.HudText = REG_USER_MSG( "HudText", -1 );
gmsg.ShowGameTitle = REG_USER_MSG("GameTitle", 0 );
gmsg.TempEntity = REG_USER_MSG( "TempEntity", -1);
gmsg.SetFog = REG_USER_MSG("SetFog", 7 );
gmsg.SetSky = REG_USER_MSG( "SetSky", 13 );
gmsg.Particle = REG_USER_MSG( "Particle", -1);
gmsg.Beams = REG_USER_MSG( "Beams", -1 );
gmsg.AddMirror = REG_USER_MSG( "AddMirror", 2);
}
/*

View File

@ -104,10 +104,6 @@ typedef struct user_messages_s
int RainData;
int HudText;
int ShowGameTitle;
int AddScreen;
int AddMirror;
int AddPortal;
int Beams;
} user_messages_t;
extern user_messages_t gmsg;

View File

@ -25,7 +25,6 @@
// Debug macros
//=========================
#define SHIFT Msg("\n")
#define ACTION Msg("Action!\n")
#define DEBUGHEAD Msg("======/Xash Debug System/======\nclassname: %s[%i], targetname %s\n", STRING(pev->classname), entindex(), STRING(pev->targetname))
#define MSGSTATEHEALTH Msg("State: %s, health %g\n", GetStringForState( GetState()), pev->health )
#define MSGSTATESTRENGTH Msg("State: %s, strength %g\n", GetStringForState( GetState()), pev->health )

View File

@ -134,10 +134,10 @@ void UTIL_FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEnt
int i,j, found = false;
char szBuf[80];
if ( !targetName )return;
if ( !targetName ) return;
//HACKHACK
if(FStrEq(targetName, "tr_endchange" ))
// HACKHACK
if( FStrEq( targetName, "tr_endchange" ))
{
SERVER_COMMAND("game_over\n");
return;
@ -221,11 +221,11 @@ void UTIL_FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEnt
targetName = szBuf;
pTarget = UTIL_FindEntityByTargetname(NULL, targetName, inputActivator);
if (!pTarget)return; // it's a locus specifier all right, but the target's invalid.
if( !pTarget ) return; // it's a locus specifier all right, but the target's invalid.
}
}
DevMsg( "Firing: (%s) with %s and value %g\n", targetName, GetStringForUseType( useType ), value );
ALERT( at_aiconsole, "Firing: (%s) with %s and value %g\n", targetName, GetStringForUseType( useType ), value );
do //start firing targets
{
@ -1164,6 +1164,7 @@ int UTIL_PrecacheAurora( const char *s )
if( !afile )
{
// verify file exists
ALERT( at_warning, "couldn't load %s\n", path );
return MAKE_STRING( "scripts/aurora/error.aur" );
}
@ -1192,17 +1193,6 @@ void UTIL_SetAurora( CBaseEntity *pAttach, int aur, int attachment )
WRITE_STRING( STRING( aur ));
MESSAGE_END();
}
//========================================================================
// Set client beams
//========================================================================
void UTIL_SetBeams( char *szFile, CBaseEntity *pStart, CBaseEntity *pEnd )
{
MESSAGE_BEGIN( MSG_ALL, gmsg.Beams );
WRITE_STRING( szFile );
WRITE_BYTE( pStart->entindex()); // beam start entity
WRITE_BYTE( pEnd->entindex() ); // beam end entity
MESSAGE_END();
}
//========================================================================
// Precaches and play sound
@ -1390,8 +1380,8 @@ void UTIL_PrecacheResourse( void )
g_sModelIndexNullSprite = UTIL_PrecacheModel("sprites/null.spr");
// global sprites and models
g_sModelIndexFireball = UTIL_PrecacheModel ("sprites/explode.spr");// fireball
g_sModelIndexWExplosion = UTIL_PrecacheModel ("sprites/wxplode.spr");// underwater fireball
g_sModelIndexFireball = UTIL_PrecacheModel ("sprites/zerogxplode.spr");// fireball
g_sModelIndexWExplosion = UTIL_PrecacheModel ("sprites/WXplo1.spr");// underwater fireball
g_sModelIndexSmoke = UTIL_PrecacheModel ("sprites/steam1.spr");// smoke
g_sModelIndexBubbles = UTIL_PrecacheModel ("sprites/bubble.spr");//bubbles
g_sModelIndexLaser = UTIL_PrecacheModel( "sprites/laserbeam.spr" );
@ -2748,13 +2738,12 @@ void UTIL_Sparks( const Vector &position )
void UTIL_Explode( const Vector &center, edict_t *pOwner, int radius, int name )
{
CBaseEntity *pExplosion = CBaseEntity::Create( "env_explosion", center, g_vecZero, pOwner );
if( pExplosion )
{
if( name ) pExplosion->pev->classname = name;
pExplosion->pev->dmg = radius;
pExplosion->pev->owner = pOwner;
pExplosion->Use( NULL, NULL, USE_ON, 0 );
}
if( !pExplosion ) return;
if( name ) pExplosion->pev->classname = name;
pExplosion->pev->dmg = radius;
pExplosion->pev->spawnflags |= SF_FIREONCE; //remove entity after explode
pExplosion->Use( NULL, NULL, USE_ON, 0 );
}
void UTIL_Ricochet( const Vector &position, float scale )
@ -3105,8 +3094,8 @@ int HaveCamerasInPVS( edict_t* edict )
}
void UTIL_SetView( int ViewEntity, int flags )
{
//Light version SetView
//Please don't use this in multiplayer
// light version of SetView
// please don't use this in multiplayer
CBaseEntity *m_pPlayer = UTIL_PlayerByIndex( 1 );
UTIL_SetView( m_pPlayer, ViewEntity, flags );
}
@ -3115,14 +3104,14 @@ void UTIL_SetView( CBaseEntity *pActivator, int ViewEntity, int flags )
{
CBaseEntity *pViewEnt = 0;
if(ViewEntity)
if ( ViewEntity )
{
//try to find by targetname
pViewEnt = UTIL_FindEntityByString( NULL, "targetname", STRING(ViewEntity));
//try to find by classname
if(FNullEnt(pViewEnt))
pViewEnt = UTIL_FindEntityByString( NULL, "classname", STRING(ViewEntity));
if(pViewEnt && pViewEnt->pev->flags & FL_MONSTER) flags |= MONSTER_VIEW;//detect monster view
// try to find by targetname
pViewEnt = UTIL_FindEntityByString( NULL, "targetname", STRING( ViewEntity ));
// try to find by classname
if( FNullEnt( pViewEnt ))
pViewEnt = UTIL_FindEntityByString( NULL, "classname", STRING( ViewEntity ));
if( pViewEnt && pViewEnt->pev->flags & FL_MONSTER ) flags |= MONSTER_VIEW; // detect monster view
}
UTIL_SetView( pActivator, pViewEnt, flags );
}

View File

@ -744,7 +744,6 @@ void UTIL_PrecacheEntity( const char *szClassname );
int UTIL_PrecacheAurora( string_t s );
int UTIL_PrecacheAurora( const char *s );
void UTIL_SetAurora( CBaseEntity *pAttach, int aur, int attachment = 0 );
void UTIL_SetBeams( char *szFile, CBaseEntity *pStart, CBaseEntity *pEnd );
extern int giAmmoIndex;

View File

@ -0,0 +1,363 @@
/***
*
* 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.
*
****/
//=========================================================
// Monster Maker - this is an entity that creates monsters
// in the game.
//=========================================================
#include "extdll.h"
#include "utils.h"
#include "cbase.h"
#include "monsters.h"
#include "saverestore.h"
// Monstermaker spawnflags
#define SF_MONSTERMAKER_START_ON 1 // start active ( if has targetname )
#define SF_MONSTERMAKER_CYCLIC 4 // drop one monster every time fired.
#define SF_MONSTERMAKER_MONSTERCLIP 8 // Children are blocked by monsterclip
#define SF_MONSTERMAKER_LEAVECORPSE 16 // Don't fade corpses.
#define SF_MONSTERMAKER_NO_WPN_DROP 1024 // Corpses don't drop weapons.
//=========================================================
// MonsterMaker - this ent creates monsters during the game.
//=========================================================
class CMonsterMaker : public CBaseMonster
{
public:
void Spawn( void );
void Precache( void );
void KeyValue( KeyValueData* pkvd);
void EXPORT ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT CyclicUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT MakerThink ( void );
void EXPORT MakeMonsterThink( void );
void DeathNotice ( entvars_t *pevChild );// monster maker children use this to tell the monster maker that they have died.
void TryMakeMonster( void ); //LRC - to allow for a spawndelay
CBaseMonster* MakeMonster( void ); //LRC - actually make a monster (and return the new creation)
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
string_t m_iszMonsterClassname;// classname of the monster(s) that will be created.
int m_cNumMonsters;// max number of monsters this ent can create
int m_cLiveChildren;// how many monsters made by this monster maker that are currently alive
int m_iMaxLiveChildren;// max number of monsters that this maker may have out at one time.
float m_flGround; // z coord of the ground under me, used to make sure no monsters are under the maker when it drops a new child
BOOL m_fActive;
BOOL m_fFadeChildren;// should we make the children fadeout?
float m_fSpawnDelay;// LRC- delay between triggering targets and making a child (for env_warpball, mainly)
};
LINK_ENTITY_TO_CLASS( monstermaker, CMonsterMaker );
TYPEDESCRIPTION CMonsterMaker::m_SaveData[] =
{
DEFINE_FIELD( CMonsterMaker, m_iszMonsterClassname, FIELD_STRING ),
DEFINE_FIELD( CMonsterMaker, m_cNumMonsters, FIELD_INTEGER ),
DEFINE_FIELD( CMonsterMaker, m_cLiveChildren, FIELD_INTEGER ),
DEFINE_FIELD( CMonsterMaker, m_flGround, FIELD_FLOAT ),
DEFINE_FIELD( CMonsterMaker, m_iMaxLiveChildren, FIELD_INTEGER ),
DEFINE_FIELD( CMonsterMaker, m_fActive, FIELD_BOOLEAN ),
DEFINE_FIELD( CMonsterMaker, m_fFadeChildren, FIELD_BOOLEAN ),
DEFINE_FIELD( CMonsterMaker, m_fSpawnDelay, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CMonsterMaker, CBaseMonster );
void CMonsterMaker :: KeyValue( KeyValueData *pkvd )
{
if ( FStrEq(pkvd->szKeyName, "monstercount") )
{
m_cNumMonsters = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "m_imaxlivechildren") )
{
m_iMaxLiveChildren = atoi(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "monstertype") )
{
m_iszMonsterClassname = ALLOC_STRING( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else if ( FStrEq(pkvd->szKeyName, "spawndelay") )
{
m_fSpawnDelay = atof( pkvd->szValue );
pkvd->fHandled = TRUE;
}
else
CBaseMonster::KeyValue( pkvd );
}
void CMonsterMaker :: Spawn( )
{
pev->solid = SOLID_NOT;
m_cLiveChildren = 0;
Precache();
if ( !FStringNull ( pev->targetname ) )
{
if ( pev->spawnflags & SF_MONSTERMAKER_CYCLIC )
{
SetUse(&CMonsterMaker :: CyclicUse );// drop one monster each time we fire
m_fActive = FALSE;
}
else
{
SetUse(&CMonsterMaker :: ToggleUse );// can be turned on/off
if ( FBitSet ( pev->spawnflags, SF_MONSTERMAKER_START_ON ) )
{
// start making monsters as soon as monstermaker spawns
m_fActive = TRUE;
SetThink(&CMonsterMaker :: MakerThink );
}
else
{
// wait to be activated.
m_fActive = FALSE;
DontThink();
}
}
}
else
{// no targetname, just start.
SetNextThink( m_flDelay );
m_fActive = TRUE;
SetThink(&CMonsterMaker :: MakerThink );
}
if ( m_cNumMonsters == 1 || (m_cNumMonsters != -1 && pev->spawnflags & SF_MONSTERMAKER_LEAVECORPSE ))
{
m_fFadeChildren = FALSE;
}
else
{
m_fFadeChildren = TRUE;
}
m_flGround = 0;
}
void CMonsterMaker :: Precache( void )
{
CBaseMonster::Precache();
UTIL_PrecacheEntity( STRING( m_iszMonsterClassname ) );
}
//=========================================================
// TryMakeMonster- check that it's ok to drop a monster.
//=========================================================
void CMonsterMaker::TryMakeMonster( void )
{
if ( m_iMaxLiveChildren > 0 && m_cLiveChildren >= m_iMaxLiveChildren )
{// not allowed to make a new one yet. Too many live ones out right now.
return;
}
if ( !m_flGround )
{
// set altitude. Now that I'm activated, any breakables, etc should be out from under me.
TraceResult tr;
UTIL_TraceLine ( pev->origin, pev->origin - Vector ( 0, 0, 2048 ), ignore_monsters, ENT(pev), &tr );
m_flGround = tr.vecEndPos.z;
}
Vector mins = pev->origin - Vector( 34, 34, 0 );
Vector maxs = pev->origin + Vector( 34, 34, 0 );
maxs.z = pev->origin.z;
mins.z = m_flGround;
CBaseEntity *pList[2];
int count = UTIL_EntitiesInBox( pList, 2, mins, maxs, FL_CLIENT|FL_MONSTER );
if ( count )
{
// don't build a stack of monsters!
return;
}
if (m_fSpawnDelay)
{
// If I have a target, fire. (no locus)
if ( !FStringNull ( pev->target ) )
{
// delay already overloaded for this entity, so can't call SUB_UseTargets()
UTIL_FireTargets( STRING(pev->target), this, this, USE_TOGGLE, 0 );
}
// ALERT(at_console,"Making Monster in %f seconds\n",m_fSpawnDelay);
SetThink(&CMonsterMaker:: MakeMonsterThink );
SetNextThink( m_fSpawnDelay );
}
else
{
// ALERT(at_console,"No delay. Making monster.\n",m_fSpawnDelay);
CBaseMonster* pMonst = MakeMonster();
// If I have a target, fire! (the new monster is the locus)
if ( !FStringNull ( pev->target ) )
{
UTIL_FireTargets( STRING(pev->target), pMonst, this, USE_TOGGLE, 0 );
}
}
}
//=========================================================
// MakeMonsterThink- a really trivial think function
//=========================================================
void CMonsterMaker::MakeMonsterThink( void )
{
MakeMonster();
}
//=========================================================
// MakeMonster- this is the code that drops the monster
//=========================================================
CBaseMonster* CMonsterMaker::MakeMonster( void )
{
edict_t *pent;
entvars_t *pevCreate;
// ALERT(at_console,"Making Monster NOW\n");
pent = CREATE_NAMED_ENTITY( m_iszMonsterClassname );
if ( FNullEnt( pent ) )
{
ALERT ( at_console, "NULL Ent in MonsterMaker!\n" );
return NULL;
}
pevCreate = VARS( pent );
pevCreate->origin = pev->origin;
pevCreate->angles = pev->angles;
SetBits( pevCreate->spawnflags, SF_MONSTER_FALL_TO_GROUND );
if (pev->spawnflags & SF_MONSTERMAKER_NO_WPN_DROP)
SetBits( pevCreate->spawnflags, SF_MONSTER_NO_WPN_DROP);
// Children hit monsterclip brushes
if ( pev->spawnflags & SF_MONSTERMAKER_MONSTERCLIP )
SetBits( pevCreate->spawnflags, SF_MONSTER_HITMONSTERCLIP );
DispatchSpawn( ENT( pevCreate ) );
pevCreate->owner = edict();
//LRC - custom monster behaviour
CBaseEntity *pEntity = CBaseEntity::Instance( pevCreate );
CBaseMonster *pMonst = NULL;
if (pEntity && (pMonst = pEntity->MyMonsterPointer()) != NULL)
{
pMonst->m_iClass = this->m_iClass;
pMonst->m_iPlayerReact = this->m_iPlayerReact;
}
if ( !FStringNull( pev->netname ) )
{
// if I have a netname (overloaded), give the child monster that name as a targetname
pevCreate->targetname = pev->netname;
}
m_cLiveChildren++;// count this monster
m_cNumMonsters--;
if ( m_cNumMonsters == 0 )
{
// Disable this forever. Don't kill it because it still gets death notices
SetThink( NULL );
SetUse( NULL );
}
else if (m_fActive)
{
SetNextThink( m_flDelay );
SetThink(&CMonsterMaker:: MakerThink );
}
return pMonst;
}
//=========================================================
// CyclicUse - drops one monster from the monstermaker
// each time we call this.
//=========================================================
void CMonsterMaker::CyclicUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
TryMakeMonster();
// ALERT(at_console,"CyclicUse complete\n");
}
//=========================================================
// ToggleUse - activates/deactivates the monster maker
//=========================================================
void CMonsterMaker :: ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if ( useType == USE_TOGGLE )
{
if ( !m_fActive )
useType = USE_ON;
else useType = USE_OFF;
}
if ( useType == USE_ON )
{
m_fActive = TRUE;
SetThink(&CMonsterMaker :: MakerThink );
}
else if ( useType == USE_OFF )
{
m_fActive = FALSE;
SetThink ( NULL );
}
SetNextThink( 0 );
}
//=========================================================
// MakerThink - creates a new monster every so often
//=========================================================
void CMonsterMaker :: MakerThink ( void )
{
SetNextThink( m_flDelay );
TryMakeMonster();
}
//=========================================================
//=========================================================
void CMonsterMaker :: DeathNotice ( entvars_t *pevChild )
{
// ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade.
m_cLiveChildren--;
if ( !m_fFadeChildren )
{
pevChild->owner = NULL;
}
}

View File

@ -160,7 +160,7 @@ entvars_t* CGraph :: LinkEntForLink ( CLink *pLink, CNode *pNode )
///!!!UNDONE - check for TOGGLE or STAY open doors here. If a door is in the way, and is
// TOGGLE or STAY OPEN, even monsters that can't open doors can go that way.
if ( ( pevLinkEnt->spawnflags & SF_DOOR_USE_ONLY ) )
if ( ( pevLinkEnt->team == 1 ) )
{// door is use only, so the door is all the monster has to worry about
return pevLinkEnt;
}
@ -234,7 +234,7 @@ int CGraph :: HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, N
pDoor = ( CBaseEntity::Instance( pevLinkEnt ) );
if ( ( pevLinkEnt->spawnflags & SF_DOOR_USE_ONLY ) )
if ( ( pevLinkEnt->team == 1 ) )
{// door is use only.
if ( ( afCapMask & bits_CAP_OPEN_DOORS ) )
@ -244,7 +244,7 @@ int CGraph :: HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, N
else
{
// monster should try for it if the door is open and looks as if it will stay that way
if ( pDoor->GetState() == STATE_ON && ( pevLinkEnt->spawnflags & SF_DOOR_NO_AUTO_RETURN ))
if ( pDoor->GetState() == STATE_ON && ( pevLinkEnt->impulse == 1 ))
{
return TRUE;
}
@ -256,13 +256,13 @@ int CGraph :: HandleLinkEnt ( int iNode, entvars_t *pevLinkEnt, int afCapMask, N
{// door must be opened with a button or trigger field.
// monster should try for it if the door is open and looks as if it will stay that way
if ( pDoor->GetState() == STATE_ON && ( pevLinkEnt->spawnflags & SF_DOOR_NO_AUTO_RETURN ))
if ( pDoor->GetState() == STATE_ON && ( pevLinkEnt->impulse == 1 ))
{
return TRUE;
}
if ( ( afCapMask & bits_CAP_OPEN_DOORS ) )
{
if ( !( pevLinkEnt->spawnflags & SF_DOOR_NOMONSTERS ) || queryType == NODEGRAPH_STATIC )
if ( queryType == NODEGRAPH_STATIC )
return TRUE;
}

View File

@ -3080,6 +3080,130 @@ const char *CBasePlayer::TeamID( void )
return m_szTeamName;
}
//=========================================================
// remove all items
//=========================================================
#define SF_REMOVE_SUIT 1
class CStripWeapons : public CPointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBasePlayer *pPlayer = NULL;
if ( pActivator && pActivator->IsPlayer() )
{
pPlayer = (CBasePlayer *)pActivator;
}
else if ( !IsMultiplayer() )
{
pPlayer = (CBasePlayer *)UTIL_PlayerByIndex( 1 );
}
else
{
ALERT( at_warning, "%s: %s activator not player. Ignored.\n", STRING( pev->classname ), STRING( pev->targetname ));
return;
}
if ( pPlayer ) pPlayer->RemoveAllItems( pev->spawnflags & SF_REMOVE_SUIT );
if ( pev->spawnflags & SF_FIREONCE ) UTIL_Remove( this );
}
};
LINK_ENTITY_TO_CLASS( player_weaponstrip, CStripWeapons );
class CRevertSaved : public CPointEntity
{
public:
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
void EXPORT MessageThink( void );
void EXPORT LoadThink( void );
void KeyValue( KeyValueData *pkvd );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
inline float Duration( void ) { return pev->dmg_take; }
inline float HoldTime( void ) { return pev->dmg_save; }
inline float MessageTime( void ) { return m_messageTime; }
inline float LoadTime( void ) { return m_loadTime; }
inline void SetDuration( float duration ) { pev->dmg_take = duration; }
inline void SetHoldTime( float hold ) { pev->dmg_save = hold; }
inline void SetMessageTime( float time ) { m_messageTime = time; }
inline void SetLoadTime( float time ) { m_loadTime = time; }
private:
float m_messageTime;
float m_loadTime;
};
LINK_ENTITY_TO_CLASS( player_loadsaved, CRevertSaved );
TYPEDESCRIPTION CRevertSaved::m_SaveData[] =
{
DEFINE_FIELD( CRevertSaved, m_messageTime, FIELD_FLOAT ), // These are not actual times, but durations, so save as floats
DEFINE_FIELD( CRevertSaved, m_loadTime, FIELD_FLOAT ),
};
IMPLEMENT_SAVERESTORE( CRevertSaved, CPointEntity );
void CRevertSaved :: KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "duration"))
{
SetDuration( atof(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "holdtime"))
{
SetHoldTime( atof(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "messagetime"))
{
SetMessageTime( atof(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else if (FStrEq(pkvd->szKeyName, "loadtime"))
{
SetLoadTime( atof(pkvd->szValue) );
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
void CRevertSaved :: Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
UTIL_ScreenFadeAll( pev->rendercolor, Duration(), HoldTime(), pev->renderamt, FFADE_OUT );
SetNextThink( MessageTime() );
SetThink(&CRevertSaved :: MessageThink );
}
void CRevertSaved :: MessageThink( void )
{
UTIL_ShowMessageAll( STRING(pev->message) );
float nextThink = LoadTime() - MessageTime();
if ( nextThink > 0 )
{
SetNextThink( nextThink );
SetThink(&CRevertSaved :: LoadThink );
}
else
LoadThink();
}
void CRevertSaved :: LoadThink( void )
{
if ( !gpGlobals->deathmatch )
{
SERVER_COMMAND("reload\n");
}
}
//==============================================
// !!!UNDONE:ultra temporary SprayCan entity to apply
@ -3773,7 +3897,7 @@ void CBasePlayer :: UpdateClientData( void )
MESSAGE_BEGIN( MSG_ONE, gmsg.Fade, NULL, pev );
WRITE_FLOAT( m_flFadeTime );
WRITE_FLOAT( m_flFadeHold );
WRITE_SHORT( m_iFadeFlags ); // fade flags
WRITE_BYTE( m_iFadeFlags ); // fade flags
WRITE_BYTE( (byte)m_FadeColor.x ); // fade red
WRITE_BYTE( (byte)m_FadeColor.y ); // fade green
WRITE_BYTE( (byte)m_FadeColor.z ); // fade blue
@ -3967,14 +4091,14 @@ void CBasePlayer :: UpdateClientData( void )
int rainmode = pEnt->pev->button;
// search for constant rain_modifies
pFind = UTIL_FindEntityByClassname( NULL, "util_rainmodify" );
pFind = UTIL_FindEntityByClassname( NULL, "env_rainmodify" );
while ( !FNullEnt( pFind ) )
{
if (pFind->pev->spawnflags & 1)
if ( pFind->pev->spawnflags & 1 )
{
// copy settings to player's data and clear fading
CBaseEntity *pEnt = CBaseEntity::Instance( pFind->edict() );
CUtilRainModify *pRainModify = (CUtilRainModify *)pEnt;
CEnvRainModify *pRainModify = (CEnvRainModify *)pEnt;
Rain_dripsPerSecond = pRainModify->pev->button;
Rain_windX = pRainModify->windXY[1];

35
server/quake.cpp Normal file
View File

@ -0,0 +1,35 @@
class CWallTorch : public CBaseEntity
{
public:
void Precache( void )
{
// if sound is missing just reset soundindex
pev->impulse = PRECACHE_SOUND( "ambience/fire1.wav" );
UTIL_PrecacheModel( "models/props/torch1.mdl" );
}
void Spawn( void )
{
Precache ();
if( !pev->impulse )
{
UTIL_Remove( this );
return;
}
// SetObjectClass( ED_NORMAL );
pev->flags |= FL_PHS_FILTER; // allow phs filter instead pvs
// setup attenuation radius
pev->armorvalue = 384.0f * ATTN_STATIC;
pev->soundindex = pev->impulse;
UTIL_SetModel( ENT( pev ), "models/props/torch1.mdl" );
UTIL_SetSize(pev, g_vecZero, g_vecZero);
SetBits( pev->flags, FL_POINTENTITY );
pev->animtime = gpGlobals->time + 0.2; // enable animation
pev->framerate = 0.5f;
}
};
LINK_ENTITY_TO_CLASS( light_torch_small_walltorch, CWallTorch );

View File

@ -61,8 +61,8 @@ TargetDir=\Xash3D\src_main\temp\server\!release
InputPath=\Xash3D\src_main\temp\server\!release\server.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\server.dll "D:\Xash3D\bin\server.dll"
"D:\Xash3D\xash\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\server.dll "D:\Xash3D\xash\bin\server.dll"
# End Custom Build
@ -101,8 +101,8 @@ TargetDir=\Xash3D\src_main\temp\server\!debug
InputPath=\Xash3D\src_main\temp\server\!debug\server.dll
SOURCE="$(InputPath)"
"D:\Xash3D\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\server.dll "D:\Xash3D\bin\server.dll"
"D:\Xash3D\xash\bin\server.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\server.dll "D:\Xash3D\xash\bin\server.dll"
# End Custom Build
@ -181,10 +181,6 @@ SOURCE=.\ents\baseother.cpp
# End Source File
# Begin Source File
SOURCE=.\ents\basepath.cpp
# End Source File
# Begin Source File
SOURCE=.\ents\basephys.cpp
# End Source File
# Begin Source File
@ -197,11 +193,11 @@ SOURCE=.\ents\basetank.cpp
# End Source File
# Begin Source File
SOURCE=.\ents\basetrigger.cpp
SOURCE=.\ents\basetrain.cpp
# End Source File
# Begin Source File
SOURCE=.\ents\baseutil.cpp
SOURCE=.\ents\basetrigger.cpp
# End Source File
# Begin Source File
@ -277,6 +273,14 @@ SOURCE=.\game\lights.cpp
# End Source File
# Begin Source File
SOURCE=.\game\maprules.cpp
# End Source File
# Begin Source File
SOURCE=.\monsters\monstermaker.cpp
# End Source File
# Begin Source File
SOURCE=.\game\multiplay_gamerules.cpp
# End Source File
# Begin Source File

View File

@ -290,7 +290,7 @@ void LinkUserMessages( void )
gmsgWeaponAnim = REG_USER_MSG( "WeaponAnim", 3 );
gmsgShowMenu = REG_USER_MSG( "ShowMenu", -1 );
gmsgShake = REG_USER_MSG("ScreenShake", 13 );
gmsgFade = REG_USER_MSG("ScreenFade", 14 );
gmsgFade = REG_USER_MSG("ScreenFade", 13 );
gmsgAmmoX = REG_USER_MSG("AmmoX", 2);
gmsgTeamNames = REG_USER_MSG( "TeamNames", -1 );
gmsgStatusIcon = REG_USER_MSG( "StatusIcon", -1 );

View File

@ -1298,11 +1298,11 @@ void UTIL_ScreenFadeWrite( const ScreenFade &fade, CBaseEntity *pEntity )
WRITE_FLOAT( fade.duration ); // fade lasts this long
WRITE_FLOAT( fade.holdTime ); // fade lasts this long
WRITE_SHORT( fade.fadeFlags ); // fade type (in / out)
WRITE_BYTE( fade.r ); // fade red
WRITE_BYTE( fade.g ); // fade green
WRITE_BYTE( fade.b ); // fade blue
WRITE_BYTE( fade.a ); // fade blue
WRITE_BYTE( fade.fadeFlags ); // fade type (in / out)
WRITE_BYTE( fade.r ); // fade red
WRITE_BYTE( fade.g ); // fade green
WRITE_BYTE( fade.b ); // fade blue
WRITE_BYTE( fade.a ); // fade blue
MESSAGE_END();
}

View File

@ -2998,7 +2998,9 @@ static _inline void R_SetColorForOutlines( void )
switch( type )
{
case MB_MODEL:
if( r_currentMeshBuffer->infokey < 0 )
if( triState.fActive )
pglColor4fv( colorBlue );
else if( r_currentMeshBuffer->infokey < 0 )
pglColor4fv( colorRed );
else pglColor4fv( colorWhite );
break;

View File

@ -499,7 +499,10 @@ bool R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, fl
ref_entity_t *e = RI.currententity;
float angle, sr, cr;
ref_shader_t *shader;
vec3_t point;
vec3_t point, origin;
// don't touch entity origin in case we doesn't have updates
VectorCopy( e->origin, origin );
switch( type )
{
@ -508,10 +511,10 @@ bool R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, fl
VectorCopy( e->axis[1], v_right );
VectorCopy( e->axis[2], v_up );
VectorScale( v_forward, 0.01f, v_forward ); // to avoid z-fighting
VectorSubtract( e->origin, v_forward, e->origin );
VectorSubtract( origin, v_forward, origin );
break;
case SPR_FACING_UPRIGHT:
VectorSet( v_right, e->origin[1] - RI.viewOrigin[1], -(e->origin[0] - RI.viewOrigin[0]), 0 );
VectorSet( v_right, origin[1] - RI.viewOrigin[1], -(origin[0] - RI.viewOrigin[0]), 0 );
VectorSet( v_up, 0, 0, 1 );
VectorNormalize( v_right );
break;
@ -569,7 +572,7 @@ bool R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, fl
if( shader->flags & SHADER_ENTITY_MERGABLE )
{
for( i = 0; i < 4; i++ )
VectorAdd( spr_xyz[i], e->origin, spr_xyz[i] );
VectorAdd( spr_xyz[i], origin, spr_xyz[i] );
R_PushMesh( &spr_mesh, features );
return false;
}
@ -1863,6 +1866,9 @@ void R_AddLightStyleToScene( int style, float r, float g, float b )
{
lightstyle_t *ls;
if( !r_worldmodel || !r_worldbrushmodel->lightgrid || !r_worldbrushmodel->numlightgridelems )
return; // don't apply lightstyles when no lighting info
if( style < 0 || style > MAX_LIGHTSTYLES )
Host_Error( "R_AddLightStyleToScene: bad light style %i\n", style );
@ -2477,8 +2483,11 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type, shader_t customShader
if( !pRefEntity || pRefEntity->v.modelindex <= 0 || pRefEntity->v.modelindex >= MAX_MODELS )
return false; // if set to invisible, skip
if( r_numEntities >= MAX_ENTITIES ) return false;
if( r_numEntities >= MAX_ENTITIES )
{
MsgDev( D_ERROR, "R_AddEntityToScene: too many visible entities\n" );
return false;
}
refent = &r_entities[r_numEntities];
if( pRefEntity->v.effects & EF_NODRAW && ed_type != ED_PORTAL )

View File

@ -687,7 +687,8 @@ void R_DrawMeshes( void )
R_LoadIdentity();
// clearing fog after each frame
triState.fogEnabled = false;
if( !( RI.params & RP_NONVIEWERREF ))
triState.fogEnabled = false;
}
/*

View File

@ -645,7 +645,7 @@ static bool Shader_SkipConditionBlock( script_t *script )
//===========================================================================
static bool Shader_CheckSkybox( const char *name )
{
const char *skybox_ext[4] = { "tga", "jpg", "png", "dds" };
const char *skybox_ext[5] = { "tga", "bmp", "jpg", "png", "dds" };
int i, j, num_checked_sides;
const char *sidename;
string loadname;
@ -662,13 +662,13 @@ static bool Shader_CheckSkybox( const char *name )
return true;
// complex cubemap pack not found, search for skybox images
for( i = 0; i < 4; i++ )
for( i = 0; i < 5; i++ )
{
num_checked_sides = 0;
for( j = 0; j < 6; j++ )
{
// build side name
sidename = va( "%s_%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] );
sidename = va( "%s%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] );
if( FS_FileExists( sidename )) num_checked_sides++;
}
@ -677,7 +677,7 @@ static bool Shader_CheckSkybox( const char *name )
for( j = 0; j < 6; j++ )
{
// build side name
sidename = va( "%s%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] );
sidename = va( "%s_%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] );
if( FS_FileExists( sidename )) num_checked_sides++;
}
if( num_checked_sides == 6 )
@ -719,7 +719,7 @@ static bool Shader_ParseSkySides( script_t *script, ref_shader_t *shader, ref_sh
for( i = 0; i < 6; i++ )
{
com.snprintf( name, sizeof( name ), "%s_%s", tok.string, r_skyBoxSuffix[i] );
com.snprintf( name, sizeof( name ), "%s%s", tok.string, r_skyBoxSuffix[i] );
image = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_NOMIPMAP|TF_SKYSIDE );
if( !image ) break;
shaders[i] = R_LoadShader( image->name, shaderType, true, image->flags, SHADER_INVALID );
@ -728,7 +728,7 @@ static bool Shader_ParseSkySides( script_t *script, ref_shader_t *shader, ref_sh
for( i = 0; i < 6; i++ )
{
com.snprintf( name, sizeof( name ), "%s%s", tok.string, r_skyBoxSuffix[i] );
com.snprintf( name, sizeof( name ), "%s_%s", tok.string, r_skyBoxSuffix[i] );
image = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_NOMIPMAP|TF_SKYSIDE );
if( !image ) break;
shaders[i] = R_LoadShader( image->name, shaderType, true, image->flags, SHADER_INVALID );