aVENGER_(RR) Posted July 20, 2007 Share Posted July 20, 2007 For the next revision of Rogue Rebalancing, I'm trying to patch as many creatures as possible instead of directly overwriting the .CRE files. Thanks to my namesake's excellent IE Lister plugin, I've managed to get all the base values which I wanted to change and patching that in worked perfectly. However, I have absolutely no idea how to add new BG2 proficiencies to creatures which currently have none assigned to them. I've tried studying some of the fixpack code (i.e. the Anomen proficiency fix) but I don't understand how it works. For now, I'm simply using the BG1 proficiencies (i.e. small sword and such) since they are very easy to modify and actually work properly even in BG2. However, for proficiencies which did not exist in BG1 (like Two Weapon Style) this workaround obviously won't cut it. So, I'd be much obliged if someone someone could explain to me (preferably in a "step-by-step for dummies" fashion ) what I need to do in order to assign 3 points in TWS to a character who previously had no BG2 proficiency points at all. It would be best if you could demonstrate the necessary code on ARLED.CRE since that's the character which I'm modifying ATM. Link to comment
Avenger Posted July 20, 2007 Share Posted July 20, 2007 You need to add effects, it is not too easy with weidu. Someone could make a diff tool which creates a series of weidu commands to update one file to another. You could use dltcep (or ni) to add the necessary effects and by running the tool you would get the weidu commands. Link to comment
aVENGER_(RR) Posted July 20, 2007 Author Share Posted July 20, 2007 Heh, I know that I can easily add the .EFF's with NI and DLTCEP (that's pretty much what I've been doing so far ) but I'm now trying to "patch-in" my changes in order to increase compatibility with other mods which may alter the same .CRE files. Link to comment
the bigg Posted July 20, 2007 Share Posted July 20, 2007 change the parts in bold. READ_LONG 0x2b8 slotoREAD_LONG 0x2bc itemo READ_LONG 0x2c4 effecto READ_LONG 0x2c8 effectn SET beffectn = effectn SET effectgain = 1 // substitute with actual number of effects to add. // repeat & edit the following three lines for every proficiency you want to add. INSERT_FILE effecto ~path/to/mod/generic_weapprof.eff~ // substitute with path to file. WRITE_LONG effecto + 0x14 3 // number of stars WRITE_LONG effecto + 0x18 101 // the proficiency code, as per stats.ids. WRITE_LONG 0x2c8 beffectn + effectgain SET sloto = sloto } (effectgain * 0x108) WRITE_LONG 0x2b8 sloto SET itemo = itemo + (effectgain * 0x108) WRITE_LONG 0x2bc itemo I'd attach path/to/mod/generic_weapprof.eff if I were able. You can export it from a working .cre using an hexadecimal editor, or here's an uuencoded version: begin-base64 644 path/to/modgeneric_weapprof.eff AAAAAAAAAADpAAAAAAAAAAAAAAAIAAAAYAAAAAkAAAAAAAAAZAAAAAAAAAAg LSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAgLSAAIAAAIC0gACAt//////////////////// /wAAAAAAIC0gACAtIAAAAAAAAAAA/////wAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ==== To decode the UUENCODEd version via GUI, try http://www.seekfordsolutions.com/Products/.../EncoderWizard/. I cannot guarantee for it. EDIT: CD's solution down here is better (no dependancy on external files), but I like simple tp2s and external logic Link to comment
CamDawg Posted July 20, 2007 Share Posted July 20, 2007 Between Fixpack and Tweaks, you can probably find every type of patching known to man. Here's a template you can use for inserting new proficiencies: COPY_EXISTING ~foo.cre~ ~override~ SET "new_fx" = 1 // adjust as needed READ_BYTE 0x33 "fx_type" READ_LONG 0x2b0 "known_off" READ_LONG 0x2b8 "slot_off" READ_LONG 0x2bc "itm_off" READ_LONG 0x2c4 "fx_off" READ_LONG 0x2c8 "fx_num" WRITE_LONG 0x2c8 ("%fx_num%" + "%new_fx%") SET "offset" = ((0x30 + (0xd8 * "%fx_type%")) * "%new_fx%") PATCH_IF ("%known_off%" >= "%fx_off%") BEGIN WRITE_LONG 0x2b0 ("%known_off%" + "%offset%") END PATCH_IF ("%slot_off%" >= "%fx_off%") BEGIN WRITE_LONG 0x2b8 ("%slot_off%" + "%offset%") END PATCH_IF ("%itm_off%" >= "%fx_off%") BEGIN WRITE_LONG 0x2bc ("%itm_off%" + "%offset%") END // repeat this block for every new prof INSERT_BYTES ("%fx_off%" ) (0x30 + (0xd8 * "%fx_type%")) WRITE_SHORT ("%fx_off%" + (0x08 * "%fx_type%")) 233 // opcode: prof WRITE_LONG ("%fx_off%" + 0x04 + (0x10 * "%fx_type%")) 1 // number of stars WRITE_LONG ("%fx_off%" + 0x08 + (0x10 * "%fx_type%")) 90 // proficiency WRITE_LONG ("%fx_off%" + 0x0c + (0x10 * "%fx_type%")) 9 // instant/permanent WRITE_LONG ("%fx_off%" + 0x12 + (0x18 * "%fx_type%")) 100 // probability BUT_ONLY_IF_IT_CHANGES If you just want to modify existing ones, this can be useful. Changing the PATCH_IF conditions is the fun bit. COPY_EXISTING ~bar.cre~ ~override~ READ_BYTE 0x33 "fx_type" ELSE 2 READ_LONG 0x2c4 "fx_off" ELSE 0 READ_LONG 0x2c8 "fx_num" ELSE 0 FOR (index = 0; index < fx_num; index = index + 1) BEGIN READ_SHORT ("%fx_off%" + (0x08 * "%fx_type%") + ("%index%" * (0x30 + (0xd8 * "%fx_type%")))) "opcode" READ_LONG ("%fx_off%" + 0x04 + (0x10 * "%fx_type%") + ("%index%" * (0x30 + (0xd8 * "%fx_type%")))) "stars" READ_LONG ("%fx_off%" + 0x08 + (0x10 * "%fx_type%") + ("%index%" * (0x30 + (0xd8 * "%fx_type%")))) "prof" PATCH_IF (("%opcode%" = 233) AND ("%prof%" = 90%") AND ("%stars%" = 1)) BEGIN // if one star in longswords WRITE_LONG ("%fx_off%" + 0x04 + (0x10 * "%fx_type%") + ("%index%" * (0x30 + (0xd8 * "%fx_type%")))) 2 // then make it two END END BUT_ONLY_IF_IT_CHANGES Link to comment
Ascension64 Posted July 20, 2007 Share Posted July 20, 2007 Here is the way I do it for addition of one effect, using ARLED.CRE as an example. Re-iteratively, you might want to use something more simpler than repeating the code over and over. COPY_EXISTING ~ARLED.CRE~ ~override/ARLED.CRE~ //Declare constants SET FX_BLOCK_SIZE = 0x108 //the size of an effect block SET FX_MODIFY_PROFICIENCIES = 233 //modify proficiencies effect code SET STATS_PROFICIENCYTWOHANDEDSWORD = 93 //stats code for THS proficiency //Read in all block offsets READ_LONG 0x2A0 known_spl_off READ_LONG 0x2A8 mem_info_off READ_LONG 0x2B0 mem_spl_off READ_LONG 0x2B8 item_slot_off READ_LONG 0x2BC item_off READ_LONG 0x2C4 fx_off //Read in all block numbeers READ_LONG 0x2A4 known_spl_num READ_LONG 0x2AC mem_info_num READ_LONG 0x2B4 mem_spl_num READ_LONG 0x2C0 item_num READ_LONG 0x2C8 fx_num //Add an effect block INSERT_BYTES %fx_off% %FX_BLOCK_SIZE% //Populate the effect block with particulars WRITE_LONG (%fx_off% + 0x8) %FX_MODIFY_PROFICIENCIES% //Effect type WRITE_LONG (%fx_off% + 0x14) 3 //Parameter 1 [#Stars] WRITE_LONG (%fx_off% + 0x18) %STATS_PROFICIENCYTWOHANDEDSWORD% //Parameter 2 [STATS.IDS proficiency code] WRITE_SHORT (%fx_off% + 0x24) 100 //Probability 1 //Based on IESDP EFF struct for identification of fields, you can adjust any of these /*WRITE_LONG (%fx_off% + 0x8) type WRITE_LONG (%fx_off% + 0xC) target WRITE_LONG (%fx_off% + 0x10) power WRITE_LONG (%fx_off% + 0x14) param1 WRITE_LONG (%fx_off% + 0x18) param2 WRITE_LONG (%fx_off% + 0x1C) timing mode WRITE_LONG (%fx_off% + 0x20) duration WRITE_SHORT (%fx_off% + 0x24) prob1 WRITE_SHORT (%fx_off% + 0x26) prob2 WRITE_ASCII (%fx_off% + 0x28) resource WRITE_LONG (%fx_off% + 0x30) #dice WRITE_LONG (%fx_off% + 0x34) dicesize WRITE_LONG (%fx_off% + 0x38) saving type WRITE_LONG (%fx_off% + 0x3C) save bonus WRITE_LONG (%fx_off% + 0x40) variable? WRITE_LONG (%fx_off% + 0x44) school WRITE_LONG (%fx_off% + 0x48) unknown WRITE_LONG (%fx_off% + 0x4C) lowestaffectedlvl WRITE_LONG (%fx_off% + 0x50) highestaffectedlevel WRITE_LONG (%fx_off% + 0x54) resistancetype WRITE_BYTE (%fx_off% + 0x58) param3 WRITE_BYTE (%fx_off% + 0x59) param4 WRITE_SHORT (%fx_off% + 0x5A) unk WRITE_LONG (%fx_off% + 0x5C) unk WRITE_LONG (%fx_off% + 0x60) unk WRITE_LONG (%fx_off% + 0x64) unk WRITE_ASCII (%fx_off% + 0x68) vvc resource WRITE_ASCII (%fx_off% + 0x70) res2 WRITE_LONG (%fx_off% + 0x78) caster xpos WRITE_LONG (%fx_off% + 0x7C) caster ypos WRITE_LONG (%fx_off% + 0x80) target xpos WRITE_LONG (%fx_off% + 0x84) target ypos WRITE_LONG (%fx_off% + 0x88) unk WRITE_ASCII (%fx_off% + 0x8C) effect source WRITE_LONG (%fx_off% + 0x94) unk WRITE_LONG (%fx_off% + 0x98) unk WRITE_LONG (%fx_off% + 0x9C) unk WRITE_ASCII (%fx_off% + 0xA0) variable (32) WRITE_SHORT (%fx_off% + 0xC0) caster level WRITE_SHORT (%fx_off% + 0xC2) unk WRITE_LONG (%fx_off% + 0xC4) unk WRITE_LONG (%fx_off% + 0xC8) secondary type WRITE_LONG (%fx_off% + 0xCC) unk WRITE_LONG (%fx_off% + 0xD0) unk WRITE_LONG (%fx_off% + 0xD4) unk WRITE_LONG (%fx_off% + 0xD8) unk WRITE_LONG (%fx_off% + 0xDC) unk WRITE_LONG (%fx_off% + 0xE0) unk WRITE_LONG (%fx_off% + 0xE4) unk WRITE_LONG (%fx_off% + 0xE8) unk WRITE_LONG (%fx_off% + 0xEC) unk WRITE_LONG (%fx_off% + 0xF0) unk WRITE_LONG (%fx_off% + 0xF4) unk WRITE_LONG (%fx_off% + 0xF8) unk WRITE_LONG (%fx_off% + 0xFC) unk WRITE_LONG (%fx_off% + 0x100) unk WRITE_LONG (%fx_off% + 0x104) unk*/ //Set the effect flag - if effect flag is 0 and CRE has an effect, game crashes WRITE_BYTE 0x33 1 //Effect flag //Increment the number of effects SET fx_num += 1 WRITE_LONG 0x2C8 %fx_num% //Check and update block offsets of other data structures PATCH_IF (%known_spl_off% > %fx_off%) || (%known_spl_off% = %fx_off% && %known_spl_num% != 0) BEGIN SET %known_spl_off% = %known_spl_off% + %FX_BLOCK_SIZE% WRITE_LONG 0x2A0 %known_spl_off% END PATCH_IF (%mem_info_off% > %fx_off%) || (%mem_info_off% = %fx_off% && %mem_info_num% != 0) BEGIN SET %mem_info_off% = %mem_info_off% + %FX_BLOCK_SIZE% WRITE_LONG 0x2A8 %mem_info_off% END PATCH_IF (%mem_spl_off% > %fx_off%) || (%mem_spl_off% = %fx_off% && %mem_spl_num% != 0) BEGIN SET %mem_spl_off% = %mem_spl_off% + %FX_BLOCK_SIZE% WRITE_LONG 0x2B0 %mem_spl_off% END PATCH_IF (%item_slot_off% > %fx_off%) || (%item_slot_off% = %fx_off%) BEGIN SET %item_slot_off% = %item_slot_off% + %FX_BLOCK_SIZE% WRITE_LONG 0x2B8 %item_slot_off% END PATCH_IF (%item_off% > %fx_off%) || (%item_off% = %fx_off% && %item_num% != 0) BEGIN SET %item_off% = %item_off% + %FX_BLOCK_SIZE% WRITE_LONG 0x2BC %item_off% END Link to comment
CamDawg Posted July 20, 2007 Share Posted July 20, 2007 Heh, and now we have three ways of doing it. Link to comment
aVENGER_(RR) Posted July 20, 2007 Author Share Posted July 20, 2007 Thanks guys! I've got two more questions: 1) I assume that this code (PATCH_IF...) checks whether the creature already has any proficiency points in the category which I intend to change, is that correct? For example, I wouldn't want to add my 3 points over someone else's 2 points and thus create an invalid value of 5 stars in TWS. 2) Do BG1 proficiency points stack or merely overlap with BG2 proficiencies? I'm asking this because many creatures already have a few points in certain BG1 categories (i.e. small sword). So, I was wondering if I add 2 points in short sword (BG2 proficiency) to a creature who already has 1 point in small sword (BG1 proficiency) would both stack and thus grant the creature 3 points in short swords (i.e. rank of mastery) or would the proficiencies merely overlap with the highest value always taking precedence? Link to comment
Nythrun Posted July 20, 2007 Share Posted July 20, 2007 Proficiencies don't stack; a creature with two stars in two-weapon fighting, three stars in two-weapon fighting, and one star in two-weapon fighting has three stars in two-weapon fighting. BG1 proficiencies also overlap, with the engine selecting the best value. If you just want to avoid the (small) chance of leaving redundant cruft in the .cres that you're patching, you could try something like: COPY_EXISTING ~arled.cre~ ~override~ PATCH_IF (SOURCE_SIZE > 0x2d3) THEN BEGIN READ_LONG 0x02c8 "ec" READ_LONG 0x02c4 "eo" FOR ("i1" = "eo"; "i1" < ("eo" + (0x0108 * "ec")); "i1" += 0x0108) BEGIN READ_LONG ("i1" + 0x08) "op" READ_LONG ("i1" + 0x14) "p1" READ_LONG ("i1" + 0x08) "p2" PATCH_IF (("op" = 0xe9) AND ("p1 != 0x03) AND ("p2" = 0x72)) THEN BEGIN SET "p1" = 0x03 WRITE_LONG ("i1" + 0x14) "p1" SET "i1" = ("eo" + (0x0108 * "ec")) END ELSE PATCH_IF (("op" = 0xe9) AND ("p1 = 0x03) AND ("p2" = 0x72)) THEN BEGIN SET "i1" = ("eo" + (0x0108 * "ec")) END END PATCH_IF !(("op" = 0xe9) AND ("p1 = 0x03) AND ("p2" = 0x72)) THEN BEGIN WRITE_LONG 0x02c8 ("ec" + 0x01) INSERT_BYTES ("eo" + 0x00) 0x0108 WRITE_LONG ("eo" + 0x08) 0xe9 WRITE_LONG ("eo" + 0x0c) 0x01 WRITE_LONG ("eo" + 0x14) 0x03 WRITE_LONG ("eo" + 0x18) 0x72 WRITE_BYTE ("eo" + 0x1c) 0x09 WRITE_SHORT ("eo" + 0x24) 0x64 FOR ("i1" = ("eo" + 0x78); "i1" < ("eo" + 0x84); "i1" += 0x04) BEGIN WRITE_LONG "i1" (` 0x00) END PATCH_FOR_EACH "o1" IN 0x02a0 0x02a8 0x02b0 0x02b8 0x02bc BEGIN READ_LONG "o1" "o2" WRITE_LONG "o1" ("o2" >= "eo" ? ("o2" + 0x0108) : "o2") END END END Link to comment
aVENGER_(RR) Posted July 20, 2007 Author Share Posted July 20, 2007 Thanks for the clarification, Nythrun. A few more questions, how do I patch a .STO file so that it accepts fenced goods and so that thieves are prohibited from stealing from it? Each of these should be within a separate code block, if that is possible, since I'd like to turn several regular merchants into fences and prohibit stealing from some other merchants who are already marked as fences. EDIT - ideally, I'd like to do this in two passes. First, I'd designate a few regular stores as fences, and I assume this can be done en mass for several .STO files ar once. After that is done, I'd like to copy all .STO files in the game, somehow check which ones have the fence flag, and then only mark those as "impossible to steal from". I'm guessing that BUT_ONLY_IF_IT_CHANGES can be used to accomplish this but I'm not sure how to do the base patching i.e. which WeiDU command to use. Could BAND or BXOR be the one I'm looking for, per chance? Link to comment
Nythrun Posted July 21, 2007 Share Posted July 21, 2007 You'll be wanting BOR to add set a flag, and BAND to unset a flag. Erm, I'll explain this better (at all!) when I get a bit more time, if someone more sensible hasn't already done so. COPY_EXISTING ~StoreThatShouldFence1.sto~ ~override~ ~StoreThatShouldFence2.sto~ ~override~ PATCH_IF (SOURCE_SIZE > 0x9b) THEN BEGIN READ_LONG 0x10 "flags" WRITE_LONG 0x10 ("flags" | 0x1000) END BUT_ONLY COPY_EXISTING_REGEXP GLOB ~^.+\.sto$~ ~override~ PATCH_IF (SOURCE_SIZE > 0x9b) THEN BEGIN READ_LONG 0x08 "type" PATCH_IF (("type" = 0x00) OR ("type" = 0x01) OR ("type" = 0x02)) THEN BEGIN READ_LONG 0x10 "flags" WRITE_LONG 0x10 (("flags" & 0x1000) != 0x00 ? ("flags" & (` 0x8)) : "flags") END END BUT_ONLY Link to comment
aVENGER_(RR) Posted July 21, 2007 Author Share Posted July 21, 2007 Heh, I've figured it out in the meanwhile by checking some of the fixpack code for adding and removing area flags. Also, in the end, I've decided against patching mod introduced fences, so I'm not going to patch all stores after all. This is my current code: COPY_EXISTING ~ARLED.STO~ ~override~ // Arledrian's store (fence on the top floor of Gaelan Bayle's house) ~BMTHIEF.STO~ ~override~ // Marina's store (Black Market Thief on the main floor of the Shadow Thief guild) ~SLSHOP01.STO~ ~override~ // halfling male thief merchant in the Slums ~SLSHOP02.STO~ ~override~ // half-orc female thief merchant in the Slums ~ROGER.STO~ ~override~ // Roger the fence (human male thief merchant in the sewers) ~BSHOP01.STO~ ~override~ // Cutpurse (halfling male thief merchant in The Bridge District) ~DMARK.STO~ ~override~ // Fovem (human male thief merchant in the Docks District, appears at night only) ~GORCH.STO~ ~override~ // Gorch (human male merchant on the main floor of MaeVar's Guild) ~SHTHSTOR.STO~ ~override~ // Rattell (Shadow Thief merchant on the main floor the thief stronghold) ~AMSMUG01.STO~ ~override~ // Carras' regular store (Amkathran smuggler in ToB) ~AMSMUG02.STO~ ~override~ // Carras' discount store (Amkathran smuggler in ToB) READ_BYTE 0x10 "flags" WRITE_LONG 0x10 ("%flags%" BOR 0b1000000000000) // allow buying stolen goods WRITE_BYTE 0x10 ("%flags%" BAND 0b11110111) // disallow stealing from fences BUT_ONLY_IF_IT_CHANGES As far as I can see, there seems to be no harm done in flagging a store already marked as fence once again as such (i.e. ROGER.STO) as long as I use BUT_ONLY_IF_IT_CHANGES. Is that correct? Link to comment
Nythrun Posted July 21, 2007 Share Posted July 21, 2007 It's harmless, yes BUT_ONLY will stop WeiDU from making a backup of the file and writing a new copy to the override if that would not do anything. It's more of a clutter reducer than it is harm prevention. You're alternating between treating the flags as a dword and as a byte, though, so you'll be wanting READ_LONG for the flags, in case something else in the second byte is set. It'll probably work as written, but something like READ_LONG 0x10 "flags" SET "flags" |= 0x1000 // allow buying stolen goods SET "flags" &= (` 0x08) // disallow stealing from fences WRITE_LONG 0x10 "flags" is safer. Link to comment
aVENGER_(RR) Posted July 21, 2007 Author Share Posted July 21, 2007 Thanks again Nythrun, it works like a charm now. Link to comment
cmorgan Posted July 21, 2007 Share Posted July 21, 2007 I need to set aside a few hours to study this thread very carefully - I almost understood a little, so I must be learning something Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.