Use
method?pev->button
flag is set (IN_USE
). This is then checked for every frame in CBasePlayer::PlayerUse
.
// Was use pressed or released?
if ( !((pev->button | m_afButtonPressed | m_afButtonReleased) & IN_USE) )
return;
If the player is/was holding it, then a certain algorithm picks an entity based on proximity and how well it is within the player's line of sight. Note that, due to the way it works, it won't always pick the entity that is under the player's crosshair. // This code is a very simplified version of the original
// player.cpp, line 1482
if ( pObject )
{
int caps = pObject->ObjectCaps();
if ( (isUsing && (caps & FCAP_CONTINUOUS_USE )) ||
(pressedUse && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) )
{
pObject->Use( this, this, USE_SET, 1 );
}
else if ( stoppedUsing && (caps & FCAP_ONOFF_USE) )
{
pObject->Use( this, this, USE_SET, 0 );
}
}
With all of the above said, it is pretty easy to figure out how to make an entity usable by the player. Just make sure it returns one of the following in ObjectCaps
:
FCAP_IMPULSE_USE
FCAP_CONTINUOUS_USE
FCAP_ONOFF_USE
class CMyEntity : public CBaseEntity
{
public:
void Spawn() override;
void Use( CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value ) override;
// This entity will be impulse-used by the player
int ObjectCaps() override { return FCAP_IMPULSE_USE; }
};
LINK_ENTITY_TO_CLASS( my_entity, CMyEntity );
// Brush entities are typically initialised like so
void CMyEntity::Spawn()
{
pev->solid = SOLID_BSP;
pev->movetype = MOVETYPE_NONE;
UTIL_SetOrigin( pev->origin );
}
// Here we detect if the activator is the player and do stuff if so
void CMyEntity::Use( CBaseEntity* pActivator, CBaseEntity* pCaller, USE_TYPE useType, float value )
{
if ( pActivator->IsPlayer() )
ALERT( at_console, "Hello, player! I see you are using me\n" );
}
Note how ObjectCaps
returns FCAP_IMPULSE_USE
and CMyEntity::Use
checks if the activator is, indeed, the player.
FCAP_IMPULSE_USE
is the button entity.
void CBaseButton::ButtonUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
if (m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN )
return;
m_hActivator = pActivator;
if ( m_toggle_state == TS_AT_TOP)
{
if (!m_fStayPushed && FBitSet(pev->spawnflags, SF_BUTTON_TOGGLE))
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, (char*)STRING(pev->noise), 1, ATTN_NORM);
ButtonReturn();
}
}
else
ButtonActivate( );
}
Every time the button is pressed, it toggles its state.
FCAP_CONTINUOUS_USE
would be health chargers and HEV chargers.CWallHealth::Use
:
// If it's not a player, ignore
if ( !pActivator->IsPlayer() )
return;
// If there is no juice left, turn it off
if ( m_iJuice <= 0 )
{
pev->frame = 1; // Changes the texture to the depleted variant
return;
}
// Time to recharge yet?
if ( m_flNextCharge >= gpGlobals->time )
return;
// Charge the player
if ( pActivator->TakeHealth( 1, DMG_GENERIC ) )
{
m_iJuice--;
}
// Govern the rate of charge
m_flNextCharge = gpGlobals->time + 0.1f;
It is also an example of a simple internal timer, so when the entity is used, it doesn't "charge" the player every frame, but rather, every 0.1 seconds.
You must log in to post a comment. You can login or register a new account.