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

Blizz-Like Melee Settings For Extra Races 2.5

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Allows Blizzard-like Victory/Defeat conditions for Altered Melee races as well as an easy selection method.
JASS:
//***************************************************************************
//*
//*  Altered Melee Starting AI Scripts
//*
//***************************************************************************

//===========================================================================
function AlteredMeleeShowAIRaceDialog takes nothing returns nothing
    local integer index = 1

    loop
        if ( udg_AM_AI_PlayerNum == 0 ) then
            if ( udg_AM_RaceChosen[index] == 0 ) then
                if ( GetPlayerController(Player(index - 1)) == MAP_CONTROL_COMPUTER ) then
                    set udg_AM_AI_PlayerNum = index
                    call DialogSetMessage( udg_AM_RaceDialog_AI_1, ( "Computer Player " + I2S(udg_AM_AI_PlayerNum) + "'s Race" ) )
                    call DialogDisplay( Player(0), udg_AM_RaceDialog_AI_1, true )
                endif
            endif
        endif
        set index = index + 1
        exitwhen index == 12
    endloop
endfunction

//===========================================================================
function AlteredMeleeStartingAI takes nothing returns nothing
    local integer index = 0
    local player  indexPlayer
    local integer indexRace

    loop
        set indexPlayer = Player(index)
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexRace = udg_AM_RaceChosen[index + 1]
            if (GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER) then
                // Run a race-specific melee AI script.
                call PickMeleeAI(indexPlayer, udg_AM_AI_FilePath[indexRace], null, null)
                call ShareEverythingWithTeamAI(indexPlayer)
            endif
        endif

        set index = index + 1
        exitwhen index == 12
    endloop
endfunction

//***************************************************************************
//*
//*  Altered Melee Starting Units Scripts
//*
//***************************************************************************

//===========================================================================
// Starting Units for Custom Race Players
//   - 1 Tier1 Hall, placed at start location
//   - 5 Primary Workers or 3 Primary Workers and 1 Seconday Worker, placed between start location and nearest gold mine 
//
function MeleeStartingUnitsCustom takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload, integer whichRace returns nothing
    local boolean  useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
    local real     unitSpacing   = 64.00
    local unit     nearestMine
    local unit     hallT1
    local location nearMineLoc
    local location nearTownLoc
    local location exactMineLoc
    local location heroLoc
    local location tempLoc1
    local real     primaryX
    local real     primaryY
    local real     secondaryX
    local real     secondaryY
    local integer mineGold

    set nearestMine = MeleeFindNearestMine(startLoc, 2000)
    if (nearestMine != null) then
        set tempLoc1 = GetUnitLoc(nearestMine)
        set nearMineLoc = MeleeGetProjectedLoc(tempLoc1, startLoc, 320, 0)
        set primaryX = GetLocationX(nearMineLoc)
        set primaryY = GetLocationY(nearMineLoc)
        set nearTownLoc = MeleeGetProjectedLoc(startLoc, tempLoc1, 288, 0)
        set secondaryX = GetLocationX(nearTownLoc)
        set secondaryY = GetLocationY(nearTownLoc)
        set exactMineLoc = MeleeGetProjectedLoc(tempLoc1, startLoc, 0, 0)
        set mineGold = GetResourceAmount(nearestMine)
        call RemoveLocation(tempLoc1)
    else
        set nearMineLoc = startLoc
        set primaryX = GetLocationX(startLoc)
        set primaryY = GetLocationY(startLoc) - 224.00
        set nearTownLoc = startLoc
        set secondaryX = primaryX
        set secondaryY = primaryY
        set exactMineLoc = startLoc
        set mineGold = 19000
    endif

    //Check to see if race has a special goldmining structure
    if (udg_AM_UnitType_Goldmine[whichRace] != null) then
        //Check to see if Tier1 Hall entangles gold mines
        if (udg_AM_HallEntanglesGoldmine[whichRace] != false) then
            //Check to see if the goldmining structure is that race's townhall
            if (udg_AM_UnitType_Goldmine[whichRace] == udg_AM_UnitType_TownhallT1[whichRace]) then
                // Create a Tier1 Hall to replace the Gold Mine
                call RemoveUnit(nearestMine)
                set nearestMine = CreateUnitAtLoc(whichPlayer, udg_AM_UnitType_TownhallT1[whichRace], exactMineLoc, 270.0)
                call SetResourceAmount(nearestMine, mineGold)
            else
                // Spawn Tier1 Hall near goldmine.
                set hallT1 = CreateUnitAtLoc(whichPlayer, udg_AM_UnitType_TownhallT1[whichRace], nearMineLoc, 270.0)
                call IssueTargetOrder(hallT1, "entangleinstant", nearestMine)
            endif
        else
            // Create a Racial Gold Mine to replace the Gold Mine.
            if (nearestMine != null) then
                call RemoveUnit(nearestMine)
                set nearestMine = CreateUnitAtLoc(whichPlayer, udg_AM_UnitType_Goldmine[whichRace], exactMineLoc, 270.0)
                call SetResourceAmount(nearestMine, mineGold)
            endif
            // Spawn Tier1 Hall at the start location.
            set hallT1 = CreateUnitAtLoc(whichPlayer, udg_AM_UnitType_TownhallT1[whichRace], startLoc, 270.0)
        endif
    else
        // Spawn Tier1 Hall at the start location.
        set hallT1 = CreateUnitAtLoc(whichPlayer, udg_AM_UnitType_TownhallT1[whichRace], startLoc, 270.0)
    endif

    // Spawn Primary Workers near the mine.
    call CreateUnit(whichPlayer, udg_AM_UnitType_PrimaryWorker[whichRace], primaryX + 0.00 * unitSpacing, primaryY + 1.00 * unitSpacing, 270.0)
    call CreateUnit(whichPlayer, udg_AM_UnitType_PrimaryWorker[whichRace], primaryX + 1.00 * unitSpacing, primaryY + 0.15 * unitSpacing, 270.0)
    call CreateUnit(whichPlayer, udg_AM_UnitType_PrimaryWorker[whichRace], primaryX - 1.00 * unitSpacing, primaryY + 0.15 * unitSpacing, 270.0)
    //If secondary workers exist then spawn 1 instead of 2 more primary workers.
    if (udg_AM_UnitType_SecondaryWorker[whichRace] != null) then
        // Spawn Secondary Workers near the Tier1 Hall.
        call CreateUnit(whichPlayer, udg_AM_UnitType_SecondaryWorker[whichRace], secondaryX + 0.60 * unitSpacing, secondaryY - 1.00 * unitSpacing, 270.0)
    else
        call CreateUnit(whichPlayer, udg_AM_UnitType_PrimaryWorker[whichRace], primaryX + 0.60 * unitSpacing, primaryY - 1.00 * unitSpacing, 270.0)
        call CreateUnit(whichPlayer, udg_AM_UnitType_PrimaryWorker[whichRace], primaryX - 0.60 * unitSpacing, primaryY - 1.00 * unitSpacing, 270.0)
    endif

    //Check to see if race starts with blight around starting area
    if (udg_AM_StartsWithBlight[whichRace] == true)  then
        // Create a patch of blight near the mine.
        call SetBlightLoc(whichPlayer,nearMineLoc, 768, true)
    endif      

    // Set random hero spawn point to be near workers.
    set heroLoc = Location(primaryX, primaryY - 2.00 * unitSpacing)
    if (doHeroes) then
        // If the "Random Hero" option is set, start the player with a random hero.
        // Otherwise, give them a "free hero" token.
        if useRandomHero then
            call MeleeRandomHeroLoc(whichPlayer, udg_AM_UnitType_Hero1[whichRace], udg_AM_UnitType_Hero2[whichRace], udg_AM_UnitType_Hero3[whichRace], udg_AM_UnitType_Hero4[whichRace], heroLoc)
        else
            call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, 1)
        endif
    endif

    if (doCamera) then
        // Center the camera on the initial Peasants.
        call SetCameraPositionForPlayer(whichPlayer, primaryX, primaryY )
        call SetCameraQuickPositionForPlayer(whichPlayer, primaryX, primaryY )
    endif
    call RemoveLocation(nearMineLoc)
    call RemoveLocation(nearTownLoc)
    call RemoveLocation(exactMineLoc)
    call RemoveLocation(heroLoc)
endfunction

//===========================================================================
function AlteredMeleeStartingUnits takes nothing returns nothing
    local integer  index = 0
    local player   indexPlayer
    local location indexStartLoc

    call Preloader( "scripts\\SharedMelee.pld" )

    loop
        set indexPlayer = Player(index)
        if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
            set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))

            // Create initial race-specific starting units
            call MeleeStartingUnitsCustom(indexPlayer, indexStartLoc, true, true, true, udg_AM_RaceChosen[index + 1])
        endif

        call RemoveLocation(indexStartLoc)

        set index = index + 1
        exitwhen index == 12
    endloop

    call RemoveLocation(indexStartLoc)
    
endfunction

//***************************************************************************
//*
//*  Altered Melee Template Victory / Defeat Conditions
//*
//***************************************************************************

//===========================================================================
// Count buildings currently owned by all allies, including the player themself.
//
function AlteredMeleeGetAllyStructureCount takes player whichPlayer returns integer
    local integer    playerIndex = 0
    local integer    buildingCount = 0
    local player     indexPlayer

    // Count the number of buildings controlled by all not-yet-defeated co-allies.
    loop
        set indexPlayer = Player(playerIndex)

        // uncomment to cause defeat even if you have control of ally structures, but yours have been nixed
        //if (PlayersAreCoAllied(whichPlayer, indexPlayer) and not bj_meleeDefeated[playerIndex]) then
        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
            set buildingCount = buildingCount + GetPlayerStructureCount(indexPlayer, true)
        endif
            
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == 12
    endloop

    return buildingCount
endfunction

//===========================================================================
// Counts key structures owned by a player and his or her allies, including
// structures currently upgrading or under construction.
//
// Key structures: Town Hall, Great Hall, Tree of Life, Necropolis
//
function AlteredMeleeGetAllyKeyStructureCount takes player whichPlayer returns integer
    local integer    playerIndex = 0
    local player     indexPlayer
    local integer    keyStructs = 0
    local integer    raceIndex = 1

    // Count the number of buildings controlled by all not-yet-defeated co-allies.
    loop
        set indexPlayer = Player(playerIndex)
        if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
            loop
                set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT1[raceIndex], indexPlayer)
                if ( udg_AM_UnitType_TownhallT2[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT2[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT3[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT3[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT4[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT4[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT5[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT5[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT6[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT6[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT7[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT7[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT8[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT8[raceIndex], indexPlayer)
                endif
                if ( udg_AM_UnitType_TownhallT9[raceIndex] != null ) then
                    set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId(udg_AM_UnitType_TownhallT9[raceIndex], indexPlayer)
                endif
                set raceIndex = raceIndex + 1
                exitwhen raceIndex == (udg_AM_NumOfRaceChoices + 1)
            endloop
        endif
            
        set playerIndex = playerIndex + 1
        exitwhen playerIndex == 12
    endloop

    return keyStructs
endfunction

//===========================================================================
// Test each player to determine if anyone has been defeated.
//
function AlteredMeleeCheckForLosersAndVictors takes nothing returns nothing
    local integer    playerIndex = 0
    local player     indexPlayer
    local force      defeatedPlayers = CreateForce()
    local force      victoriousPlayers
    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.
    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(AlteredMeleeGetAllyStructureCount(indexPlayer))+" ally buildings.")
            if (AlteredMeleeGetAllyStructureCount(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 == 12
    endloop

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

    // 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
endfunction

//===========================================================================
// Returns a race-specific "build X or be revealed" message.
//
function AlteredMeleeGetCrippledWarningMessage takes player whichPlayer returns string
    local integer indexPlayer = GetPlayerId(whichPlayer)+ 1

    return udg_AM_RevealMessage[udg_AM_RaceChosen[indexPlayer]]
endfunction

//===========================================================================
// Returns a race-specific "build X" label for cripple timers.
//
function AlteredMeleeGetCrippledTimerMessage takes player whichPlayer returns string
    local integer indexPlayer = GetPlayerId(whichPlayer)+ 1

    return udg_AM_BuildWindow[udg_AM_RaceChosen[indexPlayer]]
endfunction

//===========================================================================
function AlteredMeleePlayerIsCrippled takes player whichPlayer returns boolean
    local integer allyStructures    = AlteredMeleeGetAllyStructureCount(whichPlayer)
    local integer allyKeyStructures = AlteredMeleeGetAllyKeyStructureCount(whichPlayer)

    // Dead teams are not considered to be crippled.
    return (allyStructures > 0) and (allyKeyStructures <= 0)
endfunction

//===========================================================================
// Test each player to determine if anyone has become crippled.
//
function AlteredMeleeCheckForCrippledPlayers takes nothing returns nothing
    local integer    playerIndex = 0
    local player     indexPlayer
    local force      crippledPlayers = CreateForce()
    local boolean    isNowCrippled = false

    // 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.
    loop
        set indexPlayer = Player(playerIndex)
        set isNowCrippled = AlteredMeleePlayerIsCrippled(indexPlayer)

        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], 120.00, 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, 20.00, AlteredMeleeGetCrippledWarningMessage(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 (AlteredMeleeGetAllyStructureCount(indexPlayer) > 0) then
                    if (bj_playerIsExposed[playerIndex]) then
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, 20.00, GetLocalizedString("CRIPPLE_UNREVEALED"))
                    else
                        call DisplayTimedTextToPlayer(indexPlayer, 0, 0, 20.00, 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 == 12
    endloop
endfunction

//===========================================================================
// Determine if the lost unit should result in any defeats or victories.
//
function AlteredMeleeCheckLostUnit takes unit lostUnit returns nothing
    local player lostUnitOwner = GetOwningPlayer(lostUnit)

    // We only need to check for mortality if this was the last building.
    if (GetPlayerStructureCount(lostUnitOwner, true) <= 0) then
        call AlteredMeleeCheckForLosersAndVictors()
    endif

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

//===========================================================================
// Determine if the gained unit should result in any defeats, victories,
// or cripple-status changes.
//
function AlteredMeleeCheckAddedUnit takes unit addedUnit returns nothing
    local player addedUnitOwner = GetOwningPlayer(addedUnit)

    // If the player was crippled, this unit may have uncrippled him/her.
    if (bj_playerIsCrippled[GetPlayerId(addedUnitOwner)]) then
        call AlteredMeleeCheckForCrippledPlayers()
    endif
endfunction

//===========================================================================
function AlteredMeleeTriggerActionConstructCancel takes nothing returns nothing
    call AlteredMeleeCheckLostUnit(GetCancelledStructure())
endfunction

//===========================================================================
function AlteredMeleeTriggerActionUnitDeath takes nothing returns nothing
    if (IsUnitType(GetDyingUnit(), UNIT_TYPE_STRUCTURE)) then
        call AlteredMeleeCheckLostUnit(GetDyingUnit())
    endif
endfunction

//===========================================================================
function AlteredMeleeTriggerActionUnitConstructionStart takes nothing returns nothing
    call AlteredMeleeCheckAddedUnit(GetConstructingStructure())
endfunction

//===========================================================================
function AlteredMeleeTriggerActionPlayerDefeated 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 AlteredMeleeCheckForLosersAndVictors()
endfunction

//===========================================================================
function AlteredMeleeTriggerActionPlayerLeft takes nothing returns nothing
    local player thePlayer = GetTriggerPlayer()
    local trigger t = CreateTrigger()
    local dialog  d = DialogCreate()

    // Just show game over for observers when they leave
    if (IsPlayerObserver(thePlayer)) then
        if AllowVictoryDefeat(PLAYER_GAME_RESULT_NEUTRAL) then
            call RemovePlayer(thePlayer, PLAYER_GAME_RESULT_NEUTRAL)

            // Display "player was defeated" or "player has left the game" message

            call DisplayTimedTextFromPlayer(thePlayer, 0, 0, 60, GetLocalizedString( "PLAYER_LEFT_GAME" ))

            call DialogSetMessage( d, GetLocalizedString( "GAMEOVER_DEFEAT_MSG" ) )

            // Only show the continue button if the game is not over and observers on death are allowed
            if (not bj_meleeGameOver and IsMapFlagSet(MAP_OBSERVERS_ON_DEATH)) then
                call DialogAddButton( d, GetLocalizedString( "GAMEOVER_CONTINUE_OBSERVING" ), GetLocalizedHotkey("GAMEOVER_CONTINUE_OBSERVING") )
            endif

            set t = CreateTrigger()
            call TriggerRegisterDialogButtonEvent( t, DialogAddQuitButton( d, true, GetLocalizedString( "GAMEOVER_QUIT_GAME" ), GetLocalizedHotkey("GAMEOVER_QUIT_GAME") ) )

            call DialogDisplay( thePlayer, d, true )
            if (thePlayer == GetLocalPlayer()) then
                call StartSound(bj_defeatDialogSound)
            endif
        endif
    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 AlteredMeleeCheckForLosersAndVictors()
endfunction

//===========================================================================
function AlteredMeleeTriggerActionAllianceChange takes nothing returns nothing
    call AlteredMeleeCheckForLosersAndVictors()
    call AlteredMeleeCheckForCrippledPlayers()
endfunction

//===========================================================================
function AlteredMeleeInitVictoryDefeat takes nothing returns nothing
    local trigger    trig
    local integer    index = 0
    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.
    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], AlteredMeleeGetCrippledTimerMessage(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 AlteredMeleeTriggerActionConstructCancel)

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

            // 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 AlteredMeleeTriggerActionUnitConstructionStart)

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

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

            // 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 AlteredMeleeTriggerActionAllianceChange)
        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 AlteredMeleeTriggerActionPlayerLeft)
            endif
        endif

        set index = index + 1
        exitwhen index == 12
    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 AlteredMeleeTriggerActionAllianceChange)
endfunction

function AlteredMeleeCreateComputerDialog takes nothing returns nothing
    local integer raceIndex = 1
    // Below automatically sets up the Dialog box for Computer players with Races that have AI
    loop
        exitwhen raceIndex > udg_AM_NumOfRaceChoices
        if ( udg_AM_RaceName[raceIndex] != "" ) then
            if ( udg_AM_AI_FilePath[raceIndex] != "" ) then
                set udg_AM_NumofRacesWithAI = ( udg_AM_NumofRacesWithAI + 1 )
                if ( udg_AM_NumofRacesWithAI <= 9 ) then
                    set udg_AM_RaceButton_AI[udg_AM_NumofRacesWithAI] = DialogAddButton( udg_AM_RaceDialog_AI_1, udg_AM_RaceName[raceIndex],0 )
                    set udg_AM_AI_ButtonToRace[udg_AM_NumofRacesWithAI] = raceIndex
                else
                    if ( udg_AM_NumofRacesWithAI <= 19 ) then
                        set udg_AM_RaceButton_AI[udg_AM_NumofRacesWithAI] = DialogAddButton( udg_AM_RaceDialog_AI_2, udg_AM_RaceName[raceIndex],0 )
                        set udg_AM_AI_ButtonToRace[udg_AM_NumofRacesWithAI] = raceIndex
                    else
                        set udg_AM_RaceButton_AI[udg_AM_NumofRacesWithAI] = DialogAddButton( udg_AM_RaceDialog_AI_3, udg_AM_RaceName[raceIndex],0 )
                        set udg_AM_AI_ButtonToRace[udg_AM_NumofRacesWithAI] = raceIndex
                    endif
                endif
            endif
        endif
        set raceIndex = raceIndex + 1
    endloop
    if ( udg_AM_NumofRacesWithAI >= 10 ) then
        if ( udg_AM_NumofRacesWithAI <= 19 ) then
            set udg_AM_OtherButton[8] = DialogAddButton( udg_AM_RaceDialog_AI_1, "Next",0 )
            set udg_AM_OtherButton[10] = DialogAddButton( udg_AM_RaceDialog_AI_2, "Next",0 )
            set udg_AM_OtherButton[13] = DialogAddButton( udg_AM_RaceDialog_AI_1, "Previous",0 )
            set udg_AM_OtherButton[12] = DialogAddButton( udg_AM_RaceDialog_AI_2, "Previous",0 )
        else
            set udg_AM_OtherButton[8] = DialogAddButton( udg_AM_RaceDialog_AI_1, "Next",0 )
            set udg_AM_OtherButton[9] = DialogAddButton( udg_AM_RaceDialog_AI_2, "Next",0 )
            set udg_AM_OtherButton[10] = DialogAddButton( udg_AM_RaceDialog_AI_3, "Next",0 )
            set udg_AM_OtherButton[11] = DialogAddButton( udg_AM_RaceDialog_AI_1, "Previous",0 )
            set udg_AM_OtherButton[12] = DialogAddButton( udg_AM_RaceDialog_AI_2, "Previous",0 )
            set udg_AM_OtherButton[13] = DialogAddButton( udg_AM_RaceDialog_AI_3, "Previous",0 )
        endif
    endif
    set udg_AM_OtherButton[14] = DialogAddButton( udg_AM_RaceDialog_AI_1, "Random",0 )
endfunction

function AlteredMeleeCreatePlayerDialog takes nothing returns nothing
    local integer raceIndex = 1 

    loop
        exitwhen raceIndex > udg_AM_NumOfRaceChoices
        if ( udg_AM_RaceName[raceIndex] != "" ) then
            if ( raceIndex <= 9 ) then
                set udg_AM_RaceButton_PL[raceIndex] = DialogAddButton( udg_AM_RaceDialog_PL_1, udg_AM_RaceName[raceIndex],0 )
            else
                if ( udg_AM_NumOfRaceChoices <= 19 ) then
                    set udg_AM_RaceButton_PL[raceIndex] = DialogAddButton( udg_AM_RaceDialog_PL_2, udg_AM_RaceName[raceIndex],0 )
                else
                    set udg_AM_RaceButton_PL[raceIndex] = DialogAddButton( udg_AM_RaceDialog_PL_3, udg_AM_RaceName[raceIndex],0 )
                endif
            endif
        else
        endif
        set raceIndex = raceIndex + 1
    endloop
    if( udg_AM_NumOfRaceChoices >= 10 ) then
        if ( udg_AM_NumOfRaceChoices <= 19 ) then
            set udg_AM_OtherButton[1] = DialogAddButton( udg_AM_RaceDialog_PL_1, "Next",0 )
            set udg_AM_OtherButton[3] = DialogAddButton( udg_AM_RaceDialog_PL_2, "Next",0 )
            set udg_AM_OtherButton[5] = DialogAddButton( udg_AM_RaceDialog_PL_2, "Previous",0 )
            set udg_AM_OtherButton[6] = DialogAddButton( udg_AM_RaceDialog_PL_1, "Previous",0 )
        else
            set udg_AM_OtherButton[1] = DialogAddButton( udg_AM_RaceDialog_PL_1, "Next",0 )
            set udg_AM_OtherButton[2] = DialogAddButton( udg_AM_RaceDialog_PL_2, "Next",0 )
            set udg_AM_OtherButton[3] = DialogAddButton( udg_AM_RaceDialog_PL_3, "Next",0 )
            set udg_AM_OtherButton[4] = DialogAddButton( udg_AM_RaceDialog_PL_1, "Previous",0 )
            set udg_AM_OtherButton[5] = DialogAddButton( udg_AM_RaceDialog_PL_2, "Previous",0 )
            set udg_AM_OtherButton[6] = DialogAddButton( udg_AM_RaceDialog_PL_3, "Previous",0 )
        endif
    endif
    set udg_AM_OtherButton[7] = DialogAddButton( udg_AM_RaceDialog_PL_1, "Random",0 )
    call AlteredMeleeCreateComputerDialog()
endfunction

function Trig_AlteredMeleeCreateStartingUnits_Conditions takes nothing returns boolean
    if ( not ( udg_AM_RaceChosen[1] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[2] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[3] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[4] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[5] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[6] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[7] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[8] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[9] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[10] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[11] != 0 ) ) then
        return false
    endif
    if ( not ( udg_AM_RaceChosen[12] != 0 ) ) then
        return false
    endif
    return true
endfunction

function Trig_AlteredMeleeCreateStartingUnits_Actions takes nothing returns nothing
    call DisableTrigger( GetTriggeringTrigger() )
    call AlteredMeleeStartingUnits()
    call AlteredMeleeInitVictoryDefeat()
    call AlteredMeleeStartingAI()
endfunction

function Trig_AlteredMeleeDialogClickComputer_Actions takes nothing returns nothing
    local integer index = 1
    if ( GetClickedButton() == udg_AM_OtherButton[8] ) then
        call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_2, true )
    else
        if ( GetClickedButton() == udg_AM_OtherButton[9] ) then
            call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_3, true )
        else
            if ( GetClickedButton() == udg_AM_OtherButton[10] ) then
                call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_1, true )
            else
                if ( GetClickedButton() == udg_AM_OtherButton[11] ) then
                    call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_3, true )
                else
                    if ( GetClickedButton() == udg_AM_OtherButton[12] ) then
                        call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_1, true )
                    else
                        if ( GetClickedButton() == udg_AM_OtherButton[13] ) then
                            call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_AI_2, true )
                        else
                            if ( GetClickedButton() == udg_AM_OtherButton[14] ) then
                                set udg_AM_RaceChosen[udg_AM_AI_PlayerNum] = udg_AM_AI_ButtonToRace[GetRandomInt(1, udg_AM_NumofRacesWithAI)]
                                set udg_AM_AI_PlayerNum = 0
                                call AlteredMeleeShowAIRaceDialog()
                            else
                                loop
                                    exitwhen index > udg_AM_NumofRacesWithAI
                                    if ( GetClickedButton() == udg_AM_RaceButton_AI[index] ) then
                                        set udg_AM_RaceChosen[udg_AM_AI_PlayerNum] = udg_AM_AI_ButtonToRace[index]
                                        set udg_AM_AI_PlayerNum = 0
                                        call AlteredMeleeShowAIRaceDialog()
                                    else
                                    endif
                                    set index = index + 1
                                endloop
                            endif
                        endif
                    endif
                endif
            endif
        endif
    endif
endfunction

function Trig_AlteredMeleeDialogClickPlayer_Actions takes nothing returns nothing
    local integer index = 1
    if ( GetClickedButton() == udg_AM_OtherButton[1] ) then
        call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_2, true )
    else
        if ( GetClickedButton() == udg_AM_OtherButton[2] ) then
            call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_3, true )
        else
            if ( GetClickedButton() == udg_AM_OtherButton[3] ) then
                call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_1, true )
            else
                if ( GetClickedButton() == udg_AM_OtherButton[4] ) then
                    call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_3, true )
                else
                    if ( GetClickedButton() == udg_AM_OtherButton[5] ) then
                        call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_1, true )
                    else
                        if ( GetClickedButton() == udg_AM_OtherButton[6] ) then
                            call DialogDisplay( GetTriggerPlayer(), udg_AM_RaceDialog_PL_2, true )
                        else
                            if ( GetClickedButton() == udg_AM_OtherButton[7] ) then
                                set udg_AM_RaceChosen[GetConvertedPlayerId(GetTriggerPlayer())] = GetRandomInt(1, udg_AM_NumOfRaceChoices)
                            else
                                loop
                                    exitwhen index > udg_AM_NumOfRaceChoices
                                    if ( GetClickedButton() == udg_AM_RaceButton_PL[index] ) then
                                        set udg_AM_RaceChosen[GetConvertedPlayerId(GetTriggerPlayer())] = index
                                    else
                                    endif
                                    set index = index + 1
                                endloop
                            endif
                        endif
                    endif
                endif
            endif
        endif
    endif
    if ( GetTriggerPlayer() == Player(0) ) then
        if ( udg_AM_RaceChosen[1] != 0 ) then
            if ( IsMapFlagSet(MAP_RANDOM_RACES) == false ) then
                call AlteredMeleeShowAIRaceDialog()
            endif
        endif
    endif
