Resource icon

[VScript] give_tf_weapon 5.3.0

  • Site Migration: See bugs? Report them here. Want something changed or have an idea? Suggest it here.
  • Something not downloading? Download authors read this.
  • Fixed custom weapon viewmodels from not playing animations
    • This was due to an netprop model override "m_nModelIndexOverrides" being set for custom third person model. While it fixes crit glows, it also breaks viewmodel animations. Good to know!
    • The fix here was using the old method: Having a custom "tf_wearable" for third person models. Taunting and third person modes display correctly in this version.
  • Added "worldspawn" to GTFW_Cleanup
  • Fixed custom fists viewmodel becoming invisible by taunting
  • Fixed GiveWeapon() PostWepFix_Override replacing the table outright instead of modifying it.
  • Fixes for Passive items ("tf_wearable")
    • Added check for passive weapon slots >7 to check for other passive items
    • Added fix for "tf_wearable" by changing the classname to "tf_wearable_vs".
    • Fixed bug with custom wearable would not have the correct item ID
  • Fixes for SwitchToBest()
    • Added 0.01 delay for SwitchToBest() for weapon switching (due to bug with overlapping VM on custom weapon)
    • Added additional check for "weapon" in classname string (for weapons that are disabled weapon via classname changes)
  • Updated "GTFW_Cleanup()"
    • Now it uses a single line of I/O to find weapons, because apparently finding the parented weapons on the player wasn't working! Frustration. Good news is, it works!
Special thanks @Unicake and @SpookyToad for bug reports.

  • Fixed not being able to hit Engineer buildings if you give "Engy Toolbox" and have a wrench
  • Fixed Demo shields deleting themselves on respawn
  • Updated "Example Half-Life Shotgun.nut"
    • Fixed alt-fire animations not matching class
    • Fixed throw error
  • Updated "Example Horsemann's Hex.nut"
    • Fixed using an undefined variable
  • Fixed custom weapons not updating custom arms
  • Fixed passive weapons like Targe always deleting when giving any weapon
  • Fixed item definition index overrides not updating tf_class on CustomWeaponRegistration
Have a good day!
  • Both RegisterCustomWeapon() and GiveWeapon() have different parameters, and are incompatible with previous versions. Please update your code so it works with this update!
  • A lot of other functions (like ReturnWeaponTable()) have had their name changed. In this case, ReturnWeaponTable() is now GetWeaponTable().

I'll try my best to not have y'all revise your own scripts constantly like I did before. Thank you for understanding!

Highlights of v5.0.0.
  • Passive weapons!
    • Can now give yourself the B.A.S.E. Jumper, Targe, Danger Shield, Mantreads and other passive weapons.
  • More custom weapons!
    • Can register up to 63 weapons that use the same item definition index.
  • Fixes!
    • Weapons names input into these functions can be any letter case (i.e. "MINIgun" still gives you the stock Minigun)
  • Crit glows!
    • In thirdperson only though. Custom weapons no longer need tf_wearable for thirdperson model (datamap "m_nModelIndexOverrides" overrides any tf_weapon model!)
  • Mix Item Definition Index and Classnames, with ease!
    • Can override the item definition index to make things like an all-class Reserve Shooter (if primary... classname "tf_weapon_shotgun_primary" + IDX 415), or a bat that can backstab (classname "tf_weapon_knife" + IDX 0).
  • Organized!
    • I reorganized all the code into different files. Most functions are in separate .nut files now!
    • And custom weapons are in their own folder!
  • Tutorials Galore!
    • Comes with more example weapons!

Full Changelog
  • Updated GiveWeapon() && RegisterCustomWeapon()
    • Overhauled and simplified how parameters are managed. Too many parameters in functions causes headaches.
    • Deleted all model and ammo parameters. These parameters now fit inside a function.
    • If valid, this function is executed inside GTFW.PostWepFix()--a function that updates all params when sent through GetWeaponTable().
    • Cool things you can do with this: Typing "shotgun" as a classname will update the weapon depending on the player class.
  • Updated GiveWeapon().
    • New param order looks like:
    • GiveWeapon(
      • weapon_name/IDX/classname,
        • No changes; Accepts weapon names, Item Definition Index, classnames.
      • ItemDefinitionIndex_Override = weapon_name/IDX,
        • Allows overriding the weapon Item Definition Index with base classname, to change animations and such
      • gw_props = Defaults,
        • Adds what were CVARs here, fit into a bit system
      • PostWepFix_Override = function (table,player) {},
        • Updates various parameters like ammo, weapon models, class arm animations, etc.
      • stats_function_Override=null
        • Stats function; add attributes and think scripts here.
      • )
        • end!
    • NOTE: You don't need all these parameters when giving a weapon. You can still use GiveWeapon("Wrench") in those cases!
    • All this stuff has examples in the download, by the way.
  • Updated RegisterCustomWeapon()
    • Essentially GiveWeapon(). Accepts a custom name of your weapon in the database as first parameter, then the rest of the params are 1-for-1 the same after.
    • Added extra check for names so weapons can't use another weapon's name
      • If CVAR_GTFW_DEBUG_MODE = true, ignores this check.
  • Updated SwitchToActive()
    • Updated name to SwitchToBest()
    • Optimized code. Now uses switch:case method to checks if you have the weapon, then switches to it.
    • Switching weapons is now delayed by a few frames, so it doesn't try to switch to a weapon that doesn't exist anymore.
    • Fixed bug where getting a weapon with custom class arms for the first time breaks switching animation on first switch-to.
  • Can now give yourself the B.A.S.E. Jumper, Targe, Razorback, Mantreads and other passive weapons.
    • Demo shields cannot charge for some reason, even on Demo.
    • Everything other passive stats work, though!
  • Updated LoadLoadout()
    • Loads items backwards (slot6 -> slot0) instead of the other way ( slot0 -> slot6 ) due to weapons autoswitching
    • Can now add even more slots to save by, if you so choose to. Allows for saving/loading passive wearables in your map per class!
  • Fixed bug where sappers would let you build Dispensers (Thanks @Unicake for the bug report!)
  • Added netpropsperf (Thanks ficool2)
    • Reduces NetProp runtime by ~20%! Woo!
  • Added optional text_listener.nut
    • Simple "!give" chat command. Give yourself a weapon through chat!

I probably forgot something somewhere. If someone catches it, please report here or Discord.

Thank you!
  • Removed ClearEventCallbacks() from _master.nut
  • Fixed weapons reappearing when switching to other weapons
  • Removed "GTFW_" prefix for functions GTFW_LoadLoadout, GTFW_SaveLoadout, GTFW_DeleteLoadout.
    • Named LoadLoadout(), SaveLoadout(), DeleteLoadout(), respectively
    • (GTFW_LoadLoadout, GTFW_SaveLoadout, GTFW_DeleteLoadout still work though)
  • Added "ReturnWeaponTable()" (works like CTFPlayer.ReturnWeaponTable() but without player handle)
  • Ammo Fixes
    • Fixed forced AmmoType not being enforced
    • Fixed forced reserve ammo not being enforced
    • I think I fixed the 0 ammo reserve?
  • Fixed broken loop when using tf_weapon_builder entities
Going to try to make more examples of how to use this script eventually.
And to find a way to customize weapon classnames+Item Definition Index, because these seem to change sound/display/other properties on spawn.

New functions
  • CTFPlayer.AnnounceWeapon( weapon , int quality , string/int prefix , string has_string)
    • Display in chat a weapon a player has found!
    • weapon can be a handle, item definition index, string name, slot number (in negative), or classname. Just as long as the weapon is registered and has a valid display name, it's good!
    • quality is from a pre-made list (documented in the function), OR it can be a unicode for color. ( Valve Dev Community on VScript ClientPrint )
  • Examples
    • GetListenServerHost().AnnounceWeapon("Horsemann's Hex")
    • hPlayer.AnnounceWeapon("Natascha", 10)
    • hPlayer.AnnounceWeapon("Toolbox", 9, "VSCRIPT-MADE")
    • hPlayer.AnnounceWeapon("Medigun", 8, 18, "has stolen:")
    • 1681092827108.png
Persisting Weapons
You can now keep your custom VScript weapons after touching resupply!
Note: Make sure to update your post_inventory_application event to include the GTFW_LoadLoadout function.
Note: Weapons don't save automatically. MUST run GTFW_SaveLoadout( weapon ) after you collect a weapon.
  • CTFPlayer.GTFW_SaveLoadout( weapon , int tfclass)
    • Note: If no parameters set, saves ALL items in loadout (even non-vscript weapons!)
  • CTFPlayer.GTFW_LoadLoadout( weapon, int tfclass )
  • CTFPlayer.GTFW_DeleteLoadout( weapon, int tfclass )
  • GTFW_DeleteAllLoadouts()
"weapon" an optional parameter. So is "tfclass".
If both are is not included, it'll run the loadout for the player's current TFClass.
If "weapon" is included ( same parameter framework as ReturnWeapon() ) you can save a specific weapon to the player's loadout.
If "tfclass" is included, it'll specifically save for that TFclass on the player.

Full changelog for 4.0.0
  • Fixed bug with tf_weapon_builder not updating arms when placing a building
  • Added feature to send in item definition index when creating an extra wearable item (i.e. buff banner backpack replacement, medi pack replacement, etc).
  • Fixed extra wearables being invisible in third person due to not being initialized
  • Fixed extra wearables using netprop "m_hExtraWearable", which was already used for custom weapons
  • GiveWeapon(): Actually fixed stats function override from 3.3.2
  • Added weapons that persist between resupply. This loadout can be loaded at any time using function "CTFPlayer.GTFW_LoadLoadout()"
  • Can now find get weapon string names via table (via
  • Can announce weapons found in chat
  • code.nut: Added framework to use slots for GiveWeapon, RegisterCustomWeapon
    • Can also use classnames too
  • tables.nut: Fixed Quick-Fix itemID being 441 (meant to be 411)
  • Changed how GiveWeapon() gives weapons to player
    • Should be able to update loadouts faster
  • _master.nut: Cvar name changed for clarification: CVAR_GTFW_OVERWRITE_WEAPONS -> CVAR_GTFW_GIVEWEAPON_UPDATE_WEP_IDX_ONLY
  • Ammo fixes
    • Split AmmoFix code into its own function, CTFPlayer.UpdateAmmoFix()
    • Fixed bugs where ammo reserve cap wouldn't update correctly between weapons/classes (example, Huntsman -> Minigun)
  • Added version number in _master.nut
  • And fixed a lot of miscellaneous bugs
  • And simplified code here and there


  • Untitled.png
    594.2 KB · Views: 44
  • 1681159922089.png
    73.2 KB · Views: 50
  • (from 3.3.0) Fixed gunslinger being removed on GTFW_Cleanup()
  • (from 3.3.1) Fixed new forced_function overrides not working
  • Fixed custom weapons being visible during losing states (still probably visible during stuns, however)
  • Fixed bug in MvM/upgrade stations with custom weapons where buying a body upgrade buys several at no cost
  • To fix arrays/tables clearing after rebooting the script, added move_rope "magic rope" entity that auto-loads give_tf_weapon .nut files (which persists between rounds)
Still a bug where giving the same weapon twice will remove the weapon from the player. Still looking for the fix.
  • Updated "RegisterCustomWeapon".
    • Removed "RegisterCustomWeaponEx" code because it was redundant
      • It still works, however.
    • Fixed bug where registering through console threw an error
  • Updated "GiveWeapon".
    • Added extra switches and parameters for custom weapons.
    • GiveWeapon (weapon_name, bool force_overwrite, bool force_clear_stats, bool force_custom, function force_stats_function, string force_class_arms, string force_custom_w_model, string force_custom_v_model, string force_extra_wearable, int force_ammotype, int force_clipsize, int force_ammoreserve)
      • These can be added or excluded from the function.
      • i.e. If in MvM and Engineer, can give yourself this weapon like in the attached screenshot:
      • ME.GiveWeapon("Wrench",false,true,true,null,GTFW_ARMS.SOLDIER,"models/weapons/c_models/c_shovel/c_shovel.mdl")
      • But also ME.GiveWeapon("Wrench") still works
  • Made script more compatible with MvM/Upgrade stations (see above)
  • Fixed bug where taunting after switching from a custom weapon would make the active weapon invisible
  • Fixed CTFPlayer.HasGunslinger throwing a lot of errors
  • Removed some error throws
  • Cleaned up code


  • mvm_lost_a10003.jpg
    581.9 KB · Views: 49
  • Trying to get it compatible with MvM / upgrade stations.
    • Added variable CVAR_GTFW_OVERWRITE_WEAPONS under _master.nut
      • true by default
      • true = weapon in slot is deleted before making the new weapon (via GiveWeapon)
      • false = weapon in slot is not deleted. Instead, the item definition index is changed so the weapon can store upgrades from upgrade stations. It supports custom weapons, too!
        • (it's recommended to reset the stats by using this code:
        • NetProps.SetPropBool(handle hWeapon, "m_AttributeManager.m_Item.m_bOnlyIterateItemViewAttributes", true)
  • Fixed CTFPlayer.SwitchToActive(wep)
  • Added ficool2 fix for handling spy watches


  • mvm_aeon_a17_1.png
    895.8 KB · Views: 72
  • Updates tables.nut
    • Removed all ID2's from every weapon entry that had null in them.
    • Made any unique stock weapon into it's own entry. Each stock weapon is another entry named "Unique <weapon>".
      • Some promos were also made into another entry (Vintage Lugermorph, Genuine Huo-Long Heater, etc)
    • Removed Festives class (removed bc it was a dupe)
      • Moved all entries into TF_WEAPONS class + TF_WEAPONS_ALL array
    • Fixed "Grappling Hook" having an extra space in classname, causing giving the weapon to fail.
  • Updated code.nut to reflect above changes.