Initial note: I'm no programmer, so forgive me if I'm misusing terminology concerning OOP.
The single biggest limitation of modding FO is that almost everything of note is done through the use of prototypes. That is to say, any critter, piece of scenery, or pistol mainly exists not as a separate entity, but only as an instantiation of a prototype: a clone of all others sharing its PID except for a few exceptions such as location on a certain map, or having a certain amount of hitpoints in case of a critter, etc.
Working with these prototypes is cumbersome because they're extremely inflexible: you can't dynamically create new ones, and you can only temporarily change them on the fly, and when changing them, you of course immediately implement these changes for all those sharing the PID (which leads to amusing things such as one of Metzger's goons drinking alcohol leading to all his buddies feeling the effects as well). FO2 already saw devs experiencing the hindrances created by this approach as they implemented things like separate NPC levels and a greater variety of weapon modifications. This created the absurd situation where one single party member object had to have several prototypes, and weapons had to have another prototype with a different modification because an object in itself can't change.
So, could some limited form of individuality be attained given the tools we have? Let's look at the tools first, (limited) individuality exists in two forms for objects:
- local variables (LVAR's) in map object scripts.
- object pointers.
The way you could try working with LVAR's is by giving say, every object with a script a separate LVAR which gives them a permanent global ID, and having these objects communicate this ID to some global script whenever the script is loaded. This has some obvious limitations tho which makes it undesirable for me:
- Not every object (notably items due to the too many items bug) can or will have a script.
- Changing every single map object script in this way isn't just a hassle, but is a hassle which instantly makes any mod made with this new feature uncompatible with pretty much everything else.
So, let's move on to object pointers. An obvious drawback they have from LVAR's is that they're temporary: they're refreshed every map load. Another problem is that, like with LVAR's, they're pretty much useless for items because items stack, which disintegrates the pointer to the item that is stacked, making them more or less useless for tracking items consistently. So this route seems a dead end as well.
The only way I see it work is by concentrating solely on critters, which have the sturdiest pointers, and which also have the advantage of something else that gets registered: an inventory. Suppose you were to give every critter a separate amount of some useless misc item (e.g. bottlecaps for FO2), which then gets communicated to a global script, then you'd have persistent objects. You check at map entry/game load for how many bottlecaps are in the critter's inventory, which you can then connect with his object pointer and easily use from that point on (e.g. you have an array with {x bottlecaps : "Hank"}, then at map load you translate that to a temporary array with {obj pointer: "Hank"}). Whenever you don't find any bottlecaps on the critter (e.g. because he's been created recently or because you're entering a new map) then you simply give him a fresh ID and the bottlecaps that correspond. When the critter dies, you remove the bottlecaps from his inventory, which just leaves their appearance (and the player's possible manipulation) during stealing as an inconvenience.
I think this is a viable approach (which, as I said, sadly only works for critters) which is relatively light in terms of computing (and memory, tho that of course depends on how info much you want to store for each individual).
edit: I forgot to mention a second possible approach for critters, which is not to track them based on inventory, but location (i.e. hex, elevation and map). The problem with this is that it's not always easy to track changes (e.g. when a script uses move_to; inventory switches are by comparison AFAIK exclusively reversed immediately after, such as with merchants).
The single biggest limitation of modding FO is that almost everything of note is done through the use of prototypes. That is to say, any critter, piece of scenery, or pistol mainly exists not as a separate entity, but only as an instantiation of a prototype: a clone of all others sharing its PID except for a few exceptions such as location on a certain map, or having a certain amount of hitpoints in case of a critter, etc.
Working with these prototypes is cumbersome because they're extremely inflexible: you can't dynamically create new ones, and you can only temporarily change them on the fly, and when changing them, you of course immediately implement these changes for all those sharing the PID (which leads to amusing things such as one of Metzger's goons drinking alcohol leading to all his buddies feeling the effects as well). FO2 already saw devs experiencing the hindrances created by this approach as they implemented things like separate NPC levels and a greater variety of weapon modifications. This created the absurd situation where one single party member object had to have several prototypes, and weapons had to have another prototype with a different modification because an object in itself can't change.
So, could some limited form of individuality be attained given the tools we have? Let's look at the tools first, (limited) individuality exists in two forms for objects:
- local variables (LVAR's) in map object scripts.
- object pointers.
The way you could try working with LVAR's is by giving say, every object with a script a separate LVAR which gives them a permanent global ID, and having these objects communicate this ID to some global script whenever the script is loaded. This has some obvious limitations tho which makes it undesirable for me:
- Not every object (notably items due to the too many items bug) can or will have a script.
- Changing every single map object script in this way isn't just a hassle, but is a hassle which instantly makes any mod made with this new feature uncompatible with pretty much everything else.
So, let's move on to object pointers. An obvious drawback they have from LVAR's is that they're temporary: they're refreshed every map load. Another problem is that, like with LVAR's, they're pretty much useless for items because items stack, which disintegrates the pointer to the item that is stacked, making them more or less useless for tracking items consistently. So this route seems a dead end as well.
The only way I see it work is by concentrating solely on critters, which have the sturdiest pointers, and which also have the advantage of something else that gets registered: an inventory. Suppose you were to give every critter a separate amount of some useless misc item (e.g. bottlecaps for FO2), which then gets communicated to a global script, then you'd have persistent objects. You check at map entry/game load for how many bottlecaps are in the critter's inventory, which you can then connect with his object pointer and easily use from that point on (e.g. you have an array with {x bottlecaps : "Hank"}, then at map load you translate that to a temporary array with {obj pointer: "Hank"}). Whenever you don't find any bottlecaps on the critter (e.g. because he's been created recently or because you're entering a new map) then you simply give him a fresh ID and the bottlecaps that correspond. When the critter dies, you remove the bottlecaps from his inventory, which just leaves their appearance (and the player's possible manipulation) during stealing as an inconvenience.
I think this is a viable approach (which, as I said, sadly only works for critters) which is relatively light in terms of computing (and memory, tho that of course depends on how info much you want to store for each individual).
edit: I forgot to mention a second possible approach for critters, which is not to track them based on inventory, but location (i.e. hex, elevation and map). The problem with this is that it's not always easy to track changes (e.g. when a script uses move_to; inventory switches are by comparison AFAIK exclusively reversed immediately after, such as with merchants).
Last edited: