Locating a specific building in a location's JSON?

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

Re: Locating a specific building in a location's JSON?

Post by Hazelnut »

Hazelnut wrote: Thu Feb 04, 2021 11:55 am One of the RMBs you've modified is the same one as I change in my mod. I'm going to see if the override system handles this as I hope it will, it's a good test. I can see that as currently implemented it wont have a record to match in location data, so I think converting to building override will help avoid having to override every location it's present, but to get the name to vary by location would require some more changes.

Thinking of maybe making the NameSeed get combined with location index to achieve this as a way to automate and avoid lots of location data overrides being required for this type of change. I tried it out and it works great. What do you think?
So I've done the addition of location index to name seed to automatically vary shop/tavern names accross locations, just FYI.

The other thing I've done is to see if the override system will allow an overridden RMB to have a building overridden and it doesn't. I'd forgotten some implementation details, but the RMB replaces the entire block data which is never read from DF datafiles, wheras building overrides are merged in as DFU reads the DF datafiles. So essentially if someone has your mod then no other mods can alter the blocks you've replaced. (probably a good safelty feature actually)

Anyway this would be fine if you'd done significant work and they were completely different, as the buildings would be incompatible with the new block, but in this case where you're trying to correct issues I think it's a serious problem.

I've forked your repo and I'm going to convert ARMRAM03.RMB to building overrides so it doesn't break my Mountain Rumors quest and as an example of how you can migrate your overrides easily enough. I'll submit a PR with the changes for you to review in a little while. Thanks again for keeping such great records of your changes - makes this much easier! :)
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
XJDHDR
Posts: 158
Joined: Thu Jan 10, 2019 5:15 pm
Location: New Zealand
Contact:

Re: Locating a specific building in a location's JSON?

Post by XJDHDR »

Sorry for the late reply.
Hazelnut wrote: Wed Feb 03, 2021 8:03 pm So I've updated the section titled "Altering an existing town building" in this post viewtopic.php?p=32886#p32886 with details of how the building list stuff works with building overrides, as well as the NameSeed I've added. (should hopefully be in the next DFU release)

Please give it a read and let me know if you have any questions, or whether it's clear?
Nothing jumps out at me as needing an improvement.
Hazelnut wrote: Wed Feb 03, 2021 8:03 pm Also, if you need any assistance with converting any work from block to building overrides I'm happy to help. I know this stuff is confusing and I definitely want the initial mods to be good examples of efficient use of the world data system.
Don't worry. I think I know how building overrides work. Also, I need to check but I think converting from Block to Building overrides or vice versa can be done by dumping the one while the other is installed.

Hazelnut wrote: Thu Feb 04, 2021 11:55 am Now your website is working for me I can see that you've documented every change - nice work, very impressed actually! (I imagine that I'd have not done that and then regretted it half way though making the mod if it were me :lol:)
Thanks. I do that partly so that I can remember what I've changed.
Hazelnut wrote: Thu Feb 04, 2021 11:55 am I can see that as currently implemented it wont have a record to match in location data, so I think converting to building override will help avoid having to override every location it's present, but to get the name to vary by location would require some more changes.
Yeah, I've already encountered that issue and had to do some corresponding location overrides. The Temple to Zen fix was particularly nasty.
Hazelnut wrote: Thu Feb 04, 2021 11:55 am Thinking of maybe making the NameSeed get combined with location index to achieve this as a way to automate and avoid lots of location data overrides being required for this type of change. I tried it out and it works great. What do you think?
Sounds good. My only concern is if a building override that doesn't touch the name seed changes the buildings' names from vanilla.
Hazelnut wrote: Fri Feb 05, 2021 7:59 pm The other thing I've done is to see if the override system will allow an overridden RMB to have a building overridden and it doesn't. I'd forgotten some implementation details, but the RMB replaces the entire block data which is never read from DF datafiles, wheras building overrides are merged in as DFU reads the DF datafiles. So essentially if someone has your mod then no other mods can alter the blocks you've replaced. (probably a good safelty feature actually)
I'm very surprised and not so sure that this should be the correct way to do it. My thought is that the thing which has the smaller scope should override the thing with more. In fact, one of the reasons I went with block and location overrides is because I assumed that it worked this way. I also think the current implementation could cause issues for modders that made conflicting mods.

Let's take one possible scenario where modder #1 wants to edit a block's ground textures and Misc3dObjectRecords in the block while leaving buildings alone. Meanwhile, #2 creates a mod where he/she edits a few buildings in the block. #2 uses Building overrides whereas #1 uses a Block override since he/she has to. With how I thought things were implemented, the two mods would automatically be compatible. With how things are currently done, the two mods are incompatible unless #2 releases a separate version of the mod that consists of a block with the contents of both the Block and Building overrides.

For another scenario, modder #1 releases a mod that completely overhauls a Block and #2 makes one small change to one of the buildings. With how things are currently done, #2 once again has to release a separate version that uses the altered block and that one edit. With my assumption, #2 only needs to release a separate version of the Building override that has the changes from the two mods merged. Conversely, if #1 wants to prevent #2's mod from overriding the Block changes if his/her mod has a later priority, this can be done by creating Building overrides with the same data for every building.

That said, this is all just my opinion.

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

