patel-nikhil / SHCLiveStatReader

A program that reads and stores Stronghold Crusader stats, as they happen in game
7 stars 2 forks source link

Send current buildings/units #8

Closed GRhin closed 4 years ago

GRhin commented 4 years ago

Hi Nikhil, Can you add building counts to the output of SHCPlayerData.txt? For example: Player1 : {buildings: { Granary : 1, Woodcutter: 3, Hunter: 4 ....}, Units: {Engineers: 20, Horse Archers: 15, Assassins: 6 ....}} even better if you could get seige units (and account for ghost engineers...) I am happy for Buildings and Units to be ids (though it would be good to provide an array with id -> Unit Name for completeness)

patel-nikhil commented 4 years ago

This one should be next on my list. I have the framework setup now with a json file mapping the ids and names for buildings and units (credit to J-T-de as I used the values he found and put in his repo and made it json friendly

For buildings I just have to wrap my head around the code (using a lot of nested dictionaries and lists with weakly typed objects makes it fun to keep track of it all).

For units I know where player 1 assassin count is. I am hoping that other unit counts are stored in the same area and it's not separated by ie. european, arabic, siege unit types. I am also hoping that the offset for unit type is based on the unit id.

J-T-de commented 4 years ago

Regarding buildings: I did not find an array, where the building counts are stored.

I know, that some are stored in an 4-byte integer, for example churches and cathedrals, and these counts get, as far as I know, updated when any building is built or destroyed (and used to get the church and cathedral bonus). For other buildings I also did not find any counter. For the marketplace, I am sure that there is neither a 4-byte integer nor an 1-byte integer for the building count (and I did not find something unique which encodes a boolean isbuild), so I guess there are only fixed building counters for things, which are really needed for game logic. For the other things, there might be some function, which scans the entire map for a specific building of a specific player, but I am only guessing. Maybe you find out more by starting with the church counts

Regarding the units: There is some stuff in my repo, for example function getTroopCountAddress(player, troop) which I found in another CheatTable, however, I vaguely recall it only worked for European units... Anyway, these numbers (for player one) get displayed in the Army tab, so these numbers definitly exist ;)

edit: I have named a function building_count_update @00458F70 in 1.4.1 (unpatched, not extreme) which I vaguely recall sets church and cathedral counts. So I guess all the dwords there are building counts, but this are definitly not all buildings...

patel-nikhil commented 4 years ago

Yeah, I came to a similar conclusion about buildings; thanks for the confirmation. I did find the address where the first building placed gets stored, and the offset between each.

Unfortunately instead of being separated by player, all buildings are in the same place and the "owning" player gets stored with it. So in my latest commit(s) I've used that starting location, and scanned the area reading all buildings until I reach total building count per player.

Regarding churches and cathedrals: that is very interesting. I think they probably have a count since they have an effect on popularity?

For units, I haven't implemented anything yet but I found that there is an offset of 0x970 for arabic units. (ie. take address for European archer and add 0x970 and you will have count for arabic archers). Also TROOP_ID 32 is tunnelers. I haven't confirmed but I believe troop id 64 is cows

patel-nikhil commented 4 years ago

Another thing for units I was unable to find in spite of searching was counts for individual siege weapons. I only found the total number of siege weapons. Perhaps you have an idea how that is done? Because similar to other units, the counts for siege weapons are shown on the Army tab... my current thinking is that a function scans the area and calculates the count, only when the tab is open

J-T-de commented 4 years ago

Yeah, I came to a similar conclusion about buildings; thanks for the confirmation. I did find the address where the first building placed gets stored, and the offset between each.

Unfortunately instead of being separated by player, all buildings are in the same place and the "owning" player gets stored with it. So in my latest commit(s) I've used that starting location, and scanned the area reading all buildings until I reach total building count per player.

I saw this yesterday evening, very nice! Maybe you want to share your insights with the Sourcehold community? They are currently reversing the map format (which might be useful for many SH and SHC related things), and your data in the 'buildings.json' might be one puzzle piece.

Regarding churches and cathedrals: that is very interesting. I think they probably have a count since they have an effect on popularity?

Precisely, when calculating popularity, there is a 'if (number_of_churches != 0){ popularity += 25 }'

For units, I haven't implemented anything yet but I found that there is an offset of 0x970 for arabic units. (ie. take address for European archer and add 0x970 and you will have count for arabic archers). Also TROOP_ID 32 is tunnelers. I haven't confirmed but I believe troop id 64 is cows

Thanks, I will add those IDs. I also found some more names in the language files of firefly's text compiling tool, maybe there will be some new info.

Another thing for units I was unable to find in spite of searching was counts for individual siege weapons. I only found the total number of siege weapons. Perhaps you have an idea how that is done? Because similar to other units, the counts for siege weapons are shown on the Army tab... my current thinking is that a function scans the area and calculates the count, only when the tab is open

I will check this. But maybe its the same as with the buildings?

For the parts I worked with, most information which is displayed is not determined if this part is not displayed. For example, if you open the ale tab, there is different information displayed. However, everything except the number of active inns (iirc) is zeroed/not updated if you close this information. The active inns are needed to calculate the popularity. (And it took me more time than I like to admit to find out this fact).

patel-nikhil commented 4 years ago

Yeah units are stored like buildings in a similarly massive block of space, with all the details such as player, health, etc. But it surprises me that I could find a total siege engine count, and not one for individual siege engines. I'm not sure even in aic there is anything that relies on the total number of siege weapons so I can't fathom why there is one and not the other.

You mention ale -> 0x011F46D0 (1.41-E + UCP) is the address where the ale coverage percentage gets stored, and it's there even without opening popularity tab or clicking on an inn. It's near the granary information such as rations, and whether a type of food is served/banned

J-T-de commented 4 years ago

Yeah units are stored like buildings in a similarly massive block of space, with all the details such as player, health, etc. But it surprises me that I could find a total siege engine count, and not one for individual siege engines. I'm not sure even in aic there is anything that relies on the total number of siege weapons so I can't fathom why there is one and not the other.

You never know... not everything behind the scenes makes sense in the game...

You mention ale -> 0x011F46D0 (1.41-E + UCP) is the address where the ale coverage percentage gets stored, and it's there even without opening popularity tab or clicking on an inn. It's near the granary information such as rations, and whether a type of food is served/banned

Ah, you right. I must have had something different in mind...