ID:2156120
 
(See the best response by Lummox JR.)
Okay, i'm trying to create a system of temporary modifiers, and i want special behaviour for when code attempts to add a modifier when one of the same type already exists. my modifiers are just datums.

I create then with a new call, as thius:

modifier = new /datum/modifier/adrenaline(M, MODIFIER_REAGENT, src, _strength = 0.6, override = MODIFIER_OVERRIDE_STRENGTHEN)

The modifier var holds a reference to the created modifier - i check that var regularly and create the modifier if that var is null

Now, the problem. When a modifier of the same type already exists, i have special behaviour depending on the passed override mode. sometimes the new one will replace the old, but in most cases the new one will simply delete itself and return a reference to the existing modifier.

The intended function of this is that the modifier variable in the caller is populated with a reference to the existing one so that it doesn't keep trying to create new ones.

However that doesn't seem to be happening.
The above code always populates that modifier variable with a reference to the newly created datum, regardless of what i return in its new proc.
And since i'm deleting the newly created one when i return something else, that means the modifier var is just getting populated with null, so it keeps trying.

I need some help here. Is there any way to actually get the return var of the new proc into a variable?
Or are there any other methods of outputting something from there? like passing an out/ref variable to write a return into?
mob/verb/Example()
var/obj/o = new
var return_value = o.variable_name
that doesn't work for my example, because the datum immediately qdels itself before it finishes the new proc, which makes references to it null

i need another idea

does DM support passing variables by reference?

Is there any point at all to returning things in a new proc? any way to access the return value that doesnt require saving it somewhere else first?
No, but one workaround I can think of is something like

mob/var/tmp/list/queue = list()

mob/verb/Demo()
var random_id = "[rand()][rand()]"
new/obj(src,random_id)
src << queue[random_id]
queue -= random_id


obj/New(mob/m,random_id)
// 444 being what you would return.
m.queue[random_id] = 444
// Could make the queue[id] a list and return multiple things too ;P
Nanako, you altered the New() proc, yes? (I assume this is what you mean by "new proc" since there is no other one)

the keyword new calls the proc New() but the return value of New() is NOT available from a new statement, you can only ever get the return value of New() (which is usually null because of the above) by doing something like
var/A = thing.New(), Most people never even need to call New() directly, unless you're doing stuff like pooling.

tl;dr:
new != New(), new calls New()
The return value of a new statement is always the object created by that statement
The return value of New() is whatever you make it (usually null)
Best response
Calling new directly isn't your best play here. The behavior you want is called the factory pattern; what you're trying to do is use something like new() that returns an object that may or may not be new.

Roughly, this is what your factory would look like:

proc/NewModifier(datum/object, modifier_type, ...)
var/modifier/old = object.modifier
if(old && old.modifier_type == modifier_type)
old.Combine(...)
else object.modifier = old = new(object, modifier_type, ...)
return old