Post reply

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.
Name:
Email:
Subject:
Message icon:

Verification:
Type the letters shown in the picture
Listen to the letters / Request another image

Type the letters shown in the picture:
What color is grass?:
What is the seventh word in this sentence?:
What is five minus two (use the full word)?:

shortcuts: hit alt+s to submit/post or alt+p to preview


Topic Summary

Posted by: Wisp
« on: June 14, 2017, 11:12:09 AM »

In WeiDU 241 you'll be able to do
Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  PATCH_WITH_SCOPE BEGIN
    // insert code here
  END
BUT_ONLY
and no variables will be carried over between files patched.
Posted by: Andrea C.
« on: June 13, 2017, 03:57:14 PM »

Eureka! It works! Thank you so much, CamDawg! :)
Posted by: CamDawg
« on: June 13, 2017, 03:06:43 PM »

Yeah, remember that variables persist--the previous code had no mechanism to drop validslot back to 0, so once it was set to 1 it stayed there. The problem with setting it to zero in the INNER_ACTION is that the INNER_ACTION itself is conditional, e.g. it could get blocked by a null shield reference or bad file name, meaning it could be at 1 from the previous creature and not set back to 0. This is what you're looking for:

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  SET validslot = 0
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  PATCH_IF (shieldslot > "0") BEGIN
    READ_ASCII ((LONG_AT 0x2bc) + %shieldslot% * 0x14) itemname
    INNER_ACTION BEGIN
      COPY_EXISTING ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype
        PATCH_IF (itemtype = 12) BEGIN
          SET validslot = 1
        END
      BUT_ONLY IF_EXISTS
    END
  END
Putting that validslot = 0 at the top of the patch resets it for every creature checked.
Posted by: Andrea C.
« on: June 13, 2017, 01:27:01 PM »

Thank you, CamDawg.

The code now installs, but it still patches all CREs regardless of whether their shield slot is occupied by a weapon.

I've injected the following:

Code: [Select]
PRINT ~itemtype is %itemtype% and validslot is %validslot%~
for good measure and "validslot = 1" is systematically set  regardless of the value of itemtype.

In theory I would expect there to be no validslot set at all if itemtype isn't 12. Should I inject additional code like this to ensure that validslot isn't 1 when itemtype isn't 12?

Code: [Select]
INNER_ACTION BEGIN
      COPY_EXISTING ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype
        PATCH_IF (itemtype = 12) BEGIN
          SET validslot = 1 ELSE validslot = 0
        END
      BUT_ONLY IF_EXISTS
    END
Posted by: CamDawg
« on: June 12, 2017, 07:44:29 PM »

You'll want COPY_EXISTING, not COPY, on that INNER_ACTION. Also, you should safeguard your code with a sanity check to make sure the item exists:

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  PATCH_IF (shieldslot > "0") BEGIN
    READ_ASCII ((LONG_AT 0x2bc) + %shieldslot% * 0x14) itemname
    INNER_ACTION BEGIN
      COPY_EXISTING ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype
        PATCH_IF (itemtype = 12) BEGIN
          SET validslot = 1
        END
      BUT_ONLY IF_EXISTS
    END
  END
Posted by: Andrea C.
« on: June 12, 2017, 01:43:11 PM »

So I've experimented a little bit and the following code:

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  PATCH_IF (shieldslot > "0") BEGIN
    READ_ASCII ((LONG_AT 0x2bc) + %shieldslot% * 0x14) itemname
    INNER_ACTION BEGIN
      COPY ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype
        PATCH_IF (itemtype = 12) BEGIN
          SET validslot = 1
        END
      BUT_ONLY
    END
  END
  ELSE BEGIN
    SET validslot = 1
  END
  PATCH_IF (%validslot% = 1) BEGIN
    READ_LONG 0x28 current
    PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
      PATCH_IF (old = current) BEGIN
        WRITE_LONG 0x28 new
       END
    END
  END
BUT_ONLY

Appears to be working until I get this error message:

(http://i.imgur.com/OW6wt5O.png)

AESOLD.CRE appears to be the first .CRE with something in the shield slot (specifically, SHLD15.ITM.)

Any idea why it would fail to copy it over?
Posted by: Andrea C.
« on: June 11, 2017, 03:54:51 PM »

Hi everyone.

I'm back on this after admittedly a fairly long time.

I was wondering why exactly this code didn't work:

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  PATCH_IF (shieldslot > 0) BEGIN
    READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname
    INNER_ACTION BEGIN
      COPY ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype ELSE 0
        PATCH_IF (itemtype = 12) BEGIN
          SET validslot = 1
        END
      BUT_ONLY
    END
  END
  ELSE BEGIN
    SET validslot = 1
  END
  PATCH_IF (validslot = 1) BEGIN
    READ_LONG 0x28 current
    PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
      PATCH_IF (old = current) BEGIN
        WRITE_LONG 0x28 new
       END
    END
  END
BUT_ONLY


So I looked at a CRE I knew was getting patched despite wielding a weapon in their off-hand: OHBJOKER.CRE (from The Black Pits II)

0x2b8 corresponds indeed to item slots.

To get to the shield slot, I'm adding 0x04 as per the "values and expressions" tutorial from the WeiDU documentation:

Quote
Next, we’re going to read in the shield slot to make sure that it’s empty. We do this by taking the "itemslot" variable and adding 0x04 to it which we know is always going to be the shield slot. (You can verify this by looking at a creature file in NI. If you look at the offset 0x2b8 it will have the offset for item slots. If you add 0x04 to that number, it should equal the offset for the shield slot.)

However, 0x2b8 + 0x04 equals 0x2bc according to Google; a far cry from the 0x1fa0 that I can see in NI as the shield slot. How do I get to 0x04? On a related note, why do I need to read the item offset and go through all this trouble instead of reading 0x1fa0 directly? I mean, obviously that won't work or it would be all over WeiDU's documentation; I'm trying to understand the reason why it doesn't work and the reason why 0x2b8 + 0x04 should get me that slot in particular.

The value at 0x2b8 is 0x1f9c.

0x1f9c + 0x04 = 0x1fa0 which is exactly the offset for shield. This offset's value for OHBJOKER.CRE is "1", indicating that the shield slot is populated.

The code that follows is less clear:

Code: [Select]
READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname
I reckon from the WeiDU documentation that items are always 0x14, but that doesn't tell me why I need to multiply (item offset + shield slot) by it. This results in

(0x1efc + 0x1fa0) = 0x3E9C * 0x14 = 0x4E430

whereas the shield slot item's offset is 0x1f10.

What am I missing?

Also, should this:

Code: [Select]
PATCH_IF (shieldslot > 0) BEGIN
be this:

Code: [Select]
PATCH_IF (shieldslot > "0") BEGIN
instead?

Does it even make a difference?
Posted by: Andrea C.
« on: July 11, 2016, 01:48:38 PM »

Thank you, subtledoctor.

I applied the change and the mod installs just fine; however, CREs with weapons in their shield slots are still getting the BG1 sprite for some reason  ???
Posted by: subtledoctor
« on: July 11, 2016, 06:51:08 AM »

No, he means I was using OUTER_SET improperly. Just change it to SET.

ACTIONs are for new events - e.g. COPY is an ACTION. PATCH is for when you're in the middle of an operation. WRITE_SHORT is a PATCH because it happens *within* the COPY operation.

You can set variables either way, it's just that the command is different. If, in the middle of your code, you up and decide to set a variable, you can do it as an ACTION by using OUTER_SET. If, as here, it is inside a COMy operation and bound by a PATCH_IF conditional, then you (and I) should use SET.
Posted by: Andrea C.
« on: July 10, 2016, 02:38:22 PM »

OUTER_SET is an action, you use it in patch context. Remove "OUTER_SET".

If I remove OUTER_SET, won't I be one variable short?

My understanding of the code is that I need "validslot" to be defined as "itemtype=12" in the item that was read within the INNER_ACTION. Perhaps I should replace "PATCH_IF" with "ACTION_IF" before I OUTER_SET?
Posted by: Magus_BGforge
« on: July 10, 2016, 12:24:21 PM »

OUTER_SET is an action, you use it in patch context. Remove "OUTER_SET".

And by the way, if you've dived this deep, you're not a beginner.
Posted by: Andrea C.
« on: July 10, 2016, 10:38:10 AM »

Hi subtledoctor,

thanks for the code.

Unfortunately, it's giving me an error message: http://i.imgur.com/cWNbrQ2.jpg

Any idea what might be causing it?

Posted by: subtledoctor
« on: July 06, 2016, 12:47:15 PM »

I'm on a phone so can't check this. But it addresses
1) the ordering of INNER_ACTION and the stuff that should or should not be inside it; and
2) I'm not sure you're using %shieldslot% correctly, so I tried to abstract away from it by just setting a variable in cases where you need your operation to run on the .cre

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber 
  READ_SSHORT (itemslot + 0x04) shieldslot
  PATCH_IF (shieldslot > 0) BEGIN
    READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname
    INNER_ACTION BEGIN
      COPY ~%itemname%.itm~ ~override~
        READ_SHORT 0x1c itemtype ELSE 0
        PATCH_IF (itemtype = 12) BEGIN
          OUTER_SET validslot = 1
        END
      BUT_ONLY
    END
  END
  ELSE BEGIN
    SET validslot = 1
  END
  PATCH_IF (validslot = 1) BEGIN
    READ_LONG 0x28 current
    PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
      PATCH_IF (old = current) BEGIN
        WRITE_LONG 0x28 new
       END
    END
  END
