HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

multiple conditions in jass

06-20-2006, 02:54 PM#1
StRoNgFoE_2000
I know you can use GetBooleanAnd to use two conditions like the script below.

Collapse JASS:
local integer udg_localinteger
if (GetBooleanAnd(udg_TeamHeroBoolean[localinteger]==true, IsUnitAliveBJ(udg_TeamHero[localinteger]))) then
//blah blah actions
endif

The above script worked fine no compile errors. I've looked but cannot find how to use more than two conditions in a if/then. I'm using as much custom text to clean up my triggers and converting some totally to JASS to better understand it, but I can't figure out how I would go about converting something like the trigger below to JASS.

Trigger:
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
(TeamHero[1] is dead) Equal to True
TeamHeroBoolean[1] Equal to True
((Owner of TeamHero[1]) slot status) Equal to Is playing
Collapse Then - Actions
Set ContendingPlayer[1] = <Empty String>
Else - Actions

Previous posts taught me the editor creates a new function for if/then/else, and I want to get by that, so I can use a local integer variable for every [1] array. If I try to use GetBooleanAnd with more than 2 conditions I get compile errors. My question is, is there more proper method of using multiple conditions?
06-20-2006, 02:58 PM#2
blu_da_noob
You don't need to use GetBooleanAnd. You can just use 'and' between the two boolean statements. In your example:
Collapse JASS:
if udg_TeamHeroBoolean[localinteger] == true and IsUnitAliveBJ(udg_TeamHero[localinteger]) then
//blah blah actions
endif
(You can remove the == true part as well)

You can combine as many statements as you want in this way, eg:
Collapse JASS:
if i == 1 and j == 2 or IsUnitAliveBJ(u) then
//actions
endif
06-20-2006, 03:38 PM#3
StRoNgFoE_2000
That's a heck of a lot easier than I thought it was gonna be.

So, when using any boolean, if you don't specify true or false the game will automatically assume it's true?
06-20-2006, 03:45 PM#4
blu_da_noob
Well, what actually happens is, i == 1 returns a boolean value (true or false). Saying (i == 1) == true is basically like saying true == true. You need never compare to true and false.

Collapse JASS:
if IsUnitAliveBJ(u) == true //same as
if IsUnitAliveBJ(u)
Collapse JASS:
if IsUnitAliveBJ(u) == false //same as
if not IsUnitAliveBJ(u)
The 'not' boolean operator reverses the output, so not (true) is false and not (false) is true.
06-20-2006, 03:45 PM#5
Captain Griffen
Yes, it will test it against true.
06-20-2006, 04:32 PM#6
StRoNgFoE_2000
So far so good. I am trying to track "TeamHero" which will be the best hero off of a team based on hero kills. A problem is if a player leaves it is supposed to set the next player's hero on the team as the team hero, so it's not lost unless a whole team is empty.

Collapse JASS:
//Player 1 Leaves
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_PLAYING then
set udg_TeamHero[1] = udg_Hero[2]
endif
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_PLAYING  then
set udg_TeamHero[1] = udg_Hero[3]
endif
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_EMPTY then
set udg_Hero[1] = null
endif

The above trigger worked fine. My question is, will PLAYER_SLOT_STATE_EMPTY work if a player has left the game instead of using PLAYER_SLOT_STATE_LEFT? I tried to use an "or" inbetween but it crashed the editor when i tried adding too many ands and ors. Like this below crashed the editor:

Collapse JASS:
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(2))== PLAYER_SLOT_STATE_LEFT and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_LEFT then

Edit: Also, I'm not converting the whole trigger to JASS. It may have crashed because of trying to use too many ands and ors in a custom script line. IDK if this is the reason it crashed but I'm gonna test it now.
06-20-2006, 04:58 PM#7
Alevice
For the sake of clarity, try to separate each respective and and or within parentheses. It even helps the interpreter/compiler to get the priority between each boolean evaluation. Like this:


Collapse JASS:
udg_Hero[1]==udg_TeamHero[1] and (GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(2))== PLAYER_SLOT_STATE_LEFT) and (GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_LEFT)


And, you could put an evaluation in a function in any case. Like:

Collapse JASS:
function PlayerGone takes integer which returns boolean
return (GetPlayerSlotState(Player(which))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(which))== PLAYER_SLOT_STATE_LEFT)
endfunction

...

if udg_Hero[1]==udg_TeamHero[1] and PlayerGone(2) and PlayerGone(3) then
06-20-2006, 05:01 PM#8
The)TideHunter(
Well, you need brackets i would say.
Instead of having:

Collapse JASS:
if(Something and Something or SomethingElse and SomethingElse

Do:

Collapse JASS:
if(Something and Something) or (SomethingElse and SomethingElse)

BTW:
In your trigger, i slightly changed it to be more efficent

Collapse Old Trigger:
//Player 1 Leaves
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_PLAYING then
set udg_TeamHero[1] = udg_Hero[2]
endif
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_PLAYING  then
set udg_TeamHero[1] = udg_Hero[3]
endif
if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_EMPTY then
set udg_Hero[1] = null
endif

Collapse New Trigger:
//Player 1 Leaves
    if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_PLAYING then
        set udg_TeamHero[1] = udg_Hero[2]
    elseif udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_PLAYING  then
        set udg_TeamHero[1] = udg_Hero[3]
    elseif udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_EMPTY and GetPlayerSlotState(Player(3))==PLAYER_SLOT_STATE_EMPTY then
        set udg_Hero[1] = null
    endif
06-20-2006, 06:14 PM#9
StRoNgFoE_2000
Awesome stuff, my first JASS trigger! Well kinda.. Putting in an evaulation is the route I took. I think I'm finally starting to understand this stuff. After much headache and reading up... Does this:
Trigger:
Player 1 Leaves
Collapse Events
Time - Every 5.00 seconds of game time
Collapse Conditions
Defeat[1] Equal to False
(Player 1 (Red) slot status) Equal to Has left the game
Collapse Actions
Set Hero[1] = No unit
Set TempGroup = (Units owned by Player 1 (Red))
Unit Group - Pick every unit in TempGroup and do (Unit - Kill (Picked unit))
Unit Group - Destroy unit group TempGroup
Multiboard - Set the text for Multiboard item in column 1, row 2 to (|CFFFF0000 + *Left/Defeated*|r)
Game - Display to (All players) the text: ((Name of Player 1 (Red)) + has left the game.)
Player Group - Remove Player 1 (Red) from ForceOne
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Hero[1] Equal to TeamHero[1]
(Player 2 (Blue) slot status) Equal to Is playing
Collapse Then - Actions
Set TeamHero[1] = Hero[2]
Else - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Hero[1] Equal to TeamHero[1]
((Player 2 (Blue) slot status) Equal to Is unused) or ((Player 2 (Blue) slot status) Equal to Has left the game)
(Player 3 (Teal) slot status) Equal to Is playing
Collapse Then - Actions
Set TeamHero[1] = Hero[3]
Else - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
Hero[1] Equal to TeamHero[1]
((Player 2 (Blue) slot status) Equal to Is unused) or ((Player 2 (Blue) slot status) Equal to Has left the game)
((Player 3 (Teal) slot status) Equal to Is unused) or ((Player 3 (Teal) slot status) Equal to Has left the game)
Collapse Then - Actions
Set TeamHero[1] = No unit
Set AliveHeroes = (AliveHeroes - 1)
Else - Actions
Trigger - Run RemoveShopsNoPlayer <gen> (ignoring conditions)
Trigger - Run Victory <gen> (ignoring conditions)
Trigger - Destroy (This trigger)
Equal this?:
Collapse JASS:
function Trig_Player_1_Leaves_New_Conditions takes nothing returns boolean
    if udg_Defeat[1] == false and GetPlayerSlotState(Player(0)) == PLAYER_SLOT_STATE_LEFT then
        return false
    endif
        return true
endfunction

function Trig_Player_1_Leaves_New_Func003002 takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction

//I simply replaced which with A. I don't think it will make a difference.
function PlayerGone takes integer A returns boolean
return (GetPlayerSlotState(Player(A))==PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(A))==PLAYER_SLOT_STATE_LEFT)
endfunction

function Trig_Player_1_Leaves_New_Actions takes nothing returns nothing
    set udg_Hero[1] = null
    set udg_TempGroup = GetUnitsOfPlayerAll(Player(0))
    call ForGroupBJ( udg_TempGroup, function Trig_Player_1_Leaves_New_Func003002 )
    call DestroyGroup( udg_TempGroup )
    call MultiboardSetItemValueBJ( udg_Multiboard, 1, 2, ( "|CFFFF0000" + "*Left/Defeated*|r" ) )
    call DisplayTextToForce( GetPlayersAll(), ( GetPlayerName(Player(0)) + " has left the game." ) )
    call ForceRemovePlayerSimple( Player(0), udg_ForceOne )
    if udg_Hero[1]==udg_TeamHero[1] and GetPlayerSlotState(Player(1))==PLAYER_SLOT_STATE_PLAYING then
//This is where I started to use the evaluation.
    elseif udg_Hero[1]==udg_TeamHero[1] and PlayerGone(1) and GetPlayerSlotState(Player(2))==PLAYER_SLOT_STATE_PLAYING then
    set udg_TeamHero[1] = udg_Hero[3]
    elseif (udg_Hero[1]==udg_TeamHero[1] and PlayerGone(1) and PlayerGone(2)) then
//And this is where it ends.
    set udg_TeamHero[1] = null
    set udg_AliveHeroes = ( udg_AliveHeroes - 1 )
    endif
    call TriggerExecute( gg_trg_RemoveShopsNoPlayer )
    call TriggerExecute( gg_trg_Victory )
    call DestroyTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Player_1_Leaves_New takes nothing returns nothing
    set gg_trg_Player_1_Leaves_New = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Player_1_Leaves_New, 5.00 )
    call TriggerAddCondition( gg_trg_Player_1_Leaves_New, Condition( function Trig_Player_1_Leaves_New_Conditions ) )
    call TriggerAddAction( gg_trg_Player_1_Leaves_New, function Trig_Player_1_Leaves_New_Actions )
endfunction
06-20-2006, 06:37 PM#10
Alevice
Apparently, yes. A little stuff could be furtehr optimized, like:

Collapse JASS:
//Further ispenction lead me to believe PlayerIsActive should be more logical and slightly faster than PlayerGone
function PlayerIsActive takes integer A returns boolean
return (GetPlayerSlotState(Player(A))==PLAYER_SLOT_STATE_PLAYING)
endfunction


function Trig_Player_1_Leaves_Copy_Conditions takes nothing returns boolean
    if ( (not(udg_Defeat[1])) and not(PlayerIsActive(0) )then
        return true
    endif
    return false
endfunction

//I know there must be a way this function could get rid of. Sadly, don't remember how... :(
function KillEnumUnit takes nothing returns nothing
    call KillUnit( GetEnumUnit() )
endfunction


function Trig_Player_1_Leaves_Copy_Actions takes nothing returns nothing

    local group TempGroup //no need for a global, I guess
    
    set udg_Hero[1] = null //if you are setting it here to null, why are you comparing it later?
    
    set TempGroup = GetUnitsOfPlayerAll(Player(0))
    call ForGroupBJ( TempGroup, function KillEnumUnit )
    call DestroyGroup( TempGroup )
    call MultiboardSetItemValueBJ( udg_Multiboard, 1, 2, ( "|CFFFF0000" + "*Left/Defeated*|r" ) )
    call DisplayTextToForce( GetPlayersAll(), ( GetPlayerName(Player(0)) + " has left the game." ) )

    call ForceRemovePlayerSimple( Player(0), udg_ForceOne )

    if udg_Hero[1]==udg_TeamHero[1] then 
        if PlayerIsActive(1) then
            set udg_TeamHero[1] = udg_Hero[2]
        elseif PlayerIsActive(2) then
            set udg_TeamHero[1] = udg_Hero[3]
        else
            set udg_TeamHero[1] = null
        endif

    endif

    set udg_AliveHeroes = ( udg_AliveHeroes - 1 ) //shouldn't this be affected despite whatever happened in the conditions?

    call TriggerExecute( gg_trg_RemoveShopsNoPlayer )
    call TriggerExecute( gg_trg_Victory )
    call DestroyTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Player_1_Leaves_Copy takes nothing returns nothing
    set gg_trg_Player_1_Leaves_Copy = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Player_1_Leaves_Copy, 5.00 )
    call TriggerAddCondition( gg_trg_Player_1_Leaves_Copy, Condition( function Trig_Player_1_Leaves_Copy_Conditions ) )
    call TriggerAddAction( gg_trg_Player_1_Leaves_Copy, function Trig_Player_1_Leaves_Copy_Actions )
