ID:2053309
 
(See the best response by Kaiochao.)
Code:


Problem description:
Hello guys!
It's been a long time I don't code in DM, basically 4~5 years, and maybe some things have changed and I don't know. My question, as the title says, is that I want to create an obj and all of its properties dynamically, but I've ran into some problems... first let me explain the full situation:

This is what I have:

/obj/abilities/projectiles
Fire
name = "Fire"
icon = 'abilities/Fire_Ability.dmi'
Earth
name = "Earth"
icon = 'abilities/Earth_Ability.dmi'
obj/abilities/icons
Fire
name = "Fire"
icon = 'abilities/Fire_Icon.dmi'
Earth
name = "Earth"
icon = 'abilities/Earth_Icon.dmi'
obj/abilities/icons
verb/Activate()
var/obj = "/obj/abilities/projectiles/[src.name]"
var/obj/abilities/projectiles/p = new obj
p.loc = usr.loc


The idea is that I have separated files for the icon shown in the Abilities Tab and the icon shown in the map (cause of different sizes and properties).
It works perfectly, but I'd want to go even further. The way it works now is that it's needed to create an abilities/icon and an abilities/projectiles, but I don't see why I would need that, I can have all the information needed only in abilities/icons and then create all the projectiles dynamically. Like this:

/obj/abilities/projectiles

obj/abilities/icons
Fire
name = "Fire"
icon = 'abilities/Fire_Icon.dmi'
Earth
name = "Earth"
icon = 'abilities/Earth_Icon.dmi'
obj/abilities/icons
verb/Activate()
var/path = "abilities/[src.name]_Ability.dmi"
var/obj = "/obj/abilities/projectiles/[src.name]"
var/obj/abilities/projectiles/p = new obj
p.icon = text2path("abilities/[src.name]_Ability.dmi")
p.whatever = src.whatever
p.loc = usr.loc


The idea is that I wouldn't need to create the projectiles, I know it sounds a little bit too much, but imagining that the game might have 100+ abilities the code will have half the size it would have the other way, besides that it becomes easier to understand (I think).
The problem is that it simply doesn't work, sometimes it throws an error of icon, saying that the icon doesn't exist, other times ir runs, but nothing happens, etc (I tried a bunch of things found here in the Forum, like text2path() file() new(IconPath), but none of them worked).

My main question is if that's possible, if so just tell me the path and I'll find it. Besides that, do you think that's a good practice? Should I be doing any other thing? I'm not so used to game development, maybe there's another way.
For now all I have to say is thank you for helping, I hope I'm not disturbing you niether making you lose time with a silly question.
Best response
text2path() converts text to a type path, not a file path. It's typically used to create objects dynamically, but as you can probably tell, it's not required by the "new" instruction.

file() returns a reference to a file relative to the .dmb file. Since icon files aren't included with packaged executables, this isn't the way to do it.

If the question is how to get an icon from the cache dynamically, you can't. However, you can generate a list that associates an icon's filename to its actual resource reference. For example, if you have an associated list (AKA "map" or "dictionary") of resources like so:
var RESOURCES[] = list(
"abilities/Fire_Icon.dmi" = 'abilities/Fire_Icon.dmi',
"abilities/Earth_Icon.dmi" = 'abilities/Earth_Icon.dmi',
// etc.
)

Then you can get your icon pretty easily:
p.icon = RESOURCES["abilities/[name]_Ability.dmi"]

You can generate that RESOURCES list using code, too.
var out = "GENERATED CODE.dm"
text2file("var RESOURCES\[] = list(", out)
var files[] = flist("abilities/")
for(var/i in 1 to files.len)
text2file(" \"[files[i]]\" = 'abilities/[files[i]]'[i <= files.len ? ", " : ]", out)
text2file(")", out)
Ohhh, that's pretty interesting and I had no idea I could do that here.

I'll try it out and tell you how it goes.