Structure of stored unit array and traits thereof

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.
Post Reply
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Structure of stored unit array and traits thereof

Post by Nyanyanyan »

I'm trying to have a unit be replaced by a different unit but retain name and traits (and possibly objects), but I can't get it to work. I'm sure I saw the structure of stored unit arrays somewhere on the wiki but I'm not finding it.
The name works fine, as one would expect, but I can't seem to just be able to take all the modifications of a unit and give them to another.

This is what I tried:

Code: Select all

			
			[kill]
				x=$replaceunit.x
				y=$replaceunit.y
			[/kill]
			[unit]
				type=NewUnitType
				variation=elf
				x=$replaceunit.x
				y=$replaceunit.y
				side=$newside.side
				name=$replaceunit.name
				modifications=$replaceunit.modifications
			[/unit]
I also tried using [transform_unit], but that didn't preserve traits either and even ignored the race/variation.

Any help is appreciated.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
beetlenaut
Developer
Posts: 2814
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Structure of stored unit array and traits thereof

Post by beetlenaut »

SotA creates a lich out of a necromancer preserving all the traits (and also all experience--even if the unit had an AMLA). There is a macro in the utils folder you can look at. It's a little bit more involved than it seems like it should have to be.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: Structure of stored unit array and traits thereof

Post by vghetto »

modifications=$replaceunit.modifications

try [set_variables] mode=replace for the modifications instead.

Edit: Thank you for pointing out that objects don't carry over in [transform_unit]. Because that means my reliance on transform_unit to do something similar to what you're after was buggy this entire time :)

Anyway here's how I'm fixing it for my code, this might be helpful to your question as well.
I haven't tested it yet, but it just might work.

Code: Select all

#define SWITCH_PEASANTS ALLOWED NOT_ALLOWED
        {ALLOW_RECRUIT {ALLOWED}}
        {DISALLOW_RECRUIT {NOT_ALLOWED}}
        
        # Grab the ids and original modifications
        [store_unit]
            variable=old_units
            mode=always_clear
            kill=no
            [filter]
                side=1
                type={NOT_ALLOWED}
            [/filter]
        [/store_unit]

        # Change the type
        [transform_unit]
                side=1
                type={NOT_ALLOWED}
                transform_to={ALLOWED}
        [/transform_unit]

        # Reassign original modifications
        [for]
                array=old_units
                reverse=yes
                [do]
                        [store_unit]
                                variable=new_units
                                mode=always_clear
                                kill=yes
                                [filter]
                                        id=$old_units[$i].id
                                [/filter]
                        [/store_unit]
                        [set_variables]
                                name=new_units.modifications
                                mode=replace
                                to_variable=old_units[$i].modifications
                        [/set_variables]
                        [unstore_unit]
                                variable=new_units
                                find_vacant=no
                                x,y=$old_units[$i].x,$old_units[$i].y
                        [/unstore_unit]
                        {CLEAR_VARIABLE new_units}
                [/do]
        [/for]
        {CLEAR_VARIABLE old_units}
#enddef
Edit2: I tested transform_unit some more. The traits and objects are preserved with transform_unit, not sure what went wrong in your case.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Structure of stored unit array and traits thereof

Post by Pilauli »

Nyanyanyan wrote: November 5th, 2020, 3:34 pm I'm sure I saw the structure of stored unit arrays somewhere on the wiki but I'm not finding it.
Try this:
https://wiki.wesnoth.org/SingleUnitWML
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Structure of stored unit array and traits thereof

Post by Nyanyanyan »

beetlenaut wrote: November 5th, 2020, 3:46 pm SotA creates a lich out of a necromancer preserving all the traits (and also all experience--even if the unit had an AMLA). There is a macro in the utils folder you can look at. It's a little bit more involved than it seems like it should have to be.
Thanks!
vghetto wrote: November 5th, 2020, 3:54 pm Edit2: I tested transform_unit some more. The traits and objects are preserved with transform_unit, not sure what went wrong in your case.
Very strange. I'll do some more testing and see if I did something to make it not work.
Pilauli wrote: November 8th, 2020, 12:48 am Try this:
https://wiki.wesnoth.org/SingleUnitWML
That's not it, I mean an array structure like $unit.max_moves , just for things like traits or objects. They're also saved by store_unit, so they have to be in the $unit array somewhere.
I'll try the SotA one and see if I can make it work for me though.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
beetlenaut
Developer
Posts: 2814
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Structure of stored unit array and traits thereof

Post by beetlenaut »

Nyanyanyan wrote: November 5th, 2020, 3:34 pm I'm sure I saw the structure of stored unit arrays somewhere on the wiki but I'm not finding it.
The :inspect command can show you the stored structure of any unit on the map. Could that be where you saw it?
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: Structure of stored unit array and traits thereof

Post by vghetto »

Ok, I no longer use transform_unit because in my use case I need to change the types on the recall list.
I didn't bother with the amla, check out the sota-utils as beetlenaut said for that part.
In my case, whatever experience the unit currently has gets copied over. apart from modifications, i'm also copying variables, status and abilities.
I don't know, this might still be helpful to you.
here is the updated version:

Code: Select all

        # Grab the units on the recall list
        [store_unit]
                variable=old_units
                mode=always_clear
                kill=yes
                [filter]
                        side=1
                        type={NOT_ALLOWED}
                        x,y=recall,recall
                [/filter]
        [/store_unit]

        # make sure recall list x,y is recall,recall
        [for]
                array=old_units
                reverse=yes
                [do]
                        {VARIABLE old_units[$i].x recall}
                        {VARIABLE old_units[$i].y recall}
                [/do]
        [/for]

        # Grab the units on the map and append them to the list
        [store_unit]
                variable=old_units
                mode=append
                kill=yes
                [filter]
                        side=1
                        type={NOT_ALLOWED}
                        {X_AND_Y_ARE_ON_THE_MAP}
                [/filter]
        [/store_unit]
        
        # Create a new unit and reassign original modifications,variables,status,abilities
        [for]
                array=old_units
                reverse=yes
                [do]
                        [unit]
                                random_traits=no
                                canrecruit=$old_units[$i].canrecruit
                                facing=$old_units[$i].facing
                                gender=$old_units[$i].gender
                                goto_x=$old_units[$i].goto_x
                                goto_y=$old_units[$i].goto_y
                                name=$old_units[$i].name
                                overlays=$old_units[$i].overlays
                                role=$old_units[$i].role
                                side=$old_units[$i].side
                                type={ALLOWED}
                                x,y=$old_units[$i].x,$old_units[$i].y
                                to_variable=fresh_unit
                        [/unit]
                        
                        # copy whatever experience the unit has
                        [if]
                                {VARIABLE_CONDITIONAL old_units[$i].experience less_than $fresh_unit.max_experience}
                        [then]
                                {VARIABLE fresh_unit.experience $old_units[$i].experience}
                        [/then]
                        [else]
                        	#unit exceeds the max_experience so prime it for advancement
                                {VARIABLE fresh_unit.experience $fresh_unit.max_experience}
                                {VARIABLE_OP fresh_unit.experience sub 1}
                        [/else]
                        [/if]
                        # copy whatever hitpoints it might have
                        [if]
                                {VARIABLE_CONDITIONAL old_units[$i].hitpoints less_than $fresh_unit.max_hitpoints}
                        [then]
                                {VARIABLE fresh_unit.hitpoints $old_units[$i].hitpoints}
                        [/then]
                        [/if]
                        [set_variables]
                                name=fresh_unit.modifications
                                mode=replace
                                to_variable=old_units[$i].modifications
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.variables
                                mode=replace
                                to_variable=old_units[$i].variables
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.status
                                mode=replace
                                to_variable=old_units[$i].status
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.abilities
                                mode=replace
                                to_variable=old_units[$i].abilities
                        [/set_variables]
                        [unstore_unit]
                                variable=fresh_unit
                                find_vacant=no
                                animate=no
                                x,y=$old_units[$i].x,$old_units[$i].y
                        [/unstore_unit]
                        {CLEAR_VARIABLE fresh_unit}
                [/do]
        [/for]
        {CLEAR_VARIABLE old_units}
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Structure of stored unit array and traits thereof

Post by Nyanyanyan »

vghetto wrote: November 8th, 2020, 5:10 pm Ok, I no longer use transform_unit because in my use case I need to change the types on the recall list.
I didn't bother with the amla, check out the sota-utils as beetlenaut said for that part.
In my case, whatever experience the unit currently has gets copied over. apart from modifications, i'm also copying variables, status and abilities.
I don't know, this might still be helpful to you.
here is the updated version:

Code: Select all

        # Grab the units on the recall list
        [store_unit]
                variable=old_units
                mode=always_clear
                kill=yes
                [filter]
                        side=1
                        type={NOT_ALLOWED}
                        x,y=recall,recall
                [/filter]
        [/store_unit]

        # make sure recall list x,y is recall,recall
        [for]
                array=old_units
                reverse=yes
                [do]
                        {VARIABLE old_units[$i].x recall}
                        {VARIABLE old_units[$i].y recall}
                [/do]
        [/for]

        # Grab the units on the map and append them to the list
        [store_unit]
                variable=old_units
                mode=append
                kill=yes
                [filter]
                        side=1
                        type={NOT_ALLOWED}
                        {X_AND_Y_ARE_ON_THE_MAP}
                [/filter]
        [/store_unit]
        
        # Create a new unit and reassign original modifications,variables,status,abilities
        [for]
                array=old_units
                reverse=yes
                [do]
                        [unit]
                                random_traits=no
                                canrecruit=$old_units[$i].canrecruit
                                facing=$old_units[$i].facing
                                gender=$old_units[$i].gender
                                goto_x=$old_units[$i].goto_x
                                goto_y=$old_units[$i].goto_y
                                name=$old_units[$i].name
                                overlays=$old_units[$i].overlays
                                role=$old_units[$i].role
                                side=$old_units[$i].side
                                type={ALLOWED}
                                x,y=$old_units[$i].x,$old_units[$i].y
                                to_variable=fresh_unit
                        [/unit]
                        
                        # copy whatever experience the unit has
                        [if]
                                {VARIABLE_CONDITIONAL old_units[$i].experience less_than $fresh_unit.max_experience}
                        [then]
                                {VARIABLE fresh_unit.experience $old_units[$i].experience}
                        [/then]
                        [else]
                        	#unit exceeds the max_experience so prime it for advancement
                                {VARIABLE fresh_unit.experience $fresh_unit.max_experience}
                                {VARIABLE_OP fresh_unit.experience sub 1}
                        [/else]
                        [/if]
                        # copy whatever hitpoints it might have
                        [if]
                                {VARIABLE_CONDITIONAL old_units[$i].hitpoints less_than $fresh_unit.max_hitpoints}
                        [then]
                                {VARIABLE fresh_unit.hitpoints $old_units[$i].hitpoints}
                        [/then]
                        [/if]
                        [set_variables]
                                name=fresh_unit.modifications
                                mode=replace
                                to_variable=old_units[$i].modifications
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.variables
                                mode=replace
                                to_variable=old_units[$i].variables
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.status
                                mode=replace
                                to_variable=old_units[$i].status
                        [/set_variables]
                        [set_variables]
                                name=fresh_unit.abilities
                                mode=replace
                                to_variable=old_units[$i].abilities
                        [/set_variables]
                        [unstore_unit]
                                variable=fresh_unit
                                find_vacant=no
                                animate=no
                                x,y=$old_units[$i].x,$old_units[$i].y
                        [/unstore_unit]
                        {CLEAR_VARIABLE fresh_unit}
                [/do]
        [/for]
        {CLEAR_VARIABLE old_units}
Thanks, that's exactly what I needed.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Post Reply