//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Base combat character with no AI // // $Workfile: $ // $Date: $ // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "ammodef.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" //----------------------------------------------------------------------------- // Purpose: Return a pointer to the Ammo at the Index passed in //----------------------------------------------------------------------------- Ammo_t *CAmmoDef::GetAmmoOfIndex(int nAmmoIndex) { if ( nAmmoIndex >= m_nAmmoIndex ) return NULL; return &m_AmmoType[ nAmmoIndex ]; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::Index(const char *psz) { int i; if (!psz) return -1; for (i = 1; i < m_nAmmoIndex; i++) { if (stricmp( psz, m_AmmoType[i].pName ) == 0) return i; } return -1; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::PlrDamage(int nAmmoIndex) { if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) return 0; if ( m_AmmoType[nAmmoIndex].pPlrDmg == USE_CVAR ) { if ( m_AmmoType[nAmmoIndex].pPlrDmgCVar ) { return m_AmmoType[nAmmoIndex].pPlrDmgCVar->GetFloat(); } return 0; } else { return m_AmmoType[nAmmoIndex].pPlrDmg; } } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::NPCDamage(int nAmmoIndex) { if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) return 0; if ( m_AmmoType[nAmmoIndex].pNPCDmg == USE_CVAR ) { if ( m_AmmoType[nAmmoIndex].pNPCDmgCVar ) { return m_AmmoType[nAmmoIndex].pNPCDmgCVar->GetFloat(); } return 0; } else { return m_AmmoType[nAmmoIndex].pNPCDmg; } } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::MaxCarry(int nAmmoIndex, const CBaseCombatCharacter *owner) { if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) return 0; if ( m_AmmoType[nAmmoIndex].pMaxCarry == USE_CVAR ) { if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar ) return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetInt(); return 0; } else { return m_AmmoType[nAmmoIndex].pMaxCarry; } } bool CAmmoDef::CanCarryInfiniteAmmo(int nAmmoIndex) { if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) return false; int maxCarry = m_AmmoType[nAmmoIndex].pMaxCarry; if ( maxCarry == USE_CVAR ) { if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar ) { maxCarry = m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetInt(); } } return maxCarry == INFINITE_AMMO ? true : false; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::DamageType(int nAmmoIndex) { if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) return 0; return m_AmmoType[nAmmoIndex].nDamageType; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CAmmoDef::Flags(int nAmmoIndex) { if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) return 0; return m_AmmoType[nAmmoIndex].nFlags; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::MinSplashSize(int nAmmoIndex) { if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) return 4; return m_AmmoType[nAmmoIndex].nMinSplashSize; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::MaxSplashSize(int nAmmoIndex) { if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) return 8; return m_AmmoType[nAmmoIndex].nMaxSplashSize; } //----------------------------------------------------------------------------- // Purpose: // Input : // Output : //----------------------------------------------------------------------------- int CAmmoDef::TracerType(int nAmmoIndex) { if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) return 0; return m_AmmoType[nAmmoIndex].eTracerType; } //----------------------------------------------------------------------------- // Purpose: Figure out the damage force for a certian ammo type. // Input : // Output : //----------------------------------------------------------------------------- float CAmmoDef::DamageForce(int nAmmoIndex) { const float DEFAULT_IMPULSE = 1.0f; if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) return DEFAULT_IMPULSE; if ( m_AmmoType[nAmmoIndex].pPhysicsForceImpulse == USE_CVAR ) { if ( m_AmmoType[nAmmoIndex].pPhysicsForceImpulseCVar ) return m_AmmoType[nAmmoIndex].pPhysicsForceImpulseCVar->GetFloat(); return DEFAULT_IMPULSE; } else { return (float)m_AmmoType[nAmmoIndex].pPhysicsForceImpulse; } } //----------------------------------------------------------------------------- // Purpose: Create an Ammo type with the name, decal, and tracer. // Does not increment m_nAmmoIndex because the functions below do so and // are the only entry point. //----------------------------------------------------------------------------- bool CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, int nFlags, int minSplashSize, int maxSplashSize ) { if (m_nAmmoIndex == MAX_AMMO_TYPES) return false; int len = strlen(name); m_AmmoType[m_nAmmoIndex].pName = new char[len+1]; Q_strncpy(m_AmmoType[m_nAmmoIndex].pName, name,len+1); m_AmmoType[m_nAmmoIndex].nDamageType = damageType; m_AmmoType[m_nAmmoIndex].eTracerType = tracerType; m_AmmoType[m_nAmmoIndex].nMinSplashSize = minSplashSize; m_AmmoType[m_nAmmoIndex].nMaxSplashSize = maxSplashSize; m_AmmoType[m_nAmmoIndex].nFlags = nFlags; return true; } //----------------------------------------------------------------------------- // Purpose: Add an ammo type with it's damage & carrying capability specified via cvars //----------------------------------------------------------------------------- void CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, char const* plr_cvar, char const* npc_cvar, char const* carry_cvar, char const* impulse_cvar, int nFlags, int minSplashSize, int maxSplashSize) { if ( AddAmmoType( name, damageType, tracerType, nFlags, minSplashSize, maxSplashSize ) == false ) return; if (plr_cvar) { m_AmmoType[m_nAmmoIndex].pPlrDmgCVar = cvar->FindVar(plr_cvar); if (!m_AmmoType[m_nAmmoIndex].pPlrDmgCVar) { Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,plr_cvar); } m_AmmoType[m_nAmmoIndex].pPlrDmg = USE_CVAR; } if (npc_cvar) { m_AmmoType[m_nAmmoIndex].pNPCDmgCVar = cvar->FindVar(npc_cvar); if (!m_AmmoType[m_nAmmoIndex].pNPCDmgCVar) { Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,npc_cvar); } m_AmmoType[m_nAmmoIndex].pNPCDmg = USE_CVAR; } if (carry_cvar) { m_AmmoType[m_nAmmoIndex].pMaxCarryCVar= cvar->FindVar(carry_cvar); if (!m_AmmoType[m_nAmmoIndex].pMaxCarryCVar) { Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,carry_cvar); } m_AmmoType[m_nAmmoIndex].pMaxCarry = USE_CVAR; } if (impulse_cvar) { m_AmmoType[m_nAmmoIndex].pPhysicsForceImpulseCVar = cvar->FindVar(impulse_cvar); if (!m_AmmoType[m_nAmmoIndex].pPhysicsForceImpulseCVar) { Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,impulse_cvar); } else { // By default, use whatever value is in the convar at load time. // To enable real-time updating of the ammo impulse values, execute "tweak_ammo_impulse" which will set pPhysicsForceImpulse to USE_CVAR. m_AmmoType[m_nAmmoIndex].pPhysicsForceImpulse = m_AmmoType[m_nAmmoIndex].pPhysicsForceImpulseCVar->GetInt(); } } m_nAmmoIndex++; } //----------------------------------------------------------------------------- // Purpose: Add an ammo type with it's damage & carrying capability specified via integers //----------------------------------------------------------------------------- void CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, int plr_dmg, int npc_dmg, int carry, int impulse, int nFlags, int minSplashSize, int maxSplashSize ) { if ( AddAmmoType( name, damageType, tracerType, nFlags, minSplashSize, maxSplashSize ) == false ) return; m_AmmoType[m_nAmmoIndex].pPlrDmg = plr_dmg; m_AmmoType[m_nAmmoIndex].pNPCDmg = npc_dmg; m_AmmoType[m_nAmmoIndex].pMaxCarry = carry; m_AmmoType[m_nAmmoIndex].pPhysicsForceImpulse = impulse; m_nAmmoIndex++; } //----------------------------------------------------------------------------- // Purpose: Constructor // Input : // Output : //----------------------------------------------------------------------------- CAmmoDef::CAmmoDef(void) { // Start with an index of 1. Client assumes 0 is an invalid ammo type m_nAmmoIndex = 1; memset( m_AmmoType, 0, sizeof( m_AmmoType ) ); } CAmmoDef::~CAmmoDef( void ) { for ( int i = 1; i < MAX_AMMO_TYPES; i++ ) { delete[] m_AmmoType[ i ].pName; } }