WFL and damage special

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
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

WFL and damage special

Post by vghetto »

Hi,

I'm trying to do a weapon special [damage] that is based on the defense of the other unit. I'm having a hard time figuring out the correct WFL to make it happen.

The attacking unit damage should be multiplied by the other unit's defense * 0.01.
This is same as saying (self.damage * other.defense) / 100

Any ideas on what is the correct formula?
I tried defense_on( other , other.loc ) and chance_to_hit( other , other.loc ). They should be the same right?

Code: Select all

[damage]
    id=truestrike                       
    name= _ "truestrike"                
    description= _ "Strike true."       
    multiply="0.01 * d where d = defense_on( other , other.loc )"
    apply_to=self                       
    cumulative=no                       
[/damage]      
Thanks
User avatar
Ravana
Forum Moderator
Posts: 2952
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: WFL and damage special

Post by Ravana »

> In order to use a formula in these keys, you must enclose it in parentheses.
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

Ok, this is getting interesting.

Enclosing it parentheses gave an error.

Code: Select all

multiply="(0.01 * d where d = defense_on( other , other.loc ))"
Invalid WML found: Formula error in ability or weapon special: Illegal unary operator: '=' at formula:1) (2)
But doing it this way is getting us closer to the result.

Code: Select all

multiply="(0.01 * defense_on( tmp_other, tmp_other.loc ) where tmp_other = unit_at(other.loc))"
But it is returning the defense of the current attacking unit and not the defending other unit.

Any ideas?

Edit:
changed other.loc to defender.loc. Same result.

Hmm, self, student, attacker, defender, other all seem to point to the same thing, the current attacking unit.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: WFL and damage special

Post by WhiteWolf »

I'm not a WFL expert, but why do you need to use an external variable? Wouldn't just

Code: Select all

multiply="(0.01 * defense_on( unit_at(other.loc), other.loc ))"
work?
Just an idea though.
I also didn't find defense_on and unit_at among wiki wfl functions, so I'm guessing they are your custom ones - if it's returning defense for the wrong unit, then maybe unit_at is buggy?
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
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

I simplified to this.

Code: Select all

multiply="(defense_on(unit_at(loc(defender.x,defender.y)), loc(defender.x,defender.y)))"
The problem seems to be with the values of defender and other. They are always the same value as self.

defense_on and unit_at are part of wesnoth. https://wiki.wesnoth.org/FormulaAI_Functions
I don't think the problem is with those functions.
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: WFL and damage special

Post by WhiteWolf »

Hmm, banner at the top: "Formula AI is still functional for the time being, but it is not maintained any more. That applies to both the code and these wiki pages. " :hmm:

I'm guessing it wasn't updated to the 1.15 feature of self, student, attacker, defender, other.

EDIT:
Btw, since 1.15.3, defense is included with the unit object. So simply just

Code: Select all

multiply="(0.01 * defender.defense)"
should work I think.
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
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

WhiteWolf wrote: January 8th, 2021, 8:53 pm Btw, since 1.15.3, defense is included with the unit object. So simply just

Code: Select all

multiply="(0.01 * defender.defense)"
should work I think.
Unfortunately, that gave an error and exited wesnoth.

Code: Select all

multiply="(defender.defense)"
ERROR: TYPE ERROR: expected an integer or a decimal but found map ([castle->60, cave->40, flat->40, forest->50, frozen->20, fungus->50, hills->50, mountains->60, reef->30, sand->30, shallow_water->20, swamp_water->20, village->60])

I don't think it would have worked anyway because I checked the x coordinate value of defender.x and it always matched the unit with the object and doing the attack, not the defending unit at x+1.

Code: Select all

multiply="(defender.x)"
User avatar
WhiteWolf
Forum Moderator
Posts: 769
Joined: September 22nd, 2009, 7:48 pm
Location: Hungary

Re: WFL and damage special

Post by WhiteWolf »

Ah, so defense is a map object. Well, I have no idea how to get the terrain for it from the defending unit if defender doesn't seem to work properly.
I guess someone with more in-depth knowledge about wfl and the 1.15 stuff should take a look at what's going on. I'm out of ideas. :(
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
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

Thanks, I think the easiest solution would be having defender and other assigned correctly.

A convoluted solution would be having a [damage] case for each direction. 6 in total.
n,ne,se,s,sw,nw i think. Then use direction_from() somehow like backstab?
direction_from isn't documented in the wiki btw.
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

A working solution.

This is a simple implementation of No_Randomness_Mod and one feature of Advanced_Wesnoth_Wars as an object.

Code: Select all

                        [object]
                            name=_"Ring of Magnetism"
                            image=icons/ring_gold.png
                            description=_"This ring greatly increases the wearer's accuracy."
                            [effect]
                                apply_to=attack
                                remove_specials=magical,marksman,magnetic,magnetic_cursed
                            [/effect]
                            [effect]
                                apply_to=new_ability
                                [abilities]
                                    [dummy]
                                        id=truestrike
                                        name=_"truestrike"
                                        female_name=_"female^truestrike"
                                        description=_"All of this unit's attacks are true."
                                    [/dummy]
                                [/abilities]
                            [/effect]
                            [effect]
                                apply_to=attack
                                [set_specials]
                                    mode=append
                                    [chance_to_hit]
                                        id=magnetic
                                        value=100
                                        apply_to=self
                                        cumulative=no
                                    [/chance_to_hit]
                                    [truestrike]
                                        id=truestrike
                                        name= _ "truestrike"
                                        description= _ "Strike true."
				    [/truestrike]
                                    [damage]
                                        id=truestrike_se
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, se)) , direction_from(loc, se))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=se
					[/filter_adjacent]
                                    [/damage]
                                    [damage]
                                        id=truestrike_ne
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, ne)) , direction_from(loc, ne))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=ne
					[/filter_adjacent]
                                    [/damage]
                                    [damage]
                                        id=truestrike_nw
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, nw)) , direction_from(loc, nw))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=nw
					[/filter_adjacent]
                                    [/damage]
                                    [damage]
                                        id=truestrike_sw
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, sw)) , direction_from(loc, sw))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=sw
					[/filter_adjacent]
                                    [/damage]
                                    [damage]
                                        id=truestrike_s
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, s)) , direction_from(loc, s))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=s
					[/filter_adjacent]
                                    [/damage]
                                    [damage]
                                        id=truestrike_n
					multiply="( 1 - ( 0.01 * defense_on( unit_at(direction_from(loc, n)) , direction_from(loc, n))))"
                                        apply_to=attacker
					active_on=offense
                                        cumulative=no
					[filter_adjacent]
						is_enemy=yes
						count=1
						adjacent=n
					[/filter_adjacent]
                                    [/damage]
                                [/set_specials]
                            [/effect]
                        [/object]
User avatar
Celtic_Minstrel
Developer
Posts: 2166
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: WFL and damage special

Post by Celtic_Minstrel »

vghetto wrote: January 8th, 2021, 7:20 pm Ok, this is getting interesting.

Enclosing it parentheses gave an error.

Code: Select all

multiply="(0.01 * d where d = defense_on( other , other.loc ))"
Invalid WML found: Formula error in ability or weapon special: Illegal unary operator: '=' at formula:1) (2)
But doing it this way is getting us closer to the result.
The symbol d is reserved as the dice operator, so you can't use it as a variable.


WhiteWolf wrote: January 8th, 2021, 8:41 pm I'm not a WFL expert, but why do you need to use an external variable?
Using variables often makes the formula clearer. It probably won't make any difference in this specific example, though.

WhiteWolf wrote: January 8th, 2021, 8:53 pm Hmm, banner at the top: "Formula AI is still functional for the time being, but it is not maintained any more. That applies to both the code and these wiki pages. " :hmm:
FormulaAI refers to the use of WFL to define AI behaviour. Functions such as defense_on that are defined on that page will still continue to work - they're not deprecated. Actually, the ones that aren't deprecated should be moved to another wiki page, I just haven't done that yet…
WhiteWolf wrote: January 8th, 2021, 8:53 pm I'm guessing it wasn't updated to the 1.15 feature of self, student, attacker, defender, other.
This is definitely possible.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

vghetto wrote: January 8th, 2021, 10:35 pm A working solution.
This is still broken, when you have 2 adjacent enemy units it will multiply by the resistance of both :(
vghetto
Posts: 755
Joined: November 2nd, 2019, 5:12 pm

Re: WFL and damage special

Post by vghetto »

This seems to work in 1.15.9+
Use defender, the wfl variable other will point at self in this context.

Code: Select all

 [effect]
      apply_to=attack
      [set_specials]
          mode=append
          [chance_to_hit]
              id=magnetic
              value=100
              apply_to=self             
              cumulative=no             
          [/chance_to_hit]          
          [damage]
              id=truestrike             
              name= _ "truestrike"      
              description= _ "Strike true."
              multiply="( 1 - ( 0.01 * defense_on( defender, defender.loc )))"
              apply_to=attacker         
              active_on=offense         
              cumulative=no             
          [/damage]
      [/set_specials]
  [/effect]
Edit:

Hmm, time of day isn't being taken into account :hmm:
even with cumulative=yes
Post Reply