Help with creating sides

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
Atreides
Posts: 1075
Joined: March 30th, 2019, 10:38 pm
Location: On the 2nd story of the centre village of Merwuerdigliebe turning the lights on and off

Re: Help with creating sides

Post by Atreides »

Mr_Moist wrote: November 10th, 2023, 12:44 pm
Pentarctagon wrote: November 4th, 2023, 12:51 am
Mr_Moist wrote: November 4th, 2023, 12:24 am But this is the first scenario, what can I do for the list to change within the scenario at specific events? I want the player to be able to encounter someone on a specific location and then being able to recruit more different units. I should probably make a new thread for that right?
See https://wiki.wesnoth.org/DirectActionsW ... recruit.5D and the next couple tags following it.
Thank you so much! I didn't know there was such an easy way for that!
Programming rule #1: There is always an easier way and you will always discover it... afterwards.
Mr_Moist
Posts: 11
Joined: November 1st, 2023, 10:09 pm

Re: Help with creating sides

Post by Mr_Moist »

Spannerbag wrote: November 4th, 2023, 1:33 pm Hiya,

Edit: missed off last bit of post :doh:
Mr_Moist wrote: November 3rd, 2023, 2:29 pm Hi,
...While I know that "testvar" is just a placeholder for a name of a variable, I want to make sure I understand the "first" thing after the variable name. I would assume it is the value of the variable? If this is right, could I also write "$testvar" instead of the value? I ask this, because I want to have two events were something will be added to the variable, but I can't be sure which one would fire first if it even fired at all.
I will fix the errors about the spawning and then look into the log and also change the variable things.
Also thank you for the good wishes.
Just to clarify,

{VARIABLE.. is a core macro that comes with the game, the definition is:

Code: Select all

#define VARIABLE VAR VALUE
    # Macro to initialize a variable.  Strictly a syntatic shortcut.
    [set_variable]
        name={VAR}
        value={VALUE}
    [/set_variable]
#enddef
So it's just the same [set_variable] as you used, I'm just lazy :)



{VARIABLE testvar "first"}

Sets the value of the variable named testvar to the string "first".
So the value of testvar (i.e. $testvar) is now "first", though it could be anything you want; -99, 4.77 or "W1Bbl3".



{DEBUG_MSG (_"before: testvar=$testvar")}

This is just a lazy way of displaying the value of testvar :)
before.png



{VARIABLE testvar "$testvar|second"} # This appends "second" to $testvar's value

This sets testvar to "the present value" with the string "second" immediately bolted on.



{DEBUG_MSG (_"after: testvar=$testvar")}
after.png

Hope this helps/makes sense!

Cheers!
-- Spannerbag
Hello again,
first of all, thanks for the fast answer and sorry for the long wait for my answer. Now another thanks for the explaining, but I do have another question:
I want to add something to the recruiting list after a moveto event, I should be able to do that with the set_extra_recruit, right? But is that also possible with multiple events where something will be added to the recruiting list?
But anyway, even if that works, I still need the event to fire, and I think that doesn't happen: It should spawn a unit that then talks to my leader, afterwards you are supposed to be able to recruit more different units. But I can't seem to make it work, here is my code:

Code: Select all

[event]
	name=moveto
	[filter]
	x=29
	y=46
	[/filter]
	[unit]
		type=Elvish Ranger
		side=1
		x=28
		y=46
		id=Legolas
		gender=male
		name=Legolas
		unrenamable=yes
		upkeep=loyal
	[/unit]
	[message]
		speaker=Legolas
		message=_"Ich will euch in dem Kampf gegen diese Monster begleiten, ich werde eine große Hilfe sein!"
	[/message]
	[message]
		speaker=Friedhelm
		message=_"Großartig! Wir können jede Hilfe brauchen, ihr könnt uns bestimmt einige von euren Tricks zeigen?"
	[/message]
	[message]
		speaker=Legolas
		message=_"Aber natürlich!"
	[/message]
	[set_extra_recruit]
		extra_recruit=Elvish Fighter,Elvish Scout,Elvish Shaman
	[/set_extra_recruit]
