Name | Type | is_array | initial_value |
function Trig_Melee_Initialization_Actions takes nothing returns nothing
call MeleeStartingVisibility( )
call WC1MeleeStartingHeroLimit( )
call MeleeGrantHeroItems( )
call WC1MeleeStartingResources( )
call MeleeClearExcessUnits( )
call WC1MeleeStartingUnits( )
call WC1MeleeStartingAI( )
call MeleeInitVictoryDefeat( )
call SetCreepCampFilterState( true )
endfunction
//===========================================================================
function InitTrig_Melee_Initialization takes nothing returns nothing
set gg_trg_Melee_Initialization = CreateTrigger( )
call TriggerAddAction( gg_trg_Melee_Initialization, function Trig_Melee_Initialization_Actions )
endfunction
library WC1Script initializer WC1ScriptInit
globals
// Abilities
private constant integer UNHOLY_ARMOR = 'Alsh'
private constant integer SHADOWSTEP = 'AOss'
private constant integer BACKSTAB = 'A00E'
private constant integer CONVERSION = 'A00F'
private constant integer CHARGE = 'A00J'
private constant integer BLINDINGSMOKE = 'A00I'
// Units
private constant integer POISON_CLOUD = 'ntor'
private constant integer BLINDINGSMOKE_DUMMY = 'h001'
// Heroes
private constant integer CHAMPION = 'Hpal'
private constant integer APPRENTICE = 'Hblm'
private constant integer COMMANDER = 'Hmkg'
private constant integer CHIEFTAIN = 'Otch'
private constant integer SORCERER = 'Ofar'
private constant integer ASSASSIN = 'Obla'
// Triggers
private trigger trgTimerExpires = CreateTrigger()
// Hashtables
private hashtable htb_unholy_armor = InitHashtable()
private hashtable htb_shadowstep = InitHashtable()
private hashtable htb_conversion = InitHashtable()
private hashtable htb_charge = InitHashtable()
endglobals
//===========================================================================
// MELEE INITIALIZATION
//===========================================================================
// Initialize hero limits
function WC1MeleeStartingHeroLimit takes nothing returns nothing
local player indexPlayer
local integer index = 0
loop
set indexPlayer = Player(index)
// max heroes per player
call SetPlayerMaxHeroesAllowed(1, indexPlayer)
// each player is restricted to a limit per hero type as well
call ReducePlayerTechMaxAllowed(indexPlayer, CHAMPION, bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(indexPlayer, APPRENTICE, bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(indexPlayer, COMMANDER, bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(indexPlayer, ASSASSIN, bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(indexPlayer, SORCERER, bj_MELEE_HERO_TYPE_LIMIT)
call ReducePlayerTechMaxAllowed(indexPlayer, CHIEFTAIN, bj_MELEE_HERO_TYPE_LIMIT)
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
set indexPlayer = null
endfunction
// Initialize starting resources
function WC1MeleeStartingResources takes nothing returns nothing
local player indexPlayer
local integer index = 0
// Set each player's starting resources.
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_GOLD, 450)
call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_LUMBER, 135)
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
set indexPlayer = null
endfunction
// Initialize starting units
function WC1MeleeStartingUnits takes nothing returns nothing
local integer index = 0
local integer sheepIndex
local player indexPlayer
local location indexStartLoc
local race indexRace
local string preload
local integer townHall
local integer peon
local real peonX
local real peonY
local integer hero1
local integer hero2
local integer hero3
local boolean unknownRace
local unit nearestMine
local location nearMineLoc
local location heroLoc
local real unitSpacing = 64.00
local boolean useRandomHero = IsMapFlagSet(MAP_RANDOM_HERO)
local unit hero
local integer roll
local integer pick
call Preloader( "scripts\\SharedMelee.pld" )
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set indexStartLoc = GetStartLocationLoc(GetPlayerStartLocation(indexPlayer))
set indexRace = GetPlayerRace(indexPlayer)
set unknownRace = false
// Human
if indexRace == RACE_HUMAN or indexRace == RACE_NIGHTELF then
set preload = "scripts\\HumanMelee.pld"
set townHall = 'htow'
set peon = 'hpea'
set hero1 = CHAMPION
set hero2 = APPRENTICE
set hero3 = COMMANDER
// Orc
elseif indexRace == RACE_ORC or indexRace == RACE_UNDEAD then
set preload = "scripts\\OrcMelee.pld"
set townHall = 'ogre'
set peon = 'opeo'
set hero1 = ASSASSIN
set hero2 = CHIEFTAIN
set hero3 = SORCERER
// Unknown
else
set unknownRace = true
set peonX = GetLocationX(indexStartLoc)
set peonY = GetLocationY(indexStartLoc)
set sheepIndex = 0
loop
call CreateUnit(indexPlayer, 'nshe', peonX + GetRandomReal(-256, 256), peonY + GetRandomReal(-256, 256), GetRandomReal(0, 360))
set sheepIndex = sheepIndex + 1
exitwhen sheepIndex == 12
endloop
call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS )
endif
// Starting Units
if not unknownRace then
call Preloader(preload)
// Create Hall
call CreateUnitAtLoc(indexPlayer, townHall, indexStartLoc, bj_UNIT_FACING)
// Spawn peasants
set nearestMine = MeleeFindNearestMine(indexStartLoc, bj_MELEE_MINE_SEARCH_RADIUS)
if (nearestMine != null) then
set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), indexStartLoc, 320, 0)
// Spawn Peasants near the mine.
set peonX = GetLocationX(nearMineLoc)
set peonY = GetLocationY(nearMineLoc)
call CreateUnit(indexPlayer, peon, peonX + 0.00 * unitSpacing, peonY + 1.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX + 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX - 1.00 * unitSpacing, peonY + 0.15 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX + 0.60 * unitSpacing, peonY - 1.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, 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.
if useRandomHero then
set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine), indexStartLoc, 384, 45)
endif
else
// Spawn Peasants directly south of the town hall.
set peonX = GetLocationX(indexStartLoc)
set peonY = GetLocationY(indexStartLoc) - 224.00
call CreateUnit(indexPlayer, peon, peonX + 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX + 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX + 0.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX - 1.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
call CreateUnit(indexPlayer, peon, peonX - 2.00 * unitSpacing, peonY + 0.00 * unitSpacing, bj_UNIT_FACING)
// Set random hero spawn point to be just south of the start location.
if useRandomHero then
set heroLoc = Location(peonX, peonY - 2.00 * unitSpacing)
endif
endif
// If the "Random Hero" option is set, start the player with a random hero.
// Otherwise, give them a "free hero" token.
if useRandomHero then
set roll = GetRandomInt(1,3)
// Translate the roll into a unitid.
if roll == 1 then
set pick = hero1
elseif roll == 2 then
set pick = hero2
elseif roll == 3 then
set pick = hero3
else
// Unrecognized id index - pick the first hero in the list.
set pick = hero1
endif
// Create the hero.
set hero = CreateUnitAtLoc(indexPlayer, pick, heroLoc, bj_UNIT_FACING)
if bj_meleeGrantHeroItems then
call MeleeGrantItemsToHero(hero)
endif
else
call SetPlayerState(indexPlayer, PLAYER_STATE_RESOURCE_HERO_TOKENS, bj_MELEE_STARTING_HERO_TOKENS)
endif
endif
// Center the camera on the initial Peasants.
call SetCameraPositionForPlayer(indexPlayer, peonX, peonY)
call SetCameraQuickPositionForPlayer(indexPlayer, peonX, peonY)
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
set indexPlayer = null
set indexStartLoc = null
set indexRace = null
set nearestMine = null
set nearMineLoc = null
set heroLoc = null
set hero = null
endfunction
// Replaces all enumerated units with 'egol' mines
private function ReplaceMinesFilter takes nothing returns boolean
local unit mine = GetFilterUnit()
local real x = GetUnitX(mine)
local real y = GetUnitY(mine)
local integer gold = GetResourceAmount(mine)
call RemoveUnit(mine)
set mine = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'egol', -999999999, -999999999, bj_UNIT_FACING)
call SetResourceAmount(mine, gold)
call ShowUnit(mine, false)
call SetUnitX(mine, x)
call SetUnitY(mine, y)
call ShowUnit(mine, true)
set mine = null
return false
endfunction
// Initialize AI
function WC1MeleeStartingAI takes nothing returns nothing
local integer index = 0
local boolean haveNE_AI = false
local player indexPlayer = null
local race indexRace = null
local group mines = null
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set indexRace = GetPlayerRace(indexPlayer)
if GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER then
if indexRace == RACE_HUMAN or indexRace == RACE_ORC or indexRace == RACE_UNDEAD or indexRace == RACE_NIGHTELF then
set haveNE_AI = haveNE_AI or indexRace == RACE_NIGHTELF
call StartMeleeAI(indexPlayer, "scripts\\wc1.ai")
endif
call ShareEverythingWithTeamAI(indexPlayer)
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
// Replace 'ngol' goldmines with 'egol' goldmines if we have NE AI players
if haveNE_AI then
set mines = CreateGroup()
call GroupEnumUnitsOfType(mines, UnitId2String('ngol'), function ReplaceMinesFilter)
call DestroyGroup(mines)
endif
set indexPlayer = null
set indexRace = null
set mines = null
endfunction
//===========================================================================
// BLINDING SMOKE FUNCTIONS
//===========================================================================
private function BlindingSmokeFilter takes nothing returns boolean
local unit filterUnit = GetFilterUnit()
local boolean valid = true
set valid = valid and GetUnitState(filterUnit, UNIT_STATE_LIFE) > 0
set valid = valid and not IsUnitType(filterUnit, UNIT_TYPE_FLYING)
set valid = valid and not IsUnitType(filterUnit, UNIT_TYPE_STRUCTURE)
set valid = valid and not IsUnitType(filterUnit, UNIT_TYPE_MECHANICAL)
set valid = valid and not IsUnitType(filterUnit, UNIT_TYPE_MAGIC_IMMUNE)
set valid = valid and not BlzIsUnitInvulnerable(filterUnit)
set valid = valid and not IsPlayerAlly(GetOwningPlayer(filterUnit), GetOwningPlayer(GetSpellAbilityUnit()))
set filterUnit = null
return valid
endfunction
private function BlindingSmokeEnum takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
local real targetX = GetSpellTargetX()
local real targetY = GetSpellTargetY()
local unit dummyUnit = CreateUnit(GetOwningPlayer(GetSpellAbilityUnit()), BLINDINGSMOKE_DUMMY, targetX, targetY, bj_RADTODEG*Atan2(GetUnitY(enumUnit)-targetY, GetUnitX(enumUnit)-targetX))
call RemoveGuardPosition(dummyUnit)
call ShowUnit(dummyUnit, false)
call IssueTargetOrder(dummyUnit, "curse", enumUnit)
call UnitApplyTimedLife(dummyUnit, 'BTLF', 10)
set enumUnit = null
set dummyUnit = null
endfunction
//===========================================================================
// ABILITY TRIGGERS
//===========================================================================
private function TimerExpires takes nothing returns boolean
local timer tmr = GetExpiredTimer()
local integer id = GetHandleId(tmr)
local unit caster
// Unholy Armor: cancel unvulnerability
if HaveSavedHandle(htb_unholy_armor, id, 0) then
call SetUnitInvulnerable(LoadUnitHandle(htb_unholy_armor, id, 0), false)
call FlushChildHashtable(htb_unholy_armor, id)
// Shadowstep: reset move speed
elseif HaveSavedHandle(htb_shadowstep, id, 0) then
set caster = LoadUnitHandle(htb_shadowstep, id, 0)
call SetUnitMoveSpeed(caster, GetUnitDefaultMoveSpeed(caster))
call FlushChildHashtable(htb_shadowstep, id)
// Conversion: reset target owner
elseif HaveSavedHandle(htb_conversion, id, 0) and HaveSavedHandle(htb_conversion, id, 1) then
call SetUnitOwner(LoadUnitHandle(htb_conversion, id, 0), LoadPlayerHandle(htb_conversion, id, 1), true)
call FlushChildHashtable(htb_conversion, id)
endif
call DestroyTimer(tmr)
set tmr = null
set caster = null
return false
endfunction
private function SpellIsCast takes nothing returns boolean
local unit target
local unit caster
local group targetGroup = null
local timer tmr = null
local integer tmr_id
local integer spellId = GetSpellAbilityId()
local real hyp
local real deg
local real rad
local real speed
local real dur
local real facing
// Unholy Armor: make invulnerable and take half HP
if spellId == UNHOLY_ARMOR then
set target = GetSpellTargetUnit()
set caster = GetSpellAbilityUnit()
call SetUnitInvulnerable(target, true)
call SetUnitState(target, UNIT_STATE_LIFE, GetUnitState(target, UNIT_STATE_LIFE) / 2)
set tmr = CreateTimer()
call SaveUnitHandle(htb_unholy_armor, GetHandleId(tmr), 0, target)
if IsUnitType(caster, UNIT_TYPE_HERO) then
set dur = BlzGetAbilityRealLevelField(BlzGetUnitAbility(caster, UNHOLY_ARMOR), ABILITY_RLF_DURATION_HERO, 0)
else
set dur = BlzGetAbilityRealLevelField(BlzGetUnitAbility(caster, UNHOLY_ARMOR), ABILITY_RLF_DURATION_NORMAL, 0)
endif
// Shadowstep: move behind target and increase move speed
elseif spellId == SHADOWSTEP then
set target = GetSpellTargetUnit()
set caster = GetSpellAbilityUnit()
set hyp = BlzGetUnitCollisionSize(target)/2 + BlzGetUnitCollisionSize(caster)/2 + 20
set deg = GetUnitFacing(target)
set rad = deg*bj_DEGTORAD
call SetUnitPosition(caster, GetUnitX(target) - Cos(rad)*hyp, GetUnitY(target) - Sin(rad)*hyp)
call SetUnitFacing(caster, deg)
set speed = GetUnitDefaultMoveSpeed(caster)*1.7
if speed > GetUnitMoveSpeed(caster) then // make sure speed is actually increased
set tmr = CreateTimer()
set dur = 2
call SaveUnitHandle(htb_shadowstep, GetHandleId(tmr), 0, caster)
call SetUnitMoveSpeed(caster, speed)
endif
call IssueTargetOrder(caster, "attack", target)
// Backstab: apply damage depending on position
elseif spellId == BACKSTAB then
set target = GetSpellTargetUnit()
set caster = GetSpellAbilityUnit()
set deg = bj_RADTODEG * Atan2(GetUnitY(target) - GetUnitY(caster), GetUnitX(target) - GetUnitX(caster))
set facing = GetUnitFacing(target)
// Is caster behind target?
if facing < deg+45 and facing > deg-45 then
call UnitDamageTarget(caster, target, 720, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_HEAVY_SLICE)
else
call UnitDamageTarget(caster, target, 600, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_HEAVY_SLICE)
endif
// Conversion: change target unit owner
elseif spellId == CONVERSION then
set target = GetSpellTargetUnit()
set caster = GetSpellAbilityUnit()
set tmr = CreateTimer()
set tmr_id = GetHandleId(tmr)
set dur = 5
call SaveUnitHandle(htb_conversion, tmr_id, 0, target)
call SavePlayerHandle(htb_conversion, tmr_id, 1, GetOwningPlayer(target))
call SetUnitOwner(target, GetOwningPlayer(caster), true)
// Charge: remove buffs
elseif spellId == CHARGE then
set caster = GetSpellAbilityUnit()
call UnitRemoveBuffs(caster, false, true)
// Blinding Smoke: create dummy units & cast Curse
elseif spellId == BLINDINGSMOKE then
set targetGroup = CreateGroup()
call GroupEnumUnitsInRange(targetGroup, GetSpellTargetX(), GetSpellTargetY(), 250, function BlindingSmokeFilter)
call ForGroup(targetGroup, function BlindingSmokeEnum)
call DestroyGroup(targetGroup)
endif
// Start the timer
if tmr != null then
call TriggerRegisterTimerExpireEvent(trgTimerExpires, tmr)
call TimerStart(tmr, dur, false, null)
set tmr = null
endif
set target = null
set caster = null
set targetGroup = null
return false
endfunction
// Unit is summoned
private function UnitIsSummoned takes nothing returns boolean
local unit summonedUnit = GetSummonedUnit()
// Poison Cloud: change owner to neutral passive
if GetUnitTypeId(summonedUnit) == POISON_CLOUD then
call SetUnitOwner(summonedUnit, Player(PLAYER_NEUTRAL_PASSIVE), false)
endif
set summonedUnit = null
return false
endfunction
//===========================================================================
// LIBRARY INIT
//===========================================================================
private function WC1ScriptInit takes nothing returns nothing
local trigger trgSpellIsCast = CreateTrigger()
local trigger trgUnitIsSummoned = CreateTrigger()
local player indexPlayer
local integer index = 0
loop
set indexPlayer = Player(index)
call TriggerRegisterPlayerUnitEvent(trgSpellIsCast, indexPlayer, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerRegisterPlayerUnitEvent(trgUnitIsSummoned, indexPlayer, EVENT_PLAYER_UNIT_SUMMON, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
call TriggerAddCondition(trgSpellIsCast, function SpellIsCast)
call TriggerAddCondition(trgUnitIsSummoned, function UnitIsSummoned)
call TriggerAddCondition(trgTimerExpires, function TimerExpires)
set trgSpellIsCast = null
set trgUnitIsSummoned = null
set indexPlayer = null
endfunction
endlibrary