ID:160447
 
Hi,

I have often used the "return" function as a way to end procedures and variables immediately on the spot. I understand that it does something with returning something to the caller (whatever that means), which is what I'm asking. What exactly does it mean for it to return a value to the caller? I would like to better understand this. If someone could explain it to me as if I was a retard, that would be great, as reading both the DM guide several times over and the help guide doesn't explain it to me in terms I'm quite ready to understand.


I have never seen a point to dantoms, why not just use one of the built in ATOM options? I just can't see the purpose in this function. I would like to better understand some of it's useful functions (if any).


An answer to any of these questions would be greatly appreciated :)


I intend to build a on-screen option selection system, just to kill time (plus it's fun ;)) and I was wondering if there's anything useful I should know about making these. I don't want to see a demo, otherwise it kills the fun in it.

I was thinking I would make a proc that would put the object on the user's map up in the corner by using the locate function, (not to mention using something like: m<<object) to make sure only the user can see it, then make it so when the specific object is clicked, it checks to make sure it was the owner who clicked it. This brings me to assign the new object created the user as the owner and vise versa. Then whenever the user calls Move() just make the object copy the movement. I'm not sure yet.<br/>

Thanks for reading.


EDIT: I think my thoughts were slightly jumbled, but hopefully you get the gist of it!
Speedro wrote:
I have often used the "return" function as a way to end procedures and variables immediately on the spot. I understand that it does something with returning something to the caller (whatever that means), which is what I'm asking. What exactly does it mean for it to return a value to the caller? I would like to better understand this. If someone could explain it to me as if I was a retard, that would be great, as reading both the DM guide several times over and the help guide doesn't explain it to me in terms I'm quite ready to understand.

A proc can return a value like so:

proc/Square(x)
return x * x


If you use Square(3) in your code, the proc is run and it returns a value of 9, so it's as if you used 9 in the code.

mob/verb/Squares()
for(var/i=1, i<=10, ++i)
usr << "The square of [i] is [Square(i)]."


By default, a function will return null unless you tell it otherwise.

I have never seen a point to dantoms, why not just use one of the built in ATOM options? I just can't see the purpose in this function. I would like to better understand some of it's useful functions (if any).

A datum is like an atom except it's abstract. It doesn't have to exist anywhere on the map. A datum can represent, say, a group of characters, a guild and its membership, a piece of a pathfinding routine, and much more. In Scream of the Stickster Volume II I've used datums quite a lot in the AI work, because a datum can represent a memory of an object rather than having to be an actual object.

I intend to build a on-screen option selection system, just to kill time (plus it's fun ;)) and I was wondering if there's anything useful I should know about making these. I don't want to see a demo, otherwise it kills the fun in it.

This kind of thing is very well-suited for a datum. It can keep track of any objects it needs, menu items in use, and so on, and do all its own cleanup.

I was thinking I would make a proc that would put the object on the user's map up in the corner by using the locate function, (not to mention using something like: m<<object) to make sure only the user can see it, then make it so when the specific object is clicked, it checks to make sure it was the owner who clicked it. This brings me to assign the new object created the user as the owner and vise versa. Then whenever the user calls Move() just make the object copy the movement. I'm not sure yet.

It sounds like you'd be better off using screen_loc for this rather than images.

Lummox JR
Speedro wrote:
I have often used the "return" function as a way to end procedures and variables immediately on the spot. I understand that it does something with returning something to the caller (whatever that means), which is what I'm asking. What exactly does it mean for it to return a value to the caller?

When the proc is finished running, it returns a value to the proc that called it; often a value that is necessary for it and is used. You've probably been using return values (of built-in procs and operators, though) very often and just not realizing. When a proc or operator is used in a complex expression, before running the actual expression those procs/operators are called, and their return value is used as their 'position' in the expression in order to run it. Take for example this simple line:
var/X = 1 + 5

Of course, this means "set X to the value of (1+5). How it works though, is first the + operator is executed; with the arguments 1 and 5. It then returns a value with the result (6), and that one is used in the expression, so the 2nd argument of the = operator becomes 6, what it returned. The expression of the = operator then just executes as if the original line was this (the result is potentially dynamic though, of course):
var/X = 6


Same for procs.
var/turf/T = locate(1,1,1)

This line calls locate(), and sets what that locate() call returns to the caller (meaning, this current proc) to the variable T. I've used the = operator here, but remember return values can be used most anywhere.
mob/verb/test()
src << locate(1,1,1)
src << 1+5

This outputs to the player (src and usr are both the player in that example FYI) the turf (due to built-in behavior, it will display it's name, potentially with "the" appended) found at 1,1,1 (which locate() returns), then it will output 6, which the + operator returned.
"Custom" procs are no different; the value used in the return statement is passed to the caller for use.
proc/MyProc()
return 1000

mob/verb/test()
src << MyProc()

This simply displays "1000" to the player. Of course, such a proc is useless and return values that are used are dynamic and useful, but this is an example to demonstrate returning. Here's a (very slightly) more complex example:
mob/verb/Jump()
if(src.Can_I_Jump())
src << "You jump high in the air."
flick("jump",src)
else
src << "You can't jump now."

mob/proc/Can_I_Jump() //this one is an object (mob) proc
if(src.busy || src.frozen || !src.loc) //just some checks
return 0
/*note: it's like there is an 'else' statement here,
because the flow of execution will never reach this
spot if the code under the above if() executed - as
that code stops the proc*/

//if we're NOT busy/frozen etc, return 1
return 1

When a player tries to jump, the custom proc is called and executes to decide if he should be allowed to or not - and it lets the caller know the result of that decision through it's return value, 0 representing 'no'/'false' and 1 'yes'/'true'. Naturally it's easier and often better to use standard true and false values like this, but they could be any values, really. Look at this another quick, incomplete example:
mob/verb/Clone_Attack(mob/target in oview())
var/mob/M = src.Clone() //a mob reference is returned by the proc
viewers(src) << "[src] creates a clone!"
M.Attack(target) //call the function on the object so it (the clone) attacks

mob/proc/Clone()
var/mob/x = new(src.loc)
x.icon = src.icon
x.name = src.name+" Clone"
x.dir = src.dir
return x


Notes:
A proc doesn't have to use a called function's return value if it doesn't need it, though it will render certain functions entirely useless (such as the + operator), though some not (such as step()). Not all procs even need to/have distinct return values (in that case null is the result and always returned).

You'll also want to look into the '.' variable; look it up in the DM Reference.

I have never seen a point to dantoms, why not just use one of the built in ATOM options?

It's datums! =P
The reason for using them is for defining your own object type for processing stuff and keeping track of data. Sure, you can do it with an atom; but that is unnecessary and a waste of resources (and there are also [smaller] object instances limit on atoms) - atoms are built-in objects, and map objects, so they have lots of variables for various such purposes. But very often your special object will not need those, so it'll be a waste if it does have them. By principle, if it doesn't need to be displayed on the map control or otherwise be present on the map, it doesn't need to be an atom. There are subtle exceptions such as displaying an object on non-map controls (statpanels, grids) but that's the basic principle. If you have a custom purely-data object handling some 'internal' part of your game such as some effect, party, guild, queue or even battle system, it doesn't need to be on the map or have map-related variables; it's not visual to begin with.

Have you read these?
http://www.byond.com/docs/guide/chap18.html
http://www.byond.com/docs/ref/info.html#/datum (see the 'see also' stuff. =P)

Also take a look at this article on datums by Lummox JR: http://www.byond.com/members/ DreamMakers?command=view_post&post=35530
Note the other stuff and articles on the Dream Makers guild, there are lots of interesting and useful articles to read, especially Lummox'. =P In addition you should consult the DM Reference often (in case you didn't know, you can open it by pressing F1 at Dream Maker).

I was wondering if there's anything useful I should know about making these. I don't want to see a demo, otherwise it kills the fun in it.

I was thinking I would make a proc that would put the object on the user's map up in the corner by using the locate function, (not to mention using something like: m<<object)[...]Then whenever the user calls Move() just make the object copy the movement. I'm not sure yet.

There is a special built-in DM feature for on-map HUD/HUD-like atoms; you'll want to look into screen objects (see the 'screen var (client)' as well). It's much more convenient and it'll stay on-screen at your decided spot(s) automatically. =) For more detailed info on this one, you should try and make use of the search engines throughout the site first; these things are discussed, answered and covered quite a lot, so you should try and use the already available resources and older forum posts first before asking it again yourself.
You might also want to look into interface controls instead, but if you want it on the map, then screen objects are the way to go.
In response to Lummox JR
Screen loc, eh? (by the way, thanks Kaioken and Lummox, I can see some usefulness in them both, yet I fail to see a reason to return anything, there's always easier ways to do it I find.)


mob
verb
add_screen()
on_screen_select(src,1,1,1,new/obj/button)



mob //I tried to use a dantum in this situation, but I can't call on it from the verb with a dantum?
proc
on_screen_select(mob/m,x,y,z,obj/b)
var/n=m.client.screen
b.loc=locate(x,y,z)
n+=b
obj
button
icon='button.dmi'
What on earth am I doing? Just trying to create some sort of procedure where I might find it useful in anything I do. I'm not sure if I should still be trying to make the object copy the user's actions to stay in place... So the client's list now contains the object, I haven't an idea how I even spit out this code. Just some messing around, I guess.
In response to Speedro
Screen-list objects don't use the conventional map-positioning system, which means that loc is not the variable you want. Objects derived from atom/movable, both obj and mob, have a variable called screen_loc which is a text string representing the coordinates and pixel-offset of the object's location on-screen.
mob/verb/add_screen()
on_screen_select(1,1,new/obj/button)
mob/proc/on_screen_select(x,y,obj/b)
var/list/n = src.client.screen
b.screen_loc = "[x],[y]"
n += b
obj/button
icon = 'button.dmi'

There's what your code would look like with the correctly-used screen placement method.

(edit)
And to add to my post, since I forgot to mention the whole "return value" thing...

You probably make use of the return values of functions all the time without realizing it.
mob/verb/whirlwind_attack()
for(var/mob/M in oview(2))
hit(M)

That small code snippet right there makes use of the return value of oview(), as it returns a list. Without that, things would be much, much more complicated.

Heck, client/New() is supposed to return a reference to the client's new mob and, if it was working as it's supposed to (I recall there being a bug with it once upon a time; I don't know if it's still there or not), if client/New fails to return a mob for a player then that player can't even connect to a game in the first place! That would be a huge problem.

In general, separating your program into lots of smaller functions, which are basically sub-programs, makes things much better, easier to work with, easier to debug, more robust, and reusable.
In response to Speedro
The nicety of return comes out of encapsulation. Say I do some standard processing on x and y to get a distance from src to some given mob, it would be nice to write a proc that returns that distance, instead of calculating it myself every time and duplicating that code, or maybe having a proc that just puts the value in a variable on either src or the given mob.

On it's own, you might say "So what, not much different either way". However let's say we adjust the way distance is calculated, perhaps to add distance penalties or to path-find around obstacles. The non-proc option is not looking too nice now, because of all that duplication. Proc and a variable still is alright, however why should every mob carry a variable for that information, when we only need it some of the time? We've lost a potential variable name for mob data, when return would manage the same effect perfectly well AND free up memory when we aren't using it any more, unlike a variable attached to mob, which we'd have to clean up ourselves.

I hope that perhaps further explains the usefulness of return.
In response to Loduwijk
Thanks! Is it really needed to input the pixel offset with
"[x],[y]"
? I've never seen it used before.


Anyways, I just made a little movement system using the button clicking and I stumbled upon the fact that you couldn't click on objects have have them react? I made a work around, but is it really necessary?
obj
button
icon='button.dmi'
call_click()
world<<"uh."
world<<"[usr]"
world<<"[src]"
usr.on_screen_select(usr,2,3,new/obj/north)
usr.on_screen_select(usr,3,2,new/obj/east)
usr.on_screen_select(usr,1,2,new/obj/west)
usr.on_screen_select(usr,2,1,new/obj/south)
client
Click(atom/a)
if(istype(a,/obj))
a.call_click()

atom
proc
call_click()
In response to Speedro
Using "..()" in a proc causes the proc to first call the parent proc, then resume the current proc.
obj
proc/Lol()world<<"Blah"
objtype
Lol()
..() //Call the default action for this procedure, above
world<<"Blah again"
/*
Outputs:
Blah
Blah again
*/


What you want to do is call the default action for Click(). Do that under your button's Click() proc.
In response to Kaiochao
Sorry, big mistake on my part, COMPLETELY forgot about that. That's really bad considering I use it so much.