nuclide/src/shared/NSEntity.qc

932 lines
22 KiB
Plaintext

/*
* Copyright (c) 2016-2022 Vera Visions LLC.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
============
NSEntity::NSEntity
client doesn't have to do a whole lot here
============
*/
void NSEntity::NSEntity( void ) {
#ifdef SERVER
identity = 1;
#endif
}
void NSEntity::Spawned( void ) {
super::Spawned();
m_oldAngle = angles;
m_oldOrigin = origin;
m_oldModel = Util_FixModel( model );
m_oldSolid = solid;
#ifdef SERVER
m_oldstrTarget = target;
if ( m_oldModel ) {
precache_model( GetSpawnModel() );
}
if ( m_strOnTrigger ) {
m_strOnTrigger = CreateOutput( m_strOnTrigger );
}
#endif
}
float NSEntity::EntIndex( void ) {
return ( num_for_edict( this ) );
}
void droptofloorwrapper( entity foo ) {
entity old_self = self;
self = foo;
droptofloor();
self = old_self;
}
void NSEntity::DropToFloor( void ) {
droptofloorwrapper( this );
}
vector NSEntity::GetForward( void ) {
makevectors( angles );
return ( v_forward );
}
vector NSEntity::GetRight( void ) {
makevectors( angles );
return ( v_right );
}
vector NSEntity::GetUp( void ) {
makevectors( angles );
return ( v_up );
}
/*
============
NSEntity::WorldSpaceCenter
Returns the center of an entity's bounding boxes.
Useful on brush entities that have no real 'origin' defined.
============
*/
vector NSEntity::WorldSpaceCenter( void ) {
return ( absmin + ( 0.5 * ( absmax - absmin ) ) );
}
/*
============
NSEntity::WaterLevel
Returns whether or not the entity is able to see a given position
============
*/
float NSEntity::WaterLevel( void ) {
return ( waterlevel );
}
/*
============
NSEntity::VisibleVec
Returns whether or not the entity is able to see a given position
============
*/
bool NSEntity::VisibleVec( vector org ) {
vector flDelta;
float flFoV;
makevectors( angles );
flDelta = normalize( org - origin );
flFoV = flDelta * v_forward;
if ( flFoV > 0.3f ) {
traceline( origin, org, TRUE, this );
if ( trace_fraction == 1.0f ) {
return ( true );
}
}
return ( false );
}
/*
============
NSEntity::Visible
Returns whether or not the entity is able to see a given entity
============
*/
bool NSEntity::Visible( entity ent ) {
vector flDelta;
float flFoV;
makevectors( angles );
flDelta = normalize( ent.origin - origin );
flFoV = flDelta * v_forward;
/* is it in our field of view? */
if ( flFoV > 0.3f ) {
traceline( origin, ent.origin, MOVE_NORMAL, this );
if ( trace_fraction == 1.0f || trace_ent == ent ) {
print( sprintf( "%s can see %s\n", classname, ent.classname ) );
return ( true );
}
}
print( sprintf( "%s can not see %s\n", classname, ent.classname ) );
return ( false );
}
bool NSEntity::HasSpawnFlags( float sf ) {
return ( spawnflags & sf ) ? true : false;
}
bool NSEntity::IsOnGround( void ) {
return ( flags & FL_ONGROUND ) ? true : false;
}
bool NSEntity::IsSolid( void ) {
return ( solid != SOLID_NOT ) ? true : false;
}
entity NSEntity::GetGroundEntity( void ) {
return ( groundentity );
}
bool NSEntity::CreatedByMap( void ) {
return ( _mapspawned );
}
#ifdef CLIENT
/*
============
NSEntity::RendererRestarted
make sure any child-classes precache their assets in here
for vid_reload calls or other sudden deaths (driver restarts)
============
*/
void NSEntity::RendererRestarted( void ) {
}
/*
============
NSEntity::ReceiveEntity
============
*/
void NSEntity::ReceiveEntity( float flNew, float flChanged ) {
READENTITY_COORD( origin[0], BASEFL_CHANGED_ORIGIN_X )
READENTITY_COORD( origin[1], BASEFL_CHANGED_ORIGIN_Y )
READENTITY_COORD( origin[2], BASEFL_CHANGED_ORIGIN_Z )
READENTITY_ANGLE( angles[0], BASEFL_CHANGED_ANGLES_X )
READENTITY_ANGLE( angles[1], BASEFL_CHANGED_ANGLES_Y )
READENTITY_ANGLE( angles[2], BASEFL_CHANGED_ANGLES_Z )
READENTITY_SHORT( modelindex, BASEFL_CHANGED_MODELINDEX )
READENTITY_BYTE( solid, BASEFL_CHANGED_SOLID )
READENTITY_BYTE( movetype, BASEFL_CHANGED_FLAGS )
READENTITY_INT( flags, BASEFL_CHANGED_FLAGS )
READENTITY_COORD( mins[0], BASEFL_CHANGED_SIZE )
READENTITY_COORD( mins[1], BASEFL_CHANGED_SIZE )
READENTITY_COORD( mins[2], BASEFL_CHANGED_SIZE )
READENTITY_COORD( maxs[0], BASEFL_CHANGED_SIZE )
READENTITY_COORD( maxs[1], BASEFL_CHANGED_SIZE )
READENTITY_COORD( maxs[2], BASEFL_CHANGED_SIZE )
READENTITY_BYTE( frame, BASEFL_CHANGED_FRAME )
READENTITY_FLOAT( skin, BASEFL_CHANGED_SKIN )
READENTITY_FLOAT( effects, BASEFL_CHANGED_EFFECTS )
READENTITY_FLOAT( scale, BASEFL_CHANGED_SCALE )
READENTITY_COORD( velocity[0], BASEFL_CHANGED_VELOCITY_X )
READENTITY_COORD( velocity[1], BASEFL_CHANGED_VELOCITY_Y )
READENTITY_COORD( velocity[2], BASEFL_CHANGED_VELOCITY_Z )
READENTITY_COORD( avelocity[0], BASEFL_CHANGED_ANGULARVELOCITY )
READENTITY_COORD( avelocity[1], BASEFL_CHANGED_ANGULARVELOCITY )
READENTITY_COORD( avelocity[2], BASEFL_CHANGED_ANGULARVELOCITY )
if ( modelindex ) {
drawmask = MASK_ENGINE;
} else {
drawmask = 0;
}
if ( scale == 0.0f )
scale = 1.0f;
if ( flChanged & BASEFL_CHANGED_SIZE )
setsize( this, mins, maxs );
setorigin( this, origin );
}
/*
============
NSEntity::postdraw
============
*/
void NSEntity::postdraw( void ) {
}
#else
/* Make sure StartFrame calls this */
float NSEntity::SendEntity( entity ePEnt, float flChanged ) {
if ( !modelindex )
return ( 0 );
if ( clienttype( ePEnt ) != CLIENTTYPE_REAL )
return ( 0 );
if ( alpha == 0.0f )
return ( 0 );
WriteByte( MSG_ENTITY, ENT_ENTITY );
/* broadcast how much data is expected to be read */
WriteFloat( MSG_ENTITY, flChanged );
SENDENTITY_COORD( origin[0], BASEFL_CHANGED_ORIGIN_X )
SENDENTITY_COORD( origin[1], BASEFL_CHANGED_ORIGIN_Y )
SENDENTITY_COORD( origin[2], BASEFL_CHANGED_ORIGIN_Z )
SENDENTITY_ANGLE( angles[0], BASEFL_CHANGED_ANGLES_X )
SENDENTITY_ANGLE( angles[1], BASEFL_CHANGED_ANGLES_Y )
SENDENTITY_ANGLE( angles[2], BASEFL_CHANGED_ANGLES_Z )
SENDENTITY_SHORT( modelindex, BASEFL_CHANGED_MODELINDEX )
SENDENTITY_BYTE( solid, BASEFL_CHANGED_SOLID )
SENDENTITY_BYTE( movetype, BASEFL_CHANGED_FLAGS )
SENDENTITY_INT( flags, BASEFL_CHANGED_FLAGS )
SENDENTITY_COORD( mins[0], BASEFL_CHANGED_SIZE )
SENDENTITY_COORD( mins[1], BASEFL_CHANGED_SIZE )
SENDENTITY_COORD( mins[2], BASEFL_CHANGED_SIZE )
SENDENTITY_COORD( maxs[0], BASEFL_CHANGED_SIZE )
SENDENTITY_COORD( maxs[1], BASEFL_CHANGED_SIZE )
SENDENTITY_COORD( maxs[2], BASEFL_CHANGED_SIZE )
SENDENTITY_BYTE( frame, BASEFL_CHANGED_FRAME )
SENDENTITY_FLOAT( skin, BASEFL_CHANGED_SKIN )
SENDENTITY_FLOAT( effects, BASEFL_CHANGED_EFFECTS )
SENDENTITY_FLOAT( scale, BASEFL_CHANGED_SCALE )
SENDENTITY_COORD( velocity[0], BASEFL_CHANGED_VELOCITY_X )
SENDENTITY_COORD( velocity[1], BASEFL_CHANGED_VELOCITY_Y )
SENDENTITY_COORD( velocity[2], BASEFL_CHANGED_VELOCITY_Z )
SENDENTITY_COORD( avelocity[0], BASEFL_CHANGED_ANGULARVELOCITY )
SENDENTITY_COORD( avelocity[1], BASEFL_CHANGED_ANGULARVELOCITY )
SENDENTITY_COORD( avelocity[2], BASEFL_CHANGED_ANGULARVELOCITY )
return ( 1 );
}
void NSEntity::EvaluateEntity( void ) {
EVALUATE_VECTOR( origin, 0, BASEFL_CHANGED_ORIGIN_X )
EVALUATE_VECTOR( origin, 1, BASEFL_CHANGED_ORIGIN_Y )
EVALUATE_VECTOR( origin, 2, BASEFL_CHANGED_ORIGIN_Z )
EVALUATE_VECTOR( angles, 0, BASEFL_CHANGED_ANGLES_X )
EVALUATE_VECTOR( angles, 1, BASEFL_CHANGED_ANGLES_Y )
EVALUATE_VECTOR( angles, 2, BASEFL_CHANGED_ANGLES_Z )
EVALUATE_FIELD( modelindex, BASEFL_CHANGED_MODELINDEX )
EVALUATE_FIELD( solid, BASEFL_CHANGED_SOLID )
EVALUATE_FIELD( movetype, BASEFL_CHANGED_FLAGS )
EVALUATE_FIELD( flags, BASEFL_CHANGED_FLAGS )
EVALUATE_VECTOR( mins, 0, BASEFL_CHANGED_SIZE )
EVALUATE_VECTOR( mins, 1, BASEFL_CHANGED_SIZE )
EVALUATE_VECTOR( mins, 2, BASEFL_CHANGED_SIZE )
EVALUATE_VECTOR( maxs, 0, BASEFL_CHANGED_SIZE )
EVALUATE_VECTOR( maxs, 1, BASEFL_CHANGED_SIZE )
EVALUATE_VECTOR( maxs, 2, BASEFL_CHANGED_SIZE )
EVALUATE_FIELD( frame, BASEFL_CHANGED_FRAME )
EVALUATE_FIELD( skin, BASEFL_CHANGED_SKIN )
EVALUATE_FIELD( effects, BASEFL_CHANGED_EFFECTS )
EVALUATE_FIELD( scale, BASEFL_CHANGED_SCALE )
EVALUATE_VECTOR( velocity, 0, BASEFL_CHANGED_VELOCITY_X )
EVALUATE_VECTOR( velocity, 1, BASEFL_CHANGED_VELOCITY_Y )
EVALUATE_VECTOR( velocity, 2, BASEFL_CHANGED_VELOCITY_Z )
EVALUATE_VECTOR( avelocity, 0, BASEFL_CHANGED_ANGULARVELOCITY )
EVALUATE_VECTOR( avelocity, 1, BASEFL_CHANGED_ANGULARVELOCITY )
EVALUATE_VECTOR( avelocity, 2, BASEFL_CHANGED_ANGULARVELOCITY )
}
/* Make sure StartFrame calls this */
void NSEntity::ParentUpdate( void ) {
EvaluateEntity();
frame1time += frametime;
if ( m_parent ) {
NSEntity parent;
entity p = find( world, ::targetname, m_parent );
if ( p ) {
if ( !m_parent_attachment ) {
parent = ( NSEntity ) p;
vector ofs = parent.origin - parent.GetSpawnOrigin();
SetOrigin( GetSpawnOrigin() + ofs );
} else if ( m_parent_attachment == "origin" ) {
SetOrigin( p.origin );
}
}
}
/* handle end-touch */
if ( m_beingTouched == true )
if ( m_flTouchTime < GetTime() ) {
EndTouch( m_eTouchLast );
m_beingTouched = false;
m_eTouchLast = __NULL__;
}
}
entity NSEntity::GetParent( void ) {
return ( find( world, ::targetname, m_parent ) );
}
void NSEntity::SetParent( string name ) {
m_parent = name;
}
void NSEntity::SetParentAttachment( string name ) {
m_parent_attachment = name;
}
void NSEntity::ClearParent( void ) {
m_parent = __NULL__;
m_parent_attachment = __NULL__;
}
void NSEntity::RestoreAngles( void ) {
angles = GetSpawnAngles();
}
void NSEntity::ClearAngles( void ) {
angles =[0, 0, 0];
}
#endif
void NSEntity::SetEffects( float newEffects ) {
effects = newEffects;
}
void NSEntity::SetFrame( float newFrame ) {
if ( newFrame == frame )
return;
frame = newFrame;
frame1time = 0.0f;
}
void NSEntity::SetSkin( float newSkin ) {
skin = newSkin;
}
void NSEntity::SetOwner( entity newOwner ) {
owner = newOwner;
}
void NSEntity::SetVelocity( vector vecNew ) {
velocity = vecNew;
}
void NSEntity::SetTouch( void ()newTouch ) {
touch = newTouch;
}
/* we want to really use those set functions because they'll notify of any
* networking related changes. otherwise we'll have to keep track of copies
* that get updated every frame */
void NSEntity::SetSendFlags( float flSendFlags ) {
#ifdef SERVER
SendFlags |= flSendFlags;
#endif
}
void NSEntity::SetMovetype( float newMovetype ) {
movetype = newMovetype;
}
void NSEntity::SetGravity( float newGrav ) {
gravity = newGrav;
}
void NSEntity::SetSolid( float newSolid ) {
solid = newSolid;
}
void NSEntity::SetScale( float newScale ) {
if ( newScale == scale )
return;
scale = newScale;
setsize( this, m_vecMins * scale, m_vecMaxs * scale );
}
void NSEntity::UpdateBounds( void ) {
vector newMins, newMaxs;
float flScale = 1.0f;
newMins = m_vecMins;
newMaxs = m_vecMaxs;
/* avoid useless computation */
if ( angles !=[0, 0, 0] ) {
/* adjust bbox according to rotation */
vector vecCorner[8];
newMins = newMaxs =[0, 0, 0];
for ( int i = 0; i < 8; i++ ) {
vecCorner[i][0] = ( i & 1 ) ? m_vecMins[0] : m_vecMaxs[0];
vecCorner[i][1] = ( i & 2 ) ? m_vecMins[1] : m_vecMaxs[1];
vecCorner[i][2] = ( i & 4 ) ? m_vecMins[2] : m_vecMaxs[2];
vecCorner[i] += origin;
vecCorner[i] = Math_RotateAroundPivot( vecCorner[i], origin, angles[1] );
vecCorner[i] -= origin;
if ( !( vecCorner[i][0] <= newMaxs[0] ) )
newMaxs[0] = vecCorner[i][0];
if ( !( vecCorner[i][1] <= newMaxs[1] ) )
newMaxs[1] = vecCorner[i][1];
if ( !( vecCorner[i][2] <= newMaxs[2] ) )
newMaxs[2] = vecCorner[i][2];
if ( !( vecCorner[i][0] >= newMins[0] ) )
newMins[0] = vecCorner[i][0];
if ( !( vecCorner[i][1] >= newMins[1] ) )
newMins[1] = vecCorner[i][1];
if ( !( vecCorner[i][2] >= newMins[2] ) )
newMins[2] = vecCorner[i][2];
}
}
/* 0.0 is never valid, if you want it to disappear do something else */
if ( scale != 0.0 )
flScale = scale;
setsize( this, newMins * flScale, newMaxs * flScale );
}
void NSEntity::SetAngles( vector newAngles ) {
angles = newAngles;
}
void NSEntity::SetAngularVelocity( vector newAvel ) {
avelocity = newAvel;
}
void NSEntity::SetSize( vector newMins, vector newMaxs ) {
float flScale = 1.0f;
m_vecMins = newMins;
m_vecMaxs = newMaxs;
/* 0.0 is never valid, if you want it to disappear do something else */
if ( scale != 0.0f )
flScale = scale;
setsize( this, newMins * flScale, newMaxs * flScale );
}
void NSEntity::SetOrigin( vector newOrigin ) {
setorigin( this, newOrigin );
}
void NSEntity::SetModel( string newModel ) {
model = newModel;
setmodel( this, newModel );
/* mins/maxs have been updated by setmodel */
SetSize( mins, maxs );
}
void NSEntity::SetModelindex( float newModelIndex ) {
if ( newModelIndex == modelindex )
return;
modelindex = newModelIndex;
SetSize( mins, maxs );
}
void NSEntity::AddEffects( float fl ) {
effects |= fl;
}
void NSEntity::RemoveEffects( float fl ) {
effects &= ~fl;
}
void NSEntity::AddFlags( float fl ) {
flags |= fl;
}
void NSEntity::RemoveFlags( float fl ) {
flags &= ~fl;
}
void NSEntity::SetThink( void ( void ) func ) {
think = func;
}
void NSEntity::SetNextThink( float fl ) {
float flTime = GetTime();
/* HACK: to make sure things happen post-spawn */
if ( flTime <= 0.0f )
flTime = 0.1f;
if ( fl >= 0 )
nextthink = flTime + fl;
else
NSLog( "%s sets bogus nextthink value %f\n", classname, fl );
}
void NSEntity::ScheduleThink( void ( void ) func, float fl ) {
SetThink( func );
SetNextThink( fl );
}
vector NSEntity::GetSpawnOrigin( void ) {
return ( m_oldOrigin );
}
vector NSEntity::GetSpawnAngles( void ) {
return ( m_oldAngle );
}
string NSEntity::GetSpawnModel( void ) {
return ( m_oldModel );
}
float NSEntity::GetEffects( void ) {
return ( effects );
}
float NSEntity::GetFrame( void ) {
return ( frame );
}
float NSEntity::GetSkin( void ) {
return ( skin );
}
float NSEntity::GetScale( void ) {
return ( scale );
}
entity NSEntity::GetOwner( void ) {
return ( owner );
}
vector NSEntity::GetVelocity( void ) {
return ( velocity );
}
float NSEntity::GetSolid( void ) {
return ( solid );
}
string NSEntity::GetModel( void ) {
return ( model );
}
float NSEntity::GetModelindex( void ) {
return ( modelindex );
}
float NSEntity::GetMovetype( void ) {
return ( movetype );
}
float NSEntity::GetGravity( void ) {
return ( gravity );
}
vector NSEntity::GetAngles( void ) {
return ( angles );
}
vector NSEntity::GetAngularVelocity( void ) {
return ( avelocity );
}
vector NSEntity::GetOrigin( void ) {
return ( origin );
}
vector NSEntity::GetMins( void ) {
return ( mins );
}
vector NSEntity::GetMaxs( void ) {
return ( maxs );
}
vector NSEntity::GetRealMins( void ) {
return ( m_vecMins );
}
vector NSEntity::GetRealMaxs( void ) {
return ( m_vecMaxs );
}
vector NSEntity::GetAbsoluteMins( void ) {
return ( absmin );
}
vector NSEntity::GetAbsoluteMaxs( void ) {
return ( absmax );
}
float NSEntity::GetFlags( void ) {
return ( flags );
}
float NSEntity::GetNextThinkTime( void ) {
return ( nextthink );
}
bool NSEntity::IsThinking( void ) {
return ( nextthink > GetTime() )? true : false;
}
void NSEntity::ReleaseThink( void ) {
think = __NULL__;
nextthink = 0.0f;
}
void NSEntity::ClearVelocity( void ) {
velocity = avelocity =[0.0f, 0.0f, 0.0f];
}
#ifdef SERVER
void NSEntity::Respawn( void ) {
NSTrigger::Respawn();
SetSolid( m_oldSolid );
SetAngles( GetSpawnAngles() );
SetOrigin( GetSpawnOrigin() );
SetModel( GetSpawnModel() );
SetTriggerTarget( m_oldstrTarget ); /* FIXME: Move into NSTrigger::Respawn */
}
void NSEntity::Save( float handle ) {
super::Save( handle );
SaveFloat( handle, "pvsflags", pvsflags );
SaveFloat( handle, "_mapspawned", _mapspawned );
SaveFloat( handle, "scale", scale );
SaveVector( handle, "m_vecMins", m_vecMins );
SaveVector( handle, "m_vecMaxs", m_vecMaxs );
SaveVector( handle, "m_oldOrigin", m_oldOrigin );
SaveVector( handle, "m_oldAngle", m_oldAngle );
SaveString( handle, "m_oldModel", m_oldModel );
SaveFloat( handle, "m_oldSolid", m_oldSolid );
SaveFloat( handle, "m_flTouchTime", m_flTouchTime );
SaveBool( handle, "m_beingTouched", m_beingTouched );
SaveEntity( handle, "m_eTouchLast", m_eTouchLast );
SaveString( handle, "m_parent", m_parent );
SaveString( handle, "m_parent_attachment", m_parent_attachment );
}
void NSEntity::Restore( string strKey, string strValue ) {
switch ( strKey ) {
case "pvsflags":
pvsflags = stof( strValue );
break;
case "_mapspawned":
_mapspawned = stof( strValue );
break;
case "scale":
scale = ReadFloat( strValue );
break;
case "m_vecMins":
m_vecMins = ReadVector( strValue );
break;
case "m_vecMaxs":
m_vecMaxs = ReadVector( strValue );
break;
case "m_oldOrigin":
m_oldOrigin = ReadVector( strValue );
break;
case "m_oldAngle":
m_oldAngle = ReadVector( strValue );
break;
case "m_oldModel":
m_oldModel = ReadString( strValue );
break;
case "m_oldSolid":
m_oldSolid = ReadFloat( strValue );
break;
case "m_flTouchTime":
m_flTouchTime = ReadFloat( strValue );
break;
case "m_beingTouched":
m_beingTouched = ReadBool( strValue );
break;
case "m_eTouchLast":
m_eTouchLast = ReadEntity( strValue );
break;
case "m_parent":
m_parent = ReadString( strValue );
break;
case "m_parent_attachment":
m_parent_attachment = ReadString( strValue );
break;
default:
super::Restore( strKey, strValue );
break;
}
}
void NSEntity::RestoreComplete( void ) {
/* this is where we can handle anything post-loading */
}
void NSEntity::Input( entity eAct, string strInput, string strData ) {
switch ( strInput ) {
case "Kill":
Destroy();
break;
case "KillHierarchy":
/* this works because ents are basically just entnums */
for ( entity e = world; ( e = findfloat( e, ::owner, this ) ); ) {
NSEntity ent = ( NSEntity ) e;
ent.Destroy();
}
Destroy();
break;
case "SetParent":
SetParent( strData );
break;
case "SetParentAttachment":
SetParentAttachment( strData );
break;
case "ClearParent":
ClearParent();
break;
case "Use":
eActivator = eAct;
if ( PlayerUse )
PlayerUse();
break;
default:
NSTrigger::Input( eAct, strInput, strData );
}
}
#endif
/*
============
NSEntity::SpawnKey
note that the engine still likes to try and map key/value
pairs on its own, but we can at least undo some of that in
here if needed
============
*/
void NSEntity::SpawnKey( string strKey, string strValue ) {
/* we do re-read a lot of the builtin fields in case we want to set
defaults. just in case anybody is wondering. */
switch ( strKey ) {
case "spawnflags":
spawnflags = stof( strValue );
break;
case "origin":
origin = stov( strValue );
break;
case "model":
model = strValue;
break;
case "angles":
angles = stov( strValue );
break;
case "angle":
angles[1] = stof( strValue );
break;
case "solid":
solid = stof( strValue );
break;
#ifdef SERVER
case "health":
health = stof( strValue );
break;
case "parentname":
SetParent( strValue );
break;
case "ignorepvs":
pvsflags = PVSF_IGNOREPVS;
break;
#endif
default:
NSTrigger::SpawnKey( strKey, strValue );
break;
}
}
/*
============
OnRemoveEntity
Empty method, meant for sub-classes to clean up their contents
============
*/
void NSEntity::OnRemoveEntity( void ) {
}
/*
============
NSEntity::Destroy
Call if the entity is to be removed the next possible frame.
If you want an entity to be purged immediately, you'll have to jump
through your own hoops. This however will be sufficient 99,99% of the time.
============
*/
void NSEntity::Destroy( void ) {
OnRemoveEntity();
ScheduleThink( Util_Destroy, 0.0f );
}
void NSEntity::Show( void ) {
effects &= ~EF_NODRAW;
}
void NSEntity::Hide( void ) {
effects |= EF_NODRAW;
}
bool NSEntity::IsHidden( void ) {
return ( effects & EF_NODRAW ) ? true : false;
}
void NSEntity::Disappear( void ) {
modelindex = 0;
solid = SOLID_NOT;
}
void NSEntity::MakeStatic( void ) {
makestatic( this );
}
bool NSEntity::WithinBounds( entity check ) {
if not ( check.absmin[0] >= absmin[0] && check.absmax[0] <= absmax[0] )
return ( false );
if not ( check.absmin[1] >= absmin[1] && check.absmax[1] <= absmax[1] )
return ( false );
if not ( check.absmin[2] >= absmin[2] && check.absmax[2] <= absmax[2] )
return ( false );
return ( true );
}
bool NSEntity::StartSound( string strSample, float channel, float flags, bool broadcast ) {
if not ( whichpack( strcat( "sound/", strSample ) ) )
return ( false );
if ( broadcast ) {
sound( this, channel, strSample, 1.0, ATTN_NORM );
} else {
#ifdef SERVER
msg_entity = this;
sound( this, channel, strSample, 1.0, ATTN_NORM, 0, SOUNDFLAG_UNICAST );
msg_entity = __NULL__;
#else
sound( this, channel, strSample, 1.0, ATTN_NORM );
#endif
}
return ( true );
}
bool NSEntity::StartSoundDef( string strSample, float channel, bool broadcast ) {
NSLog( "StartSoundDef: %s %d %d", strSample, channel, broadcast );
Sound_Play( this, channel, strSample );
return ( true );
}
void NSEntity::StopSound( float channel, bool broadcast ) {
sound( this, channel, "common/null.wav", 0.1f, ATTN_NORM );
}
void NSEntity::HandleThink( void ) {
/* support for think/nextthink */
if ( think && nextthink > 0.0f ) {
if ( nextthink < time ) {
nextthink = 0.0f;
think();
}
}
}