Re: Locating a specific building in a location's JSON?

Post by Hazelnut »

XJDHDR wrote: Sun Feb 07, 2021 8:54 pm 1. Sorry for the late reply.

2. Sounds good. My only concern is if a building override that doesn't touch the name seed changes the buildings' names from vanilla.

3. I'm very surprised and not so sure that this should be the correct way to do it. My thought is that the thing which has the smaller scope should override the thing with more. In fact, one of the reasons I went with block and location overrides is because I assumed that it worked this way. I also think the current implementation could cause issues for modders that made conflicting mods.
1. No problems, I know you were deep into other bits of code. I just wanted to get my end sorted and keep you updated. No rush. :)

2. That should never be an issue, as if a building override is altering a vanilla named building it will have FactionId as 0 so that the location building data is used as normal. This should be clear from the documentation, but if you take another look and it's not - let me know.

3. The reason is performance. I understand your reasoning, but in many ways if someone overrides an entire block then they've probably changed it completely and TBH they should create a new block instead.. so I don't see this being a big concern. Hopefully the docs point in that direction now. I'm not saying there will never be a good reason to override an entire vanilla block, but I find it hard to think of a scenario where building overrides would not be better.
See my mod code for examples of how to change various aspects of DFU: https://github.com/ajrb/dfunity-mods

User avatar
XJDHDR
Posts: 158
Joined: Thu Jan 10, 2019 5:15 pm
Location: New Zealand
Contact:

Re: Locating a specific building in a location's JSON?

Post by XJDHDR »

I'm posting this because I thought I figured out how to work out a building's position in the location's Buildings array but there seems to be something wrong with my calculations.
  • First, determine which building number your building is in it's Map Block (i.e. Is the the 1st building? The 2nd? 3rd?).
  • Near the bottom of the location's json, there is a BlockNames array inside the ExteriorData object. Inside this array is a list of all the Map Blocks the location uses.
  • In that array, find the Block that has the building you're looking for. If there are multiple copies of that block, repeat the below procedure for all of them.
  • Note all the blocks above the one you're interested in. You will need to create a json dump for all of them.
  • Open the json for each of the preceding blocks. On line 8 of each block, you will find the value called NumBlockDataRecords. Take note of this value for each of the blocks.
  • Next, you need to add all of these numbers together. If a particular block appears multiple times in the list preceding the block you're interested in, multiply it's NumBlockDataRecords value by the number of times it appears. To this total, you also need to add the number of the building you're interested in.
  • The total you get should show you which building in the location's Buildings array it is. However, it doesn't.
To illustrate this procedure, I was looking for a specific bookstore found in Burgwall, Daggerfall. The bookstore is the 3rd building in the block LIBRAL03.RMB.
  • BlockNames is on line 2486, with LIBRAL03.RMB the entry on line 2501.
  • Looking at the list, the following blocks precede LIBRAL03.RMB once unless indicated otherwise: ALCHAL03.RMB, GEMSAL02.RMB, GEMSAL03.RMB (x2), TEMPAAH0.RMB, WALLAA02.RMB, WALLAA03.RMB, WALLAA05.RMB, WALLAA06.RMB (x3), WALLAA07.RMB (x2) and WALLAA10.RMB
  • After opening the dumped json for each of these blocks, they had the following numbers in their NumBlockDataRecords values: ALCHAL03.RMB = 15, GEMSAL02.RMB = 19, GEMSAL03.RMB = 19, TEMPAAH0.RMB = 14, WALLAA02.RMB = 1, WALLAA03.RMB = 1, WALLAA05.RMB = 4, WALLAA06.RMB = 4, WALLAA07.RMB = 4, WALLAA10.RMB = 4
  • Adding the numbers together, I get: 15 + 19 + 19 * 2 + 14 + 1 + 1 + 4 + 4 * 3 + 4 * 2 + 4 + 3 = 119
  • However, the bookstore in question is actually in position 84.

User avatar
BadLuckBurt
Posts: 609
Joined: Sun Nov 05, 2017 8:30 pm

Re: Locating a specific building in a location's JSON?

Post by BadLuckBurt »

I don't think you need NumBlockDataRecords. The index of SubRecords should correspond with the BuildingData array but I will whip up some Javascript to run on the location JSON to see if that's actually the case, will report back once I know more.
Daggerfall Unity on UESP: https://en.uesp.net/w/index.php?title=T ... fall_Unity
Daggerfall Unity on Nexus Mods: https://www.nexusmods.com/daggerfallunity
My github repositories with mostly DFU related stuff: https://github.com/BadLuckBurt

User avatar
XJDHDR
Posts: 158
Joined: Thu Jan 10, 2019 5:15 pm
Location: New Zealand
Contact:

Re: Locating a specific building in a location's JSON?

Post by XJDHDR »

NumBlockDataRecords is the number of objects in the SubRecords array. As you probably know, every Map Block has exactly 32 objects in it's BuildingDataList array, most of which are unused. Thus, I used NumBlockDataRecords to get the number of buildings in the block.

There is one possibility I just thought of. My maths assumes that a location's Buildings array is an ordered list. If this isn't the case, then the relevant buildings could be anywhere. Alternatively, maybe it is an ordered list but not in the order given in the BlockNames array.

Post Reply