Difference between revisions of "Throwable weapons"

From Team Fortress Wiki
Jump to: navigation, search
m (Repel: quick-fix thing was for not taking damage, removed)
m (Rewrite of article to remove source code snippets and replace with metadata citations.)
Line 1: Line 1:
 
{{beta|experimental}}
 
{{beta|experimental}}
  
'''Throwable weapons''' were a new class of weapons that were being tested internally by Valve, but were either cut or abandoned.
+
'''Throwable weapons''' were a new class of weapons that were being tested internally by Valve, but were either cut or abandoned for unspecified reasons.
  
 
== Functionality ==
 
== Functionality ==
Throwable weapons were classed as either being "primable" or "chargeable";
+
Throwable weapons were classed as either being "primable" or "chargeable" and this functionality was to be determined via one of two attributes; {{code|is_throwable_primable}} or {{code|is_throwable_chargeable}}.<ref>game\shared\tf_weapon_throwable.cpp:L300-314</ref>
  
<!--Begin-->// Primable is for timed explosions
+
If the player is in water that is above eye level, they would not have been able to use a throwable weapon.
// Charagable is for things like distance or power increases
 
// Can't really have both but can have neither<!--End-->
 
  
== Slots ==
+
== Varieties ==
Throwable slots were apparently considered, with the experimental "Utility" slot making an appearance as well.
 
 
 
<!--Begin-->#ifdef STAGING_ONLY
 
CREATE_SIMPLE_WEAPON_TABLE( TFThrowablePrimary, tf_weapon_throwable_primary )
 
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableSecondary, tf_weapon_throwable_secondary )
 
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableMelee, tf_weapon_throwable_melee )
 
CREATE_SIMPLE_WEAPON_TABLE( TFThrowableUtility, tf_weapon_throwable_utility )
 
#endif<!--End-->
 
 
 
== Throwables ==
 
 
Several varieties of throwable weapons have been discovered.
 
Several varieties of throwable weapons have been discovered.
  
 
=== Repel ===
 
=== Repel ===
A throwable airblast. Throwing it would cause it to apply airblast force to any enemies within range of it, pushing them away and making their view shake;
+
* '''Entity Classname:''' {{code|tf_projectile_throwable_repel}}
 
+
A throwable airblast. Throwing it would cause it to apply airblast force to any enemies within range of it, pushing them away and making their view shake as well as damaging them.<ref>game\shared\tf_weapon_throwable.cpp:L524-572</ref>
<!--Begin-->// Apply AirBlast Force
 
Vector vecToTarget;
 
vecToTarget = pPlayer->GetAbsOrigin() - this->GetAbsOrigin();
 
vecToTarget.z = 0;
 
VectorNormalize( vecToTarget );<!--End-->
 
 
 
<!--Begin-->float flForce = 300.0f * m_flChargePercent + 350.0f;
 
pPlayer->ApplyAirBlastImpulse( vecToTarget * flForce + Vector( 0, 0, flForce ) );
 
pPlayer->ApplyPunchImpulseX( RandomInt( -50, -30 ) );<!--End-->
 
 
 
Enemies also take damage.
 
 
 
<!--Begin-->// Apply Damage to Victim
 
CTakeDamageInfo info;
 
info.SetAttacker( GetThrower() );
 
info.SetInflictor( this );
 
info.SetWeapon( GetLauncher() );
 
info.SetDamage( GetDamage() );
 
info.SetDamageCustom( GetCustomDamageType() );
 
info.SetDamagePosition( this->GetAbsOrigin() );
 
info.SetDamageType( DMG_CLUB | DMG_PREVENT_PHYSICS_FORCE );
 
 
pPlayer->DispatchTraceAttack( info, vecToTarget, &trace );
 
ApplyMultiDamage();<!--End-->
 
  
 
=== Brick ===
 
=== Brick ===
A brick. Highly reminiscent of Timesplitters. Hitting an enemy with it would deal some damage and shake up their view;
+
* '''Entity Classname:''' {{code|tf_projectile_throwable_brick}}
 
+
A brick. Highly reminiscent of Timesplitters. Hitting an enemy with it would deal some damage and shake up their view.<ref>game\shared\tf_weapon_throwable.cpp:L573-609</ref>
<!--Begin-->// Apply Damage to Victim
 
CTakeDamageInfo info;
 
info.SetAttacker( GetThrower() );
 
info.SetInflictor( this );
 
info.SetWeapon( GetLauncher() );
 
info.SetDamage( GetDamage() );
 
info.SetDamageCustom( GetCustomDamageType() );
 
info.SetDamagePosition( GetAbsOrigin() );
 
info.SetDamageType( DMG_CLUB );
 
 
pPlayer->DispatchTraceAttack( info, vecToTarget, &trace );
 
pPlayer->ApplyPunchImpulseX( RandomInt( 15, 20 ) );
 
ApplyMultiDamage();<!--End-->
 
  
 
=== Target Dummy ===
 
=== Target Dummy ===
A portable target dummy. Throwing this would create a Target Dummy. Pretty self-explanatory.
+
* '''Entity Classname:''' {{code|tf_projectile_target_dummy}}
 
+
A portable target dummy. Throwing this would create a standard {{code|tf_target_dummy}} entity.<ref>game\shared\tf_weapon_throwable.cpp:L790-798</ref> For the purposes of internal testing, the {{code|models/props_training/target_engineer.mdl}} and {{code|models/props_training/target_demoman.mdl}} plywood target models were used. Just as they do in training mode, the targets would break into gibs when enough damage has been done to them. It appears that they scrapped the idea before adding in the model selection for the target dummy. How this model selection would have functioned, for example if it were to make the target dummy's class change to mimic that of the thrower, is unknown.
<!--Begin-->void CTFProjectile_ThrowableTargetDummy::Explode()
 
{
 
    CTFPlayer *pPlayer = ToTFPlayer( GetThrower() );
 
    if ( !pPlayer )
 
        return;
 
 
    CTFTargetDummy::Create( GetAbsOrigin(), GetAbsAngles(), pPlayer );
 
    BaseClass::Explode();
 
}<!--End-->
 
 
 
For testing, the {{code|models/props_training/target_engineer.mdl}} and {{code|models/props_training/target_demoman.mdl}} plywood target models were used, and just as they do in training mode, the targets would break into gibs when enough damage has been done to them. It appears that they scrapped the idea before adding in the model selection for the target dummy;
 
 
 
<!--Begin-->#define DUMMY_MODEL "models/props_training/target_engineer.mdl"
 
#define DUMMY_DEMO_MODEL "models/props_training/target_demoman.mdl"
 
 
// TODO: Model Selection
 
if ( RandomInt( 0, 1 ) == 1 )
 
{
 
        SetModel( DUMMY_DEMO_MODEL );
 
        BuildGibList( m_aGibs, GetModelIndex(), 1.0f, COLLISION_GROUP_NONE );
 
}
 
else
 
{
 
        SetModel( DUMMY_MODEL );
 
}<!--End-->
 
 
 
The "Model Selection" mentioned in the code comment ''could'' have been the target dummy choosing the proper {{code|models/props_training/target_<class>.mdl}} model to match the thrower's class, but the actual functionality is not known.
 
  
 
=== Concussion Grenade ===
 
=== Concussion Grenade ===
Return of the Concussion Grenade. It seems Valve had been playing around with trying to bring the Concussion Grenade back somehow.
+
* '''Entity Classname:''' {{code|tf_projectile_grenade_concussion}}
 +
Return of the [[Concussion Grenade]]. It seems Valve had been playing around with trying to bring the Concussion Grenade back somehow. This version would have functioned identically to how it would have initially.<ref>game\shared\tf_weapon_throwable.cpp:L800-874</ref>
  
 
=== Teleport Grenade ===
 
=== Teleport Grenade ===
The Teleport Grenade would teleport the user to wherever the grenade was thrown.
+
* '''Entity Classname:''' {{code|tf_projectile_grenade_teleport}}
 +
The Teleport Grenade would teleport the user to wherever the grenade was thrown.<ref>game\shared\tf_weapon_throwable.cpp:L877-949</ref>
  
<!--Begin-->// Try a few spots
+
=== Gravity Grenade ===
FOR_EACH_VEC_BACK( m_vecTrailingPos, i )
+
* '''Entity Classname:''' {{code|tf_projectile_grenade_gravity}}
{
+
Also referred to in a comment as {{code|Chain Grenade}}<ref>game\shared\tf_weapon_throwable.cpp:L108-114</ref>. A trap style grenade, it functioned similar to a black hole, dragging anyone within range closer to it.<ref>game\shared\tf_weapon_throwable.cpp:L951-1063</ref>
    // Try positions starting with the current, and moving back in time a bit
 
    Vector vecStart = m_vecTrailingPos[i];
 
    UTIL_TraceHull( vecStart, vecStart, VEC_HULL_MIN, VEC_HULL_MAX, nMask, &traceFilter, &traceHull );
 
 
    if ( !traceHull.DidHit() )
 
    {
 
        // Place a teleport effect where they came from
 
        const Vector& vecOrigin = pThrower->GetAbsOrigin();
 
        CPVSFilter pvsFilter( vecOrigin );
 
        TE_TFParticleEffect( pvsFilter, 0.f, GetExplodeEffectParticle(), vecOrigin, vec3_angle );
 
 
        // Move 'em!
 
        pThrower->Teleport( &vecStart, &pThrower->GetAbsAngles(), NULL );
 
 
        // Do a zoom effect
 
        pThrower->SetFOV( pThrower, 0.f, 0.3f, 120.f );
 
 
        // Screen flash
 
        color32 fadeColor = { 255, 255, 255, 100 };
 
        UTIL_ScreenFade( pThrower, fadeColor, 0.25f, 0.4f, FFADE_IN );
 
 
        if ( TFGameRules() )
 
        {
 
            TFGameRules()->HaveAllPlayersSpeakConceptIfAllowed( MP_CONCEPT_PLAYER_SPELL_TELEPORT, ( pThrower->GetTeamNumber() == TF_TEAM_RED ) ? TF_TEAM_BLUE : TF_TEAM_RED );
 
        }
 
    }
 
}<!--End-->
 
  
=== Chain Grenade ===
+
=== Throwing Knife ===
Also referred to in code as the Gravity Grenade. A trap style grenade, it functioned similar to a black hole, dragging anyone within range closer to it.
+
* '''Entity Classname:''' {{code|tf_projectile_throwing_knife}}
<!--Begin-->void CTFProjectile_GravityGrenade::PulseTrap( void )
+
Throwing Knives were tested as well. They would do crits if they hit someone from behind and much like arrows and some other certain projectiles, throwing knives would stick out of the person you hit.<ref>game\shared\tf_weapon_throwable.cpp:L1065-1141</ref>
{
 
    const int nMaxEnts = 32;
 
 
    Vector vecPos = GetAbsOrigin();
 
    CBaseEntity *pObjects[ nMaxEnts ];
 
    int nCount = UTIL_EntitiesInSphere( pObjects, nMaxEnts, vecPos, GetDamageRadius(), FL_CLIENT );
 
 
    // Iterate through sphere's contents
 
    for ( int i = 0; i < nCount; i++ )
 
    {
 
        CBaseCombatCharacter *pEntity = pObjects[i]->MyCombatCharacterPointer();
 
        if ( !pEntity )
 
            continue;
 
 
        if ( InSameTeam( pEntity ) )
 
            continue;
 
 
        if ( !FVisible( pEntity, MASK_OPAQUE ) )
 
            continue;
 
 
        // Draw player toward us
 
        Vector vecSourcePos = pEntity->GetAbsOrigin();
 
        Vector vecTargetPos = GetAbsOrigin();
 
        Vector vecVelocity = ( vecTargetPos - vecSourcePos ) * 2.f;
 
        vecVelocity.z += 50.f;
 
 
        if ( pEntity->GetFlags() & FL_ONGROUND )
 
        {
 
            vecVelocity.z += 150.f;
 
            pEntity->SetGroundEntity( NULL );
 
            pEntity->SetGroundChangeTime( gpGlobals->curtime + 0.5f );
 
        }
 
 
        pEntity->Teleport( NULL, NULL, &vecVelocity );
 
    }
 
 
    // NDebugOverlay::Sphere( vecPos, GetDamageRadius(), 0, 255, 0, false, 0.35f );
 
 
    PulseEffects();
 
}<!--End-->
 
  
 
=== Smoke Grenade ===
 
=== Smoke Grenade ===
Similar to the aforementioned Concussion Grenade, the Smoke Grenade would have been a second go at trying to bring back the Smoke Bomb from the early development days.
+
* '''Entity Classname:''' {{code|tf_projectile_grenade_smoke}}
 
+
Similar to the aforementioned Concussion Grenade, the Smoke Grenade would have been a second go at trying to bring back the Smoke Bomb from the early development days. Being within the smoke cloud would have granted the thrower the unused {{code|TF_COND_OBSCURED_SMOKE}} condition.<ref>game\shared\tf_weapon_throwable.cpp:L1144-1232</ref>
=== Throwing Knife ===
 
Throwing Knives were tested as well. They would do crits if they hit someone from behind and much like arrows and some other certain projectiles, throwing knives would stick out of the person you hit.
 
 
 
<!--Begin-->// Is from behind?
 
bool bIsFromBehind = DotProduct( toEnt, entForward ) > 0.7071f;
 
 
// Apply Damage to Victim
 
CTakeDamageInfo info;
 
info.SetAttacker( GetThrower() );
 
info.SetInflictor( this );
 
info.SetWeapon( GetLauncher() );
 
info.SetDamageCustom( GetCustomDamageType() );
 
info.SetDamagePosition( GetAbsOrigin() );
 
 
int iDamageType = DMG_CLUB;
 
if ( bIsFromBehind )
 
{
 
    iDamageType |= DMG_CRITICAL;
 
}
 
 
info.SetDamageType( iDamageType );
 
info.SetDamage( bIsFromBehind ? GetBackHitDamage() : GetDamage() );
 
 
pVictim->DispatchTraceAttack( info, toEnt, &trace );
 
ApplyMultiDamage();
 
 
CreateStickyAttachmentToTarget( pOwner, pVictim, &trace );<!--End-->
 
  
 
=== Snowball ===
 
=== Snowball ===
The only evidence to the existence of the Snowball is the {{code|MODEL_SNOWBALL}} enum entry from the enumerator used to store model defines for arrow projectiles;
+
The only evidence to the existence of the Snowball is the {{code|MODEL_SNOWBALL}} enum entry from the {{code|arrow_models}} enumerator used to store model defines for certain projectiles.<ref>game\shared\tf\tf_shareddefs.h:L607</ref>
  
''The comments in the code below were added for this article to help clarify what things are and were not written by Valve.''
+
== References ==
<!--Begin-->enum arrow_models
+
<references/>
{
 
    MODEL_ARROW_REGULAR, // Regular arrow
 
    MODEL_ARROW_BUILDING_REPAIR, // Rescue Ranger projectile
 
    MODEL_SNOWBALL, // Snowball?
 
    MODEL_FESTIVE_ARROW_REGULAR, // Festive arrow
 
    MODEL_SYRINGE, // Syringe Gun projectile
 
    MODEL_FESTIVE_HEALING_BOLT, // Festive Crusader's Crossbow
 
    MODEL_BREAD_MONSTER, // Self-Aware Beauty Mark and the other breadmonster Jar item
 
    MODEL_GRAPPLINGHOOK, // Grappling Hook
 
 
    // Staging
 
    MODEL_THROWING_KNIFE, // Throwing Knife, mentioned above
 
 
    TF_ARROW_MODEL_COUNT // # of models in this enumerator which would be 9
 
};<!--End-->
 
  
 
