YaLTeR / OpenAG

An open-source reimplementation of Adrenaline Gamer's client library.
https://j.mp/OpenAG
Other
131 stars 39 forks source link

[Draft] Added nametags, implements #30 #103

Open chinese-soup opened 3 years ago

chinese-soup commented 3 years ago

@execut4ble on #30:

Add hovering nametags above teammates or all players, either always visible or instantly when the player mouse-overs them like in CSGO/Overwatch. Could also add their health/armor status next to the name if they're your teammate.

So I've implemented this based on a request from egg and only yesterday I've noticed exec posted that issue back in 2017. :smiley:

I've first tried implementing this using drawn sprites above player heads. This went fine, just making an ASCII table sprite and having each frame correspond to an ASCII letter was a breeze, unfortunately it probably creates too many sprites as it crashes the game whenever there's more than > 5 players. If anyone can tell a dummy how to debug this kind of crashes (the game just exits, no error about edicts or anything), I'd be much appreciated. :) An example of that implemention can be seen here: image

Since that didn't work I then moved on to creating the hovering tags using DrawConsoleString and DrawHudString.

Obviously this has its downsides, for starters: you cannot change the font size as its "set in stone" for DrawHudString and depends on what the user has in their resource file for DrawConsoleString. (Uses the same font as the chat etc.)

Therefore I tried to use a VGUI1 label, since you could potentially change the font size depending on how far the player is, but no luck there either, the coordinate updates are way too slow as can be seen in this video: https://user-images.githubusercontent.com/5108747/114897287-5ef9e480-9e11-11eb-972f-dd3f163aa9ce.mp4

Consider this a draft for now, but here's a list of stuff that is implemented or should be decided: exec wrote:

Add hovering nametags above teammates or all players

Currently the "rules of visiblity" of the implementation are:

instantly when the player mouse-overs them like in CSGO/Overwatch. Could also add their health/armor status next to the name if they're your teammate.

I'll implement the mousing over and also health is not yet implemented either as that would require hooking the PlayerId message and therefore merging this code with hud_playerid.cpp.

I was thinking having a switch if you want to have the tags visible only on hover or "always" (as per the "rules of visibility" above).

Something like hud_nametags_hover_only 1 (or whatever):

Current cvars:

Ones I've thought would be good:

Up for discussion cc @execut4ble:

Still TODO:

The current state can be see in action here: DrawHudString: image DrawConsoleString: image https://youtu.be/rPt24qYXo8s

YaLTeR commented 3 years ago

This is cool!

how to debug this kind of crashes (the game just exits, no error about edicts or anything)

coredumpctl gdb usually works

Therefore I tried to use a VGUI1 label, since you could potentially change the font size depending on how far the player is, but no luck there either, the coordinate updates are way too slow as can be seen in this video: https://user-images.githubusercontent.com/5108747/114897287-5ef9e480-9e11-11eb-972f-dd3f163aa9ce.mp4

Huh, is this a VGUI1 thing? Would be a shame if we can't vary font size.

hud_nametags_type 0/1 - default 1 - "same font as chat" (DrawConsoleString); 0 = "hud font" (DrawHudString)

I'd keep just DrawHudString and make it always color nicknames. There should be code that does this because voting UI uses it I believe.


I'd like to get some feedback from people who requested / would use the name tags too.

chinese-soup commented 3 years ago

coredumpctl gdb usually works

Thanks, will check it out and see if I can make it work. I had an idea of using a TEMP entity with write_message stuff instead of gEngfuncs.CL_CreateVisibleEntity(ET_NORMAL, pEnt); and maybe that would fix the crashes. Will see what the debugging leads to. BTW: Sprites could also be potentially a good alternative if VGUI can't be made to work (without importing in VGUI2 from e.g.'s tmp64's repo https://github.com/tmp64/BugfixedHL, but dunno if that isn't VAC-able etc.) seeing as the sprites scale automatically based on the distance from the target player. Here's a short sprites demo from couple of days ago: https://kopr.today/2021-04-05_03-05-58.mp4 (scale is settable for a sprite entity, and the rotation was currently only set to 4 angles, as you can see in the video)

Huh, is this a VGUI1 thing? Would be a shame if we can't vary font size.

I'd assume it's a VGUI1 thing, but I've tried both vgui::Label and the one (tmp64 added?) ScorePanel uses aka CLabelHeader - which should be VGUI2(?), but it unfortunately does the same thing when you update the position like this. I'll try playing around with the VGUI2 CLabelHeader again, but I dunno if it will lead anywhere. It's a real shame because CLabelHeader can draw unicode and "create" & render system fonts and therefore create different sizes that you could interchange.

I'd keep just DrawHudString and make it always color nicknames. There should be code that does this because voting UI uses it I believe.

Personally, I prefer the DrawConsoleString appearance (with just the team color of the player/chat color if default/no team, as I am conservative and don't use a colored nickname myself, but at the same time I am liberal in the sense that I think having more options is always better than not having one at all) because of the size mostly (which if we could get VGUI labels to actually update position @ correct FPS would become redundant).

I'd like to get some feedback from people who requested / would use the name tags too.

Yep, agreed. :)

execut4ble commented 3 years ago

This is sick.

I'd honestly just disable showing nametags for enemies altogether (not just when they are 600 units away) & only show them ON HOVER as it makes the players too visible "horizontally" - seeing as you cannot change the font size (reason why I tried to use the VGUI labels) and only show them on hover. What do you think?

Yeah for sure, I think disabling nametags for enemies altogether (including on-hover) makes the most sense, otherwise it could be too advantageous to spot a nametag when otherwise the enemy visibility is low. We already have a HUD element that displays the playername on hover in the center of the screen. So just have nametags for teammates.

you can see enemies nametags if you are closer to them than 600 units.

Perhaps make this adjustable, even though there's hud_nametags_team_always which can be used for really long distances.

Also make sure to test this in other gamemodes without team deathmatch, such as FFA, Arcade, Arena (and some others). Everyone is an enemy, so no nametags should be displayed here, even if they share the same "model".

chinese-soup commented 3 years ago

Yeah for sure, I think disabling nametags for enemies altogether (including on-hover) makes the most sense, otherwise it could be too advantageous to spot a nametag when otherwise the enemy visibility is low. We already have a HUD element that displays the playername on hover in the center of the screen. So just have nametags for teammates.

:+1: True & agreed, didn't think of the on hover making an "accidental" "reveal" of an enemy. So yeah, let's not show nametags for enemies at all.

This however means that it would be non-trivial (for me anyway since AFAIK I can't hook to PlayerId if hud_playerid.cpp already does?) to make health & armor appear for the teammates on hover, so I guess we could just not show health / armor at all in the NameTag even when you hover on a teammate, seeing as it's already showed in the hud_playerid HUD.

Perhaps make this adjustable, even though there's hud_nametags_team_always which can be used for really long distances.

Will consider it, at the time always showing seemed more "trivial" for the end-user to change as the code checks if you can actually see the person and AG maps usually don't have many huge "rooms" (can only think of the square in stalkx, really, but I'm not really an avid AG DM player rn). EDIT: replaced hud_nametags_team_always with hud_nametags_team_max_distance.

Also make sure to test this in other gamemodes without team deathmatch, such as FFA, Arcade, Arena (and some others). Everyone is an enemy, so no nametags should be displayed here, even if they share the same "model".

Yep I already tested this (since the hud_nametags_team_always feature already required this) so this should already be working correctly since the code checks if teamplay is on as well as the teamname being same. Obviously will test again once I remove the nametags for enemies.

chinese-soup commented 3 years ago

Regarding the sprites: It's probably just as I thought, the sprites thing is probably just hitting the max number of temp entities (it's drawing one per letter). Gdb doesn't tell me much because it's from the engine.

Program terminated with signal SIGSEGV, Segmentation fault.
#0  AddTEntity (pEnt=0xc90c3d14 <g_VoiceStatus+192820>) at ../engine/r_trans.c:187
187 ../engine/r_trans.c: No such file or directory.
[Current thread is 1 (Thread 0xf76f86c0 (LWP 1059137))]

Dunno if there was ever a leak of HL1 engine src code, but a quick google finds stuff like ValveSoftware/halflife/issues/206 so I'd assume the limitation of temp entities is hit, not the limitation of loaded sprites/models (we're only loading & precaching one .spr).

That's a shame, can't combine the sprites on-the-fly into "one big sprite" for each player name in the client library, so I guess we're out of lock with "in-world sprites" in the client...

Will check and see if I can do anything using the sprites/TGAs in HUD and also try the VGUI2 again as I've already said before. (Cuz font size would be a very useful feature...)

Also: If we can't make the font size work with VGUI/VGUI2 there's one last rather drastic resort, that I can think of, for implementing a dynamic "font" size :smile: -- gEngfuncs.pTriAPI, but dunno if that isn't overkill for a feature like this...

tmp64 commented 3 years ago

This looks really cool!

VGUI and VGUI2 are pretty much a dead end: you can only scale them by creating a new font handle and you can't remove existing font handles. No transformations are possible either.

A better option would be to use TriangleAPI. It allows you to use a sprite as a texture (on a side note, you should probably put all ASCII chars into one sprite frame to reduce the number of texture switches: it's a fairly expensive operation for the GPU). The only downside is that may be inefficient and may reduce the FPS (not much if all chars are in one texture, something like from 500 to 400-450 if there is a lot of text) because it would require many draw calls.

The best option, in my opinion, is to buffer all rendered vertices and then draw them in one go. This is used in the engine for text rendering (link).

If you want to improve the quality of the text without increasing the resolution, you should look into signed distance field font rendering. Of course, that requires shaders and hacks to make it cooperate with fixed pipeline of the engine and it's way overkill and way too much work. It looks like it's possible to be done without shaders. But it's still overkill.

I think you shoud start by implementing it using TriAPI and then work from that. Vertex buffering is easy to implement and shouldn't cause any problems. You can find TriAPI docs in Half-Life SDK on Steam (in the "tools" section).

chinese-soup commented 2 years ago

TODO:

Might TODO eventually(TM) (or in a later PR):

solidi commented 2 years ago

@chinese-soup - hi, this change makes reference to sprites/ascii_table.spr and sprites/ascii_single.spr but are not apart of the pull request. Can you share these assets?

sabianroberts commented 11 months ago

@chinese-soup - hi, this change makes reference to sprites/ascii_table.spr and sprites/ascii_single.spr but are not apart of the pull request. Can you share these assets?

bumping this! could you please share the sprites?