endfunction

I must be missing a lot of stuff, so don't take this for granted
06-20-2006, 07:20 PM#11
StRoNgFoE_2000
That works fine, and it's a bit cleaner. As for your concerns:

I remember reading about getting rid of the "KillEnumUnit" function using a "FirstOfGoup" loop or another, I might add that in after I get this all straightened out.

Setting Hero[#] to null was my mistake, I realized that after posting. It shouldn't be set to null until the end of the trigger.

AliveHeroes is to keep track of the ammount of team heroes in the game, and is tracked in many other triggers. When a player reaches that first hero kill, it adds +1 only one time per team in another trigger (for only a total of 4), and it has to remove one permanently if an entire team is gone. So, if the last person on a force leaves, it only subtracts it then, which is why it subtracts only if the other 2 players are gone. I'm pretty sure there is no problem thus far with the way it's being tracked.

Thank you all for your help, I think I'm good to go now.
06-20-2006, 08:05 PM#12
The)TideHunter(
To get rid of the extra Enum function, you cant use ForGroup, you would just have to kill them all yourself using a loop and a local unit variable, like this:

Collapse JASS:
local group TempGroup
    local unit CurrentUnit
    loop
        set CurrentUnit = FirstOfGroup(TempGroup)
        exitwhen CurrentUnit == null
        
        // All Your actions you want to happen here.
        call KillUnit(CurrentUnit)

        call GroupRemoveUnit(TempGroup, CurrentUnit)
    endloop
    call DestroyGroup(TempGroup)
    set TempGroup = null

In your case, you could change your code to:

Collapse (Im using Alevice's optimizedish code because im lazy):
//Further ispenction lead me to believe PlayerIsActive should be more logical and slightly faster than PlayerGone
function PlayerIsActive takes integer A returns boolean
return (GetPlayerSlotState(Player(A))==PLAYER_SLOT_STATE_PLAYING)
endfunction


function Trig_Player_1_Leaves_Copy_Conditions takes nothing returns boolean
    if ( (not(udg_Defeat[1])) and not(PlayerIsActive(0) )then
        return true
    endif
    return false
endfunction

//I know there must be a way this function could get rid of. Sadly, don't remember how... :(


function Trig_Player_1_Leaves_Copy_Actions takes nothing returns nothing

    local group TempGroup //no need for a global, I guess
    local unit TempUnit

    set udg_Hero[1] = null //if you are setting it here to null, why are you comparing it later?
    
    set TempGroup = GetUnitsOfPlayerAll(Player(0))
    loop
        set TempUnit = FirstOfGroup(TempGroup)
        exitwhen(TempUnit == null)
        call KillUnit(TempUnit)
        call GroupRemoveUnit(TempGroup, TempUnit)
    endloop
    call DestroyGroup( TempGroup )
    call MultiboardSetItemValueBJ( udg_Multiboard, 1, 2, ( "|CFFFF0000" + "*Left/Defeated*|r" ) )
    call DisplayTextToForce( GetPlayersAll(), ( GetPlayerName(Player(0)) + " has left the game." ) )

    call ForceRemovePlayerSimple( Player(0), udg_ForceOne )

    if udg_Hero[1]==udg_TeamHero[1] then 
        if PlayerIsActive(1) then
            set udg_TeamHero[1] = udg_Hero[2]
        elseif PlayerIsActive(2) then
            set udg_TeamHero[1] = udg_Hero[3]
        else
            set udg_TeamHero[1] = null
        endif

    endif

    set udg_AliveHeroes = ( udg_AliveHeroes - 1 ) //shouldn't this be affected despite whatever happened in the conditions?

    call TriggerExecute( gg_trg_RemoveShopsNoPlayer )
    call TriggerExecute( gg_trg_Victory )
    call DestroyTrigger( GetTriggeringTrigger() )
endfunction

//===========================================================================
function InitTrig_Player_1_Leaves_Copy takes nothing returns nothing
    set gg_trg_Player_1_Leaves_Copy = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Player_1_Leaves_Copy, 5.00 )
    call TriggerAddCondition( gg_trg_Player_1_Leaves_Copy, Condition( function Trig_Player_1_Leaves_Copy_Conditions ) )
    call TriggerAddAction( gg_trg_Player_1_Leaves_Copy, function Trig_Player_1_Leaves_Copy_Actions )
endfunction