erebusant Posted December 17, 2007 Share Posted December 17, 2007 I've been working on a patching version of Improved Battles and have run across a few different instances where patching an effect into a CRE is very different depending on what effect you are using. It seems that the Effects that have the hex offsets sequence 8,c,0,4,8,c from top to bottom patch very easily without a lot of effort, while the Effects that have the hex offsets sequence 4,8,c,0,4,8,c need to be run through a very convoluted evolution in order to get them to patch into the cre properly. In the 1st instance I use the following code (blatantly borrowed from BP): SET found = 0 SET "info_ext"=0 FOR( cnt=0; cnt<"%effects_num%"; cnt=cnt+1 ) BEGIN READ_LONG ("%effects_offset%"+cnt*0x108+8) "type" READ_LONG ("%effects_offset%"+cnt*0x108+24) "effect" PATCH_IF( "%type%"=101 ) AND ( "%effect%"=13 ) BEGIN SET found=1 END END PATCH_IF( found=0 ) THEN BEGIN LAUNCH_PATCH_MACRO ~SET_CRE_EFFECT_VARIABLES~ SET offset = ("%effects_offset%"+0x108*"%effects_num%") INSERT_BYTES offset 0x108 WRITE_LONG offset+8 101 // +8 = Effect Type WRITE_LONG offset+12 1 // +12 = Target Type WRITE_LONG offset+16 0 // +16 = Power WRITE_LONG offset+20 0 // +20 = Unknown WRITE_LONG offset+24 13 // +24 = Effect Type (ie;Normal or Improved) WRITE_LONG offset+28 1 // +28 = Timing Mode WRITE_LONG offset+32 0 // +32 = Duration WRITE_LONG offset+36 100 // +36 = Probability 1 WRITE_LONG offset+40 0 // +40 = Probability 2 SET "effects_num"="%effects_num%"+1 WRITE_LONG 0x2c8 "%effects_num%" SET "info_ext"="%info_ext%"+0x108 END PATCH_IF ("%info_ext%">0) BEGIN PATCH_IF ("%known_spells_offset%">="%effects_offset%") BEGIN "known_spells_offset"="%known_spells_offset%"+"%info_ext%" WRITE_LONG 0x2a0 "%known_spells_offset%" END PATCH_IF ("%spell_memorization_offset%">="%effects_offset%") BEGIN "spell_memorization_offset"="%spell_memorization_offset%"+"%info_ext%" WRITE_LONG 0x2a8 "%spell_memorization_offset%" END PATCH_IF ("%item_slots_offset%">="%effects_offset%") BEGIN "item_slots_offset"="%item_slots_offset%"+"%info_ext%" WRITE_LONG 0x2b8 "%item_slots_offset%" END PATCH_IF ("%items_offset%">="%effects_offset%") BEGIN "items_offset"="%items_offset%"+"%info_ext%" WRITE_LONG 0x2bc "%items_offset%" END PATCH_IF ("%spell_memorized_offset%">="%effects_offset%") BEGIN "spell_memorized_offset"="%spell_memorized_offset%"+"%info_ext%" WRITE_LONG 0x2b0 "%spell_memorized_offset%" END END And in the 2nd instance I need to use the following procedure (also blatantly borrwed from BP): <<<<<<<< PROF_EFF.TBL CREATURE PROF_TYPE NECESSARY_STARS sevpat01.CRE 97 2 sevpat01.CRE 100 5 sevpat01.CRE 114 3 >>>>>>>> COPY + ~PROF_EFF.TBL~ ~battles/tmp.tbl~ COUNT_2DA_ROWS 3 "rows_cnt" FOR( cntg=0; cntg<"%rows_cnt%"; cntg=cntg+1 ) BEGIN READ_2DA_ENTRY cntg 0 3 "table_file_name" READ_2DA_ENTRY cntg 1 3 "prof_type" READ_2DA_ENTRY cntg 2 3 "stars" SET fileExistsInGame = 0 INNER_PATCH_FILE "%table_file_name%" BEGIN PATCH_IF (~%SOURCE_SIZE%~) BEGIN SET fileExistsInGame = 1 END END PATCH_IF fileExistsInGame=1 THEN BEGIN INNER_ACTION BEGIN COPY_EXISTING "%table_file_name%" ~override~ //patching the file from the current table entry READ_LONG 0x2a0 "known_spells_offset" READ_LONG 0x2a4 "known_spells_num" READ_LONG 0x2a8 "spell_memorization_offset" READ_LONG 0x2ac "spell_memorization_num" READ_LONG 0x2b0 "spell_memorized_offset" READ_LONG 0x2b4 "spell_memorized_num" READ_LONG 0x2b8 "item_slots_offset" READ_LONG 0x2bc "items_offset" READ_LONG 0x2c0 "items_num" READ_LONG 0x2c4 "effects_offset" READ_LONG 0x2c8 "effects_num" //**************************************************************************************************** ****** // 1st protection : it's necessary to set a valid offset for "effects_offset" // it could contain some invalid values PATCH_IF( "%effects_num%"=0 ) BEGIN "effects_offset" = "%spell_memorization_offset%"+"%spell_memorization_num%"*0x10 WRITE_LONG 0x2c4 "%effects_offset%" END //**************************************************************************************************** ****** SET found = 0 FOR( cnt=0; cnt<"%effects_num%"; cnt=cnt+1 ) BEGIN READ_LONG ("%effects_offset%"+cnt*0x108+8) "type" PATCH_IF( "%type%"=233 ) BEGIN READ_LONG ("%effects_offset%"+cnt*0x108+24) "prof_type2" PATCH_IF ("%prof_type2%" = "%prof_type%") BEGIN SET found=1 WRITE_LONG ("%effects_offset%"+cnt*0x108+20) "%stars%" END END END PATCH_IF(found=0) BEGIN SET offset = ("%effects_offset%"+0x108*"%effects_num%") INSERT_BYTES offset 0x108 WRITE_LONG offset+8 233 //Modify proficiences WRITE_LONG offset+12 1 //TargetSelf WRITE_LONG offset+20 "%stars%" WRITE_LONG offset+24 "%prof_type%" WRITE_LONG offset+28 9 //Instant/Permanent After Bonuses WRITE_LONG offset+36 100 //Probability WRITE_LONG 0x2c8 "%effects_num%"+1 SET "info_ext" = 0x108 PATCH_IF ("%known_spells_offset%">="%effects_offset%") BEGIN "known_spells_offset"="%known_spells_offset%"+"%info_ext%" WRITE_LONG 0x2a0 "%known_spells_offset%" END PATCH_IF ("%spell_memorization_offset%">="%effects_offset%") BEGIN "spell_memorization_offset"="%spell_memorization_offset%"+"%info_ext%" WRITE_LONG 0x2a8 "%spell_memorization_offset%" END PATCH_IF ("%item_slots_offset%">="%effects_offset%") BEGIN "item_slots_offset"="%item_slots_offset%"+"%info_ext%" WRITE_LONG 0x2b8 "%item_slots_offset%" END PATCH_IF ("%items_offset%">="%effects_offset%") BEGIN "items_offset"="%items_offset%"+"%info_ext%" WRITE_LONG 0x2bc "%items_offset%" END PATCH_IF ("%spell_memorized_offset%">="%effects_offset%") BEGIN "spell_memorized_offset"="%spell_memorized_offset%"+"%info_ext%" WRITE_LONG 0x2b0 "%spell_memorized_offset%" END END BUT_ONLY_IF_IT_CHANGES END END END Link to comment
CamDawg Posted December 17, 2007 Share Posted December 17, 2007 BG2 uses two different effects structures--the v1 effect which is 0x30 bytes and used in all spells, items and some creatures, and the extended 0x108 effect which is used for eff files and the rest of the creatures. The one byte flag at 0x33 in the creature file can tell you if you're using the old 0x30 effect (value 0) or the extended 0x108 effect (value 1, though I'd guess any non-zero value would work). Link to comment
devSin Posted December 17, 2007 Share Posted December 17, 2007 Except that they're both 0x108-byte effects. I don't want to troll for the difference between the two (they look roughly equivalent, albeit convoluted); I will say that there is no difference from one 0x108-byte effect to the next. Whatever problem you're encountering has nothing to do with the particular effect you're trying to apply. Luckily, Nythrun will come shortly to sort it all out. Link to comment
erebusant Posted December 18, 2007 Author Share Posted December 18, 2007 Except that they're both 0x108-byte effects. I don't want to troll for the difference between the two (they look roughly equivalent, albeit convoluted); I will say that there is no difference from one 0x108-byte effect to the next. Whatever problem you're encountering has nothing to do with the particular effect you're trying to apply. Luckily, Nythrun will come shortly to sort it all out. On another note, can you think of any reason for the same .cre to have the same effect listed 3 times? In this case, SEVPAT01.cre from Improved Battles mod has effects 86-89 listed 3 times each. The 1st time has a value=10, and the 2nd & 3rd times the value=5. Would that be the same as a cumulative 20 if it was only patched in once? Another thing I've noticed in these .cre files with modified effects, why would one modify movement rate for instance with a effect 126 and not target self? Link to comment
devSin Posted December 19, 2007 Share Posted December 19, 2007 Movement rate could be Tutu walking speeds (or anything else). Target generally won't matter in attached effects (0, 1, and 2 should all work the same). RE: cumulative, it depends on the effect (some will stack; others won't). There's nothing wrong with it per se, but I don't see why anybody would purposely do it. In the case of these resistance modifiers, if you're saying they're each repeated thrice (for a total of 12 effects), then the values do accumulate, yes (+20% for each of the four resistance types). At this point, though, I'd seriously question the brand of ass the original modder was smoking when creating these skanky files. Link to comment
Nythrun Posted December 20, 2007 Share Posted December 20, 2007 Luckily, Nythrun will come shortly to sort it all out. Speak of the devil and she...Hey! These really are functionally identical (less the SET_CRE_EFFECT_VARIABLES macro, which being unposted is not really scrutible); the second one's longer mostly because it's looking up the values it ought to add from a table rather than just writing them directly. This: SET fileExistsInGame = 0 INNER_PATCH_FILE "%table_file_name%" BEGIN PATCH_IF (~%SOURCE_SIZE%~) BEGIN SET fileExistsInGame = 1 END END is no good. While it's meant to prevent a failed install due to missing files, it won't work - INNER_PATCH_FILE will happily run on a non-existent file (totally ignoring all patches listed) and INNER_PATCH_FILE is not a COPY, meaning it never sets a SOURCE_SIZE to check - instead, you're piggybacking off of whatever value was last set in a previous copy - in this case, the COPY +. COPY + to create irremovable-by-clicky litter files kind of defeats the purpose of using inlined files, you may better escape the bigg's wrath by using COPY - . It's not impossible those resistance effects are dispellable or have staggered durations (so that the resistance wears off over time). If not you can skip the embedded effects entirely and just use FOR (i= 0x60; i < 0x65; i += 0x01) BEGIN WRITE_BYTE i 0x14 END Link to comment
devSin Posted December 20, 2007 Share Posted December 20, 2007 INNER_PATCH_FILE does a courtesy file_exists check, so the code should only run if the file actually does exist (assuming %table_file_name% is the complete 8.3 filename). The PATCH_IF truly is useless, but it won't ever affect the behavior. I also thought of maybe a generic chunk that they added to everything and only marked the relevant ones permanent, but after more thought, I decided that skanky was still an appropriate adjective. Link to comment
Nythrun Posted December 20, 2007 Share Posted December 20, 2007 It would need to run to set SOURCE_SIZE to zero is what I'm saying OUTER_SPRINT ~item~ ~asdf.foo~ OUTER_PATCH ~blah~ BEGIN INNER_PATCH_FILE ~%item%~ BEGIN PATCH_PRINT ~King Diamond is the Typhoid Mary of COPY +~ END END prints nothing. Won't argue that it's not how I'd do it Link to comment
devSin Posted December 20, 2007 Share Posted December 20, 2007 But the code as written would work regardless (even though the check is pointless, SOURCE_SIZE won't ever be 0, so it will still work iff fileExistsInGame). The code could just as easily been SET meHere = 0 INNER_PATCH_FILE "%variable-o%" BEGIN SET meHere = 1 END The result is identical, but it carries the added benefit of making sense? (If I still don't understand you, it may come from not actually looking at the full code, which I refuse to do.) Link to comment
erebusant Posted December 21, 2007 Author Share Posted December 21, 2007 I'll have to take what you guys have explained, and modify the code a bit to take out the useless parts, and see if I can come up with something that still works. What I was really interested in, was that for patching certain effects the second way of doing it was required, because if I tried doing it the first way, the file would patch, but be completely corrupted when finished, or it would always error out when attempted by not being able to convert the offset to an integer or something. I really think it has to do with the structure of the effect, and attempting to patch the improper offset, where I would be trying to patch offset +24 where in fact it was actually what the effect expected to be ofset +20 instead, or something like that. Link to comment
devSin Posted December 21, 2007 Share Posted December 21, 2007 No, it means that either the offset or count in the file was incorrect (or as Cam states, you've got some old v0 CREs where jumping by 0x108 bytes would quickly fly past the end of the file). Posting the exact error message as well as the code you were using to update would certainly help isolate the problem with the CRE file or the patching code. Link to comment
Recommended Posts
Archived
This topic is now archived and is closed to further replies.