Adding new models using mod system

Discuss modding questions and implementation details.
User avatar
Hazelnut
Posts: 3015
Joined: Sat Aug 26, 2017 2:46 pm
Contact:

Adding new models using mod system

Post by Hazelnut »

So replacing models or flats with new models is possible, and well trodden ground now.. but as far as I can see there's no way to add a brand new model to DFU, is that correct?

I'm looking at adding a guild sign for the Archaeologists guild halls, so trying to work out how best to do this. All I really need is an existing sign model with a different texture, but I think that means I need to copy the model file (maybe extract it from somewhere) and modify the texture it uses and then add it as a new model. I could be wrong though.

Hoping you can help guide me here, TheLacus or anyone who may know. :)
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
TheLacus
Posts: 1305
Joined: Wed Sep 14, 2016 6:22 pm

Re: Adding new models using mod system

Post by TheLacus »

Adding a model alone is just a matter of instantiating a gameobject at the desired position, which is something you can already do with a script mod. You also need to assing it to location parent for disposing, or use TrackLooseObject() for streaming world.

If you want to allow your model to be overridden by other mods, you can use ModManager.Instance.TryGetAsset(), which seeks assets with load order from their names. Of course you must use an unique name, maybe we can define a sort of standard? For example use model_archaeologists_sign_1 so is basically impossible that another mod provides an unrelated asset with the same name.

Maybe Uncanny_Valley could integrate support for custom models in the level editor, storing custom models by name and then instantiate them automatically.

EDIT
A quick snippet (unstested)

Code: Select all

GameManager.Instance.StreamingWorld.OnCreateLocationGameObject += (dfLocation) => 
{
    GameObject sign;
    if (ModManager.Instance && ModManager.Instance.TryGetAsset("model_archaeologists_sign_1", true, out sign))
    {
        asset.transform.SetParent(dfLocation.transform);
        asset.transform.position = new Vector3(x, y, z); // position...
    }
}
Maybe i'll add an helper in ModManager to instantiate all custom models at once, should be more performant than each mod using its own delegate.
Something like AddGameObject(string locationName, string assetName, Vector3 position);

User avatar
Hazelnut
Posts: 3015
Joined: Sat Aug 26, 2017 2:46 pm
Contact:

Re: Adding new models using mod system

Post by Hazelnut »

Thanks for the info TheLacus, that's very informative.

However adding new models this way doesn't allow them to be referenced by model ids in the data. My mod overrides the world data for the building to convert it into the guild hall. So I want to be able to add a model for the sign in the same way all of the models are referenced in DF - by a model id. I get the distinct feeling I am treading new ground again here... will take a look at the code this evening and have a think about how this could be done.
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
Uncanny_Valley
Posts: 221
Joined: Mon Mar 23, 2015 5:47 pm

Re: Adding new models using mod system

Post by Uncanny_Valley »

I have actually been thinking about this very issue for the last few days. And my suggestion is to allow user to replace non-existing vanilla models. :)

For example, all signs in the game have a ID ranging from 43700 to 43755. And there is no model that has the ID of 43756. So if you set up your custom model, to "replace" model ID 43756, then you could load that replacement model without caring whether not there exist a original. Which should be the case anyway for replacement models (why should we waste and computing time even looking for the original model if we find a proper replacement with the desired ID that we are looking for?). And so the the method (and the code) for adding new objects would be exactly the same as replacing it. Keeping things neat and tidy. And there would need to be a check in the end, that if it fails to find a replacement, and also fails to find a original model with the desired ID, it skips loading that model entirely and prints out a warning.

User avatar
TheLacus
Posts: 1305
Joined: Wed Sep 14, 2016 6:22 pm

Re: Adding new models using mod system

Post by TheLacus »

I never tried it, but id-based addition might (unintentionally) already be functional.

The issue with numeric IDs is that is a mess to merge contributes from different mods. If every mod start counting from 43756 they would all end up being incompatible with each other. This is why i suggested unique names instead, which should highly reduce the chance of a collision. For example custom world data for the archaeologists mod could prefix all model names with model_archaeologists (or something equivalent), and so on.

Maybe you're suggesting to only seek models inside resources of the mod that owns replacement world data? This might be an option, too.
Personally, i think that we should allow any mod to provide an asset replacement, even if the "existence" of this asset in location data was declared by another mod.

User avatar
Uncanny_Valley
Posts: 221
Joined: Mon Mar 23, 2015 5:47 pm

Re: Adding new models using mod system

Post by Uncanny_Valley »

True, there is a risk that mods might accidentally be incompatible with each other. But the risk is pretty low.

There are a total of 10,251 models in Daggerfall, the one with the highest ID is 99,902. So between 0 and that, there are 89,651 unused IDs for modders to use to represent their new model. And the modelID is stored in a UINT32, so in theory you have 4,294,967,295 - 10,251 unique IDs to choose from. (please correct me if I'm wrong).

And in the event that 2 mods happen to use the same ID, a modder could easily correct this by giving it a new ID from literally millions of other possibilities. And if we make sure that there is a very clear error message for the user, in the console for example, that states, "ERROR: The model with ID: (ID) is defined in both (MOD #1) and (MOD #2)", then it can be quickly spotted and reported to the mod author for him/her to correct.

User avatar
Hazelnut
Posts: 3015
Joined: Sat Aug 26, 2017 2:46 pm
Contact:

Re: Adding new models using mod system

Post by Hazelnut »

Thanks guys, I can see both points of view - thanks for the explanations.

I think UV is right that given how sparse the id's are that using numeric id's for new models should be fine for this use case. This will allow them to easily be referred to by overridden block data structures. Models added other ways should definitely use string names though. I hadn't actually realised how sparsely the modelId namespace was being used. The signs are a good example 43700-43755 with next model being 43800, it seems the original devs partitioned the id space for different categories. So for the additional Archaeologist guild hall sign I will use model id 43756.

TheLacus, having now studied the code I think you're right that it will just work out of the box. Still need to try it to be 100% sure of course. The only caveat is that the first model of each block subrecord must be an original model, as if it's not found the code that adds building data will fail I suspect. This will only be relevant if we add ability to replace whole buildings in a city block, and in that case some code changes would be required to allow injected models to do this instead. That bridge is quite a way off, if we ever reach it... :)
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
TheLacus
Posts: 1305
Joined: Wed Sep 14, 2016 6:22 pm

Re: Adding new models using mod system

Post by TheLacus »

Uncanny_Valley wrote: Tue Jul 23, 2019 9:28 pm There are a total of 10,251 models in Daggerfall, the one with the highest ID is 99,902. So between 0 and that, there are 89,651 unused IDs for modders to use to represent their new model. And the modelID is stored in a UINT32, so in theory you have 4,294,967,295 - 10,251 unique IDs to choose from. (please correct me if I'm wrong).
Hazelnut wrote: Wed Jul 24, 2019 7:44 pm I think UV is right that given how sparse the id's are that using numeric id's for new models should be fine for this use case. This will allow them to easily be referred to by overridden block data structures. Models added other ways should definitely use string names though. I hadn't actually realised how sparsely the modelId namespace was being used. The signs are a good example 43700-43755 with next model being 43800, it seems the original devs partitioned the id space for different categories. So for the additional Archaeologist guild hall sign I will use model id 43756.
You're right UV, if the id is chosen randomically chances should be pretty low. I was mostly thinking at Hazelnut example of using the next available id for tavern signs, which is a good idea but only possible because is the first one to do it. New modders will need to be careful, because i think many mod authors will try to follow some logic like this one.

Personally, i consider IDs for models a flaw we inherithed from classic game files. Finding assets with Daggerfall Modelling would be much more simple if resources had meaningful names like most other games. But we have to work with what we have, if new IDs are already working it's fine. :)
Uncanny_Valley wrote: Tue Jul 23, 2019 9:28 pm And in the event that 2 mods happen to use the same ID, a modder could easily correct this by giving it a new ID from literally millions of other possibilities. And if we make sure that there is a very clear error message for the user, in the console for example, that states, "ERROR: The model with ID: (ID) is defined in both (MOD #1) and (MOD #2)", then it can be quickly spotted and reported to the mod author for him/her to correct.
Not sure how to proceed with this one. It is allowed to have multiple mods with the same asset replacement, that's what the load order is for. For performance reasons the game only cares for the first asset found, the remaining mods are not even considered.

User avatar
Uncanny_Valley
Posts: 221
Joined: Mon Mar 23, 2015 5:47 pm

Re: Adding new models using mod system

Post by Uncanny_Valley »

It would have been so much better if the original models where stored with sensible names instead. :) Is is something I have tried to "fix" when working on my editor, linking all models numbers with proper names, so that you can actually search and find what you are looking for... a task that has been very time consuming :(
Not sure how to proceed with this one. It is allowed to have multiple mods with the same asset replacement, that's what the load order is for. For performance reasons the game only cares for the first asset found, the remaining mods are not even considered.
It doesn't necessary have to stop the user, or be a straight error. But maybe log it somewhere? So if a mod doesn't work as intended, the user has something to send the mod author and the author can more easily find our exactly what model and what other mod is in conflict. But yeah, you would need to consider if that would be more important than loading performance.

User avatar
Hazelnut
Posts: 3015
Joined: Sat Aug 26, 2017 2:46 pm
Contact:

Re: Adding new models using mod system

Post by Hazelnut »

TheLacus wrote: Sat Jul 27, 2019 12:00 pm Not sure how to proceed with this one. It is allowed to have multiple mods with the same asset replacement, that's what the load order is for. For performance reasons the game only cares for the first asset found, the remaining mods are not even considered.
I think this will be fine TBH, people will soon report that the wrong model is appearing. An explicit error would be good, but if not easy because of the basic way mod system works, I wouldn't worry too much about it.

There's a similar issue with faction id's and guild groups so I'm thinking of creating a pinned post containing a few small lists of which id's are allocated to which mods and for what. At this time I think only my Archaeologists will be on the lists, but at least it will provide a chance that mod authors will not conflict. Do you guys think that's a good idea?
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

Post Reply