endfunction

function Trig_AlteredMeleeInitRaceChoice_Actions takes nothing returns nothing
    // Below sets random race for players if (Use Random Race) is selected in lobby. Shows race choice dialog if not set.
    local integer playerIndex = 1
    local player  whichplayer
    loop
        exitwhen playerIndex > 12
        set whichplayer = ConvertedPlayer(playerIndex)
        if ( GetPlayerSlotState(whichplayer) == PLAYER_SLOT_STATE_PLAYING ) then
            if (IsPlayerObserver(whichplayer)) then
                set udg_AM_RaceChosen[playerIndex] = -1
            else
                if ( IsMapFlagSet(MAP_RANDOM_RACES) == true ) then
                    if ( GetPlayerController(whichplayer) == MAP_CONTROL_USER ) then
                        set udg_AM_RaceChosen[playerIndex] = GetRandomInt(1, udg_AM_NumOfRaceChoices)
                    else
                        set udg_AM_RaceChosen[playerIndex] = udg_AM_AI_ButtonToRace[GetRandomInt(1, udg_AM_NumofRacesWithAI)]
                    endif
                else
                    if ( GetPlayerController(whichplayer) == MAP_CONTROL_USER ) then
                        call DialogDisplay( whichplayer, udg_AM_RaceDialog_PL_1, true )
                    endif
                endif
            endif
        else
            set udg_AM_RaceChosen[playerIndex] = -1
        endif
            
        set playerIndex = playerIndex + 1
    endloop
endfunction

function InitAlteredMelee takes nothing returns nothing
    local trigger gg_trg_AlteredMeleeInitRaceChoice
    local trigger gg_trg_AlteredMeleeDialogClickPlayer
    local trigger gg_trg_AlteredMeleeDialogClickComputer
    local trigger gg_trg_AlteredMeleeCreateStartingUnits
    local integer indexA = 1
    local integer indexB = 1

    loop
        exitwhen indexA > 12
        call SetPlayerMaxHeroesAllowed( 3, ConvertedPlayer(indexA) )
        // Limit them to one of each type of custom hero
        // Custom Heroes
        set indexA = indexA + 1
    endloop

    loop
        exitwhen indexB > udg_AM_NumOfRaceChoices
        if ( udg_AM_UnitType_Hero1[indexB] != null ) then
            call SetPlayerTechMaxAllowedSwap( udg_AM_UnitType_Hero1[indexB], 1, ConvertedPlayer(indexB) )
        endif
        if ( udg_AM_UnitType_Hero2[indexB] != null ) then
            call SetPlayerTechMaxAllowedSwap( udg_AM_UnitType_Hero2[indexB], 1, ConvertedPlayer(indexB) )
        endif
        if ( udg_AM_UnitType_Hero3[indexB] != null ) then
            call SetPlayerTechMaxAllowedSwap( udg_AM_UnitType_Hero3[indexB], 1, ConvertedPlayer(indexB) )
        endif
        if ( udg_AM_UnitType_Hero4[indexB] != null ) then
            call SetPlayerTechMaxAllowedSwap( udg_AM_UnitType_Hero4[indexB], 1, ConvertedPlayer(indexB) )
        endif
        set indexB = indexB + 1
    endloop

    call AlteredMeleeCreatePlayerDialog()
    set gg_trg_AlteredMeleeInitRaceChoice = CreateTrigger()
    call TriggerRegisterTimerEventSingle( gg_trg_AlteredMeleeInitRaceChoice, 1.00 )
    call TriggerAddAction( gg_trg_AlteredMeleeInitRaceChoice, function Trig_AlteredMeleeInitRaceChoice_Actions )
    set gg_trg_AlteredMeleeDialogClickPlayer = CreateTrigger()
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickPlayer, udg_AM_RaceDialog_PL_1 )
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickPlayer, udg_AM_RaceDialog_PL_2 )
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickPlayer, udg_AM_RaceDialog_PL_3 )
    call TriggerAddAction( gg_trg_AlteredMeleeDialogClickPlayer, function Trig_AlteredMeleeDialogClickPlayer_Actions )
    set gg_trg_AlteredMeleeDialogClickComputer = CreateTrigger()
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickComputer, udg_AM_RaceDialog_AI_1 )
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickComputer, udg_AM_RaceDialog_AI_2 )
    call TriggerRegisterDialogEvent( gg_trg_AlteredMeleeDialogClickComputer, udg_AM_RaceDialog_AI_3 )
    call TriggerAddAction( gg_trg_AlteredMeleeDialogClickComputer, function Trig_AlteredMeleeDialogClickComputer_Actions )
    set gg_trg_AlteredMeleeCreateStartingUnits = CreateTrigger()
    call TriggerRegisterTimerEventPeriodic( gg_trg_AlteredMeleeCreateStartingUnits, 1.00 )
    call TriggerAddCondition( gg_trg_AlteredMeleeCreateStartingUnits, Condition( function Trig_AlteredMeleeCreateStartingUnits_Conditions ) )
    call TriggerAddAction( gg_trg_AlteredMeleeCreateStartingUnits, function Trig_AlteredMeleeCreateStartingUnits_Actions )