[/event]
[event]
	name=moveto
	[filter]
		x=20
		y=49
	[/filter]
	[unit]
		type=Skeleton Archer
		side=1
		x=21
		y=49
		id=Arthur
		name=Arthur
		unrenamable=yes
		upkeep=loyal
	[/unit]
	[message]
		speaker=Arthur
		message=_"Diese Orks hatten mich getötet und ich will mich an ihnen rächen. Ich möchte euch helfen!"
	[/message]
	[message]
		speaker=Friedhelm
		message=_"Eine gruselige, aber willkomene Überraschung, natürlich könnt ihr uns beitreten!"
	[/message]
	[message]
		speaker=Arthur
		message=_"Vielen Dank, ich habe euch auch die Möglichkeit mitgebracht, andere Seelen, die elbenfalls eine offene Rechnung mit den Orks haben, ausbilden zu können."
	[/message]
	[set_extra_recruit]
		extra_recruit=Ghost,Skeleton,Walking Corpse,Dark Adept
	[/set_extra_recruit]
[/event]
Well I hope you aren't tired of helping me, but even if you are, thanks for your help up to this point.
User avatar
Atreides
Posts: 1075
Joined: March 30th, 2019, 10:38 pm
Location: On the 2nd story of the centre village of Merwuerdigliebe turning the lights on and off

Re: Help with creating sides

Post by Atreides »

Check out mainline campaign a tale of two brothers the chase scenario where you catch muff toras has exactly that where a iron mauler joins you and adds heavy inf to recruits. (I just played this so it came to mind )
User avatar
lhybrideur
Posts: 369
Joined: July 9th, 2019, 1:46 pm

Re: Help with creating sides

Post by lhybrideur »

Mr_Moist wrote: November 14th, 2023, 4:27 pm
I think the problem here is that [set_extra_recruit] is missing the unit filter to say who is able to recruit the extra units.
so

Code: Select all

	[set_extra_recruit]
		extra_recruit=Elvish Fighter,Elvish Scout,Elvish Shaman
	[/set_extra_recruit]
should be something like

Code: Select all

        [set_extra_recruit]
        	id=id_of_your_leader
		extra_recruit=Elvish Fighter,Elvish Scout,Elvish Shaman
	[/set_extra_recruit]
User avatar
Spannerbag
Posts: 537
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Help with creating sides

Post by Spannerbag »

Hi,
Mr_Moist wrote: November 14th, 2023, 4:27 pm

Code: Select all

[event]
	name=moveto
	[filter]
	x=29
	y=46
	[/filter]
I think this will fire when any unit happens to move to x,y=29,46.
To narrow down the options you'll at least need side=1 (assuming side 1 is the player's side) to restrict the unit(s) triggering this event to player units.
If you want only the leader(s) of side 1 to cause this event to fire then use:

Code: Select all

[event]
	name=moveto
	[filter]
        x,y=29,46
	side=1
        canrecruit=yes
       	[/filter]
Little hint on code optimisation (unless things have changed since I read about this): place the most restrictive filter condition first so the remaining filter conditions have fewer units to test (as I understand it after each filter component a list of units is stored and these are tested by the next filter component and so on).
Here the most restrictive condition is x,y= as this limits the filter to 1 unit at x,y=29,46 so subsequent tests can be in any order.

If side 1 has only one leader (or you want only one specific leader amongst 2+) to fire the event then you can use:

Code: Select all

[event]
	name=moveto
	[filter]
        x,y=29,46
	side=1
        id=leader_id
       	[/filter]
Mr_Moist wrote: November 14th, 2023, 4:27 pm

Code: Select all

	[unit]
		type=Elvish Ranger
		side=1
		x=28
		y=46
		id=Legolas
		gender=male
		name=Legolas
		unrenamable=yes
		upkeep=loyal
	[/unit]
