#include "cbase.h" #include "props.h" #include "asw_ammo_drop.h" #include "asw_ammo_drop_shared.h" #include "asw_player.h" #include "asw_marine.h" #include "asw_weapon.h" #include "asw_marine_skills.h" #include "asw_marine_speech.h" #include "asw_marine_resource.h" #include "world.h" #include "asw_util_shared.h" #include "asw_fx_shared.h" #include "asw_gamerules.h" #include "ammodef.h" #include "asw_weapon_ammo_bag_shared.h" #include "particle_parse.h" #include "asw_achievements.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #define AMMO_DROP_MODEL "models/items/Ammobag/AmmoBag.mdl" LINK_ENTITY_TO_CLASS( asw_ammo_drop, CASW_Ammo_Drop ); PRECACHE_WEAPON_REGISTER( asw_ammo_drop ); IMPLEMENT_SERVERCLASS_ST(CASW_Ammo_Drop, DT_ASW_Ammo_Drop) SendPropInt(SENDINFO(m_iAmmoUnitsRemaining)), END_SEND_TABLE() BEGIN_DATADESC( CASW_Ammo_Drop ) DEFINE_FIELD( m_iAmmoUnitsRemaining, FIELD_INTEGER ), DEFINE_FIELD( m_bSuppliedAmmo, FIELD_BOOLEAN ), END_DATADESC() IMPLEMENT_AUTO_LIST( IAmmoDropAutoList ); CASW_Ammo_Drop::CASW_Ammo_Drop() { m_iAmmoUnitsRemaining = DEFAULT_AMMO_DROP_UNITS; } CASW_Ammo_Drop::~CASW_Ammo_Drop() { } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CASW_Ammo_Drop::Spawn( void ) { SetMoveType( MOVETYPE_NONE ); SetSolid( SOLID_BBOX ); SetCollisionGroup( ASW_COLLISION_GROUP_PASSABLE ); Precache(); SetModel(AMMO_DROP_MODEL); BaseClass::Spawn(); AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); SetCollisionBounds( Vector(-26,-26,0), Vector(26,26,60)); m_takedamage = DAMAGE_NO; // check for attaching to elevators trace_t tr; UTIL_TraceLine( GetAbsOrigin() + Vector(0, 0, 2), GetAbsOrigin() - Vector(0, 0, 32), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); if ( tr.fraction < 1.0f && tr.m_pEnt && !tr.m_pEnt->IsWorld() && !tr.m_pEnt->IsNPC() ) { SetParent( tr.m_pEnt ); } m_iAmmoUnitsRemaining = DEFAULT_AMMO_DROP_UNITS; } void CASW_Ammo_Drop::PlayDeploySound() { EmitSound("ASW_Ammobag.DropImpact"); } void CASW_Ammo_Drop::Precache() { PrecacheModel( AMMO_DROP_MODEL ); PrecacheScriptSound( "ASW_Ammobag.DropImpact" ); PrecacheScriptSound( "ASW_Ammobag.Pickup_sml" ); PrecacheScriptSound( "ASW_Ammobag.Pickup_med" ); PrecacheScriptSound( "ASW_Ammobag.Pickup_lrg" ); PrecacheScriptSound( "ASW_Ammobag.Fail" ); PrecacheParticleSystem( "ammo_satchel_take_sml" ); PrecacheParticleSystem( "ammo_satchel_take_med" ); PrecacheParticleSystem( "ammo_satchel_take_lrg" ); BaseClass::Precache(); } int CASW_Ammo_Drop::ShouldTransmit( const CCheckTransmitInfo *pInfo ) { return FL_EDICT_ALWAYS; } int CASW_Ammo_Drop::UpdateTransmitState() { return SetTransmitState( FL_EDICT_FULLCHECK ); } void CASW_Ammo_Drop::ActivateUseIcon( CASW_Marine* pMarine, int nHoldType ) { if ( nHoldType == ASW_USE_HOLD_START ) return; CASW_Weapon *pWeapon = GetAmmoUseUnits( pMarine ); if( pWeapon ) { int iAmmoType = pWeapon->GetPrimaryAmmoType(); int iGuns = pMarine->GetNumberOfWeaponsUsingAmmo( iAmmoType ); int iMaxAmmoCount = GetAmmoDef()->MaxCarry( iAmmoType, pMarine ) * iGuns; int iBullets = pMarine->GetAmmoCount( iAmmoType ); int iAmmoCost = GetAmmoUnitCost( iAmmoType ); int iClipsToGive = CASW_Ammo_Drop_Shared::GetAmmoClipsToGive( iAmmoType ); pMarine->SetAmmoCount( MIN( iBullets + pWeapon->GetMaxClip1() * iClipsToGive, iMaxAmmoCount ), iAmmoType ); m_iAmmoUnitsRemaining -= iAmmoCost; pMarine->GetMarineSpeech()->Chatter(CHATTER_USE); IGameEvent * event = gameeventmanager->CreateEvent( "ammo_pickup" ); if ( event ) { CASW_Player *pPlayer = pMarine->GetCommander(); event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) ); event->SetInt( "entindex", pMarine->entindex() ); gameeventmanager->FireEvent( event ); } if ( m_iAmmoUnitsRemaining <= 0 ) { CTakeDamageInfo info; BaseClass::Event_Killed( info ); } CASW_Marine *pDeployer = m_hDeployer.Get(); if ( pDeployer && pMarine != pDeployer && !m_bSuppliedAmmo ) { m_bSuppliedAmmo = true; if ( pDeployer->GetCommander() ) { pDeployer->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_AMMO_RESUPPLY ); } } } else { if ( pMarine->IsInhabited() ) { CASW_Player *pCommander = pMarine->GetCommander(); if ( pCommander ) { CSingleUserRecipientFilter filter( pCommander ); EmitSound( filter, pMarine->entindex(), "ASW_Ammobag.Fail", NULL, 0.0f ); } } } } void CASW_Ammo_Drop::MarineUsing(CASW_Marine* pMarine, float deltatime) { } void CASW_Ammo_Drop::MarineStartedUsing(CASW_Marine* pMarine) { } void CASW_Ammo_Drop::MarineStoppedUsing(CASW_Marine* pMarine) { } bool CASW_Ammo_Drop::IsUsable(CBaseEntity *pUser) { return (pUser && pUser->GetAbsOrigin().DistTo(GetAbsOrigin()) < ASW_MARINE_USE_RADIUS); // near enough? } int CASW_Ammo_Drop::GetAmmoUnitCost( int iAmmoType ) { return CASW_Ammo_Drop_Shared::GetAmmoUnitCost( iAmmoType ); } CASW_Weapon* CASW_Ammo_Drop::GetAmmoUseUnits( CASW_Marine *pMarine ) { if ( pMarine ) { CASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon(); if ( !pWeapon || pWeapon->Classify() == CLASS_ASW_AMMO_SATCHEL ) { //pWeapon CASW_Weapon *pOtherWeapon = pMarine->GetASWWeapon( 0 ); if ( pOtherWeapon && pOtherWeapon->Classify() != CLASS_ASW_AMMO_SATCHEL ) { pWeapon = pOtherWeapon; } else { pOtherWeapon = pMarine->GetASWWeapon( 1 ); if ( pOtherWeapon && pOtherWeapon->Classify() != CLASS_ASW_AMMO_SATCHEL ) { pWeapon = pOtherWeapon; } } } if ( pWeapon && pWeapon->IsOffensiveWeapon() ) { if ( pWeapon->Classify() == CLASS_ASW_CHAINSAW ) return NULL; int iAmmoType = pWeapon->GetPrimaryAmmoType(); int iGuns = pMarine->GetNumberOfWeaponsUsingAmmo( iAmmoType ); int iMaxAmmoCount = GetAmmoDef()->MaxCarry( iAmmoType, pMarine ) * iGuns; int iBullets = pMarine->GetAmmoCount( iAmmoType ); int iAmmoCost = CASW_Ammo_Drop_Shared::GetAmmoUnitCost( iAmmoType ); if ( ( iBullets < iMaxAmmoCount ) && ( m_iAmmoUnitsRemaining >= iAmmoCost ) ) { return pWeapon; } } } return NULL; } int CASW_Ammo_Drop::GetWeaponAmmoInUnits( CASW_Marine *pMarine ) { if ( pMarine ) { CASW_Weapon *pWeapon = pMarine->GetActiveASWWeapon(); if ( pWeapon && pWeapon->IsOffensiveWeapon() && ( pWeapon->GetMaxClip1() > 0 ) ) { int iAmmoType = pWeapon->GetPrimaryAmmoType(); //int iGuns = pMarine->GetNumberOfWeaponsUsingAmmo( iAmmoType ); int iClipsRemaining = pMarine->GetAmmoCount( iAmmoType ) / pWeapon->GetMaxClip1(); int iAmmoCost = GetAmmoUnitCost( iAmmoType ); return iClipsRemaining * iAmmoCost; } else { return AMMO_UNITS_MAX; // no need for ammo if no offensive weapon } } return AMMO_UNITS_MAX; // no need for ammo if no marine } // does first marine need ammo more than second? this allows us to compare regardless of weapon bool CASW_Ammo_Drop::NeedsAmmoMoreThan( CASW_Marine *pFirstMarine, CASW_Marine *pSecondMarine ) { return GetWeaponAmmoInUnits( pFirstMarine ) < GetWeaponAmmoInUnits( pSecondMarine ); } bool CASW_Ammo_Drop::AllowedToPickup( CASW_Marine *pMarine ) { // if the marine can't use it, the use portion is zero return ( GetAmmoUseUnits( pMarine ) != NULL ); }