endfunction
  • 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 - Set starting resources (for all players)
      • Melee Game - Remove creeps and critters from used start locations (for all players)
      • Melee Game - Give trained Heroes a Scroll of Town Portal (for all players)
      • Trigger - Add SetRaceVariables <gen> to the trigger queue (Checking conditions)
  • SetRaceVariables
    • Events
    • Conditions
    • Actions
      • -------- Set the variable below to the total number of races included in the map. --------
      • Set AM_NumOfRaceChoices = 5
      • -------- Race1 Alliance //If the below variable is left blank it will not show up on the dialog boxes and won't be able to be picked. --------
      • Set AM_RaceName[1] = Human
      • -------- Below limits and sets this race's heroes. None of these can be blank or else player may not have a hero when (Random Hero) is set in the lobby. --------
      • Set AM_UnitType_Hero1[1] = Paladin
      • Set AM_UnitType_Hero2[1] = Archmage
      • Set AM_UnitType_Hero3[1] = Mountain King
      • Set AM_UnitType_Hero4[1] = Blood Mage
      • -------- Below sets this races town hall structure. T2 through T9 can be blank if this race has no structures for them. These structures prevent the player from being revealed for having no town hall unit. --------
      • Set AM_UnitType_TownhallT1[1] = Town Hall
      • Set AM_UnitType_TownhallT2[1] = Keep
      • Set AM_UnitType_TownhallT3[1] = Castle
      • Set AM_UnitType_TownhallT4[1] = No unit-type
      • Set AM_UnitType_TownhallT5[1] = No unit-type
      • Set AM_UnitType_TownhallT6[1] = No unit-type
      • Set AM_UnitType_TownhallT7[1] = No unit-type
      • Set AM_UnitType_TownhallT8[1] = No unit-type
      • Set AM_UnitType_TownhallT9[1] = No unit-type
      • -------- Below sets this race's gold-mining structure. This can be left blank if they can harvest gold like humans and orcs. If the race's tier1 townhall is the same as this structure, it will spawn the townhall over the goldmine. --------
      • Set AM_UnitType_Goldmine[1] = No unit-type
      • -------- Below set this race's primary worker unit. If secondary worker is left blank 5 of these will spawn instead of 3. --------
      • Set AM_UnitType_PrimaryWorker[1] = Peasant
      • -------- Below sets this race's secondary worker unit. Spawns 1 unit of this type. Can be left blank. --------
      • Set AM_UnitType_SecondaryWorker[1] = No unit-type
      • -------- Below sets this race's build X or be revealed message. Will be displayed to the player if they have no units of the type set for the Town hall variables. --------
      • Set AM_RevealMessage[1] = You will be revealed unless you build a Town Hall
      • -------- Below set the text shown for this race's reveal countdown timer. --------
      • Set AM_BuildWindow[1] = Build Town Hall
      • -------- Below creates blight around players start location if set to true. --------
      • Set AM_StartsWithBlight[1] = False
      • -------- Below causes townhall to entangle nearby mine if set to true. --------
      • Set AM_HallEntanglesGoldmine[1] = False
      • -------- Below sets the path for this race's AI. It must be the same as it is in the Import Manager. If blank, this race will not be available for computer players. --------
      • Set AM_AI_FilePath[1] = Melee_V0\Scripts\human.ai
      • -------- Race2 Horde --------
      • Set AM_RaceName[2] = Orc
      • Set AM_UnitType_Hero1[2] = Blademaster
      • Set AM_UnitType_Hero2[2] = Far Seer
      • Set AM_UnitType_Hero3[2] = Tauren Chieftain
      • Set AM_UnitType_Hero4[2] = Shadow Hunter
      • Set AM_UnitType_TownhallT1[2] = Great Hall
      • Set AM_UnitType_TownhallT2[2] = Stronghold
      • Set AM_UnitType_TownhallT3[2] = Fortress
      • Set AM_UnitType_Goldmine[2] = No unit-type
      • Set AM_UnitType_PrimaryWorker[2] = Peon
      • Set AM_UnitType_SecondaryWorker[2] = No unit-type
      • Set AM_RevealMessage[2] = You will be revealed unless you build a Great Hall
      • Set AM_BuildWindow[2] = Build Great Hall
      • Set AM_StartsWithBlight[2] = False
      • Set AM_HallEntanglesGoldmine[2] = False
      • Set AM_AI_FilePath[2] = Melee_V0\Scripts\orc.ai
      • -------- Race3 Scourge --------
      • Set AM_RaceName[3] = Undead
      • Set AM_UnitType_Hero1[3] = Death Knight
      • Set AM_UnitType_Hero2[3] = Lich
      • Set AM_UnitType_Hero3[3] = Dreadlord
      • Set AM_UnitType_Hero4[3] = Crypt Lord
      • Set AM_UnitType_TownhallT1[3] = Necropolis
      • Set AM_UnitType_TownhallT2[3] = Halls of the Dead
      • Set AM_UnitType_TownhallT3[3] = Black Citadel
      • Set AM_UnitType_Goldmine[3] = Haunted Gold Mine
      • Set AM_UnitType_PrimaryWorker[3] = Acolyte
      • Set AM_UnitType_SecondaryWorker[3] = Ghoul
      • Set AM_RevealMessage[3] = You will be revealed unless you build a Necropolis
      • Set AM_BuildWindow[3] = Build Necropolis
      • Set AM_StartsWithBlight[3] = True
      • Set AM_HallEntanglesGoldmine[3] = False
      • Set AM_AI_FilePath[3] = Melee_V0\Scripts\undead.ai
      • -------- Race4 Sentinels --------
      • Set AM_RaceName[4] = Night Elf
      • Set AM_UnitType_Hero1[4] = Keeper of the Grove
      • Set AM_UnitType_Hero2[4] = Priestess of the Moon
      • Set AM_UnitType_Hero3[4] = Demon Hunter
      • Set AM_UnitType_Hero4[4] = Warden
      • Set AM_UnitType_TownhallT1[4] = Tree of Life
      • Set AM_UnitType_TownhallT2[4] = Tree of Ages
      • Set AM_UnitType_TownhallT3[4] = Tree of Eternity
      • Set AM_UnitType_Goldmine[4] = Entangled Gold Mine
      • Set AM_UnitType_PrimaryWorker[4] = Wisp
      • Set AM_UnitType_SecondaryWorker[4] = No unit-type
      • Set AM_RevealMessage[4] = You will be revealed unless you build a Tree of Life
      • Set AM_BuildWindow[4] = Build Tree of Life
      • Set AM_StartsWithBlight[4] = False
      • Set AM_HallEntanglesGoldmine[4] = True
      • Set AM_AI_FilePath[4] = Melee_V0\Scripts\elf.ai
      • -------- Race5 Naga --------
      • Set AM_RaceName[5] = Naga
      • Set AM_UnitType_Hero1[5] = Naga Sea Witch
      • Set AM_UnitType_Hero2[5] = Naga Sea Witch
      • Set AM_UnitType_Hero3[5] = Naga Sea Witch
      • Set AM_UnitType_Hero4[5] = Naga Sea Witch
      • Set AM_UnitType_TownhallT1[5] = Temple of Tides
      • Set AM_UnitType_TownhallT2[5] = No unit-type
      • Set AM_UnitType_TownhallT3[5] = No unit-type
      • Set AM_UnitType_Goldmine[5] = No unit-type
      • Set AM_UnitType_PrimaryWorker[5] = Mur'gul Slave
      • Set AM_UnitType_SecondaryWorker[5] = No unit-type
      • Set AM_RevealMessage[5] = You will be revealed unless you build a Temple of the Tides
      • Set AM_BuildWindow[5] = Build Temple of the Tides
      • Set AM_StartsWithBlight[5] = False
      • Set AM_HallEntanglesGoldmine[5] = False
      • Set AM_AI_FilePath[5] = war3mapImported\Naga.ai
      • -------- The If statement below is only there for easy variable transfer --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • 1 Equal to 0
        • Then - Actions
          • Set AM_AI_ButtonToRace[1] = 0
          • Set AM_AI_PlayerNum = 0
          • Set AM_NumofRacesWithAI = 0
          • Set AM_OtherButton[0] = AM_OtherButton[0]
          • Set AM_RaceButton_AI[0] = AM_RaceButton_AI[0]
          • Set AM_RaceButton_PL[0] = AM_RaceButton_PL[0]
          • Set AM_RaceChosen[0] = 0
          • Set AM_RaceDialog_AI_1 = AM_RaceDialog_AI_1
          • Set AM_RaceDialog_AI_2 = AM_RaceDialog_AI_2
          • Set AM_RaceDialog_AI_3 = AM_RaceDialog_AI_3
          • Set AM_RaceDialog_PL_1 = AM_RaceDialog_PL_1
          • Set AM_RaceDialog_PL_2 = AM_RaceDialog_PL_2
          • Set AM_RaceDialog_PL_3 = AM_RaceDialog_PL_3
        • Else - Actions
      • -------- Below automatically sets up the Dialog box for Computer players with Races that have AI --------
      • Custom script: call InitAlteredMelee()
I'm getting tired of finding people using old, broken versions of these triggers. If you won't approve it because its mostly blizzard-coding at least do it for its usefulness in the techtree contests.

Did some more work on

Keywords:
altered, melee, starting, units, victory, defeat, template
Contents

AlteredMeleeExtraRaces 2.5 (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. 10 Aug 2012 Magtheridon96: We have come to the conclusion that this will be approved. First, you have to get rid of /all/ the BJs. It's a huge improvement. For example, call...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.

10 Aug 2012
Magtheridon96:

We have come to the conclusion that this will be approved.
First, you have to get rid of /all/ the BJs.
It's a huge improvement.

For example, call PickMeleeAI(indexPlayer, udg_AM_AI_FilePath[indexRace], null, null)
runs about 10 lines of code, but it could simply be replaced with 1 line:
call StartMeleeAI(indexPlayer, udg_AM_AI_FilePath[indexRace])

Getting rid of the BJs will allow you to produce cleaner and faster code.

The function that gets the nearest gold mine can be replaced with a FirstOfGroup loop enum.

You would call GroupEnumUnitsInRange(enumGroup, x, y, 2000, null)
And loop over all the units like this:

JASS:
loop
    set tempUnit = FirstOfGroup(enumGroup)
    exitwhen tempUnit == null
    call GroupRemoveUnit(enumGroup, tempUnit)

    if GetUnitTypeId(tempUnit) == 'ngol' then
        // do actions here.
        // you would just get the distance and check if it's less
        // than the current distance you stored. If so, set the 
        // nearestMine variable to tempUnit.
    endif
endloop
// At this point, nearestMine will be equal to the nearest 
// mine.

There are so many things you could do to improve this.

12 Nov
Bribe: I don't like that this resource is 99% copied code from Blizzard.j.

To me this would be better as a tutorial, since it's not very configurable in its current state either.

I don't think any amount of work you put into this is going to make me feel good about approving it. I don't get the feeling like this is an appropriate resource for us, and it is a difficult decision for me to decide what to do with it.

edit
8th of August 2012
Magtheridon96:

As Bribe said, I also do not know whether this should be approved or not, but for the time being, it would be better to improve it.
First, you can get rid of the remaining BJs.

edit
Also, merge lines like this:

JASS:
local integer index
set index = 1
->
local integer index = 1
 
Level 4
Joined
May 17, 2010
Messages
30
at first when i saw this i though you just changed the units like instead of peons you got grunts, but once i clicked on it I understood. change the title to something else, you might get more hits. downloading.....
 
Last edited:
Level 2
Joined
Jan 22, 2011
Messages
16
Thanks. I like it. I created a lot of custom races, but i don't know anything about triggers. So, i always had to change the player slot to change the race.

But why only 8 races?

There are Humans, Orcs, Undead, Night Elf, and 4 more races.

That's not enough, at least for me.

I have 16 custom races, and want to make more 4.

One other problem:

The first hero is free, but only the first altar hero has supposed to be free. Not the first Tavern hero.
 
Level 2
Joined
Jan 22, 2011
Messages
16
Custom Races.

"You can have as many races as you can fit in a dialog box. You just need to create a dialog button for each new race and give it a numeric value. Then you need to set that race's variables like the other races have done for them and finally set the NumOfRaces variable to the number of races that you have."

Mephestrial,

You are right. I don't know what i did wrong before, But anyway, i deleted the new custom races triggers, and create them again. Now it works.

I don't know how to make the 13th, 14th, 15th ... races to work.

When i select them in the beginning, nothing happens.

13th option is Random now.



"Also even with pure melee triggers a tavern hero can be free if it is your first hero. "


You are right again! I could swear that the first Tavern hero has not free. But i checked again in Normal Melee Game, and indeed the first Tavern hero is free, if you didn't get any altar hero.

I'm sure that in the past it was not free, but with all the updates we automatically download when we go to Battle.net, this was probably changed and i didn't notice.


I don't know if it's possible to create a "Next >>" option to go to another page with more races to choose.

But, thanks a lot for these triggers. I always dreamed to have a "Custom Race" selection system. Man, i don't know how to thank you.
 
Level 2
Joined
Jan 22, 2011
Messages
16
One small bug.

I found another problem.

Set HallEntanglesGoldmine = True

Don't work.

The Tree of Life always starts too far away from the Gold Mine to entangle it.


Please, let me know when you update the triggers.
 
Level 2
Joined
Jan 22, 2011
Messages
16
It's working.

"I found another problem.

Set HallEntanglesGoldmine = True

Don't work."



Sorry. I forgot to do that:

Set UnitType_Goldmine = Entangled Gold Mine

It's perfect. Too bad there is a 12 races limit.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Lots of memory leaks in the custom script code (MeleeStartingUnitsCustom especially), lot of "ConvertedPlayerId" bj's shows very little thought was applied into the custom scripts.

This needs a lot of work. The GUI side of things sees a lot of problems.

RacesDialogClickDetection - this needs to take advantage of the else-actions.

And - All (Conditions) are true

- This line is not needed. Conditions automatically check if all are true. In fact, that whole statement should just be removed and put as an "else" action, because you do not need to re-check what the value is that way.

CreateAlteredMeleeStartingUnits - horrendous. What is it even doing? There is a lot of bad structure found her, especially concerning the waits.
 
Level 2
Joined
Dec 17, 2007
Messages
10
I having problem when I import the triggers into my map...
call AlteredMeleeStartingUnits()
call AlteredMeleeInitVictoryDefeat()

both of these made my map can not be saved...
What is the problem?
Can anyone help?


Edit..
The map can be saved but have message about the trigger error...
 
Level 4
Joined
Apr 1, 2020
Messages
73
This has been great. I've been away from WC3 modding for 16 years. I always wanted to "fix" the races (remove the blood elves from the alliance for example) and add a few more that were lore correct. This is allowing me and my friends to do just that. Thank you for posting. It has allowed me to revisit this project I abandoned 16 years ago.
 
Top