[1.14.16] unstore_unit with fire_event=no

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
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

[1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

https://wiki.wesnoth.org/DirectActionsW ... re_unit.5D says that "no" is the default value for "fire_event".

But with Wesnoth 1.14.16 and 1.15.12 I have a different behaviour whether I set this value or not.

For my campaign with living weapons, I want to have AMLA that depend on the weapon that is wielded, not on the unit type.
The following code works for 1.12.6 (it depends on a global variable living_weapons that lists the properties of all existing weapons and in the custom_AMLA variable stores the unit_type that describes the AMLA ; the macro ADVANCEMENT is set to advance or advancement depending of the version of Wesnoth).

Code: Select all

    [event]
        name=post advance
        first_time_only=no
        # Conditions for custom AMLA
        # - the unit has had an "amla_default"
        # - the unit is bonded with a living weapon
        # - this living weapon defines custom AMLA
        {LOOKUP_INDEX unit.modifications.{ADVANCEMENT} id amla_default amla}
        {LOOKUP_INDEX unit.modifications.trait id bonded is_bonded}
        {VARIABLE weapon_name $unit.modifications.trait[$is_bonded].weapon}
        [if]
            {VARIABLE_CONDITIONAL
                unit.modifications.{ADVANCEMENT}[$amla].id
                equals "amla_default"}
            {VARIABLE_CONDITIONAL
                living_weapons[$index_$weapon_name].variables.custom_AMLA
                not_equals ""}
            [then]
                {COPY_UNIT unit temp}
                # Remove default amla and its effects
                {CLEAR_VARIABLE temp.modifications.{ADVANCEMENT}[$amla]}
                {VARIABLE_OP temp.max_hitpoints add -3}
                {VARIABLE_OP temp.hitpoints add -3}
                {VARIABLE temp.max_experience "$(round($temp.max_experience/1.2))"}
                # Use custom AMLA type
                {VARIABLE temp.variables.amla_type $temp.type}
                {VARIABLE temp.type $living_weapons[$index_$weapon_name].variables.custom_AMLA}
                {VARIABLE temp.experience "$($temp.experience+$temp.max_experience)"}
                # This will propose an AMLA
                [unstore_unit]
                    variable=temp
                    find_vacant=no
                    #fire_event=no # strange behaviour with Wesnoth 1.14!
                [/unstore_unit]
                # Revert to the original unit types
                [store_unit]
                    [filter]
                        id=$temp.id
                    [/filter]
                    variable=unit
                    kill=yes
                [/store_unit]
                {COPY_UNIT unit temp}
                [if]
                    {VARIABLE_CONDITIONAL temp.variables.amla_type not_equals ""}
                    [then]
                        {VARIABLE temp.type $temp.variables.amla_type}
                        {CLEAR_VARIABLE temp.variables.amla_type}
                    [/then]
                [/if]
                [unstore_unit]
                    variable=temp
                    find_vacant=no
                [/unstore_unit]
                {CLEAR_VARIABLE temp}
            [/then]
        [/if]
        {CLEAR_VARIABLE weapon_name,is_bonded,amla}
    [/event]
It does not work for 1.14.16 or 1.15.12, because when unstore_unit is called, the post advance event is called again.
When I add fire_event=no the behaviour is different, and not better: it behaves like if advance=no was indicated too. Even if I put explictely advance=yes in the unstore_unit command.

Either I don't understand what should be the behaviour, or it is a bug of Wesnoth.

(edit: added test on 1.15.12, which has the same issue as 1.14.16, and correction of the code above: it is the first unstore_unit that behaves differently whether fire_event=no is set or not)
Last edited by Ptitboul on May 12th, 2021, 4:20 pm, edited 1 time in total.
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

I forgot to include in the code above, the definition of COPY_UNIT

Code: Select all

#define COPY_UNIT INPUT OUTPUT
    # Copy in another unit, so all object effects are recomputed
    [unit]
        side=${INPUT}.side
        x=${INPUT}.x
        y=${INPUT}.y
        experience=${INPUT}.experience
        canrecruit=${INPUT}.canrecruit
        variation=${INPUT}.variation
        type=${INPUT}.type
        id=${INPUT}.id
        moves=${INPUT}.moves
        hitpoints=${INPUT}.hitpoints
        gender=${INPUT}.gender
        name=${INPUT}.name
        facing=${INPUT}.facing
        extra_recruit=${INPUT}.extra_recruit
        underlying_id=${INPUT}.underlying_id
        unrenamable=${INPUT}.unrenamable
        overlays=${INPUT}.overlays
        animate=no
        random_traits=no
        [insert_tag]
            name=status
            variable={INPUT}.status
        [/insert_tag]
        [insert_tag]
            name=modifications
            variable={INPUT}.modifications
        [/insert_tag]
        [insert_tag]
            name=variables
            variable={INPUT}.variables
        [/insert_tag]
        to_variable={OUTPUT}
    [/unit]
    {VARIABLE {OUTPUT}.moves ${INPUT}.moves}
    {VARIABLE {OUTPUT}.attacks_left ${INPUT}.attacks_left}
#enddef
User avatar
IIIO_METAL
Posts: 191
Joined: January 18th, 2017, 5:03 pm
Location: japan

Re: [1.14.16] unstore_unit with fire_event=no

Post by IIIO_METAL »

{VARIABLE temp.experience "$($temp.experience+$temp.max_experience)"}

Maybe the '+' part is wrong and you have to make it a '-' ?
Creator of "Mountain Witch" & "Castle of evil spirit"
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

Thank you IIIO_METAL, but I don't think that this is the issue: the goal of this formula is to have the new unit making an AMLA, therefore it needs to have experience above max_experience. And it works with 1.12.

My issue here is that adding fire_event=no changes the behaviour of unstore_unit.

I have looked a bit deeper, and for 1.14 and 1.15, I observe two different behaviour of unstore_unit depending on fire_event=no or fire_event=yes. And the behaviour with no fire_event is the same as with fire_event=yes. Which is not what the documentation says.

I suppose that, if it is intended, then the documentation should says that there has been a change in 1.13 and the default value of fire_event is not the same. But I am not certain, because I did not test it in all possible configurations of unstore_unit.

I noticed that in 1.12, unstore_unit is implement in C++, while in 1.14 it is implemented in lua. This may explain why it is not backward compatible.
User avatar
WhiteWolf
Forum Moderator
Posts: 747
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: [1.14.16] unstore_unit with fire_event=no

Post by WhiteWolf »

Until someone can clarify what's going on with the changes between versions, you could try a cheap workaround:

Add a condition to your post advance event:

Code: Select all

[filter_condition]
    [variable]
        name=temp_disable_event
        not_equals=yes
    [/variable]
[/filter_condition]
Then before you'd unstore the unit just create this variable to blacklist the event firing the second time, but still fire_event=yes to allow the unit to advance:

Code: Select all

{VARIABLE temp_disable_event yes}
[unstore_unit]
      variable=temp
      find_vacant=no
      fire_event=yes
[/unstore_unit]
And below this event, make a new one that unlocks the blacklist after it's done (and exploits that these events then get called by the unstoring)

Code: Select all

[event]
        name=post advance
        first_time_only=no
	[filter_condition]
	    [variable]
	        name=temp_disable_event
	        equals=yes
	    [/variable]
	[/filter_condition]
	
	{CLEAR_VARIABLE temp_disable_event}
[/event]
Author of the Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Standalone works: The Ravagers - now for 1.14, with new bugs!
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

Thank you. Indeed, I can try this type of workaround to achieve my AMLA stuff for 1.14, but it does not solve the inconsistency with the documentation!
I have been looking at the lua for unstore_unit and here are my findings:
  • With no fire_event in the WML, the cfg.fire_event in the arguments of wesnoth.advance_unit is nil
  • With fire_event=no it is false
  • With fire_event=yes it is true
It seems that wesnoth.advance_unit understands nil as true.

In 10.15, unstore_unit calls unit:advance instead of wesnoth.advance_unit but the behaviour seems the same.
User avatar
IIIO_METAL
Posts: 191
Joined: January 18th, 2017, 5:03 pm
Location: japan

Re: [1.14.16] unstore_unit with fire_event=no

Post by IIIO_METAL »

I'm sorry to write something wrong. :oops:
I reconfirmed the contents of the event.

It may be because you changed the unit by variable substitution. Advance resets some of the changes made by variable substitution.
You should use [object] to swap AMLA to avoid that.
Creator of "Mountain Witch" & "Castle of evil spirit"
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

Hello IIIO_METAL!

In fact, there are two different things:
  • Why this AMLA stuff that works with 1.12 does not work with 1.14
  • Why when no fire_event is mentioned it is the same behaviour as with fire_event=yes
The second thing is a bug either in Wesnoth or in the documentation, IMHO.

It seems that the first thing is where you want to help me. And indeed, currently I am not able, in 1.14, to advance a unit with AMLA from another unit type.
User avatar
Lord-Knightmare
Discord Moderator
Posts: 1492
Joined: May 24th, 2010, 5:26 pm
Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
Contact:

Re: [1.14.16] unstore_unit with fire_event=no

Post by Lord-Knightmare »

Ptitboul wrote: May 14th, 2021, 10:45 am Hello IIIO_METAL!

In fact, there are two different things:
  • Why this AMLA stuff that works with 1.12 does not work with 1.14
  • Why when no fire_event is mentioned it is the same behaviour as with fire_event=yes
The second thing is a bug either in Wesnoth or in the documentation, IMHO.

It seems that the first thing is where you want to help me. And indeed, currently I am not able, in 1.14, to advance a unit with AMLA from another unit type.
Firstly, let it be mentioned that 1.12.x is deprecated and UMC authors are encouraged to stick to 1.14.x (or 1.15.x). So, code in 1.12 is not expected to work in 1.14.x.
Secondly, the default value of fire_event is no, and the documentation seems to be fine. You can see a code here where it works when fire_event is not mentioned.

Lastly, is there any special reason why you'd want to stick to 1.12 code? You can use #ifver WESNOTH_VERSION > 1.12.6 and #else to support both but I wouldn't recommend it.
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

Hello Lord-Knightmare,

I know that 1.12 is deprecated, and also that it is not guaranteed that code for 1.12 will work for 1.14, and also that it is possible to test the version of Wesnoth in use. And I did not complain that the code for 1.12 does not work with 1.14, I am just wondering why, and trying to achieve the same function with 1.14.

I also have a reason to prefer 1.12: on my computer, 1.14 is consuming cpu. It is a mac, and apparently Wesnoth 1.14 and more recent are making continuous calls to the graphic interface, which makes the WindowServer process (and the Battle for Wesnoth process) work continuously. But this is only a minor annoyance, and the main reason is that when I program something, I always try to make it compatible with as many versions as possible.

Also, I did not say that unstore_unit does not work when fire_event is not mentioned.
I noticed that, for my code, it has the same behaviour when fire_event is not mentioned as the one when fire_event=yes, and has a different behaviour when fire_event=no. This is not consistent with the documentation.

In your example from Son_Of_The_Black_Eye, I don't think that the behaviour with fire_event=yes will be different from fire_event=no, because there won't be any advance or post advance events, and the unit placed event is not defined.

I also noticed that the lua code implementing unstore_unit calls wesnoth.advance_unit (or unit:advance in 1.15) with cfg.fire_event taking the values nil, false or true depending on whether fire_event is set in the WML and to which value.

Since these functions are implemented in C, it is more difficult to find where they are implemented, and to verify that indeed nil is understood as true instead of false. One hypothesis is that it is line 178 of src/actions/unit_creator.cpp where it is written bool fire_event = temp_cfg["fire_event"].to_bool(true);
Ptitboul
Posts: 28
Joined: May 8th, 2021, 3:45 pm

Re: [1.14.16] unstore_unit with fire_event=no

Post by Ptitboul »

Anyway, whether it is a bug of Wesnoth or not, it did not prevent me to implement this AMLA stuff for 1.14 and 1.15...
It is available in my BloodLust campaign.
Post Reply