• 🏆 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!

Custom Victory/Defeat Trigger

Status
Not open for further replies.
Level 2
Joined
May 4, 2013
Messages
8
Hello Hive Workshop,

I have been using the resources on this website for years as part of personal maps I share with friends. Recently I have made a map with custom townhalls in it, and the standard Melee Victory/Defeat keeps revealing the players with custom town halls.

I had another trigger from another map maker which I was using for a while, however it would defeat any player once their number of structures reached 0, which gave the player no room to recover or escape and rebuild their hall.

So after about an hour and a half of testing on myself, I came to this Trigger.
My plan is to have three triggers, one that does the check when a peasant is killed, another for when a townhall is destroyed, another for when a hero is killed.

The triggers will then count the number of Peasants, Townhalls and Heroes they have, If all 3 are 0, they are defeated.

b85ZO0f.png


This Trigger works on me, if I destroy my own hero, hall and all my peasants, I will be defeated. However against the Undead Bot the World Editor spawns on the map, it does not seem to work.

So I am now petitioning to the Hive Community for a solution, and perhaps solving this issue will help future map makers.
 
Level 2
Joined
May 4, 2013
Messages
8
The 35 Second Delay is to avoid the trigger accidently counting any units that are still decaying, which it will, but this can be avoided by using the Matching Unit Is Alive Equal to True function
 