BUT_ONLY
Posted by: Andrea C.
« on: June 26, 2016, 04:00:28 AM »

Thank you, Wisp.

I had not considered INNER_ACTION because its tutorial in the WeiDU documentation suggests it's a very advanced feature, and I'm barely a beginner.

Indeed, because the example in the tutorial is very different from what I'm trying to do, I find its application to my case a bit confusing:

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname

  INNER_ACTION BEGIN
   COPY ~%itemname%.itm~ ~override~
    READ_SHORT 0x1c itemtype ELSE 0
     PATCH_IF (itemtype = 12) OR (shieldslot = "-1") BEGIN
      READ_LONG 0x28 current
      PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
        PATCH_IF (current = old) BEGIN
          WRITE_LONG 0x28 new
        END
      END
    END
  END
  BUT_ONLY

Unsurprisingly, this also doesn't seem to work.

Should I be using INNER_PATCH instead of PATCH_IF?

The main source of confusion here is that I'm trying to combine an INNER_ACTION clause (i.e. check whether the item equipped is a shield) with a non-INNER_ACTION one (i.e. check whether the shield slot is populated at all.)

Perhaps INNER_ACTION should happen before I try to read the item in the slot?

Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot

  INNER_ACTION BEGIN
  READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname
   COPY ~%itemname%.itm~ ~override~
    READ_SHORT 0x1c itemtype ELSE 0
  END
  PATCH_IF (itemtype = 12) OR (shieldslot = "-1") BEGIN
    READ_LONG 0x28 current
    PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
      PATCH_IF (current = old) BEGIN
        WRITE_LONG 0x28 new
       END
    END
  END
  BUT_ONLY

Posted by: Wisp
« on: June 24, 2016, 06:47:52 AM »

You need to use INNER_ACTION. As posted, you code would be more appropriately formatted like this:
Code: [Select]
COPY_EXISTING_REGEXP GLOB ~.*\.cre~ ~override~
  READ_LONG 0x2bc itemsoffset
  READ_LONG 0x2b8 itemslot
  READ_LONG 0x2c0 itemnumber
  READ_SSHORT (itemslot + 0x04) shieldslot
  READ_ASCII ((LONG_AT 0x02bc) + %shieldslot% * 0x14) itemname

COPY ~%itemname%.itm~ ~override~
  READ_SHORT 0x1c itemtype ELSE 0
  PATCH_IF (itemtype = 12) OR (shieldslot = "-1") BEGIN
    READ_LONG 0x28 current
    PATCH_PHP_EACH cd_animation_map AS old => new BEGIN
      PATCH_IF (current = old) BEGIN
        WRITE_LONG 0x28 new
      END
    END
  END
BUT_ONLY