How to make one attack cause multiple types of damage

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
ERROR1025
Posts: 46
Joined: February 23rd, 2020, 10:18 am

How to make one attack cause multiple types of damage

Post by ERROR1025 »

i hope make a unit,is a attack have 10 blade and 10 pierce,but i use

Code: Select all

    [attack]
        name=bow
        description= _"one attack"
        icon="attacks/bow.png"
        type=blade,pierce
        range=ranged
        damage=10
        number=1
    [/attack]
or

Code: Select all

    [attack]
        name=bow
        description= _"one attack"
        icon="attacks/bow.png"
        type=blade
        type=pierce
        range=ranged
        damage=10
        number=1
    [/attack]
is don't
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: How to make one attack cause multiple types of damage

Post by Pilauli »

Attacks almost always have exactly and only one damage type.

Why do you want multiple damage types, anyway? How is it supposed to behave?

Is the attack supposed to use whichever damage type is more effective? The usual solution in that case is to just give the unit two separate attacks. For example, the mainline Orcish Archer can shoot regular arrows (pierce) or fire arrows (fire).
https://units.wesnoth.org/1.15/mainline ... rcher.html
Then the computer or the player will pick whichever damage type is more effective in that case. (Note that the two bow attacks on the Orcish Archer also have slightly different damage distributions which mean even though the pierce attack usually does more damage, the fire attack does slightly more damage per strike, which is occasionally useful; this is a nice feature that makes the unit a little bit more versatile.)

If you want it to average the score somehow (so that, for example, drakes (especially vulnerable to pierce) would take slightly more (but not a ton more) damage from this bow), I have no idea how to do that.
User avatar
ERROR1025
Posts: 46
Joined: February 23rd, 2020, 10:18 am

Re: How to make one attack cause multiple types of damage

Post by ERROR1025 »

Pilauli wrote: November 7th, 2020, 2:44 am Attacks almost always have exactly and only one damage type.

Why do you want multiple damage types, anyway? How is it supposed to behave?

Is the attack supposed to use whichever damage type is more effective? The usual solution in that case is to just give the unit two separate attacks. For example, the mainline Orcish Archer can shoot regular arrows (pierce) or fire arrows (fire).
https://units.wesnoth.org/1.15/mainline ... rcher.html
Then the computer or the player will pick whichever damage type is more effective in that case. (Note that the two bow attacks on the Orcish Archer also have slightly different damage distributions which mean even though the pierce attack usually does more damage, the fire attack does slightly more damage per strike, which is occasionally useful; this is a nice feature that makes the unit a little bit more versatile.)

If you want it to average the score somehow (so that, for example, drakes (especially vulnerable to pierce) would take slightly more (but not a ton more) damage from this bow), I have no idea how to do that.
For example, the other party has 10% blade resistance and -50% pierce resistance
Then this attack will cause 9blade+15pierce=24 damage when hit
I don’t want to use multiple [attack] because it allows the player to choose the type that causes the most damage, which I don’t want to do
If I reduce the damage of an attack. This will cause me to be unable to cause the damage I hope when facing a unit that has -resistance to all damage
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: How to make one attack cause multiple types of damage

Post by Pilauli »

Hmm. That's certainly tougher.

In almost all cases, I'm sure it would be easier to find some other way to balance it, instead of introducing a completely new mechanic to gracefully handle split damage types. For example, what if you gave the unit a powerful blade attack, and a weaker pierce attack, that would do less damage most of the time so you could just use the blade attack against most enemies, but which would do a bit of extra damage to enemies that are weak to pierce?

If you are determined to implement a mixed damage type, as in if nothing else will do, then I recommend using the attacker_hits (and defender_hits) events along with the [harm_unit] action. This should (I think) work fine in the game, except that when you just casually look at the attack, it will look less powerful than it actually is. So it will work, but look a bit misleading.

Basically, you would make it so the bow does pierce (or blade, idc) damage, but also give it a dummy special ability that says something like "this attack also does an amount of blade (or pierce) damage equal to its base damage", then whenever a unit with this bow attack successfully hits an enemy with it, you use [harm_unit] to deal the extra damage of the other damage type.
User avatar
ERROR1025
Posts: 46
Joined: February 23rd, 2020, 10:18 am

Re: How to make one attack cause multiple types of damage

Post by ERROR1025 »

Pilauli wrote: November 7th, 2020, 7:20 am Hmm. That's certainly tougher.

In almost all cases, I'm sure it would be easier to find some other way to balance it, instead of introducing a completely new mechanic to gracefully handle split damage types. For example, what if you gave the unit a powerful blade attack, and a weaker pierce attack, that would do less damage most of the time so you could just use the blade attack against most enemies, but which would do a bit of extra damage to enemies that are weak to pierce?

If you are determined to implement a mixed damage type, as in if nothing else will do, then I recommend using the attacker_hits (and defender_hits) events along with the [harm_unit] action. This should (I think) work fine in the game, except that when you just casually look at the attack, it will look less powerful than it actually is. So it will work, but look a bit misleading.

Basically, you would make it so the bow does pierce (or blade, idc) damage, but also give it a dummy special ability that says something like "this attack also does an amount of blade (or pierce) damage equal to its base damage", then whenever a unit with this bow attack successfully hits an enemy with it, you use [harm_unit] to deal the extra damage of the other damage type.

Code: Select all

    [attack]
        name=ballista
        description= _"attack one"
        icon="attacks/ballista.png"
        type=pierce
        range=ranged
        damage=10
        number=3
	[event]
	name=attacker hits
		[filter]
			x,y=$x2|,$y2|
    		[/filter]
		[harm_unit]
			damage_type=impact
			amount=10
		[/harm_unit]
	[/event]
		[event]
	name=defender hits
		[filter]
			x,y=$x2|,$y2|
    		[/filter]
		[harm_unit]
			damage_type=impact
			amount=10
		[/harm_unit]
	[/event]
    [/attack]
I have not fulfilled my needs, how should I modify it?
When the attack hits, it has no effect other than direct 1-10pierce.
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: How to make one attack cause multiple types of damage

Post by Pilauli »

I think your filters are wrong. Try these.
(I didn't test them, but I think they'll work. I also hope I have put in enough comments that you can follow along.)

Code: Select all

[event]
    name=attacker hits
    first_time_only=no # This bit is important for events that can happen more than once :D

    # Happens when the attacker uses a ballista attack.
    [filter_attack]
        name=ballista
    [/filter_attack]

    # Harm the other unit.
    [harm_unit]
        # These are absolutely required.  It means "harm the unit who was attacked for 10 damage".
        [filter]
            id=$second_unit.id|
        [/filter]
        amount=10

        # Make sure the attacking unit (with the ballista) gets credit for doing the damage.
        [filter_second]
            id=$unit.id|
        [/filter_second]

        # Make sure the damage is scaled properly based on the attacker's alignment and the damage type.
        alignment=$unit.alignment|
        damage_type=impact

        # This means that if the unit is killed, any death events will fire properly and so on.
        fire_event=yes
    [/harm_unit]
[/event]

[event]
    name=defender hits

    # In both attacker_hits and defender_hits, the primary unit is the one who initiated the combat in the first place.
    # This means that here, the defender is hitting, so we have to check if the secondary unit (the defender) has the important attack.
    [filter_second_attack]
        name=ballista
    [/filter_second_attack]

    # This is basically the same thing as last time, except I swapped $unit with $second_unit.
    # This event fires when the defender successfully hits, so instead of the attacker harming the defender, this is the defender harming the attacker.
    [harm_unit]
        [filter]
            id=$unit.id|
        [/filter]
        amount=10

        [filter_second]
            id=$second_unit.id|
        [/filter_second]

        alignment=$second_unit.alignment|
        damage_type=impact

        fire_event=yes
    [/harm_unit]
[/event]
As far as your filters go, those events will never fire, because you are testing whether the primary unit (the attacker) is at the coordinates ($x2|, $y2|). I'm not actually sure if those are variables or not, but I am completely sure that if they are variables, they talk about where the secondary unit (the defender) is standing. So basically, your filters say "if the attacker and the defender are in the same place, do this."

By the way, let me refer you to the wiki, in case you haven't already found it. Some people have trouble picking their way through the details, but I've found it to be a huge help.
https://wiki.wesnoth.org/ReferenceWML
This page here has a list of a bunch of the things you might use down the right-hand side, so for example, if you wanted to see what information you can write for [harm_unit], you could look through the sidebar until you found the H section and click "harm_unit".
User avatar
Celtic_Minstrel
Developer
Posts: 2216
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: How to make one attack cause multiple types of damage

Post by Celtic_Minstrel »

I think it would actually be easier to use a custom damage type for this. I'd need to think about how to get the exact behaviour you wanted, but the basics that you would need to know for a custom damage type are:
  1. Pick a name for the type and use that in the attack, eg type=blade_and_pierce.
  2. Add a display name for the new damage type using the [language] tag:

    Code: Select all

    [+language] # Possibly the + is not needed, I'm unsure
    	type_blade_and_pierce=_"blade/pierce"
    [/language]
    
    Basically you add type_ on the front of the type name you used in the attack, and assign it a translatable string.
  3. Set up the resistance values for the new damage type for existing races that don't specify a value. For this you need [resistance_defaults] and WFL.

    Code: Select all

    [units]
    	[resistance_defaults]
    		id=blade_and_pierce
    		default="( (blade + pierce) / 2 )"
    	[/resistance_defaults]
    [/units]
    
    With that example formula, blade_and_pierce resistance always takes the average of a unit's separate blade and pierce resistances. I don't know if that formula will work for you, it's just an example.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
ERROR1025
Posts: 46
Joined: February 23rd, 2020, 10:18 am

Re: How to make one attack cause multiple types of damage

Post by ERROR1025 »

Pilauli wrote: November 7th, 2020, 10:11 am I think your filters are wrong. Try these.
(I didn't test them, but I think they'll work. I also hope I have put in enough comments that you can follow along.)

Code: Select all

[event]
    name=attacker hits
    first_time_only=no # This bit is important for events that can happen more than once :D

    # Happens when the attacker uses a ballista attack.
    [filter_attack]
        name=ballista
    [/filter_attack]

    # Harm the other unit.
    [harm_unit]
        # These are absolutely required.  It means "harm the unit who was attacked for 10 damage".
        [filter]
            id=$second_unit.id|
        [/filter]
        amount=10

        # Make sure the attacking unit (with the ballista) gets credit for doing the damage.
        [filter_second]
            id=$unit.id|
        [/filter_second]

        # Make sure the damage is scaled properly based on the attacker's alignment and the damage type.
        alignment=$unit.alignment|
        damage_type=impact

        # This means that if the unit is killed, any death events will fire properly and so on.
        fire_event=yes
    [/harm_unit]
[/event]

[event]
    name=defender hits

    # In both attacker_hits and defender_hits, the primary unit is the one who initiated the combat in the first place.
    # This means that here, the defender is hitting, so we have to check if the secondary unit (the defender) has the important attack.
    [filter_second_attack]
        name=ballista
    [/filter_second_attack]

    # This is basically the same thing as last time, except I swapped $unit with $second_unit.
    # This event fires when the defender successfully hits, so instead of the attacker harming the defender, this is the defender harming the attacker.
    [harm_unit]
        [filter]
            id=$unit.id|
        [/filter]
        amount=10

        [filter_second]
            id=$second_unit.id|
        [/filter_second]

        alignment=$second_unit.alignment|
        damage_type=impact

        fire_event=yes
    [/harm_unit]
[/event]
As far as your filters go, those events will never fire, because you are testing whether the primary unit (the attacker) is at the coordinates ($x2|, $y2|). I'm not actually sure if those are variables or not, but I am completely sure that if they are variables, they talk about where the secondary unit (the defender) is standing. So basically, your filters say "if the attacker and the defender are in the same place, do this."

By the way, let me refer you to the wiki, in case you haven't already found it. Some people have trouble picking their way through the details, but I've found it to be a huge help.
https://wiki.wesnoth.org/ReferenceWML
This page here has a list of a bunch of the things you might use down the right-hand side, so for example, if you wanted to see what information you can write for [harm_unit], you could look through the sidebar until you found the H section and click "harm_unit".
I encountered a new problem. When choosing a weapon for "AI" and "counterattack",thought that this weapon had only 1-10 piercing attacks. Is there a solution?
Pilauli
Posts: 115
Joined: August 18th, 2020, 12:56 pm

Re: How to make one attack cause multiple types of damage

Post by Pilauli »

The AI can't see the bonus damage, yeah.

I thought the attack_weight= and defense_weight= keys inside an attack ought to be able to help, but it looks like actually, it just checks whether they are positive numbers or not.
(Reference: https://wiki.wesnoth.org/UnitTypeWML#Attacks)

A hacky workaround would, I think, be to actually tell the AI that the attack does more damage, then use attack and attack_end events to reduce the damage before the fight, so it doesn't stack extra with the bonus impact damage, then increase it again after the fight to continue fooling the AI.

Celtic_Minstrel's solution (creating a custom damage type with a formula to determine each unit's resistances) is probably far superior if you can get it to work.
Post Reply