This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/server/ents/baseinfo.cpp

229 lines
6.6 KiB
C++

//=======================================================================
// Copyright (C) Shambler Team 2004
// baseinfo.cpp - point info entities.
// e.g. info_target
//=======================================================================
#include "extdll.h"
#include "utils.h"
#include "cbase.h"
#include "player.h"
//=======================================================================
// info_target (target entity)
//=======================================================================
class CInfoTarget : public CPointEntity
{
public:
void Spawn( void )
{
pev->solid = SOLID_NOT;
UTIL_SetModel(ENT(pev),"models/common/null.mdl");
UTIL_SetSize(pev, g_vecZero, g_vecZero);
SetBits( pev->flags, FL_POINTENTITY );
}
};
void CBaseDMStart::KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "master"))
{
pev->netname = ALLOC_STRING(pkvd->szValue);
pkvd->fHandled = TRUE;
}
else
CPointEntity::KeyValue( pkvd );
}
STATE CBaseDMStart::GetState( CBaseEntity *pEntity )
{
if (UTIL_IsMasterTriggered( pev->netname, pEntity ))
return STATE_ON;
else return STATE_OFF;
}
//=========================================================
// static infodecal
//=========================================================
class CDecal : public CBaseEntity
{
public:
void KeyValue( KeyValueData *pkvd )
{
if (FStrEq(pkvd->szKeyName, "texture"))
{
pev->skin = DECAL_INDEX( pkvd->szValue );
if ( pev->skin >= 0 ) return;
Msg( "Can't find decal %s\n", pkvd->szValue );
}
}
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; }
TraceResult trace;
int entityIndex, modelIndex;
UTIL_TraceLine( pev->origin - Vector(5,5,5), pev->origin + Vector(5,5,5), ignore_monsters, ENT(pev), &trace );
entityIndex = (short)ENTINDEX(trace.pHit);
if ( entityIndex ) modelIndex = (int)VARS(trace.pHit)->modelindex;
else modelIndex = 0;
if(FStringNull(pev->targetname)) g_engfuncs.pfnStaticDecal( pev->origin, (int)pev->skin, entityIndex, modelIndex );
else
{
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY);
WRITE_BYTE( TE_BSPDECAL );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( (int)pev->skin );
WRITE_SHORT( entityIndex );
if(entityIndex) WRITE_SHORT( modelIndex );
MESSAGE_END();
}
SetThink( Remove );
SetNextThink( 0.3 );
}
};
//=========================================================
// Multiplayer intermission spots.
//=========================================================
class CInfoIntermission:public CPointEntity
{
void Spawn( void );
void Think( void );
void PostActivate( void );
CBaseEntity *pTarget;
};
void CInfoIntermission::Spawn( void )
{
pev->solid = SOLID_NOT;
pev->movetype = MOVETYPE_NOCLIP;
UTIL_SetOrigin( this, pev->origin );
UTIL_SetModel( ENT( pev ), "sprites/null.spr" );
SetNextThink( 1 );// let targets spawn!
}
void CInfoIntermission::PostActivate( void )
{
pTarget = UTIL_FindEntityByTargetname( NULL, STRING( pev->target ));
if( !pev->speed ) pev->speed = 100;
}
void CInfoIntermission::Think ( void )
{
if( pTarget )
{
UTIL_WatchTarget( this, pTarget );
SetNextThink( 0 );
}
}
//====================================================================
// multisource
//====================================================================
TYPEDESCRIPTION CMultiSource::m_SaveData[] =
{
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 )
{
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 );
}
}
STATE CMultiSource::GetState( void )
{
// Is everything triggered?
int i = 0;
// Still initializing?
if ( pev->spawnflags & SF_START_ON ) return STATE_OFF;
while (i < m_iTotal)
{
if (m_rgTriggered[i] == 0) break;
i++;
}
if (i == m_iTotal)
{
if ( !m_globalstate || gGlobalState.EntityGetState( m_globalstate ) == GLOBAL_ON )
return STATE_ON;
}
return STATE_OFF;
}
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))
{
m_rgEntities[m_iTotal++] = pTarget;
pTarget = UTIL_FindEntityByTarget( pTarget, STRING(pev->targetname));
}
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;
}
LINK_ENTITY_TO_CLASS( infodecal, CDecal );
LINK_ENTITY_TO_CLASS( info_target, CInfoTarget );
LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity );
LINK_ENTITY_TO_CLASS( info_null, 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( info_player_deathmatch, CBaseDMStart);
LINK_ENTITY_TO_CLASS( info_player_start, CPointEntity);
LINK_ENTITY_TO_CLASS( info_landmark, CPointEntity);