how to filter for unknown weapon specials (of any kind)

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
Mabuse
Posts: 2239
Joined: November 6th, 2007, 1:38 pm

how to filter for unknown weapon specials (of any kind)

Post by Mabuse »

hello i want to check if a weapon has unknown weapon special.
(via weapon filter)


the task is to filter weapons that have CUSTOM specials, which can have any tag name.

so i just check if there are NO ALREADY KNOWN specials,
but this check would also be true if the weapon has NO SPECIAL AT ALL

so i need to ensure that there is no "empty" weapon special field.

so it checks that the field is not empty, but also contains no known specials, so the conclusion is that there is unknown special.

so the main question is how to check if a weapon has no special at all

something like:

special_type=notexistant/empty


this check below wont work, so also weapons with NO special will return positive

Code: Select all

                [effect]
                    apply_to=attack
                    [not]
                    special_type=notexistant      #or empty <----------------- how to check this ?
                    [or]
                    special_type=swarm
                    [/or]
                    [or]
                    special_type=slow
                    [/or]
                    [or]
                    special_type=poison
                    [/or]
                    [or]
                    special_type=plague
                    [/or]
                    [or]
                    special_type=petrifies
                    [/or]
                    [or]
                    special_type=heal_on_hit
                    [/or]
                    [or]
                    special_type=drains
                    [/or]
                    [or]
                    special_type=poison
                    [/or]
                    [or]
                    special_type=firststrike
                    [/or]
                    [or]
                    special_type=disable
                    [/or]
                    [or]
                    special_type=damage
                    [/or]
                    [or]
                    special_type=chance_to_hit
                    [/or]
                    [or]
                    special_type=berserk
                    [/or]
                    [or]
                    special_type=attacks
                    [/or]
                    [/not]

.......
The best bet is your own, good Taste.
User avatar
Spannerbag
Posts: 552
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: how to filter for unknown weapon specials (of any kind)

Post by Spannerbag »

Mabuse wrote: August 5th, 2023, 11:53 pm hello i want to check if a weapon has unknown weapon special.
(via weapon filter)


the task is to filter weapons that have CUSTOM specials, which can have any tag name.

so i just check if there are NO ALREADY KNOWN specials,
but this check would also be true if the weapon has NO SPECIAL AT ALL

so i need to ensure that there is no "empty" weapon special field.

so it checks that the field is not empty, but also contains no known specials, so the conclusion is that there is unknown special.

so the main question is how to check if a weapon has no special at all

something like:

special_type=notexistant/empty


this check below wont work, so also weapons with NO special will return positive

Code: Select all

                [effect]
                    apply_to=attack
                    [not]
                    special_type=notexistant      #or empty <----------------- how to check this ?
                    [or]
                    special_type=swarm
                    [/or]
                    [or]
                    special_type=slow
                    [/or]
                    [or]
                    special_type=poison
                    [/or]
                    [or]
                    special_type=plague
                    [/or]
                    [or]
                    special_type=petrifies
                    [/or]
                    [or]
                    special_type=heal_on_hit
                    [/or]
                    [or]
                    special_type=drains
                    [/or]
                    [or]
                    special_type=poison
                    [/or]
                    [or]
                    special_type=firststrike
                    [/or]
                    [or]
                    special_type=disable
                    [/or]
                    [or]
                    special_type=damage
                    [/or]
                    [or]
                    special_type=chance_to_hit
                    [/or]
                    [or]
                    special_type=berserk
                    [/or]
                    [or]
                    special_type=attacks
                    [/or]
                    [/not]

.......
Hmm... first off don't know why you start your code with [effect]?

In the code below (which is a first hack so may need experimentation to get it exactly right) the weapon filter ([has_attack]) does the work but I also wrapped it in a unit [filter] in case you want to limit the unit(s) to be processed in some other (non-weapon) way. If not you'll need to remove the [filter] and replace [has_attack] with [filter_attack].

Cleverer people than me might have more elegant/efficient solutions by using lua and/or a more intricate formula but I've stuck with WML.

Note that within [filter] where I've typed "..." just means "other unit identifiers" such as "x,y=23,9" and/or "side=1" etc.
I think within the weapon filter the comma separated list of specials should work but if not your code above with lots of individual [not] clauses should work.

