Pocket Plane Group

Friends and Neighbors => Weimer Republic (WeiDU.org) => WeiDU => Topic started by: Echon on August 20, 2010, 04:20:32 AM

Title: Patch request: items purchased
Post by: Echon on August 20, 2010, 04:20:32 AM
WeiDU would receive +1 to Cool Tool if it could add and remove Items Purchased from STOs.
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 04:28:04 AM
Can do, but isn't this a 5 minutes INSERT+WRITE job anyway?
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 04:31:10 AM
For you or for me? :)

Sure, I could do a macro if it does not become a patch.
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 05:06:49 AM
Five minutes INSERT job for you, of course. If I were to add all five minutes INSERT things to WeiDU, it'll be about two megabytes large.
If having the same item category code twice in the items bought section causes problems I'll add the command to WeiDU. If not, I have the following (not even tested to see if it compiles):
Code: [Select]
INSERT_BYTES (LONG_AT 0x2c) (4 * items_to_add)
WRITE_LONG 0x30 (THIS + items_to_add)
WRITE_LONG 0x34 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
WRITE_LONG 0x4c (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
WRITE_LONG 0x70 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)

WRITE_LONG (LONG_AT 0x2c +  0) item_code1
WRITE_LONG (LONG_AT 0x2c +  4) item_code2
...
( <3 devSin for asking THIS and *_AT, btw)
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 05:13:23 AM
Thanks. I will give it a try.
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 05:20:58 AM
I edited my post so that it allows to add multiple item categories in a single insert - you've seen that version, right?
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 06:08:52 AM
Yes, I have. I decided to take myself out to lunch first.
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 07:21:58 AM
Your code works perfectly. I have expanded it to include a variable amount of items, up to 10. THIS, AT_LONG and ? are new to me, though I can see what they do. Are they undocumented features or have I just missed them in the readme?

Code: [Select]
DEFINE_PATCH_MACRO ~ADD_PURCHASED_ITEM~ BEGIN
  INSERT_BYTES (LONG_AT 0x2c) (4 * items_to_add)
  WRITE_LONG 0x30 (THIS + items_to_add)
  WRITE_LONG 0x34 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x4c (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x70 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  PATCH_IF (items_to_add > 0) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  0) item_code1
  END
  PATCH_IF (items_to_add > 1) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  4) item_code2
  END
  PATCH_IF (items_to_add > 2) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  8) item_code3
  END
  PATCH_IF (items_to_add > 3) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  12) item_code4
  END
  PATCH_IF (items_to_add > 4) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  16) item_code5
  END
  PATCH_IF (items_to_add > 5) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  20) item_code6
  END
  PATCH_IF (items_to_add > 6) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  24) item_code7
  END
  PATCH_IF (items_to_add > 7) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  28) item_code8
  END
  PATCH_IF (items_to_add > 8) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  32) item_code9
  END
  PATCH_IF (items_to_add > 9) THEN BEGIN
  WRITE_LONG (LONG_AT 0x2c +  36) item_code10
  END
END
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 07:37:45 AM
THIS, AT_LONG and ? are new to me, though I can see what they do. Are they undocumented features or have I just missed them in the readme?
THIS and *_AT are new, but they should be in the readme (THIS/STHIS, in particular, is mentioned in the WRITE_* documentation). ? : has been in since forever (and it's standard for mainstream programming languages like C/C++), but I can see how it'd be hard to search for it in the readme  :)

Your code can (and probably should) be simplified using loops or arrays (so it works if you have item_code11 and higher).
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 07:57:57 AM
THIS and *_AT are new, but they should be in the readme (THIS/STHIS, in particular, is mentioned in the WRITE_* documentation). ? : has been in since forever (and it's standard for mainstream programming languages like C/C++), but I can see how it'd be hard to search for it in the readme  :)

Okay. I will go search for it then.

Quote
Your code can (and probably should) be simplified using loops or arrays (so it works if you have item_code11 and higher).

Yeah, that also occured to me. I am trying to figure out how to put it all in a WHILE loop. Can WeiDU make variable variables? Like ITEM_CODEX.
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 08:11:16 AM
EVALUATE_BUFFER ~item_code%X%~ .
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 09:02:49 AM
I have not used SPRINT or EVALUATE_BUFFER before so I tried to go with what is in the readme. I think this code is a mess but I will post it anyway in case someone can tell me what is wrong.

