Allowing a unit to pass through enemies (with [move_unit])

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

Allowing a unit to pass through enemies (with [move_unit])

Post by Nyanyanyan »

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.

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
Thanks in advance for any help.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Pilauli »

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.

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]
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.
  • 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.
You might want to include some conditional code so this will only fire when there is actually a clear hex in the right spot. (This would presumably make the unit use the normal placeholder/dummy attack if there wasn't room to charge, which sounds pretty logical to me.)

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]
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.
Last edited by Pilauli on October 30th, 2020, 7:36 pm, edited 1 time in total.
User avatar
octalot
General Code Maintainer
Posts: 783
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by octalot »

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

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Helmet »

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

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Ravana »

Why you want to use [move_unit]? This goal seems more suited to [move_unit_fake] and [unstore_unit]/[teleport].
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Pilauli »

(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?
User avatar
Ravana
Forum Moderator
Posts: 2952
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Ravana »

You need to set 3 coordinates for that: start, enemy, end. Then it does not do pathfinding.
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Nyanyanyan »

Ravana wrote: October 31st, 2020, 9:05 am You need to set 3 coordinates for that: start, enemy, end. Then it does not do pathfinding.
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.
User avatar
Ravana
Forum Moderator
Posts: 2952
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Ravana »

[store_unit] kill=yes to not need to hide and kill separately.
User avatar
Nyanyanyan
Posts: 73
Joined: May 11th, 2018, 10:40 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Nyanyanyan »

Ravana wrote: October 31st, 2020, 1:29 pm [store_unit] kill=yes to not need to hide and kill separately.
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.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Pilauli »

Nyanyanyan wrote: November 2nd, 2020, 10:39 am
Ravana wrote: October 31st, 2020, 1:29 pm [store_unit] kill=yes to not need to hide and kill separately.
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?
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.

It's safe.
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by vghetto »

MODIFY_UNIT is [store_unit] kill=yes ... change something ... [unstore_unit] find_vacant=no
data/core/macros/utils.cfg
User avatar
Ravana
Forum Moderator
Posts: 2952
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: Allowing a unit to pass through enemies (with [move_unit])

Post by Ravana »

If you do it within same event then it does not notice that there was moment without leader.
Post Reply