//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void RecvProxy_HealingTarget( const CRecvProxyData *pData, void *pStruct, void *pOut ) { CWeaponMedigun *pMedigun = ((CWeaponMedigun*)(pStruct)); if ( pMedigun != NULL ) { pMedigun->ForceHealingTargetUpdate(); } RecvProxy_IntToEHandle( pData, pStruct, pOut ); }
void CTFBonesaw::UpdateChargePoseParam( void ) { CTFPlayer *pOwner = GetTFPlayerOwner(); if ( !pOwner ) return; CWeaponMedigun *pMedigun = pOwner->GetMedigun(); if ( pMedigun ) { SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); if ( vm ) vm->SetPoseParameter( "syringe_charge_level", pMedigun->GetChargeLevel() ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CHudMedicChargeMeter::OnTick( void ) { C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !pPlayer ) return; CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); if ( !pWpn || ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN ) ) return; CWeaponMedigun *pMedigun = static_cast< CWeaponMedigun *>( pWpn ); if ( !pMedigun ) return; float flCharge = pMedigun->GetChargeLevel(); if ( flCharge != m_flLastChargeValue ) { if ( m_pChargeMeter ) { m_pChargeMeter->SetProgress( flCharge ); } if ( !m_bCharged ) { if ( flCharge >= 1.0 ) { g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicCharged" ); m_bCharged = true; } } else { // we've got invuln charge or we're using our invuln if ( !pMedigun->IsReleasingCharge() ) { g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicChargedStop" ); m_bCharged = false; } } } m_flLastChargeValue = flCharge; }
// ----------------------------------------------------------------------------- // Purpose: // Note: Think function to delay the impact decal until the animation is finished // playing. // ----------------------------------------------------------------------------- void CTFWeaponBaseMelee::Smack( void ) { trace_t trace; CBasePlayer *pPlayer = GetPlayerOwner(); if ( !pPlayer ) return; #if !defined (CLIENT_DLL) // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); #endif // We hit, setup the smack. if ( DoSwingTrace( trace ) ) { // Hit sound - immediate. if( trace.m_pEnt->IsPlayer() ) { WeaponSound( MELEE_HIT ); } else { WeaponSound( MELEE_HIT_WORLD ); } // Get the current player. CTFPlayer *pPlayer = GetTFPlayerOwner(); if ( !pPlayer ) return; Vector vecForward; AngleVectors( pPlayer->EyeAngles(), &vecForward ); Vector vecSwingStart = pPlayer->Weapon_ShootPosition(); Vector vecSwingEnd = vecSwingStart + vecForward * 48; #ifndef CLIENT_DLL // Do Damage. int iCustomDamage = TF_DMG_CUSTOM_NONE; float flDamage = GetMeleeDamage( trace.m_pEnt, iCustomDamage ); int iDmgType = DMG_BULLET | DMG_NEVERGIB | DMG_CLUB; if ( IsCurrentAttackACrit() ) { // TODO: Not removing the old critical path yet, but the new custom damage is marking criticals as well for melee now. iDmgType |= DMG_CRITICAL; } CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon(); CTFUbersaw *pUbersaw = dynamic_cast<CTFUbersaw*>(pWpn); CWeaponMedigun *pMedigun = static_cast<CWeaponMedigun*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_MEDIGUN)); if (pMedigun && pUbersaw) { if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber()) { pMedigun->AddCharge(); } } CWeaponKritzkrieg *pKritzkrieg = static_cast<CWeaponKritzkrieg*>(pPlayer->Weapon_OwnsThisID(TF_WEAPON_KRITZKRIEG)); if (pKritzkrieg && pUbersaw) { if(trace.m_pEnt->IsPlayer() && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber()) { pKritzkrieg->AddCharge(); } } CTakeDamageInfo info( pPlayer, pPlayer, flDamage, iDmgType, iCustomDamage ); CalculateMeleeDamageForce( &info, vecForward, vecSwingEnd, 1.0f / flDamage * tf_meleeattackforcescale.GetFloat() ); trace.m_pEnt->DispatchTraceAttack( info, vecForward, &trace ); ApplyMultiDamage(); OnEntityHit( trace.m_pEnt ); #endif // Don't impact trace friendly players or objects if ( trace.m_pEnt && trace.m_pEnt->GetTeamNumber() != pPlayer->GetTeamNumber() ) { #ifdef CLIENT_DLL UTIL_ImpactTrace( &trace, DMG_CLUB ); #endif m_bConnected = true; } } #if !defined (CLIENT_DLL) lagcompensation->FinishLagCompensation( pPlayer ); #endif }
void CTFPowerupBottle::ReapplyProvision() { CTFWearable::ReapplyProvision(); CBaseEntity *owner = this->GetOwnerEntity(); if (owner == nullptr) { return; } IHasAttributes *owner_ihasattr = owner->GetHasAttributesInterfacePtr(); if (owner_ihasattr == nullptr) { return; } if (this->m_bActive) { if (!owner_ihasattr->GetAttributeManager()->IsBeingProvidedToBy(this)) { this->GetAttributeManager()->ProvideTo(owner); } } else { this->GetAttributeManager()->StopProvidingTo(owner); } CTFPlayer *player = dynamic_cast<CTFPlayer *>(owner); if (player == nullptr) { return; } /* BUG: because "canteen_specialist" is an integer attribute, the call to * AttribHookValue<int> will truncate any fractional part of the powerup * duration */ float duration = CAttributeManager::AttribHookValue<float>(0.0f, "powerup_duration", this, nullptr, true); duration = CAttributeManager::AttribHookValue<int>((int)duration, "canteen_specialist", player, nullptr, true); CTFPlayer *share_with = nullptr; int share_attr = 0; if (player->IsPlayerClass(TF_CLASS_MEDIC)) { CTFWeaponBase *weapon = player->GetActiveWeapon(); if (weapon != nullptr) { CWeaponMedigun *medigun = dynamic_cast<CWeaponMedigun *>(weapon); if (medigun != nullptr) { share_with = ToTFPlayer(medigun->GetHealTarget()); if (share_with != nullptr) { share_attr = CAttributeManager::AttribHookValue<int>(0, "canteen_specialist", player, nullptr, true); } } } } bool did_share = false; if (CAttributeManager::AttribHookValue<int>(0, "critboost", this, nullptr, true) != 0) { if (this->m_bActive) { player->m_Shared.AddCond(TF_COND_CRITBOOSTED_USER_BUFF, duration); if (share_with != nullptr && share_attr != 0) { share_with->m_Shared.AddCond(TF_COND_CRITBOOSTED_USER_BUFF, duration); did_share = true; } } else { player->m_Shared.RemoveCond(TF_COND_CRITBOOSTED_USER_BUFF, true); } } if (CAttributeManager::AttribHookValue<int>(0, "ubercharge", this, nullptr, true) != 0) { if (this->m_bActive) { player->m_Shared.AddCond(TF_COND_INVULNERABLE_USER_BUFF, duration); if (player->IsPlayerClass(TF_CLASS_ENGINEER)) { int obj_count = player->GetObjectCount(); if (obj_count > 0) { for (int i = obj_count - 1; i != -1; --i) { CBaseObject *obj = player->GetObject(i); if (obj != nullptr) { CObjectSentrygun *sentry = dynamic_cast<CObjectSentrygun *>(obj); if (sentry != nullptr && !sentry->m_bCarried) { sentry->m_nShieldLevel = 2; // TODO: set float @ CObjectSentrygun+0xb14 // to gpGlobals->curtime + duration } } } } } else if (share_with != nullptr && share_attr != 0) { share_with->m_Shared.AddCond(TF_COND_INVULNERABLE_USER_BUFF, duration); did_share = true; } } else { player->m_Shared.RemoveCond(TF_COND_INVULNERABLE_USER_BUFF, true); } } if (CAttributeManager::AttribHookValue<int>(0, "recall", this, nullptr, true) != 0) { if (this->m_bActive) { player->ForceRespawn(); player->m_Shared.AddCond(TF_COND_SPEED_BOOST, 7.0f); } } if (CAttributeManager::AttribHookValue<int>(0, "refill_ammo", this, nullptr, true) != 0) { if (this->m_bActive) { for (int i = 0; i < MAX_WEAPONS; ++i) { CBaseCombatWeapon *weapon = player->GetWeapon(i); if (weapon == nullptr) { continue; } /* BUG: as soon as this loop hits a weapon which is completely * devoid of ammo (clip 0, reserve 0), it will * (a) fail to refill the clip for that weapon, and * (b) fail to refill the clip for any weapons in later slots * NOTE: for the purposes of this, energy weapons are treated as * if their reserve ammo is always empty */ if (TFGameRules() != nullptr && TFGameRules()->IsMannVsMachineMode() && ((weapon->UsesPrimaryAmmo() && !weapon->HasPrimaryAmmo()) || (weapon->UsesSecondaryAmmo() && !weapon->HasSecondaryAmmo()))) { player->AwardAchievement(TF_MVM_USE_AMMO_BOTTLE); break; } /* BUG: doesn't refill clip of energy weapons * (should vcall weapon->IsEnergyWeapon, * then call weapon->Energy_Recharge * until weapon->Energy_FullyCharged) */ // CBaseCombatWeapon::UsesPrimaryAmmo: // - if m_iPrimaryAmmoType < 0: return false // - else: return true // CBaseCombatWeapon::UsesSecondaryAmmo: // - if m_iSecondaryAmmoType < 0: return false // - else: return true // CTFWeaponBaseGun::HasPrimaryAmmo: // - there's a special case if m_iPrimaryAmmoType == TF_AMMO_METAL (e.g. Widowmaker) // - if UsesClipsForAmmo1(): return (m_iClip1 > 0) || (pOwner->GetAmmoCount(m_iPrimaryAmmoType) > 0) // - else: return (pOwner->GetAmmoCount(m_iPrimaryAmmoType) > 0) // CBaseCombatWeapon::HasSecondaryAmmo: // - if UsesClipsForAmmo1(): return (m_iClip2 > 0) || (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) // - else: return (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) weapon->GiveDefaultAmmo(); if (share_with != nullptr && share_attr != 0) { CBaseCombatWeapon *share_weapon = share_with->GetWeapon(i); if (share_weapon != nullptr) { share_weapon->GiveDefaultAmmo(); did_share = true; } } } /* NOTE: invented TF_AMMO_SOURCE_RESUPPLY for (EAmmoSource)1 */ if (share_with != nullptr && share_attr != 0) { for (int i = 0; i < TF_AMMO_COUNT; ++i) { player->GiveAmmo(player->GetMaxAmmo(i), i, true, TF_AMMO_SOURCE_RESUPPLY); share_with->GiveAmmo(share_with->GetMaxAmmo(i), i, true, TF_AMMO_SOURCE_RESUPPLY); } did_share = true; } else { for (int i = 0; i < TF_AMMO_COUNT; ++i) { player->GiveAmmo(player->GetMaxAmmo(i), i, true, TF_AMMO_SOURCE_RESUPPLY); } } } } if (CAttributeManager::AttribHookValue<int>(0, "building_instant_upgrade", this, nullptr, true) != 0) { if (this->m_bActive) { int obj_count = player->GetObjectCount(); if (obj_count > 0) { for (int i = obj_count - 1; i != -1; --i) { CBaseObject *obj = player->GetObject(i); if (obj != nullptr) { int max_level = obj->GetMaxUpgradeLevel(); if (obj->m_bCarried) { /* BUG: this can't possibly be right */ obj->m_iHighestUpgradeLevel = obj->GetMaxUpgradeLevel(); } else if (obj->GetUpgradeLevel() == max_level) { obj->SetHealth(obj->GetMaxHealth()); } else { if (TFGameRules() && TFGameRules()->IsMannVsMachineMode()) { // TODO: event mvm_quick_sentry_upgrade } obj->DoQuickBuild(true); } } } } } } if (did_share) { // TODO: event mvm_medic_powerup_shared } }