ID:156631
 
I've been confused with using USR in situations such as under other atoms. I know this is wrong, but I don't know how it'd be fixable:

obj
whatever
proc/Use()
var/mob/M = usr
M.Edit()


Should it be like this instead?

obj
whatever
proc/Use(var/mob/M as mob)
M.Edit()


Or this?

obj
whatever
proc/Use(var/mob/M)
M.Edit()
Since when the heck was:
obj/verb/UseIt()
world<<"[usr] is using [src]"

ever wrong?
usr isn't safe in procs because the context of the way the proc was called determines what usr is, and it generally is never what a new programmer thinks it is (ie. the user).

If you were to write your first snippet above as a verb, then it will be the correct usage because in the context of a client using a verb, usr is the client's mob, ie. the user who clicked the verb, and it's mostly reliable up until you call the verb as a proc.

Your second and third snippets really don't really have any difference, since the 'as mob' setting only makes sense when called as a verb.
In response to Unknown Person
Alright, so would this be OK to do?

obj/proc/ball_state()
icon_state = "ball"

obj/Squiggle
Click(var/mob/M as ???) //Brain ineffective here...
ball_state()
M.change()

mob/var/HP = 10

mob/verb/change()
if(HP <= 0)
icon_state = "dead"


(I'm more looking to learn about the usage of doing an action on your own mob in odd situations, I'm not concerned if the functionality of this 'snippet' has more work in it than need be.)
In response to OrangeWeapons
OrangeWeapons wrote:
> obj/Squiggle
> Click(var/mob/M as ???) //Brain ineffective here...
> ball_state()
> M.change()
>


If you look in the reference, the first parameter of atom/Click() is the location of whatever you clicked, so it generally isn't what you think it is.

atom/Click() is one of the procs where it is acceptable to use usr because it is called like a verb (it is called by the user's click event, client/Click()), so in this case, you can safely call usr.change(). This should always be the case unless you decide to manually call Click() as a proc (in some other part of your code), which breaks that assumption. This generally is never the case (unless you're trying to hack some code together), so you probably aren't going to deal with that situation.

obj/Squiggle
Click()
ball_state()
usr.change()
In response to Unknown Person
But what if the proc isn't Click()? What if it is a proc that I can't use <big>usr</big> with?
In response to OrangeWeapons
OrangeWeapons wrote:
But what if the proc isn't Click()? What if it is a proc that I can't use <big>usr</big> with?

If you use usr in a proc, then you need to tread carefully because of the fact that usr tends to be different if the proc is called in different contexts (such as being called from a click vs being called from another object's proc or verb). A classic problem you can find on the forums is the DeathCheck() proc.

Let's consider this example: (note: all the code below is bad, don't use it! For analysis purpose only!)

// src is the victim here
mob
var
health = 100
kills = 0
proc/DeathCheck()
if(src.health <= 0)
world << "[src] has been killed by [usr]!"
usr.kills++

mob/verb/kill_person(mob/M as mob in view(1))
M.health = 0
M.DeathCheck()


If you were to use the kill_person() verb on another player, you probably won't run into any problems. In the context of using that verb on someone, usr in DeathCheck() will be set to the person who called the verb, and thus usr will be the person who killed the victim.

However, if we decide to let players kill in different ways, such as shooting bullets at each other.

obj/bullet
Bump(atom/A)
if(ismob(A))
var/mob/M = A
M.health -= 100
M.DeathCheck()


We will run into a problem here. Since DeathCheck() is called in the context of the bullet's Bump() proc, usr will actually end up being null, or even the bullet! (depends on how it was created) Our DeathCheck proc will throw a runtime error, and it looks like we're going to have to nag forum users here to figure out why it's happening.

Pretty much, the solution is to send the required data over to any proc, which you are probably aware of. usr is a pretty volatile variable, and you should generally avoid using it not only because of its volatility, but because specifying arguments promotes cleaner and more semantic code, making it a hell of a lot easier to debug. Check out the DM Reference on usr for particular usage information.