diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/item_world.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/item_world.cpp')
| -rw-r--r-- | mp/src/game/server/item_world.cpp | 1094 |
1 files changed, 547 insertions, 547 deletions
diff --git a/mp/src/game/server/item_world.cpp b/mp/src/game/server/item_world.cpp index 9b832c8e..e4233172 100644 --- a/mp/src/game/server/item_world.cpp +++ b/mp/src/game/server/item_world.cpp @@ -1,547 +1,547 @@ -//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Handling for the base world item. Most of this was moved from items.cpp.
-//
-// $NoKeywords: $
-//===========================================================================//
-
-#include "cbase.h"
-#include "player.h"
-#include "items.h"
-#include "gamerules.h"
-#include "engine/IEngineSound.h"
-#include "iservervehicle.h"
-#include "physics_saverestore.h"
-#include "world.h"
-
-#ifdef HL2MP
-#include "hl2mp_gamerules.h"
-#endif
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include "tier0/memdbgon.h"
-
-#define ITEM_PICKUP_BOX_BLOAT 24
-
-class CWorldItem : public CBaseAnimating
-{
- DECLARE_DATADESC();
-public:
- DECLARE_CLASS( CWorldItem, CBaseAnimating );
-
- bool KeyValue( const char *szKeyName, const char *szValue );
- void Spawn( void );
-
- int m_iType;
-};
-
-LINK_ENTITY_TO_CLASS(world_items, CWorldItem);
-
-BEGIN_DATADESC( CWorldItem )
-
-DEFINE_FIELD( m_iType, FIELD_INTEGER ),
-
-END_DATADESC()
-
-
-bool CWorldItem::KeyValue( const char *szKeyName, const char *szValue )
-{
- if (FStrEq(szKeyName, "type"))
- {
- m_iType = atoi(szValue);
- }
- else
- return BaseClass::KeyValue( szKeyName, szValue );
-
- return true;
-}
-
-void CWorldItem::Spawn( void )
-{
- CBaseEntity *pEntity = NULL;
-
- switch (m_iType)
- {
- case 44: // ITEM_BATTERY:
- pEntity = CBaseEntity::Create( "item_battery", GetLocalOrigin(), GetLocalAngles() );
- break;
- case 45: // ITEM_SUIT:
- pEntity = CBaseEntity::Create( "item_suit", GetLocalOrigin(), GetLocalAngles() );
- break;
- }
-
- if (!pEntity)
- {
- Warning("unable to create world_item %d\n", m_iType );
- }
- else
- {
- pEntity->m_target = m_target;
- pEntity->SetName( GetEntityName() );
- pEntity->ClearSpawnFlags();
- pEntity->AddSpawnFlags( m_spawnflags );
- }
-
- UTIL_RemoveImmediate( this );
-}
-
-
-BEGIN_DATADESC( CItem )
-
- DEFINE_FIELD( m_bActivateWhenAtRest, FIELD_BOOLEAN ),
- DEFINE_FIELD( m_vOriginalSpawnOrigin, FIELD_POSITION_VECTOR ),
- DEFINE_FIELD( m_vOriginalSpawnAngles, FIELD_VECTOR ),
- DEFINE_PHYSPTR( m_pConstraint ),
-
- // Function Pointers
- DEFINE_ENTITYFUNC( ItemTouch ),
- DEFINE_THINKFUNC( Materialize ),
- DEFINE_THINKFUNC( ComeToRest ),
-
-#if defined( HL2MP ) || defined( TF_DLL )
- DEFINE_FIELD( m_flNextResetCheckTime, FIELD_TIME ),
- DEFINE_THINKFUNC( FallThink ),
-#endif
-
- // Outputs
- DEFINE_OUTPUT( m_OnPlayerTouch, "OnPlayerTouch" ),
- DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ),
-
-END_DATADESC()
-
-
-//-----------------------------------------------------------------------------
-// Constructor
-//-----------------------------------------------------------------------------
-CItem::CItem()
-{
- m_bActivateWhenAtRest = false;
-}
-
-bool CItem::CreateItemVPhysicsObject( void )
-{
- // Create the object in the physics system
- int nSolidFlags = GetSolidFlags() | FSOLID_NOT_STANDABLE;
- if ( !m_bActivateWhenAtRest )
- {
- nSolidFlags |= FSOLID_TRIGGER;
- }
-
- if ( VPhysicsInitNormal( SOLID_VPHYSICS, nSolidFlags, false ) == NULL )
- {
- SetSolid( SOLID_BBOX );
- AddSolidFlags( nSolidFlags );
-
- // If it's not physical, drop it to the floor
- if (UTIL_DropToFloor(this, MASK_SOLID) == 0)
- {
- Warning( "Item %s fell out of level at %f,%f,%f\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z);
- UTIL_Remove( this );
- return false;
- }
- }
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CItem::Spawn( void )
-{
- if ( g_pGameRules->IsAllowedToSpawn( this ) == false )
- {
- UTIL_Remove( this );
- return;
- }
-
- SetMoveType( MOVETYPE_FLYGRAVITY );
- SetSolid( SOLID_BBOX );
- SetBlocksLOS( false );
- AddEFlags( EFL_NO_ROTORWASH_PUSH );
-
- if( IsX360() )
- {
- AddEffects( EF_ITEM_BLINK );
- }
-
- // This will make them not collide with the player, but will collide
- // against other items + weapons
- SetCollisionGroup( COLLISION_GROUP_WEAPON );
- CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT );
- SetTouch(&CItem::ItemTouch);
-
- if ( CreateItemVPhysicsObject() == false )
- return;
-
- m_takedamage = DAMAGE_EVENTS_ONLY;
-
-#if !defined( CLIENT_DLL )
- // Constrained start?
- if ( HasSpawnFlags( SF_ITEM_START_CONSTRAINED ) )
- {
- //Constrain the weapon in place
- IPhysicsObject *pReferenceObject, *pAttachedObject;
-
- pReferenceObject = g_PhysWorldObject;
- pAttachedObject = VPhysicsGetObject();
-
- if ( pReferenceObject && pAttachedObject )
- {
- constraint_fixedparams_t fixed;
- fixed.Defaults();
- fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject );
-
- fixed.constraint.forceLimit = lbs2kg( 10000 );
- fixed.constraint.torqueLimit = lbs2kg( 10000 );
-
- m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed );
-
- m_pConstraint->SetGameData( (void *) this );
- }
- }
-#endif //CLIENT_DLL
-
-#if defined( HL2MP ) || defined( TF_DLL )
- SetThink( &CItem::FallThink );
- SetNextThink( gpGlobals->curtime + 0.1f );
-#endif
-}
-
-unsigned int CItem::PhysicsSolidMaskForEntity( void ) const
-{
- return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_PLAYERCLIP;
-}
-
-void CItem::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
-{
- CBasePlayer *pPlayer = ToBasePlayer( pActivator );
-
- if ( pPlayer )
- {
- pPlayer->PickupObject( this );
- }
-}
-
-extern int gEvilImpulse101;
-
-
-//-----------------------------------------------------------------------------
-// Activate when at rest, but don't allow pickup until then
-//-----------------------------------------------------------------------------
-void CItem::ActivateWhenAtRest( float flTime /* = 0.5f */ )
-{
- RemoveSolidFlags( FSOLID_TRIGGER );
- m_bActivateWhenAtRest = true;
- SetThink( &CItem::ComeToRest );
- SetNextThink( gpGlobals->curtime + flTime );
-}
-
-
-//-----------------------------------------------------------------------------
-// Become touchable when we are at rest
-//-----------------------------------------------------------------------------
-void CItem::OnEntityEvent( EntityEvent_t event, void *pEventData )
-{
- BaseClass::OnEntityEvent( event, pEventData );
-
- switch( event )
- {
- case ENTITY_EVENT_WATER_TOUCH:
- {
- // Delay rest for a sec, to avoid changing collision
- // properties inside a collision callback.
- SetThink( &CItem::ComeToRest );
- SetNextThink( gpGlobals->curtime + 0.1f );
- }
- break;
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Become touchable when we are at rest
-//-----------------------------------------------------------------------------
-void CItem::ComeToRest( void )
-{
- if ( m_bActivateWhenAtRest )
- {
- m_bActivateWhenAtRest = false;
- AddSolidFlags( FSOLID_TRIGGER );
- SetThink( NULL );
- }
-}
-
-#if defined( HL2MP ) || defined( TF_DLL )
-
-//-----------------------------------------------------------------------------
-// Purpose: Items that have just spawned run this think to catch them when
-// they hit the ground. Once we're sure that the object is grounded,
-// we change its solid type to trigger and set it in a large box that
-// helps the player get it.
-//-----------------------------------------------------------------------------
-void CItem::FallThink ( void )
-{
- SetNextThink( gpGlobals->curtime + 0.1f );
-
-#if defined( HL2MP )
- bool shouldMaterialize = false;
- IPhysicsObject *pPhysics = VPhysicsGetObject();
- if ( pPhysics )
- {
- shouldMaterialize = pPhysics->IsAsleep();
- }
- else
- {
- shouldMaterialize = (GetFlags() & FL_ONGROUND) ? true : false;
- }
-
- if ( shouldMaterialize )
- {
- SetThink ( NULL );
-
- m_vOriginalSpawnOrigin = GetAbsOrigin();
- m_vOriginalSpawnAngles = GetAbsAngles();
-
- HL2MPRules()->AddLevelDesignerPlacedObject( this );
- }
-#endif // HL2MP
-
-#if defined( TF_DLL )
- // We only come here if ActivateWhenAtRest() is never called,
- // which is the case when creating currencypacks in MvM
- if ( !( GetFlags() & FL_ONGROUND ) )
- {
- if ( !GetAbsVelocity().Length() && GetMoveType() == MOVETYPE_FLYGRAVITY )
- {
- // Mr. Game, meet Mr. Hammer. Mr. Hammer, meet the uncooperative Mr. Physics.
- // Mr. Physics really doesn't want to give our friend the FL_ONGROUND flag.
- // This means our wonderfully helpful radius currency collection code will be sad.
- // So in the name of justice, we ask that this flag be delivered unto him.
-
- SetMoveType( MOVETYPE_NONE );
- SetGroundEntity( GetWorldEntity() );
- }
- }
- else
- {
- SetThink( &CItem::ComeToRest );
- }
-#endif // TF
-}
-
-#endif // HL2MP, TF
-
-//-----------------------------------------------------------------------------
-// Purpose: Used to tell whether an item may be picked up by the player. This
-// accounts for solid obstructions being in the way.
-// Input : *pItem - item in question
-// *pPlayer - player attempting the pickup
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer )
-{
- if ( pItem == NULL || pPlayer == NULL )
- return false;
-
- // For now, always allow a vehicle riding player to pick up things they're driving over
- if ( pPlayer->IsInAVehicle() )
- return true;
-
- // Get our test positions
- Vector vecStartPos;
- IPhysicsObject *pPhysObj = pItem->VPhysicsGetObject();
- if ( pPhysObj != NULL )
- {
- // Use the physics hull's center
- QAngle vecAngles;
- pPhysObj->GetPosition( &vecStartPos, &vecAngles );
- }
- else
- {
- // Use the generic bbox center
- vecStartPos = pItem->CollisionProp()->WorldSpaceCenter();
- }
-
- Vector vecEndPos = pPlayer->EyePosition();
-
- // FIXME: This is the simple first try solution towards the problem. We need to take edges and shape more into account
- // for this to be fully robust.
-
- // Trace between to see if we're occluded
- trace_t tr;
- CTraceFilterSkipTwoEntities filter( pPlayer, pItem, COLLISION_GROUP_PLAYER_MOVEMENT );
- UTIL_TraceLine( vecStartPos, vecEndPos, MASK_SOLID, &filter, &tr );
-
- // Occluded
- // FIXME: For now, we exclude starting in solid because there are cases where this doesn't matter
- if ( tr.fraction < 1.0f )
- return false;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Whether or not the item can be touched and picked up by the player, taking
-// into account obstructions and other hinderances
-// Output : Returns true on success, false on failure.
-//-----------------------------------------------------------------------------
-bool CItem::ItemCanBeTouchedByPlayer( CBasePlayer *pPlayer )
-{
- return UTIL_ItemCanBeTouchedByPlayer( this, pPlayer );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : pOther -
-//-----------------------------------------------------------------------------
-void CItem::ItemTouch( CBaseEntity *pOther )
-{
- // Vehicles can touch items + pick them up
- if ( pOther->GetServerVehicle() )
- {
- pOther = pOther->GetServerVehicle()->GetPassenger();
- if ( !pOther )
- return;
- }
-
- // if it's not a player, ignore
- if ( !pOther->IsPlayer() )
- return;
-
- CBasePlayer *pPlayer = (CBasePlayer *)pOther;
-
- // Must be a valid pickup scenario (no blocking). Though this is a more expensive
- // check than some that follow, this has to be first Obecause it's the only one
- // that inhibits firing the output OnCacheInteraction.
- if ( ItemCanBeTouchedByPlayer( pPlayer ) == false )
- return;
-
- m_OnCacheInteraction.FireOutput(pOther, this);
-
- // Can I even pick stuff up?
- if ( !pPlayer->IsAllowedToPickupWeapons() )
- return;
-
- // ok, a player is touching this item, but can he have it?
- if ( !g_pGameRules->CanHaveItem( pPlayer, this ) )
- {
- // no? Ignore the touch.
- return;
- }
-
- if ( MyTouch( pPlayer ) )
- {
- m_OnPlayerTouch.FireOutput(pOther, this);
-
- SetTouch( NULL );
- SetThink( NULL );
-
- // player grabbed the item.
- g_pGameRules->PlayerGotItem( pPlayer, this );
- if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_YES )
- {
- Respawn();
- }
- else
- {
- UTIL_Remove( this );
-
-#ifdef HL2MP
- HL2MPRules()->RemoveLevelDesignerPlacedObject( this );
-#endif
- }
- }
- else if (gEvilImpulse101)
- {
- UTIL_Remove( this );
- }
-}
-
-CBaseEntity* CItem::Respawn( void )
-{
- SetTouch( NULL );
- AddEffects( EF_NODRAW );
-
- VPhysicsDestroyObject();
-
- SetMoveType( MOVETYPE_NONE );
- SetSolid( SOLID_BBOX );
- AddSolidFlags( FSOLID_TRIGGER );
-
- UTIL_SetOrigin( this, g_pGameRules->VecItemRespawnSpot( this ) );// blip to whereever you should respawn.
- SetAbsAngles( g_pGameRules->VecItemRespawnAngles( this ) );// set the angles.
-
-#if !defined( TF_DLL )
- UTIL_DropToFloor( this, MASK_SOLID );
-#endif
-
- RemoveAllDecals(); //remove any decals
-
- SetThink ( &CItem::Materialize );
- SetNextThink( gpGlobals->curtime + g_pGameRules->FlItemRespawnTime( this ) );
- return this;
-}
-
-void CItem::Materialize( void )
-{
- CreateItemVPhysicsObject();
-
- if ( IsEffectActive( EF_NODRAW ) )
- {
- // changing from invisible state to visible.
-
-#ifdef HL2MP
- EmitSound( "AlyxEmp.Charge" );
-#else
- EmitSound( "Item.Materialize" );
-#endif
- RemoveEffects( EF_NODRAW );
- DoMuzzleFlash();
- }
-
- SetTouch( &CItem::ItemTouch );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-void CItem::Precache()
-{
- BaseClass::Precache();
-
- PrecacheScriptSound( "Item.Materialize" );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pPhysGunUser -
-// PICKED_UP_BY_CANNON -
-//-----------------------------------------------------------------------------
-void CItem::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason )
-{
- m_OnCacheInteraction.FireOutput(pPhysGunUser, this);
-
- if ( reason == PICKED_UP_BY_CANNON )
- {
- // Expand the pickup box
- CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT * 2 );
-
- if( m_pConstraint != NULL )
- {
- physenv->DestroyConstraint( m_pConstraint );
- m_pConstraint = NULL;
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-// Input : *pPhysGunUser -
-// reason -
-//-----------------------------------------------------------------------------
-void CItem::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason )
-{
- // Restore the pickup box to the original
- CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT );
-}
+//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Handling for the base world item. Most of this was moved from items.cpp. +// +// $NoKeywords: $ +//===========================================================================// + +#include "cbase.h" +#include "player.h" +#include "items.h" +#include "gamerules.h" +#include "engine/IEngineSound.h" +#include "iservervehicle.h" +#include "physics_saverestore.h" +#include "world.h" + +#ifdef HL2MP +#include "hl2mp_gamerules.h" +#endif + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#define ITEM_PICKUP_BOX_BLOAT 24 + +class CWorldItem : public CBaseAnimating +{ + DECLARE_DATADESC(); +public: + DECLARE_CLASS( CWorldItem, CBaseAnimating ); + + bool KeyValue( const char *szKeyName, const char *szValue ); + void Spawn( void ); + + int m_iType; +}; + +LINK_ENTITY_TO_CLASS(world_items, CWorldItem); + +BEGIN_DATADESC( CWorldItem ) + +DEFINE_FIELD( m_iType, FIELD_INTEGER ), + +END_DATADESC() + + +bool CWorldItem::KeyValue( const char *szKeyName, const char *szValue ) +{ + if (FStrEq(szKeyName, "type")) + { + m_iType = atoi(szValue); + } + else + return BaseClass::KeyValue( szKeyName, szValue ); + + return true; +} + +void CWorldItem::Spawn( void ) +{ + CBaseEntity *pEntity = NULL; + + switch (m_iType) + { + case 44: // ITEM_BATTERY: + pEntity = CBaseEntity::Create( "item_battery", GetLocalOrigin(), GetLocalAngles() ); + break; + case 45: // ITEM_SUIT: + pEntity = CBaseEntity::Create( "item_suit", GetLocalOrigin(), GetLocalAngles() ); + break; + } + + if (!pEntity) + { + Warning("unable to create world_item %d\n", m_iType ); + } + else + { + pEntity->m_target = m_target; + pEntity->SetName( GetEntityName() ); + pEntity->ClearSpawnFlags(); + pEntity->AddSpawnFlags( m_spawnflags ); + } + + UTIL_RemoveImmediate( this ); +} + + +BEGIN_DATADESC( CItem ) + + DEFINE_FIELD( m_bActivateWhenAtRest, FIELD_BOOLEAN ), + DEFINE_FIELD( m_vOriginalSpawnOrigin, FIELD_POSITION_VECTOR ), + DEFINE_FIELD( m_vOriginalSpawnAngles, FIELD_VECTOR ), + DEFINE_PHYSPTR( m_pConstraint ), + + // Function Pointers + DEFINE_ENTITYFUNC( ItemTouch ), + DEFINE_THINKFUNC( Materialize ), + DEFINE_THINKFUNC( ComeToRest ), + +#if defined( HL2MP ) || defined( TF_DLL ) + DEFINE_FIELD( m_flNextResetCheckTime, FIELD_TIME ), + DEFINE_THINKFUNC( FallThink ), +#endif + + // Outputs + DEFINE_OUTPUT( m_OnPlayerTouch, "OnPlayerTouch" ), + DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ), + +END_DATADESC() + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CItem::CItem() +{ + m_bActivateWhenAtRest = false; +} + +bool CItem::CreateItemVPhysicsObject( void ) +{ + // Create the object in the physics system + int nSolidFlags = GetSolidFlags() | FSOLID_NOT_STANDABLE; + if ( !m_bActivateWhenAtRest ) + { + nSolidFlags |= FSOLID_TRIGGER; + } + + if ( VPhysicsInitNormal( SOLID_VPHYSICS, nSolidFlags, false ) == NULL ) + { + SetSolid( SOLID_BBOX ); + AddSolidFlags( nSolidFlags ); + + // If it's not physical, drop it to the floor + if (UTIL_DropToFloor(this, MASK_SOLID) == 0) + { + Warning( "Item %s fell out of level at %f,%f,%f\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z); + UTIL_Remove( this ); + return false; + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItem::Spawn( void ) +{ + if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) + { + UTIL_Remove( this ); + return; + } + + SetMoveType( MOVETYPE_FLYGRAVITY ); + SetSolid( SOLID_BBOX ); + SetBlocksLOS( false ); + AddEFlags( EFL_NO_ROTORWASH_PUSH ); + + if( IsX360() ) + { + AddEffects( EF_ITEM_BLINK ); + } + + // This will make them not collide with the player, but will collide + // against other items + weapons + SetCollisionGroup( COLLISION_GROUP_WEAPON ); + CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); + SetTouch(&CItem::ItemTouch); + + if ( CreateItemVPhysicsObject() == false ) + return; + + m_takedamage = DAMAGE_EVENTS_ONLY; + +#if !defined( CLIENT_DLL ) + // Constrained start? + if ( HasSpawnFlags( SF_ITEM_START_CONSTRAINED ) ) + { + //Constrain the weapon in place + IPhysicsObject *pReferenceObject, *pAttachedObject; + + pReferenceObject = g_PhysWorldObject; + pAttachedObject = VPhysicsGetObject(); + + if ( pReferenceObject && pAttachedObject ) + { + constraint_fixedparams_t fixed; + fixed.Defaults(); + fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject ); + + fixed.constraint.forceLimit = lbs2kg( 10000 ); + fixed.constraint.torqueLimit = lbs2kg( 10000 ); + + m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed ); + + m_pConstraint->SetGameData( (void *) this ); + } + } +#endif //CLIENT_DLL + +#if defined( HL2MP ) || defined( TF_DLL ) + SetThink( &CItem::FallThink ); + SetNextThink( gpGlobals->curtime + 0.1f ); +#endif +} + +unsigned int CItem::PhysicsSolidMaskForEntity( void ) const +{ + return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_PLAYERCLIP; +} + +void CItem::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) +{ + CBasePlayer *pPlayer = ToBasePlayer( pActivator ); + + if ( pPlayer ) + { + pPlayer->PickupObject( this ); + } +} + +extern int gEvilImpulse101; + + +//----------------------------------------------------------------------------- +// Activate when at rest, but don't allow pickup until then +//----------------------------------------------------------------------------- +void CItem::ActivateWhenAtRest( float flTime /* = 0.5f */ ) +{ + RemoveSolidFlags( FSOLID_TRIGGER ); + m_bActivateWhenAtRest = true; + SetThink( &CItem::ComeToRest ); + SetNextThink( gpGlobals->curtime + flTime ); +} + + +//----------------------------------------------------------------------------- +// Become touchable when we are at rest +//----------------------------------------------------------------------------- +void CItem::OnEntityEvent( EntityEvent_t event, void *pEventData ) +{ + BaseClass::OnEntityEvent( event, pEventData ); + + switch( event ) + { + case ENTITY_EVENT_WATER_TOUCH: + { + // Delay rest for a sec, to avoid changing collision + // properties inside a collision callback. + SetThink( &CItem::ComeToRest ); + SetNextThink( gpGlobals->curtime + 0.1f ); + } + break; + } +} + + +//----------------------------------------------------------------------------- +// Become touchable when we are at rest +//----------------------------------------------------------------------------- +void CItem::ComeToRest( void ) +{ + if ( m_bActivateWhenAtRest ) + { + m_bActivateWhenAtRest = false; + AddSolidFlags( FSOLID_TRIGGER ); + SetThink( NULL ); + } +} + +#if defined( HL2MP ) || defined( TF_DLL ) + +//----------------------------------------------------------------------------- +// Purpose: Items that have just spawned run this think to catch them when +// they hit the ground. Once we're sure that the object is grounded, +// we change its solid type to trigger and set it in a large box that +// helps the player get it. +//----------------------------------------------------------------------------- +void CItem::FallThink ( void ) +{ + SetNextThink( gpGlobals->curtime + 0.1f ); + +#if defined( HL2MP ) + bool shouldMaterialize = false; + IPhysicsObject *pPhysics = VPhysicsGetObject(); + if ( pPhysics ) + { + shouldMaterialize = pPhysics->IsAsleep(); + } + else + { + shouldMaterialize = (GetFlags() & FL_ONGROUND) ? true : false; + } + + if ( shouldMaterialize ) + { + SetThink ( NULL ); + + m_vOriginalSpawnOrigin = GetAbsOrigin(); + m_vOriginalSpawnAngles = GetAbsAngles(); + + HL2MPRules()->AddLevelDesignerPlacedObject( this ); + } +#endif // HL2MP + +#if defined( TF_DLL ) + // We only come here if ActivateWhenAtRest() is never called, + // which is the case when creating currencypacks in MvM + if ( !( GetFlags() & FL_ONGROUND ) ) + { + if ( !GetAbsVelocity().Length() && GetMoveType() == MOVETYPE_FLYGRAVITY ) + { + // Mr. Game, meet Mr. Hammer. Mr. Hammer, meet the uncooperative Mr. Physics. + // Mr. Physics really doesn't want to give our friend the FL_ONGROUND flag. + // This means our wonderfully helpful radius currency collection code will be sad. + // So in the name of justice, we ask that this flag be delivered unto him. + + SetMoveType( MOVETYPE_NONE ); + SetGroundEntity( GetWorldEntity() ); + } + } + else + { + SetThink( &CItem::ComeToRest ); + } +#endif // TF +} + +#endif // HL2MP, TF + +//----------------------------------------------------------------------------- +// Purpose: Used to tell whether an item may be picked up by the player. This +// accounts for solid obstructions being in the way. +// Input : *pItem - item in question +// *pPlayer - player attempting the pickup +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer ) +{ + if ( pItem == NULL || pPlayer == NULL ) + return false; + + // For now, always allow a vehicle riding player to pick up things they're driving over + if ( pPlayer->IsInAVehicle() ) + return true; + + // Get our test positions + Vector vecStartPos; + IPhysicsObject *pPhysObj = pItem->VPhysicsGetObject(); + if ( pPhysObj != NULL ) + { + // Use the physics hull's center + QAngle vecAngles; + pPhysObj->GetPosition( &vecStartPos, &vecAngles ); + } + else + { + // Use the generic bbox center + vecStartPos = pItem->CollisionProp()->WorldSpaceCenter(); + } + + Vector vecEndPos = pPlayer->EyePosition(); + + // FIXME: This is the simple first try solution towards the problem. We need to take edges and shape more into account + // for this to be fully robust. + + // Trace between to see if we're occluded + trace_t tr; + CTraceFilterSkipTwoEntities filter( pPlayer, pItem, COLLISION_GROUP_PLAYER_MOVEMENT ); + UTIL_TraceLine( vecStartPos, vecEndPos, MASK_SOLID, &filter, &tr ); + + // Occluded + // FIXME: For now, we exclude starting in solid because there are cases where this doesn't matter + if ( tr.fraction < 1.0f ) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Whether or not the item can be touched and picked up by the player, taking +// into account obstructions and other hinderances +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CItem::ItemCanBeTouchedByPlayer( CBasePlayer *pPlayer ) +{ + return UTIL_ItemCanBeTouchedByPlayer( this, pPlayer ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pOther - +//----------------------------------------------------------------------------- +void CItem::ItemTouch( CBaseEntity *pOther ) +{ + // Vehicles can touch items + pick them up + if ( pOther->GetServerVehicle() ) + { + pOther = pOther->GetServerVehicle()->GetPassenger(); + if ( !pOther ) + return; + } + + // if it's not a player, ignore + if ( !pOther->IsPlayer() ) + return; + + CBasePlayer *pPlayer = (CBasePlayer *)pOther; + + // Must be a valid pickup scenario (no blocking). Though this is a more expensive + // check than some that follow, this has to be first Obecause it's the only one + // that inhibits firing the output OnCacheInteraction. + if ( ItemCanBeTouchedByPlayer( pPlayer ) == false ) + return; + + m_OnCacheInteraction.FireOutput(pOther, this); + + // Can I even pick stuff up? + if ( !pPlayer->IsAllowedToPickupWeapons() ) + return; + + // ok, a player is touching this item, but can he have it? + if ( !g_pGameRules->CanHaveItem( pPlayer, this ) ) + { + // no? Ignore the touch. + return; + } + + if ( MyTouch( pPlayer ) ) + { + m_OnPlayerTouch.FireOutput(pOther, this); + + SetTouch( NULL ); + SetThink( NULL ); + + // player grabbed the item. + g_pGameRules->PlayerGotItem( pPlayer, this ); + if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_YES ) + { + Respawn(); + } + else + { + UTIL_Remove( this ); + +#ifdef HL2MP + HL2MPRules()->RemoveLevelDesignerPlacedObject( this ); +#endif + } + } + else if (gEvilImpulse101) + { + UTIL_Remove( this ); + } +} + +CBaseEntity* CItem::Respawn( void ) +{ + SetTouch( NULL ); + AddEffects( EF_NODRAW ); + + VPhysicsDestroyObject(); + + SetMoveType( MOVETYPE_NONE ); + SetSolid( SOLID_BBOX ); + AddSolidFlags( FSOLID_TRIGGER ); + + UTIL_SetOrigin( this, g_pGameRules->VecItemRespawnSpot( this ) );// blip to whereever you should respawn. + SetAbsAngles( g_pGameRules->VecItemRespawnAngles( this ) );// set the angles. + +#if !defined( TF_DLL ) + UTIL_DropToFloor( this, MASK_SOLID ); +#endif + + RemoveAllDecals(); //remove any decals + + SetThink ( &CItem::Materialize ); + SetNextThink( gpGlobals->curtime + g_pGameRules->FlItemRespawnTime( this ) ); + return this; +} + +void CItem::Materialize( void ) +{ + CreateItemVPhysicsObject(); + + if ( IsEffectActive( EF_NODRAW ) ) + { + // changing from invisible state to visible. + +#ifdef HL2MP + EmitSound( "AlyxEmp.Charge" ); +#else + EmitSound( "Item.Materialize" ); +#endif + RemoveEffects( EF_NODRAW ); + DoMuzzleFlash(); + } + + SetTouch( &CItem::ItemTouch ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CItem::Precache() +{ + BaseClass::Precache(); + + PrecacheScriptSound( "Item.Materialize" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pPhysGunUser - +// PICKED_UP_BY_CANNON - +//----------------------------------------------------------------------------- +void CItem::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) +{ + m_OnCacheInteraction.FireOutput(pPhysGunUser, this); + + if ( reason == PICKED_UP_BY_CANNON ) + { + // Expand the pickup box + CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT * 2 ); + + if( m_pConstraint != NULL ) + { + physenv->DestroyConstraint( m_pConstraint ); + m_pConstraint = NULL; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pPhysGunUser - +// reason - +//----------------------------------------------------------------------------- +void CItem::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ) +{ + // Restore the pickup box to the original + CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); +} |