mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-05 22:09:59 +03:00
1
This commit is contained in:
276
game/server/hl2/item_itemcrate.cpp
Normal file
276
game/server/hl2/item_itemcrate.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: The various ammo types for HL2
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "props.h"
|
||||
#include "items.h"
|
||||
#include "item_dynamic_resupply.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
const char *pszItemCrateModelName[] =
|
||||
{
|
||||
"models/items/item_item_crate.mdl",
|
||||
"models/items/item_beacon_crate.mdl",
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A breakable crate that drops items
|
||||
//-----------------------------------------------------------------------------
|
||||
class CItem_ItemCrate : public CPhysicsProp
|
||||
{
|
||||
public:
|
||||
DECLARE_CLASS( CItem_ItemCrate, CPhysicsProp );
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void Precache( void );
|
||||
void Spawn( void );
|
||||
|
||||
virtual int ObjectCaps() { return BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; };
|
||||
|
||||
virtual int OnTakeDamage( const CTakeDamageInfo &info );
|
||||
|
||||
void InputKill( inputdata_t &data );
|
||||
|
||||
virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent );
|
||||
virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
|
||||
|
||||
protected:
|
||||
virtual void OnBreak( const Vector &vecVelocity, const AngularImpulse &angVel, CBaseEntity *pBreaker );
|
||||
|
||||
private:
|
||||
// Crate types. Add more!
|
||||
enum CrateType_t
|
||||
{
|
||||
CRATE_SPECIFIC_ITEM = 0,
|
||||
CRATE_TYPE_COUNT,
|
||||
};
|
||||
|
||||
enum CrateAppearance_t
|
||||
{
|
||||
CRATE_APPEARANCE_DEFAULT = 0,
|
||||
CRATE_APPEARANCE_RADAR_BEACON,
|
||||
};
|
||||
|
||||
private:
|
||||
CrateType_t m_CrateType;
|
||||
string_t m_strItemClass;
|
||||
int m_nItemCount;
|
||||
string_t m_strAlternateMaster;
|
||||
CrateAppearance_t m_CrateAppearance;
|
||||
|
||||
COutputEvent m_OnCacheInteraction;
|
||||
};
|
||||
|
||||
|
||||
LINK_ENTITY_TO_CLASS(item_item_crate, CItem_ItemCrate);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save/load:
|
||||
//-----------------------------------------------------------------------------
|
||||
BEGIN_DATADESC( CItem_ItemCrate )
|
||||
|
||||
DEFINE_KEYFIELD( m_CrateType, FIELD_INTEGER, "CrateType" ),
|
||||
DEFINE_KEYFIELD( m_strItemClass, FIELD_STRING, "ItemClass" ),
|
||||
DEFINE_KEYFIELD( m_nItemCount, FIELD_INTEGER, "ItemCount" ),
|
||||
DEFINE_KEYFIELD( m_strAlternateMaster, FIELD_STRING, "SpecificResupply" ),
|
||||
DEFINE_KEYFIELD( m_CrateAppearance, FIELD_INTEGER, "CrateAppearance" ),
|
||||
DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ),
|
||||
DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ),
|
||||
|
||||
END_DATADESC()
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItem_ItemCrate::Precache( void )
|
||||
{
|
||||
// Set this here to quiet base prop warnings
|
||||
PrecacheModel( pszItemCrateModelName[m_CrateAppearance] );
|
||||
SetModel( pszItemCrateModelName[m_CrateAppearance] );
|
||||
|
||||
BaseClass::Precache();
|
||||
if ( m_CrateType == CRATE_SPECIFIC_ITEM )
|
||||
{
|
||||
if ( NULL_STRING != m_strItemClass )
|
||||
{
|
||||
// Don't precache if this is a null string.
|
||||
UTIL_PrecacheOther( STRING(m_strItemClass) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItem_ItemCrate::Spawn( void )
|
||||
{
|
||||
if ( g_pGameRules->IsAllowedToSpawn( this ) == false )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
DisableAutoFade();
|
||||
SetModelName( AllocPooledString( pszItemCrateModelName[m_CrateAppearance] ) );
|
||||
|
||||
if ( NULL_STRING == m_strItemClass )
|
||||
{
|
||||
Warning( "CItem_ItemCrate(%i): CRATE_SPECIFIC_ITEM with NULL ItemClass string (deleted)!!!\n", entindex() );
|
||||
UTIL_Remove( this );
|
||||
return;
|
||||
}
|
||||
|
||||
Precache( );
|
||||
SetModel( pszItemCrateModelName[m_CrateAppearance] );
|
||||
AddEFlags( EFL_NO_ROTORWASH_PUSH );
|
||||
BaseClass::Spawn( );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : &data -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItem_ItemCrate::InputKill( inputdata_t &data )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Item crates blow up immediately
|
||||
//-----------------------------------------------------------------------------
|
||||
int CItem_ItemCrate::OnTakeDamage( const CTakeDamageInfo &info )
|
||||
{
|
||||
if ( info.GetDamageType() & DMG_AIRBOAT )
|
||||
{
|
||||
CTakeDamageInfo dmgInfo = info;
|
||||
dmgInfo.ScaleDamage( 10.0 );
|
||||
return BaseClass::OnTakeDamage( dmgInfo );
|
||||
}
|
||||
|
||||
return BaseClass::OnTakeDamage( info );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItem_ItemCrate::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent )
|
||||
{
|
||||
float flDamageScale = 1.0f;
|
||||
if ( FClassnameIs( pEvent->pEntities[!index], "prop_vehicle_airboat" ) ||
|
||||
FClassnameIs( pEvent->pEntities[!index], "prop_vehicle_jeep" ) )
|
||||
{
|
||||
flDamageScale = 100.0f;
|
||||
}
|
||||
|
||||
m_impactEnergyScale *= flDamageScale;
|
||||
BaseClass::VPhysicsCollision( index, pEvent );
|
||||
m_impactEnergyScale /= flDamageScale;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CItem_ItemCrate::OnBreak( const Vector &vecVelocity, const AngularImpulse &angImpulse, CBaseEntity *pBreaker )
|
||||
{
|
||||
// FIXME: We could simply store the name of an entity to put into the crate
|
||||
// as a string entered in by worldcraft. Should we? I'd do it for sure
|
||||
// if it was easy to get a dropdown with all entity types in it.
|
||||
|
||||
m_OnCacheInteraction.FireOutput(pBreaker,this);
|
||||
|
||||
for ( int i = 0; i < m_nItemCount; ++i )
|
||||
{
|
||||
CBaseEntity *pSpawn = NULL;
|
||||
switch( m_CrateType )
|
||||
{
|
||||
case CRATE_SPECIFIC_ITEM:
|
||||
pSpawn = CreateEntityByName( STRING(m_strItemClass) );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !pSpawn )
|
||||
return;
|
||||
|
||||
// Give a little randomness...
|
||||
Vector vecOrigin;
|
||||
CollisionProp()->RandomPointInBounds( Vector(0.25, 0.25, 0.25), Vector( 0.75, 0.75, 0.75 ), &vecOrigin );
|
||||
pSpawn->SetAbsOrigin( vecOrigin );
|
||||
|
||||
QAngle vecAngles;
|
||||
vecAngles.x = random->RandomFloat( -20.0f, 20.0f );
|
||||
vecAngles.y = random->RandomFloat( 0.0f, 360.0f );
|
||||
vecAngles.z = random->RandomFloat( -20.0f, 20.0f );
|
||||
pSpawn->SetAbsAngles( vecAngles );
|
||||
|
||||
Vector vecActualVelocity;
|
||||
vecActualVelocity.Random( -10.0f, 10.0f );
|
||||
// vecActualVelocity += vecVelocity;
|
||||
pSpawn->SetAbsVelocity( vecActualVelocity );
|
||||
|
||||
QAngle angVel;
|
||||
AngularImpulseToQAngle( angImpulse, angVel );
|
||||
pSpawn->SetLocalAngularVelocity( angVel );
|
||||
|
||||
// If we're creating an item, it can't be picked up until it comes to rest
|
||||
// But only if it wasn't broken by a vehicle
|
||||
CItem *pItem = dynamic_cast<CItem*>(pSpawn);
|
||||
if ( pItem && !pBreaker->GetServerVehicle())
|
||||
{
|
||||
pItem->ActivateWhenAtRest();
|
||||
}
|
||||
|
||||
pSpawn->Spawn();
|
||||
|
||||
// Avoid missing items drops by a dynamic resupply because they don't think immediately
|
||||
if ( FClassnameIs( pSpawn, "item_dynamic_resupply" ) )
|
||||
{
|
||||
if ( m_strAlternateMaster != NULL_STRING )
|
||||
{
|
||||
DynamicResupply_InitFromAlternateMaster( pSpawn, m_strAlternateMaster );
|
||||
}
|
||||
if ( i == 0 )
|
||||
{
|
||||
pSpawn->AddSpawnFlags( SF_DYNAMICRESUPPLY_ALWAYS_SPAWN );
|
||||
}
|
||||
pSpawn->SetNextThink( gpGlobals->curtime );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CItem_ItemCrate::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason )
|
||||
{
|
||||
BaseClass::OnPhysGunPickup( pPhysGunUser, reason );
|
||||
|
||||
m_OnCacheInteraction.FireOutput( pPhysGunUser, this );
|
||||
|
||||
if ( reason == PUNTED_BY_CANNON && m_CrateAppearance != CRATE_APPEARANCE_RADAR_BEACON )
|
||||
{
|
||||
Vector vForward;
|
||||
AngleVectors( pPhysGunUser->EyeAngles(), &vForward, NULL, NULL );
|
||||
Vector vForce = Pickup_PhysGunLaunchVelocity( this, vForward, PHYSGUN_FORCE_PUNTED );
|
||||
AngularImpulse angular = AngularImpulse( 0, 0, 0 );
|
||||
|
||||
IPhysicsObject *pPhysics = VPhysicsGetObject();
|
||||
|
||||
if ( pPhysics )
|
||||
{
|
||||
pPhysics->AddVelocity( &vForce, &angular );
|
||||
}
|
||||
|
||||
TakeDamage( CTakeDamageInfo( pPhysGunUser, pPhysGunUser, GetHealth(), DMG_GENERIC ) );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user