Formalizing variables in the WFL (need help!)

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
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Formalizing variables in the WFL (need help!)

Post by Mechanical »

Hi, I need help with the WFL.

I have a global variable

Code: Select all

$metal_reserve$side_number
that sets the amount of metal for each side. It works in WML without any problems.

At the same time, I have an attack feature that disables the attack if there is too little metal.

Code: Select all

[disable]
        id=metal_cost{NUMBER}
        [filter_self]
            [not]
                formula="$metal_reserve$self.side|| < {NUMBER}"
            [/not]
        [/filter_self]
 [/disable]
But this doesn't work. I found out that it's just a matter of formula design. If I write

Code: Select all

formula="$metal_reserve1 < {NUMBER}"
everything works correctly. But if the variable consists of two variables (

Code: Select all

$metal_reserve$self.side
and the like) then Wesnoth starts giving errors and nothing works. Please help me get the double variable right.
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Toranks
Translator
Posts: 168
Joined: October 21st, 2022, 8:59 pm
Location: Sevilla
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Toranks »

This code is on a event inside another event, just in case?
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

Toranks wrote: February 26th, 2023, 1:32 pm This code is on a event inside another event, just in case?
No, all fine with [event]s in this code
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Spannerbag
Posts: 538
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Formalizing variables in the WFL (need help!)

Post by Spannerbag »

Mechanical wrote: February 26th, 2023, 1:03 pm

Code: Select all

[disable]
        id=metal_cost{NUMBER}
        [filter_self]
            [not]
                formula="$metal_reserve$self.side|| < {NUMBER}"
            [/not]
        [/filter_self]
 [/disable]
Aplogies if you've already thought of this but maybe

formula="$metal_reserve|$self.side < {NUMBER}"

might work?
Also I assume simply using
formula="$metal_reserve$self.side < {NUMBER}"
doesn't work?

I only point this out because I don't know if "|" is recognised/works inside formula?

Another way to do this might be to have an array subscripted by side?

I.e. $metal_reserve[$self.side]?
So you'd need to build and manipulate an array rather than multiple unconnected (to WML at least) variables?

