ID:1310534
 
Just a handy little bit of code I came up with that displays the name of nearby mobs when they are close, and then removes it when they get farther away.
mob
var/tmp/list/NearbyMobs=new/list
proc/NearbyMobs()
for(var/mob/M in orange(src,5)) spawn() DisplayNameOf(M)
spawn(1) NearbyMobs()

proc/DisplayNameOf(mob/M)
if(!client||M in NearbyMobs) return //Only adds a nametag to enemies
//that aren't displaying one to you already
NearbyMobs+=M
var/obj/O=new
O.layer=MOB_LAYER+10
O.mouse_opacity=0
O.pixel_y=-16
O.pixel_x=-79
O.maptext_width=200
O.maptext="<b><center>[M.name]"
var/image/i = image(O, M)
src<<i
if(M==src) return //This line makes the players name always display
//to themself by never getting to the delete line.

while(M&&get_dist(src,M)<5) //Run a continuous check to see if the mob is still nearby
sleep(1)

NearbyMobs-=M //Once the enemy is deleted or out of range, delete the nametag
del i


//All you need to do is add this
NearbyMobs()
//to your existing Login() proc for players.
Wouldn't it be better to use ohearers?

for(var/mob/M in ohearers(src,5))
In response to Kozuma3
That's sound related, so not really. Range is better. It might be best to use view or viewers if you have things like luminosity as a factor in the game.
In response to Dariuc
Dariuc wrote:
That's sound related, so not really. Range is better. It might be best to use view or viewers if you have things like luminosity as a factor in the game.

ohearers gets only the list of mobs in view instead of the turfs, I believe.

Which would be better suited for this and more efficient.
In response to Kozuma3
range is more suited to use in this particular instance. He wants to make sure that no matter what obstacles are impeding the "sight" of a mob that as soon as you draw near enough the name pops up.

Ohearers=within earshot (sound distance).
viewers=field of view (sight distance).
range=absolute distance.
as per the help file:
Format: 
hearers(Depth=world.view,Center=usr)
This is just like viewers(), but it is a list of mobs that can hear the center object. Currently, this is computed on the assumption that opaque objects block sound, just like they block light.

In this instance ohearers isn't needed, because you aren't dealing with sound. Yes, it does the same thing,but it also has some unneeded functions associated with it. (if i remember right it enables sounds to fall off based off of the distance you are from them or something like that.)

Range or viewer would be better. As to which, it depends on what you need them for. If he wants to ignore any obstructions or obstacles that could block a name from showing up, he'd use range like he is using right now.

If he only wanted names to pop up when a mob is within view, then obviously viewers would be better. It's a subtle difference on each point, but in this case he's using the right proc.
ohearers is for returning mobs only, because "turfs and objs don't have ears" which is the general concept. Its more efficient because it ignores all atoms except for mobs aside from opaque objects blocking some results.

range() will build a list of all atoms in a range, which is more costly as you'll have to loop and check more things.
In response to Dariuc
hearers() has nothing to do with sound or /sound objects and doesn't affect them at all. That doesn't even make sense.

hearers() simply returns mobs that are in range and not blocked by opaque objects.
For example, the Center can be invisible but still be heard.
Clients can have their eye set around Center and see it, but not hear it.

range() and orange() are the only things that completely ignore opacity.
In response to Kaiochao
I never said it was for sound objects.
I said it's to simulate sound. There's a difference.
Also it does make a difference, since potential sounds the player might hear when using ohearers are altered.
The point fireking made does make sense though since only mobs are tested.
In response to Dariuc
Dariuc wrote:
In this instance ohearers isn't needed, because you aren't dealing with sound. Yes, it does the same thing,but it also has some unneeded functions associated with it. (if i remember right it enables sounds to fall off based off of the distance you are from them or something like that.)
Lack of "simulate" aside, it has as much to do with sound as view() or viewers().
In response to Kaiochao
And ohearers' range is also blocked by opaqueness.
What I was saying in the beginning is that it depends on what he wants to use it for.
If he, for instance wanted to make the names pop up regardless of things like walls, he'd use range, if he only wanted it to pop up when it doesn't really matter if the player can see the mob or not, he could use viewers or hearers. Like I said above they are basically the same thing. Except a while back I read somewhere that hearers decreases the sound with a sort of fall out effect based on how close or far you might be away from the sound (keep in mind this might be obsolete, I believe i was reading a midi lib whenever i happened upon this)

Either way, like I was saying a while back-- it really just depends on what you'd like to use it for as to which you need.
I'm confused about:

while(M&&get_dist(src,M)<5)
sleep(1)

Doesn't this mean that if the distance between M and the source is less than 5, turn off nametag? And shouldn't that be the opposite?

I don't really understand DM so apologies if I'm mistaken.
In response to SilencedWhisper
While M exists, and the distance between src and M is less than 5 tiles, wait 1 decisecond.

The code after it is done waiting is what removes the nametag.
In response to SilencedWhisper
SilencedWhisper wrote:
I'm confused about:

while(M&&get_dist(src,M)<5)
sleep(1)

Doesn't this mean that if the distance between M and the source is less than 5, turn off nametag? And shouldn't that be the opposite?
What this is essentially doing is saying "While the target is still there and close by, just wait. And wait.. and wait. Once the target moves away, then it continue on in the code and deletes the nametag.
It may be less overhead in general to go with a system that is called when a mob changes location.

When a mob moves it'd make every mob within the range update the nametags. So not only would the moving mob see the nametags of mobs in the new range, but the mobs that were stationary would see the nametag of the mob that just arrived.


I only say this because if a game has a large amount of mobs, all of them running constant loops to check for names may end up causing some crippling lag.

It should be much less overhead in general to go with an on-update system rather than a constant check.
What Bravo1 said! You definitely don't want a loop going per nametag.

Instead, you'd want to show and erase the name tag as it comes into and goes out of view. There's two ways to do this that I can think of immediately - 1: on movement, 2: in a loop

On movement, you'd be removing src's name tag from anyone who can no longer see the src but could see him before.

In a loop, you'd be making a simple check and adjusting name tag appearance accordingly.

I think the movement case could work quite well, but you'd have to be careful that it doesn't make Move() take longer as it will actually delay movement in longer frames of processing.
In response to FIREking
FIREking wrote:
What Bravo1 said! You definitely don't want a loop going per nametag.

Instead, you'd want to show and erase the name tag as it comes into and goes out of view. There's two ways to do this that I can think of immediately - 1: on movement, 2: in a loop

On movement, you'd be removing src's name tag from anyone who can no longer see the src but could see him before.

In a loop, you'd be making a simple check and adjusting name tag appearance accordingly.

I think the movement case could work quite well, but you'd have to be careful that it doesn't make Move() take longer as it will actually delay movement in longer frames of processing.

Just conceptualizing and throwing ideas around, but can you remove an image from a client without deleting it?

If so, then you could easily just use images, generate the image once, then send it to clients when they got in view. That would be lightning fast.
In response to Rushnut
Rushnut wrote:

Just conceptualizing and throwing ideas around, but can you remove an image from a client without deleting it?

If so, then you could easily just use images, generate the image once, then send it to clients when they got in view. That would be lightning fast.


Yes, you can =)

client.images-=target


This way, you can generate the nametag as an image attached to the player, and when they move out of range, they can remove the image from the clients images. The only issue is: how to update those that you've moved away from.

One way is to take a list before the movement and after the movement, and whichever client is not in both lists will have their image removed. The only issue with this is that it makes you build two lists per movement instead of one.