Also the wiki lists the full range of specials as:
[attacks]: modifies the number of attacks of a weapon
[berserk]: pushes the attack for more than one combat round
[chance_to_hit]: modifies the chance to hit of a weapon
[damage]: modifies the damage of a weapon
[disable]: disables the weapon
[drains]: heals the attacker half of the damage dealt
[firststrike]: forces the weapon to always strike first
[heal_on_hit]: heals the attacker when an attack connects
[petrifies]: turns the target to stone
[plague]: when used to kill an enemy, a friendly unit takes its place
[poison]: poisons the target
[slow]: slows the target
[swarm]: number of strikes decreases as the unit loses hitpoints

So the filter below will (hopefully) exclude them all.

Note: this logic filters by [tag_name] not the special id so will also exclude customised versions of existing specials such as a modified form of [berserk] that only lasts for 3 rounds.

So if you do not want to exclude these customised versions of existing specials you'll need to filter by special_id rather than special_type.
This will make [plague] messy because it has multiple ids as shown below.

Code: Select all

#define WEAPON_SPECIAL_PLAGUE_TYPE TYPE
    # Canned definition of the Plague ability to be included in a
    # [specials] clause (with type specifier).
    [plague]
        id=plague({TYPE})
        name= _ "plague"
        description= _ "When a unit is killed by a Plague attack, that unit is replaced with a unit on the same side as the unit with the Plague attack. This doesn’t work on Undead or units in villages."
        type={TYPE}
    [/plague]
#enddef
The logic uses a weapon filter that excludes all "standard" special types (regardless of id or whether they are currently active or not) then a formula to test if the unit nevertheless does have a weapon special of some sort. It will only detect weapons with a [specials] clause that also does not include the regular specials so if a weapon has a "standard" special and a custom one then I think this logic will miss it.
You'll need to sort out the detail, I can only provide starting points :)


As I say this has been coded on the spot so might need some tweaking (or major surgery :doh: ).

Code: Select all

[filter]
...
    [has_attack]
        range=melee                                   # Or =ranged or omit if you want both
        [not]
            special_type=attacks,berserk,chance_to_hit,damage,disable,drains,firststrike,heal_on_hit,petrifies,plague,poison,slow,swarm
        [/not]
        formula="length(specials) > 0"                # Weapon has a special
    [/has_attack]
[/filter]
If the formula doesn't work I've probably done something wrong.
You could fix the formula or, alternatively, you could remove it then after [has_attack] add this instead:

Code: Select all

    [/has_attack]                                     # After has_attack
    [filter_wml]
        [specials]                                    # Inside [attack] tag
    [/filter_wml]
Though I'm not sure if [filter_wml] will accept an unclosed tag like [specials] but it's worth a try.
Also this means not everything is done inside a weapon filter :(

Note that I used:

Code: Select all

        [not]
            special_type=attacks,berserk,chance_to_hit,damage,disable,drains,firststrike,heal_on_hit,petrifies,plague,poison,slow,swarm
        [/not]
rather than (assuming it works):
special_type=null
because this would, I imagine, possibly exclude the custom specials you want depending on how they were implemented... maybe.
It's also possible that certain specials that were implemented as, say, events might be missed (because they would not be recognised as such by the game's filters). You'll know better than me if this is a problem or not.

Not had chance to test this myself but it might get you part way there?

Good luck,
Cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.17, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Ravana
Forum Moderator
Posts: 3061
Joined: January 29th, 2012, 12:49 am
Location: Estonia
Contact:

Re: how to filter for unknown weapon specials (of any kind)

Post by Ravana »

special_type represents weapon special tag name, and empty tag name is not allowed in wml. So you can be sure it is never empty. And all valid tags are allowed in abilities, so notexistant is also allowed, but wont do anything without events.
Mabuse
Posts: 2239
Joined: November 6th, 2007, 1:38 pm

Re: how to filter for unknown weapon specials (of any kind)

Post by Mabuse »

Hello :)
Spannerbag wrote: August 6th, 2023, 2:37 pm Hmm... first off don't know why you start your code with [effect]?
because its just a part of a trait (its inside a trait that is applied to the leader of a side at start of the game)

Spannerbag wrote: August 6th, 2023, 2:37 pm

Code: Select all

[filter]
...
        formula="length(specials) > 0"                # Weapon has a special
[/filter]
hey, that looks interesting, i will try that

