Help needed with a "saviour" ability
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.
- pipapopinguin
- Posts: 35
- Joined: November 3rd, 2019, 10:36 am
Help needed with a "saviour" ability
I am working on an ability to save an adjacent from a fatal blow, take the damage upon themself and let the attack go on. I wrote this code for the time being without any animations yet:
But as I have discovered the attack gets ended without checking the units health after the event. I honestly have no clue what to do so that I can solve it, because the only attack related event before "attack hits" is name=attack and there is no such variable to see which attacks hit (unless in animationWML for some reason with the variable "hits" and no it doesn't work in abilities.cfg). So yeah that's my problem any solutions?
Code: Select all
#define ABILITY_GOLDENGUARD
[dummy]
id=goldenguard
name= _ "goldenguard"
female_name= _ "female^goldenguard"
description= _ "If an adjecent unit would be dealt a fatal blow, the owner of this ability will hop in, to protect the attacked unit and take the damage."
[/dummy]
[/abilities]
[event]
first_time_only=no
name=attacker hits
[filter]
side=$side_number
[/filter]
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[filter_condition]
[variable]
name=second_unit.hitpoints
less_than_equal_to=0
[/variable]
[/filter_condition]
[heal_unit]
[filter]
id=$second_unit.id
[/filter]
amount=$damage_inflicted
[/heal_unit]
[harm_unit]
[filter]
ability=goldenguard
[filter_adjacent]
side=$other_unit.side
id=$second_unit.id
[/filter_adjacent]
[/filter]
amount=$weapon.damage
damage_type=$weapon.type
alignment=$unit.alignment
[/harm_unit]
[/event]
...
Re: Help needed with a "saviour" ability
The
To get an "attack hits" event, you need to write two events, "attacker hits" and "defender hits", with the same content (just mind the switched primary and secondary unit roles).
second_unit
variable is not stored at the time of event filters, so you can't use it in [filter_condition]. Automatically stored variables such as this are stored at the time they are first accessed inside the event (so not yet at filtering-time).To get an "attack hits" event, you need to write two events, "attacker hits" and "defender hits", with the same content (just mind the switched primary and secondary unit roles).
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: The Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Old UMC works: The Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
- pipapopinguin
- Posts: 35
- Joined: November 3rd, 2019, 10:36 am
Re: Help needed with a "saviour" ability
Are you sure? that seemed to work as it should, but anyway, I made the event with an [if] tag with the [variable] tag as condition, but the attack still gets cancelled as soon as the hitpoints drop below zero, again I am still healing it, but that doesnt change anything other than the fact it survives.
Also I only want the event to fire in the defense so no defender hits event
Re: Help needed with a "saviour" ability
Well, I was quoting the note at this section, and I remember it not working for me at filtering time. That was a long time ago, it may have been changed since
I think I recall a similar issue where hitpoints weren't tracked "live" during these events, and if it got below zero, the attack was interrupted anyway, no matter if it was healed in the event. I can't find the thread, and I'm not even sure why it would work like that, so maybe someone else can explain that, but in the meantime, the simple workaround would be to execute your code one hit earlier.
That is, in your attacker hits event, if the remaining hitpoints of the unit are <= $damage_inflicted (so could be killed with the next hit), then do your stuff, heal and do damage to the adjacent unit.
This will not catch very complicated other special attacks though, that may do a different amount of damage with each hit, etc. So if you go for this, it might be a good idea to append the description so that this only triggers for standard attacks.
I think I recall a similar issue where hitpoints weren't tracked "live" during these events, and if it got below zero, the attack was interrupted anyway, no matter if it was healed in the event. I can't find the thread, and I'm not even sure why it would work like that, so maybe someone else can explain that, but in the meantime, the simple workaround would be to execute your code one hit earlier.
That is, in your attacker hits event, if the remaining hitpoints of the unit are <= $damage_inflicted (so could be killed with the next hit), then do your stuff, heal and do damage to the adjacent unit.
This will not catch very complicated other special attacks though, that may do a different amount of damage with each hit, etc. So if you go for this, it might be a good idea to append the description so that this only triggers for standard attacks.
Main UMC campaigns: The Ravagers - now for 1.16, with new bugs!
Old UMC works: The Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
Old UMC works: The Underness Series, consisting of 5 parts: The Desolation of Karlag, The Blind Sentinel, The Stone of the North, The Invasion Of The Western Cavalry, Fingerbone of Destiny
- Celtic_Minstrel
- Developer
- Posts: 2207
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Help needed with a "saviour" ability
I think your filter_condition is wrong. It should be:
In other words, you want the event to trigger when the hit would normally kill the second unit, not when the second unit is already dead. You'd still heal the unit for
Code: Select all
[variable]
name=second_unit.hitpoints
less_than_equal_to=$damage_inflicted
[/variable]
$damage_inflicted
. I think there's an edge case that wouldn't work this way though, if the damage is greater than the unit's total hit points…I'm pretty sure this is not true. Looking at the code, the filter_condition is checked at the same time as all other filters, which is after defining the scoped unit an weapon variables.
- pipapopinguin
- Posts: 35
- Joined: November 3rd, 2019, 10:36 am
Re: Help needed with a "saviour" ability
Thats exactly what WhiteWolf wanted me to do as a "workaround", but as he said, that would trigger too early (and I tested it, it does trigger to early).Celtic_Minstrel wrote: ↑July 19th, 2021, 2:00 pm I think your filter_condition is wrong. It should be:
Code: Select all
[variable] name=second_unit.hitpoints less_than_equal_to=$damage_inflicted [/variable]
But all that doesnt matter anymore since I was too bored and created this abnormality of code:
Code: Select all
[dummy]
id=goldenguard
name= _ "goldenguard"
female_name= _ "female^goldenguard"
description= _ "If an adjecent unit would be dealt a fatal blow, the owner of this ability will hop in, to protect the attacked unit and take the damage."
[/dummy]
[/abilities]
[event]
name=attack
first_time_only=false
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[store_unit_defense]
id=$second_unit.id
loc_x,loc_y=$x2,$y2
variable=second_unit_defense
[/store_unit_defense]
[store_unit_defense]
id=$unit.id
loc_x,loc_y=$x1,$y1
variable=first_unit_defense
[/store_unit_defense]
[set_variable]
name=first_unit_attacks_left
value=$weapon.number
[/set_variable]
[set_variable]
name=second_unit_attacks_left
value=$second_weapon.number
[/set_variable]
[/event]
[event]
name=defender hits
first_time_only=no
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[set_variable]
name=second_unit_attacks_left
sub=1
[/set_variable]
[/event]
[event]
name=defender misses
first_time_only=no
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[set_variable]
name=second_unit_attacks_left
sub=1
[/set_variable]
[/event]
[event]
name=attacker misses
first_time_only=no
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[set_variable]
name=first_unit_attacks_left
sub=1
[/set_variable]
[/event]
[event]
first_time_only=no
name=attacker hits
[filter]
side=$side_number
[/filter]
[filter_second]
[filter_adjacent]
ability=goldenguard
side=$other_unit.side
[/filter_adjacent]
[/filter_second]
[set_variable]
name=first_unit_attacks_left
sub=1
[/set_variable]
[if]
[variable]
name=second_unit.hitpoints
less_than_equal_to=0
[/variable]
[then]
#animations
[if]
[variable]
name=unit.facing
contains=e
[/variable]
[then]
#animations
[/else]
[/if]
[heal_unit]
[filter]
id=$second_unit.id
[/filter]
amount=$damage_inflicted
[/heal_unit]
[if]
[variable]
name=weapon.range
equals=ranged
[/variable]
[then]
[set_variable]
name=damage_by_2
formula= "$damage_inflicted / 2"
[/set_variable]
[/then]
[/if]
[harm_unit]
[filter]
ability=goldenguard
[filter_adjacent]
side=$other_unit.side
id=$second_unit.id
[/filter_adjacent]
[/filter]
[filter_second]
id=$unit.id
[/filter_second]
experience=no
fire_event=yes
amount=$damage_by_2
damage_type=$weapon.type
alignment=$unit.alignment
[/harm_unit]
[repeat]
times=$first_unit_attacks_left
[do]
[set_variable]
name=fight_result_attacker
rand=1..100
[/set_variable]
[set_variable]
name=fight_result_defender
rand=1..100
[/set_variable]
[sync_variable]
name=fight_result_attacker,fight_result_defender
[/sync_variable]
[if]
[variable]
name=fight_result_defender
greater_than=$first_unit_defense
[/variable]
[variable]
name=second_unit_attacks_left
greater_than=0
[/variable]
[then]
[harm_unit]
[filter]
id=$unit.id
[/filter]
[filter_second]
id=$second_unit.id
[/filter_second]
amount=$second_weapon.damage
damage_type=$second_weapon.type
alignment=$unit.alignment
animate=yes
fire_event=yes
experience=no
[primary_attack]
name=$second_weapon.name
range=$second_weapon.range
type=$second_weapon.type
[/primary_attack]
[/harm_unit]
[/then]
[/if]
[set_variable]
name=second_unit_attacks_left
sub=1
[/set_variable]
[if]
[variable]
name=fight_result_attacker
greater_than=$second_unit_defense
[/variable]
[variable]
name=first_unit_attacks_left
greater_than=0
[/variable]
[then]
[harm_unit]
[filter]
ability=goldenguard
[filter_adjacent]
side=$other_unit.side
id=$second_unit.id
[/filter_adjacent]
[/filter]
[filter_second]
id=$unit.id
[/filter_second]
experience=no
amount=$damage_by_2
damage_type=$weapon.type
alignment=$unit.alignment
animate=yes
fire_event=yes
[primary_attack]
name=$weapon.name
range=$weapon.range
type=$weapon.type
[/primary_attack]
[/harm_unit]
[/then]
[/if]
[set_variable]
name=first_unit_attacks_left
sub=1
[/set_variable]
[/do]
[/repeat]
[repeat]
times=$second_unit_attacks_left
[do]
[set_variable]
name=fight_result_attacker
rand=1..100
[/set_variable]
[set_variable]
name=fight_result_defender
rand=1..100
[/set_variable]
[sync_variable]
name=fight_result_attacker,fight_result_defender
[/sync_variable]
[if]
[variable]
name=fight_result_defender
greater_than=$first_unit_defense
[/variable]
[variable]
name=first_unit_attacks_left
greater_than=0
[/variable]
[then]
[harm_unit]
[filter]
id=$unit.id
[/filter]
[filter_second]
id=$second_unit.id
[/filter_second]
amount=$second_weapon.damage
damage_type=$second_weapon.type
alignment=$unit.alignment
animate=yes
fire_event=yes
experience=no
[primary_attack]
name=$second_weapon.name
range=$second_weapon.range
type=$second_weapon.type
[/primary_attack]
[/harm_unit]
[/then]
[/if]
[set_variable]
name=second_unit_attacks_left
sub=1
[/set_variable]
[/do]
[/repeat]
#animation stuff
[/then]
[/if]
[/event]
[event]
name=die
first_time_only=no
[filter]
ability=goldenguard
[filter_adjacent]
[not]
id=$second_unit.id
[/not]
[/filter_adjacent]
[/filter]
#message stuff
[modify_unit]
[filter]
id=$second_unit.id
[/filter]
[effect]
apply_to=experience
increase=$($unit.level*4)
[/effect]
[/modify_unit]
[/event]
[event]
name=attack end
first_time_only=no
{CLEAR_VARIABLE fight_result_defender}
{CLEAR_VARIABLE fight_result_attacker}
{CLEAR_VARIABLE second_unit_attacks_left}
{CLEAR_VARIABLE first_unit_attacks_left}
{CLEAR_VARIABLE first_unit_defense}
{CLEAR_VARIABLE second_unit_defense}
{CLEAR_VARIABLE harm_amount}
{CLEAR_VARIABLE heal_amount}
[/event]
It basicly keeps track of the attacks of the units and after the attack is over, it simulates the left over attacks with harm unit and calculates the chances of them to hit. (without specials tho, maybe you can fix that)
- Celtic_Minstrel
- Developer
- Posts: 2207
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Help needed with a "saviour" ability
What exactly is it that triggers too early? Can you give me a detailed outline of what order things should happen in and also what order they happen in when you use this suggestion? I have a few ideas on how to solve the too-early issue but I need to know more about what exactly the issue is.pipapopinguin wrote: ↑July 19th, 2021, 10:09 pm Thats exactly what WhiteWolf wanted me to do as a "workaround", but as he said, that would trigger too early (and I tested it, it does trigger to early).
- pipapopinguin
- Posts: 35
- Joined: November 3rd, 2019, 10:36 am
Re: Help needed with a "saviour" ability
the event itself, including its filter.
The damage is done to the unit and the attack gets cancelled if the hp drop bellow 0, before any name=attacker hits [event]s get triggered.
I think it is intended to work that way, but there is no event name, which makes it so, so that I can modify the attack outcome, before this calculation occurs.
- beetlenaut
- Developer
- Posts: 2825
- Joined: December 8th, 2007, 3:21 am
- Location: Washington State
- Contact:
Re: Help needed with a "saviour" ability
There may be a language or terminology issue here, because I am more confused than before. I still don't know which part of the event is happening too early. Also, filters do not trigger, so I don't understand what you mean by that statement.
I think this is what you want to have happen:
I'm pretty sure this is what Celtic_Minstrel meant by a detailed outline.
If these steps are not correct, modify them or rewrite them. Then explain which step is happening before you want it to, and when you want it to happen. If you can do that, we will be able to help you effectively.
I think this is what you want to have happen:
Code: Select all
Attack begins
Attacker hits
If the defender's HP drops below zero:
Defender receives the HP it lost in the last strike
Unit with the "saviour" ability loses that amount of HP
Attack ends
Otherwise, attack continues normally
If these steps are not correct, modify them or rewrite them. Then explain which step is happening before you want it to, and when you want it to happen. If you can do that, we will be able to help you effectively.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
- Celtic_Minstrel
- Developer
- Posts: 2207
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Help needed with a "saviour" ability
Yeah, that's the kind of thing I'm looking for, beetlenaut. If the event is triggering "too early" there must be something you're seeing that indicates that it's too early. I want to know exactly what that something is.
Also, for the outline of what does happen, please use the filter I provided instead of the filter that compares to zero.
Also, for the outline of what does happen, please use the filter I provided instead of the filter that compares to zero.
- lhybrideur
- Posts: 369
- Joined: July 9th, 2019, 1:46 pm
Re: Help needed with a "saviour" ability
From what I understand, here is what he wantsbeetlenaut wrote: ↑July 20th, 2021, 10:46 pm There may be a language or terminology issue here, because I am more confused than before. I still don't know which part of the event is happening too early. Also, filters do not trigger, so I don't understand what you mean by that statement.
I think this is what you want to have happen:I'm pretty sure this is what Celtic_Minstrel meant by a detailed outline.Code: Select all
Attack begins Attacker hits If the defender's HP drops below zero: Defender receives the HP it lost in the last strike Unit with the "saviour" ability loses that amount of HP Attack ends Otherwise, attack continues normally
If these steps are not correct, modify them or rewrite them. Then explain which step is happening before you want it to, and when you want it to happen. If you can do that, we will be able to help you effectively.
Code: Select all
1) Attack begins
2)
a) Attacker hits
b) If the defender's HP drops below zero:
b') Defender receives the HP it lost in the last strike
b'') Unit with the "saviour" ability loses that amount of HP
3) Same as 2 until attackers has no more attacks left
- pipapopinguin
- Posts: 35
- Joined: November 3rd, 2019, 10:36 am
Re: Help needed with a "saviour" ability
Yes thats what I wanted, but I dont understand why this even continues, as i already am finished (see my code above), it may not be the best solution, but I actually don't need any help anymore, as it is good enough.lhybrideur wrote: ↑July 21st, 2021, 12:08 pmFrom what I understand, here is what he wantsbeetlenaut wrote: ↑July 20th, 2021, 10:46 pm There may be a language or terminology issue here, because I am more confused than before. I still don't know which part of the event is happening too early. Also, filters do not trigger, so I don't understand what you mean by that statement.
I think this is what you want to have happen:I'm pretty sure this is what Celtic_Minstrel meant by a detailed outline.Code: Select all
Attack begins Attacker hits If the defender's HP drops below zero: Defender receives the HP it lost in the last strike Unit with the "saviour" ability loses that amount of HP Attack ends Otherwise, attack continues normally
If these steps are not correct, modify them or rewrite them. Then explain which step is happening before you want it to, and when you want it to happen. If you can do that, we will be able to help you effectively.
Code: Select all
1) Attack begins 2) a) Attacker hits b) If the defender's HP drops below zero: b') Defender receives the HP it lost in the last strike b'') Unit with the "saviour" ability loses that amount of HP 3) Same as 2 until attackers has no more attacks left