-- clientside hit registration paper doll
-- author: robo

-- 100 means they are fine, 0 means big damage
local headHealth = 100;
local chestHealth = 100;
local rArmHealth = 100;
local lArmHealth = 100;
local rLegHealth = 100;
local lLegHealth = 100;

-- used for regen
local localLastHurt = CurTime();

local function drawPaperDoll()

	if( clientSettings["paperdoll"] == nil ) then
		return;
	end

	if( string.match( clientSettings["paperdoll"],"1" ) != nil ) then
	
		local function getColor( value )
		
			-- green, 100% ( 0, 255, 0 )
			-- yellow, 50% ( 255, 255, 0 )
			-- red, 0% ( 255, 0, 0 )
			
			if( value > 50 ) then
			
				local red = math.Clamp( 255 * (50-value) / 50, 0, 255 );
				
				return Color( red, 255, 0, 255 );
			
			else
			
				local green = math.Clamp( 255 * (value) / 50, 0, 255 );
				
				return Color( 255, green, 0, 255 );
			
			end
		
		end
		
		local folder = "paperdoll";
		if( string.match(LocalPlayer():GetNWString("info.model"), "female") != nil ) then
			folder = "paperdollf";
		end
		
		
		-- lets see here, 150-128 = 22 from width edge
		-- 280-256 = 24 from height edge
		-- need to keep a 128 / 256 ratio, I think I'll use just screen height cause width can go widescreen, height doesn't
		-- 150 / 1680 = .0892857...
		-- 280 / 1050 = .26666....
		-- 256 / 280 = .9142857....
		local constant = .2666666 * ScrH();
		local constant2 = constant * .9142857
	
		-- CHEST
		local tex=surface.GetTextureID("milkHud/".. folder .. "/chest");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( chestHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );

		-- HEAD
		tex=surface.GetTextureID("milkHud/".. folder .. "/head");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( headHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );
		
		-- LEFT ARM
		tex=surface.GetTextureID("milkHud/".. folder .. "/larm");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( lArmHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );
		
		-- RIGHT ARM
		tex=surface.GetTextureID("milkHud/".. folder .. "/rarm");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( rArmHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );
		
		-- LEFT LEG
		tex=surface.GetTextureID("milkHud/".. folder .. "/lleg");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( lLegHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );
		
		-- RIGHT LEG
		tex=surface.GetTextureID("milkHud/".. folder .. "/rleg");
		surface.SetTexture(tex);
		surface.SetDrawColor( getColor( rLegHealth ) );
		surface.DrawTexturedRect( ScrW() - (constant/2), ScrH() - constant, (constant2 / 2 ), constant2 );

	
	end

end
hook.Add( "HUDPaint", "paperDollDrawing", drawPaperDoll );

-- regens damage as viewed clientside
local function regenBody()

	-- don't regen if we've taken damage in last 10 seconds
	if( localLastHurt > CurTime() + 10 ) then
		return;
	end

	-- helper function, regen faster the higher the value is
	-- simple diminishing returns as value gets lower
	local function regenAmount( inValue )
	
		if( inValue < 33 ) then
			return 5;
		elseif( inValue < 66 ) then
			return 8;
		elseif( inValue < 100 ) then
			return 13;
		else
			return 100 - inValue;
		end
	
	end

	headHealth = headHealth + regenAmount( headHealth );
	chestHealth = chestHealth + regenAmount( chestHealth );
	rArmHealth = rArmHealth + regenAmount( rArmHealth );
	lArmHealth = lArmHealth + regenAmount( lArmHealth );
	rLegHealth = rLegHealth + regenAmount( rLegHealth );
	lLegHealth = lLegHealth + regenAmount( lLegHealth );
	
end
timer.Create("bodyRegen", 20, 0, regenBody);


-- called by server on respawn
local function resetDamage()

	headHealth = 100;
	chestHealth = 100;
	rArmHealth = 100;
	lArmHealth = 100;
	rLegHealth = 100;
	lLegHealth = 100;

end
usermessage.Hook("resetDamage", resetDamage);


-- called by server on damage
-- flip the incoming limbs to make it look like you're seeing your character from behind
-- more intuitive that way
local function doDamage( data )

	localLastHurt = CurTime();

	local type = data:ReadString();
	local amount = data:ReadShort();
	
--Msg("damage to: " .. type .. " amount: " .. amount .. "\n");
	
	if( string.match( type, "head" ) != nil ) then
		headHealth = headHealth - amount*5;
	elseif( string.match( type, "chest" ) != nil ) then
		chestHealth = chestHealth - amount*5;
	elseif( string.match( type, "rarm" ) != nil ) then
		lArmHealth = lArmHealth - amount*5;
	elseif( string.match( type, "larm" ) != nil ) then
		rArmHealth = rArmHealth - amount*5;
	elseif( string.match( type, "rleg" ) != nil ) then
		lLegHealth = lLegHealth - amount*5;
	elseif( string.match( type, "lleg" ) != nil ) then
		rLegHealth = rLegHealth - amount*5;
	else
	
		amount =  math.Clamp( amount, 1, 300 )
	
		headHealth = headHealth - amount*5;
		chestHealth = chestHealth - amount*5;
		rArmHealth = rArmHealth - amount*5;
		lArmHealth = lArmHealth - amount*5;
		rLegHealth = rLegHealth - amount*5;
		lLegHealth = lLegHealth - amount*5;
		
	end

end
usermessage.Hook("damageDone", doDamage);