Code: [Select]
DEFINE_PATCH_MACRO ~ADD_PURCHASED_ITEM~ BEGIN
  INSERT_BYTES (LONG_AT 0x2c) (4 * items_to_add)
  WRITE_LONG 0x30 (THIS + items_to_add)
  WRITE_LONG 0x34 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x4c (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x70 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  SET patch_count = 1
  SPRINT item_x ~patch_count~
  WHILE (items_to_add > 0) BEGIN   
    WRITE_LONG (LONG_AT 0x2c + (4 * patch_count - 4)) item_code%item_x%
      EVALUATE_BUFFER ~item_code%item_x%~
      SET patch_count += 1
      SET items_to_add -= 1
  END
END
Title: Re: Patch request: items purchased
Post by: the bigg on August 20, 2010, 10:26:07 AM
Not tested, but this should work:

DEFINE_PATCH_MACRO ~ADD_PURCHASED_ITEM~ BEGIN
  INSERT_BYTES (LONG_AT 0x2c) (4 * items_to_add)
  WRITE_LONG 0x30 (THIS + items_to_add)
  WRITE_LONG 0x34 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x4c (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WRITE_LONG 0x70 (THIS < LONG_AT 0x2c ? THIS : THIS + 4 * items_to_add)
  WHILE (items_to_add > 0) BEGIN   
    WRITE_LONG (LONG_AT 0x2c + (4 * (items_to_add - 1))) EVALUATE_BUFFER ~item_code%items_to_add%~
      SET items_to_add -= 1
  END
END
Title: Re: Patch request: items purchased
Post by: Echon on August 20, 2010, 12:48:13 PM
Lo and behold, it computes! Thanks. :)
Title: Re: Patch request: items purchased
Post by: Echon on August 25, 2010, 03:59:06 PM
I have written a macro that removes purchased items, but for some reason it only removes the first item when used several items in a row. Clues?

Code: [Select]
DEFINE_PATCH_MACRO ~DELETE_PURCHASED_ITEM~ BEGIN
  READ_LONG 0x30 "#items"
  WHILE ("%#items%" > 0) BEGIN
READ_LONG (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "purchaseditem"
PATCH_IF ("%purchaseditem%" = "%item_to_delete%") THEN BEGIN
  DELETE_BYTES (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "4"
  WRITE_LONG 0x30 (THIS - "1")
END
SET "%#items%" -= "1"
  END
  SET "#items" = "0"
  SET "purchaseditem" = "0"
  SET "item_to_delete" = "0"
END

It only removes "27" and they are all present.

Code: [Select]
SET "item_to_delete" = "27"
  LAUNCH_PATCH_MACRO DELETE_PURCHASED_ITEM
  SET "item_to_delete" = "1"
  LAUNCH_PATCH_MACRO DELETE_PURCHASED_ITEM
  SET "item_to_delete" = "32"
  LAUNCH_PATCH_MACRO DELETE_PURCHASED_ITEM
Title: Re: Patch request: items purchased
Post by: Mike1072 on August 25, 2010, 09:33:19 PM
Remember to update the offsets to any of the other parts of the file that may now be incorrect.

0x34 - items for sale
0x4c - drinks for sale
0x70 - cures for sale

If any of these are located after the purchased items section, they will need to have their offset decreased by the number of bytes you deleted from the file.

Not sure why the code isn't functioning, though - will take a look.
Title: Re: Patch request: items purchased
Post by: Echon on August 26, 2010, 01:35:25 AM
I have checked those but purchased items are at the end of the STO.
Title: Re: Patch request: items purchased
Post by: Wisp on August 26, 2010, 04:36:57 AM
I have checked those but purchased items are at the end of the STO.
They don't have to be. A STO file with, say, "items for sale" after "items purchased" is equally valid. That there are no stores like that in the vanilla game is no guarantee no one will introduce one.
Title: Re: Patch request: items purchased
Post by: GeN1e on August 26, 2010, 08:34:55 AM
Some code snippets I'm using to handle stores.
Code: [Select]
DEFINE_ACTION_MACRO buy_group BEGIN

ACTION_DEFINE_ARRAY $buy(weap)  BEGIN 0x10 0x11 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1d 0x1e END
ACTION_DEFINE_ARRAY $buy(armor) BEGIN 0x2 0x7 0xc END
ACTION_DEFINE_ARRAY $buy(rang)  BEGIN 0x5 0xe 0xf 0x12 0x1b 0x1f END
ACTION_DEFINE_ARRAY $buy(magic) BEGIN 0xb 0x23 END
ACTION_DEFINE_ARRAY $buy(potn)  BEGIN 0x9 END
ACTION_DEFINE_ARRAY $buy(jewel) BEGIN 0x1 0xa 0x21 0x22 END
ACTION_DEFINE_ARRAY $buy(misc)  BEGIN 0x0 0x3 0x4 0x6 0x8 0xd 0x1c 0x20 0x24 0x25 END
ACTION_DEFINE_ARRAY $buy(blade) BEGIN 0x13 0x14 0x19 0x1e END
ACTION_DEFINE_ARRAY $buy(blunt) BEGIN 0x10 0x11 0x15 0x16 0x17 0x18 0x1a 0x1d END
ACTION_DEFINE_ARRAY $buy(dwarf) BEGIN 0x15 0x19 END
ACTION_DEFINE_ARRAY $buy(elf)   BEGIN 0x5 0xf 0x14 END

END


DEFINE_PATCH_FUNCTION buy BEGIN
  READ_LONG 0x2c offset
  READ_LONG 0x30 number
  i=0
  DELETE_BYTES offset number*4
  PHP_EACH buy AS ind => res BEGIN
    PATCH_IF VARIABLE_IS_SET EVAL ~%%ind%%~ BEGIN
      PHP_EACH $buy("%ind%") AS i2 => r2 BEGIN
        INSERT_BYTES offset 4
        WRITE_LONG offset r2
        i+=1
      END
    END
  END
  WRITE_LONG 0x30 i
  PATCH_FOR_EACH off IN 0x34 0x4c 0x70 BEGIN
    PATCH_IF LONG_AT off>=offset BEGIN
      WRITE_LONG off (LONG_AT off - (number - i)*4)
    END
  END
END

Code: [Select]
LAM buy_group

// blah-blah-blah

COPY_EXISTING ribald.sto override PATCH_IF SOURCE_SIZE>0x9b BEGIN
  LPF buy INT_VAR weap=1 armor=1 rang=1 jewel=1 misc=1 END

// blah-blah-blah

END BUT_ONLY

EDIT
Duh, you only want to add/remove, not to rewrite the list from the scratch...
Title: Re: Patch request: items purchased
Post by: Echon on November 07, 2010, 12:09:31 PM
I am now at the point where I need to use this and I have updated the macro to include the other offsets. The problem remains the same, though. It only works once. Assistance would be much appreciated.

Code: [Select]
DEFINE_PATCH_MACRO ~DELETE_PURCHASED_ITEM~ BEGIN
  READ_LONG 0x30 "#items"
  WHILE ("%#items%" > 0) BEGIN
READ_LONG (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "purchaseditem"
PATCH_IF ("%purchaseditem%" = "%item_to_delete%") THEN BEGIN
  DELETE_BYTES (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "4"
  WRITE_LONG 0x30 (THIS - "1")
  PATCH_IF (LONG_AT 0x34 > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x34 (THIS - "4") END
  PATCH_IF (LONG_AT 0x4c > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x4c (THIS - "4") END
  PATCH_IF (LONG_AT 0x70 > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x70 (THIS - "4") END
  SET "#items" = "0"
END
SET "%#items%" -= "1"
  END
  SET "purchaseditem" = "0"
  SET "item_to_delete" = "0"
END
Title: Re: Patch request: items purchased
Post by: GeN1e on November 07, 2010, 01:49:01 PM
Change from MACRO to FUNCTION worked. Is there any particular reason why WHILE wouldn't launch for the second time, despite the condition being true?
Title: Re: Patch request: items purchased
Post by: Echon on November 07, 2010, 02:08:56 PM
I do not know what it is that fails. To test it I use the macro four times in a row and the code installs without any problems. Only one purchased item has been removed from the STO, though.
Title: Re: Patch request: items purchased
Post by: the bigg on November 07, 2010, 02:12:19 PM
Quote
DEFINE_PATCH_MACRO ~DELETE_PURCHASED_ITEM~ BEGIN
  READ_LONG 0x30 "#items"
  WHILE ("%#items%" > 0) BEGIN
   READ_LONG (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "purchaseditem"
   PATCH_IF ("%purchaseditem%" = "%item_to_delete%") THEN BEGIN
     DELETE_BYTES (LONG_AT 0x2c + ("4" * ("%#items%" - "1"))) "4"
     WRITE_LONG 0x30 (THIS - "1")
     PATCH_IF (LONG_AT 0x34 > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x34 (THIS - "4") END
     PATCH_IF (LONG_AT 0x4c > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x4c (THIS - "4") END
     PATCH_IF (LONG_AT 0x70 > LONG_AT 0x2c) THEN BEGIN WRITE_LONG 0x70 (THIS - "4") END
     SET "#items" = "0"
   END
   SET "%#items%" -= "1"
  END
  SET "purchaseditem" = "0"
  SET "item_to_delete" = "0"
END
The red %% confuses WeiDU. Removing them makes the macro work correctly.

Do you want the in-depth explanation?
Title: Re: Patch request: items purchased
Post by: Echon on November 07, 2010, 02:35:14 PM
Sure.
Title: Re: Patch request: items purchased
Post by: the bigg on November 07, 2010, 02:59:25 PM
Here goes.

When you write SET "var" = 5 (or READ_LONG offset "var"), "%var%" (quotes excluded) is associated with 5. When WeiDU tries to convert "%var%" to an integer, it looks up the association for "%%var%%"; since none is found, then it looks up the association for "%var%".

READ_LONG associates "%#items%" with the number of items.
WHILE ("%#items%" > 0) operates on the value of "%#items%" ("%%#items%%" is not found)
SET "%#items%" -= 1 reads "%#items%" ("%%#items%%" is not found) and stores the result in "%%#items%%"
from now on, WHILE will read "%%#items%%"
Finally, the macro does its job and sets "%%#items%%" to 0 because it scanned all items (if an item is found, "%#items%" is set to zero, but the loop continues because the value is never read).

Next time the macro is launched,
READ_LONG will set "%#items%" to the number of items
However, WHILE will read "%%#items%%", which is still zero from before, meaning that the loop is not executed and the macro results in a do_nothing().
Title: Re: Patch request: items purchased
Post by: Echon on November 07, 2010, 03:05:53 PM
Should I omit "" for integers and %% when reading variables? I am not sure if they were required when I started this FotD update but they were widely used. They seem to have become obsolete since then, however.
Title: Re: Patch request: items purchased
Post by: the bigg on November 07, 2010, 03:09:47 PM
They became not needed before my time, actually. It's a matter of habit whether you use them or not.

Using them is also nice because you're sure that your tp2 isn't invalidated if one of your variables become a keyword in the tp2 synthax (although you could simply write in lower-case in that case).
Title: Re: Patch request: items purchased
Post by: GeN1e on November 07, 2010, 03:10:11 PM
if an item is found, "%#items%" is set to zero, but the loop continues because the value is never read
:facepalm: I've been such a moron to not take a notice of PATCH_PRINTing even after the match...
Title: Re: Patch request: items purchased
Post by: Mike1072 on November 07, 2010, 04:00:42 PM
The resulting ugliness and extra typing involved with having unnecessary %s and "s around integers should be discouraged.

Use quotes around strings, not around variables.
Title: Re: Patch request: items purchased
Post by: Miloch on November 07, 2010, 04:06:38 PM
Last I checked, there were some statements that require both %% and quotes around variables, like STRING_EQUAL. Otherwise, it reads the variable as a string equalling the variable name, rather than the contents of the variable. But yeah, you don't need them in most cases, like the syntax above.
Title: Re: Patch request: items purchased
Post by: Echon on November 07, 2010, 04:19:33 PM
I thought strings required ~~. Is this also a thing of the past?
Title: Re: Patch request: items purchased
Post by: Mike1072 on November 07, 2010, 06:26:46 PM
Last I checked, there were some statements that require both %% and quotes around variables, like STRING_EQUAL.
STRING_EQUAL works on strings.  ~%var%~ is a string containing only the contents of the variable named var.

I thought strings required ~~. Is this also a thing of the past?
~ ~ or " " or ~~~~~ ~~~~~ or the confusing % %.  A string can be declared without using quotes, but such a string can't contain spaces or certain special characters, can't substitute variables, and can't be empty.
Title: Re: Patch request: items purchased
Post by: GeN1e on November 07, 2010, 06:49:39 PM
Last I checked, there were some statements that require both %% and quotes around variables, like STRING_EQUAL. Otherwise, it reads the variable as a string equalling the variable name, rather than the contents of the variable. But yeah, you don't need them in most cases, like the syntax above.
If you the string to be evaluated, then yes, ~%%~ should be used.

Arrays must take either ~%%~ or "%%" for indexes to be evaluated, and ~~ or "" otherwise.
SET $array("a""%b%"~%c%~)=d will work, but SET $array(a %b% c)=d failed the last time I've tried it.
Title: Re: Patch request: items purchased
Post by: the bigg on November 07, 2010, 07:04:04 PM
Yes, I'm ashamed of how variables and strings are handled in WeiDU. No, I can't fix those oddities - Refinements (and, most likely, other mods too) was hand-crafted by a more naive myself to make sure that it essentially depends on every little exception in the string handling code.
Title: Re: Patch request: items purchased
Post by: Wisp on November 08, 2010, 03:25:57 AM
but SET $array(a %b% c)=d failed the last time I've tried it.
You need to quote (or wavy-line) %b%. You can index an array with e.g. $array(a b) (if you don't need variable substitution etc).