Resource icon

[VScript] give_tf_weapon GTFW is now Retired

Hey everybody,

Thank you for taking the time to read this.
I believe the time is right to say: I am now retiring GTFW.

TF2's VScript has had enough time to develop. I believe the TF2 Community now have enough experience to be able to make their own, better custom weapon scripts.

Brief history: GTFW was my first time testing the waters of a written coded language. It ended up getting into TF2 by Heaven's grace (@LizardOfOz for VSH, and Valve). Big thanks to them. And, by this notion, I've wanted to keep this updated for future VScripters to use.

My dream was to make weapon-giving easy for everyone, to allow fast access of custom weapons to be packed into anyone's library.

Ultimately, I admit the code is a bit of a mess. Ever since GTFW's first release, I've been trying to optimize the code (with 100+ updates to this thing), but due to my limited knowledge of organizing written code, the whole thing is pretty much unusable. How unfortunate! I've learned a whole heck of a lot from this script, but I just really don't want to maintain it anymore.

Thankfully, making weapons is easier than you might believe. There are plenty of resources now online that tell you just how to do just this. So really, you don't need GTFW to do the dirty work.

Iterating through player's loadout
Giving a weapon

You are free to use my script for however you want to use it. Just understand that it needs a lot of rework, and I believe there are some useful tricks in here. Yet, it is convoluted. It is Messy. It was my stepping stone to be a better coder. And now I'm letting go of it.

Bye, GTFW. You served well, and now it's time for me to move on.
EDIT: Hey VScripter, I kinda messed this update up and it is kinda broken. I'm sorry. Right as I uploaded I found bugs, sooo. Yeah.

Original Post

This update is pretty important. It makes use of A LOT of Squirrel techniques I've learned since I first started this project. This might not be the best-written vscript since it first came out, but hey I'm trying to make it valuable!

Anyway, enough rambling. We have bug fixes and new features to talk about!

  • Please be sure to read "give_tf_weapon/_master.nut" because you need it if you intend to integrate this script into your own projects.
  • It has a lot of modular features that might be confusing at face, so I hope having references will help clear that up.

Major Update 5.4.0 Changelog

  • Added long overdue feature of writing weapon info from GTFW to weapon's scope.
    • Use for finding the weapon's real name, how much max ammo it carries, ammo type, ItemDefinitionIndex, etc. Or any of the GTFW-specific bits, like what function you tied to the weapon after it spawns, class arms animations, etc etc. It is all there.
For use on individual weapons:
GTFW.WriteTableToWeaponScope( player, weapon );
For writing to the entire loadout at once:
GTFW.WriteTableToWeaponScope_EntireLoadout( player );

( Currently, this writes to the entire loadout any time you give a weapon. And for GetWeapon() )

  • Added feature to fix class animations for unintended weapons.
    • Whenever a player uses a weapon unintended for that class, the player's world model will use animations of the class it's intended for.
( By default, GiveWeapon() will ONLY fix ref-poses and any ITEM animations )
( However, there is an option you can enable for it to apply to all weapons. Read _master.nut please)

  • Added function GetAllWeapons()
    • This scans the player loadout for any passive and non-passive weapons, then spits out an array with handles for all loadout weapons.
Use:
local this_is_an_array = player.GetAllWeapons();
foreach(k, wep in this_is_an_array) printl( wep );

- Compared to GetWeapon(), it should be very cheap process-wise to use, due to not having to parse the parameter you put in. It grabs everything for you all at once. Very nice.

  • Updated the think script that manages first and third person fixups
    • It has been completely rewritten to fix bugs and to improve processing times.
    • Now keeps track of a few events, and only runs the fixups functions one time per event.
    • The three events it tracks are when the player has switched weapons, or has taunted, or just toggled thirdperson mode.
    • Then it idles and just watches your character. Constantly. Unwaveringly. Just creepy.
Also fixes bugs taunt props being invisible, and the custom viewmodel class hands not working for Gunslinger or Heavy's fists.
(I think the prior update had a debug message using ClientPrint()? Oops!)

  • Added feature to set player's first person hands model.
    • You can set it for one-time use, or have it saved to memory for that tfclass so it always uses it.
    • Also comes with deleting and loading functions.
Use:
player.SetCustomClassArms( "model_path", optional_save_feature );​
player.DeleteCustomClassArms( optional_tfplayerclass_filter );
player.GTFW_RestoreCustomClassArms();
Basically, you can put in your model path and it will change the class hands to that model.
optional_save_feature is default false. If true, it will save your model_path to that tfclass you set it to, which means it is basically permanent. Otherwise, it only lasts until GTFW_Cleanup() removes it.

Warning: Just understand your entity count will be higher if you intend to use this for a lot of players. I'm going to be briefly technical, it creates 2 entities per weapon in the loadout, plus the classarms themselves. You can figure out the math from there. It just gets big, and it may crash the server if it hits the ent limit.

-------------

And here is the rest of the changelog. Woo hoo!

Updated GTFW_Cleanup()
- Any wearables made by GTFW are placed into the player's scope.
- For reference, before using scopes I just changed their targetname and used I/O to kill them... ...

Updated RegisterCustomWeapon()
- fixed bug with re-registering the same item using all the unique IDs.
- removed advanced bit clearing loops in favor of simpler bit math. (should improve process speed)

Updated SwitchToBest()
- Fixed bug with not switching weapons when you aren't actively holding anything.

Fixed bug in GTFW.GetAmmoFix() throwing error on invalid instance
Fixed Sandman and Cleaver not having ammo
Fixed DeleteWeapon() not switching weapons if current weapon was null

and finally I turned off debug mode by default ( CVAR_GTFW_DEBUG_MODE <- false ) !!!
  • 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.

Changelog
  • 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!
NOTE BEFORE UPDATING:
  • 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.
1681095799630.png


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 table.name)
  • Can announce weapons found in chat
  • code.nut: Added framework to use slots for GiveWeapon, RegisterCustomWeapon
    • Use enum TF_WEAPONSLOTS (PRIMARY, SECONDARY, MELEE, SLOT3, SLOT4, SLOT5, SLOT6)
    • 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

Attachments

  • Untitled.png
    Untitled.png
    594.2 KB · Views: 71
  • 1681159922089.png
    1681159922089.png
    73.2 KB · Views: 93
  • (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

Attachments

  • mvm_lost_a10003.jpg
    mvm_lost_a10003.jpg
    581.9 KB · Views: 82