Skip to content

[TF2] Restructure CTFHudPlayerHealth::SetHealth for speed & added features #1222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

treacherousfiend
Copy link

@treacherousfiend treacherousfiend commented Apr 28, 2025

Description

This is a minor restructuring of the CTFHudPlayerHealth::SetHealth function (which is used to update the health UI panels), to improve speed, add new features, and fix a bug or two.
the diff on github looks rather odd, but for the most part the code in SetHealth has mostly just moved around rather than changed.

I had hoped this would be a smaller PR, but the changes work best as one larger one.

Changes

Only run `SetHealth` if the input health is different from prior cached values

This is something that the revive dialog and the floating health icon for target ID already did, but merged into the main function and expanded. This change takes the function from taking on average ~0.025ms per call down to being so fast that vprof says it takes 0.000ms average per call.

Even in an absolute worst case scenario of having 102 healthbars (1 from your health bar, 1 from targetID, and 100 from the matchhud if for some reason you have 100 players on your team), the average time spent per frame is still 0.00ms. In my tests, I was averaging around 1000 calls every 10 seconds, and this totaled out to about 0.12ms.

Additionally, I've removed the checks from the revive dialog and floating health icon, as they are now unnecessary with this change and actually seemed to cause issues with sometimes causing the new check to fail and as such not ever running the function, I'm not sure entirely why.
This does mean that SetHealth is being run more often since the check is happening inside the function, which appeared to be ~200 times every 10 seconds, but due to the speed improvements this doesn't seem to be an issue.

Hide health and max health label panels instead of emptying their dialog variables (Fixes ValveSoftware/Source-1-Games/issues/3815)

This is done mostly for hud editors, with current behavior the `%MaxHealth%` variable is completely blank unless the player is missing 5 or more health.

Because some hud editors (myself included) want to have huds which always show max health, I've changed it so that it gets the default panels which use these variables and toggles their visibility instead. This keeps behavior with the default hud the same, while allowing hud editors to simply make their own panel to read the variable without worrying about having it hidden.

Add new dialog variable `%MaxBuffedHealth%` to display max overheal

This is debatable as being necessary, but I needed a cached variable anyway for it to make sure `SetHealth` wouldn't early out if `iMaxBuffedHealth` had changed but the other 2 health values had hadn't, so I thought it would be fun :)

I think its pretty unlikely that iMaxBuffedHealth would change without health or max health also being changed because the GetMaxBuffedHealth function used in most of the calls of SetHealth doesn't take into account the overheal multiplier attributes on the client, although if it did, then the health cross would scale oddly when medics start and stop healing you.

The only other instance I can think of in gameplay where this value would ever change is with Gloves of Running Urgently and the Eviction Notice, which do seem to show the modified overheal max properly with this change.

Remove 2 unnecessary `if ( m_pHealthImage )` checks

m_pHealthImage is initialized in the constructor, and there are many _many_ other places where the game would crash if this caused access violation errors, such as 2 lines above the first one I removed, where a function is called on it.

I suppose in theory this is kind of bad code but there are so SO many other places where an uninitialized variable could cause crashes (see below) but doesn't that I think its safe to remove this for speed.

Initialize player level label and new health/maxhealth labels to NULL

This is partially just to fix an issue I came across with my added label pointers causing access violation errors with the spectator UI, due to uninitialized memory being used and passing checks to see if the labels existed.

The level label is (re)used for the respawn timer on targetID for revive markers, but I've never heard of it breaking, so there may simply be some deeper issue that I was running into with the other labels that I have missed.

There are still other variables that are uninitialized in the constructor, but do not seem to cause issues.

Instead of clearing the maxhealth variable when above maxhealth - 5, to allow custom hud authors to use it for their own purpose.
In order to keep vanilla tf2 hud behavior, the panel which displays the maxhealth by default has its visibility toggled instead
This is significantly faster, even with the theoretical worst case scenario even outside normal gameplay of 102 health panels (1 from your health, 1 from targetid, and 100 from matchhud players on your team, although at that point they stop rendering from being too thin)
the average time spent per frame is ~0ms. seriously, vprof says 0.000. Without this patch the average per CALL was 0.028ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[TF2] [HUD] Allow %MaxHealth% to be always shown
1 participant