Jump to content

Passing arrays to patch functions


Recommended Posts

Hi,

I want to pass arrays as function parameters. I have looked at this thread which works nice for associative arrays:

In my case, I have simple arrays.

First patch function:

DEFINE_PATCH_FUNCTION disease_immunity BEGIN
  DEFINE_ARRAY spells BEGIN  
    ~SPWI409~  
    ~FL#CSDIS~
  END
  DEFINE_ARRAY opcodes BEGIN 101 END
  DEFINE_ARRAY icons BEGIN 14 130 END
  DEFINE_ARRAY strings BEGIN 39752 54337 END
 
  LPF ADD_IMMUNITY_CRE_ITM_SPL STR_VAR opcodes=~opcodes~ icons=~icons~ strings=~strings~ spells=~spells~ END
 
END

Called function:

DEFINE_PATCH_FUNCTION ADD_IMMUNITY_CRE_ITM_SPL
STR_VAR
  icons = ~~  
  strings = ~~  
  animations = ~~  
  spells = ~~  
BEGIN
    PATCH_FOR_EACH value IN %opcodes%  BEGIN
         PATCH_PRINT ~op=%value%~
    END
END  
 

This doesn't work. PATCH_FOR_EACH seems to accept only raw values.

As for caller, I was wondering if I could write without intermediate variables for short arrays. Something like this:

  LPF ADD_IMMUNITY_CRE_ITM_SPL STR_VAR opcodes=~100 110 120~ icons=~36~ strings=~10050 5680~ spells=~spells~ END
 

If I can't evaluate these values as array,  is there a way to split string into array ? Or, string parsing with REGEXP match, something like that.

WEIDU is really lacking a good documentation. 

 

 

 

Link to comment

 I have found a solution:

  LPF ADD_IMMUNITY_CRE_ITM_SPL STR_VAR opcodes=~opcodes~ icons=~14 130~ strings=~strings~ spells=~spells~ END
 

 

  PATCH_PHP_EACH EVAL ~%opcodes%~ AS _ => value BEGIN
    PATCH_PRINT ~op=%value%~
  END  
  PATCH_PHP_EACH EVAL ~%icons%~ AS _ => value BEGIN
    PATCH_PRINT ~icon=%value%~
  END  
 

Finally, it works automatically :)

Edited by aigleborgne
Link to comment

I was partially wrong with last post:

LPF ADD_IMMUNITY_CRE_ITM_SPL STR_VAR opcodes=~opcodes~ icons=~14 130~ strings=~strings~ spells=~spells~ END

icons don't get evaluated as array. I thought it worked, but I might had some interferences in my code.

Link to comment

Well, yeah. DEFINE_ARRAY parses a space-delimited list of strings to an array. Using "icons=~14 130~" in your list of arguments just sets that particular string variable to the six-character string "14 130". It's not an array, and the space is part of the string.

Link to comment
31 minutes ago, jmerry said:

Well, yeah. DEFINE_ARRAY parses a space-delimited list of strings to an array. Using "icons=~14 130~" in your list of arguments just sets that particular string variable to the six-character string "14 130". It's not an array, and the space is part of the string.

I found out, but is there a way to parse or convert a string into array ? API seems very very limited...

 

Link to comment
20 hours ago, argent77 said:

If you just want to evaluate the elements inside the string, then this code may suffice:

INNER_PATCH ~%icons%~ BEGIN
  REPLACE_EVALUATE ~[^ %TAB%]+~ BEGIN
    PATCH_PRINT ~Processing string value: "%MATCH0%"~
  END ~%MATCH0%~
END

 

Thanks, it worked very well. Although I couldn't patch inside, probably because INNER_PATCH. I wrapped it into a function:

DEFINE_PATCH_FUNCTION STRING_TO_ARRAY
STR_VAR
  string = ""     // string with space separator
RET_ARRAY array
BEGIN
  CLEAR_ARRAY array
  SET i=0
  INNER_PATCH ~%string%~ BEGIN
    REPLACE_EVALUATE ~[^ %TAB%]+~ BEGIN
      SPRINT $array("%i%") "%MATCH0%"
      i+=1
    END ~%MATCH0%~
  END    
END

Then:

      LPF STRING_TO_ARRAY STR_VAR string=EVALUATE_BUFFER "%opcodes%" RET_ARRAY array END
      PATCH_PHP_EACH array AS _ => opcode BEGIN
        // Immunity to effect
        PATCH_PRINT ~Immunity to effect [%opcode%]~
        LPF ADD_CRE_EFFECT INT_VAR opcode=101 target=1 timing=9 parameter2=EVALUATE_BUFFER "%opcode%" END  
      END
 

But it doesn't work, I can't see what param2 value is written by function ADD_CRE_EFFECT but it isn't the value that are correctly displayed in console:

Immunity to effect [25]

Immunity to effect [78]

I don't fully understand difference with this code (that works):

      PATCH_FOR_EACH ~effect~ IN ~90~ ~91~ BEGIN
        LPF ADD_CRE_EFFECT INT_VAR opcode=101 target=1 timing=9 parameter2=EVALUATE_BUFFER "%effect%" END
      END

 

 

 

 

Link to comment

I feel rather stupid about this one, but finally, it makes sense.I have just found out what was wrong by replacing ADD_CRE_EFFECT by a dummy function.

        LPF ADD_CRE_EFFECT INT_VAR opcode=101 target=1 timing=9 parameter2=EVALUATE_BUFFER "%opcode%" END  
 

I can't evaluate a variable named opcode because opcode is already an input parameter. So, WEIDU is using variable shadowing.

As far as I understand, local function starts in INIT_VAR of LPF, whereas in a typical language, parameters are always evaluated before going inside a function.

 

 

Link to comment
2 hours ago, aigleborgne said:

I feel rather stupid about this one, but finally, it makes sense.I have just found out what was wrong by replacing ADD_CRE_EFFECT by a dummy function.

        LPF ADD_CRE_EFFECT INT_VAR opcode=101 target=1 timing=9 parameter2=EVALUATE_BUFFER "%opcode%" END  
 

I can't evaluate a variable named opcode because opcode is already an input parameter. So, WEIDU is using variable shadowing.

As far as I understand, local function starts in INIT_VAR of LPF, whereas in a typical language, parameters are always evaluated before going inside a function.

That's interesting. I haven't known that, could be quite error prone. I also have some "typical language" habits and what I noticed is that with WeiDU it is often required to split things into smaller steps. In this case you would like to have maybe something like this:

SPRINT parameter2 EVALUATE_BUFFER "%opcode%"
LPF ADD_CRE_EFFECT INT_VAR opcode=101 target=1 timing=9 parameter2 END  

You can also switch order of parameters in function invocation but this not seems like good idea. :D 

Edited by marchitek
Link to comment
On 3/26/2023 at 2:56 PM, subtledoctor said:

Neither here nor there: don’t need EVALUATE_BUFFER for integer variables in functions, only for string variables. AFAIK. 

Thanks, I removed all of them!

I have also learned a few other things:

DEFINE_PATCH_FUNCTION STRING_TO_ARRAY
STR_VAR
  string = ""     // string with space separator
RET_ARRAY array
BEGIN
  CLEAR_ARRAY array
  SET i=0
  INNER_PATCH ~%string%~ BEGIN
    REPLACE_EVALUATE ~[^ %TAB%]+~ BEGIN
      SPRINT $array("%i%") "%MATCH0%"
      i+=1
    END ~%MATCH0%~
  END    
END

Considering this function, and multiple calls:

  LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array END
  LPF STRING_TO_ARRAY STR_VAR string=""  RET_ARRAY array END

It appears that array is not cleared at all if empty. I need to add a clear in between:

  LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array END
  CLEAR_ARRAY array
  LPF STRING_TO_ARRAY STR_VAR string=""  RET_ARRAY array END

I assume I have to keep the same name for returned variable between caller and called function. Something like:

  LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array1 END
  PATCH_PHP_EACH array1 AS _ => v BEGIN
    PATCH_PRINT ~Loop 1, value = %v%~
  END
  LPF STRING_TO_ARRAY STR_VAR string="" RET_ARRAY array2 END
  PATCH_PHP_EACH array2 AS _ => v BEGIN
    PATCH_PRINT ~Loop 2, value = %v%~
  END

But I can't do that. Returning variable is very special in WEIDU and not very intuitive.

At this point, I think that I could remove CLEAR_ARRAY in STRING_TO_ARRAY function as it does probably nothing, at least in my tests. Well, it isn't entirely true, as it works when I have array with at least one value:

  LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array END
  PATCH_PHP_EACH array AS _ => v BEGIN
    PATCH_PRINT ~Loop 1, value = %v%~
  END
  LPF STRING_TO_ARRAY STR_VAR string="4" RET_ARRAY array END
  PATCH_PHP_EACH array AS _ => v BEGIN
    PATCH_PRINT ~Loop 2, value = %v%~
  END

Of course, I could add a test to skip empty string, but in my mind, it shouldn't be necessary. It is a common thing to have empty array and you shouldn't test its length before a loop.

 

 

Link to comment
1 hour ago, aigleborgne said:

I assume I have to keep the same name for returned variable between caller and called function. Something like:

  LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array1 END
  PATCH_PHP_EACH array1 AS _ => v BEGIN
    PATCH_PRINT ~Loop 1, value = %v%~
  END
  LPF STRING_TO_ARRAY STR_VAR string="" RET_ARRAY array2 END
  PATCH_PHP_EACH array2 AS _ => v BEGIN
    PATCH_PRINT ~Loop 2, value = %v%~
  END

But I can't do that. Returning variable is very special in WEIDU and not very intuitive.

You can assign the return value of a function to another variable:

LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array1 = array END
// PATCH_PHP_EACH array1 AS _ => v BEGIN ...

LPF STRING_TO_ARRAY STR_VAR string="" RET_ARRAY array2 = array END
// PATCH_PHP_EACH array2 AS _ => v BEGIN ...

 

Link to comment
1 hour ago, argent77 said:

You can assign the return value of a function to another variable:

LPF STRING_TO_ARRAY STR_VAR string="1 2 3" RET_ARRAY array1 = array END
// PATCH_PHP_EACH array1 AS _ => v BEGIN ...

LPF STRING_TO_ARRAY STR_VAR string="" RET_ARRAY array2 = array END
// PATCH_PHP_EACH array2 AS _ => v BEGIN ...

 

Thanks again, your knowledge is limitless 😉

Link to comment

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...