Ammo Progress Bar for HUD: Reading SWEP Values? Data Storage? Net Library??

I’ve been beating my head against this desk for somewhere around three days now trying to figure out how to make a progress bar for ammo in a custom HUD I’m modding the way TTT displays it. I first tried extracting the code from TTT, but when adding it to my HUD the code did nothing. I’ve come up with two different approaches, but can’t implement either of them successfully. I want to somehow get the total size of the primary clip and use it as the total value like so: surface.DrawRect( x, y, math.floor(math.clamp(bulletsremaining / clipsize,0,barwidth)), h) whereas the math.clamp should down- or up-convert the decimal to percentage of bar width.

Method 1: Dynamic Variable Extraction

Method 2: Pre-Defined Manual Storage of Weapon Values
Dynamically-updated variable values are not of concern to me, so I can go through the SWEP Lua files and copy the information to a .txt file in a delineated data array of sorts. I very much understand string.Explode() and methods for extracting information from .txt files. The breakdown happened when I found out the .txt file HAS to be located on the client machine for file.Read to work. That’s when I got into Net Library functions and the whole thing collapsed in on itself. “Just use Net Library to send the file to clients” does not suffice as a suggestion for me when the only three tutorials in existence on the subject AND the Wiki all cover sending variables/strings to clients and not files. No amount of Google searching has revealed for me any way to send a .txt file to a client. The usual resource.AddFile() does not work either, I assume due to location of the .txt file outside of the ‘materials’, ‘resources’, ‘sounds’, or ‘lua’ directories.

Possible Method 3: Get Values on Spawn
I thought about this as I’m writing this post, but it may be possible to “capture” the value of Clip1() for each weapon in the table Player:GetWeapons() returns when the player spawns, but I’m not sure if there’s a way to get values from inactive weapons in the manner that GetActiveWeapon() calls the weapon in-use. Maybe define “weapon_name”, run a for/do loop for each table item stored to “weapon_name” and then ply:GetAmmoCount(client:GetWeapon( “weapon_name” ):GetPrimaryAmmoType()) ??

I’m not in any way asking anyone to write this code for me. But I am relatively new to GLua and could use the names of a few commands I might need, a bit of explanation and maybe some pre-existing examples of similar codes (the last two of which the Wiki lacks severely).

On a side note, I’ve done coding in SecondLife’s LSL and had a far easier time with things. GLua just seems counter-intuitive and convoluted to me, and has extremely brief and minimalistic documentation comparative to the LSL guides. A lot of shortcuts are taken in GLua coding and aren’t explained well if at all.

Not sure if this would work, but eh?

Unfortunately no. “bad argument #1 to ‘GetAmmoCount’ (number expected, got no value)”

I am attempting to work on Method 3 right now though.

I made this script for my own server which works just fine. Note that not all base weapons are filled in.

local wepclipsizes = {
    weapon_pistol = 18, -- These need to be here because we can't find them out in any way afaik.
    weapon_357 = 6,
    weapon_rpg = 1,
    weapon_shotgun = 6,
    weapon_crossbow = 1, 
    gmod_tool = 0, -- Garrysmod sets these to weird values
    weapon_physgun = 0,
    weapon_physcannon = 0

function DrawAmmo()
    local curwep = LocalPlayer():GetActiveWeapon()
    local allammo = 0 -- Ammo in current clip, and on the player (all useable ammo)
    local curclip = 0 -- Ammo in current clip
    local clipsize = 0
    if IsValid(curwep) then
        if wepclipsizes[curwep:GetClass()] then
            clipsize = wepclipsizes[curwep:GetClass()]
        elseif curwep.Primary and curwep.Primary.ClipSize then
            clipsize = curwep.Primary.ClipSize
        curclip = curwep:Clip1()
        if curwep:GetPrimaryAmmoType() then
            allammo = curclip + (LocalPlayer():GetAmmoCount(curwep:GetPrimaryAmmoType()) or 0)

This will give you 3 variables, allammo, curclip and clipsize which should be enough for most calculations.

local ply = LocalPlayer()
if ( !IsValid( ply ) ) then return 0 end
local wep = ply:GetActiveWeapon()
if ( !IsValid( wep ) ) then return 0 end

Holy crap thank you! This isn’t throwing any errors! At the moment the progress bar differs in size with each weapon, but I should be able to figure out a fix for that on my own :smiley:

I’ll pitch in too. Don’t forget the mandatories!

Proper HUD Creation:

Managing size:

Grabbing NON-SWEP ammo, names, etc:

So, if you’re going to use HL2 weapons, you’ll need to code accordingly.

Basically, if _p = LocalPlayer is valid, and _w = _p:GetActiveWeapon is valid, check to ensure it is a swep. You can use Ternary operations to easily switch between SWEP and NON-SWEP functions…

So, by default Ammo = -1, but if _w.Primary the table exists, and _w.Ammo1 the function exists, use the value returned from _w:Ammo1( ) [ also Clip1 works, but Magazines go into weapons unless it is an M1 Garand where the clip gets inserted into the internal magazine and ejected when empty CLING ]

local _ammo = ( _w.Primary && _w.Ammo1 ) && _w:Ammo1( ) || -1;

For HL2 Weapons, I don’t recall off hand the function for grabbing current ammo ( on laptop, limited resources ). But, you can fill it in place of -1.

If you want to have the bar move smoothly, use **Lerp **with **FrameTime **based on X speed per second ( modified by **FrameTime **) to get movement speed over the length of the frame.

If you want to use a percentage ( via float, 0-1 ) to use as a modifier against the width of the bar to ensure the bar will always fit, simply use

local _ammoModifier = math.Clamp( _ammo / _magazineCapacity, 0, 1 );

which will also ensure no overages or underages if you decide to use powerups for additional ammo… Multiply that resulting value with the width of the bar ( which, if you read the understanding scaling tut, is modified by the value resulting from the hard-coded screensize vs the user screen size ). When put together:

local _maxWidth = 250; -- Multiply by the screensize modifier if you want it to scale with different resolutions
local _ammoMod = math.Clamp( _ammo / _magazineCapacity, 0, 1 );
local _w = _maxWidth * _ammoMod;

Trust me, you don’t want to have to deal with sending files over net; I’ve done it, and we’re capped at 20KB/sec which is slow. If you overload the queue to the user, they get timed out. It isn’t worth it, just **AddCSLuaFile **before it is included for Lua, and resource.AddSingleFile for other files. If you want an automated system for resources:

You don’t need to be limited by string.Explode; there are other tools to use… JSON, SQLite, SQL via module ( MySQLOO, TMySQL ), etc… Many data storage options are available.

This doesn’t include JSON:

This does:

Writing SQL, basic queries and their formats:

Let me know, specifically, what you’re looking to do, or need help with. Chances are I may have a tut for it.

Thanks for all of this! The Size-Managing tutorial particularly was helpful for another project I’m working on involving a chatbox reskin. And as far as checking valid weapons, I have something in the code that checks for validity to determine whether to draw the HUD or not, so when the primary clip value is -1 on any weapon it turns the HUD off. Donkie’s code is working wonderfully for me, and I’m working on being able to hard-code amounts for alt-fire. As I said in another part of my first post, I’m not too concerned with total size values being dynamically updated, and if I add more weapons to loadout I can simply add more values to the script.

But yes, I’m very much interested in learning more about GLua, and have a lot more projects in mind (e.g. hull collapse/rotation for Prop Hunt, a taunt menu Derma panel, just to name a few)

If you perhaps wouldn’t mind me adding you to Steam I’d be happy to chat sometime, and go through more tutorials if you have any :smiley: