ability wml help needed

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
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

ability wml help needed

Post by Edwylm »

I am currently working on an ability for my era. This is the first time I'm working from scratch.

The idea is to give units bonuses fighting against curtain units. Example would be a unit that slays dragons but the bonus would only play in affect against drakes and dragons.
I could do it a single ability but that would be quite a lot for what I am aiming for. Along with with having errors. I feel like I need to add in events but I know little. I also looked into the WML for guidance.

basic coding sadly doesn't work

Code: Select all

#define ABILITY_(NAME)SLAYER
    [attack]
        id=slayer
        value=15
        cumulative=no
        name= _ "(name)slayer"
        description="This unit has the knowledge and experience in dealing with (name)."
        affect_self=yes

            [filter]
                race=
            [/filter]
            [filter]
                unit=
            [/filter]
            [filter]
                alignment=
            [/filter]

    [/attack]
#enddef

Another attempt using macros to try to make the coding smaller

Code: Select all

#define ABILITY_{TYPE}SLAYER
    [attack]
        id=slayer
        value=15
        cumulative=no
        {NAME}
        description="This unit has the knowledge and experience in dealing with."
        affect_self=yes
{FILTERS}

    [/attack]
#enddef

#define ABILITY_DRAGONSLAYER
     {ABILITY_DRAGONSLAYER}
        name= _ "dragonslayer"
            [filter]
                race=drake
            [/filter]
            [filter]
                unit=OE Fire Dragon,OE Wyvern
            [/filter]
#enddef

#define ABILITY_CHAOTICSLAYER
     {ABILITY_CHAOTICSLAYER}
        name= _ "chaotic slayer"
            [filter]
                alignment=chaotic
            [/filter]
#enddef
User avatar
Ravana
Forum Moderator
Posts: 2934
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: ability wml help needed

Post by Ravana »

[filter] is not recognized in [attack]. See https://wiki.wesnoth.org/AbilitiesWML#C ... on_special

You might want ABILITY_SLAYER NAME instead of ABILITY_(NAME)SLAYER https://wiki.wesnoth.org/PreprocessorRef#.23define
User avatar
Celtic_Minstrel
Developer
Posts: 2158
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: ability wml help needed

Post by Celtic_Minstrel »

I don't think you'd need any events for this type of ability (though it depends on precisely what kind of bonus you intend to give).

If you want a bonus to hit chance or damage, just use a [chance_to_hit] or [damage] weapon special filtering on the target race.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

Re: ability wml help needed

Post by Edwylm »

Well I got base of it to work

Code: Select all

#define WEAPON_SPECIAL_SLAYER_TROLL
    [damage]
        id=slayer
        add=2
        cumulative=no
        name= _ "troll slayer"
        description="This unit has the knowledge and experience in dealing with."
        apply_to=self
[filter_opponent]
race=troll
[/filter_opponent]
    [/damage]
#enddef
only issues I have right now are
#1 how to do the [filter_opponent] for chaotic alignment
#2 for the value/add part. I'm unsure on how to do this balancing wise, I think being a % based might be best.
User avatar
josteph
Inactive Developer
Posts: 741
Joined: August 19th, 2017, 6:58 pm

Re: ability wml help needed

Post by josteph »

#1:

Code: Select all

[filter_opponent]
    [filter_wml]
        alignment=chaotic
    [/filter_wml]
[/filter_opponent]
User avatar
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

Re: ability wml help needed

Post by Edwylm »

Thanks for the help.

I got the rest worked out. Now I would like to macro some of the coding if possible. Not sure how to do filter_opponent macro part.

Code: Select all

#define WEAPON_SPECIAL_SLAYER_NAME
    [damage]
        id=slayer {NAME}
        multiply=1.15
        cumulative=yes
        name= _ "{NAME} slayer"
        description="This unit has the knowledge and experience in dealing with."
        apply_to=self

{filter_opponent}
    [/damage]
#enddef

#define WEAPON_SPECIAL_SLAYER_DRAGON
[filter_opponent]
       race=drake
       [or]
       id=OE Fire Dragon,OE Wyvern
       [/or]
[/filter_opponent]
#enddef

#define WEAPON_SPECIAL_SLAYER_CHAOTIC
[filter_opponent]
    [filter_wml]
        alignment=chaotic
    [/filter_wml]
[/filter_opponent]
#enddef
User avatar
josteph
Inactive Developer
Posts: 741
Joined: August 19th, 2017, 6:58 pm

Re: ability wml help needed

Post by josteph »

The syntax is #define name arg1 arg2 and then you can use {arg1} and {arg2} until the next #enddef. You need to add some arguments on the first line. You can debug with wesnoth --preprocess.
User avatar
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

Re: ability wml help needed

Post by Edwylm »

I fixed my mistakes. however on the {arg2} i can easily use that for something like race={arg2}. I'm having the problem of for example the

Code: Select all

[filter_wml]
        alignment=chaotic
    [/filter_wml]
part. i imagine i need to use [set_variable] to store the [filter_opponents] for different specials to use for {arg2}?
User avatar
Ravana
Forum Moderator
Posts: 2934
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: ability wml help needed

Post by Ravana »

WML macro is text replace. If it wouldnt work if you manually expanded it, it wont work as macro. Similarly, if you dont need to use set_variable without macro, then you wont need it with macro either.
User avatar
josteph
Inactive Developer
Posts: 741
Joined: August 19th, 2017, 6:58 pm

Re: ability wml help needed

Post by josteph »

You can pass the whole [filter_wml] construct as a single macro argument, for example:

Code: Select all

#define WEAPON_SPECIAL_SLAYER NAME FILTER_OPPONENT
    [damage]
        id=slayer {NAME}
        multiply=1.15
        cumulative=yes
        name= _ "{NAME} slayer"
        description="This unit has the knowledge and experience in dealing with."
        apply_to=self
        [filter_opponent]
            {FILTER_OPPONENT}
        [/filter_opponent]
    [/damage]
#enddef

...

    {WEAPON_SPECIAL_SLAYER troll (
        [filter_wml]
            alignment=chaotic
        [/filter_wml]
    )}
User avatar
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

Re: ability wml help needed

Post by Edwylm »

Ah I need to do a (containing code) didn't know that worked.

Thank you all for helping.
User avatar
josteph
Inactive Developer
Posts: 741
Joined: August 19th, 2017, 6:58 pm

Re: ability wml help needed

Post by josteph »

You're welcome. I've added an example to https://wiki.wesnoth.org/PreprocessorRe ... inclusions
User avatar
Edwylm
Posts: 238
Joined: August 24th, 2015, 11:18 pm

Re: ability wml help needed

Post by Edwylm »

Currently working on modifying the Era of Magic's summon ability. I would like to create a limit on how many units can be summoned by the summoner.
I know there is a recruiting/recall limiter in the Eastern Invasion "The Dual" scenario which I am using as a reference. So far it isn't working. There is a lot of code in the summon so I might be messing it up.

This is the raw code for the summon ability. The only thing I changed was the era aberrations. For me to place a limiter it needs to be placed in "#define SUMMON portion" part I believe.

Code: Select all

#define ABILITY_OE_SUMMON ID OPTIONS
    [dummy]
        id=oe_summon
        name= _ "summon"
        description=_"This unit can summon new units on adjacent tiles, but not in villages, or on water.

For more information, choose the 'Summoning Help' rightclick option which appears when rightclicking on a unit with the 'summon' ability."
    [/dummy] # wmlxgettext: [abilities]
[/abilities]
[event]
    name=select,recruit,recall
    id=oe_summon_select_event
    first_time_only=no
    [filter]
        ability=oe_summon
        side=$side_number
    [/filter]

    [store_unit]
        [filter]
            x,y=$x1,$y1
        [/filter]
        variable=last_selected_unit
    [/store_unit]
[/event]

[event]
    name=start,post advance,recall,forcesummonoptions
    id=oe_summon_init_event_{ID}
    first_time_only=no

    {OPTIONS}
[/event]
[+abilities] # wmlxgettext: [/abilities]
#enddef

#define SUMMON_MENU_ITEM ID DESCRIPTION COST SUMMONER UNIT
    [set_menu_item]
        id=summon_{ID}
        description={DESCRIPTION}+" - "+ _ "gold:"+" "+{COST}
        [show_if]
        [/show_if]

        [filter_location]
            [filter_adjacent_location]
                [filter]
                    type={SUMMONER}
                    side=$side_number
                    [filter_wml]
                        moves=$this_unit.max_moves
                    [/filter_wml]
                    [filter_location]
                        [not]
                            terrain=C*,K*
                        [/not]
                    [/filter_location]
                [/filter]
            [/filter_adjacent_location]
            [not]
                [filter]
                [/filter]
                [or]
                    terrain=_off^_usr,Q*,W*,*^X*,X*,*^V*
                [/or]
            [/not]
        [/filter_location]
        [command]
            [store_gold]
                variable=actualgold
                side=$side_number
            [/store_gold]
            {IF_VAR actualgold greater_than_equal_to {COST} (
                [then]
                    [gold]
                        amount=-{COST}
                        side=$side_number
                    [/gold]
                    [unit]
                        type={UNIT}
                        side=$side_number
                        x,y=$x1,$y1
                        moves=0
                        animate=yes
                    [/unit]
                    {MODIFY_UNIT x,y=$x1,$y1 attacks_left 0}
                    {MODIFY_UNIT x,y=$x1,$y1 moves 0}
                    [store_unit]
                        [filter]
                            type={SUMMONER}
                            side=$side_number
                            [filter_wml]
                                moves=$this_unit.max_moves
                            [/filter_wml]
                            [filter_adjacent]
                                x,y=$x1,$y1
                            [/filter_adjacent]
                        [/filter]
                        variable=able_to_summon
                    [/store_unit]
                    {IF_VAR able_to_summon.length greater_than 1 (
                        [then]
                            {FOREACH able_to_summon a}
                                {IF_VAR able_to_summon[$a].id equals $last_selected_unit.id (
                                    [then]
                                        {VARIABLE able_to_summon[$a].attacks_left 0}
                                        {VARIABLE able_to_summon[$a].moves 0}
                                        {VARIABLE_OP able_to_summon[$a].experience add 3}

                                        [unstore_unit]
                                            variable=able_to_summon[$a]
                                            find_vacant=no
                                            text= _ "+3 exp"
                                            red,green,blue=50,50,200
                                        [/unstore_unit]
                                        {CLEAR_VARIABLE able_to_summon}
                                    [/then]
                                    [else]
                                        [filter_condition]
                                            [variable]
                                                name=last_selected_unit.id
                                                equals=$empty
                                            [/variable]
                                            [or]
                                                [have_unit]
                                                    id=$last_selected_unit.id
                                                    [not]
                                                        [filter_adjacent]
                                                            x,y=$x1,$y1
                                                        [/filter_adjacent]
                                                    [/not]
                                                [/have_unit]
                                            [/or]
                                        [/filter_condition]

                                        [store_unit]
                                            [filter]
                                                id=able_to_summon[$a].id
                                            [/filter]
                                            variable=last_selected_unit
                                        [/store_unit]
                                        {VARIABLE able_to_summon[$a].attacks_left 0}
                                        {VARIABLE able_to_summon[$a].moves 0}
                                        {VARIABLE_OP able_to_summon[$a].experience add 3}

                                        [unstore_unit]
                                            variable=able_to_summon[$a]
                                            find_vacant=no
                                            text= _ "+3 exp"
                                            red,green,blue=50,50,200
                                        [/unstore_unit]
                                        {CLEAR_VARIABLE able_to_summon}
                                        {CLEAR_VARIABLE summoners}
                                    [/else]
                                )}
                            {NEXT a}
                        [/then]
                        [else]
                            [store_unit]
                                variable=able_to_summon
                                [filter]
                                    type={SUMMONER}
                                    side=$side_number
                                    [filter_wml]
                                        moves=$this_unit.max_moves
                                    [/filter_wml]
                                    [filter_adjacent]
                                        x,y=$x1,$y1
                                    [/filter_adjacent]
                                [/filter]
                            [/store_unit]
                            {VARIABLE able_to_summon.attacks_left 0}
                            {VARIABLE able_to_summon.moves 0}
                            {VARIABLE_OP able_to_summon.experience add 3}

                            [unstore_unit]
                                variable=able_to_summon
                                find_vacant=no
                                text= _ "+3 exp"
                                red,green,blue=50,50,200
                            [/unstore_unit]
                            {CLEAR_VARIABLE able_to_summon}
                            [fire_event]
                                name=post summon
                                [primary_unit]
                                    x,y=$x1,$y1
                                [/primary_unit]
                            [/fire_event]
                        [/else]
                    )}
                [/then]
                [else]
                    [message]
                        speaker=narrator
                        side_for=$side_number
                        caption=_ "Error"
                        message= _ "I have insufficient materials. I am unable to summon."
                        image=wesnoth-icon.png
                    [/message]
                [/else]
            )}
            {CLEAR_VARIABLE actualgold}
        [/command]
    [/set_menu_item]

    [set_menu_item]
        id=summon_zhelp
        description= _ "Summoning Help"
        image=items/book2.png~CROP(21,23,27,24)~SCALE(20,20)
        [show_if]
        [/show_if]

        [filter_location]
            [filter]
                ability=oe_summon
                side=$side_number
            [/filter]
        [/filter_location]
        [command]
            [message]
                speaker=narrator
                side_for=$side_number
                caption=_ "Help"
                message= _ "To summon a unit right-click on hexes adjacent to a selected summoner.

You need all movement points (and remaining attacks) to summon one creature. You are unable to summon in villages, from castles or keeps. A new unit can’t be summoned on water.
Every summoning adds +3 to current experience.

If there are 2 or more summoners, a new unit will be summoned by the last selected unit able to summon, or if no summoner has been selected, a summoner next to the selected tile will be chosen randomly."
                image=wesnoth-icon.png
            [/message]
        [/command]
    [/set_menu_item]
#enddef
There is something else I would like to change in the summon ability but for right now I would like to get the limiter working.
User avatar
Ravana
Forum Moderator
Posts: 2934
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: ability wml help needed

Post by Ravana »

I would solve it by adding status to summoned units (possibly including info about which side/unit they were summoned by) and before allowing new summon check that count of units with such status is within limits.
User avatar
Sapient
Inactive Developer
Posts: 4453
Joined: November 26th, 2005, 7:41 am
Contact:

Re: ability wml help needed

Post by Sapient »

FYI... one should never put a macro substitution inside a translateable string:

Code: Select all

  name=_"{NAME} slayer" # won't work!
you have to pass the whole translateable string as an argument instead. or you can add two translateable strings together... but that would fail for languages where the order of the two pieces needs to be reversed, etc.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
Post Reply