Xalzar's WML Headaches

The place to post your WML questions and answers.

Moderators: Forum Moderators, Developers

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

Re: Xalzar's WML Headaches

Post by Ravana » June 11th, 2019, 9:25 pm

I believe it is possible to use it with

Code: Select all

[event]
  first_time_only=no
  name=preload
  [lua]
    code=<<
function wesnoth.wml_conditionals.is_ai()
  return wesnoth.synchronize_choice(
  function()
    return false
  end,
  function()
    return true
  end)
end
>>
  [/lua]
[/event]
And then in your [if] or [filter_condition] have [is_ai][/is_ai]

But not able to test now, going to sleep.

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 11th, 2019, 9:33 pm

Ravana wrote:
June 11th, 2019, 9:25 pm
But not able to test now, going to sleep.
Thanks again, I'll try it! Good night! ;)

User avatar
octalot
Code Contributor
Posts: 303
Joined: July 17th, 2010, 7:40 pm

Re: Xalzar's WML Headaches

Post by octalot » June 11th, 2019, 10:23 pm

Those functions need to return tables, so return { value = false }. Thanks for posting the pointers, I need the same logic in my code and was wondering how to do it.

The version below sets a variable that's accessible to WML instead of adding an [is_ai] tag. Haven't tested in multiplayer yet, but I'll also post the code and find out in the morning if it worked ;)

Code: Select all

[event]
    name=side turn
    first_time_only=no
    {VARIABLE additional_upkeep 0}
    # omitted - code counting the number of units that the Non-Fatal Wounds mod has saved
    [lua]
        # wesnoth.synchronize_choice itself takes two functions as arguments, and chooses which one to run based on whether it's an AI player
        code=<<
            wesnoth.set_variable ("is_ai",
                wesnoth.synchronize_choice(
                    function()
                        return { value = false }
                    end,
                    function()
                        return { value = true }
                    end
                )
            )
        >>
    [/lua]
    [message]
        speaker=narrator
        message=_"Upkeep for wounded units on side $side_number is $additional_upkeep (and the AI flag is true)"
        [show_if]
            [variable]
                name=is_ai[0].value
                boolean_equals=true
            [/variable]
        [/show_if]
    [/message]
    [message]
        speaker=narrator
        message=_"Upkeep for wounded units on side $side_number is $additional_upkeep (and the AI flag is false)"
        [show_if]
            [variable]
                name=is_ai[0].value
                boolean_equals=false
            [/variable]
        [/show_if]
    [/message]
[/event]

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 11th, 2019, 10:55 pm

Sadly both codes gave me errors (bad argument #1 to 'set_variable_local' (empty variable name)).

Posting part of my code so you can tell me if it's because of a mistake on my part.
@Ravana's

Code: Select all

[event]
		name=recruit
		id=modrecruit
		first_time_only=no
		[lua]
    code=<<
function wesnoth.wml_conditionals.is_ai()
  return wesnoth.synchronize_choice(
  function()
    return false
  end,
  function()
    return true
  end)
end
>>
  [/lua]
  [filter_condition]
			[is_ai]
			[/is_ai]
		[/filter_condition]
		[store_gold]
			side=$unit.side
			variable=budget
		[/store_gold]
		[gold]
			amount=$unit.cost
			side=$unit.side
		[/gold]
		[set_variable]
			name=recruitcost
			value=$unit.cost
		[/set_variable]
		[fire_event]
			id=40k_modweapons
		[/fire_event]
	[/event]
	[event]
		name=unit_recruited
		id=40k_modweapons
		first_time_only=no
		[message]
			id=$unit.id
			image="$unit.image"
			speaker=narrator
			message= _ "REDACTED"
			[option]
			...
			[/option]
		[/message]
	[/event]
@Octalot's:

Code: Select all

[event]
		name=recruit
		id=modrecruit
		first_time_only=no
		 [lua]
        # wesnoth.synchronize_choice itself takes two functions as arguments, and chooses which one to run based on whether it's an AI player
        code=<<
            wesnoth.set_variable ("is_ai",
                wesnoth.synchronize_choice(
                    function()
                        return { value = false }
                    end,
                    function()
                        return { value = true }
                    end
                )
            )
        >>
    [/lua]
		[store_gold]
			side=$unit.side
			variable=budget
		[/store_gold]
		[gold]
			amount=$unit.cost
			side=$unit.side
		[/gold]
		[set_variable]
			name=recruitcost
			value=$unit.cost
		[/set_variable]
		[fire_event]
			id=40k_modweapons
		[/fire_event]
	[/event]
	[event]
		name=unit_recruited
		id=40k_modweapons
		first_time_only=no
		[message]
			id=$unit.id
			image="$unit.image"
			speaker=narrator
			message= _ "REDACTED"
			[show_if]
				[variable]
					name=is_ai[0].value
					boolean_equals=false
				[/variable]
			[/show_if]
			[option]
			...
			[/option]
		[/message]
	[/event]
Before you ask, yes, I need to split the custom event from the first, because I need it to fire it as an action too and not only on recruit. :roll:

User avatar
Ravana
Moderator
Posts: 2060
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Xalzar's WML Headaches

Post by Ravana » June 11th, 2019, 11:04 pm

Preload event is important.

If said it needs table, returns would be

function wesnoth.wml_conditionals.is_ai()
return wesnoth.synchronize_choice(
function()
return {value=false}
end,
function()
return {value=true}
end).value
end

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 11th, 2019, 11:12 pm

Ravana wrote:
June 11th, 2019, 11:04 pm
Preload event is important.
Aaah ok, I misunderstood. I'll try it.

Also, I'm sorry but please you both disregard for the moment my previous post. I'm a bit sleepy and I've probably introduced an error somewhere else :oops: (I've got an idea of where), so I'll revise your code tomorrow with a clear mind.

