Help on creating an array of stored units.

The place to post your WML questions and answers.

Moderator: Forum Moderators

Forum rules
  • Please use [code] BBCode tags in your posts for embedding WML snippets.
  • To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Help on creating an array of stored units.

Post by Legend_Rider »

I would like to create an array of stored units that can be unstored via an option menu.
Here's what I have so far, (I just placed this at the end of Athermaw scenario for testing)

Code: Select all

[event]
    name=start
        [set_menu_item] # store units
            id=store_unit
            description= _ "Store unit"
            [command]
                [message]
                    [option]
                        message= _ "Store unit"
                        [command]
                            [store_unit]
                                [filter]
                                    id=$unit.id
                                    side=$side_number
                                [/filter]
                                variable=a_unit
                                kill=yes
                            [/store_unit]
                            [set_variables]
                                name=stored_units
                                mode=append
                                [value]
                                    description="$a_unit[0].name"
                                    [command]
                                        [message]
                                            message="$a_unit[0].type"
                                        [/message]
                                    [/command]
                                [/value]
                            [/set_variables]
                        [/command]
                    [/option]
                    [option]
                        message= _ "Cancel"
                        speaker=narrator
                    [/option]
                [/message]
            [/command]
        [/set_menu_item]
        [set_menu_item] # unstore units
            id=unstore_units
            description= _ "unstore units"
            [filter]
                side=$side_number
            [/filter]
            [command]
                [message]
                    [option]
                        [insert_tag]
                            name=options
                            variable=stored_units
                        [/insert_tag]
                    [/option]
                    [option]
                        message= _ "Cancel"
                        speaker=narrator
                    [/option]
                [/message]	
            [/command]
        [/set_menu_item]
[/event]
Edit: this is a continuation of a topic from here:
https://forums.wesnoth.org/viewtopic.ph ... 68#p662268

This thread focuses on the core desired function instead of having everything all mixed up in the middle of an unfinished mod.
Last edited by Legend_Rider on February 3rd, 2021, 2:30 am, edited 1 time in total.
User avatar
skeptical_troll
Posts: 475
Joined: August 31st, 2015, 11:06 pm

Re: Help on creating an array of stored units.

Post by skeptical_troll »

I had something similar in a scenario of Return from the Abyss, basically using an array of units to choose which one to hire. I remember I wasn't able to figure out a way of having a variable number of 'options' inside a message. You could try with a [for] tag inside it but I doubt it would work. The other way is to insert manually the maximum number of options you want to allow, and use a [show_if] to check the array length and only show the first options accordingly.

You'd need to use this inside the [message]

Code: Select all

[insert_tag]
	name = option  # this must be a supported tag inside the 'message' tag, so 'options' is not... an option
	value = variable_you_have_defined_1
[/insert_tag]
and you need to build all the variables variable_you_have_defined_1 somewhere else, which you could do through a loop. They must be structured variable with the content of the option.

These are the lines I had in my scenario which may be useful for you (or if you feel brave you can check the code around line 1000 of scenario 16 in my campaign):
Spoiler:
Last, note that in your first menu item your filter won't work, if you check the set_menu_filter doc it only supports filter_location and there is no unit variable associated, so you must use x1,y1. Also, I think you need mode = append inside store_unit too. Hope this helps, good luck!
User avatar
Pentarctagon
Project Manager
Posts: 4773
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Help on creating an array of stored units.

Post by Pentarctagon »

[insert_tag] should work on each element of an array, so this should do the same thing:

Code: Select all

{FOREACH mercenaries i} # vector of units I defined somewhere else
  [set_variables]
    name=my_options
    mode=append
    [value]
      label=$mercenaries[$i].name
      description=$mercenaries[$i].description
      image=$mercenaries[$i].image|~CROP(17,10,40,50)~SCALE(0.5,0.5)
      [command]
        {HIRE_MERCENARY mercenaries[$i] 51 37} # command to unstore/place unit. In my case defined in a macro
      [/command]
    [/value]      
  [/set_variables]
{NEXT i}

[message]
  speaker=narrator
  caption= _ "Mercenaries Available"    
  message= _ "Important! All mercenaries are loyal, but will work for you only in this scenario. Each time one of them dies while in mission for you, you will have to pay 40 gold pieces for funeral expenses and family compensation. No refunding."
  # I had 7 options
  [insert_tag]
    name=option
    variable=my_options
  [/insert_tag]
  [option]
    message= _ "Quit the tavern."
    [command]
      {VARIABLE get_out yes}
    [/command]
  [/option]
[/message]
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
User avatar
skeptical_troll
Posts: 475
Joined: August 31st, 2015, 11:06 pm

Re: Help on creating an array of stored units.

Post by skeptical_troll »

Pentarctagon wrote: February 1st, 2021, 9:21 pm [insert_tag] should work on each element of an array, so this should do the same thing
niiiiiice! I wish I realized it at the time!! :) Do you mind if I edit the wiki to specify this case with arrays? Or if you're unsure do you prefer that I check beforehand that it works as you're suggesting?
User avatar
Pentarctagon
Project Manager
Posts: 4773
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Help on creating an array of stored units.

Post by Pentarctagon »

I'm pretty confident, but it never hurts to check first.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
vghetto
Posts: 456
Joined: November 2nd, 2019, 5:12 pm

Re: Help on creating an array of stored units.

Post by vghetto »

You are not storing the unit or variable correctly, and in unstore menu you wrote options.
Test the following. There might be better alternatives too.

Code: Select all

    [event]
        name=prestart

        [set_menu_item] # boarding ships
            id=embark
            description= _ "Board ship"
            [show_if]
                [have_unit]
                    x,y=$x1,$y1
                [/have_unit]
            [/show_if]

            [command] # embark
                [message]
                    speaker=narrator
                    message="Board ship"
                    [option]
                        label= _ "Board $unit.name"
                        [command]
                            [set_variables]
                                name=shipventory
                                mode=append
                                [value]
                                    label="$unit.name"
                                    [command]
                                        [for]
                                            array=a_unit
                                            reverse=yes
                                            [do]
                                                [if]
                                                    {VARIABLE_CONDITIONAL a_unit[$|i].name equals $unit.name}
                                                    [then]
                                                        [unstore_unit]
                                                            variable=a_unit[$|i]
                                                            x,y=$|x1,$|y1
                                                        [/unstore_unit]
                                                        {CLEAR_VARIABLE a_unit[$|i]}
                                                    [/then]
                                                [/if]
                                            [/do]
                                        [/for]
                                        [for]
                                            array=shipventory
                                            reverse=yes
                                            [do]
                                                [if]
                                                    {VARIABLE_CONDITIONAL shipventory[$|i].label equals $unit.name}
                                                    [then]
                                                        {CLEAR_VARIABLE shipventory[$|i]}
                                                    [/then]
                                                [/if]
                                            [/do]
                                        [/for]
                                    [/command]
                                [/value]
                            [/set_variables]
                            [store_unit]
                                [filter]
                                    x,y=$x1,$y1
                                [/filter]
                                variable=a_unit
                                kill=yes
                                mode=append
                            [/store_unit]
                        [/command]
                    [/option]
                    [option]
                        label= _ "Cancel"
                        [command][/command]
                    [/option]
                [/message]
            [/command]
        [/set_menu_item]

        [set_menu_item] # disembark
            id=disembark
            description= _ "Disembark units from ship"
            [command] # disembark
                [message]
                    speaker=narrator
                    message="Disembark"
                    [insert_tag]
                        name=option
                        variable=shipventory
                    [/insert_tag]
                    [option]
                        label= _ "Cancel"
                        [command][/command]
                    [/option]
                [/message]
            [/command]
        [/set_menu_item]
    [/event]

Edit: your use of command message and speaker is confusing the hell out of me! I cleaned it up a bit.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

Thank you all for your very helpful replies!
I’m going to try these out! :D
I really dove in deeper than my experience level with this, (that’s how you learn though, I guess)
vghetto wrote: February 2nd, 2021, 4:34 am Edit: your use of command message and speaker is confusing the hell out of me! I cleaned it up a bit.
I did clean up some of the command message stuff a little bit too.

I will update the post with the current version I have after testing these solutions, so we’ll be on the same page.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

skeptical_troll wrote: February 1st, 2021, 9:02 pm You'd need to use this inside the [message]

Code: Select all

[insert_tag]
	name = option  # this must be a supported tag inside the 'message' tag, so 'options' is not... an option
	value = variable_you_have_defined_1
[/insert_tag]
Ah, yes! all these little things, can be trick to catch as a beginner, thanks for pointing that one out!
skeptical_troll wrote: February 1st, 2021, 9:02 pm Last, note that in your first menu item your filter won't work, if you check the set_menu_filter doc it only supports filter_location and there is no unit variable associated, so you must use x1,y1. Also, I think you need mode = append inside store_unit too. Hope this helps, good luck!
Very helpful! Thanks a bundle! 8)
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

vghetto wrote: February 2nd, 2021, 4:34 am You are not storing the unit or variable correctly, and in unstore menu you wrote options.
Test the following. There might be better alternatives too.

Code: Select all

    [event]
        name=prestart

        [set_menu_item] # boarding ships
            id=embark
            description= _ "Board ship"
            [show_if]
                [have_unit]
                    x,y=$x1,$y1
                [/have_unit]
            [/show_if]

            [command] # embark
                [message]
                    speaker=narrator
                    message="Board ship"
                    [option]
                        label= _ "Board $unit.name"
                        [command]
                            [set_variables]
                                name=shipventory
                                mode=append
                                [value]
                                    label="$unit.name"
                                    [command]
                                        [for]
                                            array=a_unit
                                            reverse=yes
                                            [do]
                                                [if]
                                                    {VARIABLE_CONDITIONAL a_unit[$|i].name equals $unit.name}
                                                    [then]
                                                        [unstore_unit]
                                                            variable=a_unit[$|i]
                                                            x,y=$|x1,$|y1
                                                        [/unstore_unit]
                                                        {CLEAR_VARIABLE a_unit[$|i]}
                                                    [/then]
                                                [/if]
                                            [/do]
                                        [/for]
                                        [for]
                                            array=shipventory
                                            reverse=yes
                                            [do]
                                                [if]
                                                    {VARIABLE_CONDITIONAL shipventory[$|i].label equals $unit.name}
                                                    [then]
                                                        {CLEAR_VARIABLE shipventory[$|i]}
                                                    [/then]
                                                [/if]
                                            [/do]
                                        [/for]
                                    [/command]
                                [/value]
                            [/set_variables]
                            [store_unit]
                                [filter]
                                    x,y=$x1,$y1
                                [/filter]
                                variable=a_unit
                                kill=yes
                                mode=append
                            [/store_unit]
                        [/command]
                    [/option]
                    [option]
                        label= _ "Cancel"
                        [command][/command]
                    [/option]
                [/message]
            [/command]
        [/set_menu_item]

        [set_menu_item] # disembark
            id=disembark
            description= _ "Disembark units from ship"
            [command] # disembark
                [message]
                    speaker=narrator
                    message="Disembark"
                    [insert_tag]
                        name=option
                        variable=shipventory
                    [/insert_tag]
                    [option]
                        label= _ "Cancel"
                        [command][/command]
                    [/option]
                [/message]
            [/command]
        [/set_menu_item]
    [/event]
WOW! :shock: That did it!

Now that the storing function is working, I will have to add the proper locations to unstore the units to etc... but that should be relatively easy ;)

I can't express how much I appreciate you all helping me through this! It certainly helped in my WML journey, and helps immensely in my ability to learn as well! :)

When I finish this mod, I would very much like to credit all of you who helped me in this, because I couldn't have possibly done it without you.

Thanks a bundle!
vghetto
Posts: 456
Joined: November 2nd, 2019, 5:12 pm

Re: Help on creating an array of stored units.

Post by vghetto »

What I wrote works but problematic.
You need to refine it in order to pinpoint the unit you want to store or unstore.
Going only by the unit name will break if 2 or more units have the same name.
It won't work with nameless walking corpses or ghosts either.
You're likely to lose units with the above method.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

vghetto wrote: February 3rd, 2021, 9:35 am What I wrote works but problematic.
You need to refine it in order to pinpoint the unit you want to store or unstore.
Going only by the unit name will break if 2 or more units have the same name.
It won't work with nameless walking corpses or ghosts either.
You're likely to lose units with the above method.
Ah, yes... that would be problematic.
I'll see what I can do.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

Would this work?
Added variable=$unit.id in [value] instead of using the label=$unit.name hopefully avoiding any issues with the name being the same, and also keeping the "id" from being seen in game when choosing the units to unstore.

Code: Select all

[set_variables]
    name=ship_inventory
    mode=append
    [value]
        label="$unit.name"
        image=$unit.image
        variable=$unit.id # instead of the "label=$unit.name" $unit.id is unique, avoiding the problems with using names?
        [command]
            [for]
                array=a_unit
                reverse=yes
                [do]
                    [if]
                        {VARIABLE_CONDITIONAL a_unit[$|i].id equals $unit.id} # changed these from "name" to "id"
                        [then]
                            [unstore_unit]
                                variable=a_unit[$|i]
                                x,y=$|x1,$|y1
                            [/unstore_unit]
                        [/then]
                    [/if]
                [/do]
            [/for]
            [for]
                array=ship_inventory
                reverse=yes
                [do]
                    [if]
                        {VARIABLE_CONDITIONAL ship_inventory[$|i].label equals $unit.name} # show name when choosing unit
                        [then]
                            {CLEAR_VARIABLE ship_inventory[$|i]}
                        [/then]
                    [/if]
                [/do]
            [/for]
        [/command]
    [/value]
[/set_variables]
I changed the variable shipventory to ship_inventory to be more understandable.
vghetto
Posts: 456
Joined: November 2nd, 2019, 5:12 pm

Re: Help on creating an array of stored units.

Post by vghetto »

Maybe.
I'd change variable=$unit.id to id=$unit.id
and i'd change

Code: Select all

{VARIABLE_CONDITIONAL ship_inventory[$|i].label equals $unit.name} # show name when choosing unit
to

Code: Select all

{VARIABLE_CONDITIONAL ship_inventory[$|i].id equals $unit.id}
Start with that and see where it gets you.

Edit: Actually, changing the variable to ship_id might be even better than id. Remember ship_inventory will get inserted into a [message] and we don't want all of its values to get processed by the [message] tag filters.
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

I need to somehow create any number of arrays, and give them each a unique id.
What I'm thinking, is that I can basically tie the ID of a ship id=$unit.id to the array.
Create a variable? to allow multiple arrays.
And maybe when a ship is recruited, that's when the array is created? and the array would simply connect to the ships id at that point.

Here's my up to date version of the mod that I'm working with.
Attachments
ships_mod.zip
(5.91 KiB) Downloaded 89 times
User avatar
Legend_Rider
Posts: 35
Joined: June 20th, 2018, 4:51 pm

Re: Help on creating an array of stored units.

Post by Legend_Rider »

I just noticed a bug... Apparently if units disembark from the ship, embark again, then disembark, they duplicate.
Post Reply