Jump to content


Photo

Using WeiDU to change flags (.sto, .itm, etc...)


14 replies to this topic

#1 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 08 March 2017 - 12:54 AM

Hello!

Here I come with another request for clarification. I read CamDawg's tutorial but I found it a bit hard to follow (all the part about BIT BOR and THIS is not clear to me) so I was wondering if someone could give me a practical example about how to use WeiDu to change, for instance, what kind of rooms are available in a specific inn.

 

Let's say I want Feldepost's Inn to not offer Peasant and Merchant rooms (it is supposed to be a highly luxurious place to sleep at, after all). Currently a patron can sleep in Peasant, Merchant, Noble and Royal rooms. Using NI is just a matter of clicking twice but I would like to learn how to do it with WeiDU instead.

COPY_EXISTING ~inn3351.sto~ ~override~
 /* CONTENT */
BUT_ONLY

I suppose WRITE_LONG 0x5c is needed but what else?

Thanks!


Edited by Salk, 08 March 2017 - 12:56 AM.


#2 Roxanne

Roxanne
  • Modders
  • 1576 posts
  • Gender:Not Telling

Posted 08 March 2017 - 01:08 AM

COPY_EXISTING ~inn3351.sto~ ~override~
WRITE_LONG 0x5c 12  //was 15 before
BUT_ONLY


Edited by Roxanne, 08 March 2017 - 01:09 AM.

The Sandrah Saga

another piece of *buggy, cheesy, unbalanced junk*


#3 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 08 March 2017 - 01:27 AM

Thanks, Roxanne!

Could you tell me how you came with that number (12) and how  you knew it was 15 before?

 

I managed to accomplish the same result with this:

COPY_EXISTING ~inn3351.sto~ ~override~
 WRITE_BYTE 0x5c 0b00001100
BUT_ONLY

but I guess there is a difference and that someone can tell me which. :)



#4 Gwendolyne

Gwendolyne
  • Members
  • 151 posts
  • Gender:Male
  • Location:France

Posted 08 March 2017 - 01:30 AM

COPY_EXISTING ~inn3351.sto~ ~override~
    WRITE_LONG 0x5c (THIS BAND BNOT BIT0)    // remove Peasant rooms
    WRITE_LONG 0x5c (THIS BAND BNOT BIT1)    // remove Merchant rooms
BUT_ONLY

And if you want to add peasant rooms :

    WRITE_LONG 0x5c THIS | BIT0

CARPE DIEM...



In progress : Menace sur le Royaume de Diamant Éternel

#5 Roxanne

Roxanne
  • Modders
  • 1576 posts
  • Gender:Not Telling

Posted 08 March 2017 - 01:35 AM

Thanks, Roxanne!

Could you tell me how you came with that number (12) and how  you knew it was 15 before?

 

I managed to accomplish the same result with this:

COPY_EXISTING ~inn3351.sto~ ~override~
 WRITE_BYTE 0x5c 0b00001100
BUT_ONLY

but I guess there is a difference and that someone can tell me which. :)

I think there is no difference.

If you go to offset 5c (using NI) you get the flags display in plain language. Right clicking on it gives you options to display the field contents in different formats (Hex, binary, number...)

There are probably a number of other methods.


The Sandrah Saga

another piece of *buggy, cheesy, unbalanced junk*


#6 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 08 March 2017 - 01:47 AM

Thank you very much for your help, Gwendolyne and Roxanne. :)


Edited by Salk, 08 March 2017 - 01:48 AM.


#7 subtledoctor

subtledoctor
  • Modders
  • 2145 posts
  • Gender:Male

Posted 08 March 2017 - 07:40 AM

Salk, as far as the BOR and BAND stuff, it took me a while to wrap my head around it as well. Here is the basic gist of its utility.

Let's say my mod alters offset 0x5c of inn3351.sto like so:
WRITE_BYTE 0x5c 0b10000000
Now you come along and want to set the 3rd and 4th bits, as in your example above. The result will be, you will unto my change and break my mod.

So you really want to set the 3rd and 4th bits, while making sure that you don't alter the other ones. In this case, you would use BOR. it means, "set a bit to 1, if either the existing version or my new version has that bit set to 1." So you first read the byte, and then apply you patch in that conditional manner:
READ_BYTE 0x5c store
WRITE_BYTE 0x5c (%store% BOR 0b00001100)
That guarantees that the 3rd and 4th bits are set to 1, regardless of their original value. And it guarantees that the other six bits remain as they were before your patch - since you have them all at 0, they will only be set to 1 if they were already 1.

BAND means "only set a bit to 1 if both the old version and my new version both set it to 1." BAND is used when you want to uncheck flags within a byte. You could reverse your change like so:
READ_BYTE 0x5c store
WRITE_BYTE 0x5c (%store% BAND 0b11110011)
That will keep bits at 1 if they already were 1, except the 3rd and 4th bits which will become 0.

Hope that's clear. I still have to pause for 10 seconds and work this stuff out in my head every time I do this. But it can be very handy.

Edited by subtledoctor, 09 March 2017 - 04:21 AM.

Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#8 DavidW

DavidW
  • Gibberlings
  • 4311 posts
  • Gender:Male

Posted 08 March 2017 - 09:15 AM

I'll make another attempt to generate interest in the SFO function library in SCS, in which you'd do this by

LAF edit_store STR_VAR store=inn3351 editstring="room_peasant=>0 room_merchant=>0" END


#9 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 08 March 2017 - 09:26 AM

Thank you very much for the tutorial, subtledoctor. Very useful.

 

And that function seems really handy, DavidW. I'll see if I can figure out how to use the SFO function library.

 

Thanks. :)



#10 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 08 March 2017 - 11:09 PM

So you really want to set the 5th and 6th bits, while making sure that you don't alter the other ones. In this case, you would use BOR. it means, "set a bit to 1, if either the existing version or my new version has that bit set to 1." So you first read the byte, and then apply you patch in that conditional manner:

READ_BYTE 0x5c store
WRITE_BYTE 0x5c (%store% BOR 0x00001100)
That guarantees that the 5th and 6th bits are set to 1, regardless of their original value. And it guarantees that the other six bits remain as they were before your patch - since you have them all at 0, they will only be set to 1 if they were already 1.

 

 

A few observations:

 

you wrote 0x00001100 but it should really be 0b00001100, right?

 

Also, what I really wanted to set above were the 3rd and 4th bits, not the 5th and 6th ones, since they are counted from right to left?

 

Said that, that piece of code alone is not sufficient because the Inn would *still* offer the rooms (Peasant and Merchant) that I do not want available, just because it is preserving the original bits.

Am I supposed to add a second line like this?

WRITE_BYTE 0x5c (%store% BAND 0b11111100)

Or perhaps there is a one line way to do everything?

 

Do you know how BNOT and THIS work, as in Gwendolyne's example?

Thanks!


Edited by Salk, 08 March 2017 - 11:44 PM.


#11 Mike1072

Mike1072
  • Gibberling Poobah
  • 2359 posts
  • Gender:Male
  • Location:Canada

Posted 09 March 2017 - 04:38 AM

Also, what I really wanted to set above were the 3rd and 4th bits, not the 5th and 6th ones, since they are counted from right to left?


Yes, in 0b00001100, it is the third and fourth bits that are set to 1. They may be referred to as bit2 and bit3, because labelling starts with bit0 in the right-most column.
 

Said that, that piece of code alone is not sufficient because the Inn would *still* offer the rooms (Peasant and Merchant) that I do not want available, just because it is preserving the original bits.

Am I supposed to add a second line like this?

WRITE_BYTE 0x5c (%store% BAND 0b11111100)
Or perhaps there is a one line way to do everything?


If you wanted to, you could chain them together like so:
 