User avatar
Ravana
Moderator
Posts: 2060
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Xalzar's WML Headaches

Post by Ravana » June 12th, 2019, 5:56 pm

I tried it out in debug, it only works for sides that start out as ai - and 1.14 does not allow undroiding such sides. If you droid side, it is still treated as human.

Code used for testing (:debug, then lua console)

Code: Select all

function wesnoth.wml_conditionals.is_ai()
return wesnoth.synchronize_choice(
function()
return {value=false}
end,
function()
return {value=true}
end).value
end

wesnoth.wml_actions.event{
	name="side turn",
	first_time_only=false,
	{"lua", {code="wesnoth.message(wesnoth.wml_conditionals.is_ai())"}}
}

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 12th, 2019, 9:46 pm

Thanks, it seems I have encountered an unexpected roadblock. :(
I'll try to think of some workaround, for now the only thing I can think of is trying to add wait_description to the message, but even if it works it's not elegant. :hmm:
And even then, the AI needs to have events reserved for it, for setting the recruitment criteria - so the problem is still there.
Maybe I should have kept insisting with AMLAs instead of switching to [message] after all...

(Or I should write a disclaimer: do not droid sides, use AIs only if set up in pre-game?) :hmm:

Edit: tried you code, Ravana, it does not work for me. I've inserted it in a preload event (inside a unit, does this change anything?), gives error "macro/file 'value=false' is missing".
I cannot understand anything about this kind of code, and I don't want you to do my work for me, so maybe I need to take a little pause and think about how to proceed.

Also, I've noticed you added this discussion to the SideWML page, lol| :lol:Let's hope something good will come out off of this topic but I'm afraid I cannot be of much help to create a functioning Lua code.

User avatar
octalot
Code Contributor
Posts: 303
Joined: July 17th, 2010, 7:40 pm

Re: Xalzar's WML Headaches

Post by octalot » June 12th, 2019, 10:21 pm

Xalzar wrote:
June 12th, 2019, 9:46 pm
error "macro/file 'value=false' is missing".
That error means the WML preprocessor is trying to process the Lua code. If you're putting Lua in a WML file, put << at the start and >> at the end to fix it.
Xalzar wrote:
June 12th, 2019, 9:46 pm
Also, I've noticed you added this discussion to the SideWML page, lol| :lol:Let's hope something good will come out off of this topic but I'm afraid I cannot be of much help to create a functioning Lua code.
That was me :D I knew I'd read somewhere on the Wiki that it didn't work in multiplayer, but I couldn't find it again until you added the link to StandardSideFilter.

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 12th, 2019, 10:32 pm

octalot wrote:
June 12th, 2019, 10:21 pm
That error means the WML preprocessor is trying to process the Lua code. If you're putting Lua in a WML file, put << at the start and >> at the end to fix it.
Of course! :doh: Please do not take anything for granted, I don't know anything about Lua. Now the error says something like (translated from my language, the exact wording may change in other versions): "unexpected characters at the beginning of the line", referring undoubtedly to the aforementioned << >>. :(
octalot wrote:
June 12th, 2019, 10:21 pm
That was me :D I knew I'd read somewhere on the Wiki that it didn't work in multiplayer, but I couldn't find it again until you added the link to StandardSideFilter.
Ah! :D

Edit: I've found some answers in the LuaWML page, I needed to add "code=" before all the lua code. :doh: See? I'm a complete n00b. :doh: Now at least it does not produce errors while loading. :roll:

Edit2: After adding the [show_if] in the recruit event, an error in-game was saying that [is_ai] is not valid (I had my doubts already since it was coming out of nowhere, WML-side speaking). Therefore I semi-improvised and I wrapped it in a [lua] tag: no error! But no event even for the human side. Tried wrapping [lua] in a [not], now both human and AI sides trigger the event. We returned to the start point. :lol:

User avatar
Ravana
Moderator
Posts: 2060
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Xalzar's WML Headaches

Post by Ravana » June 12th, 2019, 11:08 pm

wesnoth.wml_conditionals is special - if you add functions to it, they become available to wml. So wesnoth.wml_conditionals.is_ai() defines condition tag [is_ai].

Preload event fires each time game is started, including reloaded. It is used to set up lua variables and functions, since unlike wml variables they are not part of save file. So defining function wesnoth.wml_conditionals.is_ai() in preload event means it is always available.

User avatar
octalot
Code Contributor
Posts: 303
Joined: July 17th, 2010, 7:40 pm

Re: Xalzar's WML Headaches

Post by octalot » June 12th, 2019, 11:35 pm

We're mixing multiple languages together, and using insufficiently-documented features - I certainly wouldn't call you a n00b.

(Ravana has already posted the rest of the message that I was going to post.)

User avatar
Ravana
Moderator
Posts: 2060
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Xalzar's WML Headaches

Post by Ravana » June 13th, 2019, 4:56 am

Unit events are only added when unit is placed on map, and preload happens before map is loaded, so yes, it should be scenario/era/modification event.

User avatar
Xalzar
Posts: 268
Joined: April 4th, 2009, 10:03 pm
Location: New Saurgrath

Re: Xalzar's WML Headaches

Post by Xalzar » June 13th, 2019, 9:29 am

Ravana wrote:
June 13th, 2019, 4:56 am
Unit events are only added when unit is placed on map, and preload happens before map is loaded, so yes, it should be scenario/era/modification event.
Since I'm no expert in those, I've tried to avoid [modification]s, but now it's the time to use them. In the end, they're simpler than I thought.
This new code:

Code: Select all

[modification]
    id=recruit_mod
    name=_"Recruit Modifications Mod"
    description= _ "All units can be modified during recruitment."
	require_modification=no
	allow_era=REDACTED
	[event]
		first_time_only=no
		name=preload
		[lua]
		code= <<
		function wesnoth.wml_conditionals.is_ai()
		return wesnoth.synchronize_choice(
		function()
		return {value=false}
		end,
		function()
		return {value=true}
		end).value
		end

		wesnoth.wml_actions.event{
			name="side turn",
			first_time_only=false,
			{"lua", {code="wesnoth.message(wesnoth.wml_conditionals.is_ai())"}}
		}
		>>
		[/lua]
	[/event]
	[event]
		name=recruit
		id=xrecruit
		first_time_only=no
		[filter_condition]
			[not]
				[lua]
					[is_ai]
					[/is_ai]
				[/lua]
			[/not]
		[/filter_condition]
		[store_gold]
			side=$unit.side
			variable=budget
		[/store_gold]
		[gold]
			amount=$unit.cost
			side=$unit.side
		[/gold]
		[set_variable]
			name=recruitcost
			value=$unit.cost
		[/set_variable]
		[fire_event]
			id=modweapons
		[/fire_event]
	[/event]
	[event]
		name=unit_recruited
		id=modweapons
		first_time_only=no
		[message]
			id=$unit.id
			image="$unit.image"
			speaker=narrator
			message= _ "Unit Modifications: Weapons"
			#[show_if]
			#[/show_if]
			[option]
			...
			[/option]
		[/message]
	[/event]
[/modification]
	
Aaaand...nope!
Xalzar wrote:
June 12th, 2019, 10:32 pm
But no event even for the human side. Tried wrapping [lua] in a [not], now both human and AI sides trigger the event. We returned to the start point. :lol:
Same thing! This [is_ai] seems to not discriminate between human and ai sides (yes, I've set one side as ai during the pre-match phase, did not use "droid" command).
Maybe I should try to add that condition inside those #ed [show_if]s too? :hmm:

Edit: what about this? I know that is included in the code we are testing already, but it seems to me that in that example it is used a bit differently... Could taking from that help me?
Otherwise, I'm coming up with a workaround, surprisingly WML-based! It should be simple albeit of course a bit unelegant.

Edit2: new version of the code! Now with Lua messages in-game ("No" and "Yes" which means it works a bit!), and the same final results as before! :lol:
Last edited by Xalzar on June 13th, 2019, 2:22 pm, edited 1 time in total.

User avatar
Pentarctagon
Forum Administrator
Posts: 3872
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Xalzar's WML Headaches

Post by Pentarctagon » June 13th, 2019, 1:41 pm

Does the code attribute work placed directly in [event] like that?
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code

Post Reply