Problems with [have_unit] on unit placed event

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

Problems with [have_unit] on unit placed event

Post by Nyanyanyan »

A while ago I made a mod to make the first non-loyal recruited unit into a leader, however it didn't quite work out. Now I'm trying to figure out what I did wrong and how I can get the intended functionality.


This should
1. Check if the recruited unit is loyal and on the currently active side
2. If there is no unit that can cannot recruit,
is on the current side
and is not the recruited unit,
make the recruited unit into a leader (and add some fluff).
However, none of this is happening. It just recruits the unit normally, not letting it recruit or give it any of the fluff.

Thanks in advance for any help.

Code: Select all

	
	[event]
		name=unit placed
		id=deputyrecruit
		first_time_only=no
		[filter]
			side=$side_number
			[not]
				upkeep=loyal
			[/not]
		[/filter]
		[if]
			[not]
				[have_unit]
					canrecruit=no
					[and]
					side=$side_number
					[/and]
					[and]
						[not]
							x,y=$x1,$y1
						[/not]
					[/and]
				[/have_unit]
			[/not]
		[and]
			[variable]
				name=deputybox
				boolean_equals=true
			[/variable]
		[/and]
		[then]
				[modify_unit]
					[filter]
                        x,y=$x1,$y1
					[/filter]
					canrecruit=yes
					[effect]
                        apply_to=status
                        add=general
					[/effect]
				[/modify_unit]
				[unit_overlay]
					x,y=$x1,$y1
					image=misc/leader-expendable.png
				[/unit_overlay]
		[/then]
		[/if]
		[/event]
		
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Problems with [have_unit] on unit placed event

Post by Nyanyanyan »

Upon further inspection, the filtering by loyal status seems to be causing the whole thing to not run.
This code, slightly shuffled around seems to work (except for the loyal status).

Code: Select all

	[event]
		name=unit placed
		id=deputyrecruit
		first_time_only=no
		[filter]
			side=$side_number
		[/filter]
		[if]
			[not]
				[have_unit]
					canrecruit=no
					[and]
					side=$side_number
					[/and]
					[and]
						[not]
							x,y=$x1,$y1
						[/not]
					[/and]
				[/have_unit]
			[/not]
		[and]
				[not]
		[have_unit]
			side=$side_number
			[and]
				[filter_wml]
					[status]
						general=yes
					[/status]
				[/filter_wml]
			[/and]
		[/have_unit]
		[/not]
		[/and]
		[and]
			[variable]
				name=deputybox
				boolean_equals=true
			[/variable]
		[/and]
		[then]
				[modify_unit]
					[filter]
                        x,y=$x1,$y1
					[/filter]
					canrecruit=yes
					[effect]
                        apply_to=status
                        add=general
					[/effect]
				[/modify_unit]
				[unit_overlay]
					x,y=$x1,$y1
					image=misc/leader-expendable.png
				[/unit_overlay]
		[/then]
		[/if]
		[/even]
		
To integrate the filtering of loyal units, I tried simply adding the loyal term to the [modify_unit] and [unit_overlay] tags, but the same results were shown in that simply nothing happens.
See this code:

Code: Select all

	[event]
		name=unit placed
		id=deputyrecruit
		first_time_only=no
		[filter]
			side=$side_number
		[/filter]
		[if]
			[not]
				[have_unit]
					canrecruit=no
					[and]
					side=$side_number
					[/and]
					[and]
						[not]
							x,y=$x1,$y1
						[/not]
					[/and]
				[/have_unit]
			[/not]
		[and]
				[not]
		[have_unit]
			side=$side_number
			[and]
				[filter_wml]
					[status]
						general=yes
					[/status]
				[/filter_wml]
			[/and]
		[/have_unit]
		[/not]
		[/and]
		[and]
			[variable]
				name=deputybox
				boolean_equals=true
			[/variable]
		[/and]
		[then]
				[modify_unit]
					[filter]
                        x,y=$x1,$y1
						[not]
						upkeep=loyal
						[/not]
					[/filter]
					canrecruit=yes
					[effect]
                        apply_to=status
                        add=general
					[/effect]
				[/modify_unit]
				[unit_overlay]
					x,y=$x1,$y1
						[not]
						upkeep=loyal
						[/not]
					image=misc/leader-expendable.png
				[/unit_overlay]
		[/then]
		[/if]
		[/even]
		
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Problems with [have_unit] on unit placed event

Post by WhiteWolf »

My first remark, but this is just for better readability: the 'and' condition is already implied when using an extra 'not' condition. So your

Code: Select all

... list-of-conditions
[and]
    [not]
    ... extra cond.
    [/not]
[/and]
can be written in the much simpler form of:

Code: Select all

... list-of-conditions
[not]
    ... extra cond.
[/not]

As for the issue - without testing anything, (so I'm just guessing from memory), I don't think that filtering for a loyal unit through its upkeep is correct. That key is used by wesnoth itself, and is generally not for the user to muck with. (cited from the wiki.)
If your loyal units are managed by the regular loyal trait, I think it would be better to filter for this trait instead. At least this is the first thing I'd check, to see if it solves the problem.
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: 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
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Problems with [have_unit] on unit placed event

Post by Nyanyanyan »

WhiteWolf wrote: October 10th, 2020, 4:06 pm My first remark, but this is just for better readability: the 'and' condition is already implied when using an extra 'not' condition. So your

Code: Select all

... list-of-conditions
[and]
    [not]
    ... extra cond.
    [/not]
[/and]
can be written in the much simpler form of:

Code: Select all

... list-of-conditions
[not]
    ... extra cond.
[/not]
I'm always confused on where to use [and] and where it's redundant.
Thanks for pointing that out.

The problem with filtering by trait is that the units simply do not have the loyal trait. I could go back in the code and give it to every unit in question, but that would create a lot of visual clutter or take one actual trait from the units if I were to simply create a loyal "musthave" trait in the unit_type.

The StandardUnitFilter wiki page (https://wiki.wesnoth.org/StandardUnitFilter) says that upkeep is something you can theoretically filter by, and I'd be surprised if that was too much for the game engine, considering what unholy stuff you can do with variables.
Last edited by WhiteWolf on October 10th, 2020, 8:04 pm, edited 3 times in total.
Reason: accidental edit -(ignore it)
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Problems with [have_unit] on unit placed event

Post by WhiteWolf »

Nyanyanyan wrote: October 10th, 2020, 7:15 pm The StandardUnitFilter wiki page (https://wiki.wesnoth.org/StandardUnitFilter) says that upkeep is something you can theoretically filter by, and I'd be surprised if that was too much for the game engine, considering what unholy stuff you can do with variables.
Do mind the 1.15.3+ note though, but I guess you checked that. It should indeed work then.

The problem with filtering by trait is that the units simply do not have the loyal trait.
How do you make your units loyal then, if not with a trait? Because if by a simple modify_unit call to directly modify upkeep, then that could easily lead to a problem like this (for reasons above - that key is used by the game and is not supposed to be modified directly).
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: 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
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Problems with [have_unit] on unit placed event

Post by Pilauli »

To make an invisible, musthave trait:

Give them three traits (num_traits=3 in unit type), and then write a version of "loyal" with availability=musthave and make the name just an empty string (name="").

That should make the unit have one invisible trait (loyal) and two regular traits.

In the versions I tested it on (an old 1.12 version, and the latest 1.15 version on Steam), this completely removes the trait from the displayed list; it doesn't even add any extra commas. But it definitely works, because it made the little loyal ring on top of the health bar. (If you want to hide that also, then of course, you can remove the overlay-modification line from your version of the loyal trait.)

Edit to clarify, just in case my previous statement wasn't clear: I mean this completely removes the trait from the displayed list of a unit's traits in the sidebar.
But it might not show up in the help menu, either; there already exist the traits {TRAIT_LOYAL}, {TRAIT_LOYAL_HERO}, and {TRAIT_LOYAL_HERO_NOSLOT}, but loyal only appears once in the help menu. My guess is that it only shows one (probably the first) trait with any given ID (e.g. "loyal") in the help menu, and ignores the rest.
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Problems with [have_unit] on unit placed event

Post by Celtic_Minstrel »

I would suggest trying upkeep=0 rather than upkeep=loyal. These are equivalent forms in a unit definition, but I'm not sure if they're both accepted in a filter.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Problems with [have_unit] on unit placed event

Post by Nyanyanyan »

WhiteWolf wrote: October 10th, 2020, 8:01 pm Do mind the 1.15.3+ note though, but I guess you checked that. It should indeed work then.
I did indeed not check that. Working on 1.14.x since that's what most people have, so yeah.
That's my error, thanks and sorry for wasting your time.

And I just put upkeep=loyal in the unit type, since I know this unit will only ever be spawned to be loyal.

Pilauli wrote: October 10th, 2020, 8:10 pm To make an invisible, musthave trait:

Give them three traits (num_traits=3 in unit type), and then write a version of "loyal" with availability=musthave and make the name just an empty string (name="").

That should make the unit have one invisible trait (loyal) and two regular traits.
Thanks, I'll try that.
Celtic_Minstrel wrote: October 11th, 2020, 2:45 pm I would suggest trying upkeep=0 rather than upkeep=loyal. These are equivalent forms in a unit definition, but I'm not sure if they're both accepted in a filter.
I just didn't register the 1.15.3+ note on the filter page, thanks for the help though.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Problems with [have_unit] on unit placed event

Post by Celtic_Minstrel »

Ah, I see. There is a second option but I'm not sure if it works, but it could be worth a try: formula="upkeep = 0"

I think that might've actually been a feature request though…

The third option is to use [filter_wml]:

Code: Select all

	[filter]
		side=$side_number
		[not]
			[filter_wml]
				upkeep=loyal # Or 0, not entirely sure which would be needed here
			[/filter_wml]
		[/not]
	[/filter]
Last edited by Celtic_Minstrel on October 11th, 2020, 3:18 pm, edited 1 time in total.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Problems with [have_unit] on unit placed event

Post by WhiteWolf »

Nyanyanyan wrote: October 11th, 2020, 3:08 pm
And I just put upkeep=loyal in the unit type, since I know this unit will only ever be spawned to be loyal.
In the wiki, upkeep is not even a listed key in unit type :) And placing it in [unit] at the creation is unreliable, as detailed above. Are you sure the supposed loyal units are correctly loyal, and stay loyal, even after multiple scenarios? You can check their actual upkeep cost in the inspection window.

The way to reliably make a unit type always loyal is indeed with an invisible musthave trait as detailed by Pilauli, or if you're really against that, another approach is to use a 'unit placed' event to give each appearing instance of the unit type an object with the loyal effect (apply_to=loyal).
Both methods can also be then filtered for in 1.14 just fine (as in the example in the above post).
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: 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
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Problems with [have_unit] on unit placed event

Post by Celtic_Minstrel »

Setting upkeep=loyal in the [unit] is probably safe, since it's not one of the values inherited from the unit type and thus probably wouldn't be overwritten when the unit advances. If you're worried though, you can use a modification instead:

Code: Select all

[unit]
	# other information on the unit
	[modifications]
		[object]
			[effect]
				apply_to=loyal
			[/effect]
		[/object]
	[/modifications]
[/unit]
As WhiteWolf says, I don't see any evidence that upkeep=loyal does anything when placed in the unit type, and I also checked the source code in addition to the wiki. If you want a specific unit type to be always loyal, the musthave trait is probably the correct way to do it.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: Problems with [have_unit] on unit placed event

Post by vghetto »

Not sure about that [status] general=yes thing and if it carries over on advancement.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: Problems with [have_unit] on unit placed event

Post by WhiteWolf »

Celtic_Minstrel wrote: October 11th, 2020, 3:48 pm Setting upkeep=loyal in the [unit] is probably safe,
My experience supports otherwise. I used to to make heroes loyal that way, so as not to take up trait spaces, but they lost their free upkeep and reverted to full at some later point - either at the end of the scenario, or when they levelled up, I can't recall anymore. But they didn't stay loyal, that's for sure. (these are 1.14.5 results though, could be that it was changes since then). But anyway, I've always stuck to the modification->object method in your example ever since, which I think is a lot more advisable.

vghetto wrote: October 11th, 2020, 6:52 pm Not sure about that [status] general=yes thing and if it carries over on advancement.
Custom statuses should be carried over just fine on advancements.
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: 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
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Problems with [have_unit] on unit placed event

Post by Celtic_Minstrel »

Yeah, I'm pretty sure the upkeep key is supposed to be kept on advancement, but maybe there's a bug in 1.14 that prevents it from working… either that or I'm just wrong. Still, the object method still avoids using up trait spaces and shouldn't have any issues ever, so yeah.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Problems with [have_unit] on unit placed event

Post by Nyanyanyan »

WhiteWolf wrote: October 11th, 2020, 3:25 pm In the wiki, upkeep is not even a listed key in unit type :) And placing it in [unit] at the creation is unreliable, as detailed above. Are you sure the supposed loyal units are correctly loyal, and stay loyal, even after multiple scenarios? You can check their actual upkeep cost in the inspection window.
Since these units are for an Era, it's more or less fine if they wouldn't stay loyal for a new scenario, but thanks for letting me know. I'm not a fan of the [unit_placed] since that'd cost processing resources which could be a problem for lower end PCs or phones, so I'm only using it if there really is absolutely no other way. I'll probably go with the invisible trait or come up with something else.
Celtic_Minstrel wrote: October 11th, 2020, 3:48 pm As WhiteWolf says, I don't see any evidence that upkeep=loyal does anything when placed in the unit type, and I also checked the source code in addition to the wiki. If you want a specific unit type to be always loyal, the musthave trait is probably the correct way to do it.
Hmm, I'll check if it actually works. Thanks for going the extra mile.

Code: Select all

[unit]
	# other information on the unit
	[modifications]
		[object]
			[effect]
				apply_to=loyal
			[/effect]
		[/object]
	[/modifications]
[/unit]
That seems like a good idea, will definitely try.
vghetto wrote: October 11th, 2020, 6:52 pm Not sure about that [status] general=yes thing and if it carries over on advancement.
That's just for filtering purposes and I'm pretty sure it does carry over, at least I haven't seen a situation in which it doesn't.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Post Reply