Ulysses
General => Developers Corner => Topic started by: KnowledgeJunkie on July 10, 2010, 09:43:04 AM
-
I recently got permission from Facepunch user ryan1271 to edit his Metal Gear Style Health bar (http://www.facepunch.com/showthread.php?t=967091), mainly because I wanted to add resolution scaling, support for armor, and the "damage taken turns red then disappears" effect from Metal Gear Solid. I've coded the armor bar, and added resolution scaling, but it seems my "MaxArmor" and "MaxHealth" values are not being retrieved properly, or aren't taking into account the fact that ulx can set a user's health and armor. The rectangles for the health bar and armor bar seem to show a max of about 1000, but "ulx armor", for example, can set the number much higher. Also, my health amount doesn't display in any way. So I was wondering if anyone has some suggestions:
How can I reliably get a player's "MaxHealth" and "MaxArmor" (the only method I say mentioned on GModWiki: LocalPlayer():GetNetworkedInt( "MaxHealth" ) Is the method you suggest ulx mod specific? I guess I don't care too much if it doesn't work outside ulx, but making it mod-independent would be swell.
Here's my code: (I should rewrite this, as it's just a bunch of assignments then poop):
function MetalGearHUD ()
local Player = LocalPlayer()
local PlayerName = LocalPlayer():GetName()
local Health = LocalPlayer():Health()
local MaxHealth = LocalPlayer():GetNetworkedInt( "MaxHealth" )
local Armor = LocalPlayer():Armor()
local MaxArmor = LocalPlayer():GetNetworkedInt( "MaxArmor" )
local Width = ScrW()
local Height = ScrH()
local NameWidth, NameHeight = surface.GetTextSize( PlayerName )
-- Adjust the numbers in these "math.ceil()" equations to scale bar heights and starting positions.
local BarStartX = math.ceil( Width/40 )
local BarStartY = math.ceil( Height/30 )
local BarMaxWidth = ( Width/2 - BarStartX )
local BarHeight = math.ceil( Height/50 )
local ArmorBarHeight = math.ceil( Height/150 ) -- notice the armor bar's height is 1/3 the height of the health bar.
local NameOffsetWidth = math.ceil( Width/150 )
local DrawPlayerName = true -- Draw the player name? Default value == true. Must be "false" (no quotes) to hide PlayerName.
local DrawNamePlaceMarker = false -- Draw the translucent box behind the PlayerName. Default value == false.
if !Player:Alive() then
return
end
if(Player:GetActiveWeapon() == NULL or Player:GetActiveWeapon() == "Camera") then
return
end
-- Draw the Health Rectangle (translucent innards)
surface.SetDrawColor( 0, 0, 0, 50 )
surface.DrawRect( BarStartX, BarStartY, BarMaxWidth, BarHeight )
-- Draw the Heatlh bar
surface.SetDrawColor( 20, 120, 255, 250 )
surface.DrawRect( BarStartX, BarStartY, ( BarMaxWidth * math.ceil( Health/MaxHealth ) ), BarHeight )
-- Draw the Health Rectangle border
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawOutlinedRect( BarStartX, BarStartY, BarMaxWidth, BarHeight )
-- Draw the Armor Rectangle (translucent innards)
surface.SetDrawColor( 0, 0, 0, 50 )
surface.DrawRect( BarStartX, ( BarStartY + BarHeight ), BarMaxWidth, ArmorBarHeight )
-- Draw the Armor bar
surface.SetDrawColor( 0, 20, 255, 250 )
surface.DrawRect( BarStartX, ( BarStartY + BarHeight ), Armor, ArmorBarHeight )
-- Draw the Armor Rectangle border
surface.SetDrawColor( 0, 0, 0, 255 )
surface.DrawOutlinedRect( BarStartX, ( BarStartY + BarHeight ), BarMaxWidth, ArmorBarHeight )
-- Draw the Player Name, only if DrawPlayerName == true
if DrawPlayerName == true then
if DrawNamePlaceMarker == true then --Draw the NamePlaceMarker (translucent box), only if DrawPlayerName == true AND DrawNamePlaceMarker == true.
surface.SetDrawColor( 0, 0, 0, 150 )
surface.DrawRect( ( BarStartX + NameOffsetWidth-2 ), ( BarStartY + ArmorBarHeight ), NameWidth+4, NameHeight+4 )
end
surface.SetFont( "MenuLarge" )
surface.SetTextColor( 255, 255, 255, 255 )
surface.SetTextPos( ( BarStartX + NameOffsetWidth ), ( BarStartY+ArmorBarHeight+2 ) )
surface.DrawText( PlayerName )
end
end
hook.Add( "HUDPaint", "MetalGearHUD", MetalGearHUD )
-- Hide the original Health/Armor Hud
function HideThings( name )
if ( name == "CHudHealth" ) then
return false
end
if ( name == "CHudBattery" ) then
return false
end
end
hook.Add( "HUDShouldDraw", "HideThings", HideThings )
-
I'm not 100% sure, but, I think it's because you're calling LocalPlayer variables before the player has fully initialized on the server.
That, and using Networked vars is slow even after initialization at times.
All those variables get set at player connect. That is, the server hasn't even spawned the player yet for some of them, so they come back empty.
The way you have them would also never update when called later in the script.
Try turning your Armor and Health static variables into a function
Something like (Been a while since I've done this, bear with me, learn from my mistake if it doesn't work, or another team member will come behind me and straighten us out);
local Armor = function( return LocalPlayer():Armor() ) end
Same for any other 'live' dynamic numbers.
-
well, using
local Armor = function( return LocalPlayer():Armor() ) end
caused an error... function expected "name" or "...". I think I have it figured out-
local MaxArmor = 100 -- default value to set bar length
local function GetArmor()
LocalPlayer():Armor()
return CurrentArmor
if MaxArmor < CurrentArmor
MaxArmor = CurrentArmor
end
end
hook.Add( Player.SetArmor, "GettheCurrentArmorDefault", "GetArmor" )
hook.Add( ulx.cc_armor, "GettheCurrentArmorULX", "GetArmor" )
hook.Add( otheradminmod.commandhere, "GetTheCurrentArmorSomeMOD", "GetArmor" )