Request and use new function pointers
It would reduce bugs and code duplication significantly if we had access to some key DF functions, including:
- make
(building/squad/unit/item) - complete building (see https://gist.github.com/ab9rf/9fedca12642859d68db44fd3dd529990)
- assign
to (e.g. unit to occupation in location) - add sizeof()s to the global table
- chop tree (with and without producing logs)
Generating names is one that I'd love to see. I'm willing to bet that name generation has a lot going on under the hood, so dfhack created things are always going to be named differently to vanilla
Not all of these things are likely to be instance methods - e.g. "make" is probably a constructor or static function, which can't easily be made virtual.
that said, pretty much anything that only makes sense to call while a map is loaded can be (and honestly probably should be) a member function of the (singleton) world class. there's a lot of stuff that operates on globals that are nonetheless members of the world type or one of its unique members, which we can tell because the address of the global is loaded into RCX for the call (and then often unused in the implemention)
one that i would love is world_data::getBiome or whatever it's called in toady's code (it's at 0x140b69a60 in 50.05-steam). we have an implementation in dfhack but it's reverse-engineered, and if we could just call the one in game we wouldn't have a risk of it being out of sync.
i suppose i could write a recognizer to find it with each release.
Not all of these things are likely to be instance methods - e.g. "make" is probably a constructor or static function, which can't easily be made virtual.
I can all but guarantee that they're static functions - if you take a look at the source code for Kobold Quest, Toady used static "create" and "create_for_load" functions to create the various objects, and the DF disassembly shows the exact same pattern being used all over the place.
world->jobs.cancel_job appears to cause crashes when called with DestroyBuilding jobs. We either need a different function or more information about how to call the one we have. We also have to do an inordinate amount of cleanup before calling this function, further implying that it's not the one we need.
buildingst::deconstruct
arena reset (especially with regards to restoring the terrain, removing/reinstating trees, etc.)
arena reset
I'm not sure that has a relevant class to attach a vmethod to (and IMO, is probably a lower priority).
- sell prices, given a caravan_state
- item description given type, subtype, material, gloss, etc.
- item description given item
- unit description given unit
- art form description given art form
For reference, what we call caravan_state looks to be what Toady calls plot_merchantst.
- There are at least 4 different functions for getting item values:
-
- one is an item method with 3 parameters (
plot_merchantst *+entityst *+bool ignore_foreign) which recursively grabs container contents and calls the one below.
- one is an item method with 3 parameters (
-
- one is an item method with 2 parameters (
plot_merchantst *+entityst *) which includes civ preferences + quality + improvements + wear + trade agreements + stack size after calling the one below
- one is an item method with 2 parameters (
-
- one is an item method with zero parameters which just calls the one below with the item's properties
-
- one is a global function that takes
item_type + subtype + material + matglosswhich just multiplies the base value by the material value
- one is a global function that takes
- The item method for "is wood derived" might be nice, given that "is animal derived" is already virtual
I'm not sure that has a relevant class to attach a vmethod to (and IMO, is probably a lower priority).
there's no reason why toady can't just add a function pointer to the global "cheatsheet", especially now that (since we're firmly in 64-bit land) there aren't a plethora of calling conventions to deal with anymore. also, the compiler will notice that the function has had its address taken and will ensure that a callable version of its exists even if all of its other uses are inlined elsewhere
this is actually probably a better solution than artificially virtualizing things, since it avoids the overhead of forcing regular calls to that function from being forced through a vtable. it would mean that we couldn't easily interpose those functions though
For classes that don't have subclasses, vmethod calls tend to get optimized out anyway, so we can't always interpose them (e.g. job_handler::cancel_job()). Or maybe that's only for instances of classes whose types are known at compile-time (e.g. globals). As long as DF can guarantee a stable calling convention for exposed function pointers, I would be ok with going that route. I think this is basically what Putnam/Myk had in mind when talking about exposing a rudimentary "API" for common tasks too.
the C++ standard guarantees that any function whose address is taken with the & operator will be callable via the pointer generated in that manner, so if toady explicitly stores a pointer to a function into a global variable, that function is guaranteed to be callable
even greater genericism can be obtained using std::function, which can wrap pretty much any callable object and store it in a stable manner
TranslateName()
convert cancel_job to a function pointer so the hack in #3713 can be reverted
getZoneValue(unit) (unit may be NULL)
getZoneValue(unit)(unitmay be NULL)
more specifically, building_civzonest::valuation(unitst *un) is what we're looking for here
buildingst::blastbuilding would be nice -- see Discord discussion: https://discord.com/channels/793331351645323264/807444515194798090/1268955236849160267
Interestingly, we already wanted that function as of Feb 2023, just under our name for it (rather than Toady's name):
[> buildingst::deconstruct
](https://github.com/DFHack/dfhack/issues/2746#issuecomment-1432646518)
Fn that gives "a day's travel", etc.
make_announcement or markup_text_boxst fns.
Fn for playing FMOD sounds.
Fn for removing tile (recalc tile light, building support, items fall, etc.)
Fn(s) that give name/prof as displayed by unit list.