Adding moves to a unit after it has attacked

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

Adding moves to a unit after it has attacked

Post by Helmet »

I'm working on a new unit based on a frog (I already made some of the animations). After the unit attacks, instead of 0 moves, I want it to have 1 moves, allowing it to hop to an adjacent hex. This hopping should only work if the unit did not move before attacking. This feature is almost identical to the ability DISENGAGE, which bestows full movement to a qualifying unit.

I couldn't get DISENGAGE to work in my scenario, so I inserted the event directly into my scenario and tinkered with it. At some point it almost worked. A unit who did not move before attacking was given 1 moves after attacking, but the bonus moves was also given to the units who had moved before attacking. This is not acceptable, of course.

What is the code necessary to bestow 1 moves to a unit after it attacks, provided the unit has not moved?

If there are multiple ways to accomplish this, I would prefer modify_unit over unstore_unit. Regarding unstore_unit, the Wiki says it is used to "update a unit on the map after having edited its WML. This usage is common, but discouraged - if possible, you should use [modify_unit] or [object] instead."

Here is the code for DISENGAGE, if that helps. Thanks!

If you could make this feature an ability so that I don't have to copy it into all the scenarios, that would be great. Would I have to put a global variable in the main.cfg? I did that with DISENGAGE and it still didn't work for some reason.

It would also be nice if the ability's name appeared in the side bar, too. I'm going to call it BATTLEHOP.

Code: Select all

#define ABILITY_DISENGAGE_EVENTS
    [event]
        name=attack end
        first_time_only=no

        [filter]
            ability=disengage

            [not]
                [filter_wml]
                    moves=$this_unit.max_moves
                [/filter_wml]
            [/not]
        [/filter]

        {VARIABLE unit.moves 0}

        [unstore_unit]
            variable=unit
            find_vacant=no
        [/unstore_unit]
    [/event]
#enddef
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: Adding moves to a unit after it has attacked

Post by Pilauli »

To quote the wiki...
https://wiki.wesnoth.org/UnitTypeWML#Attacks wrote: [attack]: one of the unit's attacks.
...
name: the name of the attack...
type: the damage type of the attack...
...
movement_used: determines how many movement points using this attack expends. By default all movement is used up, set this to 0 to make attacking with this attack expend no movement.
I actually saw this the other day and thought to myself, "oh, right, that's a thing. I should do something cool with it."

You can probably (disclaimer: untested) just go inside the attack and write a line that says something like movement_used=4 (if the frog has 5 movement by default - so if it already moved, attacking runs it out, but if didn't move, it has one left.

I assume that it would have some weird interactions with other things that edit movement points, if you did it this way: quick frogs (I expect) would be able to hop 2 hexes instead of 1, and slowed frogs probably wouldn't be able to move after attacking, because they had/have fewer movement points to start with than the number expects. I think both of those sound logical and intuitive, though, so they might actually be good side effects.

I just realized that this proposed solution would probably let the frog attack twice if it was managed just right. If that's a problem, then either you're going to need a more complicated way to let it move again after attacking, or else you're going to need a complicated way to restrict its attacks. (I assume, at least.)

I don't presently feel like assembling and testing something like that, so I'm just going to leave this suggestion at the level of "this might be what you're looking for."
User avatar
octalot
Developer
Posts: 544
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: Adding moves to a unit after it has attacked

Post by octalot »

I just got really confused wondering how disengage worked, until I realised that it also relies on movement_used=0 in Scout.cfg's [attack] tags. So the ABILITY_DISENGAGE_EVENTS code isn't giving moves back, instead it's taking moves away from units that didn't have full movement points beforehand.

I think you could do BATTLEHOP with two [event]s:
  • One event exactly the same as disengage, [filter][not][filter_wml]moves=$this_unit.max_moves, which sets unit.moves to 0.
  • One that uses a similar filter with the [not] removed, which sets unit.moves to 1.
  • Include movement_used=0 in Frog.cfg's [attack] tags
Soliton
Site Administrator
Posts: 1638
Joined: April 5th, 2005, 3:25 pm
Location: #wesnoth-mp

Re: Adding moves to a unit after it has attacked

Post by Soliton »

Pilauli wrote: October 13th, 2020, 3:35 am I just realized that this proposed solution would probably let the frog attack twice if it was managed just right. If that's a problem, then either you're going to need a more complicated way to let it move again after attacking, or else you're going to need a complicated way to restrict its attacks. (I assume, at least.)
No, attacks default to 1.
"If gameplay requires it, they can be made to live on Venus." -- scott
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Adding moves to a unit after it has attacked

Post by Helmet »

Thanks for the help. What complicates matters is (according to the Wiki) sometimes the AI will expend some of an enemy unit's moves while thinking and strategizing, even if the unit doesn't actually move anywhere. I need to make sure this behavior doesn't throw a monkey wrench into the BATTLEHOP machinery.

This coding problem is a little beyond my meager powers, I think. Today I was struggling with a simple message tag, trying to make it only work for loyal units, and I never got it to work. If I get something as complex as BATTLEHOP to work, it will be purely by luck. Like if a bug crawls across my keyboard and I smash my hand on it several times and the functional code appears in my text editor.
User avatar
Celtic_Minstrel
Developer
Posts: 1771
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Adding moves to a unit after it has attacked

Post by Celtic_Minstrel »

Pilauli wrote: October 13th, 2020, 3:35 am I just realized that this proposed solution would probably let the frog attack twice if it was managed just right. If that's a problem, then either you're going to need a more complicated way to let it move again after attacking, or else you're going to need a complicated way to restrict its attacks. (I assume, at least.)
The number of times a unit can attack in a turn is another of the little-used stats of a unit (I believe the exact name of the stat in WML is num_attacks). As Soliton said, it's set to 1 by default, so unless it was explicitly set differently for the frog, they wouldn't be able to attack twice.
Author of The Black Cross of Aleron campaign and Default++ era.
Maintainer of Steelhive.
Soliton
Site Administrator
Posts: 1638
Joined: April 5th, 2005, 3:25 pm
Location: #wesnoth-mp

Re: Adding moves to a unit after it has attacked

Post by Soliton »

Helmet wrote: October 14th, 2020, 1:09 am What complicates matters is (according to the Wiki) sometimes the AI will expend some of an enemy unit's moves while thinking and strategizing, even if the unit doesn't actually move anywhere. I need to make sure this behavior doesn't throw a monkey wrench into the BATTLEHOP machinery.
Do you expect the AI to use your ability? It might do so by chance but it's not going to plan with it. Or maybe you misunderstood that the AI will mess with units that are not under its control?
"If gameplay requires it, they can be made to live on Venus." -- scott
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Adding moves to a unit after it has attacked

Post by Helmet »

I thought the AI might use the ability whenever I play against a computer and it has side with the frog-based unit. But AI wouldn't plan with it?

So...the AI would notice that the frog-based unit that already attacked happens to have a bonus move, and might move it, but it wouldn't purposefully keep a unit from moving in preparation for employing the ability? Bummer.

I presumed that because DISENGAGE works, battlehop would work. But now that I think about it, they serve radically different functions. The former allows a wounded unit to run toward a distant village or an empty corner of the map immediately after being attacked and harmed. That's fairly simple AI behavior, I guess. Placing a unit on a beach so that it can fight an approaching naga, with the idea that the unit will hop one hex inland after fighting, luring the naga onto a dirt terrain, that's a complicated tactic for an AI, I guess.

Hmm. This ability might be too problematic to use.

It might be overpowered, too. Using battlehop would make it much easier to surround and kill a powerful unit, like a final boss, without losing a unit (unless the boss can kill a unit in one attack). Turn 1, you surround the boss with battlehop units, but you don't attack, to preserve your units' hit points. Turn 2, all units attack the boss and hop away and similar units move into the vacated hexes, but don't attack. And so forth.
User avatar
octalot
Developer
Posts: 544
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: Adding moves to a unit after it has attacked

Post by octalot »

I doubt that the AI knows how to use disengage. I think it only gets 3 units with it in the whole campaign; those are in S09, they're in a fairly poor tactical position, and the player gets a bonus if they survive (which is hinted at when they appear).

The 2-turn pattern that you describe with battlehop is effective with disengage too.
User avatar
Nyanyanyan
Posts: 69
Joined: May 11th, 2018, 10:40 pm

Re: Adding moves to a unit after it has attacked

Post by Nyanyanyan »

I had a similar problem a while ago, came up with this:

Code: Select all

#define ABILITY_HAR
 [dummy]
  id=harspecial
  name= _ "hit and run"
  description=_"This unit gains 4 movement points after attacking."
 [/dummy]
[/abilities]
[event]
        name=attack end
        first_time_only=no

        [filter]
		ability=harspecial
        [/filter]


        {MODIFY_UNIT x,y=$x1,$y1 moves 4}
        {MODIFY_UNIT x,y=$x1,$y1 attacks_left 0}
[/event]
[+abilities]
#enddef
This is the code I use in my Era and it works fine, however it doens't care about expended movement points.

I tried modifying it for your pupose, however this is not tested, so if you want to use it, it'd be better to confirm that it's working before putting it in. Of course like with all other abilities of this kind, the AI will use the movement point if it happens to get it, but it will not plan with it.

Code: Select all

#define ABILITY_HITANDRUN
[dummy]
  id=harspecial
  name= _ "hit and run"
  description=_"This unit gains 1 movement point after attacking without having moved."
[/dummy]
[/abilities]
[event]
        name=attack start
        first_time_only=no
        [filter]
			ability=harspecial
			moves=$this_unit.max_moves
        [/filter]
	[modify_unit]
          [filter]
		x,y=$x1,$y1
           [/filter]
	[status]
		hitandrunstatus=yes
	[/status]
	[/modify_unit]
[/event]
[event]
	name=attack end
	first_time_only=no
	[filter]
		ability=harspecial
		status=hitandrunstatus
    [/filter]	
	{MODIFY_UNIT x,y=$x1,$y1 moves 1}
	{MODIFY_UNIT x,y=$x1,$y1 attacks_left 0}
	[modify_unit]
           [filter]
			status=hitandrunstatus
           [/filter]
		[status]
			hitandrunstatus=no
		[/status]
	[/modify_unit]
[/event]
[+abilities]
#enddef
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Adding moves to a unit after it has attacked

Post by Helmet »

Nyanyanyan wrote: October 14th, 2020, 2:48 pm I had a similar problem a while ago, came up with this...
Thank you! Your original code works fine. The code you modified does not work. I see the ability name on the sidebar, but nothing happens.

Parts of the code I don't understand, so this is probably a ridiculous question. Do you think maybe an if/then tag could examine the variable unit.movement_used to see if the unit moved? The difficulty seems to be learning whether or not the unit moved, not modifying the movement.

+ + +

Okay, I added an if/then tag to test the unit.movement_used variable. It did not work. But I make simple mistakes, so maybe I left off a $ or a filter. Incorrect code attached.

Code: Select all

#define ABILITY_BATTLEHOP
	[dummy]
  		id=harspecial
  		name= _ "battlehop"
  		description=_"This unit gains 1 movement point after attacking."
 	[/dummy]
[/abilities]

	[event]
    	name=attack start
    	first_time_only=no
    	[filter]
			ability=harspecial
        [/filter]
	    [set_variable]
			name=did_the_unit_move
			value=unit.movement_used
		[/set_variable]	        
	[/event]

	[event]
        name=attack end
        first_time_only=no
        [filter]
			ability=harspecial
        [/filter]
		[if]											
	    	[variable]
				name=did_the_unit_move
				equals=0
			[/variable]
			[then]		
        		{MODIFY_UNIT x,y=$x1,$y1 moves 1}
#        		{MODIFY_UNIT x,y=$x1,$y1 attacks_left 0}
			[/then]
		[/if]
	[/event]
[+abilities]
#enddef
Last edited by Helmet on October 14th, 2020, 9:45 pm, edited 1 time in total.
User avatar
Nyanyanyan
Posts: 69
Joined: May 11th, 2018, 10:40 pm

Re: Adding moves to a unit after it has attacked

Post by Nyanyanyan »

Helmet wrote: October 14th, 2020, 7:56 pm Parts of the code I don't understand, so this is probably a ridiculous question. In the second event, do you think maybe a filter_condition should check to see if moves equals $this_unit.max_moves? And if they match, that means the unit hasn't moved and will get the bonus move?
What I tried to do was have the first event filter check if the unit is at full moves, then apply a unique status (just for filtering) and then with the second event filter by the status to then add the movement point and remove the status for next turn.
I don't really have time to test it right now, but I am assuming the problem lies with applying the status or filtering for it.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Adding moves to a unit after it has attacked

Post by Helmet »

Hm. The Wiki says that a scenario can set unit.status.my_custom_key to 'yes' or 'no'. So maybe hitandrunstatus should be something like unit.status.hitandrun? I have no idea.
User avatar
Nyanyanyan
Posts: 69
Joined: May 11th, 2018, 10:40 pm

Re: Adding moves to a unit after it has attacked

Post by Nyanyanyan »

No, that's not it.
This code:

Code: Select all

					[effect]
                        apply_to=status
                        add=general
					[/effect]
Works to apply the status "general" to a unit.
I tried using this instead of [status] but it didn't work either. I'm guessing it's a timing problem. Maybe someone else can chip in what they know.
Author of Age of Lords and the Revolution and Civil War and Expendable Leaders 2 multiplayer mods.
User avatar
Helmet
Posts: 331
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: Adding moves to a unit after it has attacked

Post by Helmet »

Thanks for trying, Nyanyanyan, and for sharing your code for hit and run.
Post Reply