If you want to draw attention to this unit you can add animate=yes and the unit will appear using the recruit/recall animation.
Just a thought :-)
Mr_Moist wrote: November 14th, 2023, 4:27 pm

Code: Select all

	[set_extra_recruit]
		extra_recruit=Elvish Fighter,Elvish Scout,Elvish Shaman
	[/set_extra_recruit]
lhybrideur has already explained that you're missing which leader(s) can recruit these unit(s).
Just to make it clear that a leader has two recruit lists;
  1. The side recruit list specified by recruit= and modified by allow_recruit and disallow_recruit
    (all leaders on this side are able to recruit these units)
  2. The leader's "personal" recruit list specified by allow_extra_recruit and disallow_extra_recruit
Leaders can recruit any unit type that appears in either list.

Mr_Moist wrote: November 14th, 2023, 4:27 pm Well I hope you aren't tired of helping me, but even if you are, thanks for your help up to this point.
You're welcome, hope the above is useful :)

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
Ravana
Forum Moderator
Posts: 3018
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Help with creating sides

Post by Ravana »

Spannerbag wrote: November 15th, 2023, 11:04 pm Little hint on code optimisation (unless things have changed since I read about this): place the most restrictive filter condition first so the remaining filter conditions have fewer units to test (as I understand it after each filter component a list of units is stored and these are tested by the next filter component and so on).
Here the most restrictive condition is x,y= as this limits the filter to 1 unit at x,y=29,46 so subsequent tests can be in any order.

If side 1 has only one leader (or you want only one specific leader amongst 2+) to fire the event then you can use:

Code: Select all

[event]
	name=moveto
	[filter]
        x,y=29,46
	side=1
        id=leader_id
       	[/filter]
WML keys are not preserved as how they are in your source file, so x,y,side=29,46,1 is equal to side,x,y=1,29,46. In order to have difference the conditions need to be in separate tags, even [and] might work. Because tags are ordered - if there are multiple [and], then code can ask them by index. Some representations of WML sort keys alphabetically.

The code that uses keys of WML tag might take them in specific order, for example you can check how [set_variable] is implemented in Lua. Internal code supporting filter might do similar. It is just not affected by whether you put side or location or something else first.

And there is the general idea of premature optimizations.
User avatar
Spannerbag
Posts: 537
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Help with creating sides

Post by Spannerbag »

Hi,
Ravana wrote: November 16th, 2023, 12:00 am
Spannerbag wrote: November 15th, 2023, 11:04 pm Little hint on code optimisation (unless things have changed since I read about this): place the most restrictive filter condition first so the remaining filter conditions have fewer units to test (as I understand it after each filter component a list of units is stored and these are tested by the next filter component and so on).
Here the most restrictive condition is x,y= as this limits the filter to 1 unit at x,y=29,46 so subsequent tests can be in any order.

If side 1 has only one leader (or you want only one specific leader amongst 2+) to fire the event then you can use:

Code: Select all

[event]
	name=moveto
	[filter]
        x,y=29,46
	side=1
        id=leader_id
       	[/filter]
WML keys are not preserved as how they are in your source file, so x,y,side=29,46,1 is equal to side,x,y=1,29,46. In order to have difference the conditions need to be in separate tags, even [and] might work. Because tags are ordered - if there are multiple [and], then code can ask them by index. Some representations of WML sort keys alphabetically.

The code that uses keys of WML tag might take them in specific order, for example you can check how [set_variable] is implemented in Lua. Internal code supporting filter might do similar. It is just not affected by whether you put side or location or something else first.

And there is the general idea of premature optimizations.
Fair enough, but I got the idea from https://wiki.wesnoth.org/FilterWML/Examples_-_How_to_use_Filter#Ordering_and_writing which has I think changed since when I last read it in-depth (years ago).
The section does begin by saying:
It’s very important to note that evaluation order of top level conditions (those not embedded in and/or/not tags) is unspecified, which means your code shouldn’t rely on it. On the contrary, and/or/not tags are always executed last, in the order they are written.
Which is new to me, but further down it says this, which is the bit I remember:
⇒ Performance. Most of the time, performance is not an issue. But it can be if you have a lot of units and use [filter_wml]. More generally, it’s good programming practice to execute the more restrictive test first. Consider this example:

[filter]
race=orc
x,y=16,22
[/filter]

The first condition will be evaluated on all units. But the second one will be evaluated on all orcs. If instead we write:

[filter]
x,y=16,22
race=orc
[/filter]

obviously, the second condition will be evaluated once at most, and filtering will be faster. (Strictly speaking, I should have wrapped the second condition in an and tag to force evaluation order). Remember too that logical operators (and, or, not) are not mandatory, but are allowed. So one can use them for clarity's sake, or to force an evaluation order. It’s particularly important when using or tags.
I would find it helpful if the wiki explained either when tests can be ordered to improve performance (i.e. the example above should include [filter_wml] if omitting that negates the performance boost) or removes this performance note entirely if it's no longer (ever was?) relevant.
Of course it may also be that I've completely misunderstood what the wiki is saying, in which case I'd appreciate some clarification for my little brain :)

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
Ravana
Forum Moderator
Posts: 3018
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Help with creating sides

Post by Ravana »

The red sentence is meant in theory. Next sentence says that without [and] it does not actually change what happens. To be fair, to further optimize you could even put x and y in separate [and] based on which coordinate is expected to have less units.

If you do not have performance issues then do not focus on filter evaluation order. Avoid unneeded [filter_wml] but even if you need to use it, its ok unless you see real issues during game.
gnombat
Posts: 710
Joined: June 10th, 2010, 8:49 pm

Re: Help with creating sides

Post by gnombat »

Spannerbag wrote: November 16th, 2023, 12:04 pm I would find it helpful if the wiki explained either when tests can be ordered to improve performance (i.e. the example above should include [filter_wml] if omitting that negates the performance boost) or removes this performance note entirely if it's no longer (ever was?) relevant.
I agree that the example code should be rewritten. But it just needs an [and] tag, not [filter_wml].
Ravana wrote: November 16th, 2023, 1:21 pm The red sentence is meant in theory. Next sentence says that without [and] it does not actually change what happens.
It seems like the author was trying to explain the concept of improving performance while at the same time illustrating a possible pitfall, but the result is rather confusing.
Mr_Moist
Posts: 11
Joined: November 1st, 2023, 10:09 pm

Re: Help with creating sides

Post by Mr_Moist »

Hello everyone, thanks for all your help and advice, but I have now found the problem: the moveto event event was outside of the scenario tag.
But now I have another question :augh: : I want to have two events that give you extra recruit, but if one fires and then the other one fires, the first extra recruit gets overwritten by the second one.
Currently it looks like this:

Code: Select all

	[event]
		name=moveto
		[filter]
		side=1
		x=29
		y=46
		[/filter]
		[unit]
			type=Elvish Ranger
			side=1
			x=28
			y=46
			id=Legolas
			gender=male
			name=Legolas
			unrenamable=yes
			upkeep=loyal
			animation=yes
		[/unit]
		[message]
			speaker=Legolas
			message=_"Ich will euch in dem Kampf gegen diese Monster begleiten, ich werde eine große Hilfe sein!"
		[/message]
		[message]
			speaker=Friedhelm
			message=_"Großartig! Wir können jede Hilfe brauchen, ihr könnt uns bestimmt einige von euren Tricks zeigen?"
		[/message]
		[message]
			speaker=Legolas
			message=_"Aber natürlich!"
		[/message]
		[set_extra_recruit]
			id=Friedhelm
			extra_recruit=Elvish Fighter,Elvish Scout,Elvish Shaman
		[/set_extra_recruit]
	[/event]
	[event]
		name=moveto
		[filter]
			side=1
			x=20
			y=49
		[/filter]
		[unit]
			type=Skeleton Archer
			side=1
			x=21
			y=49
			id=Arthur
			name=Arthur
			unrenamable=yes
			upkeep=loyal
			animation=yes
		[/unit]
		[message]
			speaker=Arthur
			message=_"Diese Orks hatten mich getötet und ich will mich an ihnen rächen. Ich möchte euch helfen!"
		[/message]
		[message]
			speaker=Friedhelm
			message=_"Eine gruselige, aber willkomene Überraschung, natürlich könnt ihr uns beitreten!"
		[/message]
		[message]
			speaker=Arthur
			message=_"Vielen Dank, ich habe euch auch die Möglichkeit mitgebracht, andere Seelen, die elbenfalls eine offene Rechnung mit den Orks haben, ausbilden zu können."
		[/message]
		[set_extra_recruit]
			id=Friedhelm
			extra_recruit=Ghost,Skeleton,Walking Corpse,Dark Adept
		[/set_extra_recruit]
	[/event]
[/scenario]
Mr_Moist
Posts: 11
Joined: November 1st, 2023, 10:09 pm

Re: Help with creating sides

Post by Mr_Moist »

I just had the idea that I could use extra recruit for one event and recruit for the other event. Would that work, and if yes would there be another way and if not... why?
Mr_Moist
Posts: 11
Joined: November 1st, 2023, 10:09 pm

Re: Help with creating sides

Post by Mr_Moist »

I just tried the idea I previously had and it works! Thank you to everyone for helping me to get this far!
User avatar
lhybrideur
Posts: 369
Joined: July 9th, 2019, 1:46 pm

Re: Help with creating sides

Post by lhybrideur »

The solution to your problem is that you should use allow_extra_recruit instead of set_extra_recruit. Their name explain the reason why.
User avatar
Celtic_Minstrel
Developer
Posts: 2241
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Help with creating sides

Post by Celtic_Minstrel »

Spannerbag wrote: November 16th, 2023, 12:04 pm Fair enough, but I got the idea from https://wiki.wesnoth.org/FilterWML/Examples_-_How_to_use_Filter#Ordering_and_writing which has I think changed since when I last read it in-depth (years ago).
The section does begin by saying:
It’s very important to note that evaluation order of top level conditions (those not embedded in and/or/not tags) is unspecified, which means your code shouldn’t rely on it. On the contrary, and/or/not tags are always executed last, in the order they are written.
Which is new to me, but further down it says this, which is the bit I remember:
⇒ Performance. Most of the time, performance is not an issue. But it can be if you have a lot of units and use [filter_wml]. More generally, it’s good programming practice to execute the more restrictive test first. Consider this example:

[filter]
race=orc
x,y=16,22
[/filter]

The first condition will be evaluated on all units. But the second one will be evaluated on all orcs. If instead we write:

[filter]
x,y=16,22
race=orc
[/filter]

obviously, the second condition will be evaluated once at most, and filtering will be faster. (Strictly speaking, I should have wrapped the second condition in an and tag to force evaluation order). Remember too that logical operators (and, or, not) are not mandatory, but are allowed. So one can use them for clarity's sake, or to force an evaluation order. It’s particularly important when using or tags.
I would find it helpful if the wiki explained either when tests can be ordered to improve performance (i.e. the example above should include [filter_wml] if omitting that negates the performance boost) or removes this performance note entirely if it's no longer (ever was?) relevant.
Of course it may also be that I've completely misunderstood what the wiki is saying, in which case I'd appreciate some clarification for my little brain :)
I'm not completely certain, but I believe that this discussion of optimizing filters is almost entirely obsolete. (It's also confusingly phrased, which doesn't really help.) My understanding is that the game sees that the filter contains the x,y keys before it evaluates anything else and automatically just checks to see if the unit on that space matches the remainder of the filter. It also has similar handling for a few other keys that can drastically narrow the search area.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply