How do you access the terrain code where a unit is standing

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
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

How do you access the terrain code where a unit is standing

Post by Helmet »

How do you access the terrain code where a unit is standing, so I can input it into set_variable?

My snow monster has an attack called avalanche. After the attack ends, the terrain under the enemy unit's feet needs to be transformed into its snow or ice variant.

So far, my code only works on grass, because I don't know how to find the terrain code.

Code: Select all

    [event]
        name=attack_end
        first_time_only=no
        [filter]
            type=Snowball
        [/filter]
        {MODIFY_TERRAIN Aa ($x2) ($y2)} #           <-----   Aa is "snow flat" terrain
    [/event]
Naturally, I would like shallow water to change into ice, hills changed into snowy hills, and so forth.

Somebody had a similar question on the forum last year and the proposed solutions involved arrays and terrain masks and it was all waaay over my head. I want to use code that I understand in this instance.

Can this coding problem be solved using IF/THEN/ELSEIF or SWITCH?

Does anybody have a macro for accessing the terrain code where a unit is standing? Something like... {THIS_IS_THE_TERRAIN_ON_THIS_HEX (X) (Y)}.
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
octalot
General Code Maintainer
Posts: 786
Joined: July 17th, 2010, 7:40 pm
Location: Austria

Re: How do you access the terrain code where a unit is standing

Post by octalot »

Helmet wrote: November 6th, 2022, 6:30 pm Somebody had a similar question on the forum last year and the proposed solutions involved arrays and terrain masks and it was all waaay over my head. I want to use code that I understand in this instance.

Can this coding problem be solved using IF/THEN/ELSEIF or SWITCH?
I recommend Ravana's suggestion of Lua or using [store_locations], because it is better for long-term maintainability. However, for a quick and dirty answer that fits with how you're currently thinking there's [have_location]:

Code: Select all

    [event]
        name=moveto
        first_time_only=no
        [if]
            [have_location]
                x,y=$x1,$y1
                terrain=Ww*^*
            [/have_location]
            [then]
                [message]
                    speaker=unit
                    message=_ "I’m up to my waist in water again"
                [/message]
            [/then]
        [/if]
    [/event]
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: How do you access the terrain code where a unit is standing

Post by Helmet »

Ravana wrote: November 6th, 2022, 9:26 pm https://github.com/ProditorMagnus/Agele ... d.lua#L119 or [store_locations]
Oh my goodness. You must think I'm smart. If that github code had made sense any to me, my brain could probably have solved my little problem by itself, ha ha. :)
octalot wrote: November 6th, 2022, 9:49 pm...However, for a quick and dirty answer that fits with how you're currently thinking there's [have_location]...
Success! THAT is what I needed. Thanks. That solution makes perfect sense to me, now that I see it. I had a feeling I was barking up the wrong tree with filter_location, and other things.

I thought the working code was going to be long -- one block of code per terrain -- but WML allowed me to use commas in the terrain list, so the code is actually pretty short.

I may re-visit this thread if I run into another problem with the snow, but presently my code is doing what I want.

Here is the functional code.

Code: Select all

    [event]
        name=attack_end #                           avalanche
        first_time_only=no
        [filter]
            type=Snowball
        [/filter]
        [if]
            [have_location]
                x,y=$x2,$y2
                terrain=Hh # *^*
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ha
                [/terrain]
            [/then]
        [/if]
        [if]
            [have_location]
                x,y=$x2,$y2
                terrain=Hh,Hhd,Hd #               .*^*
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ha
                [/terrain]
            [/then]
            [elseif]
                [have_location]
                    x,y=$x2,$y2
                    terrain=Gg,Gs,Gd,Gll,Rb,Re,Rr,Rd,Rrc,Rp,Rra,Dd,Ds #                *^*
                [/have_location]
                [then]
                    [terrain]
                        x=$x2
                        y=$y2
                        terrain=Aa
                    [/terrain]
                [/then]
            [/elseif]
        [/if]
    [/event]
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
Celtic_Minstrel
Developer
Posts: 2213
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: How do you access the terrain code where a unit is standing

Post by Celtic_Minstrel »

I think this might be a bit simpler if you use a [terrain_mask] instead. It would look something like this:

Code: Select all

[event]
	name=attack_end # avalanche
	first_time_only=no
	[filter]
		type=Snowball
	[/filter]
	[terrain_mask]
		x,y=$x2,$y2
		alignment=raw # I'm not sure if this line is needed
		mask="Aa" # this might need to be mask_data instead of just mask; the terrain here will be used if none of the rules match
		# Change any hills to snowy hills
		[rule]
			old=H*
			terrain=Ha
			layer=base
		[/rule]
		# Change any grass, road, or desert to snow
		[rule]
			old=G*,R*,D*
			terrain=Aa
			layer=base
		[/rule]
		# Change pine forest to snowy pine forest
		[rule]
			old=*^Fp
			terrain=Aa^Fpa
			layer=overlay
		[/rule]
		# Any other rules you want
	[/terrain_mask]
[/event]
(By the way, [have_location] also supports the use of * as a wildcard like I've done in the above example.)
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: How do you access the terrain code where a unit is standing

Post by Helmet »

Celtic_Minstrel wrote: November 9th, 2022, 7:00 am I think this might be a bit simpler if you use a [terrain_mask] instead...
Dang, I should've checked this thread earlier. Thanks.

Anyhow, this is my tested, functional code for the avalanche attack.

Code: Select all

#define AVALANCHE_ATTACK

[event]
    name=attack_end #                 ***   avalanche attack changes terrain   ***
    #                                                 attack only
    first_time_only=no
    [filter]
        type=Snowball
    [/filter]
    
    # Gg    = Green grass                       T E R R A I N -- F L A T
    # Gs    = Semi-dry grass
    # Gd    = Dry grass
    # Gll   = Leaf litter
    # Rb    = Dark Dirt
    # Re    = Regular dirt
    # Rd    = Dry dirt
    # Rr    = Regular cobbles
    # Rrc   = Clean gray cobbles
    # Rp    = Overgrown cobbles

    # Hh    = Regular hills                     T E R R A I N -- R O U G H
    # Hhd   = Dry hills
    # Ha    = Snow hills

    # ^Efm  = Mixed flowers                     E M B E L L I S H M E N T S
    # ^Gvs  = Farmland
    # ^Es   = Stones
    # ^Esa  = Snowbits
    # ^Em   = Small mushrooms
    # ^Edt  = Trash
    # ^Edb  = Remains
    # ^Ewl  = Water lilies
    # ^Ewf  = Flowering water lilies

    [if]
        [have_location] # changes grass and leaf litter to snow (Aa). Snows over 7 specific embellishments.
            x,y=$x2,$y2
            terrain=G*,  G*^Efm,G*^Gvs,G*^Es,G*^Esa,G*^Em,G*^Edt,G*^Edb
        [/have_location]
        [then]
            [terrain]
                x=$x2
                y=$y2
                terrain=Aa
            [/terrain]
        [/then]

        [elseif]
            [have_location] # changes dirt and cobbles to snow (Aa). Snows over 7 specific embellishments.
                x,y=$x2,$y2
                terrain=R*,  R*^Efm,R*^Gvs,R*^Es,R*^Esa,R*^Em,R*^Edt,R*^Edb
                [not]
                    terrain=Rra*^* #            Icy cobbles   <-- do not affect
                [/not]
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Aa
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes regular and dry hills to snowy hills. Snows over 7 specific embellishments.
                x,y=$x2,$y2
                terrain=H*,  H*^Efm,H*^Gvs,H*^Es,H*^Esa,H*^Em,H*^Edt,H*^Edb
                [not]
                    terrain=Ha*^*,Hd*^* #        Snowy hills, dunes   <-- do not affect
                [/not]
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ha
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes shallow water, ford, reefs to ice. Ices over lilies (^Ewl), flowering water lilies (^Ewf), and 7 specific embellishments.
                x,y=$x2,$y2
                terrain=Ww*,  Ww*^Ewl,Ww*^Ewf  Ww*^Efm,Ww*^Gvs,Ww*^Es,Ww*^Esa,Ww*^Em,Ww*^Edt,Ww*^Edb
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes swamp water and muddy quagmire to ice. Ices over lilies (^Ewl), flowering water lilies (^Ewf), and 7 specific embellishments.
                x,y=$x2,$y2
                terrain=S*,  S*^Ewl,S*^Ewf  S*^Efm,S*^Gvs,S*^Es,S*^Esa,S*^Em,S*^Edt,S*^Edb
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai
                [/terrain]
            [/then]
        [/elseif]
        #                                       B R I D G E S   >>>    over shallow water, ford, reef, swamp water, muddy quagmire. Excludes deep water.
        [elseif]
            [have_location] # changes non-deep water under a wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw|,S*^Bw|
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw|
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw/,S*^Bw/
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw/
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw\,S*^Bw\
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw\
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a rotting wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw|r,S*^Bw|r
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw|r
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a rotting wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw/r,S*^Bw/r
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw/r
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a rotting wooden bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bw\r,S*^Bw\r
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bw\r
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a basic stone bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bsb|,S*^Bsb|
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bsb|
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a basic stone bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bsb\,S*^Bsb\
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bsb\
                [/terrain]
            [/then]
        [/elseif]

        [elseif]
            [have_location] # changes non-deep water under a basic stone bridge to ice.
                x,y=$x2,$y2
                terrain=Ww*^Bsb/,S*^Bsb/
            [/have_location]
            [then]
                [terrain]
                    x=$x2
                    y=$y2
                    terrain=Ai^Bsb/
                [/terrain]
            [/then]
        [/elseif]
    [/if]
[/event]
#enddef
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
beetlenaut
Developer
Posts: 2825
Joined: December 8th, 2007, 3:21 am
Location: Washington State
Contact:

Re: How do you access the terrain code where a unit is standing

Post by beetlenaut »

That's great, but you should probably know about the way to make it a lot shorter: [switch]. That tag is made for exactly this situation to avoid all the elseifs.

You would probably cut it in half that way, and it would be easier to maintain in the future (if new terrains come out for example). You could also use just one [if] that prevents the game from entering the [switch] at all if the terrain is one you want to skip.
Campaigns: Dead Water,
The Founding of Borstep,
Secrets of the Ancients,
and WML Guide
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: How do you access the terrain code where a unit is standing

Post by Helmet »

beetlenaut wrote: November 11th, 2022, 6:37 am That's great, but you should probably know about the way to make it a lot shorter: [switch].
I've used switch before. I like it; it has a logical simplicity that appeals to me. I tried to use it for my avalanche attack but couldn't figure-out how to set it up. In the past, I've only used switch with integers (e.g., counting how many items a player had gathered to fulfill an objective). I still have no idea how to set it up. Could you explain?

I thought switch wasn't capable of more complicated things. This is exciting news. If I can understand the explanation, I'll be using switch a lot.
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
Celtic_Minstrel
Developer
Posts: 2213
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: How do you access the terrain code where a unit is standing

Post by Celtic_Minstrel »

Switch is exactly equivalent to a series of if-then-else with equality tests. That means that to use switch here you would need to use [store_locations] to put the terrain in a variable. However, since it's strict equality, it means you can't use terrain wildcards, so I wouldn't really recommend switch for this use-case.

It would look something like this:

Code: Select all

[store_locations]
	variable=here
	x,y=$x2,$y2
[/store_locations]
[switch]
	variable=here.terrain
	[case]
		value=Gg,Gs,Gd # Match any of these three terrains, but only without an overlay
		[terrain]
			x,y=$x1,$y2
			terrain=Aa
		[/terrain]
	[/case]
[/switch]
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: How do you access the terrain code where a unit is standing

Post by Helmet »

Celtic_Minstrel wrote: November 11th, 2022, 1:38 pm Switch is exactly equivalent to a series of if-then-else with equality tests. That means that to use switch here you would need to use [store_locations] to put the terrain in a variable. However, since it's strict equality, it means you can't use terrain wildcards, so I wouldn't really recommend switch for this use-case.
Ah. I didn't consider [store_locations]. That's what de-railed me from figuring-out how to set it up. That, and my tendency to avoid code that requires a variable with a dot in the middle.

I saved your example into my notes. Thanks for explaining.
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
User avatar
Helmet
Posts: 641
Joined: December 19th, 2006, 5:28 pm
Location: Florida, USA

Re: How do you access the terrain code where a unit is standing

Post by Helmet »

Celtic_Minstrel wrote: November 11th, 2022, 1:38 pm Switch is exactly equivalent to a series of if-then-else with equality tests. That means that to use switch here you would need to use [store_locations] to put the terrain in a variable. However, since it's strict equality, it means you can't use terrain wildcards, so I wouldn't really recommend switch for this use-case.
Ah. I didn't consider [store_locations]. That's what de-railed me from figuring-out how to set it up. That, and my unfortunate tendency to avoid code that requires a variable with a dot in the middle.

I saved your example into my notes. Thanks for explaining.
Author of:
DIY Campaign, Confederacy of Swamp Creatures: Big Battle 1, Confederacy of Swamp Creatures: Big Battle 2, Frogfolk Delivery Service, The Pool of Ek.
Post Reply