//===========================================================================
// 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 LivingPlayerHallsFilter takes nothing returns boolean
return (IsUnitAliveBJ(GetFilterUnit()) and IsUnitType(GetFilterUnit(),UNIT_TYPE_TOWNHALL))
endfunction
function CountLivingPlayerTownHalls takes player whichPlayer returns integer
local group g
local integer matchedCount
local boolexpr b=Filter(function LivingPlayerHallsFilter)
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g, whichPlayer, b)
set matchedCount = CountUnitsInGroup(g)
call DestroyGroup(g)
call DestroyBoolExpr(b)
set b=null
set g=null
return matchedCount
endfunction
function Custom_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 + CountLivingPlayerTownHalls(indexPlayer)
// 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)
// set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "custom_h030", true, true)
// set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "custom_h01C", true, true)
// set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "custom_h012", true, true)
// set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "custom_h013", true, true)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h013',indexPlayer)//Never use group functions for this, just count living units for player. Much better idea.
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h014',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h015',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h01C',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h01E',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h01F',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h012',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h02F',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h02J',indexPlayer)
// set keyStructs = keySructs + CountLivingPlayerUnitsOfTypeId('h030',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h000',indexPlayer)//Non-modded human custom ids
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h00D',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('h00E',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('o00C',indexPlayer)//Non-modded orc custom ids
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('o00D',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('o00E',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('e00M',indexPlayer)//Non-modded night elf custom ids
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('e00N',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('e00O',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('u00C',indexPlayer)//Non-modded undead custom ids
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('u00D',indexPlayer)
// set keyStructs = keyStructs + CountLivingPlayerUnitsOfTypeId('u00E',indexPlayer)
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
return keyStructs
endfunction
//===========================================================================
function Custom_MeleePlayerIsCrippled takes player whichPlayer returns boolean
local integer allyStructures = MeleeGetAllyStructureCount(whichPlayer)
local integer allyKeyStructures = Custom_MeleeGetAllyKeyStructureCount(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 Custom_MeleeCheckForCrippledPlayers takes nothing returns nothing
local integer playerIndex
local player indexPlayer
local force crippledPlayers = CreateForce()
local boolean isNowCrippled
local race indexRace
// 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 = Custom_MeleePlayerIsCrippled(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], 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, "|cffffcc00"+udg_RevealWarning+"|r")
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
endfunction
//===========================================================================
// Determine if the lost unit should result in any defeats or victories.
//
function Custom_MeleeCheckLostUnit 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 MeleeCheckForLosersAndVictors()
endif
// Check if the lost unit has crippled or uncrippled the player.
// (A team with 0 units is dead, and thus considered uncrippled.)
call Custom_MeleeCheckForCrippledPlayers()
endfunction
//===========================================================================
// Determine if the gained unit should result in any defeats, victories,
// or cripple-status changes.
//
function Custom_MeleeCheckAddedUnit 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 Custom_MeleeCheckForCrippledPlayers()
endif
endfunction
//===========================================================================
function Custom_MeleeTriggerActionConstructCancel takes nothing returns nothing
call Custom_MeleeCheckLostUnit(GetCancelledStructure())
endfunction
//===========================================================================
function Custom_MeleeTriggerActionUnitDeath takes nothing returns nothing
if (IsUnitType(GetDyingUnit(), UNIT_TYPE_STRUCTURE)) then
call Custom_MeleeCheckLostUnit(GetDyingUnit())
endif
endfunction
//===========================================================================
function Custom_MeleeTriggerActionUnitConstructionStart takes nothing returns nothing
call Custom_MeleeCheckAddedUnit(GetConstructingStructure())
endfunction
//===========================================================================
function Custom_MeleeTriggerActionAllianceChange takes nothing returns nothing
call MeleeCheckForLosersAndVictors()
call Custom_MeleeCheckForCrippledPlayers()
endfunction
//===========================================================================
function MeleeInitVictoryDefeatCustomized 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 Custom_MeleeTriggerActionConstructCancel)
// 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 Custom_MeleeTriggerActionUnitDeath)
// 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 Custom_MeleeTriggerActionUnitConstructionStart)
// Set a trigger to fire whenever this player defeats-out
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig , indexPlayer , EVENT_PLAYER_DEFEAT)
call TriggerAddAction(trig , function MeleeTriggerActionPlayerDefeated)
// Set a trigger to fire whenever this player leaves
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig , indexPlayer , EVENT_PLAYER_LEAVE)
call TriggerAddAction(trig , function MeleeTriggerActionPlayerLeft)
// 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 Custom_MeleeTriggerActionAllianceChange)
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 MeleeTriggerActionPlayerLeft)
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 Custom_MeleeTriggerActionAllianceChange)
endfunction
//===========================================================================
// Starting Units for Orc Players
// - 1 Great Hall, placed at start location
// - 5 Peons, placed between start location and nearest gold mine
//
function MeleeStartingUnitsSammy takes player whichPlayer, location startLoc, boolean doHeroes, boolean doCamera, boolean doPreload returns nothing
local boolean useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
local real unitSpacing = 64.00
local unit nearestMine
local location nearMineLoc
local location heroLoc
local real peonX
local real peonY
if (doPreload) then
call Preloader( "scripts\\OrcMelee.pld" )
endif
set nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
if (nearestMine != null) then
// Spawn Great Hall at the start location.
call CreateUnitAtLoc(whichPlayer, 'h000', startLoc, bj_UNIT_FACING)
// Spawn Peons near the mine.
set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 320, 0)
set peonX = GetLocationX(nearMineLoc)
set peonY = GetLocationY(nearMineLoc)
call CreateUnit(whichPlayer, 'e000', peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX + 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX - 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
// Set random hero spawn point to be off to the side of the start location.
set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), startLoc, 384, 45)
else
// Spawn Great Hall at the start location.
call CreateUnitAtLoc(whichPlayer, 'h000', startLoc, bj_UNIT_FACING)
// Spawn Peons directly south of the town hall.
set peonX = GetLocationX(startLoc)
set peonY = GetLocationY(startLoc) - 224.00
call CreateUnit(whichPlayer, 'e000', peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(whichPlayer, 'e000', peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
// Set random hero spawn point to be just south of the start location.
set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
endif
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, 'E003', 'H006', 'H004', 'H005', heroLoc)
else
call SetPlayerState(whichPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
endif
endif
if (doCamera) then
// Center the camera on the initial Peons.
call SetCameraPositionForPlayer(whichPlayer, peonX, peonY)
call SetCameraQuickPositionForPlayer(whichPlayer, peonX, peonY)
endif
endfunction
//===========================================================================
function MeleeStartingUnitsCustomized takes nothing returns nothing
local integer index
local player indexPlayer
local location indexStartLoc
local race indexRace
local real racialHandicap
call Preloader( "scripts\\SharedMelee.pld" )
set index = 0
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))
set indexRace = GetPlayerRace(indexPlayer)
set racialHandicap = GetPlayerHandicap(indexPlayer)
// Create initial race-specific starting units
if (indexRace == RACE_HUMAN and racialHandicap >= 0.89 and racialHandicap <= 0.91) then
call MeleeStartingUnitsSammy(indexPlayer, indexStartLoc, true, true, true)
call SetPlayerHandicapBJ(indexPlayer,100)
else
if (indexRace == RACE_HUMAN) then
call MeleeStartingUnitsHuman(indexPlayer, indexStartLoc, true, true, true)
elseif (indexRace == RACE_ORC) then
call MeleeStartingUnitsOrc(indexPlayer, indexStartLoc, true, true, true)
elseif (indexRace == RACE_UNDEAD) then
call MeleeStartingUnitsUndead(indexPlayer, indexStartLoc, true, true, true)
elseif (indexRace == RACE_NIGHTELF) then
call MeleeStartingUnitsNightElf(indexPlayer, indexStartLoc, true, true, true)
else
call MeleeStartingUnitsUnknownRace(indexPlayer, indexStartLoc, true, true, true)
endif
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
endfunction
//===========================================================================
function MeleeStartingHeroLimitCustomized takes nothing returns nothing
local integer index
set index = 0
loop
// max heroes per player
call SetPlayerMaxHeroesAllowed(bj_MELEE_HERO_LIMIT, Player(index))
// each player is restricted to a limit per hero type as well
call ReducePlayerTechMaxAllowed(Player(index), 'Hamg', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Hmkg', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Hpal', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Hblm', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Obla', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ofar', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Otch', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Oshd', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Edem', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ekee', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Emoo', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ewar', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Udea', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Udre', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ulic', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ucrl', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Npbm', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nbrn', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nngs', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nplh', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nbst', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nalc', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Ntin', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'Nfir', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'E003', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'H004', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'H005', bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(Player(index), 'H006', bj_MELEE_HERO_TYPE_LIMIT)
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
endfunction
Name | Type | is_array | initial_value |
RevealWarning | string | No | You will be revealed to your opponents unless you build a town-hall type structure. |