A hex that kills a unit who passes through it

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
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

A hex that kills a unit who passes through it

Post by Helmet »

Time for my (almost) daily question. Thank you for helping me, WML Workshop. I'm about 80% done coding my campaign, so this barrage of WML questions will not be going on much longer.

In my scenario-in-progress, there exists a deadly pool. It is one hex in size (hex 8,3). If a unit stands in the pool, they die. I made the code without help and it works. Yay.

Here's the problem. I want the pool to be SO FREAKING DEADLY that a unit will die if he merely passes over the pool, but doesn't stop on it. If his little bootprints cross hex 8,3 while he's going somewhere, he dies the moment he reaches his destination hex.

It seems to me that exit_hex should do the heavy lifting of this event, but I can't make it work. I've tried enter_hex, too.

Here is the latest version of my nonfunctional code. In my thinking, the code filters for the last hex every unit exited. If the hex equals 8,3 (the deadly pool), the code kills the unit, who now occupies hex $unit.x,$unit.y.

Maybe I don't understand what "exited" means.

Thanks for your help.

Code: Select all

 [event] #							
     	name=exit_hex
	first_time_only=no
    	[filter_location] # deadly pool
   	      x1=8
   	      y1=3 
  	[/filter_location]
		[kill]
			x=$unit.x
			y=$unit.y
			animate=yes
		[/kill]
 [/event]
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
octalot
General Code Maintainer
Posts: 786
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: A hex that kills a unit who passes through it

Post by octalot »

Given that no unit will ever want to walk through it, maybe just stick an Impassible Overlay on the hex so that nothing walks through it. Seems fairer to the player.

With your event code, you're trying to debug two problems at the same time - if either the event filter or the kill filter doesn't match, then the event won't do anything, but you won't know which part was the problem. Start by adding a [message] so that you know the event is triggering.

For both enter_hex and exit_hex, the event uses a [filter] with x= and y=, there are examples in LoW's S02.

You may want to [cancel_action] to have the unit die there and then.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: A hex that kills a unit who passes through it

Post by Helmet »

octalot wrote: October 19th, 2020, 1:02 am Given that no unit will ever want to walk through it
The AI will know that walking on the hex will kill an AI unit? I was thinking the AI would be oblivious. That changes everything.

The pool might be too deadly, now that I think about it. Some players wouldn't like having a unit die in such a manner, like you said.

Thanks for explaining the problem with my filters and pointing me toward the Hostile Mountains scenario. I see an example I need to study.
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: A hex that kills a unit who passes through it

Post by Pilauli »

Okay, it looks like Octalot already answered the question you asked. (That's the easy, logical solution.) I had a different solution (I didn't test it, but I snagged it from something similar, so it ought to work), but I spent way too long researching the second part of this post. :roll:

$x1 means you can use it in a formula, but it doesn't seem to inherently let you check if x1=whatever. The Wesnoth Formula Language (https://wiki.wesnoth.org/Wesnoth_Formula_Language) seems to let you filter variable values, though. I was going to suggest this snippet:

Code: Select all

    [filter]
        formula="$( ($x1=8) and ($y1=3) )"
    [/filter]
Side note: when I have to do something to "unit", I generally use id=$unit.id rather than using $unit.x and $unit.y. It takes less time to type. And I'm just more comfortable, in principle, filtering by ID (which sticks to the unit) than by location (which changes, although admittedly not usually inside events).

I would also suggest making the unit say something. It's very helpful in tracking what's going on and telling the player if they didn't know. For example, "Why are my feet melting? I hardly touched the poison!" Or something like that. Actually, that gives me an idea: if it's a poison puddle, it could poison the units on contact, instead of killing them. This seems to work nicely:

Code: Select all

[harm_unit]
    [filter]
        id=$unit.id
    [/filter]
    amount=0
    poisoned=yes
[/harm_unit]
Here beginneth part 2: 'Logically, flying units shouldn't be killed by the pool.':
Reason for edit: fixing formatting that I messed up.
User avatar
octalot
General Code Maintainer
Posts: 786
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: A hex that kills a unit who passes through it

Post by octalot »

Helmet wrote: October 19th, 2020, 1:41 am The AI will know that walking on the hex will kill an AI unit? I was thinking the AI would be oblivious. That changes everything.
Ah no, the AI won't know, unless you give it an [avoid] instruction.
Pilauli wrote: October 19th, 2020, 2:43 am To my dismay, I could not find a simple, widely-applicable way to filter by whether a unit can fly. (One could, for example, say that if it is not on this (very long) list of unit types, then it can't fly, but that list would be a pain to write, and an even bigger pain to remember to update.) Eventually, I decided that if it could cross unwalkable terrain, it could fly.
In 1.12 or later you can check for $unit.flying, although this was undocumented. It's now been added to the SingleUnitWML page.

I ended up using similar logic to yours for working out if a unit can swim, as there isn't a corresponding $unit.swimming. Another possibility would be to check for undead_variation being swimmer.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: A hex that kills a unit who passes through it

Post by Pilauli »

octalot wrote: October 19th, 2020, 4:48 am In 1.12 or later you can check for $unit.flying, although this was undocumented.
It doesn't actually say whether the unit can fly or not. This is all it does:
https://wiki.wesnoth.org/UnitsWML#.5Bmovetype.5D wrote: A unit with flying=yes does not have its image's height adjusted for different terrains.
Examples of 'flying' not matching up with whether the unit can fly:
So yeah, I'd recommend sticking with the "test whether it can move on unwalkable terrain" route for the immediate future.

Modified as situations dictate, of course. If there's literally only one flying unit in the whole campaign, you could just define "non-flying" as "the ID doesn't match this particular unit's ID." If there's some non-flying unit that can move over unwalkable terrain or through impassable terrain, that's very strange, but you'll want to write your filters with that kind of unit in mind.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: A hex that kills a unit who passes through it

Post by Helmet »

Pilauli wrote: October 19th, 2020, 2:43 am

Code: Select all

    [filter]
        formula="$( ($x1=8) and ($y1=3) )"
    [/filter]
Wow, the formula worked! Thanks! The unit who tries to pass through the pool dies. I had no idea that $x1 and $y1 weren't having their variables checked. I was working on another section of code and it stopped working when I removed the $ from the variables, so I had to put them back, so I'm still trying to figure-out $. Your information helped me a lot.
Pilauli wrote: October 19th, 2020, 2:43 am Side note: when I have to do something to "unit", I generally use id=$unit.id rather than using $unit.x and $unit.y.
I will start doing that.
Pilauli wrote: October 19th, 2020, 2:43 am I would also suggest making the unit say something...
Good idea. The player is warned at the start of the scenario against entering the pool. Maybe the unit's message could be something like, "What's happening? I'm dissolving! Oh, right, I wasn't supposed to enter the pool...".
Pilauli wrote: October 19th, 2020, 2:43 am Actually, that gives me an idea: if it's a poison puddle, it could poison the units on contact, instead of killing them. This seems to work nicely:

Code: Select all

[harm_unit]
    [filter]
        id=$unit.id
    [/filter]
    amount=0
    poisoned=yes
[/harm_unit]
I like that. It's funny how it sometimes takes a hundred lines of code to do something simple, and other times under ten lines to do something awesome.
Pilauli wrote: October 19th, 2020, 2:43 am Here beginneth part 2: 'Logically, flying units shouldn't be killed by the pool.'"
Gasp! I forgot about flying units.
Pilauli wrote: October 19th, 2020, 2:43 am To my dismay, I could not find a simple, widely-applicable way to filter by whether a unit can fly. (One could, for example, say that if it is not on this (very long) list of unit types, then it can't fly, but that list would be a pain to write, and an even bigger pain to remember to update.)
In my scenario, the enemy is composed of three unit types, and none can fly. The player, however, has two recruitable flying units. I will add a filter for those two units.
Pilauli wrote: October 19th, 2020, 2:43 am Eventually, I decided that if it could cross unwalkable terrain, it could fly. And you would think this would be easy to filter for, but I couldn't figure out how to do it, and eventually decided to compare unwalkable movement costs to impassable movement costs, and play different messages depending on whether the unit could or couldn't go on unwalkable terrain. Sound confusing? Hopefully it makes more sense in code form, where I omit the explanations and just write something that hopefully works:
When I made my custom [movetype], there was a line that read flies=. I don't know if that could be helpful.
Pilauli wrote: October 19th, 2020, 2:43 am If the pool is some sort of poison, then it might also not affect undead. I was going to provide suggestions for how to implement that feature, but if you use actual poison, then undead will be naturally immune, just as they are to ghast or orcish assassin poison. It would be neat to add flavor text, though...
I like that solution. Presently, the pool is so deadly that it even kills undead. Basically, the pool dissolves anything, even metal. It's probably more of an acid than a poison. But I might change it at some point; you know how it is. A couple weeks ago, I had a mermaid trapped in the pool, haha.
Pilauli wrote: October 19th, 2020, 2:43 am Of course, if you don't have any units in that scenario who should be able to avoid that pool (or be immune to poison), then you don't have to worry about any of this stuff.
The pool is important. Destroying the evil pool of instant, horrible death is the ultimate objective of the first three scenarios. Thanks for helping me make the pool scarier.
Pilauli wrote: October 19th, 2020, 2:43 am I think I'm actually going to bookmark this page for my own future reference, because a lot of this research (your "event triggered on leaving hex" stuff and my filter/sorting stuff) would be applicable to various ideas that I've had, and it would be a shame to have to re-research it later. ;)
I know what you mean. Sometimes when I read a reply with helpful code snippets, I think, "I have learned this and will recall it perfectly later!" But when later rolls around, I've forgotten something critical and need to come back to the forum and re-read it. That's the supreme challenge of coding. One teeny-weeny mistake and thousands of lines of code may stop working or do something you don't want. At one point when I was trying to code the pool, when the unit stepped into the pool it killed him as well as the next unit I selected, and the next unit I selected, and so on until everyone was dead. It was kinda funny.

This post had a LOT of helpful information. Thanks again!
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: A hex that kills a unit who passes through it

Post by Helmet »

octalot wrote: October 19th, 2020, 4:48 am
Helmet wrote: October 19th, 2020, 1:41 am The AI will know that walking on the hex will kill an AI unit? I was thinking the AI would be oblivious. That changes everything.
Ah no, the AI won't know, unless you give it an [avoid] instruction.
Oh. Good.

In a dozen playtests, the ai-controlled saurian fighting adjacent to the pool never stepped into the pool. I thought he was just lucky. As it turns out, I was right.

+ + +

EDIT: The saurian stepped into the pool! Finally!
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
Celtic_Minstrel
Developer
Posts: 2195
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: A hex that kills a unit who passes through it

Post by Celtic_Minstrel »

Helmet wrote: October 19th, 2020, 1:41 am
octalot wrote: October 19th, 2020, 1:02 am Given that no unit will ever want to walk through it
The AI will know that walking on the hex will kill an AI unit? I was thinking the AI would be oblivious. That changes everything.
The AI would be oblivious. I think octalot meant from a world-building standpoint – since the pool is deadly, no-one would want to enter it, so why not make it impassable?
Pilauli wrote: October 19th, 2020, 2:43 am Okay, it looks like Octalot already answered the question you asked. (That's the easy, logical solution.) I had a different solution (I didn't test it, but I snagged it from something similar, so it ought to work), but I spent way too long researching the second part of this post. :roll:

$x1 means you can use it in a formula, but it doesn't seem to inherently let you check if x1=whatever. The Wesnoth Formula Language (https://wiki.wesnoth.org/Wesnoth_Formula_Language) seems to let you filter variable values, though. I was going to suggest this snippet:

Code: Select all

    [filter]
        formula="$( ($x1=8) and ($y1=3) )"
    [/filter]
Though this would work, it's definitely better to just write x,y=8,3 instead of using a formula in this case. Filters have nothing to do with variables, basically.
Pilauli wrote: October 19th, 2020, 2:43 am Side note: when I have to do something to "unit", I generally use id=$unit.id rather than using $unit.x and $unit.y. It takes less time to type. And I'm just more comfortable, in principle, filtering by ID (which sticks to the unit) than by location (which changes, although admittedly not usually inside events).
This is fine but not really applicable in this particular instance, because the intent is to check where the unit moved to.
Pilauli wrote: October 19th, 2020, 2:43 am To my dismay, I could not find a simple, widely-applicable way to filter by whether a unit can fly. (One could, for example, say that if it is not on this (very long) list of unit types, then it can't fly, but that list would be a pain to write, and an even bigger pain to remember to update.) Eventually, I decided that if it could cross unwalkable terrain, it could fly.
I think this is a pretty good metric. You could also try something like this:

Code: Select all

[filter]
	[filter_wml]
		flying=yes
	[/filter_wml]
[/filter
I'm not sure if that's quite the correct format, but I'm pretty sure there is something at least similar to that which could work. It would probably produce a slightly different answer than the unwalkable check though, and perhaps the unwalkable check is actually better.

Pilauli wrote: October 19th, 2020, 2:43 am And you would think this would be easy to filter for, but I couldn't figure out how to do it, and eventually decided to compare unwalkable movement costs to impassable movement costs,
This seems like a reasonable method. It could maybe be made a little more concise with a formula, but whatever – if it works, great. It could cause issues if you make a unit that can cross impassable terrain, but you just have to make sure you don't do that.

Pilauli wrote: October 19th, 2020, 2:43 am If the pool is some sort of poison, then it might also not affect undead. I was going to provide suggestions for how to implement that feature, but if you use actual poison, then undead will be naturally immune, just as they are to ghast or orcish assassin poison. It would be neat to add flavor text, though. Something like this.
If your goal is to respect poison immunity, I think a better filter would look something like this:

Code: Select all

    [have_unit]
        id=$unit.id
        status=unpoisonable
    [/have_unit]
That way it should match any unit who's immune to poison, not just undead.
octalot wrote: October 19th, 2020, 4:48 am I ended up using similar logic to yours for working out if a unit can swim, as there isn't a corresponding $unit.swimming. Another possibility would be to check for undead_variation being swimmer.
Yeah, deep water movement costs are probably fairly accurate on whether a unit can swim, but maybe you'd want to exclude any with a submerge ability as well… though that's possibly impossible if you consider UMC submerge abilities…
Helmet wrote: October 19th, 2020, 12:46 pm Wow, the formula worked! Thanks! The unit who tries to pass through the pool dies. I had no idea that $x1 and $y1 weren't having their variables checked. I was working on another section of code and it stopped working when I removed the $ from the variables, so I had to put them back, so I'm still trying to figure-out $. Your information helped me a lot.
I don't know that the information really helped, since if you take it at face value I suspect you might end up even more confused in the future.

You can't use variables on the left hand side of the = in WML. It's just not possible. (The closest you can get is `[insert_tag]`.) The code you originally wrote wasn't working because filters don't know anything about x1 and y1, so it just ignored those keys and matched either everything or nothing (not quite sure which off the top of my head). Filters do however know about an x and y key, so if you just use the code at the top of this post, it will work better and be more readable.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply