Jump to content

CRE Effect Patching


erebusant

Recommended Posts

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

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

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
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. :help:

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

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
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

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

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

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

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

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...