ID:2032729
 
(See the best response by Multiverse7.)
Code:
obj
item1
item2
item3
item4


Problem description: If I have some objects declared like the above, how can I also declare in a proc a list of some of the above objects (item2 and item4 for example) so that later on I can loop through all the elements of the list...

You'd be better off creating them all within a subtype and using typesof() to loop over those types.

obj
items
item1
item2
// ... and so on

mob/verb/TypeLoop()
for(var/T in typesof(/obj/items)-/obj/items)
usr << T
Best response
You have to understand the difference between a type and an instance. A type, which is referenced as a path, is the definition used to create an object, while an instance is an actual object that was created from a type.

What you have shown are object types, or more specifically types of /obj.

There is no built-in way to get a list of direct child types, so you will need a new proc to do so:
proc/childtypesof()
var/types[] = list()
. = list()
for(var/type in args)
types += typesof(type) - type
for(var/t in types)
types -= typesof(t) - t
. += types

So calling childtypesof(/obj) will return list(/obj/item1, /obj/item2, /obj/item3, /obj/item4), without all of the other things that we don't care about.

Now if you wanted actual instances instead, you could use this one (which relies on the first, for modularity):
#define islist(x) istype(x, /list)

proc/newchildtypesof()
var/prevtypes[]
. = list()
for(var/a in args)
if(islist(a))
if(length(prevtypes))
for(var/t in prevtypes)
. += new t(arglist(a))
prevtypes = list()
else
if(length(prevtypes))
for(var/t in prevtypes)
. += new t
if(ispath(a))
prevtypes = childtypesof(a)
else
prevtypes = list()
if(length(prevtypes))
for(var/t in prevtypes)
. += new t

So calling newchildtypesof(/obj) will return the equivalent of newlist(/obj/item1, /obj/item2, /obj/item3, /obj/item4).

I'm not sure how useful it is, but I also made it so that if you place a list after a path argument, the items in that list will be used as arguments for the child types' new() functions.

This means calling newchildtypesof(/obj, list(locate(3,3,1))) is the same as list(new/obj/item1(locate(3,3,1)), new/obj/item2(locate(3,3,1)), new/obj/item3(locate(3,3,1)), new/obj/item4(locate(3,3,1))). This can be a powerful way of creating a whole lot of objects very easily, without worrying about loops.

For more information, see the reference sections on typesof() and newlist().
In response to Nadrew
Nadrew wrote:
You'd be better off creating them all within a subtype and using typesof() to loop over those types.

> obj
> items
> item1
> item2
> // ... and so on
>
> mob/verb/TypeLoop()
> for(var/T in typesof(/obj/items)-/obj/items)
> usr << T
>


Thanks for the answer it works fine but I am trying a variation, trying to print the objects names but if I use usr << "[T.name]" it says undefined var and if I replace with var/obj/T it doesn't print anything...
You'd need to create an instance of the object in that case.

var/obj/my_obj = new T
usr << my_obj.name
Using the code I provided above, you can do this:
obj
items
item1
item2
// ... and so on

mob/verb/ItemLoop()
for(var/obj/I in newchildtypesof(/obj/items))
usr << I.name