Spannerbag wrote: August 6th, 2023, 2:37 pm If the formula doesn't work I've probably done something wrong.
You could fix the formula or, alternatively, you could remove it then after [has_attack] add this instead:

Code: Select all

    [/has_attack]                                     # After has_attack
    [filter_wml]
        [specials]                                    # Inside [attack] tag
    [/filter_wml]
Though I'm not sure if [filter_wml] will accept an unclosed tag like [specials] but it's worth a try.
Also this means not everything is done inside a weapon filter :(
if the above wont work i might take look at that


Spannerbag wrote: August 6th, 2023, 2:37 pm Note that I used:

Code: Select all

        [not]
            special_type=attacks,berserk,chance_to_hit,damage,disable,drains,firststrike,heal_on_hit,petrifies,plague,poison,slow,swarm
        [/not]
rather than (assuming it works):
special_type=null
because this would, I imagine, possibly exclude the custom specials you want depending on how they were implemented... maybe.
It's also possible that certain specials that were implemented as, say, events might be missed (because they would not be recognised as such by the game's filters). You'll know better than me if this is a problem or not.

Not had chance to test this myself but it might get you part way there?
custom specials that use the "standardized" tags are by now no problem, a damage tag will influence the damage in one way or another, sure it can be OP, but a units can be itself OP, so it doesnt matter - but non-standardized custom tags may do completely crazy things

the identification is simply used to remove them
(by now i copy over every weapon that has no KNOWN special (also weapons without a special) a useless-special (this process will remove all existing specials) and then remove that useless-special again, so weapons with unknown specials and weapon without specials end up with no specials.)

but in case your solution work, i will use that since then (for the sake of compensation) its possible to replace any unknown custom specials with a basic special like "magical" e.g., and give them a small damage boost or something
Spannerbag wrote: August 6th, 2023, 2:37 pm Good luck,
Cheers!
-- Spannerbag
thank you, help is very appreciated :)
The best bet is your own, good Taste.
User avatar
Spannerbag
Posts: 552
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: how to filter for unknown weapon specials (of any kind)

Post by Spannerbag »

Mabuse wrote: August 6th, 2023, 6:07 pm Hello :)
Spannerbag wrote: August 6th, 2023, 2:37 pm Hmm... first off don't know why you start your code with [effect]?
because its just a part of a trait (its inside a trait that is applied to the leader of a side at start of the game)
Ah, OK... I see you like making life easy for yourself :)

Mabuse wrote: August 6th, 2023, 6:07 pm
Spannerbag wrote: August 6th, 2023, 2:37 pm

Code: Select all

[filter]
...
        formula="length(specials) > 0"                # Weapon has a special
[/filter]
hey, that looks interesting, i will try that
Hope it (or something like it) works...

Mabuse wrote: August 6th, 2023, 6:07 pm custom specials that use the "standardized" tags are by now no problem, a damage tag will influence the damage in one way or another, sure it can be OP, but a units can be itself OP, so it doesnt matter - but non-standardized custom tags may do completely crazy things

the identification is simply used to remove them
(by now i copy over every weapon that has no KNOWN special (also weapons without a special) a useless-special (this process will remove all existing specials) and then remove that useless-special again, so weapons with unknown specials and weapon without specials end up with no specials.)


but in case your solution work, i will use that since then (for the sake of compensation) its possible to replace any unknown custom specials with a basic special like "magical" e.g., and give them a small damage boost or something
So if I understand you correctly, you assign a dummy (useless) special to all weapons without a known special (including weapons with no special) then remove it. What happens if a weapon has both one or more known special(s) and one or more custom special(s)? Can this even happen in your campaign/project?
Just curious.
Mabuse wrote: August 6th, 2023, 6:07 pm thank you, help is very appreciated :)
Glad to help :D
Hope you get your logic working the way you want!

Cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.17, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Spannerbag
Posts: 552
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: how to filter for unknown weapon specials (of any kind)

Post by Spannerbag »

Ravana wrote: August 6th, 2023, 4:23 pm special_type represents weapon special tag name, and empty tag name is not allowed in wml. So you can be sure it is never empty. And all valid tags are allowed in abilities, so notexistant is also allowed, but wont do anything without events.
Ah, I didn't think that through... really shouldn't type stuff without taking a second or two to check it makes sense! :doh:
Cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.17, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
Mabuse
Posts: 2239
Joined: November 6th, 2007, 1:38 pm

Re: how to filter for unknown weapon specials (of any kind)

Post by Mabuse »

Spannerbag wrote: August 6th, 2023, 8:29 pm So if I understand you correctly, you assign a dummy (useless) special to all weapons without a known special (including weapons with no special) then remove it. What happens if a weapon has both one or more known special(s) and one or more custom special(s)? Can this even happen in your campaign/project?
Just curious.
yes, it can happen since you might use whatever era you want in the scenario.
and you are right, this is a big disadvantage of the approach currently.

i guess i cant work around storing a unit, and iterate over every weapon, and compare every special on that weapon with a valid-list, and if it doesnt match, store the id of that non-valid-special and then delete it.
The best bet is your own, good Taste.
User avatar
Celtic_Minstrel
Developer
Posts: 2263
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: how to filter for unknown weapon specials (of any kind)

Post by Celtic_Minstrel »

Spannerbag wrote: August 6th, 2023, 2:37 pm If the formula doesn't work I've probably done something wrong.
You could fix the formula or, alternatively, you could remove it then after [has_attack] add this instead:

Code: Select all

    [/has_attack]                                     # After has_attack
    [filter_wml]
        [specials]                                    # Inside [attack] tag
    [/filter_wml]
Though I'm not sure if [filter_wml] will accept an unclosed tag like [specials] but it's worth a try.
Also this means not everything is done inside a weapon filter :(
Your formula approach is probably better, but this line of reasoning isn't completely off track. All you have to do is add a closing [specials tag and also wrap that in an [attack] tag, and it'll match only units that have [specials] in an [attack]. The only caveat is… that might be all units. I haven't checked, but it's possible the game automatically inserts an empty [specials] tag on attacks that don't have any specials.

Now, moving on to the more important part… your formula has an error in it. I realize this might be a little confusing, but the length() function in WFL measures the length of a string. If you try to use it on a list, you'll only get null() and an error message. The function to get the number of elements in a list is size().

And to make things even more confusing, I don't actually recommend using either of those functions. This is how I would write the formula:

Code: Select all

formula="specials.size > 0"
My reason for choosing .size over size() is simply that it also works on strings, so it's less confusing. There might actually be an argument for deprecating the functions and making this the sole supported way of getting the size of a list, string, or map in WFL.

There is also one other option:

Code: Select all

formula="not specials.empty"
There's no real difference between them, so choose whichever you like better. (This one also works on strings, for what it's worth.)
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Spannerbag
Posts: 552
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: how to filter for unknown weapon specials (of any kind)

Post by Spannerbag »

Mabuse wrote: August 7th, 2023, 1:39 am
Spannerbag wrote: August 6th, 2023, 8:29 pm So if I understand you correctly, you assign a dummy (useless) special to all weapons without a known special (including weapons with no special) then remove it. What happens if a weapon has both one or more known special(s) and one or more custom special(s)? Can this even happen in your campaign/project?
Just curious.
yes, it can happen since you might use whatever era you want in the scenario.
and you are right, this is a big disadvantage of the approach currently.
OK... so could I summarise what you want to do as follows?

In my campaign if a player decides to use an era/mod/resource/whatever that adds custom weapon specials (via custom tags) then these should be discarded.

That is, variants of specials that use standard tags (such as a berserk attack with a duration different to regular berserk) would be allowed but a special with a non-standard tag, like [vorpal_strike] (or, I guess [berserk_3]?) would not.

Have I understood correctly?

Mabuse wrote: August 7th, 2023, 1:39 am i guess i cant work around storing a unit, and iterate over every weapon, and compare every special on that weapon with a valid-list, and if it doesnt match, store the id of that non-valid-special and then delete it.

Had a bit of a think about the best way to do that and yeah, it's a bit gnarly.
I can see ways to do it (maybe) but they ain't pretty :shock:
And they all seem to involve iterating through all the units one way or another.
There doesn't seem to be any way in WML to store_weapon (unless I missed it).

Heh, I started mulling over how I'd do this in detail and ended up, I suspect, pretty much where you'd already gotten to, so I gave up :)

I found extracting the actual specials quite laborious, so hopefully I missed something and you've found a more elegant method...

Anyway, good luck!
Cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.17, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
Post Reply