Jump to content


Photo

a question to weidu guru


  • Please log in to reply
31 replies to this topic

#1 Gort

Gort
  • Validating
  • 614 posts

Posted 10 June 2007 - 01:53 AM

I want to make all copies of a certain item unstealable and undroppable, except 1. So, I mark all of them unst/undr, then restore flags in 1 case. But somehow restoring does not work right, depending on unrelated piece of code. See:

[codebox]
COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN // protects against invalid files
READ_LONG 0x2bc "itm_off"
READ_LONG 0x2c0 "itm_num"
WHILE ("%itm_num%" > 0) BEGIN
SET "itm_num" = ("%itm_num%" - 1)
READ_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "item"
PATCH_IF ("%item%" STRING_MATCHES_REGEXP "ring07" = 0) BEGIN
READ_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) "flags"
WRITE_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) ("%flags%" BOR 0b00001010) // adds unstealable, undroppable flags
END
END
END
BUT_ONLY_IF_IT_CHANGES

//Ring of Protection +2 ring07 //aran linvail ARAN02 (side with Bodhi); ARAN.DLG - when siding with thieves he create it in dialog
COPY_EXISTING ~ARAN02.CRE~ ~override/ARAN02.CRE~
PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN
READ_LONG 0x2bc "itm_off"
READ_LONG 0x2c0 "itm_num"
WHILE ("%itm_num%" > 0) BEGIN
SET "itm_num" = ("%itm_num%" - 1)
READ_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "item"
PATCH_IF ("%item%" STRING_COMPARE_CASE "ring07" = 0) BEGIN
READ_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) "flags"
WRITE_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) ("%flags%" BAND 0b11110101) // adds stealable&droppable flag
SET "itm_num" = 0
END
END
END
BUT_ONLY_IF_IT_CHANGES
[/codebox]

it works just fine. Ring07 at aran02.cre is stealable and droppable.

But if I add absolutely unrelated piece of code about varscona BEFORE:
[codebox]
COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN // protects against invalid files
READ_LONG 0x2bc "itm_off"
READ_LONG 0x2c0 "itm_num"
WHILE ("%itm_num%" > 0) BEGIN
SET "itm_num" = ("%itm_num%" - 1)
READ_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "item"
PATCH_IF ("%item%" STRING_MATCHES_REGEXP "ring07" = 0) BEGIN
READ_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) "flags"
WRITE_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) ("%flags%" BOR 0b00001010) // adds unstealable, undroppable flags
END
END
END
BUT_ONLY_IF_IT_CHANGES

//Long Sword +2: 'Varscona' sw1h06 - left at Kachiko c6kach2.cre (a thief to help with bodhi) GREYWO - creywolf from bg1
COPY_EXISTING ~c6kach2.cre~ ~override/c6kach2.cre~
PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN
READ_LONG 0x2bc "itm_off"
READ_LONG 0x2c0 "itm_num"
WHILE ("%itm_num%" > 0) BEGIN
SET "itm_num" = ("%itm_num%" - 1)
READ_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "item"
PATCH_IF ("%item%" STRING_COMPARE_CASE "sw1h41" = 0) BEGIN
WRITE_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "sw1h06" //restore
SET "%itm_num%" = 0
END
END
END
BUT_ONLY_IF_IT_CHANGES

//Ring of Protection +2 ring07 //aran linvail ARAN02 (side with Bodhi); ARAN.DLG - when siding with thieves he create it in dialog
COPY_EXISTING ~ARAN02.CRE~ ~override/ARAN02.CRE~
PATCH_IF (SOURCE_SIZE > 0x2d3) BEGIN
READ_LONG 0x2bc "itm_off"
READ_LONG 0x2c0 "itm_num"
WHILE ("%itm_num%" > 0) BEGIN
SET "itm_num" = ("%itm_num%" - 1)
READ_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "item"
PATCH_IF ("%item%" STRING_COMPARE_CASE "ring07" = 0) BEGIN
READ_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) "flags"
WRITE_BYTE ("%itm_off%" + 0x10 + (0x14 * "%itm_num%")) ("%flags%" BAND 0b11110101) // adds stealable&droppable flag
SET "itm_num" = 0
END
END
END
BUT_ONLY_IF_IT_CHANGES
[/codebox]

then ring07 at aran02.cre remains unstealable and undroppable. I'm confused.

Edited by Gort, 10 June 2007 - 02:17 AM.


#2 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 10 June 2007 - 02:14 AM

What happens if you switch the sword and ring blocks, so that the block that patches Aran is before the one about Varscona?

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#3 Gort

Gort
  • Validating
  • 614 posts

Posted 10 June 2007 - 02:19 AM

- then it works as supposed. Ring07 is stealable and droppable.

#4 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 10 June 2007 - 02:24 AM

And does the Varscona code work as intended, too?

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#5 Gort

Gort
  • Validating
  • 614 posts

Posted 10 June 2007 - 02:29 AM

yes, it does (in both cases). Actually, it does nothing here, because there is no sw1h41 at c6kach2.cre, there is sw1h06 from the beginning.

Edited by Gort, 10 June 2007 - 02:38 AM.


#6 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 10 June 2007 - 02:43 AM

Then if you have code that works, are you satisfied with that, or do you want an explanation to why it didn't work before?

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#7 Gort

Gort
  • Validating
  • 614 posts

Posted 10 June 2007 - 02:57 AM

it does not work. In my mod there is a block about varscona. I just tried to explain the problem better, so I put the second variant after. In my mod I patch lots of creatures, and remove lots of items. The ones after varscona block are not patched correctly. You can say "put it in the very end", but it's not a decision, varscona block may be not the only one that screwes the installation. And I can't check all creatures to verify if they are patched correctly.

#8 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 10 June 2007 - 03:56 AM

Ah, I see. To make things easier for the people trying to help you, you could have said so in the beginning. :)

The only thing I can see when looking at the code at a glance is that you have this:

PATCH_IF ("%item%" STRING_COMPARE_CASE "sw1h41" = 0) BEGIN
	  WRITE_ASCII ("%itm_off%" + (0x14 * "%itm_num%")) "sw1h06" //restore
	  SET "%itm_num%" = 0
	END
Try SET "itm_num" = 0 instead, without the %-symbols. That might mess up the itm_num variable for all following codeblocks (although I'm not entirely sure how WeiDU handles variables in this sense).

(Although you don't need that assignment anyway.)

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#9 Gort

Gort
  • Validating
  • 614 posts

Posted 10 June 2007 - 04:31 AM

omg, how could I be so blind! Thanks a lot, it did the trick!
(this line should terminate the cycle, it quickens the installation. And, I need only one copy of an item to be restored, in case if a creature possesses several of them)

Edited by Gort, 10 June 2007 - 04:38 AM.


#10 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11148 posts

Posted 10 June 2007 - 07:10 AM

omg, how could I be so blind! Thanks a lot, it did the trick!

You're welcome. :)

(this line should terminate the cycle, it quickens the installation. And, I need only one copy of an item to be restored, in case if a creature possesses several of them)

It does terminate the loop, yes, but I would wager that the amount of time saved is mariginal at best - though I haven't benchmarked it. My main concern was that it skips several occurances of an item, but you seem to have that covered already. :)

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#11 Gort

Gort
  • Validating
  • 614 posts

Posted 12 August 2007 - 07:57 AM

I'm too lazy to make new topic, and the question does not worth it, anyway. Just how I write a terminating null with weidu? I'm asking because I need to right ASCII string that should be both evaluated and terminated.

#12 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 12 August 2007 - 08:23 AM

From the WeiDU docs:

WRITE_ASCII_TERMINATE offset ascString

The ASCII ascString is written to the file starting at offset. If you do not specify a requiredSize, the terminating NUL is written.


* WRITE_ASCIIE is a synonim of WRITE_EVALUATED_ASCII.
* WRITE_ASCIIT is a synonim of WRITE_ASCII_TERMINATE.

Or, if you are asking specifically how to both evaluate the thing and then shut it down at the same time,

WRITE_EVALUATED_ASCII 0x280 ~%DEST_RES%~ #32 // death variable
	WRITE_EVALUATED_ASCII 0x2CC ~%DEST_RES%~ #8 // dialog
with the length required as determined by the IESDP research.

#13 Gort

Gort
  • Validating
  • 614 posts

Posted 12 August 2007 - 08:40 AM

yeah, I've read this. I just want to use a macro, and I don't know the length in advance

#14 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 12 August 2007 - 09:09 AM

As far as I can tell, then, you are going to have to add an inner patch which determines length on the fly, to write the #%myVar% at the end of the WRITE_ASCIIE - stuff way, way out of my league. Better wait for SConrad or the bigg, et al --- or take a quick check over with igi on his site. He does wild things with arrays and patching, including iiItem mod which does stuff I am just now beginning to figure out how to read, let alone use.

Or separate the macro into sections, for example just looking for items (where you can specify the offsets/length) then at the next thing, then at the next, in a series. Nythrun's code often includes cool stuff for this kind of usage.

Edited by cmorgan, 12 August 2007 - 09:11 AM.


#15 Gort

Gort
  • Validating
  • 614 posts

Posted 12 August 2007 - 09:15 AM

thanks, cmorgan, I think I'll just stick with separate macro. I was thinking there is a simple way to add a null, something like
WRITE_ASCII need_offset NULL
.


and one more question: what happens if I assign a regexp to a variable?
I mean, will
SET "x" = "ab\|cd"
STRING_MATCHES_REGEXP ("qwerty_ab" "qwerty_%x%")
catch it?

Edited by Gort, 12 August 2007 - 09:20 AM.


#16 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 12 August 2007 - 10:31 AM

I am not sure - my bet is it is safest *not* to assume it does, but test it and see using a throw-away install or a simple test program.

The big boys and girls really in the weidu game all get frustrated by the oddities of ocaml and weidu backwards compatibility, especially stuff dealing with regexp, case sensitivity, and the bigg did a huge push to repair or find workarounds for this kind of thing on v200, but it is not something I have ever tried myself ( I sit on the sidelines, watch the byplay, and race off to look up the words and stuff they use to figure out what they are saying.)

What I can tell you is that I can't remember seeing that usage in an existing mod; if you happen across it, or if you test it, please let me know what worked/syntax so I can learn from you!

#17 Gort

Gort
  • Validating
  • 614 posts

Posted 12 August 2007 - 10:40 AM

I can check it easily, but if it is hasn't stable behavior from version to version, there's no point in usage, anyway.

#18 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 12 August 2007 - 12:34 PM

* STRING_MATCHES_REGEXP (= STRING_COMPARE_REGEXP) and
STRING_CONTAINS_REGEXP added.
in v184 -

I think it would be worth a test run. (I can't volunteer, though - my plate is overflowing).

#19 Gort

Gort
  • Validating
  • 614 posts

Posted 12 August 2007 - 05:20 PM

yes it does.


I should probably rename this topic into "Gort's list of stupid questions"). Now I'm stuck with regexp. I have variable with regexp:
SPRINT ~x~ ~ab\|cd~ and I need to get string ~qwerty_"ab"\|qwerty_"cd"~. Using ~qwerty_"%x%"~ results in ~qwerty_"ab\|qwerty_"cd"~. Is it possible to do what I want? (I don't want to use SPRINT ~x~ ~ab"\|cd"~, because my variant is actually more complicated, and it just lacks any elegancy)

Edited by Gort, 13 August 2007 - 02:25 AM.


#20 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 13 August 2007 - 06:39 AM

You are losing me, but I will give it a try and hopefully the big boys and girls will show up soon to get it going -

My bet would be that in order to make use of that regexp, you are going to have to evaluate for individual case and create each one. For a rough example,

OUTER_SPRINT "myVariableA" "%weapontype%"
SET_STRING ~My, what a big %myVariableA% you have there ~
requires that you create a loop that evaluates for .itm files, then matches against all known weapons in the game, then builds the darned individual variable you want. Nythrun's stuff on L1NPCs goes to thousands of lines of code to do this, as she literally reads everything in all relevant .cres, then rebuilds .cres and the correct .itm, etc. assignments (and spell tables - everything) on the fly to give the player control over everything from proficiencies and class/multiclass to race and carried items. Her mod is offline right now for some reason, so the next person in line who may already have figured out how to do what you want to do is igi.

You really, really want to go see igi, I think. He does good stuff with arrays, which is what I *think* you want here.

Alternatively (and with apologies if this is not cool, but I figure it is available for download so why not), I did find code using S_C_R:

in BG2 Fixpack v3
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
/////												  \\\\\
///// Two-Handed Bastard Swords						\\\\\
/////												  \\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\
/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\/////\\\\\

BEGIN @202000 DESIGNATED 2020
GROUP @9

//add ability and effect
COPY_EXISTING ~sw1h01.itm~ ~override/sw1h01ik.itm~ // 1h zero-lore clones
			  ~sw1h02.itm~ ~override/sw1h02ik.itm~
			  ~sw1h03.itm~ ~override/sw1h03ik.itm~
			  ~sw1h18.itm~ ~override/sw1h18ik.itm~
			  ~sw1h34.itm~ ~override/sw1h34ik.itm~
			  ~sw1h37.itm~ ~override/sw1h37ik.itm~
			  ~sw1h38.itm~ ~override/sw1h38ik.itm~
			  ~sw1h39.itm~ ~override/sw1h39ik.itm~
			  ~sw1h42.itm~ ~override/sw1h42ik.itm~
			  ~sw1h62.itm~ ~override/sw1h62ik.itm~
			  ~sw1h63.itm~ ~override/sw1h63ik.itm~
			  ~sw1h64.itm~ ~override/sw1h64ik.itm~
			  ~sw1h65.itm~ ~override/sw1h65ik.itm~
			  ~sw1h72.itm~ ~override/sw1h72ik.itm~
			  ~sw1h01.itm~ ~override/iksw1h01.itm~ // 2h zero-lore clones
			  ~sw1h02.itm~ ~override/iksw1h02.itm~
			  ~sw1h03.itm~ ~override/iksw1h03.itm~
			  ~sw1h18.itm~ ~override/iksw1h18.itm~
			  ~sw1h34.itm~ ~override/iksw1h34.itm~
			  ~sw1h37.itm~ ~override/iksw1h37.itm~
			  ~sw1h38.itm~ ~override/iksw1h38.itm~
			  ~sw1h39.itm~ ~override/iksw1h39.itm~
			  ~sw1h42.itm~ ~override/iksw1h42.itm~
			  ~sw1h62.itm~ ~override/iksw1h62.itm~
			  ~sw1h63.itm~ ~override/iksw1h63.itm~
			  ~sw1h64.itm~ ~override/iksw1h64.itm~
			  ~sw1h65.itm~ ~override/iksw1h65.itm~
			  ~sw1h72.itm~ ~override/iksw1h72.itm~
			  ~sw1h01.itm~ ~override/sw1h01.itm~ // original items
			  ~sw1h02.itm~ ~override/sw1h02.itm~
			  ~sw1h03.itm~ ~override/sw1h03.itm~
			  ~sw1h18.itm~ ~override/sw1h18.itm~
			  ~sw1h34.itm~ ~override/sw1h34.itm~
			  ~sw1h37.itm~ ~override/sw1h37.itm~
			  ~sw1h38.itm~ ~override/sw1h38.itm~
			  ~sw1h39.itm~ ~override/sw1h39.itm~
			  ~sw1h42.itm~ ~override/sw1h42.itm~
			  ~sw1h62.itm~ ~override/sw1h62.itm~
			  ~sw1h63.itm~ ~override/sw1h63.itm~
			  ~sw1h64.itm~ ~override/sw1h64.itm~
			  ~sw1h65.itm~ ~override/sw1h65.itm~
			  ~sw1h72.itm~ ~override/sw1h72.itm~
			  // put tutu items here so they'll overwrite ik.. and ..ik items based on bg2 items
			  ~_sw1h01.itm~ ~override/sw1h01ik.itm~ // 1h zero-lore clone
			  ~_sw1h02.itm~ ~override/sw1h02ik.itm~
			  ~_sw1h03.itm~ ~override/sw1h03ik.itm~
			  ~_sw1h18.itm~ ~override/sw1h18ik.itm~
			  ~_sw1h01.itm~ ~override/iksw1h01.itm~ // 2h zero-lore clone
			  ~_sw1h02.itm~ ~override/iksw1h02.itm~
			  ~_sw1h03.itm~ ~override/iksw1h03.itm~
			  ~_sw1h18.itm~ ~override/iksw1h18.itm~
			  ~_sw1h01.itm~ ~override/_sw1h01.itm~  // original items
			  ~_sw1h02.itm~ ~override/_sw1h02.itm~
			  ~_sw1h03.itm~ ~override/_sw1h03.itm~
		  ~_sw1h18.itm~ ~override/_sw1h18.itm~
  PATCH_IF (SOURCE_SIZE > 0x71) BEGIN // protects against invalid files
	READ_BYTE   0x31 "prof"
	READ_LONG   0x64 "abil_off"
	READ_SHORT  0x68 "abil_num"
	WRITE_SHORT 0x68 ("%abil_num%" + 1)
	READ_LONG   0x6a "fx_off"
	WRITE_LONG  0x6a ("%fx_off%" + 0x38)
	READ_SHORT  0x70 "fx_num"
	READ_SHORT ("%abil_off%" + 0x1e + (("%abil_num%" - 1) * 0x38)) "last_fx_num"
	READ_SHORT ("%abil_off%" + 0x20 + (("%abil_num%" - 1) * 0x38)) "last_fx_idx"
	SET "new_fx" = ("%last_fx_idx%" + "%last_fx_num%")
	PATCH_IF (~%DEST_RES%~ STRING_COMPARE_CASE ~%SOURCE_RES%~ != 0) BEGIN // zero lore for new copies
	  WRITE_SHORT 0x42 0
	END ELSE BEGIN
	// if modifying the originals, set variables for charges
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h01~ = 0) BEGIN
		SET "sw1h01_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h02~ = 0) BEGIN
		SET "sw1h02_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h03~ = 0) BEGIN
		SET "sw1h03_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h18~ = 0) BEGIN
		SET "sw1h18_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h34~ = 0) BEGIN
		SET "sw1h34_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h37~ = 0) BEGIN
		SET "sw1h37_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h38~ = 0) BEGIN
		SET "sw1h38_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h39~ = 0) BEGIN
		SET "sw1h39_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h42~ = 0) BEGIN
		SET "sw1h42_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h62~ = 0) BEGIN
		SET "sw1h62_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h63~ = 0) BEGIN
		SET "sw1h63_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h64~ = 0) BEGIN
		SET "sw1h64_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h65~ = 0) BEGIN
		SET "sw1h65_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~sw1h72~ = 0) BEGIN
		SET "sw1h72_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~_sw1h01~ = 0) BEGIN
		SET "_sw1h01_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~_sw1h02~ = 0) BEGIN
		SET "_sw1h02_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~_sw1h03~ = 0) BEGIN
		SET "_sw1h03_abil_num" = ("%abil_num%" + 1)
	  END ELSE
	  PATCH_IF (~%SOURCE_RES%~ STRING_COMPARE_CASE ~_sw1h18~ = 0) BEGIN
		SET "_sw1h18_abil_num" = ("%abil_num%" + 1)
	  END
	END
	// set variable used in offset patching to help remove _ in resources
	PATCH_IF (~%SOURCE_RES%~ STRING_MATCHES_REGEXP ~_......~ = 0) BEGIN // if tutu source item
	  SET "nontutu" = 0
	END ELSE BEGIN
	  SET "nontutu" = 1
	END
	PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~[iI][kK]......~ = 0) BEGIN // if 2h
	  READ_BYTE   0x18 "flags"
	  WRITE_BYTE  0x18 ("%flags%" BOR 0b00000010) // add two-handed flag
	  WRITE_ASCII 0x22 ~S2~					   // paperdoll animation
	  FOR (loops = 0; loops < abil_num; loops = loops + 1) BEGIN
		READ_SHORT ("%abil_off%" + ("%loops%" * 0x38)) "type"
		PATCH_IF ("%type%" = 1) BEGIN // melee abilities
		  WRITE_SHORT ("%abil_off%" + 0x2c + ("%loops%" * 0x38)) 60 // overhand attacks
		  WRITE_SHORT ("%abil_off%" + 0x2e + ("%loops%" * 0x38)) 40 // slashing attacks
		  WRITE_SHORT ("%abil_off%" + 0x30 + ("%loops%" * 0x38)) 0  // thrusting attacks
		END
	  END
	END
	INSERT_BYTES				("%fx_off%" +		("%new_fx%" * 0x30)) 0x30 // new effect
	  WRITE_SHORT		   ("%fx_off%" +		("%new_fx%" * 0x30)) 122  // create inventory item
	  WRITE_BYTE			("%fx_off%" + 0x02 + ("%new_fx%" * 0x30)) 1	// target: self
	  WRITE_BYTE			("%fx_off%" + 0x0c + ("%new_fx%" * 0x30)) 1	// instant/permanent till death
	  WRITE_BYTE			("%fx_off%" + 0x12 + ("%new_fx%" * 0x30)) 100  // probability
	  PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~[iI][kK]......~ = 0) BEGIN
		WRITE_EVALUATED_ASCII ("%fx_off%" + 0x13 + "%nontutu%" + ("%new_fx%" * 0x30)) ~%SOURCE_RES%ik~ // if 2H version
		WRITE_BYTE			("%fx_off%" + 0x13 +			   ("%new_fx%" * 0x30)) 0 // removes underscore for tutu items
	  END ELSE BEGIN
		WRITE_EVALUATED_ASCII ("%fx_off%" + 0x15 + "%nontutu%" + ("%new_fx%" * 0x30)) ~%SOURCE_RES%~
		WRITE_ASCII		   ("%fx_off%" + 0x14 +			   ("%new_fx%" * 0x30)) ~ik~ // removes _ to boot
	  END
	INSERT_BYTES	  ("%fx_off%"	   ) 0x38		 // new ability
	  WRITE_BYTE  ("%fx_off%"	   ) 3			// magical
	  WRITE_BYTE  ("%fx_off%" + 0x01) 1			// ID to use
	  WRITE_SHORT ("%fx_off%" + 0x02) 3			// in item slots
	  PATCH_IF (~%DEST_RES%~ STRING_MATCHES_REGEXP ~[iI][kK]......~ = 0) BEGIN // if 2H version
		PATCH_IF ("%prof%" = 94) BEGIN // katana
		  WRITE_ASCII ("%fx_off%" + 0x04) ~isw1h43~
		END ELSE BEGIN
		  WRITE_ASCII ("%fx_off%" + 0x04) ~isw1h01~
		END
	  END ELSE BEGIN
		WRITE_ASCII ("%fx_off%" + 0x04) ~isw2h01~   // if 1H version
	  END
	  WRITE_SHORT ("%fx_off%" + 0x0c) 5			// target: caster
	  WRITE_SHORT ("%fx_off%" + 0x0e) 1			// range: 1
	  WRITE_SHORT ("%fx_off%" + 0x1e) 1			// num effects: 1
	  WRITE_SHORT ("%fx_off%" + 0x20) ("%new_fx%") // fx index
	  WRITE_SHORT ("%fx_off%" + 0x22) 1			// num charges: 1
	  WRITE_BYTE  ("%fx_off%" + 0x24) 1			// vanishes when drained
	  WRITE_SHORT ("%fx_off%" + 0x2a) 1			// projectile: none
  END
  BUT_ONLY_IF_IT_CHANGES