{{Unused content nav}}
 
{{Unused content nav}}

Revision as of 09:29, 12 May 2020

Throwable weapons were a new class of weapons that were being tested internally by Valve, but were either cut or abandoned for unspecified reasons.

Functionality

Throwable weapons were classed as either being "primable" or "chargeable" and this functionality was to be determined via one of two attributes; is_throwable_primable or is_throwable_chargeable.[1]

If the player is in water that is above eye level, they would not have been able to use a throwable weapon.

Varieties

Several varieties of throwable weapons have been discovered.

Repel

  • Entity Classname: tf_projectile_throwable_repel

A throwable airblast. Throwing it would cause it to apply airblast force to any enemies within range of it, pushing them away and making their view shake as well as damaging them.[2]

Brick

  • Entity Classname: tf_projectile_throwable_brick

A brick. Highly reminiscent of Timesplitters. Hitting an enemy with it would deal some damage and shake up their view.[3]

Target Dummy

  • Entity Classname: tf_projectile_target_dummy

A portable target dummy. Throwing this would create a standard tf_target_dummy entity.[4] For the purposes of internal testing, the models/props_training/target_engineer.mdl and models/props_training/target_demoman.mdl plywood target models were used. Just as they do in training mode, the targets would break into gibs when enough damage has been done to them. It appears that they scrapped the idea before adding in the model selection for the target dummy. How this model selection would have functioned, for example if it were to make the target dummy's class change to mimic that of the thrower, is unknown.

Concussion Grenade

  • Entity Classname: tf_projectile_grenade_concussion

Return of the Concussion Grenade. It seems Valve had been playing around with trying to bring the Concussion Grenade back somehow. This version would have functioned identically to how it would have initially.[5]

Teleport Grenade

  • Entity Classname: tf_projectile_grenade_teleport

The Teleport Grenade would teleport the user to wherever the grenade was thrown.[6]

Gravity Grenade

  • Entity Classname: tf_projectile_grenade_gravity

Also referred to in a comment as Chain Grenade[7]. A trap style grenade, it functioned similar to a black hole, dragging anyone within range closer to it.[8]

Throwing Knife

  • Entity Classname: tf_projectile_throwing_knife

Throwing Knives were tested as well. They would do crits if they hit someone from behind and much like arrows and some other certain projectiles, throwing knives would stick out of the person you hit.[9]

Smoke Grenade

  • Entity Classname: tf_projectile_grenade_smoke

Similar to the aforementioned Concussion Grenade, the Smoke Grenade would have been a second go at trying to bring back the Smoke Bomb from the early development days. Being within the smoke cloud would have granted the thrower the unused TF_COND_OBSCURED_SMOKE condition.[10]

Snowball

The only evidence to the existence of the Snowball is the MODEL_SNOWBALL enum entry from the arrow_models enumerator used to store model defines for certain projectiles.[11]

References

  1. game\shared\tf_weapon_throwable.cpp:L300-314
  2. game\shared\tf_weapon_throwable.cpp:L524-572
  3. game\shared\tf_weapon_throwable.cpp:L573-609
  4. game\shared\tf_weapon_throwable.cpp:L790-798
  5. game\shared\tf_weapon_throwable.cpp:L800-874
  6. game\shared\tf_weapon_throwable.cpp:L877-949
  7. game\shared\tf_weapon_throwable.cpp:L108-114
  8. game\shared\tf_weapon_throwable.cpp:L951-1063
  9. game\shared\tf_weapon_throwable.cpp:L1065-1141
  10. game\shared\tf_weapon_throwable.cpp:L1144-1232
  11. game\shared\tf\tf_shareddefs.h:L607