Many of us have tried to interact between different types of atom and have mostly succeeded. But success doesnt mean you did it right.
Enter() is only called when something moves onto the turf. It is useful because one can decide whether or not to let the thing Enter()ing enter or not. It is no place to be doing any programming in which youre going to do anything not related to simply allowing entry or not such as teleportation to other locations or display messages to the thing Enter()ing. Enter() should only be used to decide whether or not to let the thing Enter()ing enter or not. To do this, you must return values. 1 if you want the thing to enter or 0 if you dont want the thing to enter. One example showing this would be:
Enter() can also be used to get past density checks. If you return 1 and if density exists, you would still Enter() the turf.
In no case however must you assume that the thing Enter()ing will be a player, or even a mob for that matter. It is vital that you run checks before doing anything. Heres an example showing what not to do:
Ok sure thisll run fine when you go and test it, but have you really thought of all possibilities? What happens if a non-client Enter()s? Or what if its an obj that is Enter()ing? Youre just assuming that theres a usr there and in programming, you dont assume.
First, we need a way to refer to the thing that is Enter()ing. You can do that easily by defining a variable in turf/Enter(). But you cant just do turf/Enter(mob/M) because it could easily be an obj thats Enter()ing. You would get a runtime error like runtime error: undefined variable /obj. We know only something that can Move() will be able to Enter() our turf, therefore we can say that atom/movable will always be safe.
Next we must check to see whether or not the thing Enter()ing is a mob or an obj. A simple ismob() and isobj() test will figure that out. After running one, you should refer to the variable atom/movable/A as var/mob/M or var/obj/O if you plan on accessing mob/obj specific variables and/or procs.
This is where you should do programming that happens after the thing has successfully Enter()ed - such as teleportation or displaying messages to the thing that Entered(). It is called only when Enter() returns 1. It wont be called if Enter() returned 0.
Everything said for Enter() applies to Entered() so theres no point in repeating what is already written above.
A very useful function of Entered() is that we can know where the thing that Entered() is coming from. To do this, simply put a second argument for turf/Entered() and then you can refer to the old location. Uses include getting the distance between the two locations, checking if they came from the right place and sending them back to the old place too.
Ok so weve figured out how to get interaction between turfs and movable atoms, but what about interaction between just movable atoms?
This is one of the most misunderstood procs Ive ever seen. The way it works is that the atom you define Bump() for will be the thing that has to move and collide with something to call Bump() and the thing you define within the Bump() will be the thing collided.
In this, considering something has caused obj/Knife to move, if the Knife collides with a mob or an obj that has density, Bump() for the Knife will be called.
Again you must not assume that the thing youre Bump()ing is a player/client/mob/obj, you need to know! Similar checks used in turf/Enter() will be necessary here. First define the thing that is getting collided. Next, check if its a mob or an obj and then define a variable for it accordingly.
There is no place for usr in Bump()
An example of a strong Bump() system:
In some cases, you may not want to Bump() something but rather have that thing be Bumped() instead. There is no Bumped() proc defined in the DM language, but it is simple enough to make your own. Here is an efficient one Ive found on the forums:
Bumped() works exactly like Bump() only instead of defining the thing Bump()ed, we define the thing thats Bump()ing.
If you do include Bumped() in your projects, be sure to realize that both Bump() and Bumped() wont be called in a collision between two atoms.
In this case, all youll ever see is The knife hit the victim. You wont ever see Victim got hit by the knife because Bump() takes precedence over Bumped().
In conclusion of all interaction: Always have variables know what are the two things involved in the interaction. Run validity checks. Do relevant-to-the-game programming last. Dont use usr!