//-----------------------------------------------------------------------------
// Purpose: Spawn function 
//-----------------------------------------------------------------------------
void CWeaponSpawner::Spawn(void)
{
	// Damn it. We need both item definition and weapon script data for spawners to work properly.
	CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinition( m_nItemID );
	if ( !pItemDef )
	{
		Warning( "tf_weaponspawner has incorrect item ID %d.\n", m_nWeaponID );
		UTIL_Remove( this );
		return;
	}

	m_Item.SetItemDefIndex( m_nItemID );

	// Only merc can use weapon spawners so it's safe use him for translation.
	m_pWeaponInfo = GetTFWeaponInfoForItem( m_nItemID, TF_CLASS_MERCENARY );

	Assert( m_pWeaponInfo );

	Precache();

	SetModel( m_Item.GetWorldDisplayModel() );
	BaseClass::Spawn();

	// Ensures consistent trigger bounds for all weapons. (danielmm8888)
	SetSolid( SOLID_BBOX );
	SetCollisionBounds( -Vector(22, 22, 15), Vector(22, 22, 15) );

	AddEffects( EF_ITEM_BLINK );
}
//-----------------------------------------------------------------------------
// Purpose: Fill the item arrays with data from item schema.
//-----------------------------------------------------------------------------
bool CTFInventory::Init( void )
{
	GetItemSchema()->Init();

	// Generate item list.
	FOR_EACH_MAP( GetItemSchema()->m_Items, i )
	{
		int iItemID = GetItemSchema()->m_Items.Key( i );
		CEconItemDefinition *pItemDef = GetItemSchema()->m_Items.Element( i );

		if ( pItemDef->item_slot == -1 )
			continue;

		// Add it to each class that uses it.
		for ( int iClass = 0; iClass < TF_CLASS_COUNT_ALL; iClass++ )
		{
			if ( pItemDef->used_by_classes & ( 1 << iClass ) )
			{
				// Show it if it's either base item or has show_in_armory flag.
				int iSlot = pItemDef->GetLoadoutSlot( iClass );

				if ( pItemDef->baseitem )
				{
					CEconItemView *pBaseItem = m_Items[iClass][iSlot][0];
					if ( pBaseItem != NULL )
					{
						Warning( "Duplicate base item %d for class %s in slot %s!\n", iItemID, g_aPlayerClassNames_NonLocalized[iClass], g_LoadoutSlots[iSlot] );
						delete pBaseItem;
					}

					m_Items[iClass][iSlot][0] = new CEconItemView( iItemID );
				}
				else if ( pItemDef->show_in_armory )
				{
					CEconItemView *pNewItem = new CEconItemView( iItemID );
					m_Items[iClass][iSlot].AddToTail( pNewItem );
				}
			}
		}
	}
//-----------------------------------------------------------------------------
// Purpose: Spawn function 
//-----------------------------------------------------------------------------
void CWeaponSpawner::Spawn( void )
{
	CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinition( m_nItemID );
	if ( !pItemDef )
	{
		Warning( "tf_weaponspawner has incorrect item ID %d. DELETED\n", m_nItemID );
		UTIL_Remove( this );
		return;
	}

	m_Item.SetItemDefIndex( m_nItemID );

	Precache();

	SetModel( m_Item.GetWorldDisplayModel() );

	BaseClass::Spawn();

	// Ensures consistent trigger bounds for all weapons. (danielmm8888)
	SetSolid( SOLID_BBOX );
	SetCollisionBounds( -Vector( 22, 22, 15 ), Vector( 22, 22, 15 ) );

	AddEffects( EF_ITEM_BLINK );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void TFExplosionCallback( const Vector &vecOrigin, const Vector &vecNormal, int iWeaponID, ClientEntityHandle_t hEntity, C_TFPlayer *pPlayer, int iTeam, bool bCrit, int iItemID )
{
	// Get the weapon information.
	CTFWeaponInfo *pWeaponInfo = NULL;
	switch ( iWeaponID )
	{
	case TF_WEAPON_GRENADE_PIPEBOMB:
	case TF_WEAPON_GRENADE_DEMOMAN:
		pWeaponInfo = GetTFWeaponInfo( TF_WEAPON_PIPEBOMBLAUNCHER );
		break;
	default:
		pWeaponInfo = GetTFWeaponInfo( iWeaponID );
		break;
	}

	bool bIsPlayer = false;
	if ( hEntity.Get() )
	{
		C_BaseEntity *pEntity = C_BaseEntity::Instance( hEntity );
		if ( pEntity && pEntity->IsPlayer() )
		{
			bIsPlayer = true;
		}
	}

	// Calculate the angles, given the normal.
	bool bIsWater = ( UTIL_PointContents( vecOrigin ) & CONTENTS_WATER );
	bool bInAir = false;
	QAngle angExplosion( 0.0f, 0.0f, 0.0f );

	// Cannot use zeros here because we are sending the normal at a smaller bit size.
	if ( fabs( vecNormal.x ) < 0.05f && fabs( vecNormal.y ) < 0.05f && fabs( vecNormal.z ) < 0.05f )
	{
		bInAir = true;
		angExplosion.Init();
	}
	else
	{
		VectorAngles( vecNormal, angExplosion );
		bInAir = false;
	}

	bool bDeathmatchOverride = ( pPlayer && TFGameRules()->IsDeathmatch() );

	// Base explosion effect and sound.
	const char *pszEffect = "explosion";
	const char *pszSound = "BaseExplosionEffect.Sound";

	if ( pWeaponInfo )
	{
		// Explosions.
		if ( bIsWater )
		{
			if ( bCrit && pWeaponInfo->m_szExplosionWaterEffect_Crit[0] )
			{
				pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionWaterEffect_Crit, iTeam, bDeathmatchOverride );
			}
			else if ( pWeaponInfo->m_szExplosionWaterEffect[0] )
			{
				pszEffect = pWeaponInfo->m_szExplosionWaterEffect;
			}
		}
		else
		{
			if ( bIsPlayer || bInAir )
			{
				if ( bCrit && pWeaponInfo->m_szExplosionPlayerEffect_Crit[0] )
				{
					pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionPlayerEffect_Crit, iTeam, bDeathmatchOverride );
				}
				else if ( pWeaponInfo->m_szExplosionPlayerEffect[0] )
				{
					pszEffect = pWeaponInfo->m_szExplosionPlayerEffect;
				}
			}
			else
			{
				if ( bCrit && pWeaponInfo->m_szExplosionEffect_Crit[0] )
				{
					pszEffect = ConstructTeamParticle( pWeaponInfo->m_szExplosionEffect_Crit, iTeam, bDeathmatchOverride );
				}
				else if ( pWeaponInfo->m_szExplosionEffect[0] )
				{
					pszEffect = pWeaponInfo->m_szExplosionEffect;
				}
			}
		}

		// Sound.
		if ( pWeaponInfo->m_szExplosionSound[0] != '\0' )
		{
			pszSound = pWeaponInfo->m_szExplosionSound;
		}
	}

	// Allow schema to override explosion sound.
	if ( iItemID >= 0 )
	{
		CEconItemDefinition *pItemDef = GetItemSchema()->GetItemDefinition( iItemID );
		if ( pItemDef && pItemDef->GetVisuals()->aWeaponSounds[SPECIAL1][0] != '\0' )
		{
			pszSound = pItemDef->GetVisuals()->aWeaponSounds[SPECIAL1];
		}
	}
	
	CLocalPlayerFilter filter;
	C_BaseEntity::EmitSound( filter, SOUND_FROM_WORLD, pszSound, &vecOrigin );

	if ( bDeathmatchOverride )
	{
		DispatchParticleEffect( pszEffect, vecOrigin, angExplosion, pPlayer->m_vecPlayerColor, vec3_origin, true );
	}
	else
	{
		DispatchParticleEffect( pszEffect, vecOrigin, angExplosion );
	}
}