Jump to content

ACTION_FOR_EACH with a string array variable


Recommended Posts

Hi,

I have to parse 2 arrays of string that executes the same code, with one of them beeing conditionnal:

ACTION_FOR_EACH ~file~  ~a~ ~b~ ~c~
BEGIN
  ACTION_IF FILE_EXISTS_IN_GAME ~%file%.cre~ BEGIN
    COPY_EXISTING ~%file%.cre~ ~override~
      // do some stuff
    BUT_ONLY_IF_IT_CHANGES
  END
END
ACTION_IF sometest = 1 BEGIN
    ACTION_FOR_EACH ~file~  ~d~ ~e~ ~f~
    BEGIN
        ACTION_IF FILE_EXISTS_IN_GAME ~%file%.cre~ BEGIN
            COPY_EXISTING ~%file%.cre~ ~override~
            // do some stuff
            BUT_ONLY_IF_IT_CHANGES
        END
    END
END

It is quite ugly, and considering there are dozens of block code like this one, something must be done. Is it possible to build a string array variable and use it in ACTION_IF ?

In a typical language, you would something like:

let array = [ 'a', 'b', 'c' ];

if (sometest == 1) array = [ ...array, 'd', 'e', 'f' ];

for (let f in array) {

      // do something

}

I need to something like this in WEIDU but don't know how. If it isn't possible, I guess I'll have to use a function with file parameter.

I'd like to do it in the most concise and elegant way.

 

Link to comment

If you're iterating over an array, that's ACTION_PHP_EACH, or PHP_EACH/PATCH_PHP_EACH if you already have a resource loaded. Here's an example component of mine that uses it:

//
//
// Elemental protection spells increment resistances
// Last updated: 3.0
//

BEGIN @20000 DESIGNATED 200
GROUP @2
	ACTION_CLEAR_ARRAY resistance
	ACTION_FOR_EACH name IN ~SUN_SOUL_GREATER_SUN~ ~TALOS_STORMSHIELD~ ~CLERIC_ARMOR_OF_FAITH~ ~CLERIC_RESIST_FIRE~ ~CLERIC_PROTECTION_FROM_FIRE~ ~CLERIC_PROTECTION_FROM_LIGHTNING~ ~CLERIC_AURA_OF_FLAMING_DEATH~ ~WIZARD_WRAITH_FORM~ ~WIZARD_PROTECTION_FROM_FIRE~ ~WIZARD_PROTECTION_FROM_COLD~ ~WIZARD_FIRE_SHIELD_BLUE~ ~WIZARD_FIRE_SHIELD_RED~ ~WIZARD_PROTECTION_FROM_ELECTRICITY~ ~WIZARD_PROTECTION_FROM_ACID~ ~WIZARD_PROTECTION_FROM_MAGIC_ENERGY~ ~WIZARD_PROTECTION_FROM_THE_ELEMENTS~ ~WIZARD_PROTECTION_FROM_ENERGY~ BEGIN
		OUTER_SET num = IDS_OF_SYMBOL (~SPELL~ ~%name%~)
		ACTION_IF (num > 0) BEGIN
			LAF RES_NUM_OF_SPELL_NAME STR_VAR spell_name="%name%" RET res=spell_res END
			OUTER_SPRINT $resistance(~%name%~) ~%res%~
		END
	END

	ACTION_PHP_EACH resistance AS name => res BEGIN
		COPY_EXISTING ~%res%.SPL~ ~override~
			LPF ALTER_SPELL_EFFECT INT_VAR match_opcode=27 parameter2=0 END
			LPF ALTER_SPELL_EFFECT INT_VAR match_opcode=28 parameter2=0 END
			LPF ALTER_SPELL_EFFECT INT_VAR match_opcode=29 parameter2=0 END
			LPF ALTER_SPELL_EFFECT INT_VAR match_opcode=30 parameter2=0 END
			LPF ALTER_SPELL_EFFECT INT_VAR match_opcode=31 parameter2=0 END
		BUT_ONLY IF_EXISTS // IDS may have dud entries
	END // Change elemental resistance effects to "increment" mode.

First, build an array - in this case, elemental resistance spells, drawing from SPELL.IDS to convert symbolic names to resource names. Then I iterate over those spells and make the changes I want, converting all elemental resistance effects to "increment" mode.

Link to comment

You could simplify the code like this:

ACTION_DEFINE_ASSOCIATIVE_ARRAY my_files BEGIN
  ~a~ => 1
  ~b~ => 1
  ~c~ => 1
  ~d~ => ~%sometest%~
  ~e~ => ~%sometest%~
  ~f~ => ~%sometest%~
END

ACTION_PHP_EACH my_files AS file => condition BEGIN
  ACTION_IF (condition) BEGIN
    COPY_EXISTING ~%file%.cre~ ~override~
      // Do your stuff...
    BUT_ONLY IF_EXISTS
  END
END

 

If "sometest" is only defined after the array definition, then this code might be more suitable:

ACTION_DEFINE_ASSOCIATIVE_ARRAY my_files BEGIN
  ~a~ => 0
  ~b~ => 0
  ~c~ => 0
  ~d~ => 1
  ~e~ => 1
  ~f~ => 1
END

ACTION_PHP_EACH my_files AS file => condition BEGIN
  ACTION_IF (NOT condition || sometest && condition) BEGIN
    COPY_EXISTING ~%file%.cre~ ~override~
      // Do your stuff...
    BUT_ONLY IF_EXISTS
  END
END

 

Link to comment
20 minutes ago, argent77 said:

If "sometest" is only defined after the array definition, then this code might be more suitable:

ACTION_DEFINE_ASSOCIATIVE_ARRAY my_files BEGIN
  ~a~ => 0
  ~b~ => 0
  ~c~ => 0
  ~d~ => 1
  ~e~ => 1
  ~f~ => 1
END

ACTION_PHP_EACH my_files AS file => condition BEGIN
  ACTION_IF (NOT condition || sometest && condition) BEGIN
    COPY_EXISTING ~%file%.cre~ ~override~
      // Do your stuff...
    BUT_ONLY IF_EXISTS
  END
END

 

 

Thanks a lot, I really like the second solution as it is more concise. It can still be simplify a bit by inversion and you don't need "&& condition":

ACTION_DEFINE_ASSOCIATIVE_ARRAY my_files BEGIN
  ~a~ => 1
  ~b~ => 1
  ~c~ => 1
  ~d~ => 0
  ~e~ => 0
  ~f~ => 0
END
ACTION_PHP_EACH my_files AS file => do BEGIN
  ACTION_IF (do || sometest) BEGIN
      // Do your stuff...
  END
END

Good use of an associative array to add some logic ! I was too narrow mind with a tradionnal approach but we must be creative with WEIDU limitations :)

Edited by aigleborgne
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...