Jump to content

weidu troubles with adding effects to spell


Ardanis

Recommended Posts

DEFINE_PATCH_MACRO pro_spell BEGIN
 READ_LONG 0x64  ab_off
 READ_SHORT 0x68 ab_num
 READ_LONG 0x6a  ef_off
 FOR (i=0;i<ab_num;i+=1) BEGIN
READ_SHORT (ab_off+i*0x28+0x1e) ef_num
READ_SHORT (ab_off+i*0x28+0x20) ef_ind
WRITE_SHORT (ab_off+i*0x28+0x1e) ef_num + 1
WRITE_SHORT (ab_off+i*0x28+0x20) ef_off + i
SET off=(ef_off+(ef_ind+i)*0x30)

READ_LONG (off+0xe) time // i know, might occasionally read the effect with zero duration, but that's another matter
READ_BYTE (off+0x3) power

INSERT_BYTES off 0x30
WRITE_SHORT off 206 // opcode
WRITE_BYTE (off+0x2) 1 // target
WRITE_BYTE (off+0x3) power
WRITE_LONG (off+0xe) time
WRITE_EVALUATED_ASCII (off+0x14) ~%spell%~
 END
END

BEGIN ~globe~
COPY_EXISTING ~spwi406.spl~ ~override~ // yes, AI won't like me for that, but i disagree
 SPRINT spell ~spwi326~
 LAUNCH_PATCH_MACRO pro_spell

Works fine. However when I try to patch it with the 2nd resource

SPRINT spell ~another.spl~
 LAUNCH_PATCH_MACRO pro_spell

I get the

[./override/spwi406.spl] loaded, 16130 bytes

ERROR: illegal 4-byte read from offset 33040 of 16130-byte file spwi406.spl

ERROR: [spwi406.spl] -> [override] Patching Failed (COPY) (Failure("spwi406.spl: read out of bounds"))

The problem seems to be the SET off=(ef_off+(ef_ind+i)*0x30) line. Could someone point out the right direction? Did I forget to WRITE something else when shifting effects? I feel I wrote them all but who knows.
Link to comment

DEFINE_PATCH_MACRO pro_spell BEGIN
 READ_LONG 0x64  ab_off
 READ_SHORT 0x68 ab_num
 READ_LONG 0x6a  ef_off
 FOR (i=0;i<ab_num;i+=1) BEGIN
READ_SHORT (ab_off+i*0x28+0x1e) ef_num
READ_SHORT (ab_off+i*0x28+0x20) ef_ind

FOR (k=0;k<ef_num;k+=1) BEGIN // we can't know exact values to write in our new effect, so we have
							  // to find a good example within an ability and clone it's properties
SET check=0
  READ_SHORT (ef_off+(k+ef_ind)*0x30) guide_op
  PATCH_IF ((check = 0) AND (guide_op = 204)) BEGIN // 'immunity to spell school' is a good example
	SET check=1
	SET gu_eff=(ef_off+(k+ef_ind)*0x30) // effect-guide? hmm...
	READ_BYTE (gu_eff+0x2)  target
	READ_BYTE (gu_eff+0x3)  power
	READ_BYTE (gu_eff+0xd)  dispel
	READ_LONG (gu_eff+0xe)  duration // the only part required actually, but let's it be more universal
	READ_BYTE (gu_eff+0x12) prob1 // which one of...
	READ_BYTE (gu_eff+0x13) prob2 // ...these is 100%?
  END // other stuff - saving throws, dice, etc. - aren't needed for our particular case (they're zero)
END

SET off=(ef_off+(ef_ind+i)*0x30)

INSERT_BYTES off	   0x30
WRITE_SHORT  off	   206	   // 'protection from spell'
WRITE_BYTE  (off+0x2)  target
WRITE_BYTE  (off+0x3)  power
WRITE_BYTE  (off+0xd)  dispel
WRITE_LONG  (off+0xe)  duration
WRITE_BYTE  (off+0x12) prob1
WRITE_BYTE  (off+0x13) prob2
WRITE_EVALUATED_ASCII (off+0x14) ~%spell%~

WRITE_SHORT (ab_off+i*0x28+0x1e) ef_num + 1 // shifting
WRITE_SHORT (ab_off+i*0x28+0x20) ef_ind + i // shifting
 END
END

Now it's very confusing. I've modified the macro a bit, used it onto globes to 100% success then decided to fix Spell Immuties as well. Each of them has 12 ability headers and while the first 6 are patched correctly, the latter six's values lag behind by one - 7th added effect uses values read from 6th 'example', 8th - from 7th, etc., be it duration or something else (I intentionally changed 'target' of the 6th and voila - it popped up not only in new 6th but in 7th as well).

More than that, it happened to Evoc, Necr, Alt and Conj immunities, while Abj was absolutely fine.

 

I'm really out of guesses.

Link to comment

You may want to think about your logics again.

 

Why is there a check variable? It's set inside the inner for loop and checked immediately afterwards. (Maybe you wanted to set it outside of the for loop?)

 

And in this line

READ_SHORT (ef_off+(k+ef_ind)*0x30) guide_op

you are not taking into account, that you might have added an effect on the previous ability, so it should read

READ_SHORT (ef_off+(k+ef_ind+i)*0x30) guide_op

instead.

Same for the SET gu_eff line.

 

By the way, your code is based on the assertion that every ability has at least one effect with opcode #204.

Link to comment
you are not taking into account, that you might have added an effect on the previous ability
Are you sure? I did indeed make a similar mistake when wrote the very first variant - forgot to add '+i' into SET off=(ef_off+(ef_ind+i)*0x30). But I believe it's already attended by

  FOR (i=0;i<ab_num;i+=1) BEGIN
READ_SHORT (ab_off+i*0x28+0x1e) ef_num
READ_SHORT (ab_off+i*0x28+0x20) ef_ind
...
WRITE_SHORT (ab_off+i*0x28+0x1e) ef_num + 1 // shifting
WRITE_SHORT (ab_off+i*0x28+0x20) ef_ind + i // shifting
 END

 

Why is there a check variable? It's set inside the inner for loop and checked immediately afterwards. (Maybe you wanted to set it outside of the for loop?)
By the way, your code is based on the assertion that every ability has at least one effect with opcode #204.
Indeed, thanks for pointing out. Sadly it doesn't shed more light, still only the first six affected abilities are patched the way they should be (tried to remove 204 from one, now it's skipped, 6 others are updated, starting at 8th they begin to lag). Weird.
Link to comment
you are not taking into account, that you might have added an effect on the previous ability
Are you sure? I did indeed make a similar mistake when wrote the very first variant - forgot to add '+i' into SET off=(ef_off+(ef_ind+i)*0x30). But I believe it's already attended by

  FOR (i=0;i<ab_num;i+=1) BEGIN
READ_SHORT (ab_off+i*0x28+0x1e) ef_num
READ_SHORT (ab_off+i*0x28+0x20) ef_ind
...
WRITE_SHORT (ab_off+i*0x28+0x1e) ef_num + 1 // shifting
WRITE_SHORT (ab_off+i*0x28+0x20) ef_ind + i // shifting
 END

Partly. You are only updating the ef_ind of the current ability.

But after you added at least one effect, the ef_ind the following abilities are refering to is not correct anymore. That's why I suggested adding that "+i" to the two lines. (Where you read guide_op and the SET gu_eff line.)

Again, that's all based on the assumption, that you add exactly one effect per ability, and I'm not sure if this holds true in your case.

 

By the way, there is an ADD_SPELL_EFFECT macro shipped with WeiDU.

Link to comment

I know of ADD_SPELL_EFFECT but I thought doesn't allow to keep newly added effects in pace with already present ones. Unless there're more of syntax I'm unaware of.

 

Well, it indeed was missing '+i', the very same oversight I did when outlining macro for the first time.

In this particular case the assumption 'one eff for each abil' holds true, lest the spell is bugged on its own, meaning it couldn't be harmed anymore than it already would be, although more versatility certainly wouldn't hurt.

 

Thanks for help.

 

DEFINE_PATCH_MACRO pro_spell BEGIN
 READ_LONG 0x64  ab_off
 READ_SHORT 0x68 ab_num
 READ_LONG 0x6a  ef_off

 SET new=0

 FOR (i=0;i<ab_num;i+=1) BEGIN
READ_SHORT (ab_off+i*0x28+0x1e) ef_num
READ_SHORT (ab_off+i*0x28+0x20) ef_ind

SET check=0

FOR (k=0;k<ef_num;k+=1) BEGIN
  READ_SHORT (ef_off+(k+ef_ind+new)*0x30)
  PATCH_IF ((check = 0) AND (guide_op = checker)) BEGIN
	SET check=1
	SET gu_eff=(ef_off+(k+ef_ind+new)*0x30)
	READ_BYTE (gu_eff+0x2)
	READ_BYTE (gu_eff+0x3)
	READ_BYTE (gu_eff+0xd)
	READ_LONG (gu_eff+0xe)  duration
	READ_BYTE (gu_eff+0x12) prob1
	READ_BYTE (gu_eff+0x13) prob2
  END
END

PATCH_IF (check=1) BEGIN

  SET off=(ef_off+(ef_ind+new)*0x30)

  INSERT_BYTES off	   0x30
  WRITE_SHORT  off	   206	   // 'protection from spell'
  WRITE_BYTE  (off+0x2)  target
  WRITE_BYTE  (off+0x3)  power
  WRITE_BYTE  (off+0xd)  dispel
  WRITE_LONG  (off+0xe)  duration
  WRITE_BYTE  (off+0x12) prob1
  WRITE_BYTE  (off+0x13) prob2
  WRITE_EVALUATED_ASCII (off+0x14) ~%resource%~

  WRITE_SHORT (ab_off+i*0x28+0x1e) ef_num + 1 // shifting
  WRITE_SHORT (ab_off+i*0x28+0x20) ef_ind + new // shifting

  SET new+=1

END

 END
END

 

In case someone would want to use it, set 'checker' and 'resource' to whatever you need and that's all.

 

SET checker=xxx // desired opcode's number

SPRINT resource ~name~ // spell's filename

Link to comment

Archived

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

×
×
  • Create New...