nipkownix / re4_tweaks

Fixes and tweaks for the "UHD" port of Resident Evil 4
zlib License
342 stars 32 forks source link

Merchant stock unlocking #443

Open Corazon-SA opened 1 year ago

Corazon-SA commented 1 year ago

Hi, first I would like you very much for your hard work with RE4 tweaks, I am very happy with these amazing features I want to ask you about something that is was difficult for many of modders to figure it out, which is changing when merchant unlock his stock and upgrades For example, when you start the game and spawn the merchant in r100, merchant will have nothing in stock, because you still didn't unlock anything, you can unlock new stuff in merchant stock when you enter r104 first (or some other rooms) r104 is the first room you meet the merchant and he unlocks new stuff in his stock, we can only change what is the new stuff he has, but we cannot change room number to another room number Here is some notes from kTeo (Thanks for him)

If you open bio4.exe in hex editing the merchant stock starts at 00811950 i'll give an example of an entry 23 00 02 02 02 02 00 00 23 00 - handgun ID [02 02 02 02] - how many levels of each stat will be available to upgrade the stats are [firepower, firing speed, reload speed, and capacity] respectively FF FF 00 00 00 00 00 00 is what separates each update

Here is The order of the rooms that unlocks things in merchant stock when you enter them :r104 r102 r10e, r11b. r112, r11c, r10f, r200, r202, r204... in my mod for example I wish if I could make it at this order :r11c, r219, 105, r10e, r22c, r205 ...

THANK YOU !!!!

emoose commented 1 year ago

Merchant unlocks seem to be handled inside MerchantRoomInit func: https://pastebin.com/6pH8S6Yq

You can see it's mostly only checking room ID or scenario/unlock flags there, unfortunately the way they check room IDs using switch statements makes it kinda hard to patch though, eg. instead of that doing checks like if room == 0x104, it's doing something like n = room - 0x101, if n == 3, as a kind of optimization, so you can't just simply patch the 0x104 ID (it doesn't show that in the code I linked since that's been cleaned up, but that's mostly how the actual assembly for it works :/)

Maybe would be possible to hook that func and extend it to allow modders to set up custom room -> stock entry list pairs instead... do you know if any other DLL/tool ever implemented something like that?

There also seems to be two different things it changes in those rooms, via levelDataAdd & stockDataAdd, think levelData is for upgrades while stockData is for items, but not totally sure.

Corazon-SA commented 1 year ago

Thank you very much for looking into that, It's sad that it's that complicated

""Maybe would be possible to hook that func and extend it to allow modders to set up custom room -> stock entry list pairs instead... do you know if any other DLL/tool ever implemented something like that?"" That's will be GREAT!, but I don't any DLL or tool that implemented any of that, the only thing that we do is just switch which items that is unlocked in that particular room by editing these offsets in hex editing

'"There also seems to be two different things it changes in those rooms, via levelDataAdd & stockDataAdd, think levelData is for upgrades while stockData is for items, but not totally sure "" Yeah this might be true, because they are two different things, for items upgrading it starts at 00811950 and it covers all upgrades, then after these offsets (I thinks it starts from 00811C90) these are the offsets of items

Thank you !

emoose commented 1 year ago

Trying to think of a good way this could be customized, maybe something like a merchant.ini file, which would contain sections for as many stock lists as you like, with each list then being associated with a room ID that it should be unlocked in.

Something like

[PriceList] # updates merchant price table with any values here
0x13 = 1000
0x14 = 2000
0x16 = 500
0x9 = 300

[Stock_AfterFirstBoss] # Stock sections are for items available to buy/sell, text after "Stock_" can be anything
room=r10c
# numbers are same as the ones in the EXE data
0x13=1
0x14=1
0x16=4
0x9=2

[Upgrades_AfterFirstBoss] # Upgrades sections define the upgrade levels for each weapon
room=r10c
0x13=01010101
0x14=02020202
0x16=00000000
0x9=00000000

[Stock_AfterSecondBoss]
room=r110
0x13=1
0x14=1
0x16=4
0x18=1
0x19=1
0x9=2

...

So when you enter a room it'd just look up if the room is mentioned in any of those sections, and then apply whatever stock/upgrades are listed in the section. Not totally sure whether this could actually work properly though, don't really know how the merchant data gets saved between rooms, hopefully it just keeps the last levelDataAdd / stockDataAdd data in the save somewhere and that stays until it gets changed by another room (unless the pastebin I linked mentions all the rooms that merchant appears in maybe? that could mean you need to define the tables for every room he appears...)

The IDs there should match what's inside the EXE, we do have names that go with those IDs too (https://github.com/nipkownix/re4_tweaks/blob/master/dllmain/SDK/item.h#L8) that we could use in the INI instead, but maybe those names wouldn't be that useful anyway since modders might change what those items are entirely.

E: ohh I forgot we added JSON support in the DLL, maybe would be better suited as a JSON file, will need to have a think about it...

Corazon-SA commented 1 year ago

Having merchant.ini in that format will be awesome! "" don't really know how the merchant data gets saved between rooms, hopefully it just keeps the last levelDataAdd / stockDataAdd data in the save somewhere and that stays until it gets changed by another room"" As far as I know merchant new stock data will be saved when you enter new rooms, if you reach another room with merchant new stock this room has only the data of the new stuff in stock.

here is a tool that extracts bio4.exe and takes some of its value and translate it to .xml file to be easy to edit, this tool is by Khaled thanks to him, he spent months to make it, this tool extract all the offsets of stock, prices, available upgrades, and many other features https://www.mediafire.com/file/h3ezl0c9aeaatoe/Re4ExeExtractor.7z/file You can grab your bio4 and drag it to the tool and it will be extracted, it might be helpful if you want to make merchant.ini You can get the source code from here https://github.com/KhaleedSA/Re4ExeEditorApp

Thanks !

Corazon-SA commented 1 year ago

Hi, I wanted to check, is there any update about this? thank you !

Corazon-SA commented 1 year ago

@emoose Hi, is there any news about the merchant? I am sorry if I seemed to be urgent, I am planning to launch mod World S in 2-3 weeks and merchant is one of my final stages for the mod, so I want to know if there is any news so I can wait or just start it now and make the merchant so basic Thank you very much for your efforts.

ike9000e commented 1 year ago

From how it looks, function MerchantRoomInit relies only on pG->SaveWk_4F90.curRoomId_1C property for performing merchant stock updates, which is a single global variable.

Programmatically, if we were to detour|hook MerchantRoomInit, then anything could be done by swapping that variable just for the time the MerchantRoomInit is called.

Fe., do it by creating a lookup table that maps original room id to new room id. Check if current room id (in pG->SaveWk_4F90.curRoomId_1C) is the room u want stock-update to happen. If it is, manipulate it. Afterwards, when the call to MerchantRoomInit finishes, restore it to the original value.

Hope that makes sense.