diff options
Diffstat (limited to 'game/shared/econ/econ_wearable.cpp')
| -rw-r--r-- | game/shared/econ/econ_wearable.cpp | 860 |
1 files changed, 860 insertions, 0 deletions
diff --git a/game/shared/econ/econ_wearable.cpp b/game/shared/econ/econ_wearable.cpp new file mode 100644 index 0000000..b7bea59 --- /dev/null +++ b/game/shared/econ/econ_wearable.cpp @@ -0,0 +1,860 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "cbase.h" +#include "econ_wearable.h" +#include "vcollide_parse.h" + +#ifdef CLIENT_DLL +#include "functionproxy.h" +#include "c_te_effect_dispatch.h" +#endif // CLIENT_DLL + +#ifdef TF_CLIENT_DLL +#include "c_team.h" +#include "tf_shareddefs.h" +#include "tf_weapon_jar.h" +#include "c_tf_player.h" +#endif // TF_CLIENT_DLL + +#ifdef TF_DLL +#include "tf_player.h" +#endif // TF_DLL + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +LINK_ENTITY_TO_CLASS( wearable_item, CEconWearable ); +IMPLEMENT_NETWORKCLASS_ALIASED( EconWearable, DT_WearableItem ) + +// Network Table -- +BEGIN_NETWORK_TABLE( CEconWearable, DT_WearableItem ) +END_NETWORK_TABLE() +// -- Network Table + +// Data Desc -- +BEGIN_DATADESC( CEconWearable ) +END_DATADESC() +// -- Data Desc + +PRECACHE_REGISTER( wearable_item ); + +IMPLEMENT_NETWORKCLASS_ALIASED( TFWearableItem, DT_TFWearableItem ) + +// Network Table -- +BEGIN_NETWORK_TABLE( CTFWearableItem, DT_TFWearableItem ) +END_NETWORK_TABLE() +// -- Network Table + +// Data Desc -- +BEGIN_DATADESC( CTFWearableItem ) +END_DATADESC() +// -- Data Desc + +//----------------------------------------------------------------------------- +// SHARED CODE +//----------------------------------------------------------------------------- + +CEconWearable::CEconWearable() +{ + m_bAlwaysAllow = false; +}; + +void CEconWearable::InternalSetPlayerDisplayModel( void ) +{ + int iClass = 0; + int iTeam = 0; + +#if defined( TF_DLL ) || defined( TF_CLIENT_DLL ) + CTFPlayer *pTFPlayer = ToTFPlayer( GetOwnerEntity() ); + if ( pTFPlayer ) + { + iClass = pTFPlayer->GetPlayerClass()->GetClassIndex(); + iTeam = pTFPlayer->GetTeamNumber(); + } +#endif // defined( TF_DLL ) || defined( TF_CLIENT_DLL ) + + // Set our model to the player model + CEconItemView *pItem = GetAttributeContainer()->GetItem(); + if ( pItem && pItem->IsValid() ) + { + const char *pszPlayerDisplayModel = pItem->GetPlayerDisplayModel( iClass, iTeam ); + if ( pszPlayerDisplayModel ) + { + if ( pItem->GetStaticData()->IsContentStreamable() ) + { + modelinfo->RegisterDynamicModel( pszPlayerDisplayModel, IsClient() ); + + if ( pItem->GetVisionFilteredDisplayModel() && pItem->GetVisionFilteredDisplayModel()[ 0 ] != '\0' ) + { + modelinfo->RegisterDynamicModel( pItem->GetVisionFilteredDisplayModel(), IsClient() ); + } + } + SetModel( pszPlayerDisplayModel ); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Set up the item. GC data may not be available here depending on +// where we're called from. +//----------------------------------------------------------------------------- +void CEconWearable::Spawn( void ) +{ + InitializeAttributes(); + + Precache(); + + InternalSetPlayerDisplayModel(); + + BaseClass::Spawn(); + + AddEffects( EF_BONEMERGE ); + AddEffects( EF_BONEMERGE_FASTCULL ); + +#if !defined( CLIENT_DLL ) + SetCollisionGroup( COLLISION_GROUP_WEAPON ); + SetBlocksLOS( false ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: Player touches the item. Currently wearables don't appear in the +// world, so this is only called directly during equipment assignment. +//----------------------------------------------------------------------------- +void CEconWearable::GiveTo( CBaseEntity *pOther ) +{ + CBasePlayer *pPlayer = ToBasePlayer(pOther); + if ( !pPlayer ) + return; + +#if !defined( CLIENT_DLL ) + pPlayer->EquipWearable( this ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CEconWearable::RemoveFrom( CBaseEntity *pOther ) +{ + CBasePlayer *pPlayer = ToBasePlayer(pOther); + if ( !pPlayer ) + return; + +#if !defined( CLIENT_DLL ) + pPlayer->RemoveWearable( this ); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CEconWearable::GetSkin( void ) +{ + CEconItemView *pItem = GetAttributeContainer()->GetItem(); // Safe. Checked in base class call. + if ( pItem ) + { + int iSkin = pItem->GetSkin( GetTeamNumber() ); + if ( iSkin > -1 ) + { + return iSkin; + } + } + + return ( GetTeamNumber() == (LAST_SHARED_TEAM+1) ) ? 0 : 1; +} + +//----------------------------------------------------------------------------- +// Purpose: Attaches the item to the player. +//----------------------------------------------------------------------------- +void CEconWearable::Equip( CBasePlayer* pOwner ) +{ + if ( !CanEquip( pOwner ) ) + { + RemoveFrom( pOwner ); + return; + } + + SetTouch( NULL ); + SetAbsVelocity( vec3_origin ); + + CBaseEntity *pFollowEntity = pOwner; + + if ( IsViewModelWearable() ) + { + pFollowEntity = pOwner->GetViewModel(); + } + + FollowEntity( pFollowEntity, true ); + + SetOwnerEntity( pOwner ); + + ReapplyProvision(); + + ChangeTeam( pOwner->GetTeamNumber() ); + m_nSkin = GetSkin(); + +#ifdef GAME_DLL + UpdateModelToClass(); + UpdateBodygroups( pOwner, true ); + PlayAnimForPlaybackEvent( WAP_ON_SPAWN ); +#endif +} + + +//----------------------------------------------------------------------------- +// Purpose: Remove item from the player. +//----------------------------------------------------------------------------- +void CEconWearable::UnEquip( CBasePlayer* pOwner ) +{ +#ifdef CLIENT_DLL + SetParticleSystemsVisible( PARTICLE_SYSTEM_STATE_NOT_VISIBLE ); +#endif + +#ifdef GAME_DLL + UpdateBodygroups( pOwner, false ); +#endif + + StopFollowingEntity(); + SetOwnerEntity( NULL ); + + ReapplyProvision(); +} +/* +//----------------------------------------------------------------------------- +// Purpose: Hides or shows masked bodygroups associated with this item. +//----------------------------------------------------------------------------- +bool CEconWearable::UpdateBodygroups( CBaseCombatCharacter* pOwner, int iState ) +{ + if ( !pOwner ) + return false; + + CAttributeContainer *pCont = GetAttributeContainer(); + if ( !pCont ) + return false; + + CEconItemView *pItem = pCont->GetItem(); + if ( !pItem ) + return false; + + int iTeam = pOwner->GetTeamNumber(); + int iNumBodyGroups = pItem->GetNumModifiedBodyGroups( iTeam ); + for ( int i=0; i<iNumBodyGroups; ++i ) + { + int iBody = 0; + const char *pszBodyGroup = pItem->GetModifiedBodyGroup( iTeam, i, iBody ); + int iBodyGroup = pOwner->FindBodygroupByName( pszBodyGroup ); + + if ( iBodyGroup == -1 ) + continue; + + pOwner->SetBodygroup( iBodyGroup, iState ); + } + + return true; +} +*/ +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CEconWearable::OnWearerDeath( void ) +{ +#ifdef CLIENT_DLL + UpdateParticleSystems(); +#endif +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CEconWearable::GetDropType() +{ + CAttributeContainer *pCont = GetAttributeContainer(); + if ( !pCont ) + return 0; + + CEconItemView *pItem = pCont->GetItem(); + if ( pItem ) + return pItem->GetDropType(); + else + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Ensures that a player's correct body groups are enabled on client respawn. +//----------------------------------------------------------------------------- +void CEconWearable::UpdateWearableBodyGroups( CBasePlayer* pPlayer ) +{ + if ( !pPlayer ) + return; + + for ( int i=0; i<pPlayer->GetNumWearables(); ++i ) + { + CEconWearable* pItem = pPlayer->GetWearable(i); + if ( !pItem ) + continue; + + // Dynamic models which are not yet rendering do not modify bodygroups + if ( pItem->IsDynamicModelLoading() ) + continue; + + // On the client, ignore items that aren't valid. +#ifdef TF_CLIENT_DLL + if ( pItem->EntityDeemedInvalid() ) + continue; +#endif + + int nVisibleState = 1; +#ifdef TF_CLIENT_DLL + if ( pItem->ShouldHideForVisionFilterFlags() ) + { + // Items that shouldn't draw (pyro-vision filtered) shouldn't change any body group states + // unless they have no model (hatless hats) + nVisibleState = 0; + } +#endif + + pItem->UpdateBodygroups( pPlayer, nVisibleState ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFWearableItem::CTFWearableItem() +{ +} + +//----------------------------------------------------------------------------- +// SERVER ONLY CODE +//----------------------------------------------------------------------------- + +#if defined( GAME_DLL ) + +#endif + +//----------------------------------------------------------------------------- +// CLIENT ONLY CODE +//----------------------------------------------------------------------------- + +#if defined( CLIENT_DLL ) + +//----------------------------------------------------------------------------- +// Purpose: Mirror should draw logic. +//----------------------------------------------------------------------------- +ShadowType_t CEconWearable::ShadowCastType() +{ + if ( ShouldDraw() ) + { + return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; + } + + return SHADOWS_NONE; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CEconWearable::ShouldDraw( void ) +{ + CBasePlayer *pPlayerOwner = ToBasePlayer( GetOwnerEntity() ); + if ( !pPlayerOwner ) + { + return false; + } + + bool bUseViewModel = !pPlayerOwner->ShouldDrawThisPlayer(); + + // Don't show view models if we're drawing the real player, and don't show non view models if using view models. + if ( bUseViewModel ) + { + // VM mode. + if ( !IsViewModelWearable() ) + { + return false; + } + } + else + { + // Non-viewmodel mode. + if ( IsViewModelWearable() ) + { + return false; + } + } + + if ( !ShouldDrawWhenPlayerIsDead() && !pPlayerOwner->IsAlive() ) + { + return false; + } + + if ( pPlayerOwner->GetTeamNumber() == TEAM_SPECTATOR ) + { + return false; + } + + return BaseClass::ShouldDraw(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CEconWearable::OnDataChanged( DataUpdateType_t updateType ) +{ + BaseClass::OnDataChanged( updateType ); + + if ( updateType == DATA_UPDATE_CREATED ) + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + + // Update our visibility in case our parents' has changed. + UpdateVisibility(); + UpdateParticleSystems(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CEconWearable::ClientThink( void ) +{ + BaseClass::ClientThink(); + + UpdateParticleSystems(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CEconWearable::ShouldDrawParticleSystems( void ) +{ + // Make sure the entity we're attaching to is being drawn + CBasePlayer *pPlayerOwner = ToBasePlayer( GetOwnerEntity() ); + if ( !pPlayerOwner ) + { + Assert ( "CEconWearable has no owner?" ); // Not sure what this means - is is visible or not? + return false; + } + if ( pPlayerOwner->ShouldDrawThisPlayer() ) + { + return true; + } + return false; +} + +RenderGroup_t CEconWearable::GetRenderGroup() +{ + if ( IsViewModelWearable() ) + return RENDER_GROUP_VIEW_MODEL_TRANSLUCENT; + + return BaseClass::GetRenderGroup(); +} + +//----------------------------------------------------------------------------- +// Purpose: Wearable tint colors +//----------------------------------------------------------------------------- +class CProxyItemTintColor : public CResultProxy +{ +public: + void OnBind( void *pC_BaseEntity ) + { + Assert( m_pResult ); + Vector vResult = Vector( 0, 0, 0 ); + + if ( pC_BaseEntity ) + { + CEconItemView *pScriptItem = NULL; + + IClientRenderable *pRend = (IClientRenderable *)pC_BaseEntity; + C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); + if ( pEntity ) + { + CEconEntity *pItem = dynamic_cast< CEconEntity* >( pEntity ); + if ( pItem ) + { + pScriptItem = pItem->GetAttributeContainer()->GetItem(); + } + else if ( pEntity->GetOwnerEntity() ) + { + // Try the owner (for viewmodels, etc). + pEntity = pEntity->GetOwnerEntity(); + pItem = dynamic_cast< CEconEntity* >( pEntity ); + if ( pItem ) + { + pScriptItem = pItem->GetAttributeContainer()->GetItem(); + } + } + } + else + { + // Proxy data can be a script created item itself, if we're in a vgui CModelPanel + pScriptItem = dynamic_cast< CEconItemView* >( pRend ); + } + +#ifdef TF_CLIENT_DLL + if ( !pScriptItem ) + { + // Might be a throwable + CTFWeaponBaseGrenadeProj *pProjectile = dynamic_cast< CTFWeaponBaseGrenadeProj* >( pEntity ); + if ( pProjectile ) + { + CEconEntity *pItem = dynamic_cast< CEconEntity* >( pProjectile->GetLauncher() ); + if ( pItem ) + { + pScriptItem = pItem->GetAttributeContainer()->GetItem(); + } + } + } + + if ( pScriptItem && pScriptItem->IsValid() ) + { + const bool bAltColor = pEntity && pEntity->GetTeam() > 0 + ? pEntity->GetTeam()->GetTeamNumber() == TF_TEAM_BLUE + : pScriptItem->GetFlags() & kEconItemFlagClient_ForceBlueTeam + ? true + : false; + + int iModifiedRGB = pScriptItem->GetModifiedRGBValue( bAltColor ); + if ( iModifiedRGB ) + { + // The attrib returns a packed RGB with values between 0 & 255 packed into the bottom 3 bytes. + Color clr = Color( ((iModifiedRGB & 0xFF0000) >> 16), ((iModifiedRGB & 0xFF00) >> 8), (iModifiedRGB & 0xFF) ); + + vResult.x = clamp( clr.r() * (1.f / 255.0f), 0.f, 1.0f ); + vResult.y = clamp( clr.g() * (1.f / 255.0f), 0.f, 1.0f ); + vResult.z = clamp( clr.b() * (1.f / 255.0f), 0.f, 1.0f ); + } + } +#endif // TF_CLIENT_DLL + } + + m_pResult->SetVecValue( vResult.x, vResult.y, vResult.z ); + } +}; +EXPOSE_INTERFACE( CProxyItemTintColor, IMaterialProxy, "ItemTintColor" IMATERIAL_PROXY_INTERFACE_VERSION ); + + + +//============================================================================================================================ +extern ConVar r_propsmaxdist; + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +C_EconWearableGib::C_EconWearableGib() +{ + m_fDeathTime = -1; + m_iHealth = 0; + m_bParented = false; + m_bDelayedInit = false; +} + +C_EconWearableGib::~C_EconWearableGib() +{ + PhysCleanupFrictionSounds( this ); + VPhysicsDestroyObject(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_EconWearableGib::Initialize( bool bWillBeParented ) +{ + m_bParented = bWillBeParented; + return InitializeAsClientEntity( STRING( GetModelName() ), RENDER_GROUP_OPAQUE_ENTITY ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CStudioHdr* C_EconWearableGib::OnNewModel() +{ + CStudioHdr* pCStudioHdr = BaseClass::OnNewModel(); + if ( m_bDelayedInit && !IsDynamicModelLoading() ) + { + FinishModelInitialization(); + } + return pCStudioHdr; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_EconWearableGib::SpawnClientEntity( void ) +{ + if ( !IsDynamicModelLoading() ) + { + FinishModelInitialization(); + } + else + { + m_bDelayedInit = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_EconWearableGib::FinishModelInitialization( void ) +{ + UpdateThinkState(); + + const model_t *mod = GetModel(); + if ( mod ) + { + Vector mins, maxs; + modelinfo->GetModelBounds( mod, mins, maxs ); + SetCollisionBounds( mins, maxs ); + } + + if ( !m_bParented ) + { + // Create the object in the physics system + solid_t tmpSolid; + if ( !PhysModelParseSolid( tmpSolid, this, GetModelIndex() ) ) + { + DevMsg("C_EconWearableGib::FinishModelInitialization: PhysModelParseSolid failed for entity %i.\n", GetModelIndex() ); + return false; + } + else + { + m_pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &tmpSolid ); + + if ( !m_pPhysicsObject ) + { + // failed to create a physics object + DevMsg(" C_EconWearableGib::FinishModelInitialization: VPhysicsInitNormal() failed for %s.\n", STRING(GetModelName()) ); + return false; + } + } + } + + Spawn(); + + if ( m_fadeMinDist < 0 ) + { + // start fading out at 75% of r_propsmaxdist + m_fadeMaxDist = r_propsmaxdist.GetFloat(); + m_fadeMinDist = r_propsmaxdist.GetFloat() * 0.75f; + } + + SetCollisionGroup( COLLISION_GROUP_DEBRIS ); + + UpdatePartitionListEntry(); + + CollisionProp()->UpdatePartition(); + + SetBlocksLOS( false ); // this should be a small object + + // Set up shadows; do it here so that objects can change shadowcasting state + CreateShadow(); + + UpdateVisibility(); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_EconWearableGib::Spawn() +{ + BaseClass::Spawn(); + m_takedamage = DAMAGE_EVENTS_ONLY; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool C_EconWearableGib::ValidateEntityAttachedToPlayer( bool &bShouldRetry ) +{ + bShouldRetry = false; + + // Always valid as long as we're not parented to anything + return (GetMoveParent() == NULL); +} + +#define WEARABLE_FADEOUT_TIME 1.0f + +//----------------------------------------------------------------------------- +// Purpose: Figure out if we need to think or not +//----------------------------------------------------------------------------- +bool C_EconWearableGib::UpdateThinkState( void ) +{ + if ( m_fDeathTime > 0 ) + { + // If we're in the active fadeout portion, think rapidly. Otherwise, wait for that time. + if ( (m_fDeathTime - gpGlobals->curtime) > WEARABLE_FADEOUT_TIME ) + { + SetNextClientThink( m_fDeathTime - WEARABLE_FADEOUT_TIME ); + } + else + { + SetNextClientThink( CLIENT_THINK_ALWAYS ); + } + return true; + } + + SetNextClientThink( CLIENT_THINK_NEVER ); + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_EconWearableGib::ClientThink( void ) +{ + if ( (m_fDeathTime > 0) && ((m_fDeathTime - gpGlobals->curtime) <= WEARABLE_FADEOUT_TIME) ) + { + if ( m_fDeathTime <= gpGlobals->curtime ) + { + Release(); // Die + return; + } + + // fade out + float alpha = (m_fDeathTime - gpGlobals->curtime) / WEARABLE_FADEOUT_TIME; + SetRenderMode( kRenderTransTexture ); + SetRenderColorA( alpha * 256 ); + } + + UpdateThinkState(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_EconWearableGib::StartFadeOut( float fDelay ) +{ + m_fDeathTime = gpGlobals->curtime + fDelay + WEARABLE_FADEOUT_TIME; + UpdateThinkState(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_EconWearableGib::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) +{ + IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); + + if( !pPhysicsObject ) + return; + + Vector dir = pTrace->endpos - pTrace->startpos; + int iDamage = 0; + + if ( iDamageType & DMG_BLAST ) + { + iDamage = VectorLength( dir ); + dir *= 500; // adjust impact strenght + + // apply force at object mass center + pPhysicsObject->ApplyForceCenter( dir ); + } + else + { + Vector hitpos; + + VectorMA( pTrace->startpos, pTrace->fraction, dir, hitpos ); + VectorNormalize( dir ); + + // guess avg damage + if ( iDamageType == DMG_BULLET ) + { + iDamage = 30; + } + else + { + iDamage = 50; + } + + dir *= 4000; // adjust impact strenght + + // apply force where we hit it + pPhysicsObject->ApplyForceOffset( dir, hitpos ); + } +} + +#if 0 +#ifdef _DEBUG +#include "econ_item_system.h" + +static CUtlVector< const char * > s_possibleModels; +static CUtlVector< const GameItemDefinition_t * > s_possibleDefinitions; +void Dbg_TestDynamicWearableGibs( void ) +{ + C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pLocalPlayer ) + return; + + C_EconWearableGib *pEntity = new C_EconWearableGib(); + if ( !pEntity ) + return; + + Vector forward; + pLocalPlayer->EyeVectors( &forward ); + trace_t tr; + UTIL_TraceLine( pLocalPlayer->EyePosition(), pLocalPlayer->EyePosition() + (forward * 256), MASK_NPCSOLID, pLocalPlayer, COLLISION_GROUP_NONE, &tr ); + + Vector position = tr.endpos; + + if ( s_possibleModels.Count() == 0 ) + { + FOR_EACH_MAP( ItemSystem()->GetItemSchema()->GetItemDefinitionMap(), nDefn ) + { + const GameItemDefinition_t *pDefn = dynamic_cast<GameItemDefinition_t *>( ItemSystem()->GetItemSchema()->GetItemDefinitionMap()[nDefn] ); + if ( !pDefn ) + continue; + + const char *pszModel = pDefn->GetPlayerDisplayModel( 0 ); + if ( pszModel && pszModel[0] && pszModel[0] != '?' && pDefn->BLoadOnDemand() && pDefn->GetDropType() == ITEM_DROP_TYPE_DROP ) + { + s_possibleModels.AddToTail( pszModel ); + s_possibleDefinitions.AddToTail( pDefn ); + } + } + } + + Assert( s_possibleModels.Count() ); + + int spawnIndex = random->RandomInt( 0, s_possibleModels.Count() - 1 ); + const char *pszModelName = s_possibleModels[ spawnIndex ]; + const GameItemDefinition_t *pDefn = s_possibleDefinitions[ spawnIndex ]; + Msg( "Spawning: %s\n", pszModelName ); + pEntity->SetModelName( AllocPooledString( pszModelName ) ); + pEntity->SetAbsOrigin( position ); + pEntity->SetAbsAngles( vec3_angle ); + pEntity->SetOwnerEntity( pLocalPlayer ); + pEntity->ChangeTeam( pLocalPlayer->GetTeamNumber() ); // our gibs will match our team; this will probably not be used for anything besides team coloring + // Copy the script created item data over + pEntity->GetAttributeContainer()->GetItem()->Init( pDefn->GetDefinitionIndex(), pDefn->GetQuality(), pDefn->GetMinLevel(), true ); + + if ( !pEntity->Initialize( false ) ) + { + pEntity->Release(); + return; + } + + pEntity->StartFadeOut( 15.0f ); + return; + + IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); + if ( !pPhysicsObject ) + { + pEntity->Release(); + return; + } + + // randomize velocity by 5% + Vector rndVel = Vector(0,0,100); + pPhysicsObject->AddVelocity( &rndVel, &vec3_origin ); +} +static ConCommand dbg_testdynamicwearablegib( "dbg_testdynamicwearablegib", Dbg_TestDynamicWearableGibs, "", FCVAR_CHEAT ); +#endif // _DEBUG +#endif + +#endif // client only |