Draw 3D2D Interface on Entity

Hello guys,

at first I’m NOT a good coder anyway. I am not a noob but I’m not a pro.

I want to create an Ammo Dispenser for my server.
At the end it should look like the Entity in this video:

I got this script for now. (Serverside & Clientside in one file)

[LUA]AddCSLuaFile()

ENT.Type = “anim”
ENT.Base = “base_gmodentity”

ENT.PrintName = “Munitionsautomat”
ENT.Author = “Swapy97”
ENT.Contact = “niklas.gschaider@gschaider-systems.at”
ENT.Purpose = “Hol dir Munition!”
ENT.Instructions = “Drücke ‘E’ auf die gewünschte Munition!”

ENT.Category = “Swapy97”

ENT.Spawnable = true
ENT.AdminOnly = false

function ENT:Initialize()
self:SetModel( “models/props_interiors/VendingMachineSoda01a.mdl” )
self:PhysicsInit( SOLID_VPHYSICS )
self:SetMoveType( MOVETYPE_VPHYSICS )
self:SetSolid( SOLID_VPHYSICS )
self:SetPos( self:GetPos() + Vector( 0, 0, 30 ) )

local phys = self:GetPhysicsObject()
if phys:IsValid() then
	phys:Wake()
end

end

function ENT:Use( ply, activator )
return
end

function ENT:Draw( ply )

//self:DrawEntityOutline( 1.0 ) -- Draw an outline of 1 world unit.
self:DrawModel()       -- Draw the model.

//AddWorldTip( self:EntIndex(), "Hol dir GRATIS Munition!", 0.5, self:GetPos(), self  ) -- Add an example tip.



local offset = Vector( 50, 0, 25 )
local ang = LocalPlayer():EyeAngles()
local ang_ent = self:GetAngles()
local pos = self:GetPos() + offset + ang:Up()

ang:RotateAroundAxis( ang:Forward(), 90 )
ang:RotateAroundAxis( ang:Right(), 90 )
//ang_ent:RotateAroundAxis( ang_ent:Right(), 90 )

cam.Start3D2D( pos, Angle( 0, ang_ent.y + 90, 90 ), 0.25 )
	draw.DrawText( LocalPlayer():GetName(), "Default", 2, 2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER )
cam.End3D2D()

end

function ENT:OnRemove()
end[/LUA]

I stuck at the problem, that the Angle I get from Entity:GetAngles() is absolute. But I need the Angle relative to the entity.

Thanks in Advance!

Wont Angle() use yaw instead of y? like, ent:GetAngles() returns yaw instead of y afaik.

[editline]17th August 2015[/editline]

Also, I think this helps:

Entity:GetLocalAngles

“Returns the rotation of the entity relative to its parent entity.”

Thanks, I will give it a try soon!

[editline]17th August 2015[/editline]

Okay, my ENT:Draw function now looks like this:

[LUA]function ENT:Draw( ply )
self:DrawModel() – Draw the model.

local offset = Vector( 0, -50, 85 )
local ang = LocalPlayer():EyeAngles()
local ang_ent = self:GetLocalAngles()
local pos = self:GetPos() + offset + ang:Up()

ang:RotateAroundAxis( ang:Forward(), 90 )
ang:RotateAroundAxis( ang:Right(), 90 )

cam.Start3D2D( pos, Angle( ang_ent.x, ang_ent.y + 90, ang_ent.z + 90), 0.25 )
	draw.DrawText( LocalPlayer():GetName(), "Default", 2, 2, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER )
cam.End3D2D()

end[/LUA]

I think I really messed up with the code… I would really appreciate it if someone of the LUA Professionals out there can send me a ENT:Draw function that simply draws a text on an entity.

The huge problem for me is, that when I turn the Entity around with the Physgun, the Text gets crazy!! It’s not doing what I want it to do. It’s not even logical what it does!

as I said, try replacing ang_ent x;y;z with pitch;yaw;roll.

Ssomething like this:



function ENT:Draw()
	local dx = Vector(0,0,12.5) -- position offset
	local da = Angle(0,90,0) -- angle offset
	local scale = 0.1 -- scale
	
	cam.Start3D2D(self:LocalToWorld(dx), self:LocalToWorldAngles(da), scale)
		draw.DrawText(LocalPlayer():GetName(), "Default", 0,0, Color(255,0,0), TEXT_ALIGN_CENTER)
	cam.End3D2D()
end


Okay, thanks mijyuoon! :buckteeth:

I drawed eight RoundedBoxes like this:
[LUA]draw.RoundedBox( 3, 0, 0, 25, 25, Color( 80, 80, 255 ) )[/LUA]

Now, my question is… If ENT:Use gets called, how can I check if the player is aiming at one of those boxes (or how can I get where the player is aiming on the Entity? )

http://forum.facepunch.com/showthread.php?t=1426788

http://forum.facepunch.com/showthread.php?t=1405662&p=45303545#post45303545

Okay guys :slight_smile:

At first, Thanks for your help. You are really cool!!!

Now, ENT:Draw looks like this:

[LUA] local select_voff = Vector( 22, -20, 5 ) – position offset
local select_aoff = Angle( 0, 90, 90 ) – angle offset
local select_scale = 0.25 – scale

cam.Start3D2D( self:LocalToWorld( select_voff ), self:LocalToWorldAngles( select_aoff ), select_scale )
	draw.RoundedBox( 3, 0, 0, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 0, 35, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 35, 0, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 35, 35, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 70, 0, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 70, 35, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 105, 0, 25, 25, Color( 80, 80, 255 ) )
	draw.RoundedBox( 3, 105, 35, 25, 25, Color( 80, 80, 255 ) )
cam.End3D2D()

local pos = self:LocalToWorld( select_voff )
local isec = util.IntersectRayWithPlane( EyePos( ply ), EyeAngles(ply):Forward(), pos, self:GetAngles():Up() )

local tr = self:LocalToWorld( select_voff + Vector( 0, 25, 0 ) )
local bl = self:LocalToWorld( select_voff + Vector( 0, 0, 25 ) )

if isec then

	local ap = pos - isec
	local ab = pos - tr
	local ad = pos - bl

	local ap_ab = ap:Dot( ab )
	local ab_ab = ab:Dot( ab )
	local ap_ad = ap:Dot( ad )
	local ad_ad = ad:Dot( ad )

	if 0 < ap_ab and ap_ab < ab_ab and 0 < ap_ad and ap_ad < ad_ad 
	and ply:IsLineOfSightClear( isec ) then --and if they have line of sight of the panel

		--Do whatever you'd like, they're looking directly at the panel
		ply:ChatPrint( "It works!" )
	end

end[/LUA]

But my problem now is that the script spams the textmessage “It works!” (only for testing :open_mouth: ) when I look at other parts of the model… I think I messed up with a value… But I can’t find the problem.

I never used the isec stuff myself, never really used 3d2d, but heres a -afaik- working snippet from an code, with manual checking, where you have to set the top & left coordinate of the given button & the bottom right coordinate:



// (ON BUTTON)
		surface.SetDrawColor(0, 0, 0, 100)
		
		if (tr.Entity == self.Entity) and pos.x < 8 and pos.x > 5 and pos.y < -6 and pos.y > -13 then
			// Change the color of the button when we look at it.
			surface.SetDrawColor(0, 0, 0, 220)
		
			if (player:KeyDown(IN_USE)) and not (player.KeyOnce) then
				player:ConCommand("op_printer " .. self.Entity:EntIndex() .. " on
")
				player.KeyOnce = true
			end
	   	end
		
		surface.DrawRect(x, y + 66, 35, 15)
		draw.SimpleText("ON", "ChatFont", -48, 33, Color(27, 255, 129, alpha_on), 1, 1)
		surface.SetDrawColor(0, 0, 0, 255)


full post: http://forum.facepunch.com/showthread.php?t=1253369&p=39903038&viewfull=1#post39903038

[editline]17th August 2015[/editline]

Note you have to define tr if you use that snippet.

-nvm-

Okay, I modified the code a little bit and defined the variables.

Here is the Code:

[LUA]
ply = LocalPlayer()

self:DrawModel()

/*local munition_voff = Vector( 22, -10, 35) -- position offset
local munition_aoff = Angle(0, 90, 90) -- angle offset
local munition_scale = 0.50 -- scale

cam.Start3D2D( self:LocalToWorld( munition_voff ), self:LocalToWorldAngles( munition_aoff ), munition_scale )
	draw.DrawText( "Munition", "Default", 0,0, Color( 255, 255, 255 ), TEXT_ALIGN_CENTER )
cam.End3D2D() */

local select_voff = Vector( 22, -20, 5 ) -- position offset
local select_aoff = Angle( 0, 90, 90 ) -- angle offset
local select_scale = 0.25 -- scale


local tr_ang = ( self.Entity:GetPos() - ply:GetShootPos() )
local tr = util.GetPlayerTrace( ply, ang )
local tr = util.TraceLine( tr )
local pos = self.Entity:WorldToLocal(tr.HitPos)

local x = -65
local y = -40
local cooling_overheating = "Cooling"
local color_cooling_overheating = Color(60, 135, 210, 255)
local alpha_on = 100
local alpha_off = 255

surface.SetDrawColor(255, 0, 0, 100)

	if (tr.Entity == self.Entity) and pos.x &lt; 8 and pos.x &gt; 5 and pos.y &lt; -6 and pos.y &gt; -13 then
		// Change the color of the button when we look at it.
		surface.SetDrawColor(0, 0, 0, 220)
	
		if ply:KeyDown( IN_USE ) then
			ply:ChatPrint( "IT works!" )
		end
   	end
	
cam.Start3D2D( self:LocalToWorld( select_voff ), self:LocalToWorldAngles( select_aoff ), select_scale )
	surface.DrawRect(x, y + 66, 35, 15)
	draw.SimpleText("ON", "ChatFont", -48, 33, Color(27, 255, 129, alpha_on), 1, 1)
	surface.SetDrawColor(0, 0, 0, 255)
cam.End3D2D()

[/LUA]

[editline]18th August 2015[/editline]

That’s the ENT:Draw function. As above ^^

did you literally just paste the code I gave you? You have to edit the coordinates in the “if” check, so it has the top left corner and the bottom right corner of your button.

[editline]18th August 2015[/editline]

Does it work though?

I know I have to edit the positions but i copy&pasted it, I just want to test the code but it don’t even works on the ON button, added by this code!

I don’t edited ANY positions in the code. It should be the same as in the thread you posted above ( the original code )

[editline]18th August 2015[/editline]

The button “ON” is drawed correctly and nice, but it don’t react to my clicks :frowning:

Try pressing E(Your use key) on it, since it doesnt check for clicks, but the USE button.