Splash Damage/ Text popup/render in world

Hello, I am a new at developing Lua for Garry’s Mod. I have been coding it for about a week or so and just needed some advice on this. I am not looking for someone to “spoonfeed or give me code”, I am just looking for some pointers so that I can get started.

I am trying to develop an addon which once someone takes damage, a number pops up infront of their model saying how much damage that hit did.

An example can be see on this gif. You will see Ra uses his ultimate attack and hits the NPC for 473 damage, which the number pops up and fades away.

I am stuck on how I can make the number render for everyone and so I cannot just draw a HUD as that will only appear on the persons screen like a HUD for ammo.

Can someone offer some advice on how I can achieve this in an optimised/efficient manner? Im thinking I will limit it to only show when there is less than 10 people in a radius otherwise, it will spam the area with flying text

So I would start with the hook:
ENT:OnTakeDamage( CTakeDamageInfo damage )

And make it so that if he takes damage, the ammount of the damage is beeing broadcasted to everyone on the server. And after that you have to make Cam2d3d, here is a good tutorial

[editline]27th January 2017[/editline]

So, basicly

Bob takes damage, 200

The server sends it to every player on the server

If the player is looking on this guy, and we got a value then

CAM2D3D

Thats how I would try it. Not 100% working though im not a professional

Well you must draw a “HUD” because you can only draw/render things on client.

That means that you must network the data ( damage numbers, position, etc ) from the server to each client, and render the data on each client.

i have already watched that video, but this way you have to create an entity/prop. I just want a 2D text displaying, not a prop attached to it.

Your options for drawing are either a 3D2D display or a basic draw.SimpleText and its alternatives in a normal HUD rendering context.

Yes makes sense, i know how the hierachy would me. My question was about the last point “render the data on each client”.

I was wanting to know how i can physically make text popup on the world (render)

And for broadcasting the data, you could use net library.

[editline]27th January 2017[/editline]

As I said, you can use the 3D2D rendering method for this, just google on how to use it. ( “gmod 3d2d” )

[editline]27th January 2017[/editline]

Alternatively you could use Vector:ToScreen() and normal HUD drawing method.

draw.simpletext, doesnt that just display a message on your screen overlay? I want the number to physical appear next to the entity taking damage. so everyone can see it

Cam2d3d works, the prop attached to it can be the player.

should i use 2d or 3d. I want it so if one player is standing somewhere and another player is somewhere else (behind the entity taking damage) - both can see the text.

Vector:ToScreen() can be used to make the message appear as if it is in the world. It also gives you the added benefit of being drawn above all world geometry and all entities, which is something you may want so that the numbers are not obstructed by anything.

But AS I SAID, it is only 1 of the 2 of your options. You can use 3D2D rendering for this. It will appear in the world, with proper scaling and everything. Can be painted from either a HUDPaint hook so it appears above everything, or post/pre entity rendering hooks so it appears in the world and is obstructed by every entity and world geometry. Just google what it is and how to use it.

And no, you do not need any “props” for 3d2d to work.

I didn’t mean you need a prop, he said you need a prop because the command is entity:Cam2d3d and I ment with the thing that entity can be the player.

There’s no such thing as “entity:Cam2d3d command”, its 3D 2D, not 2D 3D, and you do not need any entities for 3D2D. Stop spreading misinformation.

I actually made a system like this awhile ago.

Everyone above basically hit the nail on the head.

  1. Hook into EntityTakeDamage, use dmginfo:GetDamagePosition() to find the position in the world (if it’s 0, 0, 0 I default to the players position + half their height up. Center of body basically).

  2. Send a net message to either ALL players, or only the player that dealt damage (net.Broadcast vs net.Send() with dmginfo:Attacker() ) containing the damage amount and position in the world.

  3. Clients receive this, and construct a structure to hold the information about the damage (a table containing position, lifetime, damage number, alpha, etc), then add this to the end of a table.(table.insert, make sure the table is created outside the scope of this, so the rendering hooks can access it)

  4. In a render function, (I personally use HUDPaint with cached distance/los checks so they don’t render through walls(and only update these checks once a second or so, but this allows me to control the scaling of the numbers via cam.PushModelMatrix vs the 3d drawing methods above), and pos:ToScreen() (be sure to check the Visible field attached to the results)), loop through table starting at the end, working your way down to the first entry and draw displays. Once display has reached the end of its lifespan, remove it from the table.

You start from the ‘end’ so you can call table.remove from within the loop and not screw anything up.
Like so:



for i = #damage_numbers, 1, -1 do
    local v = damage_numbers*;
    --blah do render here
    if (v.life <= CurTime()) then-- you can also just store an alpha value and remove it when it's <= 0. Or do this however the hell you want. This is just an example.
        table.remove(damage_numbers, i);
    end
end


If you need any more help feel free to PM me.

Thanks alot for this. I have started to implement this however i have one dilemma.

This is how i am printing my text inside a HUDPaint hook:



hook.Add("HUDPaint", "damageHUD", function()

    for i=#myDamages,1,-1 do

        local myDmg = myDamages*["dmg"];
        local myPos = myDamages*["dmgPos"];
        local timeCreated = myDamages*["timeCreated"];

        local myColor = Color(234,194,32);

        local pos2d = myPos:ToScreen()        //Change the 3D vector to a 2D one

        draw.DrawText(myDmg,"magFont2",pos2d.x,pos2d.y,myColor,TEXT_ALIGN_CENTER)

        if(CurTime() > timeCreated + 1)then
            table.remove(myDamages, i)
        end

    end


end)



With this, everytime I hit it places the number for 1 second then removes it. However I am uncertain on where to start on making it move in bounce motion like yours, or make it move in any way at all.

what i currently have:

So obviously It is missing the moving part, which i cant figure out

When you first add a new damage entry to your table, attach a random velocity field, then add it to the position each frame.

i.e.



//Attach it to your entry here.
myDamages[newentry].velocity = VectorRand() * math.random(2, 5); --Higher numbers = faster, obv


/*
Now in HUDPaint:
*/
myDamages*.mypos = myDamages*.mypos + myDamages*.velocity;