Level 22
Joined
Aug 27, 2013
Messages
3,973
Try this one.
  • DefeatChecker
    • Events
      • Unit - A unit Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • ((Triggering unit) is A peon-type unit) Equal to True
          • ((Triggering unit) is A Hero) Equal to True
          • ((Triggering unit) is A town-hall-type unit) Equal to True
    • Actions
      • Set TownHallOwned = (Units in (Playable map area) matching ((((Matching unit) is A town-hall-type unit) Equal to True) and ((Owner of (Matching unit)) Equal to (Owner of (Triggering unit)))))
      • Set PeonOwned = (Units in (Playable map area) matching ((((Matching unit) is A peon-type unit) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • Set HeroOwned = (Units in (Playable map area) matching ((((Matching unit) is A Hero) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TownHallOwned) Equal to 0
          • (Number of units in PeonOwned) Equal to 0
          • (Number of units in HeroOwned) Equal to 0
        • Then - Actions
          • Custom script: call DestroyGroup(udg_TownHallOwned)
          • Custom script: call DestroyGroup(udg_PeonOwned)
          • Custom script: call DestroyGroup(udg_HeroOwned)
          • Wait 35.00 game-time seconds
          • Game - Defeat (Triggering player) with the message: Defeat!
        • Else - Actions
          • Custom script: call DestroyGroup(udg_TownHallOwned)
          • Custom script: call DestroyGroup(udg_PeonOwned)
          • Custom script: call DestroyGroup(udg_HeroOwned)
First of all, Dying unit can be easily replaced by something else within 35 seconds. It's safe to use Triggering unit instead.
Also you can merge your idea of having 3 triggers into one like I just did.
I store them in Group Variables to avoid leaks. I also destroy the variable before the wait function to avoid the variables from being overwritten within 35 seconds.
 
Level 12
Joined
Mar 24, 2011
Messages
1,082
Just wondering, isn't the regular defeat condition for all unit-producing structures & builders to have gone or all structures & builders ?
E.g. player could have a bajillion resources & a bazillion of barracks but still get defeated?

PS: Bear with me, I've not played a melee map since 200X. I believe, in SCII you need to lose ALL buildings & workers to be defeated ?
 
Level 2
Joined
May 4, 2013
Messages
8
Try this one.
  • DefeatChecker
    • Events
      • Unit - A unit Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • ((Triggering unit) is A peon-type unit) Equal to True
          • ((Triggering unit) is A Hero) Equal to True
          • ((Triggering unit) is A town-hall-type unit) Equal to True
    • Actions
      • Set TownHallOwned = (Units in (Playable map area) matching ((((Matching unit) is A town-hall-type unit) Equal to True) and ((Owner of (Matching unit)) Equal to (Owner of (Triggering unit)))))
      • Set PeonOwned = (Units in (Playable map area) matching ((((Matching unit) is A peon-type unit) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • Set HeroOwned = (Units in (Playable map area) matching ((((Matching unit) is A Hero) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TownHallOwned) Equal to 0
          • (Number of units in PeonOwned) Equal to 0
          • (Number of units in HeroOwned) Equal to 0
        • Then - Actions
          • Custom script: call DestroyGroup(udg_TownHallOwned)
          • Custom script: call DestroyGroup(udg_PeonOwned)
          • Custom script: call DestroyGroup(udg_HeroOwned)
          • Wait 35.00 game-time seconds
          • Game - Defeat (Triggering player) with the message: Defeat!
        • Else - Actions
          • Custom script: call DestroyGroup(udg_TownHallOwned)
          • Custom script: call DestroyGroup(udg_PeonOwned)
          • Custom script: call DestroyGroup(udg_HeroOwned)
First of all, Dying unit can be easily replaced by something else within 35 seconds. It's safe to use Triggering unit instead.
Also you can merge your idea of having 3 triggers into one like I just did.
I store them in Group Variables to avoid leaks. I also destroy the variable before the wait function to avoid the variables from being overwritten within 35 seconds.

Hey thanks for the suggestion, Tried it out and it didn't seem to work. I think I mentioned earlier that the Unit Group function seems to include dead units in it's count as well, including buildings which is why the 35 Second Wait time was before the count, that gave the buildings and anything else time to fully decay before the count began, but otherwise this has certainly neatened the trigger out. I also don't know if the Triggering Unit function works in this instance, as it's not clear if that refers to the Dying Unit or the Unit that killed the Dying Unit, so I might try putting it back to Dying Unit again.
 
Level 2
Joined
May 4, 2013
Messages
8
What is odd is I seperated the trigger into 3 If, Then, Else Multiple Actions Actions. For each I had each of the three counters (Hero, Peon and Townhall), I then set it to enter a game message to confirm if each counter was successful or not, Eg, if I killed a peon, but the owning player still had peons, but no more townhalls or heroes, the Chat would come up;
Peon Count Failed - Still more Peons
Townhall Count Complete - No Townhalls Left
Hero Count Complete - No Heroes left

And funny enough the trigger was confirming all 3 counters were completing when they should, yet the player was still not getting defeated. I'm very puzzled. Here is what I did to check the conditions;
YHUPILB.png
 
Level 22
Joined
Aug 27, 2013
Messages
3,973
Hey thanks for the suggestion, Tried it out and it didn't seem to work. I think I mentioned earlier that the Unit Group function seems to include dead units in it's count as well, including buildings which is why the 35 Second Wait time was before the count, that gave the buildings and anything else time to fully decay before the count began, but otherwise this has certainly neatened the trigger out. I also don't know if the Triggering Unit function works in this instance, as it's not clear if that refers to the Dying Unit or the Unit that killed the Dying Unit, so I might try putting it back to Dying Unit again.
No, that shouldn't be the case, especially if you already include the filter "Unit is alive = true". Basically, it takes 35 seconds for the trigger to refer the dying unit and in that 35 seconds, the dying unit can be replaced by any other units who die at the time so the trigger might refer different unit instead. Doesn't Triggering unit sound rather clear? A unit which triggers the event = Dying unit. The difference is Triggering unit works like locals, so it won't be replaced within 35 seconds.

What is odd is I seperated the trigger into 3 If, Then, Else Multiple Actions Actions. For each I had each of the three counters (Hero, Peon and Townhall), I then set it to enter a game message to confirm if each counter was successful or not, Eg, if I killed a peon, but the owning player still had peons, but no more townhalls or heroes, the Chat would come up;
Peon Count Failed - Still more Peons
Townhall Count Complete - No Townhalls Left
Hero Count Complete - No Heroes left

And funny enough the trigger was confirming all 3 counters were completing when they should, yet the player was still not getting defeated. I'm very puzzled. Here is what I did to check the conditions;
YHUPILB.png
You did not put Defeat function there.
  • Game - Defeat (Triggering player) with the message: Defeat!
 
Level 2
Joined
May 4, 2013
Messages
8
New Development, turns out the default Bot you fight in the World Editor when you Test Map doesn't count as a player, and thus doesn't seem to get defeated? I'm not sure. I know this because I loaded the map from within the game instead and then destroyed a bot for testing and the trigger appeared to activate, although no 'This Player has been defeated' emerged, there was my own custom game text trigger I made which confirmed the Defeat action would have occured. Only problem is it seems to spam the trigger multiple times so I will have to add a condition, Player is defeated Equal to false on the If Then Multiple action.
 
Level 2
Joined
May 4, 2013
Messages
8
No, that shouldn't be the case, especially if you already include the filter "Unit is alive = true". Basically, it takes 35 seconds for the trigger to refer the dying unit and in that 35 seconds, the dying unit can be replaced by any other units who die at the time so the trigger might refer different unit instead. Doesn't Triggering unit sound rather clear? A unit which triggers the event = Dying unit. The difference is Triggering unit works like locals, so it won't be replaced within 35 seconds.


You did not put Defeat function there.
  • Game - Defeat (Triggering player) with the message: Defeat!

That was just for me to test the conditions, I didn't put the Defeat Trigger on that one,

and yea I see what your saying with the dying unit. Perhaps I could set up a Variable, DyingUnit Equals Event Response - Dying Unit , then use the DyingUnit variable to refer to for the rest of the actions, as..... or maybe that wouldn't work either. Still it seemed to work thus far, I'll keep testing
 
Level 13
Joined
May 10, 2009
Messages
868
If you're still interested in using all those functions made by Blizzard regarding victory/defeat (crippling and exposing players, show timer window, adapt it when a player changes their alliances), and wonder why it doesn't really work for your custom town halls, well, it is because there's a huge flaw in one of those blizzard functions.

GUI action:
  • Melee Game - Enforce victory/defeat conditions (for all players)
That action contains a lot of functions and triggers, but within them you can see that the flawed function is this one:
JASS:
function MeleeGetAllyKeyStructureCount takes player whichPlayer returns integer
    local integer    playerIndex
    local player     indexPlayer
    local integer    keyStructs

    // Count the number of buildings controlled by all not-yet-defeated co-allies.
    set keyStructs = 0
    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)
        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
            set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "townhall", true, true)
            set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "greathall", true, true)
            set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "treeoflife", true, true)
            set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "necropolis", true, true)
        endif
       
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop

    return keyStructs
endfunction
As you can see, it only checks specific unit types by their names.
I still have a map here with that bug fixed. All you need to do is copy all the code and paste it in your map header, then call the function once the map initializes.

JASS:
//==============================================================================================//
//                                                                                              //
// The main purpose of this is to just get rid of the bug where custom units flagged as         //
// town halls didn't count for the CripplePlayer function. I also removed a few leaks generated //
// by Blizzard.                                                                                 //
//                                                                                              //
//==============================================================================================//


// Count units flagged as UNIT_TYPE_TOWNHALL
function GetAllyKeyStructureCount takes player whichPlayer returns integer
    local unit fog = null
    local group g = CreateGroup()
    local integer result = 0
    local integer playerIndex = 0
 
    loop
        exitwhen playerIndex == bj_MAX_PLAYERS
        if PlayersAreCoAllied(whichPlayer, Player(playerIndex)) then
            call GroupEnumUnitsOfPlayer(g, Player(playerIndex), null)
            loop
                set fog = FirstOfGroup(g)
                exitwhen fog == null
                call GroupRemoveUnit(g, fog)
                if IsUnitType(fog, UNIT_TYPE_TOWNHALL) and GetWidgetLife(fog) > .405 then
                    set result = result + 1
                endif
            endloop
        endif
        set playerIndex = playerIndex + 1
    endloop
 
    call DestroyGroup(g)
    set g = null
    return result
endfunction

function CheckForVictors takes force opponentlessPlayers returns force
    local integer    playerIndex
    local integer    opponentIndex
    local boolean    gameOver = false
 
    // Check to see if any players have opponents remaining.
    set playerIndex = 0
    loop
        if (not bj_meleeDefeated[playerIndex]) then
            // Determine whether or not this player has any remaining opponents.
            set opponentIndex = 0
            loop
                // If anyone has an opponent, noone can be victorious yet.
                if MeleePlayerIsOpponent(playerIndex, opponentIndex) then
                    call DestroyForce(opponentlessPlayers)
                    set opponentlessPlayers = null
                    return null
                endif

                set opponentIndex = opponentIndex + 1
                exitwhen opponentIndex == bj_MAX_PLAYERS
            endloop
       
            // Keep track of each opponentless player so that we can give
            // them a victory later.
            call ForceAddPlayer(opponentlessPlayers, Player(playerIndex))
            set gameOver = true
        endif
   
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop

    // Set the game over global flag
    set bj_meleeGameOver = gameOver

    return opponentlessPlayers
endfunction

// Find opponentless players
function CheckForLosersAndVictors takes nothing returns nothing
    local integer    playerIndex
    local player     indexPlayer
    local force      defeatedPlayers = CreateForce()
    local force      victoriousPlayers = null
    local boolean    gameOver = false

    // If the game is already over, do nothing
    if (bj_meleeGameOver) then
        return
    endif

    // If the game was disconnected then it is over, in this case we
    // don't want to report results for anyone as they will most likely
    // conflict with the actual game results
    if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
        set bj_meleeGameOver = true
        return
    endif

    // Check each player to see if he or she has been defeated yet.
    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)

        if (not bj_meleeDefeated[playerIndex] and not bj_meleeVictoried[playerIndex]) then
            //call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Player"+I2S(playerIndex)+" has "+I2S(MeleeGetAllyStructureCount(indexPlayer))+" ally buildings.")
            if (MeleeGetAllyStructureCount(indexPlayer) <= 0) then

                // Keep track of each defeated player so that we can give
                // them a defeat later.
                call ForceAddPlayer(defeatedPlayers, Player(playerIndex))

                // Set their defeated flag now so MeleeCheckForVictors
                // can detect victors.
                set bj_meleeDefeated[playerIndex] = true
            endif
        endif
       
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop

    // Now that the defeated flags are set, check if there are any victors
    set victoriousPlayers = CheckForVictors(CreateForce())

    // Defeat all defeated players
    call ForForce(defeatedPlayers, function MeleeDoDefeatEnum)

    // Give victory to all victorious players
    call ForForce(victoriousPlayers, function MeleeDoVictoryEnum)

    // If the game is over we should remove all observers
    if (bj_meleeGameOver) then
        call MeleeRemoveObservers()
    endif
 
    // Destroy and null handles
    call DestroyForce(defeatedPlayers)
    if victoriousPlayers != null then
        call DestroyForce(victoriousPlayers)
        set victoriousPlayers = null
    endif
    set defeatedPlayers = null
    set indexPlayer = null
endfunction

// CRIPPLE
function CheckForCrippledPlayers takes nothing returns nothing
    local integer    playerIndex
    local player     indexPlayer
    local boolean    isNowCrippled

    // The "finish soon" exposure of all players overrides any "crippled" exposure
    if bj_finishSoonAllExposed then
        return
    endif

    // Check each player to see if he or she has been crippled or uncrippled.
    set playerIndex = 0
    loop
        set indexPlayer = Player(playerIndex)
        set isNowCrippled = (MeleeGetAllyStructureCount(indexPlayer) > 0) and (GetAllyKeyStructureCount(indexPlayer) <= 0)

        if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then

            // Player became crippled; start their cripple timer.
            set bj_playerIsCrippled[playerIndex] = true
            call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeout)

            if (GetLocalPlayer() == indexPlayer) then
                // Use only local code (no net traffic) within this block to avoid desyncs.

                // Show the timer window.
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)

                // Display a warning message.
                call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledWarningMessage(indexPlayer))
            endif

        elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then

            // Player became uncrippled; stop their cripple timer.
            set bj_playerIsCrippled[playerIndex] = false
            call PauseTimer(bj_crippledTimer[playerIndex])

            if (GetLocalPlayer() == indexPlayer) then
                // Use only local code (no net traffic) within this block to avoid desyncs.

                // Hide the timer window for this player.
                call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)

                // Display a confirmation message if the player's team is still alive.
                if (MeleeGetAllyStructureCount(indexPlayer) > 0) then
                    if (bj_playerIsExposed[playerIndex]) then
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))
                    else
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))
                    endif
                endif
            endif

            // If the player granted shared vision, deny that vision now.
            call MeleeExposePlayer(indexPlayer, false)

        endif
       
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == bj_MAX_PLAYERS
    endloop
 
    set indexPlayer = null
