Allowing a unit to pass through enemies (with [move_unit])
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.
- Nyanyanyan
- Posts: 73
- Joined: May 11th, 2018, 10:40 pm
Allowing a unit to pass through enemies (with [move_unit])
I'm trying to make a weapon special that has the attacking unit move through (and end up behind) the enemy using [move_unit] and [harm_unit], but [move_unit] doesn't allow movements that wouldn't otherwise be possible unless there is no other way.
Is there a way to allow a unit to pass through enemy units as if they were allies or some way to make [move_unit] not consider whether the unit can actually pass through the location in question?
This is the code I'm using right now. It's mostly doing what it should, except the weird behavior of taking very long routes if no direct one is available, which is why I'd prefer a direct pass-through.
Thanks in advance for any help.
Is there a way to allow a unit to pass through enemy units as if they were allies or some way to make [move_unit] not consider whether the unit can actually pass through the location in question?
This is the code I'm using right now. It's mostly doing what it should, except the weird behavior of taking very long routes if no direct one is available, which is why I'd prefer a direct pass-through.
Code: Select all
#define SPECIAL_OPENINGTHREAD
[chance_to_hit]
id=openingthread
name= _ "thread of fate"
description= _ "Walk past the enemy and strike them."
apply_to=self
value=100
cumulative=no
active_on=offense
[/chance_to_hit]
#none of this is actually relevant
[attacks]
value=0
apply_to=opponent
[filter_base_value]
greater_than=0
[/filter_base_value]
[/attacks]
[/specials]
[/attack]
[event]
name=attack
id=openingthreadhit
first_time_only=no
[filter_attack]
special=openingthread
[/filter_attack]
[store_locations]
[filter_adjacent_location]
x,y=$x2,$y2
adjacent=-$unit.facing
[/filter_adjacent_location]
variable=openingthreadlocationvar
[/store_locations]
[move_unit]
x,y=$x1,$y1
to_x=$openingthreadlocationvar.x
to_y=$openingthreadlocationvar.y
[/move_unit]
[modify_unit]
[filter]
x,y=$x2,$y2
[/filter]
facing=$-unit.facing
[/modify_unit]
[harm_unit]
[filter]
x,y=$x2,$y2
[/filter]
kill=yes
fire_event=yes
animate=yes
damage_type=blade
amount=$weapon.damage
[/harm_unit]
{CLEAR_VARIABLE openingthreadlocationvar}
[/event]
[+attack]
[+specials]
#enddef
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Re: Allowing a unit to pass through enemies (with [move_unit])
I can't find anything which will allow units to directly move through enemy units. ([move_unit] doesn't appear to have any useful arguments, according to the wiki.)
One can, however, temporarily remove the enemy unit from the map - the attacker will then move smoothly through the newly-vacated hex. I probably did it in a slightly inelegant way, but this works when I test it.
It looks a bit funny because the enemy blinks out of existence when the attacking unit walks past - it might be possible to do some more magic code to paste a fake copy of the enemy unit's image in the hex for the duration. Or you could make a special swooshy blur moving animation for your unit to disguise the disappearing enemy. Or you could just let the enemy briefly disappear and hope nobody looks to closely.
Also, when I was testing it, I discovered that this behaved funny when the enemy did not have a clear hex on the other side.
EDIT: I figured out how to do part of what I just suggested! After you store the location, wrap the rest of the event inside an [if] tag with this condition:
That means the unit will only move through the active one when the opposite hex is on the map and empty of other units.
This wouldn't do anything about walls (the unit would still not walk into the walls, it would still potentially walk all the way around the enemy to reach a location on the other side of the wall and then deal damage from there, and so on. It would, however, make the behavior more reliable.
If all of the units with this ability have the same movetype as each other, you could write a list of what terrains are valid moveto hexes, based on which ones the unit can move over: probably something like "not impassable, not unwalkable unless there is a bridge over it, not deep water unless there is a bridge over it". In fact, you might want to include conditionals that make sure the enemy's hex and the hex on the other side are both walkable, because otherwise, I assume one of these units could end up on the other side of a 1-hex-wide chasm with a drake over it.
One can, however, temporarily remove the enemy unit from the map - the attacker will then move smoothly through the newly-vacated hex. I probably did it in a slightly inelegant way, but this works when I test it.
Code: Select all
[store_unit]
[filter]
x,y=$x2,$y2
[/filter]
kill=yes
variable=defending_unit
[/store_unit]
[move_unit]
x,y=$x1,$y1
to_x=$openingthreadlocationvar.x
to_y=$openingthreadlocationvar.y
[/move_unit]
[unstore_unit]
variable=defending_unit
animate=no
[/unstore_unit]
Also, when I was testing it, I discovered that this behaved funny when the enemy did not have a clear hex on the other side.
- If the opposite hex was already occupied, the attacker moves to some hex near the target, so you can get stuff like a unit attacking from two hexes away (looks funny) or even the unit standing where the enemy was and being replaced when the enemy is unstored (which completely wastes a unit).
- If the unit tries to move off the map, then it disappears completely and an error message near the top of the screen says you can't move units outside the map.
EDIT: I figured out how to do part of what I just suggested! After you store the location, wrap the rest of the event inside an [if] tag with this condition:
Code: Select all
[have_location]
x=$openingthreadlocationvar.x
y=$openingthreadlocationvar.y
include_borders=no
[not]
[filter] # an empty [filter] tag inside a standard location filter will match any unit that is standing on the hex.
[/filter]
[/not]
[/have_location]
This wouldn't do anything about walls (the unit would still not walk into the walls, it would still potentially walk all the way around the enemy to reach a location on the other side of the wall and then deal damage from there, and so on. It would, however, make the behavior more reliable.
If all of the units with this ability have the same movetype as each other, you could write a list of what terrains are valid moveto hexes, based on which ones the unit can move over: probably something like "not impassable, not unwalkable unless there is a bridge over it, not deep water unless there is a bridge over it". In fact, you might want to include conditionals that make sure the enemy's hex and the hex on the other side are both walkable, because otherwise, I assume one of these units could end up on the other side of a 1-hex-wide chasm with a drake over it.
Last edited by Pilauli on October 30th, 2020, 7:36 pm, edited 1 time in total.
Re: Allowing a unit to pass through enemies (with [move_unit])
The Deep Elves (they're in Ageless Era) have a Tyrhai Rider unit that does this. The ability is called "trample", but there are several other abilities in Ageless that share that name. The implementation for this one is in Tyrhai_Rider.cfg itself.
I recall it having interesting bugs such as not getting XP, and teleporting through walls behind enemies.
I recall it having interesting bugs such as not getting XP, and teleporting through walls behind enemies.
Re: Allowing a unit to pass through enemies (with [move_unit])
Interesting idea.
An alternative solution (that might be easier to code, I don't know) would be to have the attacking unit and the defending unit swap places.
Furthermore, you might give the newly relocated attacking unit 1 bonus movement point, allowing them to move again -- assuming a hex is available. This would place the attacking unit on the distant hex you envision them occupying. You could also reduce all of their terrain movement costs temporarily to 1, so the attacking unit could enter terrain that they could not otherwise enter with only 1 movement point (so, for example, an orcish grunt could enter swamp water).
Warning: I couldn't code this to save my life. But is seems do-able.
An alternative solution (that might be easier to code, I don't know) would be to have the attacking unit and the defending unit swap places.
Furthermore, you might give the newly relocated attacking unit 1 bonus movement point, allowing them to move again -- assuming a hex is available. This would place the attacking unit on the distant hex you envision them occupying. You could also reduce all of their terrain movement costs temporarily to 1, so the attacking unit could enter terrain that they could not otherwise enter with only 1 movement point (so, for example, an orcish grunt could enter swamp water).
Warning: I couldn't code this to save my life. But is seems do-able.
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.
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
Re: Allowing a unit to pass through enemies (with [move_unit])
Why you want to use [move_unit]? This goal seems more suited to [move_unit_fake] and [unstore_unit]/[teleport].
Re: Allowing a unit to pass through enemies (with [move_unit])
(Not OP but) [move_unit_fake] has the fake unit go around "enemy" units anyway (at least when I test it), so that wouldn't solve the problem of the unit appearing to walk around instead of through the occupied hex. So what would be the point of temporarily replacing a unit with a different one that doesn't act any differently?
Re: Allowing a unit to pass through enemies (with [move_unit])
You need to set 3 coordinates for that: start, enemy, end. Then it does not do pathfinding.
- Nyanyanyan
- Posts: 73
- Joined: May 11th, 2018, 10:40 pm
Re: Allowing a unit to pass through enemies (with [move_unit])
Thanks, that works.
Here's my code for anyone interested.
The only problem is that there is like one frame where the unit is hidden, but the fake move hasn't started yet, but it's barely visible.
Code: Select all
[store_unit]
[filter]
x,y=$x1,$y1
[/filter]
variable=openingthreadunitvar
[/store_unit]
[hide_unit]
x,y=$x1,$y1
[/hide_unit]
[move_unit_fake]
type=$unit.type
side=$side_number
gender=$unit.gender
variation=$unit.variation
x=$x1,$x2,$openingthreadlocationvar.x
y=$y1,$y2,$openingthreadlocationvar.y
[/move_unit_fake]
[unstore_unit]
variable=openingthreadunitvar
x,y=$openingthreadlocationvar.x,$openingthreadlocationvar.y
[/unstore_unit]
[kill]
x,y=$x1,$y1
[/kill]
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Re: Allowing a unit to pass through enemies (with [move_unit])
[store_unit] kill=yes to not need to hide and kill separately.
- Nyanyanyan
- Posts: 73
- Joined: May 11th, 2018, 10:40 pm
Re: Allowing a unit to pass through enemies (with [move_unit])
But that would mean the faction in question has no leader for the duration of the movement, right?
I usually play with addons that do something while a side's (only) leader dies, so that would be bad.
Or are events not fired for that death?
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Re: Allowing a unit to pass through enemies (with [move_unit])
I just plugged some simple last_breath and die events into my code that stores one unit so the other can move through its space, and it looks like storing-and-killing the unit does not fire those events.Nyanyanyan wrote: ↑November 2nd, 2020, 10:39 amBut that would mean the faction in question has no leader for the duration of the movement, right?
I usually play with addons that do something while a side's (only) leader dies, so that would be bad.
Or are events not fired for that death?
It's safe.
Re: Allowing a unit to pass through enemies (with [move_unit])
MODIFY_UNIT is [store_unit] kill=yes ... change something ... [unstore_unit] find_vacant=no
data/core/macros/utils.cfg
data/core/macros/utils.cfg
Re: Allowing a unit to pass through enemies (with [move_unit])
If you do it within same event then it does not notice that there was moment without leader.