ID:1789464
 
I've been seeing some obvious mistakes people have been making in the developer help section. Since I had some free time before my class started, I decided to make a small post on how easy it is to learn the difference between usr and src.

The Written Difference



usr can be thought of as the user the that initially started the whole action. Or, the user who called a procedure.

src can be thought of as the source of the current level of procedures. It is what owns the current section of code that is happening and also what the procedure is called on.


Some Examples



In these examples, I will take some scripts from the Developer Help section and modify them to help you learn the difference.

obj/GUI
Self_Destruct
icon = 'boom.dmi'
icon_state = "explosion"
layer = 5

Click()
usr.self_destruct()


Quiz:
If Player 1 clicks the Self Destruct button, who is src and who is usr?

Answer (highlight/copy&paste to see):
src: The Self Destruct button
usr: Player 1


This is because Player 1 is the person who initiated the clicking. Therefore, they are the usr. Whereas src is the source of the procedure, the button. The button owns the Click() procedure and is deemed src.



mob/verb/Attack()
... //Perform attack script here
//M = Player 2 in front of Player 1
M.DeathCheck()

mob/proc/DeathCheck()
... //Perform calculations for death verification.
usr << "This is the example message 1."
src << "This is the example message 2."


Quiz:
If Player 1 clicks the Attack verb and DeathCheck() is called on Player 2, who is usr and who is src? Who gets message 1 and who gets message 2?

Answer (highlight/copy&paste to see):
usr: Player 1
src: Player 2


Player 1 will get message 1 and Player 2 will get message 2. Because DeathCheck() was called on Player 2, Player 2 now is the source (src) of DeathCheck(). And, as a result of that, Player 1 would have to be the usr that initially called this procedure.




The Twist



There are instances where usr can still be used in a similar instance of src. Lummox JR explains in a previous post when this twist occurs.

Paraphrased from Lummox JR:
Well, everything here is not exactly true. usr is the mob who called the verb. When that verb calls procs in turn, usr gets passed along as a hidden variable and keeps its initial value unless it's modified--including by the mob being deleted.



If you have any feedback on how to make this post more clear, feel free to comment below. I hope this post frees up any confusion and helps newcomers better understand the difference between the two. It really is a big difference.
This is pretty accurate. A few years ago, I got challenged to come up with a case where usr is actually ambiguous. I wasn't actually able to come up with a legitimate one.

Much later, though, I noticed a trend. People who don't understand the difference between usr and src often run into problems like this.

mob
player
var
show_menu = 0
verb
toggle_menu()
usr.show_menu = !usr.show_menu


Now, this of course will give you compiler errors. This is because usr is cast as /mob, not /mob/player. Since show_menu is defined under /mob/player, the variable access is not valid on usr.

The two most common ways that people avoid this problem, is by using the ":" look-up operator, or by moving all variable definitions under /mob. This results in all player-specific variables being available to all mobs in the world --which is quite confusing and wasteful.

Basically, people who use usr wrongly are also committing other sins like improper embedding of members, failure to perform proper typecasting, and other such issues.

Usr abuse isn't so much a problem in itself so much as a symptom of bad habits that can potentially lead to worse habits.
Ter13 wrote:
src should be preferred on any verb where the src setting is "src = usr", which is the default for all mob verbs.

The reason that src should be preferred is because usr is typecast to /mob, while src is typecast to the current path.

Here's why you should always use src instead of usr in mob verbs:
mob
combatant
var
blocking = 0
verb
block()
usr.blocking = !usr.blocking //compiler error!
block2()
blocking = !blocking //this works (src is implied)

Not only can using usr in mob verbs result in nasty compiler errors, but it adds unneeded overhead in the form of a pointer lookup that doesn't need to be done. Since usr = src, and src can be implied, the VM doesn't have to traverse the usr pointer to figure out what object to access.
I've had cases where I've needed to emulate Click() behavior, at that point it made more sense to simply call thing.Click() rather than encapsulating the behavior elsewhere. Something like, choosing a person from the world to forcefully click on something. However, since usr is invisibly passed, usr had to be set to that person before.

mob/verb/forceclick(mob/x in world) usr=x;object.Click()


At this point, usr is neither the person who calls the verb, nor the person to whom the verb belongs.

Usr and src can be as ambiguous as you make them.