Jump to content

WeiDU question


Galactygon

Recommended Posts

I have tried to adjust the eff_off of the remaining extension headers by incrementing it by 1 (the three lines with the arrows), but still no avail.

 

COPY_EXISTING ~SPPR707.spl~ ~override~
LAUNCH_PATCH_MACRO ~reindex_spell_or_item_extra_effects~
READ_LONG  0x64 ext_off
READ_SHORT 0x68 ext_num
READ_LONG  0x6a fb_off
FOR (outerloops = 0; outerloops < ext_num; outerloops += 1) BEGIN
	READ_SHORT ( outerloops * 0x28 + ext_off + 0x1e ) eff_num
	READ_SHORT ( outerloops * 0x28 + ext_off + 0x20 ) eff_off
	WRITE_SHORT	( outerloops * 0x28 + ext_off + 0x1e ) (eff_num + 1)
	FOR (innerloops = outerloops; innerloops < ext_num; innerloops += 1) BEGIN // <----------
		WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (eff_off + 1) // <----------
	END // <----------
	PATCH_PRINT ~Effect offset: %eff_off%~
	INSERT_BYTES   ("%eff_off%" + ("%eff_num%" * 0x30))	0x30
END
BUT_ONLY_IF_IT_CHANGES

 

-Galactygon

Link to comment

		READ_SHORT ( outerloops * 0x28 + ext_off + 0x20 ) eff_off

This is an index (like an array index) not a file offset.

So you can't use it like that:

		INSERT_BYTES   ("%eff_off%" + ("%eff_num%" * 0x30))	0x30

Try this instead:

		INSERT_BYTES   (fb_off + ((eff_off + eff_num) * 0x30))	0x30

 

And when readjusting the eff indices, you need to read the old index, decide whether it is after the currently inserted one and increment the old value.

 

		FOR (innerloops = 0; innerloops < ext_num; innerloops += 1) BEGIN
		READ_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) old_eff_off
		PATCH_IF (old_eff_off > eff_off) THEN BEGIN
			WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (old_eff_off + 1)
		END
	END

(Untested, but I hope you get the idea.)

 

Besides, why not use Gort's (fixed) macros?

Link to comment

Now it works like a charm. :)

COPY_EXISTING ~SPPR707.spl~ ~override~
LAUNCH_PATCH_MACRO ~reindex_spell_or_item_extra_effects~
READ_LONG  0x64 ext_off
READ_SHORT 0x68 ext_num
READ_LONG  0x6a fb_off
FOR (outerloops = 0; outerloops < ext_num; outerloops += 1) BEGIN
	READ_SHORT ( outerloops * 0x28 + ext_off + 0x1e ) eff_num
	READ_SHORT ( outerloops * 0x28 + ext_off + 0x20 ) eff_off
	WRITE_SHORT	( outerloops * 0x28 + ext_off + 0x1e ) (eff_num + 1)
	FOR (innerloops = 0; innerloops < ext_num; innerloops += 1) BEGIN
		READ_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) old_eff_off
		PATCH_IF ( old_eff_off > eff_off ) BEGIN
			WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (old_eff_off + 1)
		END
	END
	INSERT_BYTES   ("%fb_off%" + ("%eff_off%" + "%eff_num%") * 0x30)	0x30
END
BUT_ONLY_IF_IT_CHANGES

 

Try this instead:

		INSERT_BYTES   (fb_off + ((eff_off + eff_num) * 0x30))	0x30

 

So I cannot neglect the casting feature block. Makes sense. But why is it (eff_off + eff_num) * 0x30 rather than eff_off + eff_num * 0x30 ? Is the effect offset included in the effect number or something?

 

And when readjusting the eff indices, you need to read the old index, decide whether it is after the currently inserted one and increment the old value.

 

		FOR (innerloops = 0; innerloops < ext_num; innerloops += 1) BEGIN
		READ_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) old_eff_off
		PATCH_IF (old_eff_off > eff_off) THEN BEGIN
			WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (old_eff_off + 1)
		END
	END

 

So I have to increment all of the extended headers by one rather than the ones after the header which includes the new eff?

 

Besides, why not use Gort's (fixed) macros?

 

Now that I am more or less starting to see the light at the end of all this code, I would rather do it myself. It hurts more, but I'll get more out of it.

 

-Galactygon

Link to comment
So I cannot neglect the casting feature block. Makes sense. But why is it (eff_off + eff_num) * 0x30 rather than eff_off + eff_num * 0x30 ? Is the effect offset included in the effect number or something?

Because eff_off (eff_idx would be a better name) only tells you, on which feature block the effects for this extended header start. If you think in terms of lists, eff_off is the index of the head of the list and eff_num the length.

So I have to increment all of the extended headers by one rather than the ones after the header which includes the new eff?

Well, you could get away with only checking the ones after the current header, but the file format allows strange things like, the first ext. header pointing to feature block 6 and the second one to number 3. (I think the game executable on Mac chokes on this, so it should not be like that, but better safe than sorry.)

The important thing is to check the "old_eff_off" and increment only if necessary.

Link to comment
Because eff_off (eff_idx would be a better name) only tells you, on which feature block the effects for this extended header start. If you think in terms of lists, eff_off is the index of the head of the list and eff_num the length.

 

I think I am starting to see it. I will get back to this.

 

Well, you could get away with only checking the ones after the current header, but the file format allows strange things like, the first ext. header pointing to feature block 6 and the second one to number 3. (I think the game executable on Mac chokes on this, so it should not be like that, but better safe than sorry.)

 

That's just wierd. I hope GemRB fixes this.

 

The important thing is to check the "old_eff_off" and increment only if necessary.

 

"Increment only if necessary". What's more than necessary?

 

...

 

Now I added some stuff to the code. It patches alright, except the first extension header, where the values are messed up. I am guessing it has to do with %eff_off% being set to some wrong value when it first starts looping.

 

COPY_EXISTING ~SPPR707.spl~ ~override~
LAUNCH_PATCH_MACRO ~reindex_spell_or_item_extra_effects~
READ_LONG  0x64 ext_off
READ_SHORT 0x68 ext_num
READ_LONG  0x6a fb_off
FOR (outerloops = 0; outerloops < ext_num; outerloops += 1) BEGIN
	FOR (patchloops = 0; patchloops < 2; patchloops += 1) BEGIN
		READ_SHORT ( outerloops * 0x28 + ext_off + 0x1e ) eff_num
		READ_SHORT ( outerloops * 0x28 + ext_off + 0x20 ) eff_off
		WRITE_SHORT	( outerloops * 0x28 + ext_off + 0x1e ) (eff_num + 1)
		FOR (innerloops = 0; innerloops < ext_num; innerloops += 1) BEGIN
			READ_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) old_eff_off
			PATCH_IF ( old_eff_off > eff_off ) BEGIN
				WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (old_eff_off + 1)
			END
		END
		INSERT_BYTES   ("%fb_off%" + ("%eff_off%" + "%eff_num%") * 0x30)	0x30
	 		WRITE_SHORT  ("%fb_off%" +		("%eff_off%" + "%eff_num%") * 0x30) 177	// Opcode
	 		WRITE_BYTE   ("%fb_off%" + 0x03 + ("%eff_off%" + "%eff_num%") * 0x30) 7		// Power
	 		WRITE_LONG   ("%fb_off%" + 0x08 + ("%eff_off%" + "%eff_num%") * 0x30) 3		// [Param 2]
	 		WRITE_BYTE   ("%fb_off%" + 0x0c + ("%eff_off%" + "%eff_num%") * 0x30) 1		// Duration Instant
	 		WRITE_BYTE   ("%fb_off%" + 0x0d + ("%eff_off%" + "%eff_num%") * 0x30)  3	// Resisttype [Dispel/Bypass Resistance]
	 		WRITE_BYTE   ("%fb_off%" + 0x12 + ("%eff_off%" + "%eff_num%") * 0x30) 100	  // probability 100
	 		WRITE_LONG   ("%fb_off%" + 0x02 + ("%eff_off%" + "%eff_num%" * 0x30)) 2		// Targettype [Pre-Target]
	 		WRITE_LONG   ("%fb_off%" + 0x04 + ("%eff_off%" + "%eff_num%") * 0x30) 0		// [Param 1]
		PATCH_IF ("%patchloops%" = 0) BEGIN
			WRITE_ASCII   ("%fb_off%" + 0x14 + ("%eff_off%" + "%eff_num%") * 0x30) ~SPPR720Y~
		END ELSE
		PATCH_IF ("%patchloops%" = 1) BEGIN
			WRITE_ASCII   ("%fb_off%" + 0x14 + ("%eff_off%" + "%eff_num%") * 0x30) ~SPPR7201~
		END
	END
