• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Writing manually boolean conditions for unit types

Status
Not open for further replies.

Ardenian

A

Ardenian

How can I write a Boolean filter to check for unit types,
filtering out if any is false ?

Example:
A unit is ground, ancient and building.
Now I load stored Boolean ( Hashtable) to check if everything is set to true:

Unit is ground == true and Loaded Boolean == true
Unit is ancient == true and Loaded Boolean == true
Unit is building == true and Loaded Boolean == true

If any condition were false, then the unit does not pass through the check

Unit is ground == true and Loaded Boolean == true
Unit is ancient == true and Loaded Boolean == false
Unit is building == true and Loaded Boolean == true

However, additionally to this, obviously a ground unit, for example, is not an air unit, even if the loaded air is true.

Unit is air == false and Loaded Boolean == true
Unit is ground == true and Loaded Boolean == true

In this case, the unit would be filtered out although it matches the conditions, because it is not an air unit.

How can I prevent this and how would a Jass script look like doing this ?

***

I would like to achieve to check for every unit type the unit is, checking a loaded Boolean to match and if any does not match, the unit does not pass the condition block.
Additionally, if the unit is not a certain type, then it should not be filtered out because the loaded Boolean does not match.

I myself can only think about a probably inefficient way, working around with ITE for every unit type, increasing an integer based on the number of unit types a unit is and so on, but I believe there is a better way.
I would be glad to receive some initial help, please.
 

Ardenian

A

Ardenian

Excuse, I have a hard time describing it, but I think with your example I can improve it:

Yes, that would be my approach, too. However, these boolean behind ==, the true, are not fixed. That is my problem. I don't know how I can check if a unit is a certan unit type AND whether THAT unit type the unit is is allowed to ... be.

I guess I have to check for every unit type existing, as you do.
Then, next step, how would I check for the dynamic boolean now ?
It would be something like

JASS:
If unit is unittype 1 == true then
    if (LoadBoolean()  == true) == true  then
        *perform actions*
    endif
endif
[code=jass] 

But, I do not know how this works if we take multiple unit types/ unit categories in consideration.
If any of the unit types the unit is true is not true when loading the Boolean, then there won't be an action.

Something that came to my mind, as comparison: 
Imagine two lists. One with every unit type and one boolean either true or false. This is List B
List A is structured the same, unit category and one boolean, but this time the boolean is true if the unit is part if the category and false if it is not.

That means:
List A - List B 
True  - True

-> Unit is unit category == true and this category is allowed == true

True - False 

-> Unit is a category that is not allowed, therefore filter it out/ mo actions ( even if it is true for every previous and following category) 

Now comes the problem: 

False - True 

-> in this case the unit would be filtered out, as it is no match, although it had nothing to do with the unit itself. 

Hm, while writing this I might have a solution I would like to test. 
I can check if the unit is Co vertUnitType(LOOPVARIABLE) and if, then compare it to the corresponding boolean, if that unit type is allowed or not.

However, how do I add that part with unit is category() but boolean is false, then perform no actions  and considering that a unit can have multiple categories ?
 

Ardenian

A

Ardenian

JASS:
function booleancheck takes unit u returns boolean
    local boolean b
    local boolean bhash
    local integer i
    local integer o
    
    set i = 0
    
    // Get the handle of the unit type
    set o = GetUnitTypeId( u)
    
    //Loop through all unit types
    loop
    exitwhen ConvertUnitType(i) == null
    
    if IsUnitType( u, ConvertUnitType(i)) == true then
        set b = true 
        set bhash = LoadBoolean( udg_BooleanHashtable, o, i+1)
        if bhash == false then  
            //No actions    
        else 
        return b
        endif
    
    endif
    
    set i = i +1
    
    endloop
    
    return b
    
endfunction

This is what I have for now.

It loops through all default unit categories and checks if the unit is that unit type.
If it is, then check the hashtable safe( makes at the moment no sense).
If that is false, then do nothing.

However, no matter whether I check for bhash == true or bhash == false, it will result to one end:
I would perform actions if the first unit type == true with its safe == true and return the Boolean

What I would like to achieve is to first raid through all unit categories checking and then get a final Boolean telling me whether the unit fulfills all its categories as == true in the hashtable.

My approach would be to save the results of the relations and if any is false, then return false. if all are true, then return true.
 
So let me get this straight:

You want to loop through every type--if the unit is that type, then the hashtable value should be true for that type. The final result will only be false if the hashtable value returns false for some unit-type that is matched, correct?

e.g.
unit is ground == true and hash boolean == true
unit is air == false and hash boolean == anything

This example should always return true, right? (according to your rules) If so, then I assume you could do something similar to your code:
JASS:
function UnitTypeCheck takes unit u returns boolean
    local integer id = GetUnitTypeId(u)
    local integer i = 0
    loop
        exitwhen ConvertUnitType(i) == null

        /* 
            If the unit matches this type and the 
            loaded boolean is false, then return false 
        */
        if IsUnitType(u, ConvertUnitType(i)) then
            if not LoadBoolean(udg_BooleanHashtable, o, i + 1) then
                return false
            endif
        endif

        set i = i + 1
    endloop
    return true
endfunction

If my explanation was incorrect, then this code probably isn't what you're looking for. However, I still recommend approaching the issue in a similar way. Break the problem into two parts:
- When should the function return true?
- When should the function return false?

If you need help, answer those two questions and we can give a better answer. :)
 

Ardenian

A

Ardenian

'The final result will only be false if the hashtable value returns false for some unit-type that is matched, correct?'
-> exactly

I realized that the initial If does not allow false - true to happen, therefore one does not need to consider it.

Returning something ends the function, right ? That being said, what if I would like to check if every unit type of unit u matches LoadBoolean ?

My approach would be to save a combination, whether it would return true or false and then check afterwards whether there is any false.

Example:

unit is ground == true and hash boolean == true - > your example script returns true
unit is hero == true and hash boolean == false -> but heroes are not allowed

I know hero comes before ground in the unit types, but this is should to show what I mean. It would return a true although there is a mismatch.

The return Boolean should consider all current unit types of the unit.
This is my problem :)
Is there any other way than saving the results ( the returns in your example) and checking afterwards whether there is any false under it ?
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
-_-

JASS:
function UnitTypeCheck takes unit u returns boolean
    local integer i = 0
    loop
        exitwhen UNIT_TYPE[i] == null
        
        if IsUnitType(u, UNIT_TYPE[i]) != LoadBoolean(udg_BooleanHashtable, XXX, i) then
            return false
        endif

        set i = i + 1
    endloop
    return true
endfunction
or
JASS:
function UnitTypeCheck takes unit u returns boolean
    local integer i = 0
    loop
        if UNIT_TYPE[i] == null then
            return true
        endif
        
        exitwhen IsUnitType(u, UNIT_TYPE[i]) != LoadBoolean(udg_BooleanHashtable, XXX, i)

        set i = i + 1
    endloop
    return false
endfunction

Depending on if you want to place something after the "endloop" in either situations.
 

Ardenian

A

Ardenian

That is around the same what PurgeandFire wrote isn't it ...
Now I see it, thank you!
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
What paf made is check if a unit is of a certain type, however if he is not, then there will be no check to remove it.
In my script, I check if the type is equal to the boolean in the hastable.
Be aware that all unit types must be defined in the hashtable.

So you have to check for all 27 unit types if they are correct in the hashtable:
JASS:
UNIT_TYPE_HERO
UNIT_TYPE_DEAD
UNIT_TYPE_STRUCTURE
UNIT_TYPE_FLYING
UNIT_TYPE_GROUND
UNIT_TYPE_ATTACKS_FLYING
UNIT_TYPE_ATTACKS_GROUND
UNIT_TYPE_MELEE_ATTACKER
UNIT_TYPE_RANGED_ATTACKER
UNIT_TYPE_GIANT
UNIT_TYPE_SUMMONED
UNIT_TYPE_STUNNED
UNIT_TYPE_PLAGUED
UNIT_TYPE_SNARED
UNIT_TYPE_UNDEAD
UNIT_TYPE_MECHANICAL
UNIT_TYPE_PEON
UNIT_TYPE_SAPPER
UNIT_TYPE_TOWNHALL
UNIT_TYPE_ANCIENT
UNIT_TYPE_TAUREN
UNIT_TYPE_POISONED
UNIT_TYPE_POLYMORPHED
UNIT_TYPE_SLEEPING
UNIT_TYPE_RESISTANT
UNIT_TYPE_ETHEREAL
UNIT_TYPE_MAGIC_IMMUNE

However, this is a bit odd because you cannot have a town hall that is not a structure or is a hero or a peon.
And yuo cannot have a ranged attacker and melee attacker together.
Also magic immune and stunned/poisoned/polymorphed together?
Also ground and flying collide.

I don't know the exact situation where you want to use this, but it should be able to be done better.
 

Ardenian

A

Ardenian

Oh, thank you making me aware of this.
I planned to use just a few, the 'main ones', like hero, undead, ancient , giant and so on, ones you usually have as conditions.

Are the combinations you mention the only ones not possible ?
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Well... others might be possible but are rarely used.
I would rather make a list of unit types and check if the unit has those unit types.
When you give it a boolean array as well, then you can check if the boolean corresponds with the unit's type.
 
Status
Not open for further replies.
Top