Weapon special that tests if one hit could kill the target

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
MyrddinEmrys
Posts: 14
Joined: March 1st, 2019, 11:42 am
Location: yes

Weapon special that tests if one hit could kill the target

Post by MyrddinEmrys »

Heyo!

I'm currently working on a weapon special that will increase the attack's chance to hit if one hit from the weapon would be enough to kill the target. This is what I have so far:

Code: Select all

#define WEAPON_SPECIAL_SACRIFICE VALUE
# VALUE should be the maximum damage of the attack
    [chance_to_hit]
        name= _ "sacrifice"
        description= _ "If a single hit of this weapon would be enough to kill an opponent, the weapon automatically hits."
        apply_to=self
        [filter_opponent]
            formula=self.hitpoints <= {VALUE}
        [/filter_opponent]
        value=100
    [/chance_to_hit]
#enddef
Now my question is… how do I make this take into account the target's resistances as well as alterations to the base damage from status effects such as slow? Basically, I'm looking for the way to have the filter fetch the effective damage the attack would be doing.

Would be great if someone could help me out :)
User avatar
beetlenaut
Developer
Posts: 2825
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Weapon special that tests if one hit could kill the target

Post by beetlenaut »

First of all, there is no simple way to find the chance to kill with WML. There just isn't a command for it. You can find the resistances, slows status, leadership, and time of day, so you can calculate it manually. (Someone has probably done it before.) You should also be able to get at it with Lua, but I don't know how to do that off the top of my head.

Second, there are four or five problems with the posted code, but I don't think me rewriting it would help you. This is how you should have written it: :eng:
First, change the chance to hit of one unit to 100% (I usually use a moveto event to activate stuff like this), and then test it to make sure it works. Make sure you can turn it on and off when you want to.
Second, add a weapon special to the unit, and then test that to make sure it shows up.
Next, make the new weapon special change the CTH, and then test that to make sure it does.
And continue like this.
In other words: you should always add new pieces one bit at a time. This is how experienced coders do it. Doing it this way means that you know where the error has to be. You can check the wiki for the tag or key you just tried to use, and see what you did wrong, or ask on this forum. You will also get better and faster help here if you can post what you did and what didn't work when you tested it. People aren't that interested in telling you what is wrong with this because there are so many things and you should already have found and fixed some of them yourself through testing.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
User avatar
MyrddinEmrys
Posts: 14
Joined: March 1st, 2019, 11:42 am
Location: yes

Re: Weapon special that tests if one hit could kill the target

Post by MyrddinEmrys »

Thanks for the feedback, I appreciate it! :D
beetlenaut wrote: August 21st, 2022, 10:28 pm You can find the resistances, slows status, leadership, and time of day, so you can calculate it manually. (Someone has probably done it before.)
What I was trying to achieve basically boils down to how to do this. However, the more I think about it, the more I realize I might be going down a rabbit hole here that's not worth going down. For now, I've settled for a simpler alternative that was suggested to me: instead of checking whether a hit could kill a target, it will check if the target has less than 25% of its max hitpoints remaining. I have gotten that version working now without much issue, and for the context in which I use the ability, it boils down to roughly the same effect in practice (since the weapon that gets this special is weak enough compared to the unit's other weapons that it will rarely be worth picking if it's not a guaranteed kill).

As a sidenote, I must admit I don't quite understand what problems you mean, since the code I posted above did work fine for what it was supposed to do (that is, set the weapon's hit chance to 100% when the target's hp is less than {VALUE}). My goal here was not to get that code working (it already did), but to change it to do something different, more complex (that is, set the weapon's hit chance to 100% when the target's hp is less than the damage it would take from one attack).
User avatar
Celtic_Minstrel
Developer
Posts: 2207
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Weapon special that tests if one hit could kill the target

Post by Celtic_Minstrel »

If I recall correctly, in [filter_opponent] you can reference the attacking unit as other. Assuming that's true, I think there should be a way to get what you want.

There is a WFL function (possibly undocumented) called resistance_on which gives you a unit's resistance. You would use it like resistance_on(unit, location, damage_type, is_attacker). The value it returns can basically be multiplied by the weapon's base damage to get the actual damage that would be taken on one hit.

Then you need to actually obtain that base damage. This is easiest if you accept the limitation that a unit can only have one weapon with the sacrifice ability. Assuming that limitation, what you need to do is search the unit's weapons for the single one with the sacrifice ability and grab the damage from there. You can use the filter function in WFL to do this. This is used something like filter(list, some condition) where the condition is any valid WFL formula where self refers to an element in the list. The output is a list reduced to only those elements that satisfy the condition. The last step is getting weapons from a unit and damage from a weapon. This looks like unit.attacks and weapon.damage.

You also need to account for the time of day bonus (which can be obtained with the tod_bonus function), slows status (which I think is unit.status.slows), and leadership (not sure how to get this in WFL). Put it all together and you get a rather gargantuan formula that looks something like this:

Code: Select all

"
	self.hitpoints < base_damage * resistance * tod_bonus * leadership * slows_penalty
where
	base_damage = attacker_weapon.damage
	resistance = resistance_on(self, self.loc, attacker_weapon.type, 0) / 100.0
	tod_bonus = tod_bonus(other.loc) / 100.0 # I think this is only correct for lawful units, probably needs more work #
	leadership = # not sure what to put here # 1
	slows_penalty = if(self.status.slowed, 0.5, 1.0)
where
	attacker_weapon = filter(other.attacks, 'sacrifice' in self.specials)[0]
"
That's still incomplete, but I think it's a step in the right direction.

We should definitely consider adding a WFL function that does all this work for you, though.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply