Random Unit Dialogue

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.
Post Reply
User avatar
ResExsention
Posts: 97
Joined: March 17th, 2018, 12:00 am
Location: Alberta, Canada

Random Unit Dialogue

Post by ResExsention » July 24th, 2018, 2:29 am

Hello!

We all know the power of the [message] tag. From what I know, every campaign seems to have at least a few of it. So quite clearly it's a powerful tag.
[message], when invoked, receives a standard unit filter to filter out who speaks and who doesn't. This post circulates about that unit filter.

So, with the filter, you can sort out units by ID, by type, by location, by race... But how about sorting out random units from a particular side? After reading through a topic I found deep within the forums, I tried this:

Code: Select all

[message]
	side=# Whatever side e.g. side=1
	message="Hi there. I am a wesnothian genius. And I'm trying to figure out how to make units say things randomly.  :D "
[/message]
Well, not randomly, but to make a random unit from a specific side say such a thing. So I tried this out, and found that it didn't deliver the expected result.

Every time I called on this kind of filter with [message], it was like calling on the leader of that particular side to speak. In illustration, if side 5 had a leader named A, and four soldiers named B, C, D, and E, respectively, if I went like this:

Code: Select all

[message]
	side=5
	message="Let's go find somebody to help me out here! "
[/message]
Only A would say it. If I called it again, however, A would say it again. No matter how many times I would have called this tag, still, only A (the leader of side 5) would say whatever was in message=. So that's not really making a random unit say something.

So how would you do it? I couldn't find anything in the [message] reference in the WML reference, so could I please have some help here?
I am a ranger and my WML knives will implant themselves in your back.

Creator of the abandoned campaign Royalties Forgotten and the work in progress campaign Purger of Evil.
Maintainer of Fate of a Princess.

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

Re: Random Unit Dialogue

Post by Pentarctagon » July 24th, 2018, 5:13 am

You would use the speaker attribute.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code

User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Re: Random Unit Dialogue

Post by zookeeper » July 24th, 2018, 7:57 am

There's currently no simple way to choose a random unit in a situation like that. You'd have to store all units, pick a random index, and then filter by the id or location of the stored unit in that index.

It would be convenient if SUF allowed a key such as random_selection=4 which would cause only 4 randomly selected units out of all the matching units to actually end up matching. But whether there are technical reasons why that wouldn't work out well, I'm not sure.

EDIT: Alternatively, perhaps one could write a lua_function= filter function that would choose a random unit out of all the matching ones every time. Not sure if it's possible in the first place, but that'd be reasonably advanced anyway.
Pentarctagon wrote:
July 24th, 2018, 5:13 am
You would use the speaker attribute.
That... doesn't make it any more random.

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

Re: Random Unit Dialogue

Post by Pentarctagon » July 24th, 2018, 8:04 am

zookeeper wrote:
July 24th, 2018, 7:57 am
Pentarctagon wrote:
July 24th, 2018, 5:13 am
You would use the speaker attribute.
That... doesn't make it any more random.
It is what he'd need to use to have a particular unit speak though, rather than defaulting to the leader.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code

User avatar
zookeeper
WML Wizard
Posts: 9739
Joined: September 11th, 2004, 10:40 pm
Location: Finland

Re: Random Unit Dialogue

Post by zookeeper » July 24th, 2018, 9:36 am

It seems like one can't do it with a lua_function=, but this does seems to work:

Code: Select all

        [lua]
            code = <<
                function wesnoth.wml_actions.random_message(cfg)
                    local new_cfg = cfg.__literal

                    local matching_units = wesnoth.get_units(cfg)
                    local random_unit_id = matching_units[math.random(#matching_units)].id

                    table.insert(new_cfg, { "and", { id=random_unit_id } })

                    wesnoth.fire("message", new_cfg)
                end
            >>
        [/lua]

        [random_message]
            side=1
            message="random speaker 1 here!"
        [/random_message]
        [random_message]
            side=1
            message="random speaker 2 here!"
        [/random_message]
        [random_message]
            side=1
            message="random speaker 3 here!"
        [/random_message]
In other words, unless I'm missing something, the [random_message] tag works exactly like [message] except it picks a random speaker from all those who match the filter (in the example, from amongst all side 1 units). I'm sure it'd be possible to alter this so that it'd simply add a new randomness-controlling key to [message], too.

One could also add some way of preventing the same unit from getting picked twice in a row, or even more elaborate controls.

User avatar
ResExsention
Posts: 97
Joined: March 17th, 2018, 12:00 am
Location: Alberta, Canada

Re: Random Unit Dialogue

Post by ResExsention » July 24th, 2018, 8:19 pm

Thank you all for all the input, but it seems like zookeeper's solution is the best. I have incorporated it into a macro for one of my campaigns. Thank you. If I figure out how to make this truly random, I will, but zookeeper has given me a start.

:D
I am a ranger and my WML knives will implant themselves in your back.

Creator of the abandoned campaign Royalties Forgotten and the work in progress campaign Purger of Evil.
Maintainer of Fate of a Princess.

User avatar
Celtic_Minstrel
Developer
Posts: 1274
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: Random Unit Dialogue

Post by Celtic_Minstrel » August 5th, 2018, 8:00 pm

The reason your first version doesn't work is because the [message] will always choose the "first" unit that matches the provided filter. Since the leader is (almost) always the first unit spawned for its side, using side=x will always yield the leader.

The proper way to use zookeeper's example is to put the [lua] tag (with its contents, of course) at toplevel in your _main.cfg (but make sure it's below the #ifdef YOUR_CAMPAIGN line). Then you can just use [random_message] wherever you want. There's no need for any macros.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

User avatar
ResExsention
Posts: 97
Joined: March 17th, 2018, 12:00 am
Location: Alberta, Canada

Re: Random Unit Dialogue

Post by ResExsention » August 11th, 2018, 7:27 pm

Yeah, but macros are my besties when I make UMC, plus, it is kind of a little bit too late for putting it in _main.cfg; I don't really want to change it now that it's there and working. Thanks for the pointer, though.
I am a ranger and my WML knives will implant themselves in your back.

Creator of the abandoned campaign Royalties Forgotten and the work in progress campaign Purger of Evil.
Maintainer of Fate of a Princess.

User avatar
Celtic_Minstrel
Developer
Posts: 1274
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: Random Unit Dialogue

Post by Celtic_Minstrel » August 11th, 2018, 7:54 pm

The thing is that the [lua] tag only needs to run once in this case. Putting it in the macro is silly and wastefully redefines the tag every time it's called. This represents a theoretical performance hit (the Lua engine needs compile that code and then run it to define the function, every time you show a message), though in the specific case of showing a message I'm sure it wouldn't be noticeable.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

User avatar
ResExsention
Posts: 97
Joined: March 17th, 2018, 12:00 am
Location: Alberta, Canada

Re: Random Unit Dialogue

Post by ResExsention » August 14th, 2018, 5:41 pm

Which is kind of sad. It slightly uses up more of the CPU's power, constantly recompiling and all that, but even on the weakest of computers, it's alright. I'll keep that in mind, though, for any other lua I use.
I am a ranger and my WML knives will implant themselves in your back.

Creator of the abandoned campaign Royalties Forgotten and the work in progress campaign Purger of Evil.
Maintainer of Fate of a Princess.

User avatar
Celtic_Minstrel
Developer
Posts: 1274
Joined: August 3rd, 2012, 11:26 pm
Contact:

Re: Random Unit Dialogue

Post by Celtic_Minstrel » August 15th, 2018, 12:10 am

ResExsention wrote:
August 14th, 2018, 5:41 pm
I'll keep that in mind, though, for any other lua I use.
No. Not any other Lua you use. Only Lua whose purpose is to define things, such as custom tags, filter functions, status effect icons, etc. Basically if it has anything other than maybe local something = ... that's not between function . . . end, it's likely intended to be run in-place; but if it only contains function definitions, then it only needs to run once.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.

User avatar
ResExsention
Posts: 97
Joined: March 17th, 2018, 12:00 am
Location: Alberta, Canada

Re: Random Unit Dialogue

Post by ResExsention » August 15th, 2018, 5:07 pm

Oh. Maybe I should get back to my other lua post. Yes, I understand. Thanks for clarifying.
I am a ranger and my WML knives will implant themselves in your back.

Creator of the abandoned campaign Royalties Forgotten and the work in progress campaign Purger of Evil.
Maintainer of Fate of a Princess.

Post Reply