END
BUT_ONLY_IF_IT_CHANGES

 

-Galactygon

Link to comment
"Increment only if necessary". What's more than necessary?

Huh? Sorry, didn't get this.

 

Now I added some stuff to the code. It patches alright, except the first extension header, where the values are messed up. I am guessing it has to do with %eff_off% being set to some wrong value when it first starts looping.

Which value is messed up?

And you are overwriting your power level with a WRITE_LONG further down. (should be WRITE BYTE instead)

 

COPY_EXISTING ~SPPR707.spl~ ~override~
LAUNCH_PATCH_MACRO ~reindex_spell_or_item_extra_effects~
READ_LONG  0x64 ext_off
READ_SHORT 0x68 ext_num
READ_LONG  0x6a fb_off
FOR (outerloops = 0; outerloops < ext_num; outerloops += 1) BEGIN
	FOR (patchloops = 0; patchloops < 2; patchloops += 1) BEGIN
		READ_SHORT ( outerloops * 0x28 + ext_off + 0x1e ) eff_num
		READ_SHORT ( outerloops * 0x28 + ext_off + 0x20 ) eff_idx
		WRITE_SHORT	( outerloops * 0x28 + ext_off + 0x1e ) (eff_num + 1)
		FOR (innerloops = 0; innerloops < ext_num; innerloops += 1) BEGIN
			READ_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) old_eff_idx
			PATCH_IF ( old_eff_idx > eff_idx ) BEGIN
				WRITE_SHORT ( innerloops * 0x28 + ext_off + 0x20 ) (old_eff_idx + 1)
			END
		END
		SET new_eff_off = fb_off + (eff_idx + eff_num) * 0x30
		INSERT_BYTES	 new_eff_off   0x30
		WRITE_SHORT	 (new_eff_off + 0x00) 177	// Opcode
		WRITE_BYTE	  (new_eff_off + 0x02) 2	  // Targettype [Pre-Target]
		WRITE_BYTE	  (new_eff_off + 0x03) 7	  // Power
		WRITE_LONG	  (new_eff_off + 0x04) 0	  // [Param 1]
		WRITE_LONG	  (new_eff_off + 0x08) 3	  // [Param 2]
		WRITE_BYTE	  (new_eff_off + 0x0c) 1	  // Duration Instant
		WRITE_BYTE	  (new_eff_off + 0x0d) 3	  // Resisttype [Dispel/Bypass Resistance]
		WRITE_BYTE	  (new_eff_off + 0x12) 100	// probability 100
		PATCH_IF (patchloops = 0) BEGIN
			WRITE_ASCII (new_eff_off + 0x14) ~SPPR720Y~
		END ELSE
		PATCH_IF (patchloops = 1) BEGIN
			WRITE_ASCII (new_eff_off + 0x14) ~SPPR7201~
		END
	END
END
BUT_ONLY_IF_IT_CHANGES

(I renamed some variables and reordered the WRITEs a bit. Again untested.)

Link to comment

Typo again.

 

This

WRITE_LONG   ("%fb_off%" + 0x02 + ("%eff_off%" + "%eff_num%" * 0x30)) 2 // Set targettype to [2] Pre-Target

 

should have been this.

WRITE_LONG   ("%fb_off%" + 0x02 + ("%eff_off%" + "%eff_num%") * 0x30) 2 // Set targettype to [2] Pre-Target

 

Now it works. Power, by the way is WRITE_BYTE in my code. Setting a variable makes it easier and less prone to them sleight of keys.

 

-Galactygon

Link to comment

I am having a little trouble with both

 

PATCH_PRINT ~$spellcount("%a%" "%b%")~
SPRINT resource $spellcount("%a%" "%b%")

PATCH_PRINT keeps on printing $spellcount("%a%" "%b%"), and SPRINT does not SPRINT the row and column as I would like, but instead returns funny values like "%SPELL_F" or "SPELLCOU".

 

[edit] Here is the rest of code. It might be that I haven't properly set up the array, as I haven't worked with them in WeiDU before.

COPY_EXISTING ~LCIMMSPL.2da~ ~override~
COUNT_2DA_COLS immune_column_count
COUNT_2DA_ROWS 0 immune_row_count
FOR ( a=0; a<immune_column_count; a+=1 ) BEGIN
	FOR ( b=0; b<immune_row_count; b+=1 ) BEGIN
		READ_2DA_ENTRY b a 0 "%spell_file%"
		SPRINT $spellcount("%a%" "%b%") "%spell_file%"
		PATCH_PRINT ~$spellcount("%a%" "%b%")~
	END
END

 

 

-Galactygon

Link to comment
PRINT currently doesn't evaluate the dollar array syntax.
Yeah, I found that out the hard way too :fish:. Would it be difficult to add?

 

I'm not sure if you (Galactygon) need an EVALUATE_BUFFER or an operator in there (^ or +) for the variables within the parentheses. What are %a% and %b% supposed to evaluate to?

Link to comment
Would it be difficult to add?

It's at least more than a line.

But you can always first SPRINT the value to a temp variable and then PRINT this variable.

 

I'm not sure if you (Galactygon) need an EVALUATE_BUFFER or an operator in there (^ or +) for the variables within the parentheses.

No, they already get evaluated.

Link to comment
I'm not sure if you (Galactygon) need an EVALUATE_BUFFER or an operator in there (^ or +) for the variables within the parentheses. What are %a% and %b% supposed to evaluate to?

 

They are supposed to dummy variables that get incremented in my FOR loops.

 

Here, I will post my entire code. As I found out, PATCH_PRINT prints %spell_file% rather than the .2da entry %spell_file% is supposed to represent:

READ_2DA_ENTRY b a 0 "%spell_file%"
SPRINT $spellcount("%b%" "%a%") ~%spell_file%~
SPRINT resource $spellcount("%b%" "%a%")
PATCH_PRINT ~%resource%~

Here is the rest of the code:

COPY_EXISTING ~LCIMMSPL.2da~ ~override~
COUNT_2DA_COLS immune_column_count
COUNT_2DA_ROWS 0 immune_row_count
FOR ( a=0; a<immune_column_count; a+=1 ) BEGIN
	FOR ( b=0; b<immune_row_count; b+=1 ) BEGIN
		READ_2DA_ENTRY b a 0 "%spell_file%"
		SPRINT $spellcount("%b%" "%a%") ~%spell_file%~
		SPRINT resource $spellcount("%b%" "%a%")
		PATCH_PRINT ~%resource%~
	END
END

 

-Galactygon

Link to comment

READ_2DA_ENTRY b a 0 "%spell_file%"

This can cause problems after the first run through the loops.

WeiDU will read the entry to a variable named after the contents of spell_file. (i. e. use READ_2DA_ENTRY b a 0 spell_file [or "spell_file"] instead)

Link to comment

Archived

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

×
×
  • Create New...