// ensures are regexp search doesn't die
COPY_EXISTING ~ar0087.are~ ~override/xr2400.are~
			  ~ar0087.are~ ~override/xr2600.are~

// add charges to items in game
COPY_EXISTING_REGEXP GLOB ~^.+\.cre$~ ~override~
						  ~^.+\.are$~ ~override~
  PATCH_IF ("%SOURCE_FILE%" STRING_COMPARE_REGEXP "^.+\.cre$" = 0) BEGIN // if creature
	READ_LONG 0x2bc "itm_off" ELSE 0
	READ_LONG 0x2c0 "itm_num" ELSE 0
  END ELSE BEGIN
	READ_LONG  0x78 "itm_off" ELSE 0
	READ_SHORT 0x76 "itm_num" ELSE 0
  END
  FOR (index = 0; index < itm_num; index = index + 1) BEGIN
	SET "offset" = 0
	READ_ASCII ("%itm_off%" +		(0x14 * "%index%")) "item"
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h01~ = 0) BEGIN
	  SET "offset" = ("%sw1h01_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h02~ = 0) BEGIN
	  SET "offset" = ("%sw1h02_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h03~ = 0) BEGIN
	  SET "offset" = ("%sw1h03_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h18~ = 0) BEGIN
	  SET "offset" = ("%sw1h18_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h34~ = 0) BEGIN
	  SET "offset" = ("%sw1h34_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h37~ = 0) BEGIN
	  SET "offset" = ("%sw1h37_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h38~ = 0) BEGIN
	  SET "offset" = ("%sw1h38_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h39~ = 0) BEGIN
	  SET "offset" = ("%sw1h39_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h42~ = 0) BEGIN
	  SET "offset" = ("%sw1h42_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h62~ = 0) BEGIN
	  SET "offset" = ("%sw1h62_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h63~ = 0) BEGIN
	  SET "offset" = ("%sw1h63_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h64~ = 0) BEGIN
	  SET "offset" = ("%sw1h64_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h65~ = 0) BEGIN
	  SET "offset" = ("%sw1h65_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~sw1h72~ = 0) BEGIN
	  SET "offset" = ("%sw1h72_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~_sw1h01~ = 0) BEGIN
	  SET "offset" = ("%_sw1h01_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~_sw1h02~ = 0) BEGIN
	  SET "offset" = ("%_sw1h02_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~_sw1h03~ = 0) BEGIN
	  SET "offset" = ("%_sw1h03_abil_num%" * 0x02)
	END ELSE
	PATCH_IF ("%item%" STRING_COMPARE_CASE ~_sw1h18~ = 0) BEGIN
	  SET "offset" = ("%_sw1h18_abil_num%" * 0x02)
	END
	PATCH_IF ("offset" != 0) BEGIN
	  READ_SHORT ("%itm_off%" + 0x08 + "%offset%" + (0x14 * "%index%")) "charges"
	  PATCH_IF ("%charges%" = 0) BEGIN
		WRITE_SHORT ("%itm_off%" + 0x08 + "%offset%" + (0x14 * "%index%")) 1
	  END
	END
  END
  BUT_ONLY_IF_IT_CHANGES

Edited by cmorgan, 13 August 2007 - 06:51 AM.