endfunction

// UNIT DIES
function TriggerActionCheckLostUnit takes nothing returns nothing
    if IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) then
        // We only need to check for mortality if this was the last building.
        if (GetPlayerStructureCount(GetOwningPlayer(GetTriggerUnit()), true) <= 0) then
            call CheckForLosersAndVictors()
        endif

        // Check if the lost unit has crippled or uncrippled the player.
        // (A team with 0 units is dead, and thus considered uncrippled.)
        call CheckForCrippledPlayers()
    endif
endfunction

function TriggerActionAllianceChange takes nothing returns nothing
    call CheckForLosersAndVictors()
    call CheckForCrippledPlayers()
endfunction

function TriggerActionCheckAddedUnit takes nothing returns nothing
    // If the player was crippled, this unit may have uncrippled him/her.
    if (bj_playerIsCrippled[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) then
        call CheckForCrippledPlayers()
    endif
endfunction

function TriggerActionPlayerDefeated takes nothing returns nothing
    local player thePlayer = GetTriggerPlayer()
    call CachePlayerHeroData(thePlayer)

    if (MeleeGetAllyCount(thePlayer) > 0) then
        // If at least one ally is still alive and kicking, share units with
        // them and proceed with death.
        call ShareEverythingWithTeam(thePlayer)
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
            call MeleeDoDefeat(thePlayer)
        endif
    else
        // If no living allies remain, swap all units and buildings over to
        // neutral_passive and proceed with death.
        call MakeUnitsPassiveForTeam(thePlayer)
        if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
            call MeleeDoDefeat(thePlayer)
        endif
    endif
    call CheckForLosersAndVictors()
    set thePlayer = null
endfunction

function TriggerActionPlayerLeft takes nothing returns nothing
    local player thePlayer = GetTriggerPlayer()

    // Just show game over for observers when they leave
    if (IsPlayerObserver(thePlayer)) then
        call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_NEUTRAL, false)
        set thePlayer = null
        return
    endif

    call CachePlayerHeroData(thePlayer)

    // This is the same as defeat except the player generates the message
    // "player left the game" as opposed to "player was defeated".

    if (MeleeGetAllyCount(thePlayer) > 0) then
        // If at least one ally is still alive and kicking, share units with
        // them and proceed with death.
        call ShareEverythingWithTeam(thePlayer)
        call MeleeDoLeave(thePlayer)
    else
        // If no living allies remain, swap all units and buildings over to
        // neutral_passive and proceed with death.
        call MakeUnitsPassiveForTeam(thePlayer)
        call MeleeDoLeave(thePlayer)
    endif
    call CheckForLosersAndVictors()
    set thePlayer = null
endfunction

function MeleeVictoryDefeat takes nothing returns nothing
    local trigger    trig
    local integer    index
    local player     indexPlayer

    // Create a timer window for the "finish soon" timeout period, it has no timer
    // because it is driven by real time (outside of the game state to avoid desyncs)
    set bj_finishSoonTimerDialog = CreateTimerDialog(null)

    // Set a trigger to fire when we receive a "finish soon" game event
    set trig = CreateTrigger()
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)

    // Set a trigger to fire when we receive a "finish now" game event
    set trig = CreateTrigger()
    call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)
    call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)

    // Set up each player's mortality code.
    set index = 0
    loop
        set indexPlayer = Player(index)

        // Make sure this player slot is playing.
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set bj_meleeDefeated[index] = false
            set bj_meleeVictoried[index] = false

            // Create a timer and timer window in case the player is crippled.
            set bj_playerIsCrippled[index] = false
            set bj_playerIsExposed[index] = false
            set bj_crippledTimer[index] = CreateTimer()
            set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])
            call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))

            // Set a trigger to fire whenever a building is cancelled for this player.
            set trig = CreateTrigger()
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
            call TriggerAddAction(trig, function TriggerActionCheckLostUnit)

            // Set a trigger to fire whenever a unit dies for this player.
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)
            call TriggerAddAction(trig, function TriggerActionCheckLostUnit)

            // Set a trigger to fire whenever a unit begins construction for this player
            set trig = CreateTrigger()
            call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
            call TriggerAddAction(trig, function TriggerActionCheckAddedUnit)

            // Set a trigger to fire whenever this player defeats-out
            set trig = CreateTrigger()
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)
            call TriggerAddAction(trig, function TriggerActionPlayerDefeated)

            // Set a trigger to fire whenever this player leaves
            set trig = CreateTrigger()
            call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
            call TriggerAddAction(trig, function TriggerActionPlayerLeft)

            // Set a trigger to fire whenever this player changes his/her alliances.
            set trig = CreateTrigger()
            call TriggerRegisterPlayerAllianceChange(trig, indexPlayer, ALLIANCE_PASSIVE)
            call TriggerRegisterPlayerStateEvent(trig, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)
            call TriggerAddAction(trig, function TriggerActionAllianceChange)
        else
            set bj_meleeDefeated[index] = true
            set bj_meleeVictoried[index] = false

            // Handle leave events for observers
            if (IsPlayerObserver(indexPlayer)) then
                // Set a trigger to fire whenever this player leaves
                set trig = CreateTrigger()
                call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
                call TriggerAddAction(trig, function TriggerActionPlayerLeft)
            endif
        endif

        set index = index + 1
        exitwhen index == bj_MAX_PLAYERS
    endloop

    // Test for victory / defeat at startup, in case the user has already won / lost.
    // Allow for a short time to pass first, so that the map can finish loading.
    call TimerStart(CreateTimer(), 2.0, false, function TriggerActionAllianceChange)
endfunction

//==============================================================================================//

Then:
  • Melee Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Melee Game - Use melee time of day (for all players)
      • Melee Game - Limit Heroes to 1 per Hero-type (for all players)
      • Melee Game - Give trained Heroes a Scroll of Town Portal (for all players)
      • Melee Game - Set starting resources (for all players)
      • Melee Game - Remove creeps and critters from used start locations (for all players)
      • Melee Game - Create starting units (for all players)
      • Melee Game - Run melee AI scripts (for computer players)
      • Custom script: call MeleeVictoryDefeat()
 

Attachments

  • MeleeWinLoseConditions.w3x
    26.5 KB · Views: 48
Level 22
Joined
Aug 27, 2013
Messages
3,973
He has re-worked the trigger for testing to see wtf is going wrong, not to defeat players.
Well, pardon me. I did a very quick reading that I did not really follow what he intended to do with the trigger. Since he said the player was still not getting defeated so I quickly glanced through the trigger.

That was just for me to test the conditions, I didn't put the Defeat Trigger on that one,

and yea I see what your saying with the dying unit. Perhaps I could set up a Variable, DyingUnit Equals Event Response - Dying Unit , then use the DyingUnit variable to refer to for the rest of the actions, as..... or maybe that wouldn't work either. Still it seemed to work thus far, I'll keep testing
I actually did some testing and it worked if you put unit is alive = true for building in the filter as well. Since you said the wait function is to give time for the units to fully decay, it is not necessary so I removed it. Here's the test trigger I did.
  • Untitled Trigger 001
    • Events
      • Unit - A unit Dies
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • ((Triggering unit) is A peon-type unit) Equal to True
          • ((Triggering unit) is A Hero) Equal to True
          • ((Triggering unit) is A town-hall-type unit) Equal to True
    • Actions
      • Game - Display to (All players) the text: ((Name of (Triggering unit)) + dies.)
      • Set TownHallOwned = (Units in (Playable map area) matching ((((Matching unit) is A town-hall-type unit) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • Set PeonOwned = (Units in (Playable map area) matching ((((Matching unit) is A peon-type unit) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • Set HeroOwned = (Units in (Playable map area) matching ((((Matching unit) is A Hero) Equal to True) and (((Owner of (Matching unit)) Equal to (Owner of (Triggering unit))) and (((Matching unit) is alive) Equal to True))))
      • Game - Display to (All players) the text: (Hero Owned: + (String((Number of units in HeroOwned))))
      • Game - Display to (All players) the text: (Peon Owned: + (String((Number of units in PeonOwned))))
      • Game - Display to (All players) the text: (TH Owned: + (String((Number of units in TownHallOwned))))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in TownHallOwned) Equal to 0
          • (Number of units in PeonOwned) Equal to 0
          • (Number of units in HeroOwned) Equal to 0
        • Then - Actions
          • Game - Display to (All players) the text: ((Name of (Triggering player)) + has been defeated.)
          • Game - Defeat (Triggering player) with the message: Defeat!
        • Else - Actions
      • Custom script: call DestroyGroup(udg_TownHallOwned)
      • Custom script: call DestroyGroup(udg_PeonOwned)
      • Custom script: call DestroyGroup(udg_HeroOwned)
Try it with whosyourdaddy cheat.
 

Attachments

  • Test.w3x
    18.5 KB · Views: 47
Status
Not open for further replies.
Top