#include "cbase.h" #include "asw_weapon_pdw_shared.h" #include "in_buttons.h" #ifdef CLIENT_DLL #include "c_asw_player.h" #include "c_asw_weapon.h" #include "c_asw_marine.h" #include "c_te_legacytempents.h" #include "c_breakableprop.h" #include "fx.h" #include "c_asw_fx.h" #define CASW_Marine C_ASW_Marine #else #include "asw_lag_compensation.h" #include "asw_marine.h" #include "asw_player.h" #include "asw_weapon.h" #include "asw_marine_resource.h" #include "npcevent.h" #include "shot_manipulator.h" #include "asw_marine_speech.h" #include "asw_weapon_ammo_bag_shared.h" #endif #include "asw_marine_skills.h" #include "asw_weapon_parse.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" IMPLEMENT_NETWORKCLASS_ALIASED( ASW_Weapon_PDW, DT_ASW_Weapon_PDW ) BEGIN_NETWORK_TABLE( CASW_Weapon_PDW, DT_ASW_Weapon_PDW ) #ifdef CLIENT_DLL // recvprops RecvPropBool(RECVINFO(m_bBulletMod)), #else // sendprops SendPropBool(SENDINFO(m_bBulletMod)), #endif END_NETWORK_TABLE() BEGIN_PREDICTION_DATA( CASW_Weapon_PDW ) #ifdef CLIENT_DLL DEFINE_PRED_FIELD( m_bBulletMod, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), #endif END_PREDICTION_DATA() LINK_ENTITY_TO_CLASS( asw_weapon_pdw, CASW_Weapon_PDW ); PRECACHE_WEAPON_REGISTER(asw_weapon_pdw); ConVar asw_pdw_max_shooting_distance( "asw_pdw_max_shooting_distance", "400", FCVAR_REPLICATED, "Maximum distance of the hitscan weapons." ); extern ConVar asw_weapon_max_shooting_distance; extern ConVar asw_weapon_force_scale; CASW_Weapon_PDW::CASW_Weapon_PDW() { m_bBulletMod = false; } CASW_Weapon_PDW::~CASW_Weapon_PDW() { } #ifndef CLIENT_DLL extern ConVar asw_debug_marine_damage; //--------------------------------------------------------- // Save/Restore //--------------------------------------------------------- BEGIN_DATADESC( CASW_Weapon_PDW ) END_DATADESC() void CASW_Weapon_PDW::Spawn() { BaseClass::Spawn(); } // just dry fire by default void CASW_Weapon_PDW::SecondaryAttack( void ) { // Only the player fires this way so we can cast CASW_Player *pPlayer = GetCommander(); if (!pPlayer) return; CASW_Marine *pMarine = GetMarine(); if (!pMarine) return; SendWeaponAnim( ACT_VM_DRYFIRE ); BaseClass::WeaponSound( EMPTY ); m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; } #endif /* not client */ void CASW_Weapon_PDW::Precache() { // precache the weapon model here? BaseClass::Precache(); } void CASW_Weapon_PDW::PrimaryAttack() { // If my clip is empty (and I use clips) start reload if ( UsesClipsForAmmo1() && !m_iClip1 ) { Reload(); return; } CASW_Player *pPlayer = GetCommander(); CASW_Marine *pMarine = GetMarine(); if (pMarine) // firing from a marine { m_bIsFiring = true; // MUST call sound before removing a round from the clip of a CMachineGun WeaponSound(SINGLE); if (m_iClip1 <= AmmoClickPoint()) { LowAmmoSound(); } // tell the marine to tell its weapon to draw the muzzle flash pMarine->DoMuzzleFlash(); // sets the animation on the weapon model iteself SendWeaponAnim( GetPrimaryAttackActivity() ); // sets the animation on the marine holding this weapon //pMarine->SetAnimation( PLAYER_ATTACK1 ); #ifdef GAME_DLL // check for turning on lag compensation if (pPlayer && pMarine->IsInhabited()) { CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() ); } #endif FireBulletsInfo_t info; info.m_vecSrc = pMarine->Weapon_ShootPosition( ); if ( pPlayer && pMarine->IsInhabited() ) { info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount()); // 45 degrees = 0.707106781187 } else { #ifdef CLIENT_DLL Msg("Error, clientside firing of a weapon that's being controlled by an AI marine\n"); #else info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc ); #endif } // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, // especially if the weapon we're firing has a really fast rate of fire. info.m_iShots = 0; float fireRate = GetFireRate(); while ( m_flNextPrimaryAttack <= gpGlobals->curtime ) { m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate; info.m_iShots++; if ( !fireRate ) break; } // Make sure we don't fire more than the amount in the clip if ( UsesClipsForAmmo1() ) { info.m_iShots = MIN( info.m_iShots, m_iClip1 ); for (int k=0;kGetAmmoCount(m_iPrimaryAmmoType) <= 0 ) { // check he doesn't have ammo in an ammo bay CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast(pMarine->GetASWWeapon(0)); if (!pAmmoBag) pAmmoBag = dynamic_cast(pMarine->GetASWWeapon(1)); if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this)) pMarine->OnWeaponOutOfAmmo(true); } #endif } //m_bBulletMod = !m_bBulletMod; } } else { info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) ); for (int k=0;kRemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );; m_bBulletMod = !m_bBulletMod; } } info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat(); info.m_iAmmoType = m_iPrimaryAmmoType; info.m_iTracerFreq = 1; // asw tracer test everytime info.m_vecSpread = pMarine->GetActiveWeapon()->GetBulletSpread(); info.m_flDamage = GetWeaponDamage(); info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat(); #ifndef CLIENT_DLL if (asw_debug_marine_damage.GetBool()) Msg("Weapon dmg = %f\n", info.m_flDamage); info.m_flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale(); #endif pMarine->FireBullets( info ); // increment shooting stats #ifndef CLIENT_DLL if (pMarine && pMarine->GetMarineResource()) { pMarine->GetMarineResource()->UsedWeapon(this, info.m_iShots); pMarine->OnWeaponFired( this, info.m_iShots ); } #endif } } int CASW_Weapon_PDW::ASW_SelectWeaponActivity(int idealActivity) { switch( idealActivity ) { case ACT_WALK: idealActivity = ACT_MP_WALK_ITEM1; break; case ACT_RUN: idealActivity = ACT_MP_RUN_ITEM1; break; case ACT_IDLE: idealActivity = ACT_MP_STAND_ITEM1; break; case ACT_RELOAD: idealActivity = ACT_RELOAD_PISTOL; break; // short (pistol) reload case ACT_RANGE_ATTACK1: idealActivity = ACT_MP_ATTACK_STAND_ITEM1; break; case ACT_CROUCHIDLE: idealActivity = ACT_MP_CROUCHWALK_ITEM1; break; case ACT_JUMP: idealActivity = ACT_MP_JUMP_ITEM1; break; default: return BaseClass::ASW_SelectWeaponActivity(idealActivity); } return idealActivity; } float CASW_Weapon_PDW::GetWeaponDamage() { //float flDamage = 18.0f; float flDamage = GetWeaponInfo()->m_flBaseDamage; if ( GetMarine() ) { flDamage += MarineSkills()->GetSkillBasedValueByMarine(GetMarine(), ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_PDW_DMG); } //CALL_ATTRIB_HOOK_FLOAT( flDamage, mod_damage_done ); return flDamage; } #ifdef CLIENT_DLL void CASW_Weapon_PDW::OnMuzzleFlashed() { BaseClass::OnMuzzleFlashed(); // UNDONE: flash both guns from ASWUTracerDual // int iAttachment = LookupAttachment( "muzzle_flash_l" ); // if ( iAttachment > 0 ) // { // float flScale = GetMuzzleFlashScale(); // if (GetMuzzleFlashRed()) // { // FX_ASW_RedMuzzleEffectAttached( flScale, GetRefEHandle(), iAttachment, NULL, false ); // } // else // { // FX_ASW_MuzzleEffectAttached( flScale, GetRefEHandle(), iAttachment, NULL, false ); // } // } } float CASW_Weapon_PDW::GetMuzzleFlashScale( void ) { return BaseClass::GetMuzzleFlashScale(); /* // if we haven't calculated the muzzle scale based on the carrying marine's skill yet, then do so if (m_fMuzzleFlashScale == -1) { C_ASW_Marine *pMarine = GetMarine(); if (pMarine) m_fMuzzleFlashScale = 2.0f * MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_MUZZLE); else return 2.0f; } return m_fMuzzleFlashScale; */ } bool CASW_Weapon_PDW::GetMuzzleFlashRed() { return BaseClass::GetMuzzleFlashRed(); //return ((GetMuzzleFlashScale() / 2.0f) >= 1.15f); // red if our muzzle flash is the biggest size based on our skill } #endif // user message based tracer type const char* CASW_Weapon_PDW::GetUTracerType() { return "ASWUTracerDual"; } float CASW_Weapon_PDW::GetFireRate() { //float flRate = 0.035f; float flRate = GetWeaponInfo()->m_flFireRate; //CALL_ATTRIB_HOOK_FLOAT( flRate, mod_fire_rate ); return flRate; }