Lunar Alliance WML

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.
User avatar
Melon
Posts: 193
Joined: February 8th, 2008, 2:30 am
Location: Calgary

Lunar Alliance WML

Post by Melon »

This thread is dedicated towards coding some of the abilities for my new faction, the Lunar Alliance. Since my knowledge of WML is still very limited at this point and I would prefer to divert most of my time towards the artwork, I would greatly appreciate if someone where to help me code the following abilities:

High Priority Items:
"Dominate Mind" weapon special for the Lunarian Sorcerer
-Takes control of a lower level unit (only level 1 or 0 for a level 2 Sorcerer and level 2 as well at level 3)
-Does not work on leaders, heroes and non living units
-The hit chance is calculated as follows: (100-Enemy hp/Max enemy hp*100)*(Enemy defense/100)
-This effect is permanent

"Invoke Insanity" weapon special for the Lunarian Sorcerer
-Adds the "berserk" modifier to all of the targets melee attacks.
-Reverts the target back to normal by the next turn. Units that where previously berserkers will remain berserkers.
-Does not effect non living units.
-(Optional) Adds an icon to show that the unit is insane

Low Priority Items:
"Time Rift" ability for the Lunarian Avatar
-All friendly and enemy units are considered slowed as long as they remain in the zone of control of a unit with this ability, their damage is cut in half. This power does not persist if they leave the zone of control.
-Movement cost in all adjacent hexes is doubled.
-This power has no effect on units that have the "Time Rift" ability (Multiple Avatars cannot slow one another down)
-(Optional, I have no idea if this is even possible) Cut the speed of all animations in half in all adjacent hexes.
Last edited by Melon on November 30th, 2008, 4:35 pm, edited 6 times in total.
AI
Inactive Developer
Posts: 2396
Joined: January 31st, 2008, 8:38 pm

Re: Lunar Alliance WML

Post by AI »

Melon wrote:High Priority Items:
"Growth" ability for Moongates:
-Grants them 1xp per turn and automatically promotes them when they have enough.
-Need to start with no traits but gain two randomly assigned traits after they promote.
Take a look at the 'contemplative' ability of the free goblins, it does everything except assign new traits.
"Rebirth" ability for Firebirds/Phoenixes:
-If a Firebird is slain in battle the code needs to create a unit to represent its ashes in the same location as where the Firebird died.
-Though the ashes spawn with no traits, the dead Firebirds traits need to be stored away for later use.
-The ashes gain 1xp per turn (Same deal as Moongates, but the ashes require only 1xp to promote)
-If the ashes fail to be destroyed by the following turn, the dead Firebird is respawned with the same traits, xp and name that it had before it died. Its health returns to full.
A 'die' event that spawns the new unit with [variables], experience and [modifications] stored in the new unit's [variables], then restores them on post_advance:

Code: Select all

[event]
    name=die
    [filter]
        type=Firebird,Phoenix
    [/filter]
    [kill]
        x,y=$x1,$y1
        fire_event=no
        animate=yes
    [/kill]
    [unit]
        type=Ashes
        [variables]
            vars=$unit.variables
            exp=$unit.experience
            mods=$unit.modifications
        [/variables]
        x,y=$x1,$y1
    [/unit]
[/event]
[event]
    name=post_advance
    [filter]
        type=Ashes
    [/filter]
    [store_unit]
        x,y=$x1,$y1
        variable=new_bird
    [/store_unit]
    new_bird.variables=$unit.vars
    new_bird.experience=$unit.exp
    new_bird.modifications=$unit.mods
    [unstore_unit]
        variable=new_bird
        find_vacant=no
    [/unstore_unit]
    {CLEAR_VARIABLE new_bird}
[/event]

"Dominate Mind" weapon special for the Lunarian Sorcerer
-Takes control of a lower level unit (only level 1 or 0 for a level 2 Sorcerer and level 2 as well at level 3)
-Does not work on leaders, heroes and non living units
-The hit chance is calculated as follows: (100-Enemy hp/Max enemy hp*100)*(Enemy defense/100)
-This effect is permanent
Look at the 'charm' ability and remove the restoration. Chance-to-hit is a bit more difficult.
Things that I know I can code by myself, but you can help me code anyways:
"Thermoptic Camouflage" ability for the Lunarian Stalker
-Invisibility regardless of terrain and day/night cycles
Hides without a filter or with an empty filter.
User avatar
Peter the Great
Posts: 296
Joined: August 9th, 2008, 5:08 pm

Re: Lunar Alliance WML

Post by Peter the Great »

I'm no good with abilities, but I could help speed up the unit coding if you need help with that.
Latin:LVDVMAMISI (pronounced Loo-dum amee-C)
French: J'ai perdu le jeu.
English: I lost the game.
User avatar
Melon
Posts: 193
Joined: February 8th, 2008, 2:30 am
Location: Calgary

Re: Lunar Alliance WML

Post by Melon »

AI wrote:
Melon wrote:High Priority Items:
"Growth" ability for Moongates:
-Grants them 1xp per turn and automatically promotes them when they have enough.
-Need to start with no traits but gain two randomly assigned traits after they promote.
Take a look at the 'contemplative' ability of the free goblins, it does everything except assign new traits.
It doesn't work. I tried to fiddle around with the code for the past hour with no results. Here's what I came up with so far:

Code: Select all

#define ABILITY_WARP
[dummy]
    id=warp
    name= _ "Warp"
    description= _ "Warp:
It takes several turns before the Moongate will become powerful enough for a unit to cross."
[/dummy]
[/abilities]

    [event]
        name=turn refresh
        first_time_only=no

        [store_unit]
            [filter]
            ability=warp
            [/filter]
            variable=temp_moongate
        [/store_unit]

        [set_variable]
            name=temp_moongate.experience
            value=$temp_moongate.experience+1
        [/set_variable]

        [unstore_unit]
            variable=temp_moongate
        [/unstore_unit]
        {CLEAR_VARIABLE temp_moongate}
    [/event]

[+abilities]
#enddef
And I still have no clue as to how I can make it assign the traits.
User avatar
Rhishisikk
Posts: 214
Joined: August 12th, 2008, 4:58 pm
Location: As Contract Demands
Contact:

Re: Lunar Alliance WML

Post by Rhishisikk »

For Shield Wall, look at the GUARD trait for free saurian trainees in Era of Strife. That will tell you how to modify the unit. I think there is an ability in Mercenaries Era that modifies damage if another unit with the same trait is adjacent, but I forget what that is called.

Eclipse: ARGH. Morning Brain. I should be able to do this one when fully awake. Pester me Sunday if nobody else has done this, I'll have time then.

Dominate Mind: Look at 'Tame Beast' from Bob's RPG Era, and remove the recovery code. BE WARNED, I greatly dislike this ability for reasons of balance. I ask that you at least limit the number of strikes, and possibly make certain the 'to-hit' never exceeds a certain level.

Invoke Insanity: Again, Bob's RPG era. Look at the way Berserker modifies the owner's attacks. For limiting the removal of traits by class, take a look at ASSASSIN trait from Era of Strife. For removal of traits, look at the various 'construction' skills in Bob's RPG era. Icons can be added-removed in a manner similar to Modified Orocia.

Time Rift: For the exclusion of others with Time Rift, reference the same ability from Mercenaries as recommended for SHIELD WALL.

:) My WML is weak, but I am the demigod of Frankensteins. :)
Typhon Rhishisikk

If a man has a talent and cannot use it, he has failed. - Thomas Wolfe
Wesluck (TM): Guaranteed unlike any other luck, anywhere else. - Typhon

Main Projects: ANL: Universal (era), Gambit's Empire Builder
User avatar
beetlenaut
Developer
Posts: 2867
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Lunar Alliance WML

Post by beetlenaut »

I see at least one problem in your code. You can't add like that. Change the line:

Code: Select all

value=$temp_moongate.experience+1
to

Code: Select all

add=1
This event also won't work if there are multiple units on the map with that same ability. In that case, temp_moongate is going to hold an array. You will have to step through the array and change each one using FOREACH and NEXT. Here is an example of how that works. This code removes all movement points from the orcs of side 2 each turn:

Code: Select all

[store_unit]
	[filter]
		side=2
	[/filter]
	kill=yes
	variable=orcs
[/store_unit]
{FOREACH orcs orc}
[set_variable]
	name=orcs[$orc].moves
	value=0
[/set_variable]
[unstore_unit]
	variable=orcs[$orc]
[/unstore_unit]
{NEXT orc}
[clear_variable]
	name=orcs
[/clear_variable]
I don't know how to add traits either. It might not be possible.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
Lord_Aether

Re: Lunar Alliance WML

Post by Lord_Aether »

For adding traits, can't you use an [object]?
User avatar
A Guy
Posts: 793
Joined: May 24th, 2008, 1:55 am

Re: Lunar Alliance WML

Post by A Guy »

[object] doesn't allow the addition of traits, last time I checked.
I'm just... a guy...
I'm back for now, I might get started on some work again.
Lord_Aether

Re: Lunar Alliance WML

Post by Lord_Aether »

Dang :P
User avatar
beetlenaut
Developer
Posts: 2867
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Lunar Alliance WML

Post by beetlenaut »

A feature request is in order: a way to add or remove traits.

In the mean time, you could give objects that mimic traits. Objects can increase hitpoints, decrease max experience, add a movement point, make a unit loyal, etc.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
User avatar
Melon
Posts: 193
Joined: February 8th, 2008, 2:30 am
Location: Calgary

Re: Lunar Alliance WML

Post by Melon »

Played around with the WML for a bit (2 hours) again today. I got the Warp ability to work thanks to beetlenaut. Here's the code Im currently using:

Code: Select all

#define ABILITY_WARP
[dummy]
    id=warp
    name= _ "warp"
    description= _ "Warp:
It takes several turns before the Moongate will become powerful enough for a unit to cross."
[/dummy]
[/abilities]

    [event]
        name=turn refresh
        first_time_only=no

        [store_unit]
            [filter]
                ability=warp
                side="$side_number"
            [/filter]
        kill=yes
        variable=temp_moongates
        [/store_unit]

        {FOREACH temp_moongates temp_moongate}

        [set_variable]
            name=temp_moongates[$temp_moongate].experience
            add=1
        [/set_variable]

        [unstore_unit]
            variable=temp_moongates[$temp_moongate]
        [/unstore_unit]

        {NEXT temp_moongate}
        {CLEAR_VARIABLE temp_moongates}
    [/event]

[+abilities]
#enddef
The downside is that the player has no way of telling which Moongate has promoted. I tried to use this to highlight the Moongate which is about to advance:

Code: Select all

    [event]
        name=advance
        first_time_only=no
        [filter]
            ability=warp
        [/filter]
        {HIGHLIGHT_UNIT find_in=unit}
    [/event]
but it freezes up the game when the Moongate changes (Probably because the game tries to highlight the unit and pop up the unit advancement prompt at the same time).

I also took a stab at coding the Shield Wall ability with no success. Here's the code:

Code: Select all

#define ABILITY_SHIELD_WALL
[dummy]
    id=shield_wall
    name= _ "shield wall"
    description= _ "Shield Wall:
This unit will generate a zone of control as long as at least a single other unit with the shield wall ability is adjacent to it."
[/dummy]
[/abilities]
    [event]
        name=moveto
        first_time_only=no
    [filter]
        ability=shield_wall
    [/filter]
    [filter_adjacent]
        adjacent=n,ne,se,s,sw,nw
        is_enemy=no
        ability=shield_wall
    [/filter_adjacent]
    [effect]
        apply_to=zoc
        value=1
    [/effect]
    [/event]

[+abilities]
#enddef
The downside here is that even if it did work, it would only activate when a unit moves. This means that the Cultists will have no zones of control when recruited, even if they're directly adjacent to each other. Which needless to say, is a fairly bad thing.

I also recently realized that not only do we need to assign new traits for the Moongates but we also have to remove one. Moongates start with the "portal" trait, which sets their status to non-living. This trait carries over to all of their promotion branches. Perhaps it would be best to use an event that removes the Moongate unit upon its promotion, opens a menu with a list of advancement options and then creates a brand new unit with a set of random traits. Thoughts?

edit: Another thing I've noticed is that the AI never seems to recruit Moongates since I assume it considers them a useless unit. The Moongates role is set to "defender" (The only defender in the faction) and the current recruitment pattern I'm using is: "defender,fighter,fighter,healer". Is there any way that I can force the AI to recruit Moongates?
User avatar
beetlenaut
Developer
Posts: 2867
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Lunar Alliance WML

Post by beetlenaut »

You have to pay attention to what tags can go where. Refer to the wiki often to make sure you are using the tags correctly. The shield wall code has a couple tags that are in the wrong place. [filter_adjacent] is a subtag of [filter], so it has to go inside it. [effect] is only a subtag of [object], but it's inside [event] instead. Another problem I see is that you have no way to remove the zoc once it is added. Here is what I suggest. Make the event a "turn refresh": the zoc doesn't have to come and go any time one of these units moves. It only matters when an enemy's turn starts. Use a FOREACH loop again. Loop through all the units that have shield_wall, and remove each one's zoc. Use another FOREACH loop to go through again, and add the zoc where necessary. To check whether the zoc should be turned on, use [if]...[have_unit]...[filter_adjacent].... To turn it on and off, you will have to [store_unit], [set_variable], and [unstore_unit]. (Turning it off is going to look almost exactly like my orc code.)

edit: Re: edit: Something could be wrong with how you are specifying the recuitment pattern. Try setting it to defender,defender. If it ignores you, it's probably not understanding right, and just using the default. The only way I know to force the AI to recruit anything is to give it only one option. I've done that before for the first turn. On the AI's second turn, I gave it the rest of the list. You might try leaving it only one option to see if it recruits the moongates then.

edit: Also, "find_in=unit" doesn't sound like it should work. Try "description=$unit.description". Maybe it is working though, because the game is crashing. HIGHLIGHT_UNIT kills the unit and brings it back a few times. Maybe the game is trying to advance it while it's dead.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
User avatar
Melon
Posts: 193
Joined: February 8th, 2008, 2:30 am
Location: Calgary

Re: Lunar Alliance WML

Post by Melon »

beetlenaut wrote:You have to pay attention to what tags can go where. Refer to the wiki often to make sure you are using the tags correctly. The shield wall code has a couple tags that are in the wrong place. [filter_adjacent] is a subtag of [filter], so it has to go inside it. [effect] is only a subtag of [object], but it's inside [event] instead. Another problem I see is that you have no way to remove the zoc once it is added. Here is what I suggest. Make the event a "turn refresh": the zoc doesn't have to come and go any time one of these units moves. It only matters when an enemy's turn starts. Use a FOREACH loop again. Loop through all the units that have shield_wall, and remove each one's zoc. Use another FOREACH loop to go through again, and add the zoc where necessary. To check whether the zoc should be turned on, use [if]...[have_unit]...[filter_adjacent].... To turn it on and off, you will have to [store_unit], [set_variable], and [unstore_unit]. (Turning it off is going to look almost exactly like my orc code.)
Thank you, that kind of works. I probably did something wrong though since the ZoCs seem to get assigned in a fairly random manner. Sometimes only a few members of a group develop a ZoC and sometimes a lone unit will get a ZoC for no reason. Here's the code:

Code: Select all

#define ABILITY_SHIELD_WALL
[dummy]
    id=shield_wall
    name= _ "shield wall"
    description= _ "Shield Wall:
This unit will generate a zone of control as long as at least a single other unit with the shield wall ability is adjacent to it."
[/dummy]
[/abilities]

    [event]
        name=turn refresh
        first_time_only=no

        [store_unit]
            [filter]
                ability=shield_wall
            [/filter]
            [filter]
                level=0
            [/filter]
        kill=yes
        variable=temp_guards
        [/store_unit]

        {FOREACH temp_guards i}

        [if]
            [have_unit]
                name=temp_guards[$i]
                [filter_adjacent]
                    adjacent=n,ne,se,s,sw,nw
                    is_enemy=no
                    ability=shield_wall
                [/filter_adjacent]
            [/have_unit]
            [then]
                [set_variable]
                    name=temp_guards[$i].zoc
                    value=1
                [/set_variable]
            [/then]
            [else]
                [set_variable]
                    name=temp_guards[$i].zoc
                    value=0
                [/set_variable]
            [/else]
        [/if]

        [unstore_unit]
            variable=temp_guards[$i]
        [/unstore_unit]

        {NEXT i}
        {CLEAR_VARIABLE temp_guards}
    [/event]

[+abilities]
#enddef
beetlenaut wrote:edit: Re: edit: Something could be wrong with how you are specifying the recuitment pattern. Try setting it to defender,defender. If it ignores you, it's probably not understanding right, and just using the default. The only way I know to force the AI to recruit anything is to give it only one option. I've done that before for the first turn. On the AI's second turn, I gave it the rest of the list. You might try leaving it only one option to see if it recruits the moongates then.
Doesn't work even if the pattern's set to nothing but defenders. The AI leader hates the unit so much that it would rather just sit in the castle and not do anything. I suppose the only countermeasure would be to write an AI script that assigns a high value to the "Warp" ability.
beetlenaut wrote:edit: Also, "find_in=unit" doesn't sound like it should work. Try "description=$unit.description". Maybe it is working though, because the game is crashing. HIGHLIGHT_UNIT kills the unit and brings it back a few times. Maybe the game is trying to advance it while it's dead.
Produces the exact same glitch as my code. So I guess that at least it's "working".
User avatar
beetlenaut
Developer
Posts: 2867
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: Lunar Alliance WML

Post by beetlenaut »

You have two [filter] tags in [store_unit]. Put both keys into just one [filter]. You also have name=temp_guards[$i]. That should be name=temp_guards[$i].name. Actually, you shouldn't use "name" because it's not guaranteed to be unique. Use "description". (If you are using BfW 1.5.x, that's been changed to "id".)

When you get this working, it would be very nice to give the player a visual cue to let them know the two units have a ZoC. (It would also let you know while you're working on it.) So, along with zoc, I would change the ellipse from the dashed one of a level-0 unit to the solid one.

Code: Select all

[set_variable]
    name=temp_guards[$i].ellipse
    value=misc/ellipse-nozoc  # for dashed
    value=misc/ellipse  # for solid
[/set_variable]
Melon wrote:The AI leader hates the unit so much that it would rather just sit in the castle and not do anything.
A typo in three or four places could cause this.
Melon wrote:Produces the exact same glitch as my code.
Weird. Why don't you just use FLOATING_TEXT (in wesnoth/data/core/macros/interface-utils.cfg) to say "Level up!" or something like that? You should scroll_to the unit first too.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
User avatar
Melon
Posts: 193
Joined: February 8th, 2008, 2:30 am
Location: Calgary

Re: Lunar Alliance WML

Post by Melon »

beetlenaut wrote:You have two [filter] tags in [store_unit]. Put both keys into just one [filter]. You also have name=temp_guards[$i]. That should be name=temp_guards[$i].name. Actually, you shouldn't use "name" because it's not guaranteed to be unique. Use "description". (If you are using BfW 1.5.x, that's been changed to "id".)

When you get this working, it would be very nice to give the player a visual cue to let them know the two units have a ZoC. (It would also let you know while you're working on it.) So, along with zoc, I would change the ellipse from the dashed one of a level-0 unit to the solid one.
I'm pretty sure that I've done everything the way you asked me to, but it's still broken during tests.

Code: Select all

#define ABILITY_SHIELD_WALL
[dummy]
    id=shield_wall
    name= _ "shield wall"
    description= _ "Shield Wall:
This unit will generate a zone of control as long as at least a single other unit with the shield wall ability is adjacent to it."
[/dummy]
[/abilities]

    [event]
        name=turn refresh
        first_time_only=no

        [store_unit]
            [filter]
                ability=shield_wall
                level=0
            [/filter]
        kill=yes
        variable=temp_guards
        [/store_unit]

        {FOREACH temp_guards i}

        [if]
            [have_unit]
                id=temp_guards[$i].id
                [filter_adjacent]
                    adjacent=n,ne,se,s,sw,nw
                    is_enemy=no
                    ability=shield_wall
                [/filter_adjacent]
            [/have_unit]
            [then]
                [set_variable]
                    name=temp_guards[$i].zoc
                    value=1
                [/set_variable]
                [set_variable]
                    name=temp_guards[$i].ellipse
                    value=misc/ellipse
                [/set_variable]
            [/then]
            [else]
                [set_variable]
                    name=temp_guards[$i].zoc
                    value=0
                [/set_variable]
                [set_variable]
                    name=temp_guards[$i].ellipse
                    value=misc/ellipse-nozoc
                [/set_variable]
            [/else]
        [/if]

        [unstore_unit]
            variable=temp_guards[$i]
        [/unstore_unit]

        {NEXT i}
        {CLEAR_VARIABLE temp_guards}
    [/event]

[+abilities]
#enddef
beetlenaut wrote:
Melon wrote:The AI leader hates the unit so much that it would rather just sit in the castle and not do anything.
A typo in three or four places could cause this.
Couldn't find any typos. Maybe the defender unit class was discontinued in 1.5?
beetlenaut wrote:
Melon wrote:Produces the exact same glitch as my code.
Weird. Why don't you just use FLOATING_TEXT (in wesnoth/data/core/macros/interface-utils.cfg) to say "Level up!" or something like that? You should scroll_to the unit first too.
Tried it. Produces a very similar glitch. Weird.

Thank you for your help and patience Beetlenaut, I really appreciate it :) . Since I don't have a lot of coding practice, having someone hold my hand through these things is absolutely essential.
Post Reply