WRITE_BYTE 0x5c (%store% BAND 0b11111100) BOR 0b00001100
(It's similar to arithmetic.)
 

Do you know how BNOT and THIS work, as in Gwendolyne's example?


THIS is a special variable that is automatically set every time you WRITE_ to a field. Before the WRITE_ occurs, the current value of the field is READ_ and stored in the variable named THIS. It's for convenience.
 
READ_BYTE 0x5c store
WRITE_BYTE 0x5c (%store% BOR 0b00001100)
is equivalent to
 
WRITE_BYTE 0x5c (THIS BOR 0b00001100)

BNOT is a bitwise command that changes bits in a value - all the 0s become 1s and all the 1s become 0s.

In Gwendolyne's example, WRITE_LONG 0x5c (THIS BAND BNOT BIT0), what's happening is BNOT is being applied to the variable BIT0. The BIT0 variable has a value of 0b00000001. Therefore, BNOT BIT0 is 0b11111110.

So, if you BAND BNOT BIT0, you are preserving all bits except BIT0, which you set to 0. If you BOR BIT0, you preserve all bits except BIT0, which you set to 1.

#12 subtledoctor

subtledoctor
  • Modders
  • 2145 posts
  • Gender:Male

Posted 09 March 2017 - 04:40 AM

Yes - you are correct of course. I was writing off the top of my head, on my phone, on a train. I've updated my post for the sake of posterity. (I had always thought about the bits as going from left to right when written, and from bottom to top when looking in NI... I am still a rank amateur at this.)

I believe THIS is a variable which just represents the existing byte, letting you skip the READ_BYTE line. I've only started using it very recently; I tend to still READ_BYTE and use a variable since it's easier to see what my code is doing. (If I focus on other stuff for a couple months and then come back to my code, sometimes I literally don't understand what I had done earlier.)

The pipe symbol "|" is just a synonym for BOR... I forget what the 1-character synonym for BAND is - I haven't found it necessary to shorten 3-letter words :p

I haven't used, or learned how to use, BNOT.

Edited by subtledoctor, 09 March 2017 - 09:53 AM.

Faiths & Powers: Spell spheres and kit pack for priests and paladins
Might & Guile: Tweaks and kits for warriors and rogues
Scales of Balance: Game tweaks and rule overhauls
NPC_EE: More options for NPCs in BGEE, SoD, & BG2EE


#13 Mike1072

Mike1072
  • Gibberling Poobah
  • 2359 posts
  • Gender:Male
  • Location:Canada

Posted 09 March 2017 - 04:48 AM

The pipe symbol "|" is just a synonym for BAND... I forget what the 1-character synonym for BOR is - I haven't found it necessary to shorten 3-letter words :p


BAND: &
BOR: |
BNOT: ` (backtick)

The first two share a nice parallel with the logical operators && and ||.

#14 Salk

Salk
  • Modders
  • 2889 posts
  • Gender:Male
  • Location:Sweden

Posted 09 March 2017 - 06:12 AM

I think this could be very useful for others as well.

 

Thanks, Mike1072 and subtledoctor.



#15 Ardanis

Ardanis

    A very GAR character

  • Modders
  • 2551 posts
  • Gender:Male
  • Location:Saint-Petersburg, Russia

Posted 09 March 2017 - 08:14 AM

I haven't used, or learned how to use, BNOT.

 
BNOT 0b00001000 = 0b11110111
 
This is particularly useful for unchecking flags:

WRITE_BYTE offset THIS | BIT1 // set BIT1
WRITE_BYTE offset THIS & `BIT1 // unset BIT1
I believe THIS is a variable which just represents the existing byte, letting you skip the READ_BYTE line.

 

Same for _SHORT and _LONG.


Edited by Ardanis, 09 March 2017 - 08:15 AM.

"Uguu~ Boku Ayu."

Before you start breaking wall tiles with your bare fists, ask yourself first - do you truly need it?



Reply to this topic



  


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users