Jump to content

ADD_CRE_EFFECT - Visual Effects


JediMindTrix

Recommended Posts

I need to remove all flags from a single .spl. I think I can use WRITE_SHORT 0x18 0 to do so, since without any bits/bytes set, 0 is what it should add up too.

My question is if I had to set flag 11 and flag 8 (the numbers are what they are called in NI, since these flags are presented as a byte/bit table in the IESDP I suspect they are identified differently.), what would I input in place of 0 in the code I wrote above? Is this another case of adding bytes and bits?

2^11+2^8 expressed in binary. Weidu supports bit shifting, so it can do the work for you with left shift and bitwise oring (something like 1

WeiDU even has variables defined for all of the bits. You can use (BIT11 | BIT8) if you like.

 

Thank you Mike, that visual aid helped me a lot, as did Jarno's explanation of what he meant by +0 to the sum.

Say you wish to know what the .spl file's second extended headers has at the offset 0x0000, it's not the spells offset zero, but the offset after the header(lenght of which is 0x072 bits) and the first extended header(lenght of which is 0x0028 bits) aka you are looking for the bit at offset 0x72+0x28, which is 0x9a or 154. But then, for what réver reason you wish to know what the headers has at offset 0x0000, then you are looking at files the offset zero.

Just to be clear, the abilities don't have to come directly after the header. Sometimes the effects come before the abilities. To determine where abilities or effects start, you should always read the value from abilities_off (0x64) or effects_off (0x6a).

 

Likewise, the global effects usually come before the feature blocks in the group of effects, but they don't have to. That is why there is an effects_ind (0x6e), so you'll know where they begin.

Link to comment

No. What that code does is set that bit to 1 and every other bit to 0. Repeating the procedure will have no effect.

 

If your goal is to change only the value of that one bit and not any of the others, you need to use different code.

 

WRITE_SHORT 0x18 (THIS | BIT3)

Link to comment

If your goal is to change only the value of that one bit and not any of the others, you need to use different code.

WRITE_SHORT 0x18 (THIS | BIT3)

For my own benefit, if I'm reading that right, is | equal to BOR?

 

Do you not have to define THIS first? (With "READ_SHORT 0x18 THIS")

 

If not, does that mean I can contract

COPY_EXISTING ~whatever.itm/cre/spl~
READ_SHORT 0x18 this
WRITE_SHORT 0x18 (this BOR 0x00100000)
to just

COPY_EXISTING ~whatever.itm/cre/spl~
WRITE_SHORT 0x18 (this | BIT3)
?

 

Even assuming the READ is still necessary, that sure is prettier.

Link to comment

For my own benefit, if I'm reading that right, is | equal to BOR?

 

Yes. Check the WeiDU readme under the primary name (BOR) to find information on synonyms.

 

THIS is a special variable. Whenever a WRITE_ is performed, a READ_ happens in the background, assigning the original value to the variable THIS. THIS is not the same as this.

Link to comment

Harking back to the header related questions,

 

In order to create a header from scratch, would I first need to use ADD_ITEM_EFFECT (or CLONE_EFFECT) to create a new header, then use WRITE_xyz to set the various variables inside of the newly created header?

 

For example:

//Now we create a header where there was none before
LPF ADD_ITEM_EFFECT
INT_VAR
  header = 1
  type = 0
  opcode = .....

...WRITE_BYTE 0x73 1 ///Identify To Use

Additionally, do the BIT3/BIT4/BIT5, etc, work when called inside of an ADD_x_EFFECT command? Such as the one below:

LPF ADD_ITEM_EFFECT //Level drain
INT_VAR
 header = 1
 type = 0
 opcode = 216
 target = 2
 power = 1
 parameter1 = 2
 timing = 9
 resist_dispel = 2
 probability1 = 100
 savingthrow = BIT0
END

How would I set one to no saving throw? Just... savingthrow = 0?

Link to comment

ADD_ITEM_EFFECT creates effects, not ability headers, and I don't think there is a built-in function to create an ability header (though there are some that modify and delete them).

What exactly are you trying to do?

Additionally, do the BIT3/BIT4/BIT5, etc, work when called inside of an ADD_x_EFFECT command? Such as the one below:

LPF ADD_ITEM_EFFECT //Level drain
INT_VAR
 header = 1
 type = 0
 opcode = 216
 target = 2
 power = 1
 parameter1 = 2
 timing = 9
 resist_dispel = 2
 probability1 = 100
 savingthrow = BIT0
END

 

Yes. When assigning INT_VAR variables, you can provide anything that is a value. Lots of things are values. 0 is a value. BIT0 is a variable, which is a value. (BIT0 + 10) is a value. (~%SOURCE_RES%~ STRING_EQUAL_CASE ~arow01~ ? 10 : 20) is a value.

 

How would I set one to no saving throw? Just... savingthrow = 0?

 

Yes.

Link to comment

Again, thanks for answering my questions. Saving Throw can have more than one type/flag selected so I believe the optimal choice for ease of coding would be to use BIT1 | BIT 2 in those cases.

 

I am trying to use WeidU to patch an Item Ability (usable, not an on-equip) on an amulet that in vanilla BG does not have one.

 

EDIT: The IESDP mentions 1 char as a type of information. Are these edited via WRITE_ASCII?

Link to comment

I am trying to use WeidU to patch an Item Ability (usable, not an on-equip) on an amulet that in vanilla BG does not have one.

I think you may need a function to add an ability header.

 

I found some function that Ardanis added to Item Revisions. I have no idea what it does (it seems to either create or clone headers), but you're free to give it a try.

 

 

 

DEFINE_PATCH_FUNCTION ~ADD_ITEM_HEADER~
  INT_VAR
    type=3
    required_id=0
    location=3
    alt_dicesize=0
    target=1
    target_count=0
    range=0
    projectile_type=0
    alt_dicenumber=0
    speed=0
    alt_damage=0
    thaco=0
    dicesize=0
    school=0
    dicenumber=0
    sectype=0
    damage=0
    damage_type=0
    charges=0
    depletion=0
    flags=0
    projectile=1
    overhand=0
    backhand=0
    thrust=0
    is_bow=0
    is_xbow=0
    is_sling=0

    copy_header=0
    insert_point=~-1~
  STR_VAR
    icon=~~
  RET
    insert_point
BEGIN
  LPF ~FJ_SPL_ITM_REINDEX~ END
  hs=0x38

  READ_LONG 0x64 ho
  READ_SHORT 0x68 hc
  READ_LONG 0x6a eo
  insert_point = (insert_point>hc || insert_point<0) ? hc : insert_point
  copy_header = (copy_header<0) ? 0 : copy_header

  PATCH_IF copy_header>hc BEGIN
    PATCH_WARN ~Unable to copy %copy_header%th header, %SOURCE_FILE% contains only %hc% headers!~
  END ELSE BEGIN
    INSERT_BYTES ho+insert_point*hs hs
    hc+=1
    eo+=hs
    PATCH_IF copy_header BEGIN
      READ_SHORT ho+(copy_header - 1)*hs+0x1e ec
      READ_SHORT ho+(copy_header - 1)*hs+0x20 ei
      READ_ASCII eo+ei*0x30 effs (ec*0x30)
      READ_ASCII ho+(copy_header - 1)*hs copy (hs)
      WRITE_ASCIIE ho+insert_point*hs ~%copy%~ (hs)
    END
    WRITE_SHORT 0x68 hc
    WRITE_LONG 0x6a eo

    READ_SHORT 0x70 ei // technically, it is a counter
    FOR (i=ho;i<ho+hc*hs;i+=hs) BEGIN
      READ_SHORT i+0x1e ec
      WRITE_SHORT i+0x20 ei
      ei+=ec
    END

    PATCH_IF copy_header BEGIN
      READ_SHORT ho+insert_point*hs+0x1e ec
      READ_SHORT ho+insert_point*hs+0x20 ei
      INSERT_BYTES eo+ei*0x30 ec*0x30
      WRITE_ASCIIE eo+ei*0x30 ~%effs%~ (ec*0x30)
    END ELSE BEGIN
      off=ho+insert_point*hs
      WRITE_BYTE off type
      WRITE_BYTE off+0x1 required_id
      WRITE_BYTE off+0x2 location
      WRITE_BYTE off+0x3 alt_dicesize
      WRITE_ASCIIE off+0x4 ~%icon%~ (8)
      WRITE_BYTE off+0xc target
      WRITE_BYTE off+0xd target_count
      WRITE_SHORT off+0xe range
      WRITE_BYTE off+0x10 projectile_type
      WRITE_BYTE off+0x11 alt_dicenumber
      WRITE_BYTE off+0x12 speed
      WRITE_BYTE off+0x13 alt_damage
      WRITE_SHORT off+0x14 thaco
      WRITE_BYTE off+0x16 dicesize
      WRITE_BYTE off+0x17 school
      WRITE_BYTE off+0x18 dicenumber
      WRITE_BYTE off+0x19 sectype
      WRITE_SHORT off+0x1a damage
      WRITE_SHORT off+0x1c damage_type
      WRITE_SHORT off+0x22 charges
      WRITE_SHORT off+0x24 depletion
      WRITE_LONG off+0x26 flags
      WRITE_SHORT off+0x2a projectile
      WRITE_SHORT off+0x2c overhand
      WRITE_SHORT off+0x2e backhand
      WRITE_SHORT off+0x30 thrust
      WRITE_SHORT off+0x32 is_bow
      WRITE_SHORT off+0x34 is_xbow
      WRITE_SHORT off+0x36 is_sling
    END
  END
END
Oh, and it requires this function, too.

// found by Ardanis in Rogue Rebalancing, had apparently been written by Nythrun
// fixed two things, wrapped a function over it

DEFINE_PATCH_FUNCTION ~FJ_SPL_ITM_REINDEX~ BEGIN

PATCH_IF !(~%SOURCE_FILE%~ STRING_MATCHES_REGEXP ~^.+\.spl~) BEGIN
  hs = 0x28
  WRITE_LONG 0xc ~-1~ //Identified name
  WRITE_LONG 0x54 ~-1~ //Identified description
  PATCH_FOR_EACH tz IN 0x44 0x48 0x58 0x5c BEGIN
    WRITE_LONG tz 0
  END
END ELSE PATCH_IF !(~%SOURCE_FILE%~ STRING_MATCHES_REGEXP ~^.+\.itm~) BEGIN
  hs = 0x38
END
READ_LONG 0x64 hf //Extended header offset
READ_SHORT 0x68 hc //Extended header count
READ_LONG 0x6a fb //Feature block table offset
READ_SHORT 0x70 fc //Feature block count
PATCH_IF ((hf > fb) AND (hc > 0)) BEGIN // Ardanis: fixed "hc > 1" to "hc > 0"
  READ_ASCII hf ~eh~ ELSE ~fail~ (hs * hc)
  PATCH_IF (~%eh%~ STRING_EQUAL ~fail~) BEGIN
    WHILE ((~%eh%~ STRING_EQUAL ~fail~) AND (hc > 0)) BEGIN
      READ_ASCII hf ~eh~ ELSE ~fail~ (hs * hc)
      hc -= 1
    END
  END
  DELETE_BYTES hf (hs * hc)
  hf = 0x72
  WRITE_LONG 0x64 hf
  WRITE_SHORT 0x68 hc
  fb = (0x72 + (hs * hc))
  WRITE_LONG 0x6a fb
  PATCH_IF !(~%eh%~ STRING_EQUAL ~fail~) BEGIN
    INSERT_BYTES hf (hs * hc)
    WRITE_ASCIIE hf ~%eh%~
  END
END ELSE PATCH_IF ((hf != 0x72) AND (hc = 0)) BEGIN
  hf = 0x72
  WRITE_LONG 0x64 hf
END
FOR (i1 = 0; i1 < (hs * hc); i1 += hs) BEGIN
  WRITE_SHORT (hf + i1 + 0x20) fc
  READ_SHORT (hf + i1 + 0x1e) cx
  fc += cx
END
PATCH_IF (SOURCE_SIZE > (0x72 + (hs * hc) + (0x30 * fc))) BEGIN
  DELETE_BYTES (0x72 + (hs * hc) + (0x30 * fc)) (SOURCE_SIZE - (0x72 + (hs * hc) + (0x30 * fc)))
END

// added by Ardanis
WRITE_SHORT 0x6e 0

END // end of function

 

 

EDIT: The IESDP mentions 1 char as a type of information. Are these edited via WRITE_ASCII?

No, not necessarily. Check the description to see what kind of data is held there. If it's a letter (this would be very unlikely), use WRITE_ASCII. If it's a number, use WRITE_BYTE.

Link to comment

EDIT: My questions were silly, please ignore this post. Sometimes you just have to read more carefully :D

 

The function can both clone and add headers - to clone, set the variable copy_header=0 to whichever header you wish to copy, and set whichever variables you wish to change, otherwise do not define it. All variables are set to 0 by default except Type and Location (which are 3), target and projectile (which are both 1). I think the second DEFINE_FUNCTION you posted should actually be defined first, since the first DEFINE_FUNCTION you posted references it.

 

This should be included in the next WeidU release!

 

Next question: In Neverwinter Nights scripting, you can create a custom function in a separate script file then include the file in another script and be able to call the same custom function. Is this possible in WeidU?

 

EDIT: Above question was answered while I was editing.

Link to comment

You don't need to delete it and you can't delete it.

 

If you want to put the code into a separate file, do so and then INCLUDE that file in any components that will use the function (before you try to use it). Or, INCLUDE it in your ALWAYS section so that it is available in all components.

Link to comment

I am trying to use WeidU to patch an Item Ability (usable, not an on-equip) on an amulet that in vanilla BG does not have one.

That's when I put Weidu down, and pick up NI or DLTCEP. Different tools for different jobs. (That "add/clone header" function is interesting, though.)

Link to comment

That's when I put Weidu down, and pick up NI or DLTCEP. Different tools for different jobs.

But see you can't patch the existing file with Weidu if you need to use the NI or DLTCEP to make it.

Well, ok, the DLTCEP actually has a weidu-tp2-fication of the actions took, but I have never used it, so I can't recommend it.

Link to comment

Archived

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

×
×
  • Create New...