Hope this helps (even if only by excluding options that don't work!) :)
Good luck!

Cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.17, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

Spannerbag wrote: February 26th, 2023, 3:08 pm
Mechanical wrote: February 26th, 2023, 1:03 pm

Code: Select all

[disable]
        id=metal_cost{NUMBER}
        [filter_self]
            [not]
                formula="$metal_reserve$self.side|| < {NUMBER}"
            [/not]
        [/filter_self]
 [/disable]
Aplogies if you've already thought of this but maybe

formula="$metal_reserve|$self.side < {NUMBER}"

might work?
Also I assume simply using
formula="$metal_reserve$self.side < {NUMBER}"
doesn't work?

I only point this out because I don't know if "|" is recognised/works inside formula?

Another way to do this might be to have an array subscripted by side?

I.e. $metal_reserve[$self.side]?
So you'd need to build and manipulate an array rather than multiple unconnected (to WML at least) variables?

Hope this helps (even if only by excluding options that don't work!) :)
Good luck!

Cheers!
-- Spannerbag
Hi! Thank you for your reply. I found your ideas interesting, but unfortunately they cause the same bug (I attached a screenshot).

As for the array, I already checked it, unfortunately it doesn't work either. :(
Attachments
bug.png
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Ravana
Forum Moderator
Posts: 3013
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Ravana »

Did you verify that $self is assigned?
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

Ravana wrote: February 26th, 2023, 4:08 pm Did you verify that $self is assigned?
I'm not so sure about that. However, the problem is different.
I tried writing $attacker.side and $defender.side (as well as making the ability active only in attack and only in defense respectively), it gave the same result.

I'm inclined to think that the reason here is purely technical - wrongly written variable. I don't know where to put the right signs.
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Ravana
Forum Moderator
Posts: 3013
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Ravana »

Since the code you posted doesnt assign attacker or defender either it doesnt give any further confidence for me.
User avatar
Celtic_Minstrel
Developer
Posts: 2235
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Celtic_Minstrel »

Mechanical wrote: February 26th, 2023, 1:03 pm Hi, I need help with the WFL.

I have a global variable

Code: Select all

$metal_reserve$side_number
that sets the amount of metal for each side. It works in WML without any problems.

At the same time, I have an attack feature that disables the attack if there is too little metal.

Code: Select all

[disable]
        id=metal_cost{NUMBER}
        [filter_self]
            [not]
                formula="$metal_reserve$self.side|| < {NUMBER}"
            [/not]
        [/filter_self]
 [/disable]
But this doesn't work. I found out that it's just a matter of formula design. If I write

Code: Select all

formula="$metal_reserve1 < {NUMBER}"
everything works correctly. But if the variable consists of two variables (

Code: Select all

$metal_reserve$self.side
and the like) then Wesnoth starts giving errors and nothing works. Please help me get the double variable right.
I'm assuming for the sake of example here that {NUMBER} expands to 3.

The obvious issue that would cause this is probably that $self is not defined, which results in $self.side expanding to nothing, meaning the game is working with $metal_reserve| < 3, but $metal_reserve is also not defined (for obvious reasons) so it also expands to nothing, so the formula ends up looking like < 3, which is not a valid formula.

While you could use certainly use some debugging features to figure out why $self is undefined at the crucial moment, I think there's actually a better approach here. You can store variables in the side itself, like this:

Code: Select all

[modify_side]
	side=2
	[set_variable]
		name=metal_reserve
		value=5
	[/set_variable]
[/modify_side]
If you do that with different sides, each side will have its own personal value for that variable. So, instead of having variables $metal_reserve1, …, $metal_reserveN, each side has its own variable called $metal_reserve.

If you arrange things like that, then you can filter on the side's variable by loading the variable directly into the formula (instead of using variable substitution). I believe this will work:

Code: Select all

[disable]
	id=metal_cost{NUMBER}
	[filter_self]
		[filter_side]
			[not]
				formula="wml_vars.metal_reserve < {NUMBER}"
			[/not]
		[/filter_side]
	[/filter_self]
 [/disable]
 
(Actually, that general format will also work without the extra step of using side variables. For example:

Code: Select all

[disable]
	id=metal_cost{NUMBER}
	[filter_self]
		[not]
			formula="wml_vars.metal_reserve$self.side| < {NUMBER}"
		[/not]
	[/filter_self]
 [/disable]
 
Of course that still relies on $self being set though.)
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

Celtic_Minstrel wrote: February 27th, 2023, 2:58 am
I'm assuming for the sake of example here that {NUMBER} expands to 3.

The obvious issue that would cause this is probably that $self is not defined, which results in $self.side expanding to nothing, meaning the game is working with $metal_reserve| < 3, but $metal_reserve is also not defined (for obvious reasons) so it also expands to nothing, so the formula ends up looking like < 3, which is not a valid formula.

While you could use certainly use some debugging features to figure out why $self is undefined at the crucial moment, I think there's actually a better approach here. You can store variables in the side itself, like this:

Code: Select all

[modify_side]
	side=2
	[set_variable]
		name=metal_reserve
		value=5
	[/set_variable]
[/modify_side]
If you do that with different sides, each side will have its own personal value for that variable. So, instead of having variables $metal_reserve1, …, $metal_reserveN, each side has its own variable called $metal_reserve.

If you arrange things like that, then you can filter on the side's variable by loading the variable directly into the formula (instead of using variable substitution). I believe this will work:

Code: Select all

[disable]
	id=metal_cost{NUMBER}
	[filter_self]
		[filter_side]
			[not]
				formula="wml_vars.metal_reserve < {NUMBER}"
			[/not]
		[/filter_side]
	[/filter_self]
 [/disable]
 
(Actually, that general format will also work without the extra step of using side variables. For example:

Code: Select all

[disable]
	id=metal_cost{NUMBER}
	[filter_self]
		[not]
			formula="wml_vars.metal_reserve$self.side| < {NUMBER}"
		[/not]
	[/filter_self]
 [/disable]
 
Of course that still relies on $self being set though.)
Hi. Thanks for the reply. I started to try your suggestions, but ran into a problem. If I put the metal_reserve variable in the side, how do I subtract {NUMBER} from it at the end of the attack?

It used to look like this (and it worked): {VARIABLE_OP metal_reserve$unit.side sub {NUMBER}}

But it doesn't work like that now.
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Celtic_Minstrel
Developer
Posts: 2235
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Celtic_Minstrel »

You can put {VARIABLE_OP metal_reserve sub {NUMBER}} inside a [modify_side], much like in my example. Both the {VARIABLE_OP} and {VARIABLE} macros expand to a [set_variable] tag, so any of the three work in [modify_side]. (You can also use [clear_variable] and the macro equivalent. Unfortunately, [set_variables], with an S, does not currently work there.)

So basically, it looks like this:

Code: Select all

[modify_side]
	side=$unit.side
	{VARIABLE_OP metal_reserve sub {NUMBER}}
[/modify_side]
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

Celtic_Minstrel wrote: February 27th, 2023, 1:29 pm You can put {VARIABLE_OP metal_reserve sub {NUMBER}} inside a [modify_side], much like in my example. Both the {VARIABLE_OP} and {VARIABLE} macros expand to a [set_variable] tag, so any of the three work in [modify_side]. (You can also use [clear_variable] and the macro equivalent. Unfortunately, [set_variables], with an S, does not currently work there.)

So basically, it looks like this:

Code: Select all

[modify_side]
	side=$unit.side
	{VARIABLE_OP metal_reserve sub {NUMBER}}
[/modify_side]
I rewrote the code according to your suggestion for a variable inside the side. Now it works. I need to check a few more things before making sure everything works perfectly.

I've got one more question. I want to display floating text over a unit after an attack, this text should show the rest of the metal. But I don't know how to correctly write the side-embedded variable there. The normal $metal_reserve doesn't return anything.
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Mechanical
Posts: 347
Joined: June 29th, 2015, 4:11 pm
Location: Russia

Re: Formalizing variables in the WFL (need help!)

Post by Mechanical »

(gives nothing i mean)
My art thread
If you like my art, try The Great Steppe Era!
Also try my Rage (16+) drakes slasher campaign!
Join the Wesnoth Modders Guild community!
User avatar
Celtic_Minstrel
Developer
Posts: 2235
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Formalizing variables in the WFL (need help!)

Post by Celtic_Minstrel »

My understanding is that you would need to use [store_side], something like this:

Code: Select all

[store_side]
	side=$unit.side
	variable=my_side
[/store_side]
# then use $my_side.variables.metal_reserve instead of just $metal_reserve
I haven't tried this before so I'm not 100% certain. If you need it to work somewhere that's not an event (for example in objectives, or a menu item), it could be a little trickier.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply