native UnitAlive takes unit u returns boolean
function Msg takes player whatPlayer, string s returns nothing //to player
if GetLocalPlayer()==whatPlayer then
call DisplayTextToPlayer(whatPlayer, 0.00, 0.00, s)
endif
endfunction
function MsgDev takes string s returns nothing //developing message (to all)
if DEV_MODE then
call DisplayTextToPlayer(GetLocalPlayer(), 0.00, 0.00, s)
endif
endfunction
function MsgAll takes string s returns nothing //to player
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 10.00, s)
endfunction
function MsgTipAttackWave takes integer poolNo, string s returns nothing
local integer i=0
loop
exitwhen i>3
if g_printTips[i] then
call DisplayTextToPlayer(Player(i), 0.00, 0.00, s)
call PingMinimapEx(GetUnitX(zergSpawningPool[poolNo]), GetUnitY(zergSpawningPool[poolNo]), 5.00, 255, 0, 0, false)
endif
set i=i+1
endloop
endfunction
function MsgTip takes player pla, string s returns nothing
if g_printTips[GetPlayerId(pla)] then
call Msg(pla, s)
endif
endfunction
function IsMagicImmune takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)
endfunction
function IsGround takes unit u returns boolean
return (not IsUnitType(u, UNIT_TYPE_FLYING))
endfunction
function IsFlying takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_FLYING)
endfunction
function IsUnitInvulnerable takes unit whichUnit returns boolean
//when Blizzard fix this native - remove "not" !
//in 1.30.1 native works fine (it is fixed)
return BlzIsUnitInvulnerable(whichUnit)
//return false // FOR 1.27 only!!!
endfunction
/*
function BlzGetUnitMaxHP takes unit u returns integer
return 1 // FOR 1.27 only!!!
endfunction
function BlzSetUnitMaxHP takes unit u, integer amount returns nothing
// FOR 1.27 only!!!
endfunction
function BlzGetUnitMaxMana takes unit u returns integer
return 0 // FOR 1.27 only!!!
endfunction
function BlzSetUnitMaxMana takes unit u, integer amount returns nothing
// FOR 1.27 only!!!
endfunction
function BlzGetUnitAbilityCooldownRemaining takes unit u, integer spellId returns real
return 1.00 // FOR 1.27 only!!!
endfunction
function BlzGetAbilityManaCost takes integer spellId, integer level returns integer
return 0 // FOR 1.27 only!!!
endfunction
*/
//------------------------- sound functions ------------------------------------------------------------
function Play3DSound takes sound soundHandle, real x, real y returns nothing
call SetSoundPosition(soundHandle, x, y, 50.00)
call SetSoundVolume(soundHandle, 127)
set bj_lastPlayedSound = soundHandle
if (soundHandle != null) then
call StartSound(soundHandle)
endif
endfunction
function Play3DSoundOnUnit takes sound soundHandle, unit u returns nothing
call AttachSoundToUnit(soundHandle, u)
call SetSoundVolume(soundHandle, 127)
set bj_lastPlayedSound = soundHandle
if (soundHandle != null) then
call StartSound(soundHandle)
endif
endfunction
function PlaySoundForPlayer takes sound s, player p returns nothing
set bj_lastPlayedSound = s
if s != null and GetLocalPlayer() == p then
call StartSound(s)
endif
endfunction
function GetUnitPercentLife takes unit u returns real
if not UnitAlive(u) then
return 0.00
endif
return (GetWidgetLife(u) / BlzGetUnitMaxHP(u))
endfunction
function GetUnitMissingLife takes unit u returns real
return I2R(BlzGetUnitMaxHP(u)) - GetWidgetLife(u)
endfunction
//---------------------------------------------------------------------------------
// ----------------------------------------------------------------
// text size=10, visible for owner of unit
//use visibleForPlayer = null to make text visible for all
// ----------------------------------------------------------------
function CreateTextOnUnit takes unit u, string s, integer c, player visibleForPlayer returns nothing
set bj_lastCreatedTextTag = CreateTextTag()
call SetTextTagText(bj_lastCreatedTextTag, s, 0.023) //size 10
call SetTextTagPosUnit(bj_lastCreatedTextTag, u, 0.00) // 2
if c==RED then
call SetTextTagColor(bj_lastCreatedTextTag, 255, 10, 10, 255) // red green blue
elseif c==GREEN then
call SetTextTagColor(bj_lastCreatedTextTag, 10, 255, 10, 255) // red green blue
elseif c==BLUE then
call SetTextTagColor(bj_lastCreatedTextTag, 10, 10, 255, 255) // red green blue
elseif c==YELLOW then
call SetTextTagColor(bj_lastCreatedTextTag, 255, 255, 10, 255) // red green blue
else //white
call SetTextTagColor(bj_lastCreatedTextTag, 255, 255, 255, 255) // red green blue
endif
//for speed 64, for angle 90:
call SetTextTagVelocity(bj_lastCreatedTextTag, 0.00, 0.0355)
call SetTextTagPermanent(bj_lastCreatedTextTag, false)
call SetTextTagLifespan(bj_lastCreatedTextTag, 4.00)
call SetTextTagFadepoint(bj_lastCreatedTextTag, 2.00)
if visibleForPlayer != null then
call SetTextTagVisibility(bj_lastCreatedTextTag, (GetLocalPlayer() == visibleForPlayer))
endif
endfunction
//---------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
function SetTwoPlayersEnemy takes player p1, player p2 returns nothing
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_REQUEST, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_RESPONSE, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_XP, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_SPELLS, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
// ------------- 2 sided ---------------
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_REQUEST, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_RESPONSE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_XP, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_SPELLS, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
endfunction
//-----------------------------------------------------------------------------
function SetTwoPlayersAlly takes player p1, player p2 returns nothing
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_REQUEST, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_RESPONSE, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_XP, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_SPELLS, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
// ----- must be 2-sided-------
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_REQUEST, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_RESPONSE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_XP, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_SPELLS, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
endfunction
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
function ModuloIntegerEx takes integer counter, integer divisor returns integer
return (counter - ((counter / divisor) * divisor))
endfunction
//--------------------------------------------------------------------------------------------------------------
//converts to 5-digit string with "+" or "-" at the begining
function ConvertIntToString takes integer i returns string
local boolean positive=(i>=0)
local string zeros=""
local string value
local integer add
if not positive then // "i" is always >0
set i=-i
endif
set value=I2S(i)
set add=5 - StringLength(value) // 1..5
//add "0" :
loop
exitwhen add==0
set zeros=zeros+"0"
set add=add-1
endloop
//set sign
if positive then
set value="+"+zeros+value
else
set value="-"+zeros+value
endif
// 30000 is max x/y for 480x480 map
return value
endfunction
// GetStringX GetStringY works with "ConvertIntToString"
function GetStringX takes string s returns integer//1..6
local string sign=SubStringBJ(s, 1, 1)
local integer value=S2I(SubStringBJ(s, 2, 6))
if sign=="-" then
set value=-value
endif
return value
endfunction
function GetStringY takes string s returns integer//7..12
local string sign=SubStringBJ(s, 7, 7)
local integer value=S2I(SubStringBJ(s, 8, 12))
if sign=="-" then
set value=-value
endif
return value
endfunction
//--------------------------------------------------------------------------------------------------------------
/*****************************************************************************
* by Bannar
* ExtensionMethods
*
* General purpose functions that extend native jass interface.
*
******************************************************************************
*
* Item handle extension methods:
*
* function GetUnitItemCount takes unit whichUnit returns integer
* Returns the number of items equipped.
*
* function IsUnitInventoryFull takes unit whichUnit returns boolean
* Checks if unit inventory is full.
*
* function GetUnitItemSlot takes unit whichUnit, item whichItem returns integer
* Retrieves slot number of specified item equiped by unit whichUnit or -1 if not found.
*
* function IsItemAlive takes item whichItem returns boolean
* Returns value indicating whether specified item is alive.
*
* function IsItemPickupable takes item whichItem returns boolean
* Returns value indicating whether specified item can be picked up.
*
*****************************************************************************/
function GetUnitItemCount takes unit whichUnit returns integer
local integer size = UnitInventorySize(whichUnit)
local integer slot = 0
local integer result = 0
loop
exitwhen slot >= size
if UnitItemInSlot(whichUnit, slot) != null then
set result = result + 1
endif
set slot = slot + 1
endloop
return result
endfunction
function IsUnitInventoryFull takes unit whichUnit returns boolean
return GetUnitItemCount(whichUnit) == UnitInventorySize(whichUnit)
endfunction
function GetUnitItemSlot takes unit whichUnit, item whichItem returns integer
local integer slot = 0
local integer size
if UnitHasItem(whichUnit, whichItem) then
set size = UnitInventorySize(whichUnit)
loop
if UnitItemInSlot(whichUnit, slot) == whichItem then
return slot
endif
set slot = slot + 1
exitwhen slot >= size
endloop
endif
return -1 // NOT_FOUND
endfunction
function IsItemAlive takes item whichItem returns boolean
return GetItemTypeId(whichItem) != 0 and GetWidgetLife(whichItem) > 0.405
endfunction
function IsItemPickupable takes item whichItem returns boolean
return IsItemAlive(whichItem) and not IsItemOwned(whichItem) and IsItemVisible(whichItem)
endfunction
/*
* END ExtensionMethods by Bannar
*/
Name | Type | is_array | initial_value |
CargoEvent | real | No | |
CargoTransportGroup | group | Yes | |
CargoTransportUnit | unit | Yes | |
CheckDeathInList | boolean | Yes | |
CheckDeathList | integer | Yes | |
CheckDeathTimer | timer | No | |
DeathEvent | real | No | |
DetectRemoveAbility | abilcode | No | |
DetectTransformAbility | abilcode | No | |
dialogTEST | dialog | No | |
GameModeDialog | button | No | |
GDD__Integers | integer | Yes | |
GDD__LeftMapGroup | group | No | |
GDD__TriggerArray | trigger | Yes | |
GDD__UnitArray | unit | Yes | |
GDD_Damage | real | No | |
GDD_DamagedUnit | unit | No | |
GDD_DamageSource | unit | No | |
GDD_Event | real | No | |
IsUnitAlive | boolean | Yes | |
IsUnitBeingUnloaded | boolean | Yes | |
IsUnitNew | boolean | Yes | |
IsUnitPreplaced | boolean | Yes | |
IsUnitReincarnating | boolean | Yes | |
IsUnitRemoved | boolean | Yes | |
IsUnitTransforming | boolean | Yes | |
KillerOfUnit | unit | Yes | |
MBStats | multiboard | No | |
PRM_Change | integer | No | |
PRM_EVENT | real | No | |
PRM_FireEvent | boolean | No | |
PRM_GoldLevel | integer | Yes | |
PRM_LumberLevel | integer | Yes | |
PRM_MonitorPlayer | boolean | Yes | |
PRM_Player | player | No | |
PtV_Farmer | unit | No | |
PtV_FarmerReturnX | integer | No | |
PtV_FarmerReturnY | integer | No | |
PtV_Fisherman | unit | No | |
PtV_FishermanCarrier | unit | No | |
PtV_FishermanReturnX | integer | No | |
PtV_FishermanReturnY | integer | No | |
PtV_Miner | unit | No | |
PtV_MinerReturnX | integer | No | |
PtV_MinerReturnY | integer | No | |
PtVtempUnit | unit | No | |
SummonerOfUnit | unit | Yes | |
UDex | integer | No | |
UDexLastRecycled | integer | No | |
UDexMax | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexUnits | unit | Yes | |
UMovNext | integer | Yes | |
UMovPrev | integer | Yes | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitMovementInterval | real | No | |
UnitMoving | boolean | Yes | |
UnitMovingEvent | real | No | |
UnitMovingX | real | Yes | |
UnitMovingY | real | Yes | |
UnitTypeEvent | real | No | |
UnitTypeOf | unitcode | Yes | |
WorldMaxX | real | No | |
WorldMaxY | real | No |
Unit Event for GUI gives you access to all kinds of events which normal GUI events can't do.
Now fully integrating Unit Indexer, I've listed all substantial events and variables.
In each event, the custom value of the "triggering unit" is equal to UDex and the way to get the unit
with that custom value is via UDexUnits[(Custom value of Unit) --- In this case "UDex"].
Detect the instant when a unit starts reincarnating
Event: Game - DeathEvent Becomes Equal to 0.50
Detect when a unit is brought back to life via Reincarnation, Resurrect or Reanimate
Event: Game - DeathEvent Becomes Equal to 2.00
You can differentiate between the three of these as well.
If it is summoned, that means it was reanimated.
If IsUnitReincarnating[UDex] is true, that means it finished reincarnating. Otherwise, it was simply resurrected.
Detect when a unit is loaded into a transport
Event: Game - CargoEvent Becomes Equal to 1.00
Unit: CargoTransportUnit[UDex] --- The unit who loaded this unit
Detect when a unit is unloaded from a transport
Event: Game - CargoEvent Becomes Equal to 2.00
Unit: CargoTransportUnit[UDex] --- The unit who unloaded this unit
Detect when a unit transforms into a new unit type
Event: Game - UnitTypeEvent Becomes Equal to 1.00
Unit Type: UnitTypeOf[UDex] --- The previous unit type
Detect the instant before a unit is completely removed from the game
Event: Game - UnitIndexEvent Becomes Equal to 2.00
To detect when any unit is created (including pre-placed units)
Event: Game - UnitIndexEvent Becomes Equal to 1.00
To detect when a new unit is summoned (fires after the Create event)
Event: Game - UnitIndexEvent Becomes Equal to 0.50
Unit: SummonerOfUnit[UDex]
To detect when any unit dies (including units created dead)
Event: Game - DeathEvent Becomes Equal to 1.00
Unit: KillerOfUnit[UDex]
Unit Event also gives you access to some other useful variables, such as:
Boolean: IsUnitAlive[(Custom value of Unit)] - never bugs (checking life is not always accurate)
Unit Group: CargoTransportGroup[(Custom value of Transporter)] -
A unit group which holds all of the cargo of a transporting unit.
//===========================================================================
function UnitEventDestroyGroup takes integer i returns nothing
if udg_CargoTransportGroup[i] != null then
call DestroyGroup(udg_CargoTransportGroup[i])
set udg_CargoTransportGroup[i] = null
endif
endfunction
function UnitEventCheckAfter takes nothing returns nothing
local integer i = 0
loop
set i = udg_CheckDeathList[i]
exitwhen i == 0
if udg_IsUnitNew[i] then
//The unit was just created.
set udg_IsUnitNew[i] = false
elseif udg_IsUnitTransforming[i] then
//Added 21 July 2017 to fix the issue re-adding this ability in the same instant
set udg_UDex = i
set udg_UnitTypeEvent = 0.00
set udg_UnitTypeEvent = 1.00
set udg_UnitTypeOf[i] = GetUnitTypeId(udg_UDexUnits[i]) //Set this afterward to give the user extra reference
set udg_IsUnitTransforming[i] = false
call UnitAddAbility(udg_UDexUnits[i], udg_DetectTransformAbility)
elseif udg_IsUnitAlive[i] then
//The unit has started reincarnating.
set udg_IsUnitReincarnating[i] = true
set udg_IsUnitAlive[i] = false
set udg_UDex = i
set udg_DeathEvent = 0.50
set udg_DeathEvent = 0.00
endif
set udg_CheckDeathInList[i] = false
endloop
//Empty the list
set udg_CheckDeathList[0] = 0
endfunction
function UnitEventCheckAfterProxy takes integer i returns nothing
if udg_CheckDeathList[0] == 0 then
call TimerStart(udg_CheckDeathTimer, 0.00, false, function UnitEventCheckAfter)
endif
if not udg_CheckDeathInList[i] then
set udg_CheckDeathList[i] = udg_CheckDeathList[0]
set udg_CheckDeathList[0] = i
set udg_CheckDeathInList[i] = true
endif
endfunction
function UnitEventOnUnload takes nothing returns nothing
local integer i = udg_UDex
call GroupRemoveUnit(udg_CargoTransportGroup[GetUnitUserData(udg_CargoTransportUnit[i])], udg_UDexUnits[i])
set udg_IsUnitBeingUnloaded[i] = true
set udg_CargoEvent = 0.00
set udg_CargoEvent = 2.00
set udg_CargoEvent = 0.00
set udg_IsUnitBeingUnloaded[i] = false
if not IsUnitLoaded(udg_UDexUnits[i]) or IsUnitType(udg_CargoTransportUnit[i], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_CargoTransportUnit[i]) == 0 then
set udg_CargoTransportUnit[i] = null
endif
endfunction
function UnitEventOnDeath takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_UDex != 0 then
set udg_KillerOfUnit[udg_UDex] = GetKillingUnit() //Added 29 May 2017 for GIMLI_2
set udg_IsUnitAlive[udg_UDex] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
set udg_KillerOfUnit[udg_UDex] = null
if udg_CargoTransportUnit[udg_UDex] != null then
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnOrder takes nothing returns boolean
local integer pdex = udg_UDex
local unit u = GetFilterUnit()
local integer i = GetUnitUserData(u)
if i > 0 then
set udg_UDex = i
if GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
if not udg_IsUnitRemoved[i] then
set udg_IsUnitRemoved[i] = true
set udg_IsUnitAlive[i] = false
set udg_SummonerOfUnit[i] = null
//For backwards-compatibility:
set udg_DeathEvent = 0.00
set udg_DeathEvent = 3.00
set udg_DeathEvent = 0.00
//Fire deindex event for UDex:
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 2.00
set udg_UnitIndexEvent = 0.00
set udg_UDexNext[udg_UDexPrev[i]] = udg_UDexNext[i]
set udg_UDexPrev[udg_UDexNext[i]] = udg_UDexPrev[i]
// Recycle the index for later use
set udg_UDexUnits[i] = null
set udg_UDexPrev[i] = udg_UDexLastRecycled
set udg_UDexLastRecycled = i
call UnitEventDestroyGroup(i)
endif
elseif not udg_IsUnitAlive[i] then
if not IsUnitType(u, UNIT_TYPE_DEAD) then
set udg_IsUnitAlive[i] = true
set udg_DeathEvent = 0.00
set udg_DeathEvent = 2.00
set udg_DeathEvent = 0.00
set udg_IsUnitReincarnating[i] = false
endif
elseif IsUnitType(u, UNIT_TYPE_DEAD) then
if udg_IsUnitNew[i] then
//This unit was created as a corpse.
set udg_IsUnitAlive[i] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
elseif udg_CargoTransportUnit[i] == null or not IsUnitType(u, UNIT_TYPE_HERO) then
//The unit may have just started reincarnating.
call UnitEventCheckAfterProxy(i)
endif
elseif GetUnitAbilityLevel(u, udg_DetectTransformAbility) == 0 and not udg_IsUnitTransforming[i] then
set udg_IsUnitTransforming[i] = true
call UnitEventCheckAfterProxy(i) //This block has been updated on 21 July 2017
endif
if udg_CargoTransportUnit[i] != null and not udg_IsUnitBeingUnloaded[i] and not IsUnitLoaded(u) or IsUnitType(u, UNIT_TYPE_DEAD) then
call UnitEventOnUnload()
endif
set udg_UDex = pdex
endif
set u = null
return false
endfunction
function UnitEventOnSummon takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_IsUnitNew[udg_UDex] then
set udg_SummonerOfUnit[udg_UDex] = GetSummoningUnit()
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 0.50
set udg_UnitIndexEvent = 0.00
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnLoad takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = GetUnitUserData(GetTriggerUnit())
local integer index
if i != 0 then
set udg_UDex = i
if udg_CargoTransportUnit[i] != null then
call UnitEventOnUnload()
endif
//Loaded corpses do not issue an order when unloaded, therefore must
//use the enter-region event method taken from Jesus4Lyf's Transport.
if not udg_IsUnitAlive[i] then
call SetUnitX(udg_UDexUnits[i], udg_WorldMaxX)
call SetUnitY(udg_UDexUnits[i], udg_WorldMaxY)
endif
set udg_CargoTransportUnit[i] = GetTransportUnit()
set index = GetUnitUserData(udg_CargoTransportUnit[i])
if udg_CargoTransportGroup[index] == null then
set udg_CargoTransportGroup[index] = CreateGroup()
endif
call GroupAddUnit(udg_CargoTransportGroup[index], udg_UDexUnits[i])
set udg_CargoEvent = 0.00
set udg_CargoEvent = 1.00
set udg_CargoEvent = 0.00
set udg_UDex = pdex
endif
return false
endfunction
function UnitEventEnter takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = udg_UDexLastRecycled
local unit u = GetFilterUnit()
if udg_UnitIndexerEnabled and GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
//Generate a unique integer index for this unit
if i == 0 then
set i = udg_UDexMax + 1
set udg_UDexMax = i
else
set udg_UDexLastRecycled = udg_UDexPrev[i]
endif
//Link index to unit, unit to index
set udg_UDexUnits[i] = u
call SetUnitUserData(u, i)
//For backwards-compatibility, add the unit to a linked list
set udg_UDexNext[i] = udg_UDexNext[0]
set udg_UDexPrev[udg_UDexNext[0]] = i
set udg_UDexNext[0] = i
set udg_UDexPrev[i] = 0
set udg_CheckDeathInList[i] = false
call UnitAddAbility(u, udg_DetectRemoveAbility)
call UnitMakeAbilityPermanent(u, true, udg_DetectRemoveAbility)
call UnitAddAbility(u, udg_DetectTransformAbility)
set udg_UnitTypeOf[i] = GetUnitTypeId(u)
set udg_IsUnitNew[i] = true
set udg_IsUnitAlive[i] = true
set udg_IsUnitRemoved[i] = false
set udg_IsUnitReincarnating[i] = false
set udg_IsUnitPreplaced[i] = udg_IsUnitPreplaced[0] //Added 29 May 2017 for Spellbound
call UnitEventCheckAfterProxy(i)
//Fire index event for UDex
set udg_UDex = i
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 1.00
set udg_UnitIndexEvent = 0.00
else
set udg_UDex = GetUnitUserData(u)
if udg_CargoTransportUnit[udg_UDex] != null and not IsUnitLoaded(u) then
//The unit was dead, but has re-entered the map.
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
set u = null
return false
endfunction
//===========================================================================
function UnitEventInit takes nothing returns nothing
local integer i = bj_MAX_PLAYER_SLOTS //update to make it work with 1.29
local player p
local trigger t = CreateTrigger()
local trigger load = CreateTrigger()
local trigger death = CreateTrigger()
local trigger summon = CreateTrigger()
local rect r = GetWorldBounds()
local region re = CreateRegion()
local boolexpr enterB = Filter(function UnitEventEnter)
local boolexpr orderB = Filter(function UnitEventOnOrder)
set udg_WorldMaxX = GetRectMaxX(r)
set udg_WorldMaxY = GetRectMaxY(r)
call RegionAddRect(re, r)
call RemoveRect(r)
call UnitEventDestroyGroup(0)
call UnitEventDestroyGroup(1)
set udg_CheckDeathList[0] = 0
set udg_UnitIndexerEnabled = true
call TriggerRegisterEnterRegion(CreateTrigger(), re, enterB)
call TriggerAddCondition(load, Filter(function UnitEventOnLoad))
call TriggerAddCondition(death, Filter(function UnitEventOnDeath))
call TriggerAddCondition(summon, Filter(function UnitEventOnSummon))
loop
set i = i - 1
set p = Player(i)
call SetPlayerAbilityAvailable(p, udg_DetectRemoveAbility, false)
call SetPlayerAbilityAvailable(p, udg_DetectTransformAbility, false)
call TriggerRegisterPlayerUnitEvent(summon, p, EVENT_PLAYER_UNIT_SUMMON, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, orderB)
call TriggerRegisterPlayerUnitEvent(death, p, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(load, p, EVENT_PLAYER_UNIT_LOADED, null)
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, enterB)
exitwhen i == 0
endloop
set summon = null
set death = null
set load = null
set re = null
set enterB = null
set orderB = null
set p = null
set r = null
set t = null
endfunction
function InitTrig_Unit_Event takes nothing returns nothing
endfunction
// check BlzIsUnitInvulnerable here depending on game version 1.29 or 1.30.1 and above
library FilteringSystem /* v3.4.0 */
/*
************************************************************************************************************************
* Filtering System's API v3.4.0
* by The Wrecker
*
* Credits:
* - God : God supports anyone.
* - Nestharus : Algorithm of this system is
* shaped in time by ideas of him, and as you
* see, the algorithm is perfect; many other
* thanks to him for many other useful hints.
* THIS SYSTEM OWES ITS QUALITY TO Nestharus.
* - Magtheridon96 : His hints made the way
* to create this system easier and more
* efficient, many thanks to him. His
* advocacy for this system was awesome:
* [url]https://www.hiveworkshop.com/posts/2471786/[/url]
*
* by TheWrecker
*
* [url]http://www.hiveworkshop.com/forums/jass-resources-412/filtering-system-240887/[/url]
*
* Contents:
*
* - Functions
* - How to use Filters
* - How to use Filtering System
* - Settings
* - Full Example
* - Side Functions
* - Constants (filters)
*
************************************************************************************************************************
* Functions:
*
* - function UnitFilter takes unit whichUnit, player whichPlayer, integer filter returns boolean
*
* + It will check if 'whichUnit' meets given conditions or not.
* + 'whichPlayer' is only required when Alliance and Visibility filters
* are applied and must be passed 'null' when not using Alliance and
* Visibility filters.
* + 'filter' is an integer explained in section "How to use Filters".
*
* - function ItemFilter takes item whichItem, integer filter returns boolean
*
* + It checks if 'whichItem' passes given filters or not.
* + 'filter' is an integer explained in section "How to use Filters".
*
* - function PlayerFilter takes player whichPlayer, player otherPlayer, integer filter returns boolean
*
* + It checks whether 'whichPlayer' meets given filters or not.
* + 'otherPlayer' is the other player used to check two-player related
* filters: Shared Units, Shared Vision, Alliance.
* if not using the above filters, you can pass 'null' as 'otherPlayer'.
* + 'filter' is an integer explained in section "How to use Filters".
*
************************************************************************************************************************
* How to use Filters:
*
* - 'filter' is an hexadecimal integer which is made like this:
* Filter1 + Filter2 + Filter3 + ...
* + You don't have to do any mathematics, only type your
* desired filters' names like above.
*
* - Filters in Filtring System are in 3 groups: Unit, Item, Player.
* + Use each group only with its related filtering function.
*
* - Filter rules are as below:
* <Filter1 and Filter2 are opposites like Dead and Alive>
* + Filter1: Units matching it will pass.
* + Filter1 + Filter 2: NO UNIT WILL PASS.
* + nothing: All units will pass.
* + If you didn't get what above means take a look to section
* "Full Example"
*
************************************************************************************************************************
* How to use Filtering System:
*
* - vJass and Jass:
* + A simple line:
* if [Unit/Player/Item]Filter(argument1,argument2[if exists],'filter') then
* //Scripts
* endif
*
* - GUI:
* + A Custom Script (New Action -> General -> Custom Script) line:
* Custom Script : if [Unit/Player/Item]Filter(argument1,argument2[if exists],'filter') then
* //Scripts
* Custom Script : endif
*
************************************************************************************************************************
* Settings:
*
* - Ward and Dummy classificators:
*
* */globals/*
*
* CONFIGURABLE PART
*
* */
constant integer ABILITY_WARD_CLASSIFIER = 'Alit'/*
* This system checks for a spell to realize the fact that a unit is
* a ward or not, because perhaps you add a ward classification to a unit
* to remove its spell icons, but that unit is not really a ward, so instead
* of checking for classification we use a spell to define ward classification;
* change it to your desired spell or leave it as it is.
*
* */
constant integer ABILITY_DUMMY_CLASSIFIER = 'Aloc'/*
* This system checks for a spell to realize the fact that a unit is
* a dummy or not, change this to your desired spell or leave it as it is, note
* that this system doesn't do anything about dummies, in fact when it finds this
* spell in a unit, it completely ignores that unit and that unit will not pass
* the filtering, so if you want a specific unit to not pass this filtering, add
* this spell to it.
*
* END OF CONFIGURABLE PART
*
************************************************************************************************************************
* Full Example:
*
* - Alive, enemy ranged heroes:
* + if UnitFilter(Target,Caster,FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_HERO + FS_UNIT_RANGED) then
* + NOTE : ORDER OF FILTERS IS NOT IMPORTANT.
*
* - Non-Summoned undead units:
* + if UnitFilter(Target,null,FS_UNIT_UNDEAD + FS_UNIT_NON_SUMMONED) then
*
* - All units:
* + if UnitFilter(Target,null,0) then
* + Pay attention to zero (0).
*
* - No unit:
* + if UnitFilter(Target,null,FS_UNIT_ALIVE + FS_UNIT_DEAD) then
* + 'FS_UNIT_HERO + FS_UNIT_NON_HERO','FS_UNIT_ALLY + FS_UNIT_ENEMY' and
* other opposites can be placed as 'FS_UNIT_ALIVE + FS_UNIT_DEAD'.
*
* - Ally computer players with shared vision:
* + if PlayerFilter(Player1,Player2,FS_PLAYER_ALLY + FS_PLAYER_COMPUTER + FS_PLAYER_VISION) then
*
* - Sellable, Campaign class items which are not owned:
* + if ItemFilter(Item,FS_ITEM_SELLABLE + FS_ITEM_CAMPAIGN + FS_ITEM_NON_OWNED) then
*
************************************************************************************************************************
* Side Functions:
*
* Because of the unique algorithm of this system, there are unpredicted functions
* that this system can have, one of them is known and others may be found later.
*
* - Mixing the filters into single filter (Constraints):
* (found by Magtheridon96)
*
* This is the method of mixing some filters and converting them into a
* single filter to use that single filter instead of using many filters
* more and more again. An example should show you the way:
*
* integer USUAL = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_ORGANIC
*
* this way, you will type in 'USUAL' everytime your filter contain these
* three filters instead of typing all three of them.
*
* + Be sure that no filter is repeated two times in a single
* constraint.
* + If sum of some constraints contain repeated filters, be sure
* to substract that filter until there is only one filter of that
* type left, an example is needed:
*
* USUAL = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_ORGANIC
* HERO_2 = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_IMMUNE
* UNDEAD_9 = FS_UNIT_ALIVE + FS_UNIT_UNDEAD
* USUAL_HERO = USUAL + FS_UNIT_HERO
*
* If you want to use USUAL + HERO_2 + UNDEAD_9, be sure to
* use it this way (FS_UNIT_ALIVE is repeated 3 times,
* FS_UNIT_ENEMY is repeated 2 times):
* USUAL + HERO_2 + UNDEAD_9 - 2*FS_UNIT_ALIVE - FS_UNIT_ENEMY
*
* To use this method, you have to define your own constraints using
* this way:
*
* globals
* constant integer CONSTRAINT_NAME = COND1 + COND2 + ...
* endglobals
*
* If you are GUI, you have to put these three lines in three adjacent
* Custom Script lines.
*
************************************************************************************************************************
* Constants (filters):
* - These are the filters available:
*
* FS_UNIT_ENEMY
* FS_UNIT_ALLY
* FS_UNIT_ALIVE
* FS_UNIT_DEAD
* FS_UNIT_ORGANIC
* FS_UNIT_STRUCTURE
* FS_UNIT_MECHANICAL
* FS_UNIT_HERO
* FS_UNIT_NON_HERO
* FS_UNIT_IMMUNE //magic immunity, ofcourse!
* FS_UNIT_NON_IMMUNE
* FS_UNIT_SUMMONED
* FS_UNIT_NON_SUMMONED
* FS_UNIT_VISIBLE
* FS_UNIT_INVISIBLE
* FS_UNIT_WARD
* FS_UNIT_NON_WARD
* FS_UNIT_ANCIENT
* FS_UNIT_NON_ANCIENT
* FS_UNIT_GROUND
* FS_UNIT_FLYING
* FS_UNIT_MELEE
* FS_UNIT_RANGED
* FS_UNIT_UNDEAD
* FS_UNIT_NON_UNDEAD
*
* FS_ITEM_OWNED
* FS_ITEM_NON_OWNED
* FS_ITEM_RUNE //includes runes, tomes, powerups, etc.
* FS_ITEM_NON_RUNE
* FS_ITEM_SELLABLE
* FS_ITEM_NON_SELLABLE
* FS_ITEM_PAWNABLE
* FS_ITEM_NON_PAWNABLE
* FS_ITEM_PERMANENT
* FS_ITEM_NON_PERMANENT
* FS_ITEM_CHARGED
* FS_ITEM_NON_CHARGED
* FS_ITEM_POWERUP
* FS_ITEM_NON_POWERUP
* FS_ITEM_ARTIFACT
* FS_ITEM_NON_ARTIFACT
* FS_ITEM_PURCHASABLE
* FS_ITEM_NON_PURCHASABLE
* FS_ITEM_CAMPAIGN
* FS_ITEM_NON_CAMPAIGN
* FS_ITEM_MISC
* FS_ITEM_NON_MISC
* FS_ITEM_VISIBLE
* FS_ITEM_HIDDEN
*
* FS_PLAYER_ENEMY
* FS_PLAYER_ALLY
* FS_PLAYER_USER
* FS_PLAYER_COMPUTER
* FS_PLAYER_PLAYING
* FS_PLAYER_LEFT //also includes non-used slots.
* FS_PLAYER_NEUTRAL
* FS_PLAYER_NON_NEUTRAL
* FS_PLAYER_VISION //shared vision.
* FS_PLAYER_NON_VISION
* FS_PLAYER_CONTROL //shared unit control.
* FS_PLAYER_NON_CONTROL
*
************************************************************************************************************************
* -----END OF API-----
*/
constant integer FS_UNIT_ENEMY = 0x1
constant integer FS_UNIT_ALLY = 0x2
constant integer FS_UNIT_ALIVE = 0x4
constant integer FS_UNIT_DEAD = 0x8
constant integer FS_UNIT_ORGANIC = 0x10
constant integer FS_UNIT_STRUCTURE = 0x20
constant integer FS_UNIT_MECHANICAL = 0x40
constant integer FS_UNIT_HERO = 0x80
constant integer FS_UNIT_NON_HERO = 0x100
constant integer FS_UNIT_IMMUNE = 0x200
constant integer FS_UNIT_NON_IMMUNE = 0x400
constant integer FS_UNIT_SUMMONED = 0x800
constant integer FS_UNIT_NON_SUMMONED = 0x1000
constant integer FS_UNIT_VISIBLE = 0x2000
constant integer FS_UNIT_INVISIBLE = 0x4000
//constant integer FS_UNIT_WARD = 0x8000
constant integer FS_UNIT_INVULNERABLE = 0x8000
//constant integer FS_UNIT_NON_WARD = 0x10000
constant integer FS_UNIT_NON_INVULNERABLE = 0x10000
constant integer FS_UNIT_ANCIENT = 0x20000
constant integer FS_UNIT_NON_ANCIENT = 0x40000
constant integer FS_UNIT_GROUND = 0x80000
constant integer FS_UNIT_FLYING = 0x100000
constant integer FS_UNIT_MELEE = 0x200000
constant integer FS_UNIT_RANGED = 0x400000
constant integer FS_UNIT_UNDEAD = 0x800000
constant integer FS_UNIT_NON_UNDEAD = 0x1000000
constant integer FS_ITEM_OWNED = 0x1
constant integer FS_ITEM_NON_OWNED = 0x2
constant integer FS_ITEM_RUNE = 0x4
constant integer FS_ITEM_NON_RUNE = 0x8
constant integer FS_ITEM_SELLABLE = 0x10
constant integer FS_ITEM_NON_SELLABLE = 0x20
constant integer FS_ITEM_PAWNABLE = 0x40
constant integer FS_ITEM_NON_PAWNABLE = 0x80
constant integer FS_ITEM_PERMANENT = 0x100
constant integer FS_ITEM_NON_PERMANENT = 0x200
constant integer FS_ITEM_CHARGED = 0x400
constant integer FS_ITEM_NON_CHARGED = 0x800
constant integer FS_ITEM_POWERUP = 0x1000
constant integer FS_ITEM_NON_POWERUP = 0x2000
constant integer FS_ITEM_ARTIFACT = 0x4000
constant integer FS_ITEM_NON_ARTIFACT = 0x8000
constant integer FS_ITEM_PURCHASABLE = 0x10000
constant integer FS_ITEM_NON_PURCHASABLE = 0x20000
constant integer FS_ITEM_CAMPAIGN = 0x40000
constant integer FS_ITEM_NON_CAMPAIGN = 0x80000
constant integer FS_ITEM_MISC = 0x100000
constant integer FS_ITEM_NON_MISC = 0x200000
constant integer FS_ITEM_VISIBLE = 0x400000
constant integer FS_ITEM_HIDDEN = 0x800000
constant integer FS_PLAYER_ENEMY = 0x1
constant integer FS_PLAYER_ALLY = 0x2
constant integer FS_PLAYER_USER = 0x4
constant integer FS_PLAYER_COMPUTER = 0x8
constant integer FS_PLAYER_PLAYING = 0x10
constant integer FS_PLAYER_LEFT = 0x20
constant integer FS_PLAYER_NEUTRAL = 0x40
constant integer FS_PLAYER_NON_NEUTRAL = 0x80
constant integer FS_PLAYER_VISION = 0x100
constant integer FS_PLAYER_NON_VISION = 0x200
constant integer FS_PLAYER_CONTROL = 0x400
constant integer FS_PLAYER_NON_CONTROL = 0x800
endglobals
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
function UnitFilter takes unit whichUnit, player whichPlayer, integer filter returns boolean
set filter = filter + 0x1
if filter > 0x2000 then
if filter > 0x1000000 then
set filter = filter - 0x1000000 //non-undead
if IsUnitType(whichUnit, UNIT_TYPE_UNDEAD) then
return false
endif
endif
if filter > 0x800000 then //undead
set filter = filter - 0x800000
if not IsUnitType(whichUnit, UNIT_TYPE_UNDEAD) then
return false
endif
endif
if filter > 0x400000 then // ranged
//set filter = filter - 0x40000 // fixed by Zibi 23.01.2019
set filter = filter - 0x400000
if not IsUnitType(whichUnit, UNIT_TYPE_RANGED_ATTACKER) then
return false
endif
endif
if filter > 0x200000 then
set filter = filter - 0x200000 //melee
if not IsUnitType(whichUnit, UNIT_TYPE_MELEE_ATTACKER) then
return false
endif
endif
if filter > 0x100000 then
set filter = filter - 0x100000 // flying
if not IsUnitType(whichUnit, UNIT_TYPE_FLYING) then
return false
endif
endif
if filter > 0x80000 then
set filter = filter - 0x80000 //ground
//if not IsUnitType(whichUnit, UNIT_TYPE_GROUND) then // changed by Zibi 23.01.2019
if IsUnitType(whichUnit, UNIT_TYPE_FLYING) then
return false
endif
endif
if filter > 0x40000 then //non-ancient
set filter = filter - 0x40000
if IsUnitType(whichUnit, UNIT_TYPE_ANCIENT) then
return false
endif
endif
if filter > 0x20000 then //ancient
set filter = filter - 0x20000
if not IsUnitType(whichUnit, UNIT_TYPE_ANCIENT) then
return false
endif
endif
if filter > 0x10000 then
set filter = filter - 0x10000 //non-Invulnerable
//if GetUnitAbilityLevel(whichUnit,ABILITY_WARD_CLASSIFIER)!=0 then
//in 1.30.1 native BlzIsUnitInvulnerable works fine (it is fixed), in previous version it works opposite
if BlzIsUnitInvulnerable(whichUnit) then //for version 1.30.1 and above
//if not BlzIsUnitInvulnerable(whichUnit) then //for version 1.29
return false
endif
endif
if filter > 0x8000 then
set filter = filter - 0x8000 // Invulnerable
//if GetUnitAbilityLevel(whichUnit,ABILITY_WARD_CLASSIFIER)==0 then
if not BlzIsUnitInvulnerable(whichUnit) then //for version 1.30.1 and above
//if BlzIsUnitInvulnerable(whichUnit) then //for version 1.29
return false
endif
endif
if filter > 0x4000 then //invisible
set filter = filter - 0x4000
if IsUnitVisible(whichUnit,whichPlayer) then
return false
endif
endif
if filter > 0x2000 then //visible
set filter = filter - 0x2000
if not IsUnitVisible(whichUnit,whichPlayer) then
return false
endif
endif
endif
if filter < 0x2001 then
if filter > 0x1000 then //non-summoned
set filter = filter - 0x1000
if IsUnitType(whichUnit, UNIT_TYPE_SUMMONED) then
return false
endif
endif
if filter > 0x800 then //summoned
set filter = filter - 0x800
if not IsUnitType(whichUnit, UNIT_TYPE_SUMMONED) then
return false
endif
endif
if filter > 0x400 then //non-immune
set filter = filter - 0x400
if IsUnitType(whichUnit, UNIT_TYPE_MAGIC_IMMUNE) then
return false
endif
endif
if filter > 0x200 then //immune
set filter = filter - 0x200
if not IsUnitType(whichUnit, UNIT_TYPE_MAGIC_IMMUNE) then
return false
endif
endif
if filter > 0x100 then //non-hero
set filter = filter - 0x100
if IsUnitType(whichUnit, UNIT_TYPE_HERO) then
return false
endif
endif
if filter > 0x80 then //hero
set filter = filter - 0x80
if not IsUnitType(whichUnit, UNIT_TYPE_HERO) then
return false
endif
endif
if filter > 0x40 then //mechanical
set filter = filter - 0x40
if not IsUnitType(whichUnit,UNIT_TYPE_MECHANICAL) then
return false
endif
endif
if filter > 0x20 then //structure
set filter = filter - 0x20
if not IsUnitType(whichUnit,UNIT_TYPE_STRUCTURE) then
return false
endif
endif
if filter > 0x10 then //organic
set filter = filter - 0x10
if IsUnitType(whichUnit,UNIT_TYPE_STRUCTURE) or IsUnitType(whichUnit,UNIT_TYPE_MECHANICAL) then
return false
endif
endif
if filter > 0x8 then //dead
set filter = filter - 0x8
if GetWidgetLife(whichUnit)>0.405 and IsUnitType(whichUnit,UNIT_TYPE_DEAD)==false then
return false
endif
endif
if filter > 0x4 then //alive
set filter = filter - 0x4
//if GetWidgetLife(whichUnit)<=0.405 or IsUnitType(whichUnit,UNIT_TYPE_DEAD) then
if not UnitAlive(whichUnit) then
return false
endif
endif
if filter > 0x2 then //ally
set filter = filter - 0x2
if IsUnitEnemy(whichUnit,whichPlayer) then
return false
endif
endif
if filter > 0x1 then //enemy
set filter = filter - 0x1
if not IsUnitEnemy(whichUnit,whichPlayer) then
return false
endif
endif
endif
if GetUnitAbilityLevel(whichUnit,ABILITY_DUMMY_CLASSIFIER)!=0 then
return false
endif
return true
endfunction
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
function ItemFilter takes item whichItem, integer filter returns boolean
set filter = filter + 0x1
if filter > 0x2000 then
if filter > 0x800000 then
set filter = filter - 0x800000
if not IsItemVisible(whichItem) then
return false
endif
endif
if filter > 0x400000 then
set filter = filter - 0x40000
if IsItemVisible(whichItem) then
return false
endif
endif
if filter > 0x200000 then
set filter = filter - 0x200000
if GetItemType(whichItem)==ITEM_TYPE_MISCELLANEOUS then
return false
endif
endif
if filter > 0x100000 then
set filter = filter - 0x100000
if GetItemType(whichItem)!=ITEM_TYPE_MISCELLANEOUS then
return false
endif
endif
if filter > 0x80000 then
set filter = filter - 0x80000
if GetItemType(whichItem)==ITEM_TYPE_CAMPAIGN then
return false
endif
endif
if filter > 0x40000 then
set filter = filter - 0x40000
if GetItemType(whichItem)!=ITEM_TYPE_CAMPAIGN then
return false
endif
endif
if filter > 0x20000 then
set filter = filter - 0x20000
if GetItemType(whichItem)==ITEM_TYPE_PURCHASABLE then
return false
endif
endif
if filter > 0x10000 then
set filter = filter - 0x10000
if GetItemType(whichItem)!=ITEM_TYPE_PURCHASABLE then
return false
endif
endif
if filter > 0x8000 then
set filter = filter - 0x8000
if GetItemType(whichItem)==ITEM_TYPE_ARTIFACT then
return false
endif
endif
if filter > 0x4000 then
set filter = filter - 0x4000
if GetItemType(whichItem)!=ITEM_TYPE_ARTIFACT then
return false
endif
endif
if filter > 0x2000 then
set filter = filter - 0x2000
if GetItemType(whichItem)==ITEM_TYPE_POWERUP then
return false
endif
endif
endif
if filter < 0x2001 then
if filter > 0x1000 then
set filter = filter - 0x1000
if GetItemType(whichItem)!=ITEM_TYPE_POWERUP then
return false
endif
endif
if filter > 0x800 then
set filter = filter - 0x800
if GetItemType(whichItem)==ITEM_TYPE_CHARGED then
return false
endif
endif
if filter > 0x400 then
set filter = filter - 0x400
if GetItemType(whichItem)!=ITEM_TYPE_CHARGED then
return false
endif
endif
if filter > 0x200 then
set filter = filter - 0x200
if GetItemType(whichItem)==ITEM_TYPE_PERMANENT then
return false
endif
endif
if filter > 0x100 then
set filter = filter - 0x100
if GetItemType(whichItem)!=ITEM_TYPE_PERMANENT then
return false
endif
endif
if filter > 0x80 then
set filter = filter - 0x80
if IsItemPawnable(whichItem) then
return false
endif
endif
if filter > 0x40 then
set filter = filter - 0x40
if not IsItemPawnable(whichItem) then
return false
endif
endif
if filter > 0x20 then
set filter = filter - 0x20
if IsItemSellable(whichItem) then
return false
endif
endif
if filter > 0x10 then
set filter = filter - 0x10
if not IsItemSellable(whichItem) then
return false
endif
endif
if filter > 0x8 then
set filter = filter - 0x8
if IsItemPowerup(whichItem) then
return false
endif
endif
if filter > 0x4 then
set filter = filter - 0x4
if not IsItemPowerup(whichItem) then
return false
endif
endif
if filter > 0x2 then
set filter = filter - 0x2
if IsItemOwned(whichItem) then
return false
endif
endif
if filter > 0x1 then
set filter = filter - 0x1
if not IsItemOwned(whichItem) then
return false
endif
endif
endif
return true
endfunction
function PlayerFilter takes player whichPlayer, player otherPlayer, integer filter returns boolean
if filter > 0x800 then
set filter = filter - 0x800
if GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_CONTROL) then
return false
endif
endif
if filter > 0x400 then
set filter = filter - 0x400
if not GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_CONTROL) then
return false
endif
endif
if filter > 0x200 then
set filter = filter - 0x200
if GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_VISION) then
return false
endif
endif
if filter > 0x100 then
set filter = filter - 0x100
if not GetPlayerAlliance(whichPlayer,otherPlayer,ALLIANCE_SHARED_VISION) then
return false
endif
endif
if filter > 0x80 then
set filter = filter - 0x80
if (whichPlayer==Player(12) or whichPlayer==Player(13) or whichPlayer==Player(14) or whichPlayer==Player(15)) then
return false
endif
endif
if filter > 0x40 then
set filter = filter - 0x40
if (not(whichPlayer==Player(12) or whichPlayer==Player(13) or whichPlayer==Player(14) or whichPlayer==Player(15))) then
return false
endif
endif
if filter > 0x20 then
set filter = filter - 0x20
if GetPlayerSlotState(whichPlayer)!=PLAYER_SLOT_STATE_LEFT then
return false
endif
endif
if filter > 0x10 then
set filter = filter - 0x10
if GetPlayerSlotState(whichPlayer)!=PLAYER_SLOT_STATE_PLAYING then
return false
endif
endif
if filter > 0x8 then
set filter = filter - 0x8
if GetPlayerController(whichPlayer)!=MAP_CONTROL_COMPUTER then
return false
endif
endif
if filter > 0x4 then
set filter = filter - 0x4
if GetPlayerController(whichPlayer)!=MAP_CONTROL_USER then
return false
endif
endif
if filter > 0x2 then
set filter = filter - 0x2
if IsPlayerEnemy(whichPlayer,otherPlayer) then
return false
endif
endif
if filter > 0x1 then
set filter = filter - 0x1
if IsPlayerAlly(whichPlayer,otherPlayer) then
return false
endif
endif
return true
endfunction
endlibrary
// GUI-Friendly Damage Detection -- v1.2.1 -- by Weep
// http:// www.thehelper.net/forums/showthread.php?t=137957
//
// Requires: only this trigger and its variables.
//
// -- What? --
// This snippet provides a leak-free, GUI-friendly implementation of an "any unit takes
// damage" event. It requires no JASS knowledge to use.
//
// It uses the Game - Value Of Real Variable event as its method of activating other
// triggers, and passes the event responses through a few globals.
//
// -- Why? --
// The traditional GUI method of setting up a trigger than runs when any unit is damaged
// leaks trigger events. This snippet is easy to implement and removes the need to do
// you own GUI damage detection setup.
//
// -- How To Implement --
// 0. Before you copy triggers that use GDD into a new map, you need to copy over GDD
// with its GDD Variable Creator trigger, or there will be a problem: the variables
// won't be automatically created correctly.
//
// 1. Be sure "Automatically create unknown variables while pasting trigger data" is
// enabled in the World Editor general preferences.
// 2. Copy this trigger category ("GDD") and paste it into your map.
// (Alternately: create the variables listed in the globals block below, create a
// trigger named "GUI Friendly Damage Detection", and paste in this entire text.)
// 3. Create your damage triggers using Game - Value Of Real Variable as the event,
// select GDD_Event as the variable, and leave the rest of the settings to the default
// "becomes Equal to 0.00".
// The event responses are the following variables:
// GDD_Damage is the amount of damage, replacing Event Response - Damage Taken.
// GDD_DamagedUnit is the damaged unit, replacing Event Response - Triggering Unit.
// Triggering Unit can still be used, if you need to use waits.
// Read the -- Notes -- section below for more info.
// GDD_DamageSource is the damaging unit, replacing Event Response - Damage Source.
//
// -- Notes --
// GDD's event response variables are not wait-safe; you can't use them after a wait in
// a trigger. If you need to use waits, Triggering Unit (a.k.a. GetTriggerUnit()) can
// be used in place of GDD_DamageSource. There is no usable wait-safe equivalent to
// Event Damage or Damage Source; you'll need to save the values yourself.
//
// Don't write any values to the variables used as the event responses, or it will mess
// up any other triggers using this snippet for their triggering. Only use their values.
//
// This uses arrays, so can detect damage for a maximum of 8190 units at a time, and
// cleans up data at a rate of 33.33 per second, by default. This should be enough for
// most maps, but if you want to change the rate, change the value returned in the
// GDD_RecycleRate function at the top of the code, below.
//
// By default, GDD will not register units that have Locust at the moment of their
// entering the game, and will not recognize when they take damage (which can only
// happen if the Locust ability is later removed from the unit.) To allow a unit to have
// Locust yet still cause GDD damage events if Locust is removed, you can either design
// the unit to not have Locust by default and add it via triggers after creation, or
// edit the GDD_Filter function at the top of the code, below.
//
// -- Credits --
// Captain Griffin on wc3c.net for the research and concept of GroupRefresh.
//
// Credit in your map not needed, but please include this README.
//
// -- Version History --
// 1.2.1: Minor code cleaning. Added configuration functions. Updated documentation.
// 1.2.0: Made this snippet work properly with recursive damage.
// 1.1.1: Added a check in order to not index units with the Locust ability (dummy units).
// If you wish to check for damage taken by a unit that is unselectable, do not
// give the unit-type Locust in the object editor; instead, add the Locust ability
// 'Aloc' via a trigger after its creation, then remove it.
// 1.1.0: Added a check in case a unit gets moved out of the map and back.
// 1.0.0: First release.
//===================================================================
// Configurables.
function GDD_RecycleRate takes nothing returns real //The rate at which the system checks units to see if they've been removed from the game
return 0.03
endfunction
function GDD_Filter takes unit u returns boolean //The condition a unit has to pass to have it registered for damage detection
return GetUnitAbilityLevel(u, 'Aloc') == 0 //By default, the system ignores Locust units, because they normally can't take damage anyway
endfunction
//===================================================================
// This is just for reference.
// If you use JassHelper, you could uncomment this section instead of creating the variables in the trigger editor.
//globals
//real udg_GDD_Event = 0.
//real udg_GDD_Damage = 0.
//unit udg_GDD_DamagedUnit
//unit udg_GDD_DamageSource
//trigger array udg_GDD__TriggerArray
//integer array udg_GDD__Integers
//unit array udg_GDD__UnitArray
//group udg_GDD__LeftMapGroup = CreateGroup()
//endglobals
//===================================================================
// System code follows. Don't touch!
function GDD_Event takes nothing returns boolean
local unit damagedcache = udg_GDD_DamagedUnit
local unit damagingcache = udg_GDD_DamageSource
local real damagecache = udg_GDD_Damage
set udg_GDD_DamagedUnit = GetTriggerUnit()
set udg_GDD_DamageSource = GetEventDamageSource()
set udg_GDD_Damage = GetEventDamage()
set udg_GDD_Event = 1.
set udg_GDD_Event = 0.
set udg_GDD_DamagedUnit = damagedcache
set udg_GDD_DamageSource = damagingcache
set udg_GDD_Damage = damagecache
set damagedcache = null
set damagingcache = null
return false
endfunction
function GDD_AddDetection takes nothing returns boolean
// if(udg_GDD__Integers[0] > 8190) then
// call BJDebugMsg("GDD: Too many damage events! Decrease number of units present in the map or increase recycle rate.")
// ***Recycle rate is specified in the GDD_RecycleRate function at the top of the code. Smaller is faster.***
// return
// endif
if(IsUnitInGroup(GetFilterUnit(), udg_GDD__LeftMapGroup)) then
call GroupRemoveUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
elseif(GDD_Filter(GetFilterUnit())) then
set udg_GDD__Integers[0] = udg_GDD__Integers[0]+1
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = GetFilterUnit()
set udg_GDD__TriggerArray[udg_GDD__Integers[0]] = CreateTrigger()
call TriggerRegisterUnitEvent(udg_GDD__TriggerArray[udg_GDD__Integers[0]], udg_GDD__UnitArray[udg_GDD__Integers[0]], EVENT_UNIT_DAMAGED)
call TriggerAddCondition(udg_GDD__TriggerArray[udg_GDD__Integers[0]], Condition(function GDD_Event))
endif
return false
endfunction
function GDD_PreplacedDetection takes nothing returns nothing
local group g = CreateGroup()
local integer i = 0
loop
call GroupEnumUnitsOfPlayer(g, Player(i), Condition(function GDD_AddDetection))
set i = i+1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call DestroyGroup(g)
set g = null
endfunction
function GDD_GroupRefresh takes nothing returns nothing
// Based on GroupRefresh by Captain Griffen on wc3c.net
if (bj_slotControlUsed[5063] == true) then
call GroupClear(udg_GDD__LeftMapGroup)
set bj_slotControlUsed[5063] = false
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetEnumUnit())
endfunction
function GDD_Recycle takes nothing returns nothing
if(udg_GDD__Integers[0] <= 0) then
return
elseif(udg_GDD__Integers[1] <= 0) then
set udg_GDD__Integers[1] = udg_GDD__Integers[0]
endif
if(GetUnitTypeId(udg_GDD__UnitArray[udg_GDD__Integers[1]]) == 0) then
call DestroyTrigger(udg_GDD__TriggerArray[udg_GDD__Integers[1]])
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = null
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = udg_GDD__TriggerArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[1]] = udg_GDD__UnitArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = null
set udg_GDD__Integers[0] = udg_GDD__Integers[0]-1
endif
set udg_GDD__Integers[1] = udg_GDD__Integers[1]-1
endfunction
function GDD_LeaveMap takes nothing returns boolean
local boolean cached = bj_slotControlUsed[5063]
if(udg_GDD__Integers[2] < 64) then
set udg_GDD__Integers[2] = udg_GDD__Integers[2]+1
else
set bj_slotControlUsed[5063] = true
call ForGroup(udg_GDD__LeftMapGroup, function GDD_GroupRefresh)
set udg_GDD__Integers[2] = 0
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
set bj_slotControlUsed[5063] = cached
return false
endfunction
// ===========================================================================
function InitTrig_GUI_Friendly_Damage_Detection takes nothing returns nothing
local region r = CreateRegion()
call RegionAddRect(r, GetWorldBounds())
call TriggerRegisterEnterRegion(CreateTrigger(), r, Condition(function GDD_AddDetection))
call TriggerRegisterLeaveRegion(CreateTrigger(), r, Condition(function GDD_LeaveMap))
call GDD_PreplacedDetection()
call TimerStart(CreateTimer(), GDD_RecycleRate(), true, function GDD_Recycle)
set r = null
endfunction
library ORDER
globals
//strange ones at bottom
public constant integer OFFSET=851970
public constant integer absorb=852529
public constant integer acidbomb=852662
public constant integer acolyteharvest=852185
public constant integer AImove=851988
public constant integer ambush=852131
public constant integer ancestralspirit=852490
public constant integer ancestralspirittarget=852491
public constant integer animatedead=852217
public constant integer antimagicshell=852186
public constant integer attack=851983
public constant integer attackground=851984
public constant integer attackonce=851985
public constant integer attributemodskill=852576
public constant integer auraunholy=852215
public constant integer auravampiric=852216
public constant integer autodispel=852132
public constant integer autodispeloff=852134
public constant integer autodispelon=852133
public constant integer autoentangle=852505
public constant integer autoentangleinstant=852506
public constant integer autoharvestgold=852021
public constant integer autoharvestlumber=852022
public constant integer avatar=852086
public constant integer avengerform=852531
public constant integer awaken=852466
public constant integer banish=852486
public constant integer barkskin=852135
public constant integer barkskinoff=852137
public constant integer barkskinon=852136
public constant integer battleroar=852099
public constant integer battlestations=852099
public constant integer bearform=852138
public constant integer berserk=852100
public constant integer blackarrow=852577
public constant integer blackarrowoff=852579
public constant integer blackarrowon=852578
public constant integer blight=852187
public constant integer blink=852525
public constant integer blizzard=852089
public constant integer bloodlust=852101
public constant integer bloodlustoff=852103
public constant integer bloodluston=852102
public constant integer board=852043
public constant integer breathoffire=852580
public constant integer breathoffrost=852560
public constant integer build=851994
public constant integer burrow=852533
public constant integer cannibalize=852188
public constant integer carrionscarabs=852551
public constant integer carrionscarabsinstant=852554
public constant integer carrionscarabsoff=852553
public constant integer carrionscarabson=852552
public constant integer carrionswarm=852218
public constant integer chainlightning=852119
public constant integer channel=852600
public constant integer charm=852581
public constant integer chemicalrage=852663
public constant integer cloudoffog=852473
public constant integer clusterrockets=852652
public constant integer coldarrows=852244
public constant integer coldarrowstarg=852243
public constant integer controlmagic=852474
public constant integer corporealform=852493
public constant integer corrosivebreath=852140
public constant integer coupleinstant=852508
public constant integer coupletarget=852507
public constant integer creepanimatedead=852246
public constant integer creepdevour=852247
public constant integer creepheal=852248
public constant integer creephealoff=852250
public constant integer creephealon=852249
public constant integer creepthunderbolt=852252
public constant integer creepthunderclap=852253
public constant integer cripple=852189
public constant integer curse=852190
public constant integer curseoff=852192
public constant integer curseon=852191
public constant integer cyclone=852144
public constant integer darkconversion=852228
public constant integer darkportal=852229
public constant integer darkritual=852219
public constant integer darksummoning=852220
public constant integer deathanddecay=852221
public constant integer deathcoil=852222
public constant integer deathpact=852223
public constant integer decouple=852509
public constant integer defend=852055
public constant integer detectaoe=852015
public constant integer detonate=852145
public constant integer devour=852104
public constant integer devourmagic=852536
public constant integer disassociate=852240
public constant integer disenchant=852495
public constant integer dismount=852470
public constant integer dispel=852057
public constant integer divineshield=852090
public constant integer doom=852583
public constant integer drain=852487
public constant integer dreadlordinferno=852224
public constant integer dropitem=852001
public constant integer drunkenhaze=852585
public constant integer earthquake=852121
public constant integer eattree=852146
public constant integer elementalfury=852586
public constant integer ensnare=852106
public constant integer ensnareoff=852108
public constant integer ensnareon=852107
public constant integer entangle=852147
public constant integer entangleinstant=852148
public constant integer entanglingroots=852171
public constant integer etherealform=852496
public constant integer evileye=852105
public constant integer faeriefire=852149
public constant integer faeriefireoff=852151
public constant integer faeriefireon=852150
public constant integer fanofknives=852526
public constant integer farsight=852122
public constant integer fingerofdeath=852230
public constant integer firebolt=852231
public constant integer flamestrike=852488
public constant integer flamingarrows=852174
public constant integer flamingarrowstarg=852173
public constant integer flamingattack=852540
public constant integer flamingattacktarg=852539
public constant integer flare=852060
public constant integer forceboard=852044
public constant integer forceofnature=852176
public constant integer forkedlightning=852587
public constant integer freezingbreath=852195
public constant integer frenzy=852561
public constant integer frenzyoff=852563
public constant integer frenzyon=852562
public constant integer frostarmor=852225
public constant integer frostarmoroff=852459
public constant integer frostarmoron=852458
public constant integer frostnova=852226
public constant integer getitem=851981
public constant integer gold2lumber=852233
public constant integer grabtree=852511
public constant integer harvest=852018
public constant integer heal=852063
public constant integer healingspray=852664
public constant integer healingward=852109
public constant integer healingwave=852501
public constant integer healoff=852065
public constant integer healon=852064
public constant integer hex=852502
public constant integer holdposition=851993
public constant integer holybolt=852092
public constant integer howlofterror=852588
public constant integer humanbuild=851995
public constant integer immolation=852177
public constant integer impale=852555
public constant integer incineratearrow=852670
public constant integer incineratearrowoff=852672
public constant integer incineratearrowon=852671
public constant integer inferno=852232
public constant integer innerfire=852066
public constant integer innerfireoff=852068
public constant integer innerfireon=852067
public constant integer instant=852200
public constant integer invisibility=852069
public constant integer lavamonster=852667
public constant integer lightningshield=852110
public constant integer load=852046
public constant integer loadarcher = 852142
public constant integer loadcorpse=852050
public constant integer loadcorpseinstant=852053
public constant integer locustswarm=852556
public constant integer lumber2gold=852234
public constant integer magicdefense=852478
public constant integer magicleash=852480
public constant integer magicundefense=852479
public constant integer manaburn=852179
public constant integer manaflareoff=852513
public constant integer manaflareon=852512
public constant integer manashieldoff=852590
public constant integer manashieldon=852589
public constant integer massteleport=852093
public constant integer mechanicalcritter=852564
public constant integer metamorphosis=852180
public constant integer militia=852072
public constant integer militiaconvert=852071
public constant integer militiaoff=852073
public constant integer militiaunconvert=852651
public constant integer mindrot=852565
public constant integer mirrorimage=852123
public constant integer monsoon=852591
public constant integer mount=852469
public constant integer mounthippogryph=852143
public constant integer move=851986
public constant integer nagabuild=852467
public constant integer neutraldetectaoe=852023
public constant integer neutralinteract=852566
public constant integer neutralspell=852630
public constant integer nightelfbuild=851997
public constant integer orcbuild=851996
public constant integer parasite=852601
public constant integer parasiteoff=852603
public constant integer parasiteon=852602
public constant integer patrol=851990
public constant integer phaseshift=852514
public constant integer phaseshiftinstant=852517
public constant integer phaseshiftoff=852516
public constant integer phaseshifton=852515
public constant integer phoenixfire=852481
public constant integer phoenixmorph=852482
public constant integer poisonarrows=852255
public constant integer poisonarrowstarg=852254
public constant integer polymorph=852074
public constant integer possession=852196
public constant integer preservation=852568
public constant integer purge=852111
public constant integer rainofchaos=852237
public constant integer rainoffire=852238
public constant integer raisedead=852197
public constant integer raisedeadoff=852199
public constant integer raisedeadon=852198
public constant integer ravenform=852155
public constant integer recharge=852157
public constant integer rechargeoff=852159
public constant integer rechargeon=852158
public constant integer rejuvination=852160
public constant integer renew=852161
public constant integer renewoff=852163
public constant integer renewon=852162
public constant integer repair=852024
public constant integer repairoff=852026
public constant integer repairon=852025
public constant integer replenish=852542
public constant integer replenishlife=852545
public constant integer replenishlifeoff=852547
public constant integer replenishlifeon=852546
public constant integer replenishmana=852548
public constant integer replenishmanaoff=852550
public constant integer replenishmanaon=852549
public constant integer replenishoff=852544
public constant integer replenishon=852543
public constant integer request_hero=852239
public constant integer requestsacrifice=852201
public constant integer restoration=852202
public constant integer restorationoff=852204
public constant integer restorationon=852203
public constant integer resumebuild=851999
public constant integer resumeharvesting=852017
public constant integer resurrection=852094
public constant integer returnresources=852020
public constant integer reveal=852270
public constant integer revenge=852241
public constant integer revive=852039
public constant integer roar=852164
public constant integer robogoblin=852656
public constant integer root=852165
public constant integer sacrifice=852205
public constant integer sanctuary=852569
public constant integer scout=852181
public constant integer selfdestruct=852040
public constant integer selfdestructoff=852042
public constant integer selfdestructon=852041
public constant integer sentinel=852182
public constant integer setrally=851980
public constant integer shadowsight=852570
public constant integer shadowstrike=852527
public constant integer shockwave=852125
public constant integer silence=852592
public constant integer sleep=852227
public constant integer slow=852075
public constant integer slowoff=852077
public constant integer slowon=852076
public constant integer smart=851971
public constant integer soulburn=852668
public constant integer soulpreservation=852242
public constant integer spellshield=852571
public constant integer spellshieldaoe=852572
public constant integer spellsteal=852483
public constant integer spellstealoff=852485
public constant integer spellstealon=852484
public constant integer spies=852235
public constant integer spiritlink=852499
public constant integer spiritofvengeance=852528
public constant integer spirittroll=852573
public constant integer spiritwolf=852126
public constant integer stampede=852593
public constant integer standdown=852113
public constant integer starfall=852183
public constant integer stasistrap=852114
public constant integer steal=852574
public constant integer stomp=852127
public constant integer stoneform=852206
public constant integer stop=851972
public constant integer submerge=852604
public constant integer summonfactory=852658
public constant integer summongrizzly=852594
public constant integer summonphoenix=852489
public constant integer summonquillbeast=852595
public constant integer summonwareagle=852596
public constant integer tankdroppilot=852079
public constant integer tankloadpilot=852080
public constant integer tankpilot=852081
public constant integer taunt=852520
public constant integer thunderbolt=852095
public constant integer thunderclap=852096
public constant integer tornado=852597
public constant integer townbelloff=852083
public constant integer townbellon=852082
public constant integer tranquility=852184
public constant integer transmute=852665
public constant integer unavatar=852087
public constant integer unavengerform=852532
public constant integer unbearform=852139
public constant integer unburrow=852534
public constant integer uncoldarrows=852245
public constant integer uncorporealform=852494
public constant integer undeadbuild=851998
public constant integer undefend=852056
public constant integer undivineshield=852091
public constant integer unetherealform=852497
public constant integer unflamingarrows=852175
public constant integer unflamingattack=852541
public constant integer unholyfrenzy=852209
public constant integer unimmolation=852178
public constant integer unload=852047
public constant integer unloadall=852048
public constant integer unloadallcorpses=852054
public constant integer unloadallinstant=852049
public constant integer unpoisonarrows=852256
public constant integer unravenform=852156
public constant integer unrobogoblin=852657
public constant integer unroot=852166
public constant integer unstableconcoction=852500
public constant integer unstoneform=852207
public constant integer unsubmerge=852605
public constant integer unsummon=852210
public constant integer unwindwalk=852130
public constant integer vengeance=852521
public constant integer vengeanceinstant=852524
public constant integer vengeanceoff=852523
public constant integer vengeanceon=852522
public constant integer volcano=852669
public constant integer voodoo=852503
public constant integer ward=852504
public constant integer waterelemental=852097
public constant integer wateryminion=852598
public constant integer web=852211
public constant integer weboff=852213
public constant integer webon=852212
public constant integer whirlwind=852128
public constant integer windwalk=852129
public constant integer wispharvest=852214
public constant integer scrollofspeed=852285
public constant integer cancel=851976
public constant integer moveslot1=852002
public constant integer moveslot2=852003
public constant integer moveslot3=852004
public constant integer moveslot4=852005
public constant integer moveslot5=852006
public constant integer moveslot6=852007
public constant integer useslot1=852008
public constant integer useslot2=852009
public constant integer useslot3=852010
public constant integer useslot4=852011
public constant integer useslot5=852012
public constant integer useslot6=852013
public constant integer skillmenu=852000
public constant integer stunned=851973
public constant integer instant1=851991 //?
public constant integer instant2=851987 //?
public constant integer instant3=851975 //?
public constant integer instant4=852019 //?
public constant integer itemillusion = 852274 // added by zibi
endglobals
endlibrary
library WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
*
* Fields
* -------------------------
*
* readonly static integer maxX
* readonly static integer maxY
* readonly static integer minX
* readonly static integer minY
*
* readonly static integer centerX
* readonly static integer centerY
*
* readonly static rect world
* readonly static region worldRegion
*
************************************************************************************/
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX = R2I(GetRectMaxX(world))
set maxY = R2I(GetRectMaxY(world))
set minX = R2I(GetRectMinX(world))
set minY = R2I(GetRectMinY(world))
set centerX = R2I((maxX + minX)/2)
set centerY = R2I((minY + maxY)/2)
set worldRegion = CreateRegion()
call RegionAddRect(worldRegion, world)
endmethod
endmodule
struct WorldBounds extends array
readonly static integer maxX
readonly static integer maxY
readonly static integer minX
readonly static integer minY
readonly static integer centerX
readonly static integer centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary
//added by Zibi
function MapContainsXY takes real x, real y returns boolean
return x >= WorldBounds.minX and x <= WorldBounds.maxX and y >= WorldBounds.minY and y <= WorldBounds.maxY
endfunction
library IsDestructableTree uses optional UnitIndexer /* v1.3.1
*************************************************************************************
* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-isdestructabletree-248054/
* by BPower
* Detect whether a destructable is a tree or not.
*
***************************************************************************
*
* Credits
*
* To PitzerMike
* -----------------------
*
* for IsDestructableTree
*
*************************************************************************************
*
* Functions
*
* function IsDestructableTree takes destructable d returns boolean
*
* function IsDestructableAlive takes destructable d returns boolean
*
* function IsDestructableDead takes destructable d returns boolean
*
* function IsTreeAlive takes destructable tree returns boolean
* - May only return true for trees.
*
* function KillTree takes destructable tree returns boolean
* - May only kill trees.
*
*/
globals
private constant integer HARVESTER_UNIT_ID = 'hpea'//* human peasant
private constant integer HARVEST_ABILITY = 'Ahrl'//* ghoul harvest
private constant integer HARVEST_ORDER_ID = 0xD0032//* harvest order ( 852018 )
private constant player NEUTRAL_PLAYER = Player(PLAYER_NEUTRAL_PASSIVE)
private unit harvester = null
endglobals
function IsDestructableTree takes destructable d returns boolean
//* 851973 is the order id for stunned, it will interrupt the preceding harvest order.
return (IssueTargetOrderById(harvester, HARVEST_ORDER_ID, d)) and (IssueImmediateOrderById(harvester, 851973))
endfunction
function IsDestructableDead takes destructable d returns boolean
return (GetWidgetLife(d) <= 0.405)
endfunction
function IsDestructableAlive takes destructable d returns boolean
return (GetWidgetLife(d) > .405)
endfunction
function IsTreeAlive takes destructable tree returns boolean
return IsDestructableAlive(tree) and IsDestructableTree(tree)
endfunction
function KillTree takes destructable tree returns boolean
if (IsTreeAlive(tree)) then
call KillDestructable(tree)
return true
endif
return false
endfunction
private function Init takes nothing returns nothing
static if LIBRARY_UnitIndexer then//* You may adapt this to your own indexer.
set UnitIndexer.enabled = false
endif
set harvester = CreateUnit(NEUTRAL_PLAYER, HARVESTER_UNIT_ID, 0, 0, 0)
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = true
endif
call UnitAddAbility(harvester, HARVEST_ABILITY)
call UnitAddAbility(harvester, 'Aloc')
call ShowUnit(harvester, false)
endfunction
//* Seriously?
private module Inits
private static method onInit takes nothing returns nothing
call Init()
endmethod
endmodule
private struct I extends array
implement Inits
endstruct
endlibrary
library TerrainPathability initializer Init
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This script can be used to detect the type of pathing at a specific point.
//* It is valuable to do it this way because the IsTerrainPathable is very
//* counterintuitive and returns in odd ways and aren't always as you would
//* expect. This library, however, facilitates detecting those things reliably
//* and easily.
//*
//******************************************************************************
//*
//* > function IsTerrainDeepWater takes real x, real y returns boolean
//* > function IsTerrainShallowWater takes real x, real y returns boolean
//* > function IsTerrainLand takes real x, real y returns boolean
//* > function IsTerrainPlatform takes real x, real y returns boolean
//* > function IsTerrainWalkable takes real x, real y returns boolean
//*
//* These functions return true if the given point is of the type specified
//* in the function's name and false if it is not. For the IsTerrainWalkable
//* function, the MAX_RANGE constant below is the maximum deviation range from
//* the supplied coordinates that will still return true.
//*
//* The IsTerrainPlatform works for any preplaced walkable destructable. It will
//* return true over bridges, destructable ramps, elevators, and invisible
//* platforms. Walkable destructables created at runtime do not create the same
//* pathing hole as preplaced ones do, so this will return false for them. All
//* other functions except IsTerrainWalkable return false for platforms, because
//* the platform itself erases their pathing when the map is saved.
//*
//* After calling IsTerrainWalkable(x, y), the following two global variables
//* gain meaning. They return the X and Y coordinates of the nearest walkable
//* point to the specified coordinates. These will only deviate from the
//* IsTerrainWalkable function arguments if the function returned false.
//*
//* Variables that can be used from the library:
//* [real] TerrainPathability_X
//* [real] TerrainPathability_Y
//*
globals
private constant real MAX_RANGE = 10.
private constant integer DUMMY_ITEM_ID = 'wolg'
endglobals
globals
private item Item = null
private rect Find = null
private item array Hid
private integer HidMax = 0
public real X = 0.
public real Y = 0.
endglobals
function IsTerrainDeepWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
function IsTerrainShallowWater takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
function IsTerrainLand takes real x, real y returns boolean
return IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY)
endfunction
function IsTerrainPlatform takes real x, real y returns boolean
return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY)
endfunction
private function HideItem takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set Hid[HidMax] = GetEnumItem()
call SetItemVisible(Hid[HidMax], false)
set HidMax = HidMax + 1
endif
endfunction
function IsTerrainWalkable takes real x, real y returns boolean
//Hide any items in the area to avoid conflicts with our item
call MoveRectTo(Find, x, y)
call EnumItemsInRect(Find ,null, function HideItem)
//Try to move the test item and get its coords
call SetItemPosition(Item, x, y) //Unhides the item
set X = GetItemX(Item)
set Y = GetItemY(Item)
static if LIBRARY_IsTerrainWalkable then
//This is for compatibility with the IsTerrainWalkable library
set IsTerrainWalkable_X = X
set IsTerrainWalkable_Y = Y
endif
call SetItemVisible(Item, false)//Hide it again
//Unhide any items hidden at the start
loop
exitwhen HidMax <= 0
set HidMax = HidMax - 1
call SetItemVisible(Hid[HidMax], true)
set Hid[HidMax] = null
endloop
//Return walkability
return (X-x)*(X-x)+(Y-y)*(Y-y) <= MAX_RANGE*MAX_RANGE and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endfunction
private function Init takes nothing returns nothing
set Find = Rect(0., 0., 128., 128.)
set Item = CreateItem(DUMMY_ITEM_ID, 0, 0)
call SetItemVisible(Item, false)
endfunction
endlibrary
// Merge Sort [GUI Friendly] v1.01
// by Flux
// MODIFIED BY ZIBI
// http://www.hiveworkshop.com/forums/members/flux/
//
// Merge Sort is an efficient sorting algorithm
// that has a worst case performance of O(n logn)
// This system allows you to sort values of an array
// in either ascending or descending order
// Additionally, it this system allows you to get the
// sorted indices of the array values.
// Purely written in JASS and doesn't require anything
//
// MSort_Merge_Sort(integer <startIndex>, integer <endIndex>, boolean <ascending>) "true = rosnaco, false=malejaco"
//
// First: transfer array you wish to sort to the sorter array:
/*
set i=0 //start index
loop
exitwhen i > 3 //end index
set MSort_Values[i] = myArray[i]
set MSort_IndexInitial[i] = i
set i = i + 1
endloop
*/
// call MSort_Merge_Sort(0, 3, false) // "true = rosnaco, false=malejaco"
// sorted values are: MSort_Values[i] and its MSort_Indices[i]
globals
real array MSort_Values
real array MSort_Left
real array MSort_Right
integer array MSort_IndexInitial
integer array MSort_Indices
endglobals
function MSort_Merge takes integer leftStart, integer leftEnd, integer rightStart, integer rightEnd, boolean ascending returns nothing
local integer i = leftStart
local integer j = rightStart
local integer k = i
loop
exitwhen i > leftEnd or j > rightEnd
//if udg_MSort_Ascending then
if ascending then
if MSort_Left[i] < MSort_Right[j] then
set MSort_Values[k] = MSort_Left[i]
set MSort_Indices[k] = MSort_IndexInitial[i]
set k = k + 1
set i = i + 1
else
set MSort_Values[k] = MSort_Right[j]
set MSort_Indices[k] = MSort_IndexInitial[j]
set k = k + 1
set j = j + 1
endif
else
if MSort_Left[i] > MSort_Right[j] then
set MSort_Values[k] = MSort_Left[i]
set MSort_Indices[k] = MSort_IndexInitial[i]
set k = k + 1
set i = i + 1
else
set MSort_Values[k] = MSort_Right[j]
set MSort_Indices[k] = MSort_IndexInitial[j]
set k = k + 1
set j = j + 1
endif
endif
endloop
//Fill up remaining
loop
exitwhen i > leftEnd
set MSort_Values[k] = MSort_Left[i]
set MSort_Indices[k] = MSort_IndexInitial[i]
set k = k + 1
set i = i + 1
endloop
loop
exitwhen j > rightEnd
set MSort_Values[k] = MSort_Right[j]
set MSort_Indices[k] = MSort_IndexInitial[j]
set k = k + 1
set j = j + 1
endloop
//Update IndexInitial
set i = leftStart
loop
exitwhen i == k
set MSort_IndexInitial[i] = MSort_Indices[i]
set i = i + 1
endloop
endfunction
//Recursive Function
//function MSort_Merge_Sort takes integer start, integer end returns nothing
function MSort_Merge_Sort takes integer start, integer end, boolean ascending returns nothing
local integer i = start
local integer mid
if end - start >= 1 then
set mid = (end + start)/2
call MSort_Merge_Sort(start, mid, ascending)
call MSort_Merge_Sort(mid+1, end, ascending)
loop
exitwhen i > mid
set MSort_Left[i] = MSort_Values[i]
set i = i + 1
endloop
loop
exitwhen i > end
set MSort_Right[i] = MSort_Values[i]
set i = i + 1
endloop
call MSort_Merge(start, mid, mid+1, end, ascending)
endif
endfunction
//===========================================================================
function InitTrig_MergeSortByFlux takes nothing returns nothing
set gg_trg_MergeSortByFlux = CreateTrigger( )
endfunction
library BonusMod initializer OnInit requires optional AbilityPreload, optional xepreload
private keyword AbilityBonus
////////////////////////////////////////////////////////////////////////////////
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@ BonusMod - v3.3.1
//@=============================================================================
//@ Credits:
//@-----------------------------------------------------------------------------
//@ Written by:
//@ Earth-Fury
//@ Based on the work of:
//@ weaaddar
//@-----------------------------------------------------------------------------
//@ If you use this system, please at least credit weaaddar. Without him, this
//@ system would not exist. I would be happy if you credited me as well.
//@=============================================================================
//@ Requirements:
//@-----------------------------------------------------------------------------
//@ This library is written in vJass and thus requires JASS Helper in order to
//@ function correctly. This library also uses the ObjectMerger created by
//@ PitzerMike. The ObjectMerger must be configured as an external tool for
//@ JASS Helper.
//@
//@ All of these things are present in the NewGen world editor.
//@
//@=============================================================================
//@ Introduction:
//@-----------------------------------------------------------------------------
//@ BonusMod is a system for applying reversible bonuses to certain stats, such
//@ as attack speed or mana regen, for specific units. Most of the bonuses
//@ provided by BonusMod show green or red numbers in the command card, exactly
//@ like the bonuses provided by items.
//@
//@ BonusMod has two kinds of bonuses:
//@ 1. Ability based bonuses
//@ 2. Code based bonuses
//@
//@ All of the bonuses in the configuration section for the basic BonusMod
//@ library are ability-based bonuses. Code-based bonuses are provided by
//@ additional libraries.
//@
//@ Ability based bonuses have a limit to how much of a bonus they can apply.
//@ The actual limit depends on the number of abilities that type of bonus uses.
//@ See the "Default bonuses" section of this readme for the default limits
//@ of the bonuses that come with BonusMod. For changing the limits of the
//@ default bonuses, or for adding new types of bonuses, see the below
//@ configuration section.
//@
//@ Code based bonuses may or may not have a limit to how much of a bonus they
//@ can apply. The limits for code based bonuses depend entirely on how the
//@ bonus is implemented. See their documentation for more information.
//@
//@=============================================================================
//@ Adding BonusMod to your map:
//@-----------------------------------------------------------------------------
//@ First, you must place the BonusMod library in a custom-text trigger in your
//@ map.
//@
//@ You must then save your map with ability generation enabled. After you save
//@ your map with ability generation enabled, you must close your map in the
//@ editor, and reopen it. You can then disable ability generation.
//@ See the configuration section for information on how to enable and disable
//@ ability generation.
//@
//@=============================================================================
//@ Default bonuses:
//@-----------------------------------------------------------------------------
//@
//@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//@ | Bonus Type constants: | Minimum bonus: | Maximum bonus: |
//@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//@ | BONUS_SIGHT_RANGE | -2048 | +2047 |
//@ | BONUS_ATTACK_SPEED | -512 | +511 |
//@ | BONUS_ARMOR | -1024 | +1023 |
//@ | BONUS_MANA_REGEN_PERCENT | -512% | +511% |
//@ | BONUS_LIFE_REGEN | -256 | +255 |
//@ | BONUS_DAMAGE | -1024 | +1023 |
//@ | BONUS_STRENGTH | -256 | +255 |
//@ | BONUS_AGILITY | -256 | +255 |
//@ | BONUS_INTELLIGENCE | -256 | +255 |
//@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//@
//@ Notes:
//@ - The bonuses for stength, agility, and intelligence can only be
//@ applied to heroes. Attempting to add them to normal units will
//@ fail to work completely.
//@ - Using a negative BONUS_STRENGTH bonus can give a unit negative
//@ maximum life. Don't do that. It really messes stuff up.
//@ - Using a negative BONUS_INTELLIGENCE bonus can remove a hero's
//@ mana. This is not a big issue, as mana will return when the
//@ bonus is removed.
//@ - The maximum effective sight range for a unit is 1800.
//@ - There is a maximum attack speed. I have no idea what it is.
//@
//@ See the configuration section for information on how to change the range of
//@ bonuses, as well as how to add new ability-based bonuses, and remove unused
//@ ones.
//@
//@=============================================================================
//@ Public API / Function list:
//@-----------------------------------------------------------------------------
//@ Note that BonusMod will only output error messages if JASS Helper is set to
//@ compile in debug mode.
//@
//@ Bonus constants such as BONUS_DAMAGE have .min and .max properties which
//@ are the minimum and maximum bonus that type of bonus can apply. Note that
//@ for code based bonuses, these constants may not reflect the minimum or
//@ maximum bonus for a specific unit. Use the IsBonusValid() function to check
//@ if the given bonus value is okay for a given unit.
//@
//@ function SetUnitBonus
//@ takes unit u, Bonus bonusType, integer amount
//@ returns integer
//@
//@ This function sets the bonus of the type bonusType for the given unit to
//@ the given amount. The returned integer is the unit's actual current
//@ bonus, after it has been changed. If the given amount is above the
//@ maximum possible bonus for this type, then the maximum possible bonus
//@ is applied to the unit. The same is true if the given value is below
//@ the minimum possible bonus.
//@
//@ function GetUnitBonus
//@ takes unit u, Bonus bonusType
//@ returns integer
//@
//@ Returns the given unit's current bonus of bonusType. A value of 0 means
//@ that the given unit does not have a bonus of the given type.
//@
//@ function AddUnitBonus
//@ takes unit u, Bonus bonusType, integer amount
//@ returns integer
//@
//@ Increases the unit's bonus by the given amount. You can use a negitive
//@ amount to subtract from the unit's current bonus. Note that the same
//@ rules SetUnitBonus has apply for going over/under the maximum bonus.
//@ The returned value is the unit's actual new bonus.
//@
//@ function RemoveUnitBonus
//@ takes unit u, Bonus bonusType
//@ returns nothing
//@
//@ Sets the bonus of the type bonusType to 0 for the given unit. This
//@ function is faster then using SetUnitBonus(u, bonusType, 0).
//@
//@ function IsBonusValid
//@ takes unit u, Bonus abstractBonus, integer value
//@ returns boolean
//@
//@ Returns true if the given value is a valid bonus value for the given
//@ unit. This will also return false if the given bonus type is a hero-
//@ only bonus type, and the given unit is not a hero.
//@
//@=============================================================================
//@ Writing code-based bonuses:
//@-----------------------------------------------------------------------------
//@ This section of the readme tells you how to create your own bonus types
//@ that apply their bonuses using vJass code instead of abilities. You do not
//@ need to read or understand this to use BonusMod as-is.
//@
//@ Creating a new bonus type is simple. Extend the Bonus struct, implement the
//@ methods provided within it, and create a single instance of your struct
//@ within a variable named BONUS_YOUR_BONUS_TYPES_NAME of the type Bonus.
//@
//@ The methods you must implement are:
//@
//@ method setBonus takes unit u, integer amount returns integer
//@ This method sets the given unit's current bonus to amount, returning
//@ the actual bonus that was applied. If the given amount is higher then
//@ the maximum amount your bonus type can apply to a unit, you must apply
//@ the maximum possible bonus, and return that amount. The same holds true
//@ for the minimum bonus.
//@
//@ method getBonus takes unit u returns integer
//@ This method returns the current bonus the given unit has.
//@
//@ method removeBonus takes unit u returns nothing
//@ This method sets the current bonus of the given unit to 0.
//@
//@ method isValueInRange takes integer value returns boolean
//@ This method returns true if the given integer is a valid bonus amount
//@ for this bonus type, and false otherwise.
//@
//@ Note that it is your responsibility to do any clean up in the event a unit
//@ dies or is removed with an active bonus on it. There is no guarantee that
//@ removeBonus() will be called before a unit dies or is removed.
//@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
////////////////////////////////////////////////////////////////////////////////
//==============================================================================
// Configuration:
//==============================================================================
//------------------------------------------------------------------------------
// If the following constant is set to true, the abilities used by this library
// will be preloaded at map initialization. This will slightly increase loading
// time, but will prevent a slight to medium lag spike the first time a bonus
// of a type is applied.
//
// Note that your map must contain either the xepreload library, or the
// AbilityPreload library for preloading to work.
//
// It is highly recommended that you do not set this to false.
//------------------------------------------------------------------------------
globals
private constant boolean PRELOAD_ABILITIES = false
endglobals
//------------------------------------------------------------------------------
// The BonusMod_BeginBonuses macro takes a single boolean type parameter.
// If set to true, bonus abilities will be created (or recreated) on save.
// If set to false, abilities will not be generated.
//
// If you modify any of the bonus declaration macros, or add new ones, you must
// regenerate abilities.
//
// Note that if you remove a bonus, the abilities it had created will not be
// automatically removed. This is also true of reducing the number of abilities
// a bonus uses.
//
// After you generate abilities, you must close your map and reopen it in the
// editor. You can then disable ability generation until the next time you
// modify the bonus types.
//------------------------------------------------------------------------------
//! runtextmacro BonusMod_BeginBonuses("false")
//--------------------------------------------------------------------------
// Below are where bonus types are defined.
//
// The first parameter is the name of the bonus type. A constant will be
// generated for each bonus type, that will take the form: BONUS_NAME
//
// The second parameter is the maximum power of 2 the bonus type can add
// to a unit. For example, 8 abilities gives a range of -256 to +255.
//
// The third parameter is the base ability. The base ability must give the
// desired effect when the given field is changed.
//
// The fourth parameter is the rawcode prefix of the bonuses generated
// abilities. The prefix must be 3 characters long. Your map must not
// already contain bonuses which start with the given prefix.
//
// The fifth parameter is the object field to modify for each generated
// ability.
//
// The sixth parameter must be true of the bonus should only work on hero
// units, and false otherwise.
//
// The final parameter is the icon that will be displayed in the object
// editor. This has no effect on anything ingame.
//--------------------------------------------------------------------------
// | NAME |ABILITY|SOURCE |PREFIX|FIELD | HERO | ICON
// | | COUNT |ABILITY| | | ONLY |
//! runtextmacro BonusMod_DeclareBonus("ARMOR", "10", "AId1", "(A)", "Idef", "false", "BTNHumanArmorUpOne.blp")
//! runtextmacro BonusMod_DeclareBonus("DAMAGE", "14", "AItg", "(B)", "Iatt", "false", "BTNSteelMelee.blp")
//! runtextmacro BonusMod_DeclareBonus("SIGHT_RANGE", "10", "AIsi", "(C)", "Isib", "false", "BTNTelescope.blp")
//! runtextmacro BonusMod_DeclareBonus("LIFE_REGEN", "11", "Arel", "(E)", "Ihpr", "false", "BTNRingSkull.blp")
//! runtextmacro BonusMod_DeclareBonus("STRENGTH", "11", "AIa1", "(F)", "Istr", "true" , "BTNGoldRing.blp")
//! runtextmacro BonusMod_DeclareBonus("AGILITY", "11", "AIa1", "(G)", "Iagi", "true" , "BTNGoldRing.blp")
//! runtextmacro BonusMod_DeclareBonus("INTELLIGENCE", "11", "AIa1", "(H)", "Iint", "true" , "BTNGoldRing.blp")
// | NAME |ABILITY|SOURCE |PREFIX|FIELD |HERO | ICON
// | | COUNT |ABILITY| | | ONLY |
//! runtextmacro BonusMod_DeclarePercentBonus("ATTACK_SPEED", "10", "AIsx", "(I)", "Isx1", "false", "BTNGlove.blp")
//! runtextmacro BonusMod_DeclarePercentBonus("MANA_REGEN_PERCENT", "10", "AIrm", "(D)", "Imrp", "false", "BTNSobiMask.blp")
//! runtextmacro BonusMod_EndBonuses()
//==============================================================================
// End of configuration
//==============================================================================
//! textmacro BonusMod_BeginBonuses takes SHOULD_GENERATE_ABILITIES
private function Setup takes nothing returns nothing
// The following is a lua script for the ObjectMerger, used to generate abilities
//*
// ! externalblock extension=lua ObjectMerger $FILENAME$
//! i if "$SHOULD_GENERATE_ABILITIES$" == "true" then
//! i function FormatName(name)
//! i name = string.lower(name)
//! i name = string.gsub(name, "_", " ")
//! i s = name
//! i name = ""
//! i for w in string.gmatch(s, "%a%w*") do
//! i name = name .. string.upper(string.sub(w, 1, 1)) .. string.sub(w, 2, -1)
//! i name = name .. " "
//! i end
//! i name = string.sub(name, 1, string.len(name) - 1)
//! i return name
//! i end
//! i function SetupAbility(name, suffix, icon, hero)
//! i makechange(current, "anam", "BonusMod - " .. FormatName(name))
//! i makechange(current, "ansf", "(" .. suffix .. ")")
//! i makechange(current, "aart", "ReplaceableTextures\\CommandButtons\\" .. icon)
//! i makechange(current, "aite", 0)
//! i if hero then
//! i makechange(current, "Iagi", 1, 0)
//! i makechange(current, "Iint", 1, 0)
//! i makechange(current, "Istr", 1, 0)
//! i end
//! i end
//! i function CreateAbility(sourceAbility, prefix, field, abilityCount, name, icon)
//! i powOf2 = abilityCount - 1
//! i lengthOfMax = string.len(tostring(2^abilityCount))
//! i for i = 0, powOf2 do
//! i padding = ""
//! i for k = 0, lengthOfMax - string.len(tostring(2^i)) - 1 do
//! i padding = padding .. "0"
//! i end
//! i createobject(sourceAbility, prefix .. string.sub(chars, i + 1, i + 1))
//! i SetupAbility(name, "+" .. padding .. tostring(2 ^ i), icon, true)
//! i makechange(current, field, 1, tostring(2^i))
//! i end
//! i createobject(sourceAbility, prefix .. "-")
//! i SetupAbility(name, "-" .. tostring(2 ^ abilityCount), icon, true)
//! i makechange(current, field, 1, tostring(-(2^abilityCount)))
//! i end
//! i function CreatePercentageAbility(sourceAbility, prefix, field, abilityCount, name, icon)
//! i powOf2 = abilityCount - 1
//! i lengthOfMax = string.len(tostring(2^abilityCount))
//! i for i = 0, powOf2 do
//! i padding = ""
//! i for k = 0, lengthOfMax - string.len(tostring(2^i)) - 1 do
//! i padding = padding .. "0"
//! i end
//! i createobject(sourceAbility, prefix .. string.sub(chars, i + 1, i + 1))
//! i SetupAbility(name, "+" .. padding .. tostring(2 ^ i) .. "%", icon, false)
//! i makechange(current, field, 1, tostring((2 ^ i) / 100))
//! i end
//! i createobject(sourceAbility, prefix .. "-")
//! i SetupAbility(name, "-" .. tostring(2 ^ abilityCount) .. "%", icon, false)
//! i makechange(current, field, 1, tostring(-((2 ^ abilityCount) / 100)))
//! i end
//! i setobjecttype("abilities")
//! i chars = "abcdefghijklmnopqrstuvwxyz"
//! i
// */
//! endtextmacro
//! textmacro BonusMod_DeclareBonus takes NAME, ABILITY_COUNT, SOURCE_ABILITY, RAWCODE_PREFIX, FIELD, HERO_ONLY, ICON
//! i CreateAbility("$SOURCE_ABILITY$", "$RAWCODE_PREFIX$", "$FIELD$", $ABILITY_COUNT$, "$NAME$", "$ICON$")
globals
Bonus BONUS_$NAME$
endglobals
set BONUS_$NAME$ = AbilityBonus.create('$RAWCODE_PREFIX$a', $ABILITY_COUNT$, '$RAWCODE_PREFIX$-', $HERO_ONLY$)
//! endtextmacro
//! textmacro BonusMod_DeclarePercentBonus takes NAME, ABILITY_COUNT, SOURCE_ABILITY, RAWCODE_PREFIX, FIELD, HERO_ONLY, ICON
//! i CreatePercentageAbility("$SOURCE_ABILITY$", "$RAWCODE_PREFIX$", "$FIELD$", $ABILITY_COUNT$, "$NAME$", "$ICON$")
globals
Bonus BONUS_$NAME$
endglobals
set BONUS_$NAME$ = AbilityBonus.create('$RAWCODE_PREFIX$a', $ABILITY_COUNT$, '$RAWCODE_PREFIX$-', $HERO_ONLY$)
//! endtextmacro
//! textmacro BonusMod_EndBonuses
//*
//! i end
// ! endexternalblock
// */
endfunction
//! endtextmacro
// ===
// Precomputed integer powers of 2
// ===
globals
private integer array powersOf2
private integer powersOf2Count = 0
endglobals
// ===
// Utility functions
// ===
private function ErrorMsg takes string func, string s returns nothing
call BJDebugMsg("|cffFF0000BonusMod Error|r|cffFFFF00:|r |cff8080FF" + func + "|r|cffFFFF00:|r " + s)
endfunction
private function LoadAbility takes integer abilityId returns nothing
static if PRELOAD_ABILITIES then
static if LIBRARY_xepreload then
call XE_PreloadAbility(abilityId)
else
static if LIBRARY_AbilityPreload then
call AbilityPreload(abilityId)
endif
endif
endif
endfunction
// ===
// Bonus Types
// ===
private interface BonusInterface
integer minBonus = 0
integer maxBonus = 0
private method destroy takes nothing returns nothing defaults nothing
endinterface
private keyword isBonusObject
struct Bonus extends BonusInterface
boolean isBonusObject = false
public static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set this.isBonusObject = true
return this
endmethod
stub method setBonus takes unit u, integer amount returns integer
debug call ErrorMsg("Bonus.setBonus()", "I have no idea how or why you did this, but don't do it.")
return 0
endmethod
stub method getBonus takes unit u returns integer
debug call ErrorMsg("Bonus.getBonus()", "I have no idea how or why you did this, but don't do it.")
return 0
endmethod
stub method removeBonus takes unit u returns nothing
call this.setBonus(u, 0)
endmethod
stub method isValidBonus takes unit u, integer value returns boolean
return true
endmethod
method operator min takes nothing returns integer
return this.minBonus
endmethod
method operator max takes nothing returns integer
return this.maxBonus
endmethod
endstruct
private struct AbilityBonus extends Bonus
public integer count
public integer rawcode
public integer negativeRawcode
public integer minBonus = 0
public integer maxBonus = 0
public boolean heroesOnly
public static method create takes integer rawcode, integer count, integer negativeRawcode, boolean heroesOnly returns thistype
local thistype bonus = thistype.allocate()
local integer i
debug local boolean error = false
// Error messages
static if DEBUG_MODE then
if rawcode == 0 then
call ErrorMsg("AbilityBonus.create()", "Bonus constructed with a rawcode of 0?!")
call bonus.destroy()
return 0
endif
if count < 0 or count == 0 then
call ErrorMsg("AbilityBonus.create()", "Bonus constructed with an ability count <= 0?!")
call bonus.destroy()
return 0
endif
endif
// Grow powers of 2
if powersOf2Count < count then
set i = powersOf2Count
loop
exitwhen i > count
set powersOf2[i] = 2 * powersOf2[i - 1]
set i = i + 1
endloop
set powersOf2Count = count
endif
// Preload this bonus' abilities
static if PRELOAD_ABILITIES then
set i = 0
loop
exitwhen i == count
call LoadAbility(rawcode + i)
set i = i + 1
endloop
if negativeRawcode != 0 then
call LoadAbility(negativeRawcode)
endif
endif
// Set up this bonus object
set bonus.count = count
set bonus.negativeRawcode = negativeRawcode
set bonus.rawcode = rawcode
set bonus.heroesOnly = heroesOnly
// Calculate the minimum and maximum bonuses
if negativeRawcode != 0 then
set bonus.minBonus = -powersOf2[count]
else
set bonus.minBonus = 0
endif
set bonus.maxBonus = powersOf2[count] - 1
// Return the bonus object
return bonus
endmethod
// Interface methods:
method setBonus takes unit u, integer amount returns integer
return SetUnitBonus.evaluate(u, this, amount)
endmethod
method getBonus takes unit u returns integer
return GetUnitBonus.evaluate(u, this)
endmethod
method removeBonus takes unit u returns nothing
call RemoveUnitBonus.evaluate(u, this)
endmethod
public method isValidBonus takes unit u, integer value returns boolean
return (value >= this.minBonus) and (value <= this.maxBonus)
endmethod
endstruct
// ===
// Public API
// ===
function IsBonusValid takes unit u, Bonus abstractBonus, integer value returns boolean
local AbilityBonus bonus = AbilityBonus(abstractBonus)
static if DEBUG_MODE then
if not abstractBonus.isBonusObject then
call ErrorMsg("IsBonusValid()", "Invalid bonus type given")
endif
endif
if abstractBonus.min > value or abstractBonus.max < value then
return false
endif
if abstractBonus.getType() != AbilityBonus.typeid then
return abstractBonus.isValidBonus(u, value)
endif
if bonus.heroesOnly and not IsUnitType(u, UNIT_TYPE_HERO) then
return false
endif
return (value >= bonus.minBonus) and (value <= bonus.maxBonus)
endfunction
function RemoveUnitBonus takes unit u, Bonus abstractBonus returns nothing
local integer i = 0
local AbilityBonus bonus = AbilityBonus(abstractBonus)
static if DEBUG_MODE then
if not abstractBonus.isBonusObject then
call ErrorMsg("RemoveUnitBonus()", "Invalid bonus type given")
endif
endif
if abstractBonus.getType() != AbilityBonus.typeid then
call abstractBonus.removeBonus(u)
return
endif
if bonus.heroesOnly and not IsUnitType(u, UNIT_TYPE_HERO) then
debug call ErrorMsg("RemoveUnitBonus()", "Trying to remove a hero-only bonus from a non-hero unit")
return
endif
call UnitRemoveAbility(u, bonus.negativeRawcode)
loop
exitwhen i == bonus.count
call UnitRemoveAbility(u, bonus.rawcode + i)
set i = i + 1
endloop
endfunction
function SetUnitBonus takes unit u, Bonus abstractBonus, integer amount returns integer
local integer i
local integer output = 0
local AbilityBonus bonus = AbilityBonus(abstractBonus)
local boolean applyMinBonus = false
static if DEBUG_MODE then
if not abstractBonus.isBonusObject then
call ErrorMsg("SetUnitBonus()", "Invalid bonus type given")
endif
endif
if amount == 0 then
call RemoveUnitBonus(u, bonus)
return 0
endif
if abstractBonus.getType() != AbilityBonus.typeid then
return abstractBonus.setBonus(u, amount)
endif
if bonus.heroesOnly and not IsUnitType(u, UNIT_TYPE_HERO) then
debug call ErrorMsg("SetUnitBonus()", "Trying to set a hero-only bonus on a non-hero unit")
return 0
endif
if amount < bonus.minBonus then
debug call ErrorMsg("SetUnitBonus()", "Attempting to set a bonus to below its min value")
set amount = bonus.minBonus
elseif amount > bonus.maxBonus then
debug call ErrorMsg("SetUnitBonus()", "Attempting to set a bonus to above its max value")
set amount = bonus.maxBonus
endif
if amount < 0 then
set amount = -(bonus.minBonus - amount)
set applyMinBonus = true
endif
call UnitRemoveAbility(u, bonus.negativeRawcode)
set i = bonus.count - 1
loop
exitwhen i < 0
if amount >= powersOf2[i] then
call UnitAddAbility(u, bonus.rawcode + i)
call UnitMakeAbilityPermanent(u, true, bonus.rawcode + i)
static if DEBUG_MODE then
if GetUnitAbilityLevel(u, bonus.rawcode + i) <= 0 then
call ErrorMsg("SetUnitBonus()", "Failed to give the 2^" + I2S(i) + " ability to the unit!")
endif
endif
set amount = amount - powersOf2[i]
set output = output + powersOf2[i]
else
call UnitRemoveAbility(u, bonus.rawcode + i)
static if DEBUG_MODE then
if GetUnitAbilityLevel(u, bonus.rawcode + i) > 0 then
call ErrorMsg("SetUnitBonus()", "Unit still has the 2^" + I2S(i) + " ability after it was removed!")
endif
endif
endif
set i = i - 1
endloop
if applyMinBonus then
call UnitAddAbility(u, bonus.negativeRawcode)
call UnitMakeAbilityPermanent(u, true, bonus.negativeRawcode)
else
call UnitRemoveAbility(u, bonus.negativeRawcode)
endif
return output
endfunction
function GetUnitBonus takes unit u, Bonus abstractBonus returns integer
local integer i = 0
local integer amount = 0
local AbilityBonus bonus = AbilityBonus(abstractBonus)
static if DEBUG_MODE then
if not abstractBonus.isBonusObject then
call ErrorMsg("GetUnitBonus()", "Invalid bonus type given")
endif
endif
if abstractBonus.getType() != AbilityBonus.typeid then
return abstractBonus.getBonus(u)
endif
if bonus.heroesOnly and not IsUnitType(u, UNIT_TYPE_HERO) then
debug call ErrorMsg("GetUnitBonus()", "Trying to get a hero-only bonus from a non-hero unit")
return 0
endif
if GetUnitAbilityLevel(u, bonus.negativeRawcode) > 0 then
set amount = bonus.minBonus
endif
loop
exitwhen i == bonus.count
if GetUnitAbilityLevel(u, bonus.rawcode + i) > 0 then
set amount = amount + powersOf2[i]
endif
set i = i + 1
endloop
return amount
endfunction
function AddUnitBonus takes unit u, Bonus bonus, integer amount returns integer
return SetUnitBonus(u, bonus, GetUnitBonus(u, bonus) + amount)
endfunction
// ===
// Initialization
// ===
private function OnInit takes nothing returns nothing
local integer i
// Set up powers of 2
set powersOf2[0] = 1
set powersOf2Count = 1
static if DEBUG_MODE and PRELOAD_ABILITIES and not LIBRARY_xepreload and not LIBRARY_AbilityPreload then
call ErrorMsg("Initialization", "PRELOAD_ABILITIES is set to true, but neither usable preloading library is detected")
endif
// Setup bonuses
call Setup()
endfunction
endlibrary
library MovementModifier initializer Init //ver 1.07 by ZibiTheWand3r3r, 18-08-2018
// Allows to change unit's movement speed for given duration (or permanent)
// All Object Editor abilities [that changing move speed] will work with this system - they stack.
// System's bonuses also stack.
// ********************************
// ==> Requires Unit Event
// https://www.hiveworkshop.com/threads/gui-unit-event-v2-5-2-0.201641/
// ********************************
// ==> Applying move speed bonus:
// UnitAddMoveSpeedBonus(unit u, real percentBonus, real flatBonus, real duration)
// u - unit whos move speed will be changed
// percentBonus - positive to increase speed, negative to slow a target (use 0.00 to not apply percent bonus)
// bonus will be added as percent (like Endurance Aura for example)
// flatBonus - positive to increase speed, negative to slow a target (use 0.00 to not apply flat bonus)
// bonus will be added like item's Boots of Speed for example
// duration - how long bonus will be on unit, [use duration = 0.00 to make bonus permanent]
// both percentBonus and flatBonus can be used in one function call -- or use one chosen bonus only
// ==> Removing timed movespeed bonuses:
// UnitRemoveMoveSpeedBonuses(unit u, boolean removePositiveBonuses, boolean removeNegativeBonuses)
// u - unit whos timed bonuses will be removed
// removePositiveBonuses - if "true" _all_ positive timed bonuses (bonus>0.00) will be removed
// removeNegativeBonuses - if "true" _all_ negative timed bonuses (bonus<0.00) will be removed
// ==> Usage examples:
// Speed up unit u: +45% move speed for 12sec: call UnitAddMoveSpeedBonus(u, 0.45, 0.00, 12.00)
// Speed up unit u: +120 flat move speed for ever: call UnitAddMoveSpeedBonus(u, 0.00, 120, 0.00)
// Slow unit u: -15%(percent) and -20(flat) for 7sec: call UnitAddMoveSpeedBonus(u, -0.15, -20.00, 7.00)
// Remove *all negative* move speed bonuses: call UnitRemoveMoveSpeedBonuses(u, false, true)
// Remove *all positive* move speed bonuses: call UnitRemoveMoveSpeedBonuses(u, true, false)
// Remove _all_ (negative and positive) move speed bonuses: call UnitRemoveMoveSpeedBonuses(u, true, true)
// how bonuses are calculated:
// moveSpeed = (GetUnitDefaultMoveSpeed(u) + flatBonus) * (1 + percentageBonus1 + percentageBonus2 + etc)
globals
// configuration:
private constant real INTERVAL = 0.50 //How precise is timed applied movespeed change, for greater accuracy use lower value like 0.20 or 0.10
private constant boolean PERSISTS_THROUGH_DEATH = true // if "true" then unit/hero's death will not end up applied bonus
// Set to "false" to end bonus-instance upon unit's death. Above boolean will affect only timed bonuses.
// end of configuration ----------------------------------------------------------------------------
private real array totalFlat // total flat bonus [targetId] => binded to target unit
private real array totalPercent // total percent bonus [targetId]
private boolean array instanceIsBonusPositive // [id] => connected to spell instance
private real array instanceBonus // bonus [id]
private real array instanceDuration // duration [id]
private unit array instanceTarget // target [id]
private boolean array instanceIsBonusFlat // [id]
private integer instanceId = 0
private timer t = CreateTimer()
endglobals
//--------------------------------------------------------------------
native UnitAlive takes unit id returns boolean
//--------------------------------------------------------------------
private function Loop takes nothing returns nothing
local integer id=1
local integer targetId
loop
exitwhen id>instanceId
set instanceDuration[id] = instanceDuration[id] - INTERVAL //when spell expires:
if instanceDuration[id] <= 0.00 or ((not PERSISTS_THROUGH_DEATH) and (not UnitAlive(instanceTarget[id]))) then
//revert:
set targetId = GetUnitUserData(instanceTarget[id])
if instanceIsBonusFlat[id] then
set totalFlat[targetId] = totalFlat[targetId] - instanceBonus[id] //minus specific flat bonus
else
set totalPercent[targetId] = totalPercent[targetId] - instanceBonus[id] //minus specific % bonus
endif
call SetUnitMoveSpeed(instanceTarget[id], (GetUnitDefaultMoveSpeed(instanceTarget[id]) + totalFlat[targetId])*(1+totalPercent[targetId]))
//dealloc: /move data from max to current/
set instanceIsBonusPositive[id] = instanceIsBonusPositive[instanceId]
set instanceBonus[id] = instanceBonus[instanceId]
set instanceDuration[id] = instanceDuration[instanceId]
set instanceTarget[id] = instanceTarget[instanceId]
set instanceIsBonusFlat[id] = instanceIsBonusFlat[instanceId]
set instanceTarget[instanceId] = null
set instanceId=instanceId-1
set id=id-1
if instanceId==0 then
call PauseTimer(t)
endif
endif
set id=id+1
endloop
endfunction
//--------------------------------------------------------------------
private function UnitAddMoveSpeedBonus_Ex takes unit u, real bonus, boolean isFlatBonus, real duration returns nothing
local integer targetId = GetUnitUserData(u)
//common part:
if isFlatBonus then
set totalFlat[targetId] = totalFlat[targetId] + bonus //add flat bonus
else
set totalPercent[targetId] = totalPercent[targetId] + bonus //add % bonus
endif
call SetUnitMoveSpeed(u, (GetUnitDefaultMoveSpeed(u) + totalFlat[targetId])*(1+totalPercent[targetId]))
//permanent:
if duration==0.00 then
return
endif
//timed:
set instanceId = instanceId + 1
set instanceTarget[instanceId] = u
set instanceDuration[instanceId] = duration
set instanceIsBonusFlat[instanceId] = isFlatBonus
set instanceIsBonusPositive[instanceId] = bonus>0.00
set instanceBonus[instanceId] = bonus
if instanceId==1 then
call TimerStart(t, INTERVAL, true, function Loop)
endif
endfunction
//--------------------------------------------------------------------
//--------------------------------------------------------------------
function UnitAddMoveSpeedBonus takes unit u, real percentBonus, real flatBonus, real duration returns nothing
if not (u==null or (not UnitAlive(u)) or duration<0.00 or (percentBonus==0.00 and flatBonus==0.00)) then //<=protection
if percentBonus != 0.00 then
call UnitAddMoveSpeedBonus_Ex(u, percentBonus, false, duration)
endif
if flatBonus != 0.00 then
call UnitAddMoveSpeedBonus_Ex(u, flatBonus, true, duration)
endif
endif
endfunction
//-----------------------------------------------------------------------------------
// ==> Removing timed movespeed bonuses
function UnitRemoveMoveSpeedBonuses takes unit u, boolean removePositiveBonuses, boolean removeNegativeBonuses returns nothing
local integer id=1
loop
exitwhen id>instanceId
if u == instanceTarget[id] then
if removePositiveBonuses and instanceIsBonusPositive[id] then
set instanceDuration[id] = 0.00
endif
if removeNegativeBonuses and (not instanceIsBonusPositive[id]) then
set instanceDuration[id] = 0.00
endif
endif
set id=id+1
endloop
call Loop()
endfunction
//-----------------------------------------------------------------------------------
// Units that changing their form (metamorphosis, chamical rage, destroyer form, bear form etc)
// will lose their move speed bonuses comes from SetUnitMoveSpeed.
// To prevent that: after unit transforms to new unit-type this function must be called:
function Trig_UnitUpdateMoveSpeedBonusAfterMorph takes nothing returns boolean
local integer targetId = GetUnitUserData(udg_UDexUnits[udg_UDex])
call SetUnitMoveSpeed(udg_UDexUnits[udg_UDex], (GetUnitDefaultMoveSpeed(udg_UDexUnits[udg_UDex]) + totalFlat[targetId])*(1+totalPercent[targetId]))
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitTypeEvent", EQUAL, 1.00)
call TriggerAddCondition(t, function Trig_UnitUpdateMoveSpeedBonusAfterMorph)
set t=null
endfunction
endlibrary
// API:
// UnitAddBonus( unit <u>, integer <bonusType>, integer <amount>)
// UnitAddBonusTimed( unit <u>, integer <bonusType>, integer <amount>, real <duration>)
// UnitImmediateOrderAfterDelay(unit <u>, integer <or>, real <delay>)
// AddTimedEffectTarget( unit <u>, real <duration>, string <attPoint>, string <eff>)
// AddTimedEffect( real <x>, real <y>, real <duration>, string <eff>)
// UnitRemoveAbilityDelayed( unit <u>, integer <abilityId>, real <removeAfterXseconds>)
// UnitAddAbilityTimed( unit <u>, integer <abilityId>, integer <abilityLevel>, real <time>)
// UnitAddTypeTimed(unit <u>, unitType <classification>, real <time>)
//===========================================
//===== BONUS MOD TIMED ========================
//===========================================
// bonunes from library BonusMod (integers):
// BONUS_ARMOR (1), BONUS_DAMAGE (2), BONUS_SIGHT_RANGE (3), BONUS_LIFE_REGEN (4),
// BONUS_STRENGTH (5), BONUS_AGILITY (6), BONUS_INTELLIGENCE (7),
// BONUS_ATTACK_SPEED (8), BONUS_MANA_REGEN_PERCENT (9)
// BONUS_MAX_LIFE (10), BONUS_MAX_MANA (11)
// KEY_WEAPON_MOVEMENT (12)
globals
constant integer BONUS_MAX_LIFE = 10
constant integer BONUS_MAX_MANA = 11
constant integer KEY_WEAPON_MOVEMENT = 12 // connection weapon-->move speed
hashtable g_timedHash = InitHashtable() // used only by "Timed" system
//*************************************************************
// for Timed Ability, Timed Effect and Timed BonusMod
constant integer KEY_REMOVE_ABILITY_DELAYED_UNIT = 200
constant integer KEY_REMOVE_ABILITY_DELAYED_ABIL = 201
constant integer KEY_TIMED_EFFECT_UNIT = 202
constant integer KEY_TIMED_EFFECT_EFFECT = 203
constant integer KEY_TIMED_EFFECT_DURATION = 204
constant integer KEY_BONUSMODTIMED_UNIT = 205
constant integer KEY_BONUSMODTIMED_TYPE = 206
constant integer KEY_BONUSMODTIMED_AMOUNT = 207
constant integer KEY_BONUSMODTIMED_DURATION = 208
constant integer KEY_TIMED_CLASSIFICATION_UNIT = 209
constant integer KEY_TIMED_CLASSIFICATION_INTEGER = 210
constant integer KEY_UNIT_ORD_U = 211
constant integer KEY_UNIT_ORD_O = 212
//*************************************************************
endglobals
function UnitAddBonus takes unit u, integer bonusType, integer amount returns nothing
local real percent = 0.00 //due to Blizz bug, we must update current unit hp/mana
if u==null then
return
endif
if bonusType == BONUS_MAX_LIFE then
set percent = GetWidgetLife(u) / I2R(BlzGetUnitMaxHP(u)) //for 1.29.2 new natives
call BlzSetUnitMaxHP(u, BlzGetUnitMaxHP(u)+amount)
call SetWidgetLife(u, I2R(BlzGetUnitMaxHP(u)) * percent)
elseif bonusType == BONUS_MAX_MANA then
set percent = GetUnitState(u, UNIT_STATE_MANA) / I2R(BlzGetUnitMaxMana(u))
call BlzSetUnitMaxMana(u, BlzGetUnitMaxMana(u)+amount)
call SetUnitState(u, UNIT_STATE_MANA, I2R(BlzGetUnitMaxMana(u)) * percent)
elseif bonusType == KEY_WEAPON_MOVEMENT then //suports only flat movement bonus (for WeaponItems)
call UnitAddMoveSpeedBonus(u, 0.00, I2R(amount), 0.00)
else
call AddUnitBonus(u, bonusType, amount)
endif
endfunction
//------------------------------------------------------------------------------------------------------------
function UnitAddBonusTimed_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
local unit u = LoadUnitHandle(g_timedHash, h_id, KEY_BONUSMODTIMED_UNIT)
local integer bonusType = LoadInteger(g_timedHash, h_id, KEY_BONUSMODTIMED_TYPE)
local integer amount = LoadInteger(g_timedHash, h_id, KEY_BONUSMODTIMED_AMOUNT)
call UnitAddBonus(u, bonusType, -amount)
call FlushChildHashtable(g_timedHash, h_id)
call DestroyTimer(t)
set t = null
set u=null
endfunction
// unit's death will NOT cancel timed bonus (only duration)
function UnitAddBonusTimed takes unit u, integer bonusType, integer amount, real duration returns nothing
local timer t
local integer h_id
if duration>0.00 and UnitAlive(u) and bonusType>=1 and bonusType<=11 then
set t=CreateTimer()
set h_id=GetHandleId(t)
call UnitAddBonus(u, bonusType, amount)
call SaveUnitHandle(g_timedHash, h_id, KEY_BONUSMODTIMED_UNIT, u)
call SaveInteger(g_timedHash, h_id, KEY_BONUSMODTIMED_TYPE, bonusType)
call SaveInteger(g_timedHash, h_id, KEY_BONUSMODTIMED_AMOUNT, amount)
call TimerStart(t, duration, false, function UnitAddBonusTimed_Child)
endif
set t=null
endfunction
//--------------------------------------------------------------------------------------------
function UnitImmediateOrderAfterDelay_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
local unit u = LoadUnitHandle(g_timedHash, h_id, KEY_UNIT_ORD_U)
local integer ord = LoadInteger(g_timedHash, h_id, KEY_UNIT_ORD_O)
call IssueImmediateOrderById(u, ord)
call FlushChildHashtable(g_timedHash, h_id)
call DestroyTimer(t)
set t = null
set u=null
endfunction
//unit order after delay
function UnitImmediateOrderAfterDelay takes unit u, integer ord, real delay returns nothing
local timer t
local integer h_id
if UnitAlive(u) and delay>=0.00 then
set t=CreateTimer()
set h_id=GetHandleId(t)
call SaveUnitHandle(g_timedHash, h_id, KEY_UNIT_ORD_U, u)
call SaveInteger(g_timedHash, h_id, KEY_UNIT_ORD_O, ord)
call TimerStart(t, delay, false, function UnitImmediateOrderAfterDelay_Child)
endif
set t=null
endfunction
//=======================================================
//=========== TIMED EFFECT =================================
//=======================================================
function AddTimedEffectTarget_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
local unit u = LoadUnitHandle(g_timedHash, h_id, KEY_TIMED_EFFECT_UNIT)
local real durationLeft=LoadReal(g_timedHash, h_id, KEY_TIMED_EFFECT_DURATION) - 1.00
call SaveReal(g_timedHash, h_id, KEY_TIMED_EFFECT_DURATION, durationLeft)
if durationLeft<=0.00 or not UnitAlive(u) then
set bj_lastCreatedEffect=LoadEffectHandle(g_timedHash, h_id, KEY_TIMED_EFFECT_EFFECT)
call DestroyEffect(bj_lastCreatedEffect)
//---
call FlushChildHashtable(g_timedHash, h_id)
call PauseTimer(t)
call DestroyTimer(t)
endif
set t = null
set u=null
endfunction
function AddTimedEffectTarget takes unit u, real duration, string attPoint, string eff returns nothing
local timer t=CreateTimer()
set bj_lastCreatedEffect=AddSpecialEffectTarget(eff, u, attPoint)
call SaveUnitHandle(g_timedHash, GetHandleId(t), KEY_TIMED_EFFECT_UNIT, u)
call SaveEffectHandle(g_timedHash, GetHandleId(t), KEY_TIMED_EFFECT_EFFECT, bj_lastCreatedEffect)
call SaveReal(g_timedHash, GetHandleId(t), KEY_TIMED_EFFECT_DURATION, duration)
call TimerStart(t, 1.00, true, function AddTimedEffectTarget_Child)
set t=null
endfunction
//-------------------------------------------------------------------------------------------------
function AddTimedEffect_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
set bj_lastCreatedEffect=LoadEffectHandle(g_timedHash, h_id, KEY_TIMED_EFFECT_EFFECT)
call DestroyEffect(bj_lastCreatedEffect)
call FlushChildHashtable(g_timedHash, h_id)
call DestroyTimer(t)
set t = null
endfunction
function AddTimedEffect takes real x, real y, real duration, string eff returns nothing
local timer t=CreateTimer()
set bj_lastCreatedEffect=AddSpecialEffect(eff, x, y)
call SaveEffectHandle(g_timedHash, GetHandleId(t), KEY_TIMED_EFFECT_EFFECT, bj_lastCreatedEffect)
call TimerStart(t, duration, false, function AddTimedEffect_Child)
set t=null
endfunction
//==============================================================
//===== TIMED ABILITY ==============================================
//==============================================================
function UnitRemoveAbilityDelayed_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
local unit u = LoadUnitHandle(g_timedHash, h_id, KEY_REMOVE_ABILITY_DELAYED_UNIT)
local integer abilityId = LoadInteger(g_timedHash, h_id, KEY_REMOVE_ABILITY_DELAYED_ABIL)
call UnitRemoveAbility(u, abilityId)
call FlushChildHashtable(g_timedHash, h_id)
call DestroyTimer(t)
set t = null
set u=null
endfunction
function UnitRemoveAbilityDelayed takes unit u, integer abilityId, real removeAfterXseconds returns nothing
local timer t=CreateTimer()
call SaveUnitHandle(g_timedHash, GetHandleId(t), KEY_REMOVE_ABILITY_DELAYED_UNIT, u)
call SaveInteger(g_timedHash, GetHandleId(t), KEY_REMOVE_ABILITY_DELAYED_ABIL, abilityId)
call TimerStart(t, removeAfterXseconds, false, function UnitRemoveAbilityDelayed_Child)
set t=null
endfunction
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
function UnitAddAbilityTimed takes unit u, integer abilityId, integer abilityLevel, real time returns nothing
call UnitAddAbility(u, abilityId)
call SetUnitAbilityLevel(u, abilityId, abilityLevel)
call UnitRemoveAbilityDelayed(u, abilityId, time)
endfunction
//----------------------------------------------------------------------------------------------------------------------
//-------------------TIMED CLASSIFICATION ----------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
function GetIntegerFromUnittype takes unittype classification returns integer
local integer i=0
local boolean found=false
loop
exitwhen i>=30
if ConvertUnitType(i)==classification then
set found=true
exitwhen true
endif
set i=i+1
endloop
if found then
return i
endif
call BJDebugMsg("GetIntegerFromUnittype function fails !")
return 0
endfunction
function UnitAddTypeTimed_Child takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer h_id=GetHandleId(t)
local unit u = LoadUnitHandle(g_timedHash, h_id, KEY_TIMED_CLASSIFICATION_UNIT)
local integer i = LoadInteger(g_timedHash, h_id, KEY_TIMED_CLASSIFICATION_INTEGER)
call UnitRemoveType(u, ConvertUnitType(i))
call FlushChildHashtable(g_timedHash, h_id)
call DestroyTimer(t)
set t = null
set u=null
endfunction
function UnitAddTypeTimed takes unit u, unittype classification, real time returns nothing
local timer t=CreateTimer()
local integer i = GetIntegerFromUnittype(classification)
//constant unittype UNIT_TYPE_ANCIENT = ConvertUnitType(19)
//constant native ConvertUnitType takes integer i returns unittype //up to 26
//native SaveAgentHandle takes hashtable table, integer parentKey, integer childKey, agent whichAgent returns boolean
//type unittype extends handle
call UnitAddType(u, classification)
call SaveUnitHandle(g_timedHash, GetHandleId(t), KEY_TIMED_CLASSIFICATION_UNIT, u)
call SaveInteger(g_timedHash, GetHandleId(t), KEY_TIMED_CLASSIFICATION_INTEGER, i)
call TimerStart(t, time, false, function UnitAddTypeTimed_Child)
set t=null
endfunction
//===========================================================================
function InitTrig_Timed takes nothing returns nothing
set gg_trg_Timed = CreateTrigger( )
endfunction
library KnockbackSimple initializer Init uses IsDestructableTree, TerrainPathability // by ZibiTheWand3r3r v.1.03
// Features:
// Simple to use knockback: one function call, configurable behavior (16 possible versions), supports diffrent collision sizes
// callback function, can destroy knockbacks any time, system is for ground units only
// *****************************
// Requires:
// library IsDestructableTree * by BPower:
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-isdestructabletree-248054/
// library TerrainPathability * by Rising_Dusk
// http://www.wc3c.net/showthread.php?t=103862
// GUI Unit Event v2.2.1.0 * by Bribe
// http://www.hiveworkshop.com/threads/gui-unit-event-v2-2-1-0.201641/
// *****************************
// How to use:
// function KnockBack takes:
// (code) onHitCode = code that will be executed when unit bounce/hits other unit/obstacles (structure, cliff, doodad, tree)
// set to "null" if not needed, (onHitCode is executed as trigger action)
// (unit) u = knockbacked unit
// (real) distance = how far unit will be moved
// (real) duration = how long knockback exists [sec]
// (real) angle = knockback angle [in radians!]
// (boolean) interruptSpells = if "true" it's interrupts orders/channeling spells on unit u, when knockback starts
// (boolean) killTrees = if "true" unit(s) will destroy trees if unit travels with >minimum speed, kb_minSpeedToKillTree
// (boolean) disableMovement = if "true" unit won't be able to move during knockback, it's using SetUnitPropWindow
// technique, so if you already using this in your map it may interfere. In this case set this boolean to false.
// (integer) kbType see table below, avaiable 4 types: KB_TYPE_NO_BOUNCE ,
// KB_TYPE_SLIDE , KB_TYPE_STOP_ON_OBSTACLES , KB_TYPE_NORMAL
// (integer) bounceTypeFiltr see table below, avaiable 4 filters: KB_FILTR_BOUNCE_NONE ,
// KB_FILTR_BOUNCE_ENEMY_ONLY , KB_FILTR_BOUNCE_ALLIED_ONLY , KB_FILTR_BOUNCE_ALL
// (string) effects - special effect played on unit(s) every given distance (variable effectOccursDistance),
// if null, no effect will be played
// (string) effectAttachPoint - atachment point for special effect, example: "origin"
// (real) effectOccursDistance - special effect declared above will be played every [effectOccursDistance] distance
// *****************************
// (code) onHitCode example:
// function OnHitExample takes nothing returns nothing
// avaiable global variables inside this callback function, read-only:
// (unit) kb_unit = main unit connected with this function
// (unit) kb_obstacle_unit = unit who was hit by kb_unit (if a unit was hit)
// (integer) kb_hitCount = counts all hits done by kb_unit
// (integer) kb_callback use to determine 2 'events' type: KB_HIT_OBSTACLE_UNIT or KB_HIT_THE_WALL
// KB_HIT_THE_WALL = structure or doodad or cliff or tree, if KB_HIT_OBSTACLE_UNIT it refers to kb_obstacle_unit
// don't use "waits" here
// if kb_callback == KB_HIT_OBSTACLE_UNIT and kb_hitCount == 1 then
// call DisplayTextToForce(GetPlayersAll(), GetUnitName(kb_unit) + " hits the " + GetUnitName(kb_obstacle_unit))
// endif
// endfunction
// *****************************
// knockback types / bounce types description
// kbType: KB_TYPE_NO_BOUNCE: stops on obstacles /structures/cliffs/doodads
// if code "onHitCode" is specifed then it will be executed when unit hits obstacle/unit
// kb_bounceFiltrType: KB_FILTR_BOUNCE_NONE:
// ignore all units pathing on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ENEMY_ONLY:
// ignore alied units pathing on my way, stops on first enemy unit on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALLIED_ONLY:
// ignore enemy units pathing on my way, stops on first allied unit on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALL:
// stops on first unit found on my way
// kb_type: KB_TYPE_SLIDE: bounce me on obstacles and:
// if code "onHitCode" is specifed then it will be executed when unit hits obstacle/unit
// kb_bounceFiltrType: KB_FILTR_BOUNCE_NONE:
// ignore all units pathing on my way, don't bounce me from other units, and *don't bounce any units on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ENEMY_ONLY:
// ignore all units pathing on my way, don't bounce me from other units, but bounce unit on my way- enemies only
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALLIED_ONLY:
// ignore all units pathing on my way, don't bounce me from other units, but bounce unit on my way- allied only
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALL:
// ignore all units pathing on my way, don't bounce me from other units, but bounce all units on my way
// --> if 2 knockbacked units meet, KB_TYPE_SLIDE has priority and it *may* overwrite existing knockback <---
// --> if KB_TYPE_SLIDE will bounce other units it will be done with angle 90 degrees <--
// kb_type: KB_TYPE_STOP_ON_OBSTACLES: don't bounce me on obstacles structures/cliffs/doodads/trees and:
// if code "onHitCode" is specifed then it will be executed if unit hits obstacle/unit
// kb_bounceFiltrType: KB_FILTR_BOUNCE_NONE:
// bounce me on any other unit, and don't bounce units on my way (allied and enemy)
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ENEMY_ONLY:
// ignore only allies pathing on my way, and bounce me and enemy units on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALLIED_ONLY:
// ignore only enemies pathing on my way, and bounce me and allied units on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALL:
// bounce me on other unit, and bounce all units on my way (allied and enemy)
// kb_type: KB_TYPE_NORMAL: bounce me on obstacles and:
// if code "onHitCode" is specifed then it will be executed if unit hits obstacle/unit
// kb_bounceFiltrType: KB_FILTR_BOUNCE_NONE:
// bounce me on any other unit, and don't bounce units on my way (allied and enemy)
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ENEMY_ONLY:
// ignore only allies pathing on my way, and bounce me and enemy units on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALLIED_ONLY:
// ignore only enemies pathing on my way, and bounce me and allied units on my way
// kb_bounceFiltrType: KB_FILTR_BOUNCE_ALL:
// bounce me on other unit, and bounce all units on my way (allied and enemy)
//
private function KB_FilterOutAbility takes integer abiId returns nothing
set kb_filterOutAbiInteger = kb_filterOutAbiInteger + 1
set kb_filterOutAbility[kb_filterOutAbiInteger] = abiId
endfunction
//*****************************************************************
// **************** BEGIN OF USER CONFIGURABLES **********************
private function KB_AdvancedUserConfigurables takes nothing returns nothing
// these will apply >globaly< to knockback system:
set kb_minSpeedToKillTree = 500.00 // minimum unit speed that allow to destroy tree, only positive values allowed
set kb_reduceSpeedOnHitFactor = 20.00 // allowed range: 0 ... 100
// (very high values of kb_reduceSpeedOnHitFactor may look ugly and cause unit to stop instantly)
// following settings will filter out units with abilities "ghost" "ghosts visible" and with buff "windwalk"
// so units with these abilities will not be bounced, as they already can be walked over
call KB_FilterOutAbility('Agho')
call KB_FilterOutAbility('Aeth')
call KB_FilterOutAbility('BOwk')
// you can add more abilities/buffs here like 3 above
// call KB_FilterOutAbility('YourAbiId')
endfunction
// **************** END OF USER CONFIGURABLES ************************
//*****************************************************************
globals
group kb_ug
real array kb_distance
real array kb_time
real array kb_angle
real array kb_d1
real array kb_d2
real array kb_sin
real array kb_cos
boolean array kb_killTrees
boolean array kb_interruptSpells
boolean array kb_disableMovement
integer array kb_knockbackType
integer array kb_bounceFiltrType
string array kb_effect
string array kb_effectAttachPoint
real array kb_effectOccursDistance
real array kb_lastDistanceEffect
real array kb_collision
real array kb_distanceLeft
real array kb_timeLeft
trigger array kb_trg_onHit
trigger kb_trg_loop
integer array kb_hitCounter // for callback function
integer kb_hitCount = 0 // for callback function
unit kb_unit = null // for callback function
unit kb_obstacle_unit = null // for callback function
player kb_player
rect kb_rect
group kb_group
timer kb_timer
real kb_minSpeedToKillTree = 500.00
real kb_reduceSpeedOnHitFactor = 10.00
real kb_reduceSpeedOnHit = 1.00
constant real KB_DETECT_OBSTACLE_UNIT_RADIUS = 150.00
constant real KB_INTERVAL = 0.03125
constant real KB_STEPS_PER_SEC = 1.00 / KB_INTERVAL
constant real KB_PI_DIVIDED_BY_2 = bj_PI / 2.00
constant real KB_PI_MULTIPLIED_BY_2 = bj_PI * 2.00
boolexpr array kb_filtr
constant integer KB_FILTR_BOUNCE_NONE = 0
constant integer KB_FILTR_BOUNCE_ENEMY_ONLY = 2
constant integer KB_FILTR_BOUNCE_ALLIED_ONLY = 3
constant integer KB_FILTR_BOUNCE_ALL = 4
constant integer KB_TYPE_NO_BOUNCE = 0
constant integer KB_TYPE_SLIDE = 10
constant integer KB_TYPE_STOP_ON_OBSTACLES = 20
constant integer KB_TYPE_NORMAL = 30
constant integer KB_HIT_OBSTACLE_UNIT = 101
constant integer KB_HIT_THE_WALL = 102
integer kb_callback
integer kb_filterOutAbiInteger = 0
integer array kb_filterOutAbility
endglobals
//-----------------------------------------------------------
//x, y, = centerX, centerY
//-----------------------------------------------------------
function KB_IsPointWalkableForSize takes real x, real y, real whatSize returns boolean //x, y, = centerX, centerY
if whatSize <= 16.00 then //one item check:
return IsTerrainWalkable(x, y)
endif // for larger units: 5 item checks
return IsTerrainWalkable(x, y) and IsTerrainWalkable(x+32.00, y) and IsTerrainWalkable(x-32.00, y) and IsTerrainWalkable(x, y+32.00) and IsTerrainWalkable(x, y-32.00)
endfunction
//------------------------------------------------------------
//------------------------------------------------------------
function KB_GetBounceAngle takes real angle, real x, real y, integer id returns real
local real newAngleVer1 = ( - angle )
local real newAngleVer2 = ( - bj_PI - angle ) // for negative angles
if angle>0.00 then
set newAngleVer2 = (bj_PI - angle)
endif
//++++
if KB_IsPointWalkableForSize(x+kb_d1[id] * Cos(newAngleVer1), y+kb_d1[id] * Sin(newAngleVer1), kb_collision[id]) then
return newAngleVer1
elseif KB_IsPointWalkableForSize(x+kb_d1[id] * Cos(newAngleVer2), y+kb_d1[id] * Sin(newAngleVer2), kb_collision[id]) then
return newAngleVer2
else //3rd version - reverse direction:
set newAngleVer1 = (angle + bj_PI) // for negative angle
if angle>0.00 then
set newAngleVer1 = (angle - bj_PI)
endif
endif
return newAngleVer1
endfunction
//------------------------------------------------------------
//-----------------------------x/y = obstacleUnit X/Y
function KB_GetBounceAngle90 takes real angle, real x, real y, real unitX, real unitY returns real
local real newAnglePlus = ModuloReal((angle + KB_PI_DIVIDED_BY_2), KB_PI_MULTIPLIED_BY_2) // +90
local real newAngleMinus = ModuloReal((angle - KB_PI_DIVIDED_BY_2), KB_PI_MULTIPLIED_BY_2) // -90
local real x1 = x+32.00 * Cos(newAnglePlus)
local real y1 = y+32.00 * Sin(newAnglePlus)
local real x2 = x+32.00 * Cos(newAngleMinus)
local real y2 = y+32.00 * Sin(newAngleMinus)
//compare distances
if ((x1-unitX) * (x1-unitX) + (y1-unitY) * (y1-unitY)) > ((x2-unitX) * (x2-unitX) + (y2-unitY) * (y2-unitY)) then
return newAnglePlus
endif
return newAngleMinus
endfunction
//-------------------------------------------------------------------------------
//-------------Zwiebelchen:-------------------------------------------
// The difference between GroupEnumUnitsInRange and IsUnitInRangeXY is, that the former will only enumerate units
// whose coordinate center is inside the radius.
// The IsUnitInRange natives will already return true if only a part of the unit is inside the radius.
//--------------------------------------------------------
// KB_GetUnitCollisionSize checks up to 64 unit collision size // returns values from 8 ..to.. 64
//--------------------------------------------------------
function KB_GetUnitCollisionSize takes unit u, real unitX, real unitY returns real
local real i=0.00
local real size=64.00
loop
exitwhen i==64.00
if not IsUnitInRangeXY(u, (unitX+i), unitY, 0.00) then
set size = (i-1.00)
exitwhen true
endif
set i=i+1.00
endloop
if size<8.00 then
return 8.00
endif
return size
endfunction
//------------------------------------------------------------
function IsUnitAlive takes unit u returns boolean
return not (GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD))
endfunction
//------------------------------------------------------------
// DisableUnitMovement /* v1.0.0.1
// * Disables unit movement. They can still turn, but will stay in
// * place. It simulates an ensnare-like effect, except that it will
// * not ground units, it does not have buffs, does not interrupt
// * channeled casts and appears to have no downsides.
// * Full credits to WaterKnight for discovering this technique.
//--------------------------------------------------------------------
function DisableUnitMovement takes unit u returns nothing
call SetUnitPropWindow(u, 0)
endfunction
//--------------------------------------------------------------------
function EnableUnitMovement takes unit u returns nothing
call SetUnitPropWindow(u, GetUnitDefaultPropWindow(u) * bj_DEGTORAD)
endfunction
//------------------------------------------------------------
function KBFiltr_1 takes unit u returns boolean
local integer a=1
local integer id = GetUnitUserData(u)
local boolean isKb = IsUnitInGroup(u, kb_group) // is knockbacked?
if IsUnitAlive(u) and (not IsUnitType(u, UNIT_TYPE_FLYING)) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (IsUnitVisible(u, kb_player)) then
if not (isKb and ((kb_knockbackType[id]==KB_TYPE_SLIDE) or (kb_knockbackType[id]==KB_TYPE_NO_BOUNCE and kb_bounceFiltrType[id]==KB_FILTR_BOUNCE_NONE))) then
if not (isKb and ((IsUnitAlly(u, kb_player) and kb_bounceFiltrType[id]==KB_FILTR_BOUNCE_ENEMY_ONLY) or (IsUnitEnemy(u, kb_player) and kb_bounceFiltrType[id]==KB_FILTR_BOUNCE_ALLIED_ONLY))) then
loop
exitwhen a>kb_filterOutAbiInteger
if GetUnitAbilityLevel(u, kb_filterOutAbility[a]) > 0 then
return false
endif
set a=a+1
endloop
return true
endif
endif
endif
return false
endfunction
//--------
function KBFiltr_groundNotStruc takes nothing returns boolean
return KBFiltr_1(GetFilterUnit())
endfunction
// set kb_player before confirm this 2 checks!
function KBFiltr_groundNotStrucAlliedOnly takes nothing returns boolean
return KBFiltr_1(GetFilterUnit()) and IsUnitAlly(GetFilterUnit(), kb_player)
endfunction
function KBFiltr_groundNotStrucEnemyOnly takes nothing returns boolean
return KBFiltr_1(GetFilterUnit()) and IsUnitEnemy(GetFilterUnit(), kb_player)
endfunction
//------------------------------------------------------------------------
function KB_OnRemoveFromGame takes nothing returns nothing
call GroupRemoveUnit(kb_group, udg_UDexUnits[udg_UDex])
//clean:
if kb_trg_onHit[udg_UDex] != null then
call DestroyTrigger(kb_trg_onHit[udg_UDex])
set kb_trg_onHit[udg_UDex] = null
endif
set kb_effect[udg_UDex] = null
set kb_effectAttachPoint[udg_UDex] = null
if FirstOfGroup(kb_group)==null then
call PauseTimer(kb_timer)
endif
endfunction
//----------------------------------------------------------------------------
function KB_DestroyKnockbackOnUnit takes unit u returns nothing
local integer id = GetUnitUserData(u)
call GroupRemoveUnit(kb_group, u)
if kb_trg_onHit[id] != null then
call DestroyTrigger(kb_trg_onHit[id])
set kb_trg_onHit[id] = null
endif
call EnableUnitMovement(u)
set kb_effect[id] = null
set kb_effectAttachPoint[id] = null
if FirstOfGroup(kb_group)==null then
call PauseTimer(kb_timer)
endif
endfunction
//----------------------------------------------------------------------------
function KB_DestroyAllEnum takes nothing returns nothing
call KB_DestroyKnockbackOnUnit(GetEnumUnit())
endfunction
//----------------------------
function KB_DestroyAllKnockbacks takes nothing returns nothing
call ForGroup(kb_group, function KB_DestroyAllEnum)
endfunction
//----------------------------
//=======================================================
function KB_CheckAllowedTypes takes integer kbType, integer bounceTypeFiltr returns boolean
if kbType == KB_TYPE_NO_BOUNCE or kbType == KB_TYPE_SLIDE or kbType == KB_TYPE_STOP_ON_OBSTACLES or kbType == KB_TYPE_NORMAL then
if bounceTypeFiltr == KB_FILTR_BOUNCE_NONE or bounceTypeFiltr == KB_FILTR_BOUNCE_ENEMY_ONLY or bounceTypeFiltr == KB_FILTR_BOUNCE_ALLIED_ONLY or bounceTypeFiltr == KB_FILTR_BOUNCE_ALL then
return true
endif
endif
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Knockback error: wrong integer pass to function")
return false
endfunction
//-----------------------------------------------------------------------------------------
//-----main function --------------------------------------------------------------------
function KnockBack takes code onHitCode, unit u, real distance, real duration, real angle, boolean interruptSpells, boolean killTrees, boolean disableMovement, integer kbType, integer bounceTypeFiltr, string effects, string effectAttachPoint, real effectOccursDistance returns nothing
local integer id = GetUnitUserData(u)
local integer q = R2I(duration / KB_INTERVAL) // (Number of steps)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
if GetUnitDefaultMoveSpeed(u) == 0.00 or (not KB_CheckAllowedTypes(kbType, bounceTypeFiltr)) then //protection
return
endif
set kb_effect[id] = null
set kb_effectAttachPoint[id] = null
if kb_trg_onHit[id] != null then
call DestroyTrigger(kb_trg_onHit[id])
set kb_trg_onHit[id] = null
endif
if onHitCode != null then
set kb_trg_onHit[id] = CreateTrigger()
call TriggerAddAction(kb_trg_onHit[id], onHitCode)
endif
set kb_distance[id] = distance
set kb_distanceLeft[id] = distance
set kb_time[id] = duration
set kb_timeLeft[id] = duration
set kb_hitCounter[id] = 0
set kb_angle[id] = angle
set kb_sin[id] = Sin(angle)
set kb_cos[id] = Cos(angle)
set kb_d1[id] = 2 * kb_distance[id] / (q + 1) // the "bit" in "moving a unit a bit a time"
set kb_d2[id] = kb_d1[id] / q // will decrease d1 with each execution
set kb_killTrees[id] = killTrees
set kb_interruptSpells[id] = interruptSpells
set kb_disableMovement[id] = disableMovement
set kb_knockbackType[id] = kbType
set kb_bounceFiltrType[id] = bounceTypeFiltr
if kb_interruptSpells[id] then
call SetUnitPosition(u, x, y)
endif
if kb_disableMovement[id] then
call DisableUnitMovement(u)
endif
if effects != null then
set kb_effect[id] = effects
endif
set kb_effectAttachPoint[id] = effectAttachPoint
set kb_lastDistanceEffect[id] = kb_distance[id]
set kb_effectOccursDistance[id] = effectOccursDistance
set kb_collision[id] = KB_GetUnitCollisionSize(u, x, y)
if FirstOfGroup(kb_group)==null then
call TimerStart(kb_timer, KB_INTERVAL, true, null)
endif
call GroupAddUnit(kb_group, u)
endfunction
// KBLOOP part =============================================
function KB_BounceEvent takes unit u, integer id, integer eventType returns nothing
if kb_trg_onHit[id] != null then
set kb_callback = eventType // KB_HIT_OBSTACLE_UNIT or KB_HIT_THE_WALL
set kb_unit = u
set kb_hitCounter[id] = kb_hitCounter[id] + 1
set kb_hitCount = kb_hitCounter[id]
call TriggerExecute(kb_trg_onHit[id])
endif
endfunction
//------------------------------------------------------------------------------------------------
// use this for bounce from structures/cliffs/doodads ONLY:
//------------------------------------------------------------------------------------------------
function KB_BounceUnit takes unit u, integer id, real unitX, real unitY returns nothing
set kb_angle[id] = KB_GetBounceAngle(kb_angle[id], unitX, unitY, id) //change angle
set kb_sin[id] = Sin(kb_angle[id])
set kb_cos[id] = Cos(kb_angle[id])
call SetUnitX(u, unitX + kb_d1[id] * kb_cos[id])
call SetUnitY(u, unitY + kb_d1[id] * kb_sin[id])
set kb_d1[id] = kb_d1[id] * kb_reduceSpeedOnHit // reducing distance kb_d1
call KB_BounceEvent(u, id, KB_HIT_THE_WALL) //fire hit event
endfunction
//------------------------------------------------------------------------------------------------
//-this for better visual effect --
//-KB_BounceEvent is not included here inside this func -----------
function KB_BounceUnitReverseWithMinSpeed takes unit u, integer id returns nothing
local real angle = (kb_angle[id] + bj_PI)
if kb_angle[id]>0.00 then // reverse direction:
set angle = (kb_angle[id] - bj_PI)
endif // initiate new kb, so old one will be ended:
call KnockBack(null, u, 25.00, 0.30, angle, false, kb_killTrees[id], kb_disableMovement[id], KB_TYPE_SLIDE, KB_FILTR_BOUNCE_NONE, null, null, 1.00)
endfunction
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
function KB_TwoUnitsHit takes unit mainUnit, integer id, unit obstacleUnit, integer obstacleId returns nothing
local integer kb1 = kb_knockbackType[id]
local integer kb2
if IsUnitInGroup(obstacleUnit, kb_group) then
set kb2 = kb_knockbackType[obstacleId]
if kb2 == KB_TYPE_NO_BOUNCE then
set kb_obstacle_unit = obstacleUnit
call KB_BounceEvent(mainUnit, id, KB_HIT_OBSTACLE_UNIT)
set kb_obstacle_unit = mainUnit
call KB_BounceEvent(obstacleUnit, obstacleId, KB_HIT_OBSTACLE_UNIT)
if kb2 == kb1 then // both "no-bounce"
call KB_BounceUnitReverseWithMinSpeed(mainUnit, id)
call KB_BounceUnitReverseWithMinSpeed(obstacleUnit, obstacleId)
endif
elseif (kb2 == KB_TYPE_NORMAL or kb2 == KB_TYPE_STOP_ON_OBSTACLES) and (kb1 == KB_TYPE_NORMAL or kb1 == KB_TYPE_STOP_ON_OBSTACLES or kb1 == KB_TYPE_SLIDE) then
set kb_obstacle_unit = mainUnit
call KB_BounceEvent(obstacleUnit, obstacleId, KB_HIT_OBSTACLE_UNIT)
set kb_obstacle_unit = obstacleUnit
call KB_BounceEvent(mainUnit, id, KB_HIT_OBSTACLE_UNIT)
endif
else // obstacle unit *not* in kb_group:
set kb_obstacle_unit = obstacleUnit
call KB_BounceEvent(mainUnit, id, KB_HIT_OBSTACLE_UNIT)
if kb1 == KB_TYPE_NO_BOUNCE then
call KB_BounceUnitReverseWithMinSpeed(mainUnit, id)
endif
endif
endfunction
//-------------------------------------------------------------------------------
// kb_u primary unit, unitX = GetUnitX(kb_u)
// bouncePrimaryUnit - if "true" will bounce kb_u in opposite direction to new unit on way
// bounceNewUnit -if "true" will bounce new unit in opposite direction to kb_u unit
function KB_CheckUnitsAroundAndBounce takes unit kb_u, integer kb_id, real unitX, real unitY, real targetX, real targetY, integer filtrNr, boolean bouncePrimaryUnit, boolean bounceNewUnit returns boolean
local unit obst_u
local integer obst_id
local real obstX
local real obstY
local integer foundUnits=0
local real angle
local integer t
local integer b
local real Tx
local real Ty
local real c
local real newDistance
set kb_player = GetOwningPlayer(kb_u)
call GroupEnumUnitsInRange(kb_ug, targetX, targetY, KB_DETECT_OBSTACLE_UNIT_RADIUS, kb_filtr[filtrNr])
loop
set obst_u = FirstOfGroup(kb_ug)
exitwhen obst_u == null
set obstX = GetUnitX(obst_u)
set obstY = GetUnitY(obst_u)
set c = KB_GetUnitCollisionSize(obst_u, obstX, obstY)
if (obst_u != kb_u) and IsUnitInRange(obst_u, kb_u, RMaxBJ(c, kb_collision[kb_id])) then //pick bigger collision
set foundUnits = 1
set obst_id = GetUnitUserData(obst_u)
call KB_TwoUnitsHit(kb_u, kb_id, obst_u, obst_id)
// if bounce primary unit:
if bouncePrimaryUnit then
set angle = Atan2(unitY - obstY, unitX - obstX) // reverse angle
set Tx = unitX+kb_d1[kb_id] * Cos(angle)
set Ty = unitY+kb_d1[kb_id] * Sin(angle)
if KB_IsPointWalkableForSize(Tx, Ty, kb_collision[kb_id]) then
call SetUnitX(kb_u, Tx)
call SetUnitY(kb_u, Ty)
set kb_angle[kb_id] = angle //change angle
set kb_sin[kb_id] = Sin(kb_angle[kb_id])
set kb_cos[kb_id] = Cos(kb_angle[kb_id])
set kb_d1[kb_id] = kb_d1[kb_id] * kb_reduceSpeedOnHit // reducing distance kb_d1
else // not walkable:
set kb_d1[kb_id] = 0.00 // end knockback
endif
elseif kb_knockbackType[kb_id] == KB_TYPE_SLIDE then // if not bounce, then move [for slide type only]:
call SetUnitX(kb_u, targetX)
call SetUnitY(kb_u, targetY)
endif
// if bounce obstacle unit:
if bounceNewUnit then
set angle = Atan2(obstY - unitY, obstX - unitX) // reverse angle
if IsUnitInGroup(obst_u, kb_group) then
if kb_knockbackType[kb_id] == KB_TYPE_SLIDE then // hit by sliding unit, initiate new slide, slide overwrites existing one
if kb_timeLeft[kb_id] * kb_distanceLeft[kb_id] > 1.00 then //don't run very low knockbacks! <---
set b = kb_bounceFiltrType[kb_id] // new bounce filter:
if kb_bounceFiltrType[kb_id] == KB_FILTR_BOUNCE_ENEMY_ONLY then
set b = KB_FILTR_BOUNCE_ALLIED_ONLY
endif
set angle = KB_GetBounceAngle90(kb_angle[kb_id], obstX, obstY, unitX, unitY) //angle 90 degrees
if KB_IsPointWalkableForSize((obstX+kb_d1[obst_id] * Cos(angle)), (obstY+kb_d1[obst_id] * Sin(angle)), c) then
call KnockBack(null, obst_u, kb_distanceLeft[kb_id], kb_timeLeft[kb_id], angle, kb_interruptSpells[kb_id], kb_killTrees[kb_id], kb_disableMovement[kb_id], kb_knockbackType[kb_id], b, kb_effect[kb_id], kb_effectAttachPoint[kb_id], kb_effectOccursDistance[kb_id])
endif
endif
else // hit by non-sliding unit, update existing kb:
set Tx = obstX+kb_d1[obst_id] * Cos(angle)
set Ty = obstY+kb_d1[obst_id] * Sin(angle)
if KB_IsPointWalkableForSize(Tx, Ty, c) then
call SetUnitX(obst_u, Tx)
call SetUnitY(obst_u, Ty)
set kb_angle[obst_id] = angle //change angle
set kb_sin[obst_id] = Sin(kb_angle[obst_id])
set kb_cos[obst_id] = Cos(kb_angle[obst_id])
set kb_d1[obst_id] = kb_d1[obst_id] * kb_reduceSpeedOnHit // reducing distance kb_d1
endif
endif
elseif (kb_timeLeft[kb_id] * kb_distanceLeft[kb_id]) > 1.00 then //unit NOT in kb_group, initial new kb; don't run very low knockbacks! <---
set b = kb_bounceFiltrType[kb_id] // new bounce filter:
if b == KB_FILTR_BOUNCE_ENEMY_ONLY then
set b = KB_FILTR_BOUNCE_ALLIED_ONLY
endif
if kb_knockbackType[kb_id] == KB_TYPE_SLIDE then // if obstacle hits by sliding unit, change angle to 90
set angle = KB_GetBounceAngle90(kb_angle[kb_id], obstX, obstY, unitX, unitY) //angle 90 degrees
endif // now calculate new distance to get the same speed as kb_u
set newDistance = (kb_d1[kb_id] * ((I2R(R2I(kb_timeLeft[kb_id] / KB_INTERVAL)) + 1))) / 2.00
if KB_IsPointWalkableForSize((obstX+kb_d1[obst_id] * Cos(angle)), (obstY+kb_d1[obst_id] * Sin(angle)), c) then
call KnockBack(null, obst_u, newDistance, kb_timeLeft[kb_id], angle, kb_interruptSpells[kb_id], kb_killTrees[kb_id], kb_disableMovement[kb_id], kb_knockbackType[kb_id], b, kb_effect[kb_id], kb_effectAttachPoint[kb_id], kb_effectOccursDistance[kb_id])
endif
endif
endif
//bounce obstacle unit:end
endif
call GroupRemoveUnit(kb_ug, obst_u)
endloop
call GroupClear (kb_ug)
set obst_u=null
return foundUnits > 0
endfunction
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
function KB_MoveUnit takes unit u, integer id, real unitX, real unitY, real targetX, real targetY returns nothing
local boolean isWalkable = KB_IsPointWalkableForSize(targetX, targetY, kb_collision[id])
if kb_knockbackType[id] == KB_TYPE_NO_BOUNCE then // no bounce at all
if not isWalkable then
call KB_BounceEvent(u, id, KB_HIT_THE_WALL) //fire hit event, obstacle
call KB_BounceUnitReverseWithMinSpeed(u, id)
elseif kb_bounceFiltrType[id] == KB_FILTR_BOUNCE_NONE then // walkable:
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
elseif (not KB_CheckUnitsAroundAndBounce(u, id, unitX, unitY, targetX, targetY, kb_bounceFiltrType[id], false, false)) then //3 other filters:
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
endif
//---------------------------------SLIDE:-------------------------------------------------
elseif kb_knockbackType[id] == KB_TYPE_SLIDE then
if not isWalkable then
call KB_BounceUnit(u, id, unitX, unitY) //fires hit event
elseif kb_bounceFiltrType[id] == KB_FILTR_BOUNCE_NONE then
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
elseif (not KB_CheckUnitsAroundAndBounce(u, id, unitX, unitY, targetX, targetY, kb_bounceFiltrType[id], false, true)) then //3 other filters:
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
endif
//--------------------------------- KB_TYPE_NORMAL / KB_TYPE_STOP_ON_OBSTACLES -------------------
elseif kb_knockbackType[id] == KB_TYPE_NORMAL or kb_knockbackType[id] == KB_TYPE_STOP_ON_OBSTACLES then
if not isWalkable then
if kb_knockbackType[id] == KB_TYPE_NORMAL then
call KB_BounceUnit(u, id, unitX, unitY)
elseif kb_knockbackType[id] == KB_TYPE_STOP_ON_OBSTACLES then
call KB_BounceEvent(u, id, KB_HIT_THE_WALL) //fire hit event, obstacle
call KB_BounceUnitReverseWithMinSpeed(u, id)
endif
elseif (kb_bounceFiltrType[id] == KB_FILTR_BOUNCE_NONE) then //walkable:
if (not (KB_CheckUnitsAroundAndBounce(u, id, unitX, unitY, targetX, targetY, KB_FILTR_BOUNCE_ALL, true, false))) then
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
endif
elseif (not (KB_CheckUnitsAroundAndBounce(u, id, unitX, unitY, targetX, targetY, kb_bounceFiltrType[id], true, true))) then //3 other filters
call SetUnitX(u, targetX)
call SetUnitY(u, targetY)
endif
endif
endfunction
//-----------------------------------------------------------------
function KB_KillTree takes nothing returns nothing
call KillTree(GetEnumDestructable())
endfunction
//------------------------------------------------------------------
function KB_ShowEffect takes unit u, integer id returns nothing
if kb_effect[id] != null and (kb_distanceLeft[id] < (kb_lastDistanceEffect[id] - kb_effectOccursDistance[id])) then
call DestroyEffect(AddSpecialEffectTarget(kb_effect[id], u, kb_effectAttachPoint[id]))
set kb_lastDistanceEffect[id] = kb_distanceLeft[id]
endif
endfunction
//------------------------------------------------------------------
function KB_LoopEnum takes nothing returns nothing
local unit u = GetEnumUnit()
local integer id = GetUnitUserData(u)
local real unitX = GetUnitX(u)
local real unitY = GetUnitY(u)
local real targetX = unitX + kb_d1[id] * kb_cos[id]
local real targetY = unitY + kb_d1[id] * kb_sin[id]
//if (not IsUnitAlive(u)) or kb_d1[id] <= 0.00 then
if (not IsUnitAlive(u)) or kb_d1[id] <= 0.00 or (GetUnitDefaultMoveSpeed(u)==0.00) then//21.02.2019
call KB_DestroyKnockbackOnUnit(u)
set u=null
return
endif
if kb_killTrees[id] and ((kb_d1[id]*KB_STEPS_PER_SEC) > kb_minSpeedToKillTree) then
call MoveRectTo(kb_rect, targetX, targetY)
call EnumDestructablesInRect(kb_rect, null, function KB_KillTree)
endif
call KB_ShowEffect(u, id)
call KB_MoveUnit(u, id, unitX, unitY, targetX, targetY)
set kb_d1[id] = kb_d1[id] - kb_d2[id] // decrease speed
set kb_distanceLeft[id] = kb_distanceLeft[id] - kb_d1[id] // for additional kb-ed units
set kb_timeLeft[id] = kb_timeLeft[id] - KB_INTERVAL // for additional kb-ed units
set u=null
endfunction
//--------------------------------------------------------------------------
function KB_Loop takes nothing returns boolean
call ForGroup(kb_group, function KB_LoopEnum)
return false
endfunction
//=======================================================
//=======================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
set kb_ug = CreateGroup()
set kb_group = CreateGroup()
set kb_timer = CreateTimer()
set kb_rect = Rect(0.0, 0.0, 256.0, 256.0)
set kb_trg_loop = CreateTrigger()
call TriggerRegisterTimerExpireEvent(kb_trg_loop, kb_timer) //timer kb_timer expires
call TriggerAddCondition(kb_trg_loop, Condition(function KB_Loop))
//----------------------------------------------------
call KB_AdvancedUserConfigurables()
set kb_minSpeedToKillTree = RMaxBJ(kb_minSpeedToKillTree, 0.00)
if kb_reduceSpeedOnHitFactor < 0.00 then
set kb_reduceSpeedOnHitFactor = 0.00
elseif kb_reduceSpeedOnHitFactor > 100.00 then
set kb_reduceSpeedOnHitFactor = 100.00
endif
set kb_reduceSpeedOnHit = 1.00 - (kb_reduceSpeedOnHitFactor / 100.00) // for kb_d1, range: 0.00 ... 1.00
//----------------------------------------------------
set kb_filtr[KB_FILTR_BOUNCE_NONE] = Condition(function KBFiltr_groundNotStruc)
set kb_filtr[KB_FILTR_BOUNCE_ALL] = Condition(function KBFiltr_groundNotStruc)
set kb_filtr[KB_FILTR_BOUNCE_ALLIED_ONLY] = Condition(function KBFiltr_groundNotStrucAlliedOnly)
set kb_filtr[KB_FILTR_BOUNCE_ENEMY_ONLY] = Condition(function KBFiltr_groundNotStrucEnemyOnly)
call TriggerRegisterVariableEvent( t, "udg_UnitIndexEvent", EQUAL, 2.00 ) // remove unit detection
call TriggerAddAction(t, function KB_OnRemoveFromGame)
set t=null
endfunction
endlibrary
//Group_IsMixed(group <g>) returns boolean
// "true" if group consist walking & flying units
//Group_InRange(group <g>, integer <x>, integer <y>, integer<dist>) returns boolean
// returns "true" if all group members are nearby given location, (returns "true" for empty group)
//Group_Stretched(group <g>, integer <maxDistance>) returns boolean
// checking distance between all units in group
//Group_GetCount(group <g>) returns integer
//Group_GetCenter(group <g>) returns string
// returns x/y coordinates converted to string. To get x/y use GetStringX(coordsString) & Y
//Group_GetUnitCoordsClosestToXY(group <g>, integer <Tx>, integer<Ty>) returns string
// searches for group member closest to Tx Ty.
// returns x/y coordinates converted to string. To get x/y, use GetStringX(coordsString) & Y
//Group_CountUnitType(group <g>, integer <unitId>) returns integer
//**************************************************************************************
// above functions work for a group which has a trigger with event "unit dies" that removes dying unit from a group !
//**************************************************************************************
// GroupEnum functions:
//
//CountUnitsInRange(real <x>, real <y>, integer <maxDist>, boolexpr <filtr>) returns integer
//GetClosestUnitInRangeEx(real <x>, real <y>, integer <maxDist>, boolexpr <filtr>, unit <omitUnit>) returns unit
//GetClosestUnit(real <x>, real <y>, integer <maxDist>, boolexpr <filtr>) returns unit
//GetWeakestUnitInRangeEx(real <x>, real <y>, integer <maxDist>, boolexpr <filtr>, unit <omitUnit>) returns unit
//GetWeakestUnit(real <x>, real <y>, integer <maxDist>, boolexpr <filtr>) returns unit
globals
group g_swapGroupUtils=CreateGroup()
unit g_guTempTarget=null
// used in GetClosestUnit , GetWeakestUnit , GetClosestUnitInRangeEx GetWeakestUnitInRangeEx
endglobals
//-------------------------------------------------------------------------------
//-------------------Group_IsMixed----------------------------------------
//-------------------------------------------------------------------------------
// returns "true" only if group consist walking & flying units
function Group_IsMixed takes group g returns boolean
local unit FoG=null
local boolean walkers=false
local boolean flyers=false
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if IsUnitType(FoG, UNIT_TYPE_FLYING) then
set flyers=true
//else
elseif not IsUnitLoaded(FoG) then
set walkers=true
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
//---
return (walkers and flyers)
endfunction
//----------------------------------------------------------------------------------------
//------------------- Group_InRange ----------------------------------------------
//----------------------------------------------------------------------------------------
// returns "true" if all group members are nearby given location, (returns "true" for empty group)
function Group_InRange takes group g, integer x, integer y, integer dist returns boolean
local unit FoG=null
local boolean inRange=true
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if inRange==true and (not IsUnitLoaded(FoG)) and (not IsUnitInRangeXY(FoG, x, y, dist)) then
set inRange=false
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
return inRange
endfunction
//-------------------------------------------------------------------------------------------
//------------------- Group_Stretched -----------------------------------------------
//-------------------------------------------------------------------------------------------
// checking distance between all units in group
function Group_Stretched takes group g , integer maxDistance returns boolean
local unit FoG=null
local integer array x
local integer array y
local integer count=0
local integer a=1
local integer b=1
loop // set x/y array
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if not IsUnitLoaded(FoG) then
set count=count+1
set x[count]=R2I(GetUnitX(FoG))
set y[count]=R2I(GetUnitY(FoG))
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
//---
set maxDistance=maxDistance*maxDistance
loop
exitwhen a>count
set b=a+1
loop
exitwhen b>count
if ((x[a] - x[b]) * (x[a] - x[b]) + (y[a] - y[b]) * (y[a] - y[b])) > maxDistance then
return true
endif
set b=b+1
endloop
set a=a+1
endloop
return false
endfunction
//----------------------------------------------------------------------------------------
//------------------- Group_GetCount ---------------------------------------------
//----------------------------------------------------------------------------------------
function Group_GetCount takes group g returns integer
local unit FoG=null
local integer count=0
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
set count=count+1
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
//---
return count
endfunction
//----------------------------------------------------------------------------------------
//------------------- Group_GetCenter --------------------------------------------
//----------------------------------------------------------------------------------------
// returns x/y coordinates converted to string. To get x/y use GetStringX(coordsString) & Y
function Group_GetCenter takes group g returns string
local unit FoG=null
local real x=0.00
local real y=0.00
local integer count=0
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if not IsUnitLoaded(FoG) then
set x=x + GetUnitX(FoG)
set y=y + GetUnitY(FoG)
set count=count+1
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
//---
if count>0 then
set x=x / count
set y=y / count
call IsTerrainWalkable(x, y)
set x = TerrainPathability_X // from library TerrainPathability
set y = TerrainPathability_Y // from library TerrainPathability
endif
return ConvertIntToString(R2I(x)) + ConvertIntToString(R2I(y))
endfunction
//-------------------------------------------------------------------------------------------------------
//------------------- Group_GetUnitCoordsClosestToXY -------------------------------------
//-------------------------------------------------------------------------------------------------------
// searches for group "g" member closest to Tx Ty
// returns x/y coordinates converted to string. To get x/y use GetStringX(coordsString) & Y
function Group_GetUnitCoordsClosestToXY takes group g, integer Tx, integer Ty returns string
local unit FoG=null
local integer minDistance=1000000000
local integer dist2=0
local integer x=0
local integer y=0
local integer X=0
local integer Y=0
local boolean mixed=Group_IsMixed(g)
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if (not mixed) or (mixed and (not IsUnitType(FoG, UNIT_TYPE_FLYING))) then
set x=R2I(GetUnitX(FoG))
set y=R2I(GetUnitY(FoG))
set dist2 = ((x-Tx) * (x-Tx) + (y-Ty) * (y-Ty))
if dist2<minDistance then
set minDistance=dist2
set X=x
set Y=y
endif
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
return ConvertIntToString(X) + ConvertIntToString(Y)
endfunction
//----------------------------------------------------------------------------------------------------
function Group_CountUnitType takes group g, integer unitId returns integer
local unit FoG=null
local integer count=0
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if GetUnitTypeId(FoG)==unitId then
set count=count+1
endif
//---
call GroupAddUnit(g_swapGroupUtils, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupUtils)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupUtils, FoG)
endloop
return count
endfunction
//----------------------------------------------------------------------------------------------------
// GROUP ENUM functions
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
function CountUnitsInRange takes real x, real y, integer maxDist, boolexpr filtr returns integer
local unit FoG=null
local integer count=0
call GroupEnumUnitsInRange(ug, x, y, maxDist, filtr)
loop
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
set count=count+1
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
return count
endfunction
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
function GetClosestUnitInRangeEx takes real x, real y, integer maxDist, boolexpr filtr, unit omitUnit returns unit
local unit FoG=null
local real max=1000000.00
local real r=0.00
set g_guTempTarget=null
call GroupEnumUnitsInRange(ug, x, y, maxDist, filtr)
loop
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
if not (FoG==omitUnit) then
set r=(x - GetUnitX(FoG)) * (x - GetUnitX(FoG)) + (y - GetUnitY(FoG)) * (y - GetUnitY(FoG))
if r<max then
set max=r
set g_guTempTarget=FoG
endif
endif
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
return g_guTempTarget
endfunction
//----------------------------------------------------------------------------------------------------------------
function GetClosestUnit takes real x, real y, integer maxDist, boolexpr filtr returns unit
return GetClosestUnitInRangeEx(x, y, maxDist, filtr, null)
endfunction
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
function GetWeakestUnitInRangeEx takes real x, real y, integer maxDist, boolexpr filtr, unit omitUnit returns unit
local unit FoG=null
local real max=1000000.00
set g_guTempTarget=null
call GroupEnumUnitsInRange(ug, x, y, maxDist, filtr)
loop
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
if not (FoG==omitUnit) then
if GetWidgetLife(FoG)<max then
set max=GetWidgetLife(FoG)
set g_guTempTarget=FoG
endif
endif
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
return g_guTempTarget
endfunction
//----------------------------------------------------------------------------------------------------------------
function GetWeakestUnit takes real x, real y, integer maxDist, boolexpr filtr returns unit
return GetWeakestUnitInRangeEx(x, y, maxDist, filtr, null)
endfunction
//-------------------------------------------------------------------------------------------
//==========================================================
function InitTrig_GroupUtils takes nothing returns nothing
endfunction
globals
integer array cargoOccupiedSlots // [transport's ID]
endglobals
// Tracks number of occupied slots in Transports
function Trig_CargoEntersRemoved takes nothing returns boolean
set cargoOccupiedSlots[udg_UDex] = 0
return false
endfunction
function Trig_CargoLoad takes nothing returns boolean
local integer cargoId = GetUnitUserData(udg_CargoTransportUnit[udg_UDex])
set cargoOccupiedSlots[cargoId] = cargoOccupiedSlots[cargoId] + 1
return false
endfunction
function Trig_CargoUnload takes nothing returns boolean
local integer cargoId = GetUnitUserData(udg_CargoTransportUnit[udg_UDex])
set cargoOccupiedSlots[cargoId] = cargoOccupiedSlots[cargoId] - 1
return false
endfunction
//===========================================================================
function InitTrig_Cargo takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00) //Enters Map
call TriggerAddCondition(t, Condition(function Trig_CargoEntersRemoved))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00) //Removed from Map
call TriggerAddCondition(t, Condition(function Trig_CargoEntersRemoved))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_CargoEvent", EQUAL, 1.00 ) //Load
call TriggerAddCondition(t, Condition(function Trig_CargoLoad))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_CargoEvent", EQUAL, 2.00 ) //Unload
call TriggerAddCondition(t, Condition(function Trig_CargoUnload))
set t=null
endfunction
//===============================================
// Player Resources Monitoring ver 1.01
// fires an event when gold/lumber has changed
// Use Event: "Game PRM_EVENT becomes Equal to 1.00" to detect gold changes
// Use Event: "Game PRM_EVENT becomes Equal to 2.00" to detect lumber changes
// Use "PRM_Player" to filter who's resource changed
// "PRM_Change" is the amount of gold (or lumber) player gain or lose on event
// (can be positive or negative).
// If boolean "PRM_MonitorPlayer[gui-player-number]" is set to false then corresponding
// player will not be monitored, anyway by default all (16) players are monitored.
// If you want to add/subtract/set resource *inside* PRM_EVENT trigger then:
// 1. set boolean "PRM_FireEvent" to false
// 2. add/subtract/set resource
// 3. set boolean "PRM_FireEvent" to true
// --------------------------------------
// happy mapping;] ZibiTheWand3r3r
//================================================
function PRM_Monitor takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer id = GetPlayerId(p)
local integer g = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)
local integer l = GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)
if not udg_PRM_MonitorPlayer[id+1] then // keep up-to date player's resources:
set udg_PRM_GoldLevel[id] = g
set udg_PRM_LumberLevel[id] = l
return false
endif
set udg_PRM_Player = p
if g != udg_PRM_GoldLevel[id] then //gold change detected
set udg_PRM_Change = g - udg_PRM_GoldLevel[id]
set udg_PRM_GoldLevel[id] = g
if udg_PRM_FireEvent then
set udg_PRM_EVENT = 0.00
set udg_PRM_EVENT = 1.00
endif
elseif l != udg_PRM_LumberLevel[id] then // lumber change detected
set udg_PRM_Change = l - udg_PRM_LumberLevel[id]
set udg_PRM_LumberLevel[id] = l
if udg_PRM_FireEvent then
set udg_PRM_EVENT = 0.00
set udg_PRM_EVENT = 2.00
endif
endif
return false
endfunction
//================================================
//================================================
function InitTrig_PRM takes nothing returns nothing
local integer id=0
set gg_trg_PRM = CreateTrigger( )
set udg_PRM_EVENT = 0.00
set udg_PRM_Change = 0
set udg_PRM_FireEvent = true
set udg_PRM_Player = Player(0)
loop
set udg_PRM_GoldLevel[id] = GetPlayerState(Player(id), PLAYER_STATE_RESOURCE_GOLD)
set udg_PRM_LumberLevel[id] = GetPlayerState(Player(id), PLAYER_STATE_RESOURCE_LUMBER)
set udg_PRM_MonitorPlayer[id+1] = true // for gui use range: 1-16
call TriggerRegisterPlayerStateEvent(gg_trg_PRM, Player(id), PLAYER_STATE_RESOURCE_GOLD, NOT_EQUAL, 0.00)
call TriggerRegisterPlayerStateEvent(gg_trg_PRM, Player(id), PLAYER_STATE_RESOURCE_GOLD, EQUAL, 0.00)
call TriggerRegisterPlayerStateEvent(gg_trg_PRM, Player(id), PLAYER_STATE_RESOURCE_LUMBER, NOT_EQUAL, 0.00)
call TriggerRegisterPlayerStateEvent(gg_trg_PRM, Player(id), PLAYER_STATE_RESOURCE_LUMBER, EQUAL, 0.00)
set id=id+1
exitwhen id == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(gg_trg_PRM, Condition(function PRM_Monitor))
endfunction
// 19.11.2018
/*
UnitCombatState uses external resources:
1. MergeSortByFlux , 2. function IsUnitInvulnerable
CSUnit_Attacked (unit <victim>, real <overLastXSeconds>) returns boolean
CSUnit_GetDamageDealtByUnit (unit <victim>, unit <attacker>) returns real
CSUnit_GetDamageDealtByPlayer (unit <victim>, player <p>) returns real
CSUnit_GetThreadAttacker [takes into consideration only damage dealt by attacker]
(unit <victim>, integer <x>, integer <y>, integer <maxRangeFromXY>, boolexpr <attackersFilter>) returns unit
CSUnit_GetPrimaryAttacker [takes into consideration damage dealt by attacker and his life]
(unit <victim>, integer <x>, integer <y>, integer <maxRangeFromXY>, boolexpr <attackersFilter>) returns unit
CSUnit_GetThreadPlayer (unit <victim>, integer <positionOnList>) returns player (positionOnList can be: 1 .. 25)
attackersFilter: CS_FILTR_any, CS_FILTR_onlyUnits, CS_FILTR_onlyHeroes, CS_FILTR_onlyStructures,
CS_FILTR_onlyGround, CS_FILTR_onlyFlying
*/
globals
constant real REMEMBER_DAMAGE_TIME = 15.00
constant integer MAX_INDEX_FOR_PLAYER = 24 // 0..23 for players plus 24 for neutral hostile
boolexpr CS_FILTR_any=null
boolexpr CS_FILTR_onlyUnits=null
boolexpr CS_FILTR_onlyHeroes=null
boolexpr CS_FILTR_onlyStructures=null
boolexpr CS_FILTR_onlyGround=null
boolexpr CS_FILTR_onlyFlying=null
hashtable g_CShash = InitHashtable() // used only by CombatState system
timer g_timerGame=CreateTimer()
group array g_attackersGroup // [victim's unit user data]
boolean array g_unitAttackedFlag // [victim's unit user data]
real array g_lastTimeDamaged // [victim's unit user data]
group cs_group=CreateGroup()
constant integer CS_BY_THREAD=0
constant integer CS_BY_THREAD_AND_HP=1
constant integer CS_KEY_PLAYER_PREFIX=50000 // plus "attacker player id" , reserve 50000 .. 5024
constant integer CS_KEY_THREAD_PLAYER_PREFIX = 50050 // plus positionOnList (1..25) .. reserve 50051 to 50075
constant integer CS_KEY_LAST_TIME_SORT_PLAYERS=50100 // in "CSSortThreadPlayers"
unit g_CSPrimaryAttacker=null //Get-Unit-PrimaryAttacker part
endglobals
//hash
// GetHandleId(victim) -->
// SaveReal - key is attackerId (GetUnitUserData) - saves attacker's damage dealt to victim
// SaveReal - key is (playerId + 50000) saves player attacker's damage dealt to victim
// SaveReal - CS_KEY_LAST_TIME_SORT_PLAYERS (50100) saves time to not repeat actions "CSSortThreadPlayers"
// SaveInteger - 50050 + positionOnList saves player's id who is on given position on thread list
// SaveInteger - CS_KEY_UNIT_TO_GROUP (50101) saves handle id of a group unit is in
function CSUnit_Attacked takes unit victim, real overLastXSeconds returns boolean
if overLastXSeconds > REMEMBER_DAMAGE_TIME then
set overLastXSeconds = REMEMBER_DAMAGE_TIME
endif
return TimerGetElapsed(g_timerGame) - g_lastTimeDamaged[GetUnitUserData(victim)] <= overLastXSeconds
endfunction
//for internal use mostly ..
function CSUnit_AttackedSimple takes unit victim returns boolean
return TimerGetElapsed(g_timerGame) - g_lastTimeDamaged[GetUnitUserData(victim)] <= REMEMBER_DAMAGE_TIME
endfunction
function CSUnit_GetDamageDealtByUnit takes unit victim, unit attacker returns real
return LoadReal(g_CShash, GetHandleId(victim), GetUnitUserData(attacker))
endfunction
function CSUnit_GetDamageDealtByPlayer takes unit victim, player p returns real
return LoadReal(g_CShash, GetHandleId(victim), (GetPlayerId(p) + CS_KEY_PLAYER_PREFIX))
endfunction
//-------------------------------------------------------------------------------------------------------------
//---------GET UNIT PRIMARY ATTACKER ---------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
function CSUnit_GetAttackerEx takes unit victim, integer x, integer y, integer maxRangeFromXY, boolexpr attackersFilter, integer byThreadByHp returns unit
local player p=GetOwningPlayer(victim)
local integer id=GetUnitUserData(victim)
local unit FoG=null
local real value=0.00
local real maxValue=0.00
set g_CSPrimaryAttacker=null
//---------------------
call GroupEnumUnitsInRange(cs_group, x, y, maxRangeFromXY, attackersFilter)
loop
set FoG = FirstOfGroup(cs_group)
exitwhen FoG == null
if (IsUnitVisible(FoG, p)) and IsUnitInGroup(FoG, g_attackersGroup[id]) and IsUnitEnemy(FoG, p) then
set value = CSUnit_GetDamageDealtByUnit(victim, FoG)
if byThreadByHp==CS_BY_THREAD_AND_HP then
set value = value / (GetWidgetLife(FoG)+1.00)
endif
if value>maxValue then
set maxValue=value
set g_CSPrimaryAttacker = FoG
endif
endif
call GroupRemoveUnit(cs_group, FoG)
endloop
call GroupClear(cs_group)
//---------------------
set p=null
return g_CSPrimaryAttacker
endfunction
//----------------------------------------
//takes into consideration only damage dealt by attacker:
function CSUnit_GetThreadAttacker takes unit victim, integer x, integer y, integer maxRangeFromXY, boolexpr attackersFilter returns unit
if CSUnit_AttackedSimple(victim) then
return CSUnit_GetAttackerEx(victim, x, y, maxRangeFromXY, attackersFilter, CS_BY_THREAD)
endif
return null
endfunction
//----------------------------------------
//takes into consideration damage dealt by attacker and his life:
function CSUnit_GetPrimaryAttacker takes unit victim, integer x, integer y, integer maxRangeFromXY, boolexpr attackersFilter returns unit
if CSUnit_AttackedSimple(victim) then
return CSUnit_GetAttackerEx(victim, x, y, maxRangeFromXY, attackersFilter, CS_BY_THREAD_AND_HP)
endif
return null
endfunction
//------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------GET THREAD PLAYER IDS ---------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------------------------
function CSUnit_SortThreadPlayers takes unit victim returns nothing
local real time = TimerGetElapsed(g_timerGame) // time stamp
local integer h_id=GetHandleId(victim)
local integer i=0
local integer positionOnList=0
local real lastTimeSavedPlayers = LoadReal(g_CShash, h_id, CS_KEY_LAST_TIME_SORT_PLAYERS)
if (time - lastTimeSavedPlayers) == 0.00 then // do not proceed, this function was called just right before
return
endif
call SaveReal(g_CShash, h_id, CS_KEY_LAST_TIME_SORT_PLAYERS, time)
//sorter:
//players index: 0..23 plus 24 as neutral hostile (MAX_INDEX_FOR_PLAYER = 24)
//Transfer the unsorted array to mergeSortValues array
set i=0 //start index
loop
exitwhen i > MAX_INDEX_FOR_PLAYER //end index
//set MSort_Values[i] = CSGetDamageDealtByPlayer(victim, i) //damage dealt by Player(i) to unit victim
set MSort_Values[i] = LoadReal(g_CShash, h_id, (i + CS_KEY_PLAYER_PREFIX)) //damage dealt by Player(i) to victim
set MSort_IndexInitial[i] = i
set i = i + 1
endloop
call MSort_Merge_Sort(0, MAX_INDEX_FOR_PLAYER, false) // "true = rosnaco, false=malejaco"
//end sorter
set i=0
loop
exitwhen i > MAX_INDEX_FOR_PLAYER
set positionOnList=i+1
//call SaveReal(g_CShash, h_id, CS_KEY_THREAD_PLAYER_PREFIX_DMG+positionOnList, MSort_Values[i]) // save sorted damage values
call SaveInteger(g_CShash, h_id, CS_KEY_THREAD_PLAYER_PREFIX+positionOnList, MSort_Indices[i]) // save sorted playerIds
set i=i+1
endloop
endfunction
//-----------------------------------------------------------------------------------------------
// positionOnList can be: 1 .. 25
function CSUnit_GetThreadPlayer takes unit victim, integer positionOnList returns player
local integer i=0
if positionOnList >= 1 and positionOnList <= (MAX_INDEX_FOR_PLAYER+1) then
call CSUnit_SortThreadPlayers(victim)
set i=LoadInteger(g_CShash, GetHandleId(victim), CS_KEY_THREAD_PLAYER_PREFIX+positionOnList)
return Player(i)
endif
return null
endfunction
//===========================================================================
//===== trigger's related functions: unit created/leaves/takesDamage ==============================
//===========================================================================
function Trig_CSUnit_EntersMap takes nothing returns boolean
//local integer h_id=GetHandleId(udg_UDexUnits[udg_UDex])
set g_attackersGroup[udg_UDex] = CreateGroup()
set g_lastTimeDamaged[udg_UDex] = -REMEMBER_DAMAGE_TIME
return false
endfunction
function Trig_CSUnit_LeavesMap takes nothing returns boolean
local integer h_id=GetHandleId(udg_UDexUnits[udg_UDex])
call FlushChildHashtable(g_CShash, h_id) //clean data connected to removed damagedUnit
call DestroyGroup(g_attackersGroup[udg_UDex])
set g_attackersGroup[udg_UDex] = null
return false
endfunction
//----------------------------------------------------------------------------------
function Trig_CSUnitOnDamage takes nothing returns boolean
local real time = TimerGetElapsed(g_timerGame) // time stamp ticking up ...
local integer id = GetUnitUserData(udg_GDD_DamagedUnit)
local integer h_id = GetHandleId(udg_GDD_DamagedUnit)
local integer attackerId = GetUnitUserData(udg_GDD_DamageSource)
local integer PLAYER_KEY = GetPlayerId(GetOwningPlayer(udg_GDD_DamageSource)) + CS_KEY_PLAYER_PREFIX // I assume that UnitUserData will never reach 50000
local real cumulatedDamage = 0.00
if not IsUnitEnemy(udg_GDD_DamagedUnit, GetOwningPlayer(udg_GDD_DamageSource)) then
return false
endif
//DAMAGED UNIT:
//save attacker damage
if IsUnitInGroup(udg_GDD_DamageSource, g_attackersGroup[id]) then
set cumulatedDamage = LoadReal(g_CShash, h_id, attackerId) // previous cumulated damage dealt by this attacker
endif
call SaveReal(g_CShash, h_id, attackerId, cumulatedDamage+udg_GDD_Damage) //save damage for attacker
//save attacker-player damage
set cumulatedDamage = LoadReal(g_CShash, h_id, PLAYER_KEY)
call SaveReal(g_CShash, h_id, PLAYER_KEY, cumulatedDamage+udg_GDD_Damage) //save damage for attacker-player
//save time:
set g_lastTimeDamaged[id] = time //save time "last-time-damaged" for damaged unit
set g_unitAttackedFlag[id]=true //used in periodic check for clean
//ATTACKER
if (GetUnitAbilityLevel(udg_GDD_DamageSource, 'Aloc')==0) then //if damageSource is NOT locusted
call GroupAddUnit(g_attackersGroup[id], udg_GDD_DamageSource)
endif
return false
endfunction
//===========================================================================
function F_Alive takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function F_OnlyHeroes takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function F_OnlyUnits takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO)) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function F_OnlyStructures takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function F_OnlyGround takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function F_OnlyFlying takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
//===========================================================================
function InitTrig_UnitCombatState takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00) // event: unit created
call TriggerAddCondition(t, Condition(function Trig_CSUnit_EntersMap))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00) // event: unit removed from the game
call TriggerAddCondition(t, Condition(function Trig_CSUnit_LeavesMap))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_GDD_Event", EQUAL, 0) //event: any unit takes damage
call TriggerAddCondition(t, Condition(function Trig_CSUnitOnDamage))
//---
call TimerStart(g_timerGame, 36000.00, false, null)//=10 hours
set CS_FILTR_any = Condition(function F_Alive)
set CS_FILTR_onlyHeroes = Condition(function F_OnlyHeroes)
set CS_FILTR_onlyUnits = Condition(function F_OnlyUnits)
set CS_FILTR_onlyStructures = Condition(function F_OnlyStructures)
set CS_FILTR_onlyGround = Condition(function F_OnlyGround)
set CS_FILTR_onlyFlying = Condition(function F_OnlyFlying)
endfunction
// 14.02.2019
//**************************************************************************************
// functions work for a group which has a trigger with event "unit dies" that removes dying unit from a group !
//**************************************************************************************
globals
group cs_swapGroup=CreateGroup()
unit cs_tempAtt=null
unit cs_tempAtt_P=null
unit cs_tempAtt_T=null
endglobals
//=======================================================
function CSZGroup_Attacked takes group g, real overLastXSeconds returns boolean
local real lastDamagedTime = LoadReal(zergHash, GetHandleId(g), KEY_GROUP_DAMAGED)
return (TimerGetElapsed(g_timerGame) - lastDamagedTime) <= overLastXSeconds
endfunction
//-----------------------------------------------------------------------------------------------------
//use z_filters here like g_filtrZEnemy etc
function CSZGroup_GetAttacker takes group g, integer x, integer y, integer maxDist, boolexpr attackersFilter returns unit
local unit FoG=null
local real dmg=0.00
local real maxDmg_T=0.00
local real maxDmg_P=0.00
set cs_tempAtt=null
set cs_tempAtt_T=null
set cs_tempAtt_P=null
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---thread attacker:
set cs_tempAtt=CSUnit_GetThreadAttacker(FoG, x, y, maxDist, attackersFilter)
set dmg=CSUnit_GetDamageDealtByUnit(FoG, cs_tempAtt)
if dmg>maxDmg_T then
set maxDmg_T=dmg
set cs_tempAtt_T=cs_tempAtt
endif
//---primary attacker:
set cs_tempAtt=CSUnit_GetPrimaryAttacker(FoG, x, y, maxDist, attackersFilter)
set dmg=CSUnit_GetDamageDealtByUnit(FoG, cs_tempAtt)
if dmg>maxDmg_P then
set maxDmg_P=dmg
set cs_tempAtt_P=cs_tempAtt
endif
//---
call GroupAddUnit(cs_swapGroup, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(cs_swapGroup)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(cs_swapGroup, FoG)
endloop
//---
if cs_tempAtt_P != null then
return cs_tempAtt_P
elseif cs_tempAtt_T != null then
return cs_tempAtt_T
endif
set cs_tempAtt = GetClosestUnit(x, y, maxDist, attackersFilter)
return cs_tempAtt
endfunction
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
function Trig_CS_ZergGroup takes nothing returns boolean
local integer id=GetUnitUserData(udg_GDD_DamagedUnit)
if (g_zGroupId[id] > 0) then
//save time "last-time-damaged" for damaged group
call SaveReal(zergHash, g_zGroupId[id], KEY_GROUP_DAMAGED, TimerGetElapsed(g_timerGame))
endif
return false
endfunction
//=======================================================================
function InitTrig_GroupCombatState takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_GDD_Event", EQUAL, 0) //event: any unit takes damage
call TriggerAddCondition(t, Condition(function Trig_CS_ZergGroup))
endfunction
// 14.02.2019
function Trig_CombatStatePeriodic_Clean takes nothing returns boolean
local integer i=1 // i = UnitUserData
loop //through all units in map
exitwhen i>udg_UDexMax
//UnitCombatState :
// flag is set only by "Trig_CSOnDamage", and here
if g_unitAttackedFlag[i]==true and (not CSUnit_AttackedSimple(udg_UDexUnits[i])) then
set g_unitAttackedFlag[i]=false //to prevent doing this clean every second
call GroupClear(g_attackersGroup[i])
call FlushChildHashtable(g_CShash, GetHandleId(udg_UDexUnits[i])) //clean data connected to damaged unit
endif
set i=i+1
endloop
return false
endfunction
//=======================================================================
function InitTrig_CombatStatePeriodic takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterTimerEvent(t, 1.00, true) //periodic
call TriggerAddCondition(t, Condition(function Trig_CombatStatePeriodic_Clean))
endfunction
/*
UnitChanneling (unit <u>) returns boolean
UnitSpellReady (unit <u>, integer <spellId>) returns boolean, [for one-level abilities]
GetUnitAbilityLastCastedTime (unit <caster>, integer <abilityId>) returns real
*/
globals
//hashtable g_spellStateHash = InitHashtable()
boolean array g_unitChanneling // [unit's unit user data]
endglobals
//-------------------------------------------------------------------------------------------
function UnitChanneling takes unit u returns boolean
return g_unitChanneling[GetUnitUserData(u)]
endfunction
//-------------------------------------------------------------------------------------------
function UnitSpellReady takes unit u, integer spellId returns boolean
local integer level = GetUnitAbilityLevel(u, spellId)
local boolean cdReady = (level>0) and (BlzGetUnitAbilityCooldownRemaining(u, spellId) == 0.00)
local boolean hasMana = (GetUnitState(u, UNIT_STATE_MANA) >= I2R(BlzGetAbilityManaCost(spellId, level)))
return cdReady and hasMana
endfunction
//-------------------------------------------------------------------------------------------
//function GetUnitAbilityLastCastedTime000 takes unit caster, integer abilityId returns real
//return LoadReal(g_spellStateHash, GetHandleId(caster), abilityId)
//endfunction
//-------------------------------------------------------------------------------------------
function Trig_Unit_StartChannel takes nothing returns boolean
set g_unitChanneling[GetUnitUserData(GetTriggerUnit())] = true
return false
endfunction
//-------------------------------------------------------------------------------------------
function Trig_Unit_EndChannel takes nothing returns boolean
set g_unitChanneling[GetUnitUserData(GetTriggerUnit())] = false
return false
endfunction
//it writes "time" of any abilities casted by any player:
//function Trig_Unit_SpellEffect takes nothing returns boolean
//call SaveReal(g_spellStateHash, GetHandleId(GetTriggerUnit()), GetSpellAbilityId(), TimerGetElapsed(g_timerGame))
//return false
//endfunction
//-------------------------------------------------------------------------------------------
//function Trig_SpellStateUnit_LeavesMap takes nothing returns boolean
//local integer h_id=GetHandleId(udg_UDexUnits[udg_UDex])
//call FlushChildHashtable(g_spellStateHash, h_id) //clean data connected to removed unit
//return false
//endfunction
//==================================================================
function InitTrig_SpellState takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CHANNEL) //triggers to set boolean variable "g_unitChanneling[unit user data]"
call TriggerAddCondition(t, Condition(function Trig_Unit_StartChannel))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
call TriggerAddCondition(t, Condition(function Trig_Unit_EndChannel))
/*
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT) // unit cast ability: remember time
call TriggerAddCondition(t, Condition(function Trig_Unit_SpellEffect))
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00) // event: unit removed from the game
call TriggerAddCondition(t, Condition(function Trig_SpellStateUnit_LeavesMap))
set t=null
*/
endfunction
globals
boolean DEV_MODE = false
constant integer MAX_PLAYERS = 4
player PLAYER_ZERG = Player(4)//gui 5 (yellow)
player PLAYER_VILLAGERS = Player(6)//gui 7 (green)
player PLAYER_PASSIVE=null
boolean array g_printTips
constant integer DUMMY = 'n001'
unit LIBRARY=null
unit CATHEDRAL=null
constant integer ABI_LIGHTNING_UNIT2UNIT = 'A00S'
integer g_playerHeroMaxLevel=1 //tracks max level of any player' hero
group ug=CreateGroup()
boolexpr g_filtr_Gr_notStrucNotMech
boolexpr g_filtr_Gr_notStruc
boolexpr g_filtr_notStruc
boolexpr g_filtr_alive
boolexpr g_filtr_defenderUnit1
boolexpr g_filtr_defendersEnemy=null
boolexpr g_filtr_onlyHeroes
boolexpr g_filtr_onlyUnits
fogmodifier array g_fog
constant integer WHITE=1
constant integer RED=2
constant integer GREEN=3
constant integer BLUE=4
constant integer YELLOW=5
//spells variables
unit array spellCaster
unit array spellTargetUnit
unit array spellMissle
real array spellDamage
real array spellDamage2
real array spellRadius
real array spellDuration
real array spellReal
real array spellAngle
real array spellDistance
integer array spellCounter
integer array spellLevel
integer array spellInteger
integer array spellUnitType
effect array spellEffect
effect array spellEffect2
boolean array spellBool
group array spellGroup
timer array spellTimer
group array spellGroupVictims
group array spellGroupToAdd
endglobals
native GetPlayerUnitTypeCount takes player p, integer unitid returns integer
/*AI*/ native GetUnitCount takes integer unitid returns integer
//=============================================
// IntToString used to display "Progress Bar" (floating text)
function IntToString takes integer i returns string
local string s=""
loop
exitwhen i <= 0
set s=s+"I"
set i=i-1
endloop
return s
endfunction
//-----------------------------------------------------------------------------------
function IsDefenderUnit takes unit u returns boolean
local player p=GetOwningPlayer(u)
return p==Player(0) or p==Player(1) or p==Player(2) or p==Player(3)
endfunction
function UnitMoving takes unit u returns boolean
return udg_UnitMoving[GetUnitUserData(u)]
endfunction
//-----------------------------------------------------------------------------------------------------------
// ----------------------------------filters: ---------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------
function Filtr_GroundNotStrucNotMech takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL))
endfunction
function Filtr_GroundNotStruc takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE))
endfunction
function Filtr_NotStruc takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE))
endfunction
function Filtr_Alive takes nothing returns boolean
return UnitAlive(GetFilterUnit())
endfunction
function Filtr_PlayerUnitDefenderUnit takes nothing returns boolean
// return UnitAlive(GetFilterUnit()) and IsDefenderUnit(GetFilterUnit()) and IsUnitVisible(GetFilterUnit(), AI_PLAYER_HADES) and (not IsUnitInvulnerable(GetFilterUnit()))
return false
endfunction
function Filtr_DefendersEnemy takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and IsUnitEnemy(GetFilterUnit(), Player(0)) and (not IsUnitInvulnerable(GetFilterUnit()))
endfunction
function Filtr_OnlyHeroes takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO)
endfunction
function Filtr_OnlyUnits takes nothing returns boolean
return UnitAlive(GetFilterUnit()) and (not IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO))
endfunction
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
function InitSettings takes nothing returns nothing
set PLAYER_PASSIVE=Player(PLAYER_NEUTRAL_PASSIVE)
set LIBRARY = gg_unit_h001_0067
set CATHEDRAL = gg_unit_h000_0073
//forces:
call SetPlayerName(PLAYER_ZERG, "Zerg")
call SetTwoPlayersEnemy(Player(0), PLAYER_ZERG)
call SetTwoPlayersEnemy(Player(1), PLAYER_ZERG)
call SetTwoPlayersEnemy(Player(2), PLAYER_ZERG)
call SetTwoPlayersEnemy(Player(3), PLAYER_ZERG)
set g_circle[0]=gg_unit_ncop_0011
set g_circle[1]=gg_unit_ncop_0013
set g_circle[2]=gg_unit_ncop_0017
set g_circle[3]=gg_unit_ncop_0014
set g_tavern[1]=gg_unit_n005_0006 //str
set g_tavern[2]=gg_unit_n006_0004 //agi
set g_tavern[3]=gg_unit_n007_0005 //int
set g_hero[0] = null
set g_hero[1] = null
set g_hero[2] = null
set g_hero[3] = null
//heroes array (start from "1")
set g_heroArray[1]='Nalc' //alchemist
set g_heroArray[2]='Hamg' //archmage
set g_heroArray[3]='Nbst' //beastmaster
set g_heroArray[4]='Obla' //blademaster
set g_heroArray[5]='Hblm' // blood mage
set g_heroArray[6]='Nbrn' //dark ranger
set g_heroArray[7]='Edem' //demon hunter
set g_heroArray[8]='Ofar' // far seer
set g_heroArray[9]='Ekee' // keeper
set g_heroArray[10]='Hmkg'// mountain king
set g_heroArray[11]='Hpal' // paladin
set g_heroArray[12]='Npbm' //pandaren
set g_heroArray[13]='Emoo' // priestess
set g_heroArray[14]='Oshd' // shadow hunter
set g_heroArray[15]='Otch' // tauren
set g_heroArray[16]='Ntin' //tinker
set g_heroArray[17]='Ewar'
set g_heroesQuantity=17
endfunction
//================================================================
//================================================================
function Trig_Init_Actions takes nothing returns nothing
local integer i=0
//set filters:
set g_filtr_Gr_notStrucNotMech = Condition(function Filtr_GroundNotStrucNotMech)
set g_filtr_Gr_notStruc = Condition(function Filtr_GroundNotStruc)
set g_filtr_notStruc = Condition(function Filtr_NotStruc)
set g_filtr_alive = Condition(function Filtr_Alive)
set g_filtr_defenderUnit1 = Condition(function Filtr_PlayerUnitDefenderUnit)
set g_filtr_defendersEnemy = Condition(function Filtr_DefendersEnemy)
set g_filtr_onlyHeroes = Condition(function Filtr_OnlyHeroes)
set g_filtr_onlyUnits = Condition(function Filtr_OnlyUnits)
//create groups/timers for spells:
set i=1
loop
exitwhen i>20 // max number of spell types
set spellGroup[i] = CreateGroup()
set spellTimer[i] = CreateTimer()
set i=i+1
endloop
// fog - uses wait!!
set i=0
loop
set g_fog[i]=CreateFogModifierRect(Player(i), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false)
call FogModifierStart(g_fog[i]) //vision on all map for 5 sec:
set g_printTips[i]=false
set i=i+1
exitwhen i==MAX_PLAYERS
endloop
call TriggerSleepAction(5.00)
set i=0
loop
call DestroyFogModifier(g_fog[i])
set i=i+1
exitwhen i==MAX_PLAYERS
endloop
//end fog
endfunction
//===========================================================================
function InitTrig_Init takes nothing returns nothing
set gg_trg_Init = CreateTrigger( )
call TriggerAddAction( gg_trg_Init, function Trig_Init_Actions )
call InitSettings()
endfunction
globals
trigger trg_dayON
trigger trg_nightON
boolean isDay = false
endglobals
//============================================
function Trg_DayOn takes nothing returns nothing
if GetFloatGameState(GAME_STATE_TIME_OF_DAY) < 18.00 then
set isDay=true
call MsgDev("DAY is ON")
endif
endfunction
//------------------------------------------------------------------
function Trg_NightOn takes nothing returns nothing
set isDay=false
call MsgDev("NIGHT is ON")
endfunction
//========================================================
function InitTrig_Environment takes nothing returns nothing
//--------
set trg_dayON = CreateTrigger()
call TriggerRegisterGameStateEventTimeOfDay( trg_dayON, GREATER_THAN_OR_EQUAL, 6.00 )
call TriggerAddAction( trg_dayON, function Trg_DayOn )
//--------
set trg_nightON = CreateTrigger()
call TriggerRegisterGameStateEventTimeOfDay( trg_nightON, EQUAL, 18.00 )
call TriggerRegisterGameStateEventTimeOfDay( trg_nightON, EQUAL, 0.00 )
call TriggerAddAction( trg_nightON, function Trg_NightOn )
endfunction
function Trig_Tips_Conditions takes nothing returns boolean
local integer id=GetPlayerId(GetTriggerPlayer())
if g_printTips[id] then
set g_printTips[id]=false
call Msg(GetTriggerPlayer(), "Tips: OFF")
else
set g_printTips[id]=true
call Msg(GetTriggerPlayer(), "Tips: ON")
endif
return false
endfunction
function Trig_DevMode takes nothing returns boolean
if DEV_MODE then
call Msg(GetTriggerPlayer(), "Dev Mode: OFF")
set DEV_MODE=false
else
set DEV_MODE=true
call Msg(GetTriggerPlayer(), "Dev Mode: ON")
endif
return false
endfunction
//===========================================================================
function InitTrig_Tips takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterPlayerChatEvent( t, Player(0), "tips", true )
call TriggerRegisterPlayerChatEvent( t, Player(1), "tips", true )
call TriggerRegisterPlayerChatEvent( t, Player(2), "tips", true )
call TriggerRegisterPlayerChatEvent( t, Player(3), "tips", true )
call TriggerAddCondition( t, Condition( function Trig_Tips_Conditions ) )
set t=CreateTrigger()
call TriggerRegisterPlayerChatEvent( t, Player(0), "devmode", true )
call TriggerRegisterPlayerChatEvent( t, Player(1), "devmode", true )
call TriggerRegisterPlayerChatEvent( t, Player(2), "devmode", true )
call TriggerRegisterPlayerChatEvent( t, Player(3), "devmode", true )
call TriggerAddCondition( t, Condition( function Trig_DevMode ) )
endfunction
function DisplayPlayer takes integer playerId returns nothing
local string status="?"
local string level=""
local string name
local string array color
set color[0]="|cffff6347"
set color[1]="|cff87cefa"
set color[2]="|cff00fa9a"
set color[3]="|cffdda0dd"
set name = color[playerId] + GetPlayerName(Player(playerId)) + "|r"
if g_hero[playerId] != null then
set level = I2S(GetHeroLevel(g_hero[playerId]))
set name = name + " |cffd4d0c8(" + GetUnitName(g_hero[playerId]) + ": "+level+")|r"
endif
if GetPlayerSlotState(Player(playerId)) == PLAYER_SLOT_STATE_PLAYING then
set status=" *" + "|cffd4d0c8in game|r" + "*"
elseif GetPlayerSlotState(Player(playerId)) == PLAYER_SLOT_STATE_LEFT then
set status=" *" + "|cff808080has left|r" + "*"
elseif GetPlayerSlotState(Player(playerId)) == PLAYER_SLOT_STATE_EMPTY then
set status=" *" + "|cff808080empty slot|r" + "*"
endif
set name=name+status
call Msg(GetTriggerPlayer(), name)
endfunction
function Trig_PlayersStatusDisplay_Actions takes nothing returns nothing
call DisplayPlayer(0)
call DisplayPlayer(1)
call DisplayPlayer(2)
call DisplayPlayer(3)
endfunction
//===========================================================================
function InitTrig_PlayersStatusDisplay takes nothing returns nothing
set gg_trg_PlayersStatusDisplay = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_PlayersStatusDisplay, Player(0), "players", true )
call TriggerRegisterPlayerChatEvent( gg_trg_PlayersStatusDisplay, Player(1), "players", true )
call TriggerRegisterPlayerChatEvent( gg_trg_PlayersStatusDisplay, Player(2), "players", true )
call TriggerRegisterPlayerChatEvent( gg_trg_PlayersStatusDisplay, Player(3), "players", true )
call TriggerAddAction( gg_trg_PlayersStatusDisplay, function Trig_PlayersStatusDisplay_Actions )
endfunction
globals
boolean GAME_OVER=false
boolean GAME_VICTORY=false
real gameOverReal=0.00
boolean GAME_DIFFICULTY_NORMAL = true
endglobals
//--------------------------------------------------------------------------------------------------
//flag=true for victory
function GameSetVictoryDefeat takes boolean flag returns nothing
set GAME_VICTORY=flag
set GAME_OVER=true
if (TimerGetRemaining(timerGameMode)>0.00) then
call PauseTimer(timerGameMode)
set g_lb_countdown=false
endif
set gameOverReal = 0.00
set gameOverReal = 1.00
set gameOverReal = 0.00
endfunction
//--------------------------------------------------------------------------------------------------
//used in trigger "SpawningPool" (functionTrig_SpwningPoolDies_Actions)
//used here in TriggerAddAction(t, function CheckGameOver)
//used as action for timer "timerGameMode" in TimerSelectHero_Expires function
function CheckGameOver takes nothing returns nothing
local integer i=1
local integer alivePools=0
local boolean playersBuildingDead=(not UnitAlive(CATHEDRAL)) or (not UnitAlive(LIBRARY))
local boolean timerGameExpires = (TimerGetRemaining(timerGameMode)<=0.00)
if GAME_OVER then //prevent running more then once
return
endif
loop
exitwhen i>6
if UnitAlive(zergSpawningPool[i]) and (not IsUnitHidden(zergSpawningPool[i])) then
set alivePools=alivePools+1
endif
set i=i+1
endloop
if playersBuildingDead then // players lose always - if key building was destroyed
call GameSetVictoryDefeat(false) //defeat
return
endif
if alivePools==0 then // players win always - if all pools are dead
call GameSetVictoryDefeat(true) //victory
return
endif
if timerGameExpires then //if time is up:
if GAME_DIFFICULTY_NORMAL and (not playersBuildingDead) then
call GameSetVictoryDefeat(true) //victory
return
endif
if (not GAME_DIFFICULTY_NORMAL) and (alivePools>0) then // if "hard"
call GameSetVictoryDefeat(true) //defeat
return
endif
endif
endfunction
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
function Trig_GameOver_Actions takes nothing returns nothing
local integer i=1
loop
exitwhen i>6
if UnitAlive(zergSpawningPool[i]) and (not IsUnitHidden(zergSpawningPool[i])) then
call SetUnitInvulnerable(zergSpawningPool[i], true)
endif
set i=i+1
endloop
if UnitAlive(LIBRARY) then
call SetUnitInvulnerable(LIBRARY, true)
endif
if UnitAlive(CATHEDRAL) then
call SetUnitInvulnerable(CATHEDRAL, true)
endif
if GAME_VICTORY then
call MsgAll("|c0000FF00Congratulations! You won the game!|r")
call TriggerSleepAction(20.00)
call CustomVictoryBJ( Player(0), true, true )
call CustomVictoryBJ( Player(1), true, true )
call CustomVictoryBJ( Player(2), true, true )
call CustomVictoryBJ( Player(3), true, true )
else
call MsgAll("|c00FF0000Alien forces have defeated you!|r")
call TriggerSleepAction(20.00)
call CustomDefeatBJ( Player(0), "Defeat!" )
call CustomDefeatBJ( Player(1), "Defeat!" )
call CustomDefeatBJ( Player(2), "Defeat!" )
call CustomDefeatBJ( Player(3), "Defeat!" )
endif
endfunction
//===========================================================================
function InitTrig_Game takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterUnitEvent(t, LIBRARY, EVENT_UNIT_DEATH)
call TriggerRegisterUnitEvent(t, CATHEDRAL, EVENT_UNIT_DEATH)
call TriggerAddAction(t, function CheckGameOver)
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "gameOverReal", EQUAL, 1)
call TriggerAddAction(t, function Trig_GameOver_Actions)
endfunction
globals
constant integer STARTING_GOLD=100
constant integer TIME_TO_PICK_HERO = 60
constant integer GAME_TIME_MODE_NORMAL = 60 * 30 // 30 min
constant integer GAME_TIME_MODE_HARD = 60 * 40 // 40 min
timer g_timerUpdateLB=CreateTimer()
real g_lb_time=0.00
integer g_lb_index0=0
integer g_lb_index1=0
integer g_lb_index2=0
integer g_lb_index3=0
integer g_lb_index4=0
boolean g_lb_countdown=false
constant string GAME_MODE_NORMAL_DESC = "Game mode: normal. To win: protect Library and Cathedral buildings for 30min."
constant string GAME_MODE_HARD_DESC = "Game mode: hard. To win: kill all Zerg's Spawning Pools in 40min. Do not let Zerg destroy Library and Cathedral buildings."
integer g_heroesQuantity=0
quest g_quest1=null
timer timerGameMode=CreateTimer()
timerdialog timerWindow=null
unit array g_circle
unit array g_tavern
unit array g_hero
integer array g_heroArray
integer g_playersQuantity = 4
boolean array g_playerSlotEmpty // [player id]
constant integer ABI_PICK_RANDOM_HERO='A013' // circle ability
endglobals
//--------------------------------------------------------------------------------------
function LBConvertRealToTimeString takes real r returns string
local integer i=R2I(r)
local integer min=i/60
local integer sec=i-(min*60)
local string s="Time left "+I2S(min)+":"
if sec<10 then
set s=s+"0"+I2S(sec)
else
set s=s+I2S(sec)
endif
return s
endfunction
//-------------------------------------------------------------------------------------
function LB_SetGameModeHard takes nothing returns nothing
call LeaderboardSetLabelBJ( bj_lastCreatedLeaderboard, "Mode: HARD")
set g_lb_time=GAME_TIME_MODE_HARD
call LeaderboardSetItemLabel(bj_lastCreatedLeaderboard, g_lb_index4, LBConvertRealToTimeString(g_lb_time)) //time
endfunction
//-------------------------------------------------------------------------------------
function UpdateLB takes nothing returns nothing //update every second
//attackers:
call LeaderboardSetItemLabel(bj_lastCreatedLeaderboard, g_lb_index1, "Library ["+I2S(g_waveNo_L)+"]")
call LeaderboardSetItemLabel(bj_lastCreatedLeaderboard, g_lb_index2, "Cathedral ["+I2S(g_waveNo_C)+"]")
call LeaderboardSetItemValue(bj_lastCreatedLeaderboard, g_lb_index1, g_totalAttackers_Library)
call LeaderboardSetItemValue(bj_lastCreatedLeaderboard, g_lb_index2, g_totalAttackers_Cathedral)
//income
call LeaderboardSetItemValue(bj_lastCreatedLeaderboard, g_lb_index3, g_incomePercent)
//time
if g_lb_countdown then
set g_lb_time=g_lb_time-1.00
if g_lb_time>=0 then
call LeaderboardSetItemLabel(bj_lastCreatedLeaderboard, g_lb_index4, LBConvertRealToTimeString(g_lb_time))
endif
endif
endfunction
//-------------------------------------------------------------------------------------
function CreateLB takes nothing returns nothing
local leaderboard lb
call CreateLeaderboardBJ( bj_FORCE_ALL_PLAYERS, "Mode: NORMAL" )
set lb=bj_lastCreatedLeaderboard
call LeaderboardAddItemBJ( Player(0), lb, "Attackers count", 0 )
call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, Player(0)), 255, 255, 255, 210)
call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, Player(0)), 255, 116, 13, 0)//transparent
call LeaderboardAddItemBJ( Player(1), lb, "Library", 0 )
call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, Player(1)), 255, 116, 13, 255)
call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, Player(1)), 255, 116, 13, 255)
call LeaderboardAddItemBJ( Player(2), lb, "Cathedral", 0 )
call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, Player(2)), 255, 116, 13, 255)
call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, Player(2)), 255, 116, 13, 255)
call LeaderboardAddItemBJ(Player(3), lb, "Income (%)", 100)
call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, Player(3)), 155, 155, 155, 255)
call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, Player(3)), 155, 155, 155, 255)
call LeaderboardAddItemBJ( Player(4), lb, "Time left ", 0 )
call LeaderboardSetItemLabelColor(lb, LeaderboardGetPlayerIndex(lb, Player(4)), 255, 255, 255, 210)
call LeaderboardSetItemValueColor(lb, LeaderboardGetPlayerIndex(lb, Player(4)), 255, 116, 13, 0)//transparent
set g_lb_index0= LeaderboardGetPlayerIndex(lb, Player(0))
set g_lb_index1= LeaderboardGetPlayerIndex(lb, Player(1))
set g_lb_index2= LeaderboardGetPlayerIndex(lb, Player(2))
set g_lb_index3= LeaderboardGetPlayerIndex(lb, Player(3))
set g_lb_index4= LeaderboardGetPlayerIndex(lb, Player(4))
set g_lb_time=GAME_TIME_MODE_NORMAL
call LeaderboardSetItemLabel(bj_lastCreatedLeaderboard, g_lb_index4, LBConvertRealToTimeString(g_lb_time)) //time
endfunction
//--------------------------------------------------------------------------------------
// used in PlayerLeft trigger and "Trig_GameMode_Actions"
//--------------------------------------------------------------------------------------
function CountPlayingPlayers takes nothing returns integer
local integer i=0
local integer count=0
loop
exitwhen i>3
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
set count=count+1
set g_playerSlotEmpty[i]=false
else
set g_playerSlotEmpty[i]=true
endif
set i=i+1
endloop
set g_playersQuantity = count
return count
endfunction
//---------------------------------------------------------------------------------
function SharePlayersControlAtStart takes nothing returns nothing
local integer i=0
loop
exitwhen i>3
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_LEFT then
call ShareEverythingWithTeam(Player(i))
endif
set i=i+1
endloop
endfunction
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
function TimerSelectHero_Expires takes nothing returns nothing
local integer i=0
local integer a=1
local integer count=0
local integer heroId=0
local player pla
call MsgAll("Time for picking a hero is up.")
call DisableTrigger(GetTriggeringTrigger())// it is trigger action
call DisableTrigger(gg_trg_PickForAbsentPlayer)
loop
exitwhen i>3
if g_hero[i] == null then //give random hero for those who did not pick one
set pla=Player(i)
set a = GetRandomInt(1, g_heroesQuantity)
set heroId = g_heroArray[a]//use local integer cause global g_heroArray can be changed in TavernSells trigger
call MsgAll("Random hero for player "+GetPlayerName(pla)+": "+ GetObjectName(heroId))
call IssueNeutralImmediateOrderById(pla, g_tavern[1], heroId)
call IssueNeutralImmediateOrderById(pla, g_tavern[2], heroId)
call IssueNeutralImmediateOrderById(pla, g_tavern[3], heroId)
endif
set i=i+1
endloop
call TriggerSleepAction(3.00)
call KillUnit(g_tavern[1])
call KillUnit(g_tavern[2])
call KillUnit(g_tavern[3])
//
if GAME_DIFFICULTY_NORMAL then
call QuestMessageBJ( GetPlayersAll(), bj_QUESTMESSAGE_DISCOVERED, "Game Mode: NORMAL" )
call QuestSetDescription(g_quest1, GAME_MODE_NORMAL_DESC)
call TimerStart(timerGameMode, GAME_TIME_MODE_NORMAL, false, function CheckGameOver)//30 min
else
call TimerStart(timerGameMode, GAME_TIME_MODE_HARD, false, function CheckGameOver)//40 min
endif
call TimerDialogSetTitle(timerWindow, "Time left")
call TimerDialogDisplay(timerWindow, false)
set g_lb_countdown=true //let the leaderboard count down time
endfunction
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
function Trig_GameModeHard takes nothing returns nothing
call DisableTrigger(GetTriggeringTrigger())
set GAME_DIFFICULTY_NORMAL=false
call QuestMessageBJ( GetPlayersAll(), bj_QUESTMESSAGE_DISCOVERED, "Game Mode: HARD" )
call QuestSetDescription(g_quest1, GAME_MODE_HARD_DESC)
call LB_SetGameModeHard()
//make some setting for game mode HARD:
call TriggerExecute(gg_trg_Hard)
endfunction
//----------------------------------------------------------------------------------------------------------------
// 2 seconds of the game
//----------------------------------------------------------------------------------------------------------------
function Trig_GameMode_Actions takes nothing returns nothing
local trigger t=CreateTrigger()
local trigger trg_timerExpires=CreateTrigger()
local integer i=0
call CountPlayingPlayers() //writes global var
call SetPlayerState(Player(0), PLAYER_STATE_RESOURCE_GOLD, STARTING_GOLD+GetPlayerState(Player(0), PLAYER_STATE_RESOURCE_GOLD))
call SetPlayerState(Player(1), PLAYER_STATE_RESOURCE_GOLD, STARTING_GOLD+GetPlayerState(Player(1), PLAYER_STATE_RESOURCE_GOLD))
call SetPlayerState(Player(2), PLAYER_STATE_RESOURCE_GOLD, STARTING_GOLD+GetPlayerState(Player(2), PLAYER_STATE_RESOURCE_GOLD))
call SetPlayerState(Player(3), PLAYER_STATE_RESOURCE_GOLD, STARTING_GOLD+GetPlayerState(Player(3), PLAYER_STATE_RESOURCE_GOLD))
call TriggerRegisterTimerExpireEvent(trg_timerExpires, timerGameMode)
call TriggerAddAction(trg_timerExpires, function TimerSelectHero_Expires)
call TimerStart(timerGameMode, TIME_TO_PICK_HERO, false, null)
set timerWindow = CreateTimerDialog(timerGameMode)
call TimerDialogSetTitle(timerWindow, "Select Hero")
call TimerDialogDisplay(timerWindow, true)
call ShowUnit(g_tavern[1], true)
call ShowUnit(g_tavern[2], true)
call ShowUnit(g_tavern[3], true)
call UnitAddAbility(g_circle[0], ABI_PICK_RANDOM_HERO)
call UnitAddAbility(g_circle[1], ABI_PICK_RANDOM_HERO)
call UnitAddAbility(g_circle[2], ABI_PICK_RANDOM_HERO)
call UnitAddAbility(g_circle[3], ABI_PICK_RANDOM_HERO)
call MsgAll("Select your hero.")
call SharePlayersControlAtStart()
call EnableTrigger(gg_trg_PickForAbsentPlayer)
set GAME_DIFFICULTY_NORMAL=true
call CreateQuestBJ( bj_QUESTTYPE_REQ_DISCOVERED, "Game", GAME_MODE_NORMAL_DESC+"|n|n"+GAME_MODE_HARD_DESC, "ReplaceableTextures\\CommandButtons\\BTNAmbush.blp" )
set g_quest1=bj_lastCreatedQuest
call CreateQuestBJ( bj_QUESTTYPE_OPT_DISCOVERED, "Absent player", "One can pick a hero for absent player by typing: |cffffcc00heroX name|r where 'X' is player id (1..to..4) and 'name' is hero name.|nList of hero names:|n"+LIST_HERO_NAMES1+LIST_HERO_NAMES2, "ReplaceableTextures\\CommandButtons\\BTNAmbush.blp" )
call CreateQuestBJ( bj_QUESTTYPE_OPT_DISCOVERED, "Commands", "To display players status type: |cffffcc00players|r, on/off tips: |cffffcc00tips|r", "ReplaceableTextures\\CommandButtons\\BTNAmbush.blp" )
call MultiboardAllowDisplayBJ( false ) //hide all MBs
call CreateLB()
call TimerStart(g_timerUpdateLB, 1.00, true, function UpdateLB)
call TriggerSleepAction(1.00)
set i=0
loop //find top player
exitwhen i>3
exitwhen GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING
set i=i+1
endloop
call TriggerRegisterPlayerChatEvent(t, Player(i), "hard", true)
call TriggerAddAction(t, function Trig_GameModeHard)
call MsgAll(GetPlayerName(Player(i))+" can change Game Mode to 'hard'.")
call Msg(Player(i), "You can change Game Mode to hard by typing |cffffcc00hard|r")
// ---
endfunction
//===========================================================================
function InitTrig_GameMode takes nothing returns nothing
set gg_trg_GameMode = CreateTrigger( )
call TriggerRegisterTimerEventSingle( gg_trg_GameMode, 2.00 )
call TriggerAddAction( gg_trg_GameMode, function Trig_GameMode_Actions )
call ShowUnit(g_tavern[1], false)
call ShowUnit(g_tavern[2], false)
call ShowUnit(g_tavern[3], false)
endfunction
function AllPlayersHaveHero takes nothing returns boolean
return (g_hero[0] != null) and (g_hero[1] != null) and (g_hero[2] != null) and (g_hero[3] != null)
endfunction
//---------------------------------------------------------------------------------
function Trig_TavernSells_Actions takes nothing returns nothing
local unit hero=GetSoldUnit()
local integer heroId=GetUnitTypeId(hero)
local player pla=GetOwningPlayer(hero)
local integer i=GetPlayerId(pla)
local integer a=1
call ShowUnit(g_circle[i], false)
call SetPlayerTechMaxAllowed(Player(0), heroId, 0) // set hero unavailable
call SetPlayerTechMaxAllowed(Player(1), heroId, 0)
call SetPlayerTechMaxAllowed(Player(2), heroId, 0)
call SetPlayerTechMaxAllowed(Player(3), heroId, 0)
set g_hero[i]=hero
call TriggerRegisterUnitEvent(gg_trg_PlayerHeroes, g_hero[i], EVENT_UNIT_DEATH)
loop //remove hero from the list
exitwhen a>g_heroesQuantity
if heroId == g_heroArray[a] then
set g_heroArray[a] = g_heroArray[g_heroesQuantity]
set g_heroesQuantity = g_heroesQuantity - 1
exitwhen true
endif
set a=a+1
endloop
if AllPlayersHaveHero() and TimerGetRemaining(timerGameMode)>5.00 then//cut timer to 5sec
call TimerStart(timerGameMode, 5.00, false, null)
endif
set hero=null
set pla=null
endfunction
//===========================================================================
function InitTrig_TavernSells takes nothing returns nothing
set gg_trg_TavernSells = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_TavernSells, gg_unit_n005_0006, EVENT_UNIT_SELL )
call TriggerRegisterUnitEvent( gg_trg_TavernSells, gg_unit_n006_0004, EVENT_UNIT_SELL )
call TriggerRegisterUnitEvent( gg_trg_TavernSells, gg_unit_n007_0005, EVENT_UNIT_SELL )
call TriggerAddAction( gg_trg_TavernSells, function Trig_TavernSells_Actions )
endfunction
globals
constant string LIST_HERO_NAMES1 = "alchemist, archmage, beastmaster, blademaster, bloodmage, darkranger, demonhunter, farseer, keeper, mountainking, "
constant string LIST_HERO_NAMES2 = "paladin, pandaren, priestess, shadowhunter, tauren, tinker, warden"
endglobals
function ConvertStringToHeroId takes string s returns integer
if s=="alchemist" then
return 'Nalc'
elseif s=="archmage" then
return 'Hamg'
elseif s=="beastmaster" then
return 'Nbst'
elseif s=="blademaster" then
return 'Obla'
elseif s=="bloodmage" then
return 'Hblm'
elseif s=="darkranger" then
return 'Nbrn'
elseif s=="demonhunter" then
return 'Edem'
elseif s=="farseer" then
return 'Ofar'
elseif s=="keeper" then
return 'Ekee'
elseif s=="mountainking" then
return 'Hmkg'
elseif s=="paladin" then
return 'Hpal'
elseif s=="pandaren" then
return 'Npbm'
elseif s=="priestess" then
return 'Emoo'
elseif s=="shadowhunter" then
return 'Oshd'
elseif s=="tauren" then
return 'Otch'
elseif s=="tinker" then
return 'Ntin'
elseif s=="warden" then
return 'Ewar'
endif
return 0
endfunction
//===================================================
// heroX nameOfHero
function Trig_PickAbsent_Actions takes nothing returns nothing
local string s=GetEventPlayerChatString()
local integer i=S2I(SubStringBJ(s, 5, 5)) // gui player id
local string name=SubStringBJ(s, 7, StringLength(s))
local integer heroId=ConvertStringToHeroId(name)
set i=i-1
if i>=0 and i<=3 and (heroId != 0) then
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_EMPTY or GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_LEFT then
call IssueNeutralImmediateOrderById(Player(i), g_tavern[1], heroId)
call IssueNeutralImmediateOrderById(Player(i), g_tavern[2], heroId)
call IssueNeutralImmediateOrderById(Player(i), g_tavern[3], heroId)
else
call Msg(GetTriggerPlayer(), GetPlayerName(Player(i))+" is playing!")
endif
else
call Msg(GetTriggerPlayer(), "Error: please check entered player id and hero name.")
endif
endfunction
//===========================================================================
function InitTrig_PickForAbsentPlayer takes nothing returns nothing
set gg_trg_PickForAbsentPlayer = CreateTrigger( )
call DisableTrigger(gg_trg_PickForAbsentPlayer)
call TriggerRegisterPlayerChatEvent(gg_trg_PickForAbsentPlayer, Player(0), "hero", false)
call TriggerRegisterPlayerChatEvent(gg_trg_PickForAbsentPlayer, Player(1), "hero", false)
call TriggerRegisterPlayerChatEvent(gg_trg_PickForAbsentPlayer, Player(2), "hero", false)
call TriggerRegisterPlayerChatEvent(gg_trg_PickForAbsentPlayer, Player(3), "hero", false)
call TriggerAddAction( gg_trg_PickForAbsentPlayer, function Trig_PickAbsent_Actions )
endfunction
function Trig_ci_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A013'
endfunction
function Trig_ci_Actions takes nothing returns nothing
local integer heroId=0
local integer i=GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set heroId = g_heroArray[GetRandomInt(1, g_heroesQuantity)]
call IssueNeutralImmediateOrderById(Player(i), g_tavern[1], heroId)
call IssueNeutralImmediateOrderById(Player(i), g_tavern[2], heroId)
call IssueNeutralImmediateOrderById(Player(i), g_tavern[3], heroId)
//+50 gold
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD)+50)
endfunction
//===========================================================================
function InitTrig_PickRandomHero takes nothing returns nothing
set gg_trg_PickRandomHero = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_PickRandomHero, gg_unit_ncop_0011, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_PickRandomHero, gg_unit_ncop_0013, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_PickRandomHero, gg_unit_ncop_0017, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_PickRandomHero, gg_unit_ncop_0014, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_PickRandomHero, Condition( function Trig_ci_Conditions ) )
call TriggerAddAction( gg_trg_PickRandomHero, function Trig_ci_Actions )
endfunction
globals
real eventPlayerHeroLevelUp=0.00
integer array g_reviveX //[player id]
integer array g_reviveY //[player id]
unit array g_reviveBuilding //[player id]
endglobals
function Trig_HeroDies_Actions takes nothing returns nothing
local unit hero=GetTriggerUnit()
local player pla=GetOwningPlayer(hero)
local integer lvl=GetHeroLevel(hero)
local real delay=4.00+(I2R(lvl)*1.00)
local integer id=GetPlayerId(pla)
local integer gld=GetPlayerState(pla, PLAYER_STATE_RESOURCE_GOLD)
local integer cost=40+(lvl*10)
call SetPlayerState(pla, PLAYER_STATE_RESOURCE_GOLD, gld-cost)
call DisplayTimedTextToPlayer(pla, 0.00, 0.00, delay, "|c0080FF00Revive in "+I2S(R2I(delay))+" seconds.|r |c00FF0000-"+I2S(cost)+" gold.|r")
call TriggerSleepAction(delay)
if not GAME_OVER then
call ReviveHero(hero, g_reviveX[id], g_reviveY[id], true)
endif
set pla=null
set hero=null
endfunction
//===========================================================================
function Trig_HeroLevelUp_Conditions takes nothing returns boolean
local unit u=GetLevelingUnit()
local integer lvl=GetHeroLevel(u)
if u==g_hero[0] or u==g_hero[1] or u==g_hero[2] or u==g_hero[3] then
if lvl>g_playerHeroMaxLevel then
set g_playerHeroMaxLevel=lvl
set eventPlayerHeroLevelUp=1.00
set eventPlayerHeroLevelUp=0.00
endif
endif
set u=null
return false
endfunction
//===========================================================================
function Trig_SetReviveLoc_Conditions takes nothing returns boolean
local unit u=GetTriggerUnit()
if u==g_hero[0] or u==g_hero[1] or u==g_hero[2] or u==g_hero[3] then
set u=null
return true
endif
set u=null
return false
endfunction
function Trig_SetReviveLocLibrary_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer id=GetPlayerId(GetOwningPlayer(u))
if g_reviveBuilding[id]==CATHEDRAL or g_reviveBuilding[id]==null then
set g_reviveBuilding[id]=LIBRARY
set g_reviveX[id]=1280
set g_reviveY[id]=390
call Msg(GetOwningPlayer(u), "|c0000FFFFRevive at Library position.|r")
endif
set u=null
endfunction
function Trig_SetReviveLocCathedral_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer id=GetPlayerId(GetOwningPlayer(u))
if g_reviveBuilding[id]==LIBRARY or g_reviveBuilding[id]==null then
set g_reviveBuilding[id]=CATHEDRAL
set g_reviveX[id]=-1024
set g_reviveY[id]=-1700
call Msg(GetOwningPlayer(u), "|c0000FFFFRevive at Cathedral position.|r")
endif
set u=null
endfunction
//===========================================================================
function InitTrig_PlayerHeroes takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterUnitInRangeSimple(t, 400.00, gg_unit_h001_0067 ) //library
call TriggerAddCondition(t, Condition( function Trig_SetReviveLoc_Conditions ) )
call TriggerAddAction(t, function Trig_SetReviveLocLibrary_Actions)
set t = CreateTrigger( )
call TriggerRegisterUnitInRangeSimple(t, 400.00, gg_unit_h000_0073 ) //cathedral
call TriggerAddCondition(t, Condition( function Trig_SetReviveLoc_Conditions ) )
call TriggerAddAction(t, function Trig_SetReviveLocCathedral_Actions )
set g_reviveBuilding[0]=null
set g_reviveBuilding[1]=null
set g_reviveBuilding[2]=null
set g_reviveBuilding[3]=null
set g_reviveX[0]=-1024 //cathedral by default
set g_reviveY[0]=-1700
set g_reviveX[1]=-1024
set g_reviveY[1]=-1700
set g_reviveX[2]=-1024
set g_reviveY[2]=-1700
set g_reviveX[3]=-1024
set g_reviveY[3]=-1700
set t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_LEVEL)
call TriggerAddCondition(t, Condition( function Trig_HeroLevelUp_Conditions))
set gg_trg_PlayerHeroes = CreateTrigger( )
call TriggerAddAction( gg_trg_PlayerHeroes, function Trig_HeroDies_Actions )
endfunction
function Trig_PlayerLeft_Actions takes nothing returns nothing
local player pla=GetTriggerPlayer()
local integer count=CountPlayingPlayers()
local integer gold = GetPlayerState(pla, PLAYER_STATE_RESOURCE_GOLD) / count
local integer lumber = GetPlayerState(pla, PLAYER_STATE_RESOURCE_LUMBER) / count
local integer i=0
call SetPlayerState(pla, PLAYER_STATE_RESOURCE_GOLD, 0)// reset
call SetPlayerState(pla, PLAYER_STATE_RESOURCE_LUMBER, 0)// reset
call ShareEverythingWithTeam(pla)
loop
exitwhen i>3
if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD) + gold)
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER) + lumber)
endif
set i=i+1
endloop
call MsgAll(GetPlayerName(pla) +" has left. His gold/lumber is shared between all other players.")
call MultiboardAllowDisplayBJ( false ) //hide all MBs
set pla=null
endfunction
//===========================================================================
function InitTrig_PlayerLeft takes nothing returns nothing
set gg_trg_PlayerLeft = CreateTrigger( )
call TriggerRegisterPlayerEvent(gg_trg_PlayerLeft, Player(0), EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(gg_trg_PlayerLeft, Player(1), EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(gg_trg_PlayerLeft, Player(2), EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(gg_trg_PlayerLeft, Player(3), EVENT_PLAYER_LEAVE)
call TriggerAddAction( gg_trg_PlayerLeft, function Trig_PlayerLeft_Actions )
endfunction
function Trig_GoldIncomeEmptySlot_Conditions takes nothing returns boolean
local integer i=GetPlayerId(udg_PRM_Player)
return i>=0 and i<=3 and g_playerSlotEmpty[i] and (udg_PRM_Change > 0)
endfunction
// if gold increased for empty player slot :
//----------------------------------------------------------------------------------------------------
function Trig_GoldIncomeEmptySlot_Actions takes nothing returns nothing
local player p=udg_PRM_Player
local integer gold = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) / g_playersQuantity
// local integer lumber = GetPlayerState(udg_PRM_Player, PLAYER_STATE_RESOURCE_LUMBER) / count
set udg_PRM_FireEvent = false
if not g_playerSlotEmpty[0] then
call SetPlayerState(Player(0), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(0), PLAYER_STATE_RESOURCE_GOLD) + gold)
//call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_LUMBER) + lumber)
endif
if not g_playerSlotEmpty[1] then
call SetPlayerState(Player(1), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(1), PLAYER_STATE_RESOURCE_GOLD) + gold)
endif
if not g_playerSlotEmpty[2] then
call SetPlayerState(Player(2), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(2), PLAYER_STATE_RESOURCE_GOLD) + gold)
endif
if not g_playerSlotEmpty[3] then
call SetPlayerState(Player(3), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(3), PLAYER_STATE_RESOURCE_GOLD) + gold)
endif
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, 0)
set udg_PRM_FireEvent = true
set p=null
endfunction
//===========================================================================
function InitTrig_GoldIncomeEmptySlot takes nothing returns nothing
set gg_trg_GoldIncomeEmptySlot = CreateTrigger( )
call TriggerRegisterVariableEvent( gg_trg_GoldIncomeEmptySlot, "udg_PRM_EVENT", EQUAL, 1.00 )
call TriggerAddCondition( gg_trg_GoldIncomeEmptySlot, Condition( function Trig_GoldIncomeEmptySlot_Conditions ) )
call TriggerAddAction( gg_trg_GoldIncomeEmptySlot, function Trig_GoldIncomeEmptySlot_Actions )
endfunction
// set here awards from killed Zergs
function GetZergAward takes unit zerg returns integer
local integer t=GetUnitTypeId(zerg)
local real award=0.00
//lower gold income when zerg upgrades leveling up
local real percent=g_incomePercent/100.00 //global set in ItemPower" trigger: 100,85,70,50
//heroes and spawning pool are independant from percent
if IsUnitType(zerg, UNIT_TYPE_HERO) then
return (70+(GetHeroLevel(zerg) * 30))
elseif t==ZERG_SPAWNING_POOL then
return 500
endif
if t==ZERG_ZERGLING or t==ZERG_BURROW_ZERGLING then
set award=20
elseif t==ZERG_HYDRALISK or t==ZERG_BURROW_HYDRALISK then
set award=40
elseif t==ZERG_HUNTER_KILLER or t==ZERG_BURROW_RED_HYDRALISK then
set award=60
elseif t==ZERG_OVERLORD then
set award=80
elseif t==ZERG_DEFILER or t==ZERG_BURROW_DEFILER then
set award=100
elseif t==ZERG_MUTALISK then
set award=120
elseif t==ZERG_LURKER or t==ZERG_BURROW_LURKER then
set award=140
elseif t==ZERG_ULTRALISK then
set award=180
elseif t==ZERG_GUARDIAN then
set award=200
endif
set award=award*percent
return R2I(award)
endfunction
//-------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
function Trig_Income_Conditions takes nothing returns boolean
local unit zerg=GetTriggerUnit()
local real array dmg
local real total=0.00
local real totalAward=I2R(GetZergAward(zerg))
local integer array award
local integer i=0
//local integer playerId=0
if ( GetKillingUnit() != null ) and (totalAward>0) then
//set playerId=GetPlayerId(GetOwningPlayer(GetKillingUnit()))
//if playerId>=0 and playerId<=3 then
set dmg[0]=CSUnit_GetDamageDealtByPlayer(zerg, Player(0))
set dmg[1]=CSUnit_GetDamageDealtByPlayer(zerg, Player(1))
set dmg[2]=CSUnit_GetDamageDealtByPlayer(zerg, Player(2))
set dmg[3]=CSUnit_GetDamageDealtByPlayer(zerg, Player(3))
set total=dmg[0]+dmg[1]+dmg[2]+dmg[3]
set dmg[0]=dmg[0] / total
set dmg[1]=dmg[1] / total
set dmg[2]=dmg[2] / total
set dmg[3]=dmg[3] / total
set award[0]=R2I(dmg[0]*totalAward)
set award[1]=R2I(dmg[1]*totalAward)
set award[2]=R2I(dmg[2]*totalAward)
set award[3]=R2I(dmg[3]*totalAward)
loop
exitwhen i>3
if award[i]>0 then
call CreateTextOnUnit(zerg, "+"+I2S(award[i]), GREEN, Player(i))
call SetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(i), PLAYER_STATE_RESOURCE_GOLD)+award[i])
endif
set i=i+1
endloop
//endif
endif
set zerg=null
return false
endfunction
//===========================================================================
function InitTrig_Income takes nothing returns nothing
set gg_trg_Income = CreateTrigger( )
call TriggerRegisterPlayerUnitEvent(gg_trg_Income, Player(4), EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddCondition( gg_trg_Income, Condition( function Trig_Income_Conditions ) )
endfunction
function Trig_RepairLibrary takes nothing returns nothing
local unit u=gg_unit_h003_0008
local real x=GetUnitX(u)
local real y=GetUnitY(u)
loop
exitwhen not UnitAlive(u)
call ShowUnit(u, false)//hide
if GAME_DIFFICULTY_NORMAL then
call TriggerSleepAction(60*5)//5min
else
call TriggerSleepAction(60*8)//8min
endif
loop
exitwhen GetUnitPercentLife(LIBRARY)<0.80
call TriggerSleepAction(5.00)
endloop
call ShowUnit(u, true)
call IssueTargetOrderById(u, ORDER_smart, LIBRARY)
loop
call TriggerSleepAction(1.00)
exitwhen IsUnitInRange(u, LIBRARY, 250.00) or (not UnitAlive(u))
endloop
call TriggerSleepAction(30.00)//repair
if UnitAlive(u) then
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
endif
endloop
endfunction
//==============================================================
function InitTrig_RepairLibrary takes nothing returns nothing
set gg_trg_RepairLibrary = CreateTrigger( )
call TriggerAddAction( gg_trg_RepairLibrary, function Trig_RepairLibrary )
endfunction
function Trig_RepairCathedral_Actions takes nothing returns nothing
local unit u=gg_unit_h003_0012
local real x=GetUnitX(u)
local real y=GetUnitY(u)
loop
exitwhen not UnitAlive(u)
call ShowUnit(u, false)//hide
if GAME_DIFFICULTY_NORMAL then
call TriggerSleepAction(60*5)//5min
else
call TriggerSleepAction(60*8)//8min
endif
loop
exitwhen GetUnitPercentLife(CATHEDRAL)<0.80
call TriggerSleepAction(5.00)
endloop
call ShowUnit(u, true)
call IssueTargetOrderById(u, ORDER_smart, CATHEDRAL)
loop
call TriggerSleepAction(1.00)
exitwhen IsUnitInRange(u, CATHEDRAL, 250.00) or (not UnitAlive(u))
endloop
call TriggerSleepAction(30.00)//repair
if UnitAlive(u) then
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
endif
endloop
endfunction
//===========================================================================
function InitTrig_RepairCathedral takes nothing returns nothing
set gg_trg_RepairCathedral = CreateTrigger( )
call TriggerAddAction( gg_trg_RepairCathedral, function Trig_RepairCathedral_Actions )
endfunction
function Trig_FishermanAI_Actions takes nothing returns nothing
local unit u=udg_PtV_Fisherman
local unit carrier=udg_PtV_FishermanCarrier
local real x=udg_PtV_FishermanReturnX
local real y=udg_PtV_FishermanReturnY
local real x1=GetUnitX(u)
local real y1=GetUnitY(u)
local integer food=0
loop
call TriggerSleepAction(GetRandomReal(35,45))
exitwhen not UnitAlive(carrier)
exitwhen not UnitAlive(u)
call IssuePointOrderById(carrier, ORDER_move, x1, y1)
loop
exitwhen IsUnitInRangeXY(carrier, x1, y1, 100.00)
exitwhen not UnitAlive(carrier)
call TriggerSleepAction(1.00)
endloop
if UnitAlive(u) then
call AddUnitAnimationProperties(carrier, "gold", true)
endif
call IssuePointOrderById(carrier, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(carrier, x, y, 100.00)
exitwhen not UnitAlive(carrier)
call TriggerSleepAction(1.00)
endloop
call AddUnitAnimationProperties(carrier, "gold", false)
//add food
set food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)
if food<300 then
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, food+1)
endif
endloop
set u=null
set carrier=null
endfunction
//===========================================================================
function InitTrig_FishermanAI takes nothing returns nothing
set gg_trg_FishermanAI = CreateTrigger( )
call TriggerAddAction( gg_trg_FishermanAI, function Trig_FishermanAI_Actions )
endfunction
function CountChickensSouth takes nothing returns integer
local integer count=0
if UnitAlive(gg_unit_n00E_0035) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0024) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0065) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0069) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0070) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0077) then
set count=count+1
endif
return count
endfunction
function Trig_EggsSouth_Actions takes nothing returns nothing
local unit farmer=gg_unit_h006_0079
local unit eggs=gg_unit_n00F_0078
local real x=GetUnitX(eggs)
local real y=GetUnitY(eggs)
local real Tx=-3853
local real Ty=-5758
local integer chickens=0
local integer food=0
loop
call AddUnitAnimationProperties(eggs, "alternate", true)//empty
call TriggerSleepAction(GetRandomReal(35,45))
if CountChickensSouth()>0 then
call AddUnitAnimationProperties(eggs, "alternate", false)
endif
call TriggerSleepAction(10)
exitwhen not UnitAlive(farmer)
set chickens=CountChickensSouth()
exitwhen chickens==0
call IssuePointOrderById(farmer, ORDER_move, x, y)
loop
exitwhen not UnitAlive(farmer)
exitwhen IsUnitInRangeXY(farmer, x, y, 100.00)
call TriggerSleepAction(1)
endloop
call AddUnitAnimationProperties(eggs, "alternate", true)//empty
call IssuePointOrderById(farmer, ORDER_move, Tx, Ty)
loop
exitwhen not UnitAlive(farmer)
exitwhen IsUnitInRangeXY(farmer, Tx, Ty, 100.00)
call TriggerSleepAction(1)
endloop
//add food depending on chickens count
set food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)+chickens
if food>300 then
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, 300)
else
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, food)
endif
endloop
set farmer=null
set eggs=null
endfunction
//===========================================================================
function InitTrig_EggsSouth takes nothing returns nothing
set gg_trg_EggsSouth = CreateTrigger( )
call TriggerAddAction( gg_trg_EggsSouth, function Trig_EggsSouth_Actions )
endfunction
function CountChickensNorth takes nothing returns integer
local integer count=0
if UnitAlive(gg_unit_n00E_0082) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0081) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0083) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0084) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0085) then
set count=count+1
endif
if UnitAlive(gg_unit_n00E_0086) then
set count=count+1
endif
return count
endfunction
function Trig_EggsNorth_Actions takes nothing returns nothing
local unit farmer=gg_unit_h006_0087
local unit eggs=gg_unit_n00F_0080
local real x=GetUnitX(eggs)
local real y=GetUnitY(eggs)
local real Tx=3968
local real Ty=3658
local integer chickens=0
local integer food=0
loop
call AddUnitAnimationProperties(eggs, "alternate", true)//empty
call TriggerSleepAction(GetRandomReal(35,45))
if CountChickensSouth()>0 then
call AddUnitAnimationProperties(eggs, "alternate", false)
endif
call TriggerSleepAction(10)
exitwhen not UnitAlive(farmer)
set chickens=CountChickensSouth()
exitwhen chickens==0
call IssuePointOrderById(farmer, ORDER_move, x, y)
loop
exitwhen not UnitAlive(farmer)
exitwhen IsUnitInRangeXY(farmer, x, y, 100.00)
call TriggerSleepAction(1)
endloop
call AddUnitAnimationProperties(eggs, "alternate", true)//empty
call IssuePointOrderById(farmer, ORDER_move, Tx, Ty)
loop
exitwhen not UnitAlive(farmer)
exitwhen IsUnitInRangeXY(farmer, Tx, Ty, 100.00)
call TriggerSleepAction(1)
endloop
//add food depending on chickens count
set food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)+chickens
if food>300 then
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, 300)
else
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, food)
endif
endloop
set farmer=null
set eggs=null
endfunction
//===========================================================================
function InitTrig_EggsNorth takes nothing returns nothing
set gg_trg_EggsNorth = CreateTrigger( )
call TriggerAddAction( gg_trg_EggsNorth, function Trig_EggsNorth_Actions )
endfunction
function Trig_FarmerAI_Actions takes nothing returns nothing
local unit u=udg_PtV_Farmer
local real x=udg_PtV_FarmerReturnX
local real y=udg_PtV_FarmerReturnY
local real x1=GetUnitX(u)
local real y1=GetUnitY(u)
local real face=GetUnitFacing(u)
local integer food=0
loop
call AddUnitAnimationProperties(u, "work", true)
call TriggerSleepAction(GetRandomReal(35,45))
exitwhen not UnitAlive(u)
call AddUnitAnimationProperties(u, "work", false)
call AddUnitAnimationProperties(u, "gold", true)
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call AddUnitAnimationProperties(u, "gold", false)
//food
set food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)
if food<300 then
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, food+1)
endif
//--back on the field
call IssuePointOrderById(u, ORDER_move, x1, y1)
loop
exitwhen IsUnitInRangeXY(u, x1, y1, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call SetUnitFacingTimed(u, face, 1.00)
call TriggerSleepAction(1.00)
endloop
set u=null
endfunction
//==================================================================
function InitTrig_FarmerAI takes nothing returns nothing
set gg_trg_FarmerAI = CreateTrigger( )
call TriggerAddAction( gg_trg_FarmerAI, function Trig_FarmerAI_Actions )
endfunction
function Trig_FarmerAIWheat_Actions takes nothing returns nothing
local unit u=udg_PtV_Farmer
local real x=udg_PtV_FarmerReturnX
local real y=udg_PtV_FarmerReturnY
local real x1=GetUnitX(u)
local real y1=GetUnitY(u)
local real face=GetUnitFacing(u)
local integer food=0
loop
call AddUnitAnimationProperties(u, "work", true)
call TriggerSleepAction(GetRandomReal(35,45))
exitwhen not UnitAlive(u)
call AddUnitAnimationProperties(u, "work", false)
call AddUnitAnimationProperties(u, "lumber", true)
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call AddUnitAnimationProperties(u, "lumber", false)
//food
set food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)
if food<300 then
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, food+1)
endif
//--back on the field
call IssuePointOrderById(u, ORDER_move, x1, y1)
loop
exitwhen IsUnitInRangeXY(u, x1, y1, 100.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call SetUnitFacingTimed(u, face, 1.00)
call TriggerSleepAction(1.00)
endloop
set u=null
endfunction
//===========================================================================
function InitTrig_FarmerAIWheat takes nothing returns nothing
set gg_trg_FarmerAIWheat = CreateTrigger( )
call TriggerAddAction( gg_trg_FarmerAIWheat, function Trig_FarmerAIWheat_Actions )
endfunction
function Trig_MinersAI_Actions takes nothing returns nothing
local unit u=udg_PtV_Miner
local real x=udg_PtV_MinerReturnX
local real y=udg_PtV_MinerReturnY
local real x1=GetUnitX(u)
local real y1=GetUnitY(u)
local real face=GetUnitFacing(u)
local integer gold=0
loop
call AddUnitAnimationProperties(u, "work", true)
call TriggerSleepAction(GetRandomReal(35,45))
exitwhen not UnitAlive(u)
call AddUnitAnimationProperties(u, "work", false)
call AddUnitAnimationProperties(u, "gold", true)
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 75.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call AddUnitAnimationProperties(u, "gold", false)
// gold
set gold=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_GOLD)
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_GOLD, gold+10)
//--back on the field
call IssuePointOrderById(u, ORDER_move, x1, y1)
loop
exitwhen IsUnitInRangeXY(u, x1, y1, 50.00)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call SetUnitFacingTimed(u, face, 1.00)
call TriggerSleepAction(2.00)
endloop
set u=null
endfunction
//================================================================
function InitTrig_MinersAI takes nothing returns nothing
set gg_trg_MinersAI = CreateTrigger( )
call TriggerAddAction( gg_trg_MinersAI, function Trig_MinersAI_Actions )
endfunction
globals
unit array g_obelisk
constant integer ABI_OBELISK_CALL_FOR_HELP='A01T'
integer g_libraryVotes=0
integer g_cathedralVotes=0
string array g_playerVote
endglobals
function Trig_CallForHelp_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_OBELISK_CALL_FOR_HELP
endfunction
function CallForHelp_CountVotes takes nothing returns nothing
local integer i=0
set g_cathedralVotes=0
set g_libraryVotes=0
loop
exitwhen i>3
if g_playerVote[i]=="C" then
set g_cathedralVotes=g_cathedralVotes+1
elseif g_playerVote[i]=="L" then
set g_libraryVotes=g_libraryVotes+1
endif
set i=i+1
endloop
endfunction
function Trig_CallForHelp_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local player pla=GetOwningPlayer(u)
local integer i=GetPlayerId(pla)
if u==g_obelisk[i] then//vote for cathedral
call AddUnitAnimationProperties(u, "work", true)
call AddUnitAnimationProperties(g_obelisk[i+10], "work", false)
call UnitRemoveAbility(u, ABI_OBELISK_CALL_FOR_HELP)
call UnitAddAbility(g_obelisk[i+10], ABI_OBELISK_CALL_FOR_HELP)
set g_playerVote[i]="C"
elseif u==g_obelisk[i+10] then //vote for Library
call AddUnitAnimationProperties(u, "work", true)
call AddUnitAnimationProperties(g_obelisk[i], "work", false)
call UnitRemoveAbility(u, ABI_OBELISK_CALL_FOR_HELP)
call UnitAddAbility(g_obelisk[i], ABI_OBELISK_CALL_FOR_HELP)
set g_playerVote[i]="L"
endif
call CallForHelp_CountVotes()
//call MsgAll("vote C: "+I2S(g_cathedralVotes)+", cote L: "+I2S(g_libraryVotes))
endfunction
//=============================================================
function InitTrig_CallForHelp takes nothing returns nothing
set g_obelisk[0]=gg_unit_n008_0128 //cathedral
set g_obelisk[0+10]=gg_unit_n008_0134// library
set g_obelisk[1]=gg_unit_n008_0075 //C
set g_obelisk[1+10]=gg_unit_n008_0133 //L
set g_obelisk[2]=gg_unit_n008_0072 //C
set g_obelisk[2+10]=gg_unit_n008_0132 //L
set g_obelisk[3]=gg_unit_n008_0074 //C
set g_obelisk[3+10]=gg_unit_n008_0135 //L
set gg_trg_CallForHelp = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0128, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0134, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0075, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0133, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0072, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0132, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0074, EVENT_UNIT_SPELL_EFFECT )
call TriggerRegisterUnitEvent( gg_trg_CallForHelp, gg_unit_n008_0135, EVENT_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_CallForHelp, Condition( function Trig_CallForHelp_Conditions ) )
call TriggerAddAction( gg_trg_CallForHelp, function Trig_CallForHelp_Actions )
endfunction
globals
constant integer MARKSMAN='h008'
unit g_marksman=null
unit g_marksmanBuilding=null
real g_marksmanAngle=0.00
boolean array g_marksmanAttacks
endglobals
function VillagersPayPrice takes integer newGold, integer newLumber, integer newFood returns nothing
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_GOLD, newGold)
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_LUMBER, newLumber)
call SetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP, newFood)
endfunction
function Trig_Marksman_Actions takes nothing returns nothing
// after 10min: 500gold, 2000lumber 280food
local integer gold=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_GOLD)
local integer lumber=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_LUMBER)
local integer food=GetPlayerState(PLAYER_VILLAGERS, PLAYER_STATE_RESOURCE_FOOD_CAP)
local boolean resourcesOk = (gold>=400) and (lumber>=1600) and (food>=200)
local integer c=0
//local integer marksmanCount=GetPlayerUnitTypeCount(PLAYER_VILLAGERS, MARKSMAN)
//call MsgDev(I2S(marksmanCount))
if resourcesOk then
if g_libraryVotes>g_cathedralVotes then
call MsgAll("|c0080FF00Four Marksmans came to help protect the Library.|r")
call PingMinimapEx(7100, -400, 4.00, 0, 255, 0, true)
call VillagersPayPrice(gold-400, lumber-1600, food-200)
loop
exitwhen c>3
set g_marksman=CreateUnit(PLAYER_VILLAGERS, MARKSMAN, 7100, -400, 0.00)
call RemoveGuardPosition(g_marksman)
set g_marksmanBuilding=LIBRARY
set g_marksmanAngle=I2R(c)*90.00
call TriggerExecute(gg_trg_MarksmanAI)
set c=c+1
endloop
elseif g_cathedralVotes>g_libraryVotes then
call MsgAll("|c0080FF00Four Marksmans came to help protect the Cathedral.|r")
call PingMinimapEx(-7234, -2145, 4.00, 0, 255, 0, true)
call VillagersPayPrice(gold-400, lumber-1600, food-200)
loop
exitwhen c>3
set g_marksman=CreateUnit(PLAYER_VILLAGERS, MARKSMAN, -7234, -2145, 0.00)
call RemoveGuardPosition(g_marksman)
set g_marksmanBuilding=CATHEDRAL
set g_marksmanAngle=I2R(c)*90.00
call TriggerExecute(gg_trg_MarksmanAI)
set c=c+1
endloop
endif
endif
endfunction
//===========================================================================
function InitTrig_Marksman takes nothing returns nothing
set gg_trg_Marksman = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Marksman, 15.00 )
call TriggerAddAction( gg_trg_Marksman, function Trig_Marksman_Actions )
endfunction
function Trig_MarksmanAI_Actions takes nothing returns nothing
local unit u=g_marksman
local unit structure=g_marksmanBuilding
local real angle=g_marksmanAngle // degrees
local integer id=GetUnitUserData(u)
local real dist=225.00
local real x = GetUnitX(structure) + dist * Cos(angle * bj_DEGTORAD)
local real y = GetUnitY(structure) + dist * Sin(angle * bj_DEGTORAD)
call IssuePointOrderById(u, ORDER_move, x, y)
loop
exitwhen IsUnitInRangeXY(u, x, y, 100)
exitwhen (IsUnitInRangeXY(u, x, y, 600) and g_marksmanAttacks[id])
call TriggerSleepAction(1.00)
endloop
call UnitRemoveAbility(u, 'Avul')
loop
exitwhen not UnitAlive(u)
if (not IsUnitInRangeXY(u, x, y, 100)) and (not CSUnit_Attacked(u, 3.00)) then
call IssuePointOrderById(u, ORDER_attack, x, y)
endif
call TriggerSleepAction(5.00)
endloop
set u=null
set structure=null
endfunction
//===========================================================================
function InitTrig_MarksmanAI takes nothing returns nothing
set gg_trg_MarksmanAI = CreateTrigger( )
call TriggerAddAction( gg_trg_MarksmanAI, function Trig_MarksmanAI_Actions )
endfunction
function Trig_MarksmanAttacking_Conditions takes nothing returns boolean
if GetUnitTypeId(GetAttacker()) == MARKSMAN then
set g_marksmanAttacks[GetUnitUserData(GetAttacker())]=true
endif
return false
endfunction
//===========================================================================
function InitTrig_MarksmanAttacking takes nothing returns nothing
set gg_trg_MarksmanAttacking = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_MarksmanAttacking, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( gg_trg_MarksmanAttacking, Condition( function Trig_MarksmanAttacking_Conditions ) )
endfunction
globals
hashtable g_hashItems = InitHashtable()
//PURCHASABLE:
constant integer ITEM_POTION_HEAL='I000'
constant integer ITEM_POTION_MANA='I001'
constant integer ITEM_POTION_INVULNERABLE='I002'
constant integer ITEM_POTION_SPEED='I003'
constant integer ITEM_POTION_VAMPIRIC='I004'
constant integer ITEM_POTION_ANTIMAGIC='I005'
constant integer ITEM_POTION_DUST='I006'
constant integer ITEM_POTION_WARDS='I007'
constant integer ITEM_SCROLL_PROTECT='I008'
constant integer ITEM_SCROLL_BEAST='I009'
constant integer ITEM_WAND='I00A'
//PERMANENT:
constant integer ITEM_GAUNTLETS='I00E'
constant integer ITEM_SLIPPERS='I00F'
constant integer ITEM_MANTLE='I00G'
constant integer ITEM_BOOTS='I00C'
constant integer ITEM_SOBIMASK='I00K'
constant integer ITEM_SHIELD='I00H'
constant integer ITEM_RING_REGEN='I00R'
constant integer ITEM_PERIAPT='I00I'
constant integer ITEM_GLOVES='I00B'
constant integer ITEM_CLAWS='I00J'
constant integer ITEM_SWORD='I00D'
//ARTIFACTS:
constant integer ITEM_CRYSTAL_BALL='I00L'
constant integer ITEM_TELEPORTATION_STAFF='I00Q'
constant integer ITEM_MAUL_OF_STRENGTH='I00N'
constant integer ITEM_SEARING_BLADE='I00O'
constant integer ITEM_SHAMAN_CLAWS='I00P'
constant integer ITEM_ARCANE_SHIELD='I00T'
constant integer ITEM_SHIELD_OF_HONOR='I00S'
integer array KEY_CHARGE //[number of charges]
constant integer KEY_ITM_POWER=100
endglobals
//------------------------------------------------------------------------------------------------
function ItmBonusSave takes integer itemId, integer bonus, integer amount1, integer amount2, integer amount3 returns nothing
call SaveInteger(g_hashItems, itemId, bonus+KEY_CHARGE[1], amount1)
call SaveInteger(g_hashItems, itemId, bonus+KEY_CHARGE[2], amount2)
call SaveInteger(g_hashItems, itemId, bonus+KEY_CHARGE[3], amount3)
endfunction
//------------------------------------------------------------------------------------------------
// BONUS_ARMOR (1), BONUS_DAMAGE (2), BONUS_SIGHT_RANGE (3), BONUS_LIFE_REGEN (4),
// BONUS_STRENGTH (5), BONUS_AGILITY (6), BONUS_INTELLIGENCE (7),
// BONUS_ATTACK_SPEED (8), BONUS_MANA_REGEN_PERCENT (9)
// BONUS_MAX_LIFE (10), BONUS_MAX_MANA (11)
// KEY_WEAPON_MOVEMENT (12)
function Trig_ItemBonuses_Actions takes nothing returns nothing
set KEY_CHARGE[0]=0
set KEY_CHARGE[1]=0
set KEY_CHARGE[2]=100
set KEY_CHARGE[3]=200
//child keys: from BonusMod;: 1..12
call ItmBonusSave(ITEM_GAUNTLETS, BONUS_STRENGTH, 5, 11, 18)
call ItmBonusSave(ITEM_SLIPPERS, BONUS_AGILITY, 5, 11, 18)
call ItmBonusSave(ITEM_MANTLE, BONUS_INTELLIGENCE, 5, 11, 18)
call ItmBonusSave(ITEM_BOOTS, KEY_WEAPON_MOVEMENT, 20, 50, 90)
call ItmBonusSave(ITEM_SOBIMASK, BONUS_MANA_REGEN_PERCENT, 50, 110, 180)
call ItmBonusSave(ITEM_SOBIMASK, BONUS_MAX_MANA, 30, 60, 100)
call ItmBonusSave(ITEM_SHIELD, BONUS_ARMOR, 3, 7, 12)
call ItmBonusSave(ITEM_RING_REGEN, BONUS_LIFE_REGEN, 1, 3, 6)
call ItmBonusSave(ITEM_PERIAPT, BONUS_MAX_LIFE, 200, 500, 1000)
call ItmBonusSave(ITEM_GLOVES, BONUS_ATTACK_SPEED, 15, 35, 60)
call ItmBonusSave(ITEM_CLAWS, BONUS_DAMAGE, 15, 30, 45)
call ItmBonusSave(ITEM_SWORD, BONUS_DAMAGE, 15, 30, 45)
//artifacts (no charges)
// ITEM_MANTLE + ITEM_SOBIMASK + ITEM_POTION_DUST
call SaveInteger(g_hashItems, ITEM_CRYSTAL_BALL, BONUS_INTELLIGENCE, 18)
call SaveInteger(g_hashItems, ITEM_CRYSTAL_BALL, BONUS_MANA_REGEN_PERCENT, 180)
call SaveInteger(g_hashItems, ITEM_CRYSTAL_BALL, BONUS_MAX_MANA, 100)
// ITEM_SLIPPERS + ITEM_BOOTS + ITEM_POTION_SPEED
call SaveInteger(g_hashItems, ITEM_TELEPORTATION_STAFF, BONUS_AGILITY, 18)
call SaveInteger(g_hashItems, ITEM_TELEPORTATION_STAFF, KEY_WEAPON_MOVEMENT, 90)
// ITEM_GAUNTLETS + ITEM_GLOVES + ITEM_POTION_INVULNERABLE
call SaveInteger(g_hashItems, ITEM_MAUL_OF_STRENGTH, BONUS_STRENGTH, 18)
call SaveInteger(g_hashItems, ITEM_MAUL_OF_STRENGTH, BONUS_ATTACK_SPEED, 60)
// ITEM_SLIPPERS + ITEM_SWORD + ITEM_SCROLL_BEAST
call SaveInteger(g_hashItems, ITEM_SEARING_BLADE, BONUS_AGILITY, 18)
call SaveInteger(g_hashItems, ITEM_SEARING_BLADE, BONUS_DAMAGE, 45)
// ITEM_MANTLE + ITEM_CLAWS + ITEM_POTION_VAMPIRIC
call SaveInteger(g_hashItems, ITEM_SHAMAN_CLAWS, BONUS_INTELLIGENCE, 18)
call SaveInteger(g_hashItems, ITEM_SHAMAN_CLAWS, BONUS_DAMAGE, 45)
// ITEM_RING_REGEN + ITEM_PERIAPT + ITEM_POTION_ANTIMAGIC
call SaveInteger(g_hashItems, ITEM_ARCANE_SHIELD, BONUS_LIFE_REGEN, 6)
call SaveInteger(g_hashItems, ITEM_ARCANE_SHIELD, BONUS_MAX_LIFE, 1000)
// ITEM_SHIELD + ITEM_PERIAPT + ITEM_SCROLL_PROTECT
call SaveInteger(g_hashItems, ITEM_SHIELD_OF_HONOR, BONUS_ARMOR, 12)
call SaveInteger(g_hashItems, ITEM_SHIELD_OF_HONOR, BONUS_MAX_LIFE, 1000)
endfunction
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
function UnitAddItemBonuses takes unit u, item itm returns nothing
local integer itemId=GetItemTypeId(itm)
local integer charges=GetItemCharges(itm)
local integer bonusNr=1
local integer bonusAmount=0
loop // bonus mod for range 1..11 call directly UnitAddBonus + KEY_WEAPON_MOVEMENT(12)
exitwhen bonusNr>12
set bonusAmount = LoadInteger(g_hashItems, itemId, bonusNr+KEY_CHARGE[charges])
if bonusAmount != 0 then
call UnitAddBonus(u, bonusNr, bonusAmount)
endif
set bonusNr=bonusNr+1
endloop
endfunction
//------------------------------------------------------------------------------------------------
function UnitRemoveItemBonuses takes unit u, item itm returns nothing
local integer itemId=GetItemTypeId(itm)
local integer charges=GetItemCharges(itm)
local integer bonusNr=1
local integer bonusAmount=0
loop // bonus mod for range 1..11 call directly UnitAddBonus + KEY_WEAPON_MOVEMENT(12)
exitwhen bonusNr>12
set bonusAmount = LoadInteger(g_hashItems, itemId, bonusNr+KEY_CHARGE[charges])
if bonusAmount != 0 then
call UnitAddBonus(u, bonusNr, - bonusAmount)
endif
set bonusNr=bonusNr+1
endloop
endfunction
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
function UnitHasItemType takes unit u, integer itemId returns boolean
local integer size = UnitInventorySize(u)
local integer slot = 0
local item itm=null
loop
exitwhen slot >= size
set itm=UnitItemInSlot(u, slot)
if (itm != null) and GetItemTypeId(itm)==itemId then
set itm=null
return true
endif
set slot = slot + 1
endloop
set itm=null
return false
endfunction
//===========================================================================
function InitTrig_ItemBonuses takes nothing returns nothing
set gg_trg_ItemBonuses = CreateTrigger( )
call TriggerAddAction( gg_trg_ItemBonuses, function Trig_ItemBonuses_Actions )
endfunction
function Trig_MergePotion_Conditions takes nothing returns boolean
return ( GetItemType(GetManipulatedItem()) == ITEM_TYPE_PURCHASABLE )
endfunction
//-----------------------------------------------------------------------------------------------
function Trig_MergePotion_Actions takes nothing returns nothing
local unit u=GetManipulatingUnit()
local item itm=GetManipulatedItem()
local integer itemType=GetItemTypeId(itm)
local integer size = UnitInventorySize(u)
local item tempItem=null
local integer oldCharges=0
local integer slot = 0
local integer properSlot=-1
loop
exitwhen slot >= size
set tempItem=UnitItemInSlot(u, slot)
if (tempItem != itm) and GetItemTypeId(tempItem)==itemType then
set properSlot=slot
set oldCharges=oldCharges + GetItemCharges(tempItem)
call RemoveItem(tempItem)
endif
set slot = slot + 1
endloop
call SetItemCharges(itm, GetItemCharges(itm)+oldCharges)
if properSlot != -1 then
call UnitDropItemSlot(u, itm, properSlot)
endif
set u=null
set itm=null
set tempItem=null
endfunction
//===========================================================================
function InitTrig_MergePotion takes nothing returns nothing
set gg_trg_MergePotion = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergePotion, Player(0), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergePotion, Player(1), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergePotion, Player(2), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergePotion, Player(3), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition( gg_trg_MergePotion, Condition( function Trig_MergePotion_Conditions ) )
call TriggerAddAction( gg_trg_MergePotion, function Trig_MergePotion_Actions )
endfunction
function Trig_MergeItems_Conditions takes nothing returns boolean
return GetItemType(GetManipulatedItem()) == ITEM_TYPE_PERMANENT
endfunction
function Trig_MergeItems_Actions takes nothing returns nothing
local unit u=GetManipulatingUnit()
local item itm=GetManipulatedItem()
local integer itemType=GetItemTypeId(itm)
local integer size = UnitInventorySize(u)
local item tempItem=null
local integer oldCharges=0
local integer slot = 0
if GetItemCharges(itm)<3 then //merge (if possible)
loop
exitwhen slot >= size
set tempItem=UnitItemInSlot(u, slot)
set oldCharges=GetItemCharges(tempItem)
if (tempItem != itm) and GetItemTypeId(tempItem)==itemType and (oldCharges+GetItemCharges(itm))<=3 then
call RemoveItem(tempItem)
call SetItemCharges(itm, GetItemCharges(itm)+oldCharges)
call UnitDropItemSlot(u, itm, slot)
exitwhen true
endif
set slot = slot + 1
endloop
endif
call UnitAddItemBonuses(u, itm)
set u=null
set itm=null
set tempItem=null
endfunction
//===========================================================================
function InitTrig_MergeItems takes nothing returns nothing
set gg_trg_MergeItems = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeItems, Player(0), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeItems, Player(1), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeItems, Player(2), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeItems, Player(3), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition( gg_trg_MergeItems, Condition( function Trig_MergeItems_Conditions ) )
call TriggerAddAction( gg_trg_MergeItems, function Trig_MergeItems_Actions )
endfunction
function Trig_DropItems_Conditions takes nothing returns boolean
if GetItemType(GetManipulatedItem()) == ITEM_TYPE_PERMANENT then
call UnitRemoveItemBonuses(GetManipulatingUnit(), GetManipulatedItem())
elseif GetItemType(GetManipulatedItem()) == ITEM_TYPE_ARTIFACT then
call UnitRemoveItemBonuses(GetManipulatingUnit(), GetManipulatedItem())
endif
return false
endfunction
//===========================================================================
function InitTrig_DropItems takes nothing returns nothing
set gg_trg_DropItems = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_DropItems, Player(0), EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_DropItems, Player(1), EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_DropItems, Player(2), EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_DropItems, Player(3), EVENT_PLAYER_UNIT_DROP_ITEM )
call TriggerAddCondition( gg_trg_DropItems, Condition( function Trig_DropItems_Conditions ) )
endfunction
function Trig_Artifacts_Conditions takes nothing returns boolean
return GetItemType(GetManipulatedItem()) == ITEM_TYPE_ARTIFACT
endfunction
function Trig_Artifacts_Actions takes nothing returns nothing
call UnitAddItemBonuses(GetManipulatingUnit(), GetManipulatedItem())
endfunction
//===================================================================
function InitTrig_ArtifactsPickUp takes nothing returns nothing
set gg_trg_ArtifactsPickUp = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_ArtifactsPickUp, Player(0), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_ArtifactsPickUp, Player(1), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_ArtifactsPickUp, Player(2), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_ArtifactsPickUp, Player(3), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition( gg_trg_ArtifactsPickUp, Condition( function Trig_Artifacts_Conditions ) )
call TriggerAddAction( gg_trg_ArtifactsPickUp, function Trig_Artifacts_Actions )
endfunction
// charges does not matter
function UnitGetItemSlot_Potion takes unit u, integer itemPotionId returns integer
local integer size = UnitInventorySize(u)
local integer slot = 0
local integer result = -1
local item itm=null
loop
exitwhen slot >= size
set itm=UnitItemInSlot(u, slot)
if (itm != null) and GetItemTypeId(itm)==itemPotionId then
set result=slot
exitwhen true
endif
set slot = slot + 1
endloop
set itm=null
return result
endfunction
//-----------------------------------------------------------------------------------------------
// required charges==3
function UnitGetItemSlot_Permanent takes unit u, integer itemId returns integer
local integer size = UnitInventorySize(u)
local integer slot = 0
local integer result = -1
local item itm=null
loop
exitwhen slot >= size
set itm=UnitItemInSlot(u, slot)
if (itm != null) and GetItemTypeId(itm)==itemId and GetItemCharges(itm)==3 then
set result=slot
exitwhen true
endif
set slot = slot + 1
endloop
set itm=null
return result
endfunction
//-----------------------------------------------------------------------------------------------
function UnitCreateArtifact takes unit u, integer s1, integer s2, integer s3, integer artifactId returns nothing
if (s1 != -1) and (s2 != -1) and (s3 != -1) then
call RemoveItem(UnitItemInSlot(u, s1))
call RemoveItem(UnitItemInSlot(u, s2))
call RemoveItem(UnitItemInSlot(u, s3))
call UnitAddItemById(u, artifactId)
call MsgAll(GetPlayerName(GetOwningPlayer(u))+" has just created |c0080FF00"+GetObjectName(artifactId)+"|r")
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIlm\\AIlmTarget.mdl", u, "origin"))
endif
endfunction
//-----------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------
function Trig_MergeArtifacts_Actions takes nothing returns nothing
local unit u=GetManipulatingUnit()
local item itm=GetManipulatedItem()
local integer s1
local integer s2
local integer s3
// ITEM_CRYSTAL_BALL
set s1=UnitGetItemSlot_Permanent(u, ITEM_MANTLE)
set s2=UnitGetItemSlot_Permanent(u, ITEM_SOBIMASK)
set s3=UnitGetItemSlot_Potion(u, ITEM_POTION_DUST)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_CRYSTAL_BALL)
// ITEM_TELEPORTATION_STAFF
set s1=UnitGetItemSlot_Permanent(u, ITEM_SLIPPERS)
set s2=UnitGetItemSlot_Permanent(u, ITEM_BOOTS)
set s3=UnitGetItemSlot_Potion(u, ITEM_POTION_SPEED)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_TELEPORTATION_STAFF)
// ITEM_MAUL_OF_STRENGTH
set s1=UnitGetItemSlot_Permanent(u, ITEM_GAUNTLETS)
set s2=UnitGetItemSlot_Permanent(u, ITEM_GLOVES)
set s3=UnitGetItemSlot_Potion(u, ITEM_POTION_INVULNERABLE)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_MAUL_OF_STRENGTH)
// ITEM_SEARING_BLADE
set s1=UnitGetItemSlot_Permanent(u, ITEM_SLIPPERS)
set s2=UnitGetItemSlot_Permanent(u, ITEM_SWORD)
set s3=UnitGetItemSlot_Potion(u, ITEM_SCROLL_BEAST)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_SEARING_BLADE)
// ITEM_SHAMAN_CLAWS
set s1=UnitGetItemSlot_Permanent(u, ITEM_MANTLE)
set s2=UnitGetItemSlot_Permanent(u, ITEM_CLAWS)
set s3=UnitGetItemSlot_Potion(u, ITEM_POTION_VAMPIRIC)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_SHAMAN_CLAWS)
// ITEM_ARCANE_SHIELD
set s1=UnitGetItemSlot_Permanent(u, ITEM_RING_REGEN)
set s2=UnitGetItemSlot_Permanent(u, ITEM_PERIAPT)
set s3=UnitGetItemSlot_Potion(u, ITEM_POTION_ANTIMAGIC)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_ARCANE_SHIELD)
// ITEM_SHIELD_OF_HONOR
set s1=UnitGetItemSlot_Permanent(u, ITEM_SHIELD)
set s2=UnitGetItemSlot_Permanent(u, ITEM_PERIAPT)
set s3=UnitGetItemSlot_Potion(u, ITEM_SCROLL_PROTECT)
call UnitCreateArtifact(u, s1, s2, s3, ITEM_SHIELD_OF_HONOR)
set u=null
set itm=null
endfunction
//====================================================================
function InitTrig_MergeArtifacts takes nothing returns nothing
set gg_trg_MergeArtifacts = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeArtifacts, Player(0), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeArtifacts, Player(1), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeArtifacts, Player(2), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_MergeArtifacts, Player(3), EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddAction( gg_trg_MergeArtifacts, function Trig_MergeArtifacts_Actions )
endfunction
function Trig_TeleportationStaff_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A015'
endfunction
function Trig_TeleportationStaff_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local player pla=GetOwningPlayer(u)
local real Tx=GetSpellTargetX()
local real Ty=GetSpellTargetY()
local integer i=0
local string eff = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl"
local effect e1
local effect e2
if IsTerrainDeepWater(Tx,Ty) or IsTerrainShallowWater(Tx,Ty) then
call Msg(pla, "|c00FFFF00Cannot teleport on water area.|r")
call TriggerSleepAction(1.00)
call BlzEndUnitAbilityCooldown(u, 'A015')
elseif IsTerrainWalkable(Tx, Ty) then
set Tx=TerrainPathability_X
set Ty=TerrainPathability_Y
set e1=AddSpecialEffectTarget(eff, u, "origin")
set e2=AddSpecialEffect(eff, Tx, Ty)
call DisableUnitMovement(u)
loop
if i>4 then
call SetUnitPosition(u, Tx, Ty)
call EnableUnitMovement(u)
exitwhen true
endif
call TriggerSleepAction(0.20)
set i=i+1
endloop
call DestroyEffect(e1)
call DestroyEffect(e2)
else
call Msg(pla, "|c00FFFF00Cannot target this point.|r")
call TriggerSleepAction(1.00)
call BlzEndUnitAbilityCooldown(u, 'A015')
endif
set u=null
set pla=null
set e1=null
set e2=null
endfunction
//===========================================================================
function InitTrig_TeleportationStaff takes nothing returns nothing
set gg_trg_TeleportationStaff = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_TeleportationStaff, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_TeleportationStaff, Condition( function Trig_TeleportationStaff_Conditions ) )
call TriggerAddAction( gg_trg_TeleportationStaff, function Trig_TeleportationStaff_Actions )
endfunction
globals
constant integer ABI_ITEM_HARDENEDSKIN = 'A01B'
constant integer ABI_ITEM_SHIELDOFHONOR = 'A01C' //channel based
endglobals
function Trig_ShieldOfHonor_Conditions takes nothing returns boolean
return GetSpellAbilityId()==ABI_ITEM_SHIELDOFHONOR
endfunction
function Trig_ShieldOfHonor_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local effect eff=null
local integer c=0
set eff=AddSpecialEffectTarget("war3mapImported\\ReplenishManaCaster1.mdl", u, "overhead")
call UnitAddAbility(u, ABI_ITEM_HARDENEDSKIN)
loop
exitwhen not UnitHasItemType(u, ITEM_SHIELD_OF_HONOR)
exitwhen not UnitAlive(u)
exitwhen c>15
call TriggerSleepAction(1.00)
set c=c+1
endloop
call UnitRemoveAbility(u, ABI_ITEM_HARDENEDSKIN)
call DestroyEffect(eff)
set u=null
set eff=null
endfunction
//===========================================================================
function InitTrig_ShieldOfHonor takes nothing returns nothing
set gg_trg_ShieldOfHonor = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_ShieldOfHonor, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_ShieldOfHonor, Condition( function Trig_ShieldOfHonor_Conditions ) )
call TriggerAddAction( gg_trg_ShieldOfHonor, function Trig_ShieldOfHonor_Actions )
endfunction
globals
//gold spend on hero's items
//will trigger zerg upgrades
constant integer PLAYER_ITEM_POWER_LIMIT_1=3000
constant integer PLAYER_ITEM_POWER_LIMIT_2=4300
constant integer PLAYER_ITEM_POWER_LIMIT_3=5500
constant integer PLAYER_ITEM_POWER_LIMIT_4=6500
timer g_timerCPIP=CreateTimer() //check players items power
constant integer ZERG_UPGRADE_DEFENCE='R000'
constant integer ZERG_UPGRADE_ATTACK='R001'
constant integer ZERG_UPGRADE_DEFENCE_HERO='R003'
constant integer ZERG_UPGRADE_ATTACK_HERO='R002'
integer g_incomePercent=100
endglobals
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
function ZergUpgrade takes integer upgradeLevel returns nothing //1,2,3
local integer array bonus
local integer bonusHP
local integer bonusRegen
local integer bonusAS
local integer bonusMove
local integer bonusAttribute
//units:
call SetPlayerTechResearched(PLAYER_ZERG, ZERG_UPGRADE_DEFENCE, upgradeLevel)
call SetPlayerTechResearched(PLAYER_ZERG, ZERG_UPGRADE_ATTACK, upgradeLevel)
//heroes:
call SetPlayerTechResearched(PLAYER_ZERG, ZERG_UPGRADE_DEFENCE_HERO, upgradeLevel) //armor: +1 / upgrade
call SetPlayerTechResearched(PLAYER_ZERG, ZERG_UPGRADE_ATTACK_HERO, upgradeLevel) //attack: +10 / upgrade
// ZERG_HERO_QUEEN
//balance 19-03-2019
set bonusHP=100+(100*upgradeLevel) //200,300,400,500 = 1400
set bonusRegen=upgradeLevel //1,2,3,4 = 10
set bonusAS=5*upgradeLevel //5,10,15,20 = 50
set bonusMove=30 //30,30,30,30 = 120
set bonusAttribute=2+(upgradeLevel) //3,4,5,6 = 18
call UnitAddBonus(ZERG_HERO_QUEEN, BONUS_MAX_LIFE, bonusHP)
call UnitAddBonus(ZERG_HERO_QUEEN, BONUS_LIFE_REGEN, bonusRegen)
call UnitAddBonus(ZERG_HERO_QUEEN, BONUS_ATTACK_SPEED, bonusAS)
call UnitAddBonus(ZERG_HERO_QUEEN, KEY_WEAPON_MOVEMENT, bonusMove)
call UnitAddBonus(ZERG_HERO_QUEEN, BONUS_INTELLIGENCE, bonusAttribute)
//items:
set g_zergHeroItm=ZERG_HERO_QUEEN
if upgradeLevel==2 then
set g_zergHeroItemId='spsh' //amulet spell shield
call TriggerExecute(gg_trg_ZergAddItem)
elseif upgradeLevel==3 then
set g_zergHeroItemId='brac' //runed bracers
call TriggerExecute(gg_trg_ZergAddItem)
endif
// ZERG_HERO_BEAST
set bonusHP=300+(100*upgradeLevel) //400,500,600,700 = 2200
set bonusRegen=upgradeLevel //1,2,3,4 = 10
set bonusAS=7+(upgradeLevel) //8,9,10,11 = 38
set bonusMove=30 //30,30,30,30 = 120
set bonusAttribute=3+(upgradeLevel) //4,5,6,7 = 22
call UnitAddBonus(ZERG_HERO_BEAST, BONUS_MAX_LIFE, bonusHP)
call UnitAddBonus(ZERG_HERO_BEAST, BONUS_LIFE_REGEN, bonusRegen)
call UnitAddBonus(ZERG_HERO_BEAST, BONUS_ATTACK_SPEED, bonusAS)
call UnitAddBonus(ZERG_HERO_BEAST, KEY_WEAPON_MOVEMENT, bonusMove)
call UnitAddBonus(ZERG_HERO_BEAST, BONUS_STRENGTH, bonusAttribute)
//items:
set g_zergHeroItm=ZERG_HERO_BEAST
if upgradeLevel==2 then
set g_zergHeroItemId='bgst' //belt of giant strength
call TriggerExecute(gg_trg_ZergAddItem)
elseif upgradeLevel==3 then
set g_zergHeroItemId='rump' //rusty mining pick (bash)
call TriggerExecute(gg_trg_ZergAddItem)
endif
// ZERG_HERO_SLAYER
set bonusHP=200+(100*upgradeLevel) //300,400,500,600 = 1800
set bonusRegen=upgradeLevel //1,2,3,4 = 10
set bonusAS=7+(upgradeLevel) //8,9,10,11 = 38
set bonusMove=30 //30,30,30,30 = 120
set bonusAttribute=1+(upgradeLevel) //2,3,4,5 = 14
//if not GAME_DIFFICULTY_NORMAL then
//endif
call UnitAddBonus(ZERG_HERO_SLAYER, BONUS_MAX_LIFE, bonusHP)
call UnitAddBonus(ZERG_HERO_SLAYER, BONUS_LIFE_REGEN, bonusRegen)
call UnitAddBonus(ZERG_HERO_SLAYER, BONUS_ATTACK_SPEED, bonusAS)
call UnitAddBonus(ZERG_HERO_SLAYER, KEY_WEAPON_MOVEMENT, bonusMove)
call UnitAddBonus(ZERG_HERO_SLAYER, BONUS_AGILITY, bonusAttribute)
//items:
set g_zergHeroItm=ZERG_HERO_SLAYER
if upgradeLevel==2 then
set g_zergHeroItemId='belv' //boots of quelThalas
call TriggerExecute(gg_trg_ZergAddItem)
elseif upgradeLevel==3 then
set g_zergHeroItemId='srbd' //fury blade (critical strike)
call TriggerExecute(gg_trg_ZergAddItem)
endif
endfunction
//-----------------------------------------------------------------------------------------------------
function SaveItemCosts takes nothing returns nothing
//PERMANENT: gold cost (per charge)
call SaveInteger(g_hashItems, ITEM_GAUNTLETS, KEY_ITM_POWER, 150)
call SaveInteger(g_hashItems, ITEM_SLIPPERS, KEY_ITM_POWER, 150)
call SaveInteger(g_hashItems, ITEM_MANTLE, KEY_ITM_POWER, 150)
call SaveInteger(g_hashItems, ITEM_BOOTS, KEY_ITM_POWER, 150)
call SaveInteger(g_hashItems, ITEM_SOBIMASK, KEY_ITM_POWER, 175)
call SaveInteger(g_hashItems, ITEM_SHIELD, KEY_ITM_POWER, 175)
call SaveInteger(g_hashItems, ITEM_RING_REGEN, KEY_ITM_POWER, 200)
call SaveInteger(g_hashItems, ITEM_PERIAPT, KEY_ITM_POWER, 250)
call SaveInteger(g_hashItems, ITEM_GLOVES, KEY_ITM_POWER, 300)
call SaveInteger(g_hashItems, ITEM_CLAWS, KEY_ITM_POWER, 300)
call SaveInteger(g_hashItems, ITEM_SWORD, KEY_ITM_POWER, 320)
//ARTIFACTS: gold cost
call SaveInteger(g_hashItems, ITEM_CRYSTAL_BALL, KEY_ITM_POWER, 1075)
call SaveInteger(g_hashItems, ITEM_TELEPORTATION_STAFF, KEY_ITM_POWER, 1000)
call SaveInteger(g_hashItems, ITEM_MAUL_OF_STRENGTH, KEY_ITM_POWER, 1450)
call SaveInteger(g_hashItems, ITEM_SEARING_BLADE, KEY_ITM_POWER, 1510)
call SaveInteger(g_hashItems, ITEM_SHAMAN_CLAWS, KEY_ITM_POWER, 1450)
call SaveInteger(g_hashItems, ITEM_SHIELD_OF_HONOR, KEY_ITM_POWER, 1375)
call SaveInteger(g_hashItems, ITEM_ARCANE_SHIELD, KEY_ITM_POWER, 1450)
endfunction
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
function GetHeroItemsGoldCost takes unit u returns integer
local integer slot=0
local item tempItem=null
local integer size = UnitInventorySize(u)
local integer cost=0
loop
exitwhen slot >= size
set tempItem=UnitItemInSlot(u, slot)
if (tempItem != null) then
if GetItemType(tempItem) == ITEM_TYPE_PERMANENT then
set cost=cost + (LoadInteger(g_hashItems, GetItemTypeId(tempItem), KEY_ITM_POWER) * GetItemCharges(tempItem))
elseif GetItemType(tempItem) == ITEM_TYPE_ARTIFACT then
set cost=cost + LoadInteger(g_hashItems, GetItemTypeId(tempItem), KEY_ITM_POWER)
endif
endif
set slot = slot + 1
endloop
set tempItem=null
return cost
endfunction
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
function CheckPlayersItemPower_Limit takes integer limit returns boolean
local integer c0=GetHeroItemsGoldCost(g_hero[0])
local integer c1=GetHeroItemsGoldCost(g_hero[1])
local integer c2=GetHeroItemsGoldCost(g_hero[2])
local integer c3=GetHeroItemsGoldCost(g_hero[3])
return c0>limit or c1>limit or c2>limit or c3>limit
endfunction
function CheckPlayersItemPower_4 takes nothing returns nothing
if CheckPlayersItemPower_Limit(PLAYER_ITEM_POWER_LIMIT_4) then
//upgrade zerg
set g_incomePercent=40
call ZergUpgrade(4)
else
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_4)
endif
endfunction
function CheckPlayersItemPower_3 takes nothing returns nothing
if CheckPlayersItemPower_Limit(PLAYER_ITEM_POWER_LIMIT_3) then
//upgrade zerg
set g_incomePercent=50
call ZergUpgrade(3)
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_4)
else
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_3)
endif
endfunction
function CheckPlayersItemPower_2 takes nothing returns nothing
if CheckPlayersItemPower_Limit(PLAYER_ITEM_POWER_LIMIT_2) then
//upgrade zerg
set g_incomePercent=70
call ZergUpgrade(2)
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_3)
else
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_2)
endif
endfunction
function CheckPlayersItemPower_1 takes nothing returns nothing
if CheckPlayersItemPower_Limit(PLAYER_ITEM_POWER_LIMIT_1) then
//upgrade zerg
set g_incomePercent=85
call ZergUpgrade(1)
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_2)
else
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_1)
endif
endfunction
//===========================================================================
function InitTrig_ItemPower takes nothing returns nothing
call SaveItemCosts()
call TimerStart(g_timerCPIP, 15.00, false, function CheckPlayersItemPower_1)
endfunction
function Trig_AlchemistTransmute_Conditions takes nothing returns boolean
return GetSpellAbilityId() == 'A01E'
endfunction
function Trig_AlchemistTransmute_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local real angle=GetUnitFacing(u)
local real x = GetUnitX(u) + 150.00 * Cos(angle * bj_DEGTORAD)
local real y = GetUnitY(u) + 150.00 * Sin(angle * bj_DEGTORAD)
set bj_lastCreatedItem=CreateItem('gold', x, y)
set u=null
endfunction
//===========================================================================
function InitTrig_AlchemistTransmute takes nothing returns nothing
set gg_trg_AlchemistTransmute = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_AlchemistTransmute, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_AlchemistTransmute, Condition( function Trig_AlchemistTransmute_Conditions ) )
call TriggerAddAction( gg_trg_AlchemistTransmute, function Trig_AlchemistTransmute_Actions )
endfunction
globals
constant integer ABI_BLADEMASTER_DASH = 'A01G'
endglobals
function BlademasterDashOnHit takes nothing returns nothing
local unit hero=kb_unit
local unit u=kb_obstacle_unit
local integer lvl=GetUnitAbilityLevel(hero, ABI_BLADEMASTER_DASH)
local real dmg=15.00+(15.00*I2R(lvl))//30/45/60
if kb_callback == KB_HIT_OBSTACLE_UNIT and kb_hitCount<6 then
call UnitDamageTarget(hero, u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
//magic damage
endif
set hero=null
set u=null
endfunction
function Trig_Blademaster_Dash_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_BLADEMASTER_DASH
endfunction
function Trig_Blademaster_Dash_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real Tx=GetSpellTargetX()
local real Ty=GetSpellTargetY()
local real dx = Tx - x
local real dy = Ty - y
local real distance=SquareRoot(dx * dx + dy * dy)
local real angle=Atan2(Ty - y, Tx - x)
local string eff="Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
local real dur=distance / 600.00
//dist max 800, min 200: 0.50, speed=400
call KnockBack(function BlademasterDashOnHit, u, distance, dur, angle, false, false, true, KB_TYPE_SLIDE, KB_FILTR_BOUNCE_ENEMY_ONLY, eff, "origin", 60.00)
set u=null
endfunction
//===========================================================================
function InitTrig_Blademaster_Dash takes nothing returns nothing
set gg_trg_Blademaster_Dash = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Blademaster_Dash, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Blademaster_Dash, Condition( function Trig_Blademaster_Dash_Conditions ) )
call TriggerAddAction( gg_trg_Blademaster_Dash, function Trig_Blademaster_Dash_Actions )
endfunction
function Trig_BladeMaster_Dash1_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_BLADEMASTER_DASH
endfunction
function Trig_BladeMaster_Dash1_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real Tx=GetSpellTargetX()
local real Ty=GetSpellTargetY()
local real dx = Tx - x
local real dy = Ty - y
local real distance2=(dx * dx + dy * dy)
if distance2<200.00*200.00 then
call Msg(GetOwningPlayer(u), "|c00FFFF00Min distance is 200.|r")
call UnitImmediateOrderAfterDelay(u, ORDER_stop, 0.00)
endif
set u=null
endfunction
//===========================================================================
function InitTrig_BladeMaster_Dash1 takes nothing returns nothing
set gg_trg_BladeMaster_Dash1 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_BladeMaster_Dash1, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_BladeMaster_Dash1, Condition( function Trig_BladeMaster_Dash1_Conditions ) )
call TriggerAddAction( gg_trg_BladeMaster_Dash1, function Trig_BladeMaster_Dash1_Actions )
endfunction
globals
constant integer ABI_DEMONHUNTER_FOCUS='A01M'
constant integer ABI_DEMONHUNTER_FOCUS_DEMOLISH='A01L'
endglobals
function Trig_DemonHunter_Focus_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_DEMONHUNTER_FOCUS
endfunction
function Trig_DemonHunter_Focus_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer lvl=GetUnitAbilityLevel(u, ABI_DEMONHUNTER_FOCUS)
call UnitAddAbilityTimed(u, ABI_DEMONHUNTER_FOCUS_DEMOLISH, lvl, 10.00)
call AddTimedEffectTarget(u, 10.00, "weapon", "Abilities\\Spells\\Items\\AIfb\\AIfbTarget.mdl")
set u=null
endfunction
//===========================================================================
function InitTrig_DemonHunter_Focus takes nothing returns nothing
set gg_trg_DemonHunter_Focus = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_DemonHunter_Focus, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_DemonHunter_Focus, Condition( function Trig_DemonHunter_Focus_Conditions ) )
call TriggerAddAction( gg_trg_DemonHunter_Focus, function Trig_DemonHunter_Focus_Actions )
endfunction
globals
constant integer ABI_PALADIN_HOLYLIGHT='A01N'
endglobals
function Trig_Paladin_HolyLight_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_PALADIN_HOLYLIGHT
endfunction
function Trig_Paladin_HolyLight_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local player pla=GetOwningPlayer(u)
local real lvl=I2R(GetUnitAbilityLevel(u, ABI_PALADIN_HOLYLIGHT))
local unit target=GetSpellTargetUnit()
local real dmg=50.00+(150.00*lvl) //200 350 500
if IsUnitAlly(target, pla) then
if (R2I(GetWidgetLife(target))<BlzGetUnitMaxHP(target)) then
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl", target, "origin"))
call SetWidgetLife(target, GetWidgetLife(target)+dmg)
endif
else //enemy, magic damage:
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl", target, "origin"))
call UnitDamageTarget(u, target, dmg/2.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
endif
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_Paladin_HolyLight takes nothing returns nothing
set gg_trg_Paladin_HolyLight = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Paladin_HolyLight, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Paladin_HolyLight, Condition( function Trig_Paladin_HolyLight_Conditions ) )
call TriggerAddAction( gg_trg_Paladin_HolyLight, function Trig_Paladin_HolyLight_Actions )
endfunction
function Trig_Paladin_HolyLight2_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_PALADIN_HOLYLIGHT
endfunction
function Trig_Paladin_HolyLight2_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local real lvl=I2R(GetUnitAbilityLevel(u, ABI_PALADIN_HOLYLIGHT))
local unit target=GetSpellTargetUnit()
if IsUnitAlly(target, GetOwningPlayer(u)) and not (R2I(GetWidgetLife(target))<BlzGetUnitMaxHP(target)) then
call Msg(GetOwningPlayer(u), "|c00FFFF00Target at max health.|r")
call UnitImmediateOrderAfterDelay(u, ORDER_stop, 0.00)
endif
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_Paladin_HolyLight2 takes nothing returns nothing
set gg_trg_Paladin_HolyLight2 = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Paladin_HolyLight2, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_Paladin_HolyLight2, Condition( function Trig_Paladin_HolyLight2_Conditions ) )
call TriggerAddAction( gg_trg_Paladin_HolyLight2, function Trig_Paladin_HolyLight2_Actions )
endfunction
globals
constant integer ABI_PALADIN_ANGELIC_SUPPORT='A01P'
endglobals
function Trig_Paladin_AngelicSupport_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_PALADIN_ANGELIC_SUPPORT
endfunction
function Trig_Paladin_AngelicSupport_LoopEnum takes nothing returns nothing
local unit d = GetEnumUnit()
local integer id = GetUnitUserData(d)
local real x=0.00
local real y=0.00
local unit u=null
local player pla=null
local real angle=0.00
if spellCounter[id]<19 and (not UnitChanneling(spellCaster[id])) then
set spellDuration[id]=0.00
elseif spellCounter[id]>=19 then
set spellDuration[id]=0.00
call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\HolyStomp.mdl", spellCaster[id], "origin"))
set pla=GetOwningPlayer(spellCaster[id])
set x=GetUnitX(spellCaster[id])
set y=GetUnitY(spellCaster[id])
call GroupEnumUnitsInRange(ug, x, y, 300.00, g_filtr_alive)
loop
set u = FirstOfGroup(ug)
exitwhen (u == null)
if IsUnitEnemy(u, pla) then//magic dmg
call UnitDamageTarget(spellCaster[id], u, spellDamage[id], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
set angle=Atan2(GetUnitY(u) - y, GetUnitX(u) - x)
call KnockBack(null, u, 500.00, 1.00, angle, false, true, true, KB_TYPE_NORMAL, KB_FILTR_BOUNCE_ALLIED_ONLY, null, null, 1.00)
endif
//---
call GroupRemoveUnit(ug, u)
endloop
call GroupClear(ug)
set u=null
endif
//---
set spellCounter[id] = spellCounter[id] + 1
set spellDuration[id] = spellDuration[id] - 0.10
if spellDuration[id] <= 0.00 then // Clean up any data attached to this spell
set spellCaster[id] = null
//---
call GroupRemoveUnit(spellGroup[5], d)
call RemoveUnit(d)
if FirstOfGroup(spellGroup[5]) == null then
call PauseTimer(spellTimer[5])
endif
endif
set d=null
endfunction
//--------------------------------------------------------------------------------------
function Trig_Paladin_AngelicSupport_Loop takes nothing returns nothing
call ForGroup(spellGroup[5], function Trig_Paladin_AngelicSupport_LoopEnum)
endfunction
//--------------------------------------------------------------------------------------
function Trig_Paladin_AngelicSupport_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit dummy=CreateUnit(GetOwningPlayer(u), DUMMY, GetUnitX(u), GetUnitY(u), 0.00)
local integer id=GetUnitUserData(dummy)
set spellCaster[id]=u
set spellDuration[id] = 4.00
set spellCounter[id] = 0
set spellDamage[id] = 250.00
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Human\\Resurrect\\ResurrectCaster.mdl", u, "origin"))
if FirstOfGroup(spellGroup[5]) == null then
call TimerStart(spellTimer[5], 0.10, true, function Trig_Paladin_AngelicSupport_Loop)
endif
call GroupAddUnit(spellGroup[5], dummy)
set u=null
set dummy=null
endfunction
//===========================================================================
function InitTrig_Paladin_AngelicSupport takes nothing returns nothing
set gg_trg_Paladin_AngelicSupport = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Paladin_AngelicSupport, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Paladin_AngelicSupport, Condition( function Trig_Paladin_AngelicSupport_Conditions ) )
call TriggerAddAction( gg_trg_Paladin_AngelicSupport, function Trig_Paladin_AngelicSupport_Actions )
endfunction
// zerg mutation time: set in OE "point value" field
globals
unit ZERG_HERO_BEAST=null
unit ZERG_HERO_SLAYER=null
unit ZERG_HERO_QUEEN=null
unit array zergSpawningPool //[1..6]
location array zergPoolLoc //[1..6]
integer array zergMaxPaths //[pool's No]
integer array zergMeetingPointX
integer array zergMeetingPointY
//bind unit with its group id
integer array g_zGroupId //[GetUnitUserData(zerg)] = handleId of a group, unit is in
group g_swapGroupZG=CreateGroup() //used in "ZergGroup_SetTarget" & ZergOrders category
unit array g_zergTarget // [id] of zerg attacker
boolean array g_zergHeroTeleporting // [id of zerg hero] // set in "CreateAllHeroes"
constant integer ZERG_SPAWNING_POOL = 'n002'
constant integer ZERG_EGG = 'o001'
constant integer ZERG_OVERLORD = 'u000'
constant integer ZERG_ZERGLING = 'u001'
constant integer ZERG_HYDRALISK = 'z000'
constant integer ZERG_HUNTER_KILLER = 'z001'
constant integer ZERG_LURKER = 'z004'
constant integer ZERG_DEFILER = 'u002'
constant integer ZERG_MUTALISK = 'u007'
constant integer ZERG_GUARDIAN = 'u008'
constant integer ZERG_ULTRALISK = 'u005'
constant integer ZERG_BURROW_ZERGLING = 'u003'
constant integer ZERG_BURROW_HYDRALISK = 'z002'
constant integer ZERG_BURROW_RED_HYDRALISK = 'z003'
constant integer ZERG_BURROW_DEFILER = 'u00B'
constant integer ZERG_BURROW_LURKER = 'z005'
constant integer ABI_ZERG_EGG_THROW = 'A006'//"clusterrockets" based
group g_zergWardVisibilityGroup=CreateGroup()
constant integer ZERG_VISIBILITY_WARD='o000'
constant integer ATTACK=1 // for " ZergCreateGroup"
constant integer DEFENCE=2
constant integer ATTACK_CARGO=3
constant real ZERG_EGG_THROW_PAUSE = 0.70//0.90 // pause between eggs throw
constant integer ZERG_MAX_QUEUE_NR=100 // for each spawningPool unit
constant integer GROUP_STATE_CREATING = 0
constant integer GROUP_STATE_CONSOLIDATE = 1
constant integer GROUP_STATE_ATTACK_MOVE = 2
constant integer GROUP_STATE_FIGHT = 3
constant integer GROUP_STATE_DEF_SLEEP = 1
constant integer GROUP_STATE_DEF_BACK = 2
constant integer GROUP_STATE_DEF_FIGHT = 3
//--------------------------------------------------------------------------------------
//Hashtable :
//--------------------------------------------------------------------------------------
hashtable zergHash=InitHashtable()
constant integer KEY_HERO=302
constant integer KEY_WAVE_S=0//to save string (plus number of wave)(PLUS 1000 for "hard difficulty)
constant integer KEY_WAVE_H=200//to save addHero (plus number of wave) (PLUS 1000 for "hard difficulty)
constant integer KEY_WAVE_C=400//to save useCargo (plus number of wave) (PLUS 1000 for "hard difficulty)
constant integer KEY_WAVE_P=600//to save time between next wave (plus number of wave) (PLUS 1000 for "hard difficulty)
//uses under GetHandleId (library) or (cathedral)
// keys: KEY_WAVE_S (0..199) max199 waves on Library, and max199 wave for Cathedral - (PLUS 1000 for "hard difficulty)
// keys: KEY_WAVE_H (200..399) - (PLUS 1000 for "hard difficulty)
// keys: KEY_WAVE_C (400..599) - (PLUS 1000 for "hard difficulty)
// keys: KEY_WAVE_P (600..799) - (PLUS 1000 for "hard difficulty)
constant integer KEY_GROUP=2
constant integer KEY_GROUP_DAMAGED=3 // for use in GroupCombatState
constant integer KEY_GROUP_COUNT=5
constant integer KEY_GROUP_MAX_SIZE=6
constant integer KEY_GROUP_TRG=7
constant integer KEY_GROUP_COMPLETED=8
constant integer KEY_GROUP_FLYERS=9
constant integer KEY_GROUP_WALKERS=10
constant integer KEY_GROUP_CAN_ATTACK_AIR=11
constant integer KEY_GROUP_DESTINATION_X=12
constant integer KEY_GROUP_DESTINATION_Y=13
constant integer KEY_GROUP_TARGET=14
constant integer KEY_GROUP_POOL_NO=15
constant integer KEY_GROUP_PATH_NO=16
constant integer KEY_GROUP_POINT_NO=17
constant integer KEY_WARD=19
constant integer KEY_GROUP_CENTER_X=20
constant integer KEY_GROUP_CENTER_Y=21
constant integer KEY_GROUP_TYPE=22
constant integer KEY_OVERLORDS_DAMAGED=23
constant integer KEY_HERO_POOL_NO=25
constant integer KEY_GROUP_CONSOLIDATE_X=26
constant integer KEY_GROUP_CONSOLIDATE_Y=27
constant integer KEY_GROUP_STATE=28
constant integer KEY_GROUP_AGAINST_LIBRARY=29
//uses under GetHandleId(TRIGGER): [dynamically created] in trigger "CreateZergGroup"
// keys: KEY_GROUP (2)
//uses under GetHandleId(TRIGGER): [dynamically created] in trigger "OverlordCargo"
// keys: KEY_GROUP (2)
//uses under GetHandleId(zerg GROUP)
// KEY_GROUP_COUNT, KEY_GROUP_MAX_SIZE,
// KEY_GROUP_TRG, KEY_GROUP_COMPLETED
// KEY_GROUP_FLYERS, KEY_GROUP_WALKERS, KEY_GROUP_CAN_ATTACK_AIR
// KEY_GROUP_DESTINATION_X, KEY_GROUP_DESTINATION_Y, KEY_GROUP_TARGET
// KEY_GROUP_POOL_NO, KEY_GROUP_PATH_NO, KEY_GROUP_POINT_NO
// KEY_WARD
// KEY_GROUP_CENTER_X, KEY_GROUP_CENTER_Y
// KEY_HERO, KEY_GROUP_TYPE
// KEY_OVERLORDS_DAMAGED
// KEY_GROUP_CONSOLIDATE_X KEY_GROUP_CONSOLIDATE_Y KEY_GROUP_STATE
// KEY_GROUP_AGAINST_LIBRARY
// (0,5,6,7,8,9,10,11,12,13,14,15,16,18,19,20,302, 21,22,23,26,27,28,29)
// uses under GetHandleId(zergWard)
// keys: KEY_GROUP
// uses under GetHandleId(ZERG_HERO)
// keys: KEY_GROUP (2)
// keys: KEY_HERO_POOL_NO (25)
//--------------------------------------------------------------------------------------
//end of hashtable settings
//--------------------------------------------------------------------------------------
endglobals
//==========================================================
//-----------------------------------------------------------------------------
//only for setting Zerg_SaveMeetingPoints at Init
function ZergSetPoint takes integer arrayNo, integer x, integer y returns nothing
set zergMeetingPointX[arrayNo]=x
set zergMeetingPointY[arrayNo]=y
endfunction
//-----------------------------------------------------------------------------
function Zerg_SavePools takes nothing returns nothing
set zergSpawningPool[1] = gg_unit_n002_0054 // bottom (left)
set zergSpawningPool[2] = gg_unit_n002_0055 // top left
set zergSpawningPool[3] = gg_unit_n002_0056 // top right
set zergSpawningPool[4] = gg_unit_n002_0007 // botoom (right)
set zergSpawningPool[5] = gg_unit_n002_0033 // expansion top
set zergSpawningPool[6] = gg_unit_n002_0071 // expansion bottom
set zergPoolLoc[1]=GetUnitLoc(zergSpawningPool[1])
set zergPoolLoc[2]=GetUnitLoc(zergSpawningPool[2])
set zergPoolLoc[3]=GetUnitLoc(zergSpawningPool[3])
set zergPoolLoc[4]=GetUnitLoc(zergSpawningPool[4])
set zergPoolLoc[5]=GetUnitLoc(zergSpawningPool[5])
set zergPoolLoc[6]=GetUnitLoc(zergSpawningPool[6])
call ShowUnit(zergSpawningPool[5], false)
call ShowUnit(zergSpawningPool[6], false)
endfunction
//-----------------------------------------------------------------------------
function Zerg_SaveMeetingPoints takes nothing returns nothing
//zergMeetingPoint[spawningPool No -- Path No -- PointNo ]
// Path 1 and 2 --> Library
// Path 3 and 4 --> Cathedral
//SPAWNING POOL 1 (bottom-left)
call ZergSetPoint(111, -5450, -6690) //OK
call ZergSetPoint(112, -70, -6660)
call ZergSetPoint(113, 250, -4980)
call ZergSetPoint(114, 4600, -4980)
call ZergSetPoint(115, 4375, -1500)
call ZergSetPoint(116, 2685, -1300)
call ZergSetPoint(117, 1270, 850) // Library position
call ZergSetPoint(121, -6430, -2600) //OK
call ZergSetPoint(122, -6335, 70)
call ZergSetPoint(123, -7000, 5190)
call ZergSetPoint(124, -5845, 6600)
call ZergSetPoint(125, -2530, 6666)
call ZergSetPoint(126, -2654, 3100)
call ZergSetPoint(127, -580, 3040)
call ZergSetPoint(128, 1270, 850) // Library position
call ZergSetPoint(131, -4680, -4150) // przy tartaku [3] OK
call ZergSetPoint(132, -3210, -4000)
call ZergSetPoint(133, -830, -3920)
call ZergSetPoint(134, -1000, -1500) // cathedral position
call ZergSetPoint(141, -5450, -6690) // ze strony poludniowej [4] OK
call ZergSetPoint(142, -70, -6660)
call ZergSetPoint(143, -840, -4720)
call ZergSetPoint(144, -1000, -1500) // cathedral position
set zergMaxPaths[1]=4
//------------------------------------------------------------------------------
//SPAWNING POOL 2 (top-left)
call ZergSetPoint(211, -2294, 6743) //OK
call ZergSetPoint(212, 1832, 4865)
call ZergSetPoint(213, 1270, 850) // Library position
call ZergSetPoint(221, -2586, 6686) // OK
call ZergSetPoint(222, -2656, 3795)
call ZergSetPoint(223, -2020, 2158)
call ZergSetPoint(224, -443, 2256)
call ZergSetPoint(225, 1270, 850) // Library position
call ZergSetPoint(231, -6350, 75)
call ZergSetPoint(232, -3600, -75)
call ZergSetPoint(233, -1000, -1500) // cathedral position OK
call ZergSetPoint(241, -6350, 75)
call ZergSetPoint(242, -6420, -2570)
call ZergSetPoint(243, -3660, -2264)
call ZergSetPoint(244, -2564, -1640)
call ZergSetPoint(245, -1000, -1500) // cathedral position OK
set zergMaxPaths[2]=4
//------------------------------------------------------------------------------
//SPAWNING POOL 3 (top-right)
call ZergSetPoint(311, 4122, 5211) //OK
call ZergSetPoint(312, 5622, 2794)
call ZergSetPoint(313, 1270, 850) // Library position
call ZergSetPoint(321, 6793, -293) //OK
call ZergSetPoint(322, 3692, 0)
call ZergSetPoint(323, 1270, 850) // Library position
call ZergSetPoint(331, 6842, -4695) //OK
call ZergSetPoint(332, 2105, -4968)
call ZergSetPoint(333, -1000, -1500) // cathedral position
call ZergSetPoint(341, 2271, 6674) //OK
call ZergSetPoint(342, 322, 5400)
call ZergSetPoint(343, -2165, 6733)
call ZergSetPoint(344, -6158, 6570)
call ZergSetPoint(345, -6937, 5070)
call ZergSetPoint(346, -6366, -2626)
call ZergSetPoint(347, -3649, -2285)
call ZergSetPoint(348, -1000, -1500) // cathedral position
set zergMaxPaths[3]=4
//------------------------------------------------------------------------------
//SPAWNING POOL 4 (bottom-right)
call ZergSetPoint(411, 4364, -3684) //OK
call ZergSetPoint(412, 4400, -1500)
call ZergSetPoint(413, 2700, -1350)
call ZergSetPoint(414, 1270, 850) // Library position
call ZergSetPoint(421, 6848, -4680) //OK
call ZergSetPoint(422, 6850, 2780)
call ZergSetPoint(423, 5463, 2737)
call ZergSetPoint(424, 1270, 850) // Library position
call ZergSetPoint(431, 5617, -4961) //OK
call ZergSetPoint(432, 529, -4826)
call ZergSetPoint(433, -1000, -1500) // cathedral position
call ZergSetPoint(441, 5617, -4961) //OK
call ZergSetPoint(442, 2394, -4890)
call ZergSetPoint(443, -1000, -1500) // cathedral position
set zergMaxPaths[4]=4
//------------------------------------------------------------------------------
//SPAWNING POOL 5 (expansion top)
call ZergSetPoint(511, -890, 3100) //OK
call ZergSetPoint(512, 1270, 850) // Library position
call ZergSetPoint(521, 1580, 4800) //OK
call ZergSetPoint(522, 2682, 2778)
call ZergSetPoint(523, 1270, 850) // Library position
call ZergSetPoint(531, -2567, 6280) //OK
call ZergSetPoint(532, -6000, 6700)
call ZergSetPoint(533, -7050, 5090)
call ZergSetPoint(534, -6260, 125)
call ZergSetPoint(535, -3670, 0)
call ZergSetPoint(536, -3100, -1557)
call ZergSetPoint(537, -1000, -1500) // cathedral position
call ZergSetPoint(541, -2567, 6280) //OK
call ZergSetPoint(542, -6000, 6700)
call ZergSetPoint(543, -7050, 5090)
call ZergSetPoint(544, -6450, -6190)
call ZergSetPoint(545, -3080, -6800)
call ZergSetPoint(546, -3200, -2880)
call ZergSetPoint(547, -1000, -1500) // cathedral position
set zergMaxPaths[5]=4
//------------------------------------------------------------------------------
//SPAWNING POOL 6 (expansion bottom)
call ZergSetPoint(611, 1144, -5020) //OK
call ZergSetPoint(612, 6922, -4688)
call ZergSetPoint(613, 6818, -340)
call ZergSetPoint(614, 3820, -67)
call ZergSetPoint(615, 1270, 850) // Library position
call ZergSetPoint(621, 1144, -5020) //OK
call ZergSetPoint(622, 5760, -4820)
call ZergSetPoint(623, 5750, -1350)
call ZergSetPoint(624, 2720, -1257)
call ZergSetPoint(625, 1270, 850) // Library position
call ZergSetPoint(631, 1215, -7000) //OK
call ZergSetPoint(632, -1933, -6960)
call ZergSetPoint(633, -2070, -2613)
call ZergSetPoint(634, -1000, -1500) // cathedral position
call ZergSetPoint(641, 1271, -5888) //OK
call ZergSetPoint(642, -1000, -1500) // cathedral position
set zergMaxPaths[6]=4
endfunction
//=============================================================
//=============================================================
function InitTrig_ZergData takes nothing returns nothing
call Zerg_SavePools()
call Zerg_SaveMeetingPoints()
set ZERG_HERO_BEAST=gg_unit_U009_0049
set ZERG_HERO_SLAYER=gg_unit_N003_0047
set ZERG_HERO_QUEEN=gg_unit_U006_0032
endfunction
globals
boolexpr g_filtrZEnemy=null
boolexpr g_filtrZEnemyStructure=null
boolexpr g_filtrZEnemyGround=null
boolexpr g_filtrZEnemyNotImmune=null
boolexpr g_filtrZEnemyGroundNotImmune=null
boolexpr g_filtrZEnemyOrganicNotImmune=null
boolexpr g_filtrZEnemyGroundOrganicNotImmune=null
boolexpr g_filtrZEnemyGroundOrganicNotImmuneHero=null
boolexpr g_filtrZergUnits=null
boolexpr g_filtrZergUnits_OrganicNotHero=null
endglobals
//----------------------------------------------------------------------------------------------------------------
// ZERG FILTERS
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemies takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemiesStructureOnly takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE + FS_UNIT_STRUCTURE
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemiesGroundOnly takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE + FS_UNIT_GROUND
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemiesNotMagImmune takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE + FS_UNIT_NON_IMMUNE
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
function FiltrZergEnemiesGroundNotMagImmune takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE + FS_UNIT_GROUND + FS_UNIT_NON_IMMUNE
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemiesOrganicNotMagImmune takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE + FS_UNIT_NON_IMMUNE + FS_UNIT_ORGANIC
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergEnemiesOrganicGroundOnly_NotMagicImmune takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE
set f = f + FS_UNIT_ORGANIC + FS_UNIT_GROUND + FS_UNIT_NON_IMMUNE
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZEnemyOrganicGround_NotImmune_Hero takes nothing returns boolean
local integer f = FS_UNIT_ALIVE + FS_UNIT_ENEMY + FS_UNIT_VISIBLE + FS_UNIT_NON_INVULNERABLE
set f = f + FS_UNIT_ORGANIC + FS_UNIT_GROUND + FS_UNIT_NON_IMMUNE + FS_UNIT_HERO
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, f)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergUnits takes nothing returns boolean
//return UnitAlive(GetFilterUnit()) and GetOwningPlayer(GetFilterUnit())==PLAYER_ZERG
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, FS_UNIT_ALIVE + FS_UNIT_ALLY)
endfunction
//----------------------------------------------------------------------------------------------------------------
function FiltrZergUnits_OrganicNotHero takes nothing returns boolean
return UnitFilter(GetFilterUnit(), PLAYER_ZERG, FS_UNIT_ALIVE + FS_UNIT_ALLY + FS_UNIT_NON_HERO + FS_UNIT_ORGANIC)
endfunction
//----------------------------------------------------------------------------------------------------------------
function ZergSetFilters takes nothing returns nothing
set g_filtrZEnemy = Condition(function FiltrZergEnemies)
set g_filtrZEnemyGround = Condition(function FiltrZergEnemiesGroundOnly)
set g_filtrZEnemyStructure = Condition(function FiltrZergEnemiesStructureOnly)
set g_filtrZEnemyNotImmune = Condition(function FiltrZergEnemiesNotMagImmune)
set g_filtrZEnemyGroundNotImmune = Condition(function FiltrZergEnemiesGroundNotMagImmune)
set g_filtrZEnemyOrganicNotImmune = Condition(function FiltrZergEnemiesOrganicNotMagImmune)
set g_filtrZEnemyGroundOrganicNotImmune = Condition(function FiltrZergEnemiesOrganicGroundOnly_NotMagicImmune)
set g_filtrZEnemyGroundOrganicNotImmuneHero = Condition(function FiltrZEnemyOrganicGround_NotImmune_Hero)
set g_filtrZergUnits = Condition(function FiltrZergUnits)
set g_filtrZergUnits_OrganicNotHero = Condition(function FiltrZergUnits_OrganicNotHero)
endfunction
//===================================================================
function InitTrig_ZergFilters takes nothing returns nothing
set gg_trg_ZergFilters = CreateTrigger( )
call ZergSetFilters()
endfunction
/*
zerg group
ZergGroup_Alive, ZergGroup_GetCount, ZergGroup_Completed,
ZergGroup_GetFlyersCount, ZergGroup_GetWalkersCount, ZergGroup_IsMixed
ZergGroup_GetPoolNo, ZergGroup_GetCenterX, ZergGroup_GetCenterY
ZergGroup_IsDefendersGroup, ZergGroup_IsAttackersGroup
ZergGroup_CanAttackAir
ZergGroup_GetDestinationX, ZergGroup_GetDestinationY, ZergGroup_SetDestinationXY
ZergGroup_GetUnitsAlivePercent
ZergGroup_SetTarget, ZergGroup_ResetTarget, ZergGroup_GetTarget, ZergGroup_HasTarget
ZergGetStretchedValue, ZergGetNOTStretchedValue
ZergGroup_Stretched, ZergGroup_NotStretched, ZergGroup_InRangeOfDest
ZergGroup_EnemyCanSeeInvisible
zerg unit
Zerg_GetTarget, Zerg_SetTarget, Zerg_ResetTarget
ZergUnit_CanAttackAir, Zerg_GetNotBurrowedUnitId, Zerg_TargetValid, ZergHaveTargetForMagicAttack
spawning pool
ZergGetPoolNo, ZPool_SetHeroesCount, ZPool_GetHeroesCount, ZergGetRandomPoolForHero
*/
globals
unit zergTempWard=null // used in "ZergGroup_EnemyCanSeeInvisible"
unit zergGTempTarget1=null //used in "ZergGroup_GetTarget" , ZergG_GetTarget
endglobals
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
function ZergGroup_Alive takes group g returns boolean // GetHandleId(null) is zero
return HaveSavedInteger(zergHash, GetHandleId(g), KEY_GROUP_COUNT)
endfunction
function ZergGroup_GetCount takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_COUNT)
endfunction
function ZergGroup_Completed takes group g returns boolean
return LoadBoolean(zergHash, GetHandleId(g), KEY_GROUP_COMPLETED)
endfunction
function ZergGroup_GetFlyersCount takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_FLYERS)
endfunction
function ZergGroup_GetWalkersCount takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_WALKERS)
endfunction
// if group contains flyers and walkers -> returns true
function ZergGroup_IsMixed takes group g returns boolean
return (ZergGroup_GetFlyersCount(g)>0) and (ZergGroup_GetWalkersCount(g)>0)
endfunction
function ZergGroup_GetPoolNo takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_POOL_NO)
endfunction
// group center x/y updated every 2seconds in trigger "ZergVisibilityWard"
function ZergGroup_GetCenterX takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_CENTER_X)
endfunction
function ZergGroup_GetCenterY takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_CENTER_Y)
endfunction
function ZergG_GetCenterX takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_CENTER_X)
endfunction
function ZergG_GetCenterY takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_CENTER_Y)
endfunction
function ZergGroup_IsDefendersGroup takes group g returns boolean
return (LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_TYPE)==DEFENCE)
endfunction
function ZergGroup_IsAttackersGroup takes group g returns boolean
return (LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_TYPE)==ATTACK)
endfunction
function ZergGroup_IsCargoGroup takes group g returns boolean
return (LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_TYPE)==ATTACK_CARGO)
endfunction
function ZergGroup_CanAttackAir takes group g returns boolean
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_CAN_ATTACK_AIR)>0
endfunction
//destination Get/Set
function ZergGroup_GetDestinationX takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_DESTINATION_X)
endfunction
function ZergGroup_GetDestinationY takes group g returns integer
return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_DESTINATION_Y)
endfunction
function ZergG_GetDestinationX takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_DESTINATION_X)
endfunction
function ZergG_GetDestinationY takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_DESTINATION_Y)
endfunction
function ZergGroup_SetDestinationXY takes group g, integer x, integer y returns nothing
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_DESTINATION_X, x)
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_DESTINATION_Y, y)
endfunction
//consolidate Get/Set
function ZergG_GetConsolidateX takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_CONSOLIDATE_X)
endfunction
function ZergG_GetConsolidateY takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_CONSOLIDATE_Y)
endfunction
function ZergG_SetConsolidateXY takes group g, integer x, integer y returns nothing
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_CONSOLIDATE_X, x)
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_CONSOLIDATE_Y, y)
endfunction
//group state
function ZergGroup_SetState takes group g, integer state returns nothing
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_STATE, state)
endfunction
function ZergG_GetState takes integer group_id returns integer
return LoadInteger(zergHash, group_id, KEY_GROUP_STATE)
endfunction
// example 1.00 : all group mambers alive, 0.20 : 20% of group is alive
function ZergGroup_GetUnitsAlivePercent takes group g returns real
local integer groupMaxSize=LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_MAX_SIZE)
local integer count=LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_COUNT)
return I2R(count) / I2R(groupMaxSize)
endfunction
//----------------------------------------------------------------------------------------------------------------
//ZergGroup_ResetTarget, ZergGroup_SetTarget, ZergGroup_GetTarget, ZergGroup_HasTarget
//----------------------------------------------------------------------------------------------------------------
function ZergGroup_SetTarget takes group g, unit target returns nothing
local unit FoG=null
call SaveUnitHandle(zergHash, GetHandleId(g), KEY_GROUP_TARGET, target)
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
set g_zergTarget[GetUnitUserData(FoG)]=target
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
endfunction
function ZergGroup_ResetTarget takes group g returns nothing
local unit FoG=null
call RemoveSavedHandle(zergHash, GetHandleId(g), KEY_GROUP_TARGET)
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
set g_zergTarget[GetUnitUserData(FoG)]=null
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
endfunction
//zergGTempTarget1
function ZergGroup_GetTarget takes group g returns unit
set zergGTempTarget1 = LoadUnitHandle(zergHash, GetHandleId(g), KEY_GROUP_TARGET)
return zergGTempTarget1
endfunction
//zergGTempTarget1
function ZergG_GetTarget takes integer group_id returns unit
set zergGTempTarget1 = LoadUnitHandle(zergHash, group_id, KEY_GROUP_TARGET)
return zergGTempTarget1
endfunction
function ZergGroup_HasTarget takes group g returns boolean
return HaveSavedHandle(zergHash, GetHandleId(g), KEY_GROUP_TARGET) and UnitAlive(ZergGroup_GetTarget(g))
endfunction
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
function ZergGetStretchedValue takes group g returns integer
local integer i=ZergGroup_GetWalkersCount(g)
if i<8 then
return 1000
elseif i<15 then
return 1300
elseif i<20 then
return 1500
endif
return 1700
endfunction
function ZergGetNOTStretchedValue takes group g returns integer
local integer i=ZergGroup_GetWalkersCount(g)
if i<8 then
return 600
elseif i<15 then
return 1000
elseif i<20 then
return 1200
endif
return 1400
endfunction
//-------------------------------------------------------------------------------------------------------
function ZergGroup_Stretched takes group g returns boolean
return Group_Stretched(g, ZergGetStretchedValue(g))
endfunction
function ZergGroup_NotStretched takes group g returns boolean
return not Group_Stretched(g, ZergGetNOTStretchedValue(g))
endfunction
//-------------------------------------------------------------------------------------------------------
function ZergGroup_InRangeOfDest takes group g returns boolean
local integer Tx=ZergGroup_GetDestinationX(g)
local integer Ty=ZergGroup_GetDestinationY(g)
return Group_InRange(g, Tx, Ty, ZergGetNOTStretchedValue(g))
endfunction
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
function ZergGroup_EnemyCanSeeInvisible takes group g returns boolean
// Can zerg enemy see invisible zerg units at group center location?
set zergTempWard=LoadUnitHandle(zergHash, GetHandleId(g), KEY_WARD)//ward
return IsUnitVisible(zergTempWard, Player(0))
endfunction
function ZergG_EnemyCanSeeInvisible takes integer group_id returns boolean
// Can zerg enemy see invisible zerg units at group center location?
set zergTempWard=LoadUnitHandle(zergHash, group_id, KEY_WARD)//ward
return IsUnitVisible(zergTempWard, Player(0))
endfunction
//-------------------------------------------------------------------------------------------------------
// UNIT
//-------------------------------------------------------------------------------------------------------
function Zerg_GetTarget takes unit zerg returns unit
return g_zergTarget[GetUnitUserData(zerg)]
endfunction
function Zerg_SetTarget takes unit zerg, unit target returns nothing
set g_zergTarget[GetUnitUserData(zerg)]=target
endfunction
function Zerg_ResetTarget takes unit zerg returns nothing
set g_zergTarget[GetUnitUserData(zerg)]=null
endfunction
//run on zerg unit removal:
function Trig_OnZergRemovalCleanTarget_Actions takes nothing returns boolean
set g_zergTarget[udg_UDex]=null
set g_zGroupId[udg_UDex] = 0
return false
endfunction
function ZergUnit_CanAttackAir takes unit u returns boolean
local integer unitId=GetUnitTypeId(u)
if unitId==ZERG_HYDRALISK or unitId==ZERG_HUNTER_KILLER or unitId==ZERG_DEFILER or unitId==ZERG_MUTALISK then
return true
elseif unitId==ZERG_BURROW_HYDRALISK or unitId==ZERG_BURROW_RED_HYDRALISK or unitId==ZERG_BURROW_DEFILER then
return true
elseif IsUnitType(u, UNIT_TYPE_HERO) then
return true
endif
return false
endfunction
//----------------------------------------------------------------------------------------------------------------
function Zerg_GetNotBurrowedUnitId takes integer unitId returns integer
if unitId==ZERG_BURROW_ZERGLING then
return ZERG_ZERGLING
elseif unitId==ZERG_BURROW_HYDRALISK then
return ZERG_HYDRALISK
elseif unitId==ZERG_BURROW_RED_HYDRALISK then
return ZERG_HUNTER_KILLER
elseif unitId==ZERG_BURROW_DEFILER then
return ZERG_DEFILER
elseif unitId==ZERG_BURROW_LURKER then
return ZERG_LURKER
endif
return unitId
endfunction
//----------------------------------------------------------------------------------------------------------------
// returns "false" if target is dead / invisible / out of range / invulnerable
function Zerg_TargetValid takes unit u, integer x, integer y, integer range returns boolean
return UnitAlive(u) and IsUnitVisible(u, PLAYER_ZERG) and IsUnitInRangeXY(u, x, y, range) and (not IsUnitInvulnerable(u))
endfunction
//----------------------------------------------------------------------------------------------------------------
function ZergHaveTargetForMagicAttack takes real centerX, real centerY, real distance returns boolean
local unit u=null
local boolean found=false
call GroupEnumUnitsInRange(ug, centerX, centerY, distance, g_filtrZEnemyNotImmune)
loop //filtr: alive, enemy, visible, not invulnerable, not magic immune
set u = FirstOfGroup(ug)
exitwhen (u == null) or found
set found=true
//---
call GroupRemoveUnit(ug, u)
endloop
call GroupClear(ug)
set u=null
return found
endfunction
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
// SPAWNING POOL
//----------------------------------------------------------------------------------------------------
function ZergGetPoolNo takes unit pool returns integer
local integer i=1
loop
exitwhen i>6
if pool==zergSpawningPool[i] then
return i
endif
set i=i+1
endloop
return 1
endfunction
//---------------------------------------------------------------------------------------------------
//new
function ZPool_SetHeroesCount takes integer poolNo, integer count returns nothing
set g_poolHeroesCount[poolNo]=count
endfunction
function ZPool_GetHeroesCount takes integer poolNo returns integer
return g_poolHeroesCount[poolNo]
endfunction
//----------------------------------------------------------------------------------------------
// searches for random pool without a hero; if all pools have hero(s) then it picks a pool with lowest hp
//----------------------------------------------------------------------------------------------
function ZergGetRandomPoolForHero takes nothing returns integer
local string s=""
local integer position=1
local integer i=1
local real lowestHP=100000.00
local integer lowestHPPoolNo = 1
loop
exitwhen i>6
if UnitAlive(zergSpawningPool[i]) and (not IsUnitHidden(zergSpawningPool[i])) then
//lowest hp part start
if GetWidgetLife(zergSpawningPool[i]) < lowestHP then
set lowestHP = GetWidgetLife(zergSpawningPool[i])
set lowestHPPoolNo = i
endif //lowest hp part end
//pool w/o a hero:
if ZPool_GetHeroesCount(i) == 0 then
set s=s+I2S(i)
endif
endif
set i=i+1
endloop
if not (s == "") then
set position=GetRandomInt(1, StringLength(s))
return S2I(SubStringBJ(s, position, position))
endif
return lowestHPPoolNo
endfunction
function ZergIsBurrowed takes unit u returns boolean
local integer unitId=GetUnitTypeId(u)
if unitId==ZERG_BURROW_ZERGLING or unitId==ZERG_BURROW_HYDRALISK or unitId==ZERG_BURROW_RED_HYDRALISK then
return true
elseif unitId==ZERG_BURROW_DEFILER or unitId==ZERG_BURROW_LURKER then
return true
endif
return false
endfunction
//for DefendersGroup
function ZGDef_ExecTrg takes unit u returns nothing
local integer t=GetUnitTypeId(u)
local integer id=GetUnitUserData(u)
set g_zergBehaviourUnit=u
if t==ZERG_OVERLORD then
call TriggerExecute(gg_trg_ZDefO)
elseif t==ZERG_DEFILER then
call TriggerExecute(gg_trg_ZDefD)
elseif t==ZERG_LURKER then
call TriggerExecute(gg_trg_ZDefL)
elseif u==ZERG_HERO_BEAST then
set g_zFlag[id]=NEUTRAL
call TriggerExecute(gg_trg_BeastDef)
elseif u==ZERG_HERO_SLAYER then
set g_zFlag[id]=NEUTRAL
call TriggerExecute(gg_trg_SlayerDef)
elseif u==ZERG_HERO_QUEEN then
set g_zFlag[id]=NEUTRAL
call TriggerExecute(gg_trg_QueenDef)
else
call TriggerExecute(gg_trg_ZDef1)
endif
endfunction
//for Attackers Group
function ZGAtt_ExecTrg takes unit u returns nothing
local integer t=GetUnitTypeId(u)
set g_zergBehaviourUnit=u
if t==ZERG_ZERGLING or t==ZERG_HYDRALISK or t==ZERG_HUNTER_KILLER then
call TriggerExecute(gg_trg_ZAttZHR)
elseif t==ZERG_OVERLORD then
call TriggerExecute(gg_trg_ZAttO)
elseif t==ZERG_ULTRALISK then
call TriggerExecute(gg_trg_ZAttU)
elseif t==ZERG_GUARDIAN then
call TriggerExecute(gg_trg_ZAttG)
elseif t==ZERG_MUTALISK then
call TriggerExecute(gg_trg_ZAttM)
elseif t==ZERG_DEFILER then
call TriggerExecute(gg_trg_ZAttD)
elseif t==ZERG_LURKER then
call TriggerExecute(gg_trg_ZAttL)
elseif u==ZERG_HERO_BEAST then
call TriggerExecute(gg_trg_BeastAttack)
elseif u==ZERG_HERO_SLAYER then
call TriggerExecute(gg_trg_SlayerAttack)
elseif u==ZERG_HERO_QUEEN then
call TriggerExecute(gg_trg_QueenAttack)
endif
endfunction
//======================================= ==========================
function InitTrig_ZergFunctions takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
call TriggerAddCondition(t, Condition(function Trig_OnZergRemovalCleanTarget_Actions))
endfunction
/*
When hero dies all connections are reseted. Revive at Pool location. Add to defenders group.
Hero can be added to AttackingGroup if
alive, not teleporting, has Pool (is in defenders group),
its Pool was not attacked over last 15sec.
*/
//---------------------------------------------------------------------------------------------------
//--------------Hero <--> (attacking) group ---------------------------------------------------
//---------------------------------------------------------------------------------------------------
function ZHeroAttackGroup_Disconnect takes unit hero, group attackGroup returns nothing
call RemoveSavedHandle(zergHash, GetHandleId(hero), KEY_GROUP)
call RemoveSavedHandle(zergHash, GetHandleId(attackGroup), KEY_HERO)
endfunction
function ZHeroAttackGroup_Connect takes unit hero, group attackGroup returns nothing
call SaveGroupHandle(zergHash, GetHandleId(hero), KEY_GROUP, attackGroup)
call SaveUnitHandle(zergHash, GetHandleId(attackGroup), KEY_HERO, hero)
endfunction
function ZAttackGroup_HasHero takes group g returns boolean
return HaveSavedHandle(zergHash, GetHandleId(g), KEY_HERO)
endfunction
function ZAttackGroup_GetHero takes group g returns unit
return LoadUnitHandle(zergHash, GetHandleId(g), KEY_HERO)
endfunction
function ZHero_IsInAttackingGroup takes unit hero returns boolean
return HaveSavedHandle(zergHash, GetHandleId(hero), KEY_GROUP)
endfunction
function ZHero_GetAttackingGroup takes unit hero returns group
return LoadGroupHandle(zergHash, GetHandleId(hero), KEY_GROUP)
endfunction
//-------------------------------------------------------------------------
// for defenders group
//-------------------------------------------------------------------------
function ZergHero_GetPoolNo takes unit hero returns integer
return LoadInteger(zergHash, GetHandleId(hero), KEY_HERO_POOL_NO)
endfunction
function ZergHero_SetPoolNo takes unit hero, integer poolNo returns nothing
call SaveInteger(zergHash, GetHandleId(hero), KEY_HERO_POOL_NO, poolNo)
endfunction
//----------------------------------------------------------------------------------------------------
//-----------uses trigger sleep 1.00sec ----------------------------------------------------------
//----------------------------------------------------------------------------------------------------
function ZergTeleportHero takes unit hero, real x, real y returns nothing
local string eff = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl"
set g_zergHeroTeleporting[GetUnitUserData(hero)]=true
call DisableUnitMovement(hero)
call SetUnitInvulnerable(hero, true)
call AddTimedEffect(GetUnitX(hero), GetUnitY(hero), 1.50, eff)
call AddTimedEffect(x, y, 1.50, eff)
call TriggerSleepAction(1.00)
call SetUnitPosition(hero, x, y)
call SetUnitInvulnerable(hero, false)
call EnableUnitMovement(hero)
set g_zergHeroTeleporting[GetUnitUserData(hero)]=false
endfunction
//----------------------------------------------------------------------------------------------------
// alive, not teleporting, has Pool (is in defenders group),
// its Pool was not attacked over last 15sec.
//----------------------------------------------------------------------------------------------------
function ZergGetHeroToAttack takes nothing returns unit
local string s=""
local integer position=1
local boolean alive1 = UnitAlive(ZERG_HERO_QUEEN)
local boolean alive2 = UnitAlive(ZERG_HERO_SLAYER)
local boolean alive3 = UnitAlive(ZERG_HERO_BEAST)
local boolean notTeleporting1 = not g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_QUEEN)]
local boolean notTeleporting2 = not g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_SLAYER)]
local boolean notTeleporting3 = not g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_BEAST)]
local integer x1 = ZergHero_GetPoolNo(ZERG_HERO_QUEEN)//may be "0"
local integer x2 = ZergHero_GetPoolNo(ZERG_HERO_SLAYER)
local integer x3 = ZergHero_GetPoolNo(ZERG_HERO_BEAST)
local boolean isInDefendersGroup1 = (x1>0)
local boolean isInDefendersGroup2 = (x2>0)
local boolean isInDefendersGroup3 = (x3>0)
local boolean poolOK1 = (not CSUnit_Attacked(zergSpawningPool[x1], 15.00))
local boolean poolOK2 = (not CSUnit_Attacked(zergSpawningPool[x2], 15.00))
local boolean poolOK3 = (not CSUnit_Attacked(zergSpawningPool[x3], 15.00))
if alive1 and notTeleporting1 and isInDefendersGroup1 and poolOK1 then
set s=s+"1"
elseif alive2 and notTeleporting2 and isInDefendersGroup2 and poolOK2 then
set s=s+"2"
elseif alive3 and notTeleporting3 and isInDefendersGroup3 and poolOK3 then
set s=s+"3"
endif
if not (s == "") then
set position=GetRandomInt(1, StringLength(s))
set s = SubStringBJ(s, position, position)
if s=="1" then
return ZERG_HERO_QUEEN
elseif s=="2" then
return ZERG_HERO_SLAYER
elseif s=="3" then
return ZERG_HERO_BEAST
endif
endif
return null
endfunction
//-------------------------------------------------------------------------
// 1. runs when hero dies
//-------------------------------------------------------------------------
function ZergHero_Disconnect takes unit hero returns nothing
local integer poolNo=ZergHero_GetPoolNo(hero)
local group g=null
if ZHero_IsInAttackingGroup(hero) then //was in attacking group?
set g=ZHero_GetAttackingGroup(hero)
call ZHeroAttackGroup_Disconnect(hero, g)
elseif poolNo > 0 then //hero is in defenders group
call GroupRemoveUnit(g_zergDefendersGroup[poolNo], hero)
call ZPool_SetHeroesCount(poolNo, ZPool_GetHeroesCount(poolNo) - 1)
call ZergHero_SetPoolNo(hero, 0) // disconnect poolNo from hero
endif
set g_zGroupId[GetUnitUserData(hero)] = 0
set g=null
endfunction
//-------------------------------------------------------------------------
// 1. trigger ZergCreateHeroes
// 2. hero revived
// 3. here in function "ZergPoolDead_ReconnectHeroes" -> this func is called in "ZergAIdefend" after pool dies
//-------------------------------------------------------------------------
function ZergHero_ConnectPool takes unit hero, integer poolNo returns nothing
local unit target=null
call ZPool_SetHeroesCount(poolNo, ZPool_GetHeroesCount(poolNo) + 1) //update pool's heroes count
call ZergHero_SetPoolNo(hero, poolNo) //connect poolNo to hero
call GroupAddUnit(g_zergDefendersGroup[poolNo], hero) //add to defenders group
set g_zGroupId[GetUnitUserData(hero)] = GetHandleId(g_zergDefendersGroup[poolNo])
call ZGDef_ExecTrg(hero)
set target=null
endfunction
//----------------------------------------------------------------------------------------------------
// 1. Hero goes to attack (AttackWaveLibrary / Cathedral)
//----------------------------------------------------------------------------------------------------
function ZergAttackGroup_AddHero takes group g, unit hero returns nothing
local integer group_id=GetHandleId(g)
local integer groupCount=LoadInteger(zergHash, group_id, KEY_GROUP_COUNT)
local integer walkers=LoadInteger(zergHash, group_id, KEY_GROUP_WALKERS)
local integer canAttackAir=LoadInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR)
local integer id=GetUnitUserData(hero)
local integer poolNo=ZergHero_GetPoolNo(hero)
local trigger t=LoadTriggerHandle(zergHash, group_id, KEY_GROUP_TRG)
// hero who is added: -- > alive, not teleporting, has Pool (is in defenders group), (its Pool was not attacked over last 15sec.)
call GroupRemoveUnit(g_zergDefendersGroup[poolNo], hero)
call ZPool_SetHeroesCount(poolNo, ZPool_GetHeroesCount(poolNo) - 1)
call ZergHero_SetPoolNo(hero, 0) // disconnect poolNo from hero
//...
call TriggerRegisterUnitEvent(t, hero, EVENT_UNIT_DEATH) //add event to trigger
//...
call GroupAddUnit(g, hero)//add to attacking group
call SaveInteger(zergHash, group_id, KEY_GROUP_COUNT, groupCount+1)
call SaveInteger(zergHash, group_id, KEY_GROUP_WALKERS, walkers+1)
call SaveInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR, canAttackAir+1)
call ZHeroAttackGroup_Connect(hero, g)
set g_zGroupId[id] = group_id
// cancel behaviour defence trigger:
//wait until defence behaviour trigger is OFF for this hero
set g_zFlag[id]=INTERRUPT
loop
exitwhen not g_zergBehaviourTrgRunning[id]
call TriggerSleepAction(0.20)
endloop
set t=null
endfunction
//-------------------------------------------------------------------------
// used in ZergAIdefend, after pool dies
//-------------------------------------------------------------------------
function ZergPoolDies_ReconnectHeroes takes integer poolNo returns nothing
local integer newPoolNo=1
//wait until defence behaviour trigger is OFF for this hero
if ZergHero_GetPoolNo(ZERG_HERO_BEAST)==poolNo then
loop
exitwhen not g_zergBehaviourTrgRunning[GetUnitUserData(ZERG_HERO_BEAST)]
call TriggerSleepAction(0.50)
endloop
// move alive heroes to diffrent alive pool
call GroupRemoveUnit(g_zergDefendersGroup[poolNo], ZERG_HERO_BEAST)
set newPoolNo=ZergGetRandomPoolForHero()
call ZergTeleportHero(ZERG_HERO_BEAST, GetUnitX(zergSpawningPool[newPoolNo]), GetUnitY(zergSpawningPool[newPoolNo]))//uses sleep 1sec
call ZergHero_ConnectPool(ZERG_HERO_BEAST, newPoolNo)
endif
if ZergHero_GetPoolNo(ZERG_HERO_SLAYER)==poolNo then
loop
exitwhen not g_zergBehaviourTrgRunning[GetUnitUserData(ZERG_HERO_SLAYER)]
call TriggerSleepAction(0.50)
endloop
call GroupRemoveUnit(g_zergDefendersGroup[poolNo], ZERG_HERO_SLAYER)
set newPoolNo=ZergGetRandomPoolForHero()
call ZergTeleportHero(ZERG_HERO_SLAYER, GetUnitX(zergSpawningPool[newPoolNo]), GetUnitY(zergSpawningPool[newPoolNo]))//uses sleep 1sec
call ZergHero_ConnectPool(ZERG_HERO_SLAYER, newPoolNo)
endif
if ZergHero_GetPoolNo(ZERG_HERO_QUEEN)==poolNo then
loop
exitwhen not g_zergBehaviourTrgRunning[GetUnitUserData(ZERG_HERO_QUEEN)]
call TriggerSleepAction(0.50)
endloop
call GroupRemoveUnit(g_zergDefendersGroup[poolNo], ZERG_HERO_QUEEN)
set newPoolNo=ZergGetRandomPoolForHero()
call ZergTeleportHero(ZERG_HERO_QUEEN, GetUnitX(zergSpawningPool[newPoolNo]), GetUnitY(zergSpawningPool[newPoolNo]))//uses sleep 1sec
call ZergHero_ConnectPool(ZERG_HERO_QUEEN, newPoolNo)
endif
endfunction
//===========================================================================
function InitTrig_ZergFunctionsHero takes nothing returns nothing
endfunction
globals
//queue list:
integer array g_zType
group array g_zGroup
integer array g_zPoolNo
integer g_zQueueNo=0
integer g_zQueuePoolStart=1
//mutation:
integer g_mutating_poolNo=1
real g_mutating_x=0.00
real g_mutating_y=0.00
integer g_mutating_type=0
group g_mutating_group=CreateGroup()
//pool <-> heroes count:
integer array g_poolHeroesCount //[1..6]
endglobals
//----------------------------------------------------------------------------------------------------
//----------it sets 3 globals----------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
function QueueEgg takes integer poolNo, integer zergType, group addToGroup returns nothing
if UnitAlive(zergSpawningPool[poolNo]) then
set g_zQueueNo = g_zQueueNo + 1
if g_zQueueNo>ZERG_MAX_QUEUE_NR then // set new limit ~1000
set g_zQueueNo=1
endif
//set 3 globals:
set g_zPoolNo[g_zQueueNo]=poolNo
set g_zType[g_zQueueNo]=zergType
set g_zGroup[g_zQueueNo]=addToGroup
endif
endfunction
//---------------------------------------i=poolNo-------------------------------------------------------------
function CreateEgg takes integer i, integer zergType, group g returns nothing
local real dist=GetRandomReal(150.00, 250.00)
local real angle=GetRandomReal(0.00, 2*bj_PI)
local real Tx=0.00
local real Ty=0.00
if ZergGroup_IsAttackersGroup(g) or ZergGroup_IsCargoGroup(g) then
set dist=GetRandomReal(350.00, 450.00)
endif
set Tx=GetUnitX(zergSpawningPool[i])+dist*Cos(angle)
set Ty=GetUnitY(zergSpawningPool[i])+dist*Sin(angle)
call IsTerrainWalkable(Tx, Ty)
call IssuePointOrder(zergSpawningPool[i], "clusterrockets", TerrainPathability_X, TerrainPathability_Y)
//start mutation loop:
set g_mutating_x=TerrainPathability_X
set g_mutating_y=TerrainPathability_Y
set g_mutating_poolNo=i
set g_mutating_type=zergType
set g_mutating_group=g
call TriggerExecute(gg_trg_Mutation)
endfunction
//----------------------------------------------------------------------------------------------------
//---------------- set g_zQueuePoolStart and run this trigger (6 times) -----------
//----------------------------------------------------------------------------------------------------
function Trig_Pools_Actions takes nothing returns nothing
local integer poolNo=g_zQueuePoolStart
local integer x=0
loop
exitwhen GAME_OVER or (not UnitAlive(zergSpawningPool[poolNo]))
set x=0
loop //check list (starts from 1):
exitwhen x>ZERG_MAX_QUEUE_NR
if g_zPoolNo[x]==poolNo and g_zType[x] != 0 then
call CreateEgg(poolNo, g_zType[x], g_zGroup[x])
set g_zPoolNo[x]=0 //reset
set g_zType[x]=0 //reset
set g_zGroup[x]=null //reset
exitwhen true
endif
set x=x+1
endloop
call TriggerSleepAction(ZERG_EGG_THROW_PAUSE)
endloop
endfunction
//-------------------------------------------------------------------------------------------
// Pool dies
//-------------------------------------------------------------------------------------------
function Trig_PoolDies takes nothing returns nothing
call CheckGameOver()
endfunction
//-------------------------------------------------------------------------------------------
// run on zerg Init
//-------------------------------------------------------------------------------------------
function ZergInitPools takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=1
loop
exitwhen i>6
call ZPool_SetHeroesCount(i, 0)
call TriggerRegisterUnitEvent(t, zergSpawningPool[i], EVENT_UNIT_DEATH)
set g_zQueuePoolStart=i
call TriggerExecute(gg_trg_Pool)
set i=i+1
endloop
call TriggerAddAction(t, function Trig_PoolDies)
//run this func on map init
endfunction
//===========================================================================
function InitTrig_Pool takes nothing returns nothing
set gg_trg_Pool = CreateTrigger( )
call TriggerAddAction( gg_trg_Pool, function Trig_Pools_Actions )
endfunction
//------------------------------------------------------------------------------------------------
// update group when new unit is created
//------------------------------------------------------------------------------------------------
function ZergUpdateGroup_OnUnitCreation takes group g, unit newMember returns nothing
local integer group_id=GetHandleId(g)
local integer groupCount=ZergGroup_GetCount(g) + 1 //increase group count by 1
local integer requiredGroupSize=LoadInteger(zergHash, group_id, KEY_GROUP_MAX_SIZE)
local integer flyersCount=LoadInteger(zergHash, group_id, KEY_GROUP_FLYERS)
local integer walkersCount=LoadInteger(zergHash, group_id, KEY_GROUP_WALKERS)
local integer canAttackAirCount=LoadInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR)
local trigger t=LoadTriggerHandle(zergHash, group_id, KEY_GROUP_TRG)
local unit target=null
local integer groupType=LoadInteger(zergHash, group_id, KEY_GROUP_TYPE)
//bind unit with its group id
set g_zGroupId[GetUnitUserData(newMember)] = group_id
call GroupAddUnit(g, newMember) // required by "GroupCombatState"
call SaveInteger(zergHash, group_id, KEY_GROUP_COUNT, groupCount)//save new count
if IsUnitType(newMember, UNIT_TYPE_FLYING) then
call SaveInteger(zergHash, group_id, KEY_GROUP_FLYERS, flyersCount+1)
else
call SaveInteger(zergHash, group_id, KEY_GROUP_WALKERS, walkersCount+1)
endif
if ZergUnit_CanAttackAir(newMember) then
call SaveInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR, canAttackAirCount+1)
endif
if groupCount==requiredGroupSize then
call SaveBoolean(zergHash, group_id, KEY_GROUP_COMPLETED, true)
endif
call TriggerRegisterUnitEvent(t, newMember, EVENT_UNIT_DEATH) //add event to trigger
if groupType==DEFENCE then
call ZGDef_ExecTrg(newMember)
elseif groupType==ATTACK then
call ZGAtt_ExecTrg(newMember)
elseif groupType==ATTACK_CARGO then
//call ZGAtt_ExecTrg(newMember)
endif
set t=null
set target=null
endfunction
//***********************************************************************
//------------------------------------------------------------------------------------------------
// update group when new unit dies
//------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
// in "ZergAIdefend" trigger, after pool dies
// here, in function "Trig_WaveMemberDies"
//---------------------------------------------------------------------------------------------
function ZergGroup_Reset takes group g returns nothing
local integer group_id=GetHandleId(g)
local trigger trig=LoadTriggerHandle(zergHash, group_id, KEY_GROUP_TRG)
local integer trigger_id=GetHandleId(trig)
local unit ward=LoadUnitHandle(zergHash, group_id, KEY_WARD)
call MsgDev(" destroying group .." +I2S(group_id))
//trigger part:
call FlushChildHashtable(zergHash, trigger_id)
call DisableTrigger(trig)
call DestroyTrigger(trig)
set trig=null
//ward part:
call FlushChildHashtable(zergHash, GetHandleId(ward))//clean hash connected to ward
call KillUnit(ward)
call GroupRemoveUnit(g_zergWardVisibilityGroup, ward)
set ward=null
// clean all data conneted to group:
call FlushChildHashtable(zergHash, group_id)//clean hash connected to zerg GROUP
call DestroyGroup(g)
endfunction
//------------------------------------------------------------------------------------------------
// update group when unit dies (defender)
//------------------------------------------------------------------------------------------------
function Trig_DefenderMemberDies takes nothing returns nothing //specific unit dies event
local trigger t=GetTriggeringTrigger()
local integer trigger_id=GetHandleId(t)
local unit u=GetTriggerUnit()
local integer unitId=Zerg_GetNotBurrowedUnitId(GetUnitTypeId(u))
local group g = LoadGroupHandle(zergHash, trigger_id, KEY_GROUP)
local integer group_id=GetHandleId(g)
local integer poolNo = LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer groupCount=LoadInteger(zergHash, group_id, KEY_GROUP_COUNT) - 1 // new count
local boolean groupCompleted=LoadBoolean(zergHash, group_id, KEY_GROUP_COMPLETED)
local integer flyers=LoadInteger(zergHash, group_id, KEY_GROUP_FLYERS)
local integer walkers=LoadInteger(zergHash, group_id, KEY_GROUP_WALKERS)
local integer canAttackAir=LoadInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR)
set g_zGroupId[GetUnitUserData(u)] = 0
call SaveInteger(zergHash, group_id, KEY_GROUP_COUNT, groupCount)
call GroupRemoveUnit(g, u)
//call MsgDev(GetUnitName(u)+" defender dies, current group "+I2S(group_id)+" count: "+I2S(groupCount))
if IsUnitType(u, UNIT_TYPE_FLYING) then
call SaveInteger(zergHash, group_id, KEY_GROUP_FLYERS, flyers-1)
else
call SaveInteger(zergHash, group_id, KEY_GROUP_WALKERS, walkers-1)
endif
if ZergUnit_CanAttackAir(u) then
call SaveInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR, canAttackAir-1)
endif
if (not IsUnitType(u, UNIT_TYPE_HERO)) then
call QueueEgg(poolNo, unitId, g)
endif
set t=null
set u=null
set g=null
endfunction
//------------------------------------------------------------------------------------------------
// update group when unit dies (attack wave)
//------------------------------------------------------------------------------------------------
function Trig_WaveMemberDies takes nothing returns nothing//specific unit dies event
local trigger t=GetTriggeringTrigger()
local integer trigger_id=GetHandleId(t)
local unit u=GetTriggerUnit()
local integer unitId=Zerg_GetNotBurrowedUnitId(GetUnitTypeId(u))
local group g = LoadGroupHandle(zergHash, trigger_id, KEY_GROUP)
local integer group_id=GetHandleId(g)
local integer poolNo = LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer groupCount=LoadInteger(zergHash, group_id, KEY_GROUP_COUNT) - 1 // new count
local boolean groupCompleted=LoadBoolean(zergHash, group_id, KEY_GROUP_COMPLETED)
local integer flyers=LoadInteger(zergHash, group_id, KEY_GROUP_FLYERS)
local integer walkers=LoadInteger(zergHash, group_id, KEY_GROUP_WALKERS)
local integer canAttackAir=LoadInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR)
local boolean groupAgainstLibrary=LoadBoolean(zergHash, group_id, KEY_GROUP_AGAINST_LIBRARY)
set g_zGroupId[GetUnitUserData(u)] = 0
call SaveInteger(zergHash, group_id, KEY_GROUP_COUNT, groupCount)
call GroupRemoveUnit(g, u)
call MsgDev(GetUnitName(u)+" dies, current group "+I2S(group_id)+" count: "+I2S(groupCount))
if IsUnitType(u, UNIT_TYPE_FLYING) then
call SaveInteger(zergHash, group_id, KEY_GROUP_FLYERS, flyers-1)
else
call SaveInteger(zergHash, group_id, KEY_GROUP_WALKERS, walkers-1)
endif
if ZergUnit_CanAttackAir(u) then
call SaveInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR, canAttackAir-1)
endif
if (not groupCompleted) and (not IsUnitType(u, UNIT_TYPE_HERO)) then
call QueueEgg(poolNo, unitId, g)
endif
if groupCompleted then
if groupAgainstLibrary then
set g_totalAttackers_Library=g_totalAttackers_Library-1
else
set g_totalAttackers_Cathedral=g_totalAttackers_Cathedral-1
endif
endif
if groupCompleted and (groupCount==0) then
call ZergGroup_Reset(g)
endif
set t=null
set u=null
set g=null
endfunction
//===========================================================================
function InitTrig_ZGroupUpdate takes nothing returns nothing
set gg_trg_ZGroupUpdate = CreateTrigger( )
endfunction
function Trig_Mutation_Actions takes nothing returns nothing
local real x=g_mutating_x
local real y=g_mutating_y
local integer poolNo=g_mutating_poolNo
local integer zergType=g_mutating_type
local group g=g_mutating_group
local unit egg=null
local integer mutatingTime = GetUnitPointValueByType(zergType)*2 // x2 cause of 0.5sec wait in loop
local integer duration = 0
local integer phase=0
call TriggerSleepAction(1.10)
set egg=CreateUnit(PLAYER_ZERG, ZERG_EGG, x, y, 0.00)
if zergType==ZERG_GUARDIAN or zergType==ZERG_ULTRALISK then
call SetUnitScale(egg, 1.20, 1.20, 1.20)
endif
loop
if phase==0 and (not UnitAlive(egg)) then //queue to SpawningPool throw Egg, that was just destroyed
call QueueEgg(poolNo, zergType, g)
exitwhen true
endif
if duration==mutatingTime then
set phase=1
call KillUnit(egg)
elseif duration==(mutatingTime+1) then //create new zerg unit
set bj_lastCreatedUnit=CreateUnit(GetOwningPlayer(egg), zergType, GetUnitX(egg), GetUnitY(egg), GetRandomReal(0.00,360.00))
call ZergUpdateGroup_OnUnitCreation(g, bj_lastCreatedUnit)
exitwhen true
endif
call TriggerSleepAction(0.50)
set duration=duration+1
endloop
set egg=null
set g=null
endfunction
//===========================================================================
function InitTrig_Mutation takes nothing returns nothing
set gg_trg_Mutation = CreateTrigger( )
call TriggerAddAction( gg_trg_Mutation, function Trig_Mutation_Actions )
endfunction
//--------------------------------------------------------------------------------------------------------------------
// ----1-----------2-------------3----------------4-------------5----------6-----------7-----------8------------9----
// overlord / zergling / hydralisk / red hydralisk / lurker / defiler / mutalisk / guardian / ultralisk
//--------------------------------------------------------------------------------------------------------------------
function ZergCreateGroup takes integer groupType, unit pool, integer q1, integer q2, integer q3, integer q4, integer q5, integer q6, integer q7, integer q8, integer q9 returns group
local integer i=ZergGetPoolNo(pool)
local group g=CreateGroup()
local integer group_id = GetHandleId(g)
local integer requiredGroupSize=q1+q2+q3+q4+q5+q6+q7+q8+q9
local trigger trig=CreateTrigger() // unit dies trg
local unit ward=CreateUnitAtLoc(PLAYER_ZERG, ZERG_VISIBILITY_WARD, zergPoolLoc[i], 0.00)
//zergWardVisibility connected <-> g
call GroupAddUnit(g_zergWardVisibilityGroup, ward)
call SaveGroupHandle(zergHash, GetHandleId(ward), KEY_GROUP, g) //connect ward with its group
//group connected data:
call SaveUnitHandle(zergHash, group_id, KEY_WARD, ward)
call SaveInteger(zergHash, group_id, KEY_GROUP_POOL_NO, i)
call SaveInteger(zergHash, group_id, KEY_GROUP_MAX_SIZE, requiredGroupSize)
call SaveTriggerHandle(zergHash, group_id, KEY_GROUP_TRG, trig)
call SaveInteger(zergHash, group_id, KEY_GROUP_COUNT, 0)
call SaveBoolean(zergHash, group_id, KEY_GROUP_COMPLETED, false)
call SaveInteger(zergHash, group_id, KEY_GROUP_FLYERS, 0)
call SaveInteger(zergHash, group_id, KEY_GROUP_WALKERS, 0)
call SaveInteger(zergHash, group_id, KEY_GROUP_CAN_ATTACK_AIR, 0)
call SaveInteger(zergHash, group_id, KEY_GROUP_CENTER_X, R2I(GetUnitX(pool)))
call SaveInteger(zergHash, group_id, KEY_GROUP_CENTER_Y, R2I(GetUnitY(pool)))
call SaveInteger(zergHash, group_id, KEY_GROUP_TYPE, groupType)
call SaveInteger(zergHash, group_id, KEY_GROUP_STATE, GROUP_STATE_CREATING)
//trg connected:
call SaveGroupHandle(zergHash, GetHandleId(trig), KEY_GROUP, g) //connect trigger with group
if groupType==DEFENCE then
call TriggerAddAction(trig, function Trig_DefenderMemberDies)
else
call TriggerAddAction(trig, function Trig_WaveMemberDies)
endif
set ward=null
set trig=null
//SET QueueEggThrow:
loop
exitwhen q1==0
call QueueEgg(i, ZERG_OVERLORD, g)
set q1=q1-1
endloop
loop
exitwhen q2==0
call QueueEgg(i, ZERG_ZERGLING, g)
set q2=q2-1
endloop
loop
exitwhen q3==0
call QueueEgg(i, ZERG_HYDRALISK, g)
set q3=q3-1
endloop
loop
exitwhen q4==0
call QueueEgg(i, ZERG_HUNTER_KILLER, g)
set q4=q4-1
endloop
loop
exitwhen q5==0
call QueueEgg(i, ZERG_LURKER, g)
set q5=q5-1
endloop
loop
exitwhen q6==0
call QueueEgg(i, ZERG_DEFILER, g)
set q6=q6-1
endloop
loop
exitwhen q7==0
call QueueEgg(i, ZERG_MUTALISK, g)
set q7=q7-1
endloop
loop
exitwhen q8==0
call QueueEgg(i, ZERG_GUARDIAN, g)
set q8=q8-1
endloop
loop
exitwhen q9==0
call QueueEgg(i, ZERG_ULTRALISK, g)
set q9=q9-1
endloop
return g
endfunction
//---------------------------------------------------------------------------------------------
//============================================================
function InitTrig_CreateZergGroup takes nothing returns nothing
endfunction
// one ward per group
// ward created in function "ZergCreateGroup"
function ZergVisibilityWard_Loop takes nothing returns nothing
local unit ward=GetEnumUnit()
local group g=LoadGroupHandle(zergHash, GetHandleId(ward), KEY_GROUP)
local string coords=Group_GetCenter(g)
local integer x=GetStringX(coords)
local integer y=GetStringY(coords)
//update group center in hash
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_CENTER_X, x)
call SaveInteger(zergHash, GetHandleId(g), KEY_GROUP_CENTER_Y, y)
call SetUnitX(ward, x)
call SetUnitY(ward, y)
set ward=null
set g=null
endfunction
function Trig_ZVisWard_Conditions takes nothing returns boolean
call ForGroup(g_zergWardVisibilityGroup, function ZergVisibilityWard_Loop)
return false
endfunction
//===========================================================================
function InitTrig_ZVisWard takes nothing returns nothing
set gg_trg_ZVisWard = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_ZVisWard, 2 )
call TriggerAddCondition( gg_trg_ZVisWard, Condition( function Trig_ZVisWard_Conditions ) )
endfunction
function Trig_ChangeOwner_Conditions takes nothing returns boolean
return not IsUnitType(GetChangingUnit(), UNIT_TYPE_HERO)
endfunction
function Trig_ChangeOwner_Actions takes nothing returns nothing
local unit u = GetChangingUnit()
local player p=GetOwningPlayer(u)
local integer unitId=GetUnitTypeId(u)
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real face=GetUnitFacing(u)
set bj_lastCreatedUnit=CreateUnit(p, unitId, x, y, face)
call KillUnit(u)
set u=null
set p=null
endfunction
//===========================================================================
function InitTrig_ChangeOwner takes nothing returns nothing
set gg_trg_ChangeOwner = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_ChangeOwner, EVENT_PLAYER_UNIT_CHANGE_OWNER )
call TriggerAddCondition( gg_trg_ChangeOwner, Condition( function Trig_ChangeOwner_Conditions ) )
call TriggerAddAction( gg_trg_ChangeOwner, function Trig_ChangeOwner_Actions )
endfunction
/*
ZergGroup_CanBeLoaded(g)
Zerg_CanBeLoaded(u)
ZergGroup_IsLoaded(g)
ZergGroup_IsUnloaded(g)
ZergGroup_Load(g)
ZergGroup_UnloadInstant(g)
ZergGroup_UnloadFindXY(g)
ZergGroup_Unload(g)
*/
globals
real OVERLORD_DAMAGED_VALUE = 400.00 // if cargo overlord is damaged to 400hp it will trigger unload
trigger trg_zergOverlordUnload=CreateTrigger()
unit g_zergOverlordUnload=null
unit g_zergGroupTempHero=null // used in "ZergGroup_Load"
endglobals
// Overlord Cargo: 10 units
//--------------------------------------------------------------------------------------------------------
function ZergGroup_CanBeLoaded takes group g returns boolean
local integer groundUnits=ZergGroup_GetWalkersCount(g)
local integer cargoHold=Group_CountUnitType(g, ZERG_OVERLORD)*10
return (groundUnits>0) and (groundUnits <= cargoHold)
endfunction
//--------------------------------------------------------------------------------------------------------
function Zerg_CanBeLoaded takes unit u returns boolean
local integer id=GetUnitTypeId(u)
if id==ZERG_ZERGLING or id==ZERG_HYDRALISK or id==ZERG_HUNTER_KILLER then
return true
elseif id==ZERG_LURKER or id==ZERG_DEFILER or id==ZERG_ULTRALISK then
return true
elseif IsUnitType(u, UNIT_TYPE_HERO) then
return true
endif
return false
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_IsLoadedUnloaded takes group g, boolean loaded, boolean unloaded returns boolean
local unit FoG=null
local boolean b=true
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if loaded then
if Zerg_CanBeLoaded(FoG) and (not IsUnitLoaded(FoG)) then
set b=false
endif
elseif unloaded then
if GetUnitTypeId(FoG)==ZERG_OVERLORD and (cargoOccupiedSlots[GetUnitUserData(FoG)]>0) then
set b=false
endif
endif
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
return b
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_IsLoaded takes group g returns boolean
return ZergGroup_IsLoadedUnloaded(g, true, false)
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_IsUnloaded takes group g returns boolean
return ZergGroup_IsLoadedUnloaded(g, false, true)
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_OverlordsDamaged takes group g returns boolean
return LoadBoolean(zergHash, GetHandleId(g), KEY_OVERLORDS_DAMAGED)
endfunction
function Trig_OverlordsLife takes nothing returns nothing
local trigger t=GetTriggeringTrigger()
local integer trigger_id=GetHandleId(t)
local group g = LoadGroupHandle(zergHash, trigger_id, KEY_GROUP)
call SaveBoolean(zergHash, GetHandleId(g), KEY_OVERLORDS_DAMAGED, true)
call FlushChildHashtable(zergHash, trigger_id)// clean
set g=null
call DisableTrigger(t)
call DestroyTrigger(t)
set t=null
endfunction
//--------------------------------------------------------------------------------------------------------
//---------------------LOAD-----------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
function ZergGroup_Load takes group g returns nothing
local integer groundUnits=ZergGroup_GetWalkersCount(g)
local integer q=0 // number of Overlords needed
local unit array overlord
local unit FoG=null
local integer a=1
local integer x=0
local trigger t=CreateTrigger()
call SaveGroupHandle(zergHash, GetHandleId(t), KEY_GROUP, g) //connect trigger with group
call SaveBoolean(zergHash, GetHandleId(g), KEY_OVERLORDS_DAMAGED, false)
loop
if groundUnits>10 then
set q=q+1
set groundUnits=groundUnits-10
elseif groundUnits>0 then
set q=q+1
exitwhen true
endif
endloop
// q is number of Overlords needed
//set up overlords - start
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if GetUnitTypeId(FoG)==ZERG_OVERLORD then
set overlord[a]=FoG
call TriggerRegisterUnitStateEvent(t, FoG, UNIT_STATE_LIFE, LESS_THAN, OVERLORD_DAMAGED_VALUE) // 400hp or less will set a flag "overlordsDamaged"
set a=a+1
endif
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
call TriggerAddAction(t, function Trig_OverlordsLife)
//set up overlords - end
//load units start
set a=0
set x=1
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if Zerg_CanBeLoaded(FoG) then
call IssueTargetOrderById(FoG, ORDER_smart, overlord[x])
set a=a+1
if a==10 then
set overlord[x]=null//clean leak
set a=0
set x=x+1
endif
endif
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
//load units end
set t=null
endfunction
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
function Zerg_UnloadXYWalkable takes real x, real y returns boolean
//angle: radians: 0.00, 1.57 3.14 4.71 //+128 in 4 directions
local boolean b1=IsTerrainWalkable(x,y)
local boolean b2=IsTerrainWalkable(x+128.00*Cos(0.00), y+128.00*Sin(0.00))
local boolean b3=IsTerrainWalkable(x+128.00*Cos(1.57), y+128.00*Sin(1.57))
local boolean b4=IsTerrainWalkable(x+128.00*Cos(3.14), y+128.00*Sin(3.14))
local boolean b5=IsTerrainWalkable(x+128.00*Cos(4.71), y+128.00*Sin(4.71))
return b1 and b2 and b3 and b4 and b5
endfunction
//-------------------------------------------------------------------------------------------------
//-------- trigger action function -(UNLOAD)--------------------------------------------------
//-------------------------------------------------------------------------------------------------
function Trig_ZergOverlordUnload takes nothing returns nothing
local unit overlord=g_zergOverlordUnload
local real x=GetUnitX(overlord)
local real y=GetUnitY(overlord)
local real Tx=0.00
local real Ty=0.00
local real dist=256.00
local real angle=0.00
local integer step=1
local boolean pointFound=false
//angle 8 directions: radians: 0.00, 0.78, 1.57, 2.35, 3.14, 3.92, 4.71, 5.49
loop
set Tx=x+dist*Cos(angle)
set Ty=y+dist*Sin(angle)
if MapContainsXY(Tx, Ty) and Zerg_UnloadXYWalkable(Tx, Ty) then
set pointFound=true
exitwhen true
endif
set angle=angle+0.785
set step=step+1
if step>8 then
set dist=dist+256.00
set angle=0.00
set step=1
endif
exitwhen dist>3000.00 //to prevent infinite loop
endloop
if not pointFound then
call KillUnit(overlord)
endif
if pointFound then
loop
call IssuePointOrderById(overlord, ORDER_move, Tx, Ty)
call TriggerSleepAction(1.00)
exitwhen IsUnitInRangeXY(overlord, Tx, Ty, 64.00) or (not UnitAlive(overlord))
endloop
call IssuePointOrderById(overlord, ORDER_unloadall, Tx, Ty)
loop
exitwhen not UnitAlive(overlord)
exitwhen cargoOccupiedSlots[GetUnitUserData(overlord)]==0
call TriggerSleepAction(0.50)
endloop
endif
set overlord=null
endfunction
//-------------------------------------------------------------------------------------------------
//------------------UNLOAD---------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------
function ZergGroup_UnloadInstantFindXY takes group g, boolean instant, boolean findXY returns nothing
local unit FoG=null
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
if GetUnitTypeId(FoG)==ZERG_OVERLORD and (cargoOccupiedSlots[GetUnitUserData(FoG)]>0) then
if instant then
call IssuePointOrderById(FoG, ORDER_unloadall, GetUnitX(FoG), GetUnitY(FoG))
elseif findXY then
set g_zergOverlordUnload=FoG
call TriggerExecute(trg_zergOverlordUnload)
endif
endif
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_UnloadInstant takes group g returns nothing
call ZergGroup_UnloadInstantFindXY(g, true, false)
endfunction
//--------------------------------------------------------------------------------------------------------
function ZergGroup_UnloadFindXY takes group g returns nothing
call ZergGroup_UnloadInstantFindXY(g, false, true)
endfunction
//--------------------------------------------------------------------------------------------------------
// used directly in trigger "ZergAICargo"
function ZergGroup_Unload takes group g returns nothing
call ZergGroup_UnloadInstant(g) //try unload at current overlords position
call TriggerSleepAction(1.00)
if not ZergGroup_IsUnloaded(g) then
call ZergGroup_UnloadFindXY(g)
loop
exitwhen ZergGroup_IsUnloaded(g)
call TriggerSleepAction(1.00)
endloop
endif
endfunction
//===========================================================================
function InitTrig_OverlordCargo takes nothing returns nothing
call TriggerAddAction(trg_zergOverlordUnload, function Trig_ZergOverlordUnload)
endfunction
//-------------------------------------------------------------------------------------
// it is executed once only for each attack group (in ZergAI1)
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
function ZergGroupPickPathNo takes group g, unit target returns nothing
local integer group_id=GetHandleId(g)
local integer poolNo=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer pathNo=1
local string s
local integer index
if target==LIBRARY then
set pathNo=GetRandomInt(1, 2)
elseif target==CATHEDRAL then
set pathNo=GetRandomInt(3, 4)
endif
call SaveInteger(zergHash, group_id, KEY_GROUP_PATH_NO, pathNo)
call SaveInteger(zergHash, group_id, KEY_GROUP_POINT_NO, 1)
set s=I2S(poolNo)+I2S(pathNo)+"1"
set index=S2I(s)
call ZergGroup_SetDestinationXY(g, zergMeetingPointX[index], zergMeetingPointY[index])
endfunction
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
//returns "true" if next point exists
function ZergGroup_SetNextPointNo takes group g returns boolean
local integer group_id=GetHandleId(g)
local integer poolNo=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer pathNo=LoadInteger(zergHash, group_id, KEY_GROUP_PATH_NO)
local integer pointNo=LoadInteger(zergHash, group_id, KEY_GROUP_POINT_NO) + 1
local string s=I2S(poolNo)+I2S(pathNo)+I2S(pointNo)
local integer index=S2I(s)
if zergMeetingPointX[index] == null then
//call MsgDev("There's no next point for group"+I2S(group_id))
return false
else
call SaveInteger(zergHash, group_id, KEY_GROUP_POINT_NO, pointNo)
call ZergGroup_SetDestinationXY(g, zergMeetingPointX[index], zergMeetingPointY[index])
call MsgDev("Setting next meeting point for group "+I2S(group_id))
//call PingMinimap(zergMeetingPointX[index], zergMeetingPointY[index], 5.00)
endif
return true
endfunction
//--------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------
function ZergGroup_CargoSetDest takes group g, unit target returns nothing
if target==LIBRARY then
call ZergGroup_SetDestinationXY(g, 1270, 850)
elseif target==CATHEDRAL then
call ZergGroup_SetDestinationXY(g, -1000, -1500)
endif
endfunction
//=============================================================
function InitTrig_ZergAIDest takes nothing returns nothing
endfunction
globals
unit g_zergATT2 = null
endglobals
//------------------------------------------------------------------------------------------------------------------
//-----------------------------FIGHT (g_zergATT2)-------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZergGroup_AttackedEx takes group g, integer maxDist returns boolean
local string coords=Group_GetCenter(g)
local boolean hasHero = ZAttackGroup_HasHero(g)
local boolean canAttackAir = hasHero or ZergGroup_CanAttackAir(g)
local unit hero = ZAttackGroup_GetHero(g)
set g_zergATT2 = null
if hasHero and UnitAlive(hero) and CSUnit_Attacked(hero, 3.00) then
set g_zergATT2 = CSUnit_GetPrimaryAttacker(hero, GetStringX(coords), GetStringY(coords), maxDist, CS_FILTR_any)
elseif ZergGroup_Alive(g) and CSZGroup_Attacked(g, 4.00) then
if canAttackAir then
set g_zergATT2 = CSZGroup_GetAttacker(g, GetStringX(coords), GetStringY(coords), maxDist, g_filtrZEnemy)
else
set g_zergATT2 = CSZGroup_GetAttacker(g, GetStringX(coords), GetStringY(coords), maxDist, g_filtrZEnemyGround)
endif
endif
return (g_zergATT2 != null)
endfunction
//------------------------------------------------------------------------------------------------------------------
//----------------------------- CONSOLIDATE LOOP ------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZG_Consolidate_Loop takes group g returns nothing
local integer c=0
local string coords=Group_GetUnitCoordsClosestToXY(g, ZergGroup_GetDestinationX(g), ZergGroup_GetDestinationY(g))
call MsgDev("ATT::consolidate")
call ZergG_SetConsolidateXY(g, GetStringX(coords), GetStringY(coords)) //23.02.2019
call ZergGroup_SetState(g, GROUP_STATE_CONSOLIDATE)
loop
call TriggerSleepAction(1.00)
set c=c+1
if c>1 then
exitwhen ZergGroup_NotStretched(g)
exitwhen ZergGroup_AttackedEx(g, 1800) or (not ZergGroup_Alive(g))
exitwhen c>10 // max time to consolidate: 10sec
endif
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//-------------------------------------- ATTACK-MOVE LOOP --------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZG_AttackMove_Loop takes group g, boolean lookForNextPoint returns nothing
local integer c=0
call MsgDev("ATT::attack-move")
call ZergGroup_SetState(g, GROUP_STATE_ATTACK_MOVE)
loop
call TriggerSleepAction(1.00)
exitwhen ZergGroup_AttackedEx(g, 1800) or (not ZergGroup_Alive(g))
exitwhen ZergGroup_Stretched(g)
if lookForNextPoint then
if ZergGroup_InRangeOfDest(g) and ZergGroup_SetNextPointNo(g) then// new coords found
call TriggerSleepAction(0.50)
//force consolidate?
call ZG_Consolidate_Loop(g)
exitwhen true
endif
endif
if c==6 then
call ZG_Consolidate_Loop(g)
exitwhen true
endif
set c=c+1
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------------------------Fight Loop --------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZG_Fight_Loop takes group g, unit firstTarget returns nothing
local integer c=1
local string coords=Group_GetCenter(g)
local integer x=GetStringX(coords) //remember coords when we start the fight
local integer y=GetStringY(coords)
local unit target=firstTarget
call MsgDev("ATT::fight ("+GetUnitName(target)+")")
call ZergGroup_SetState(g, GROUP_STATE_FIGHT)
call ZergGroup_SetTarget(g, target)
loop
call TriggerSleepAction(1.00)
exitwhen not ZergGroup_Alive(g)
exitwhen not ZergGroup_AttackedEx(g, 1800)
exitwhen not Zerg_TargetValid(target, x, y, 2000)
exitwhen c>6
set c=c+1
endloop
call ZergGroup_ResetTarget(g)
set target=null
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------MAIN AI------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function Trig_ZergAI1_Actions takes nothing returns nothing
local group g=groupAI
local boolean b =g_lookForNextPointWhenMove
if g_zergWavePickPath then
call ZergGroupPickPathNo(g, g_waveTarget)
endif
loop
exitwhen not ZergGroup_Alive(g)
if ZergGroup_AttackedEx(g, 1800) then
call ZG_Fight_Loop(g, g_zergATT2)
elseif ZergGroup_Stretched(g) then
call ZG_Consolidate_Loop(g)
else
call ZG_AttackMove_Loop(g, b)
endif
call TriggerSleepAction(0.20)
endloop
call MsgDev("Main AttackAI ends ...")
set g=null
endfunction
//===========================================================================
function InitTrig_ZergAI1 takes nothing returns nothing
set gg_trg_ZergAI1 = CreateTrigger( )
call TriggerAddAction( gg_trg_ZergAI1, function Trig_ZergAI1_Actions )
endfunction
function ZGroup_AttackMoveXY takes group g, integer x, integer y returns nothing
local unit FoG=null
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//---
call IssuePointOrderById(FoG, ORDER_attack, x, y)
//---
call GroupAddUnit(g_swapGroupZG, FoG)
call GroupRemoveUnit(g, FoG)
endloop
loop //add units back [by Zibi]
set FoG=FirstOfGroup(g_swapGroupZG)
exitwhen FoG==null
call GroupAddUnit(g, FoG)
call GroupRemoveUnit(g_swapGroupZG, FoG)
endloop
//---
endfunction
function RunAttackTrg_Loop takes nothing returns nothing
call ZGAtt_ExecTrg(GetEnumUnit())
endfunction
//------------------------------------------------------------------------------------------------------------------
//----------------------------- Consolidate_CARGO_Loop------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZG_ConsolidateCargo_Loop takes group g returns nothing
local integer c=0
local string coords=Group_GetUnitCoordsClosestToXY(g, ZergGroup_GetDestinationX(g), ZergGroup_GetDestinationY(g))
call MsgDev("consolidate cargo")
call ZergG_SetConsolidateXY(g, GetStringX(coords), GetStringY(coords)) //23.02.2019
call ZGroup_AttackMoveXY(g, GetStringX(coords), GetStringY(coords))
loop
call TriggerSleepAction(1.00)
set c=c+1
exitwhen not ZergGroup_Alive(g)
exitwhen ZergGroup_OverlordsDamaged(g)
exitwhen not Group_Stretched(g, 450)
exitwhen c>10 // max time to consolidate: 10sec
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------------------------Move Loop CARGO -----------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZG_MoveCargo_Loop takes group g returns nothing
local integer Tx=ZergGroup_GetDestinationX(g)
local integer Ty=ZergGroup_GetDestinationY(g)
call MsgDev("cargo move")
call ZGroup_AttackMoveXY(g, Tx, Ty)
loop
call TriggerSleepAction(1.00)
exitwhen not ZergGroup_Alive(g)
exitwhen ZergGroup_OverlordsDamaged(g)
exitwhen Group_InRange(g, Tx, Ty, 500)
exitwhen Group_Stretched(g, 800)
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------MAIN AI------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function Trig_ZergAICargo_Actions takes nothing returns nothing
local group g=groupAI
local boolean b=g_lookForNextPointWhenMove
local integer Tx=0
local integer Ty=0
call ZergGroup_CargoSetDest(g, g_waveTarget) // global var
set Tx=ZergGroup_GetDestinationX(g)
set Ty=ZergGroup_GetDestinationY(g)
loop //Cargo
exitwhen (not ZergGroup_Alive(g)) or ZergGroup_OverlordsDamaged(g) or Group_InRange(g, Tx, Ty, 500)
if Group_Stretched(g, 800) then
call ZG_ConsolidateCargo_Loop(g)
else
call ZG_MoveCargo_Loop(g)
endif
call TriggerSleepAction(0.20)
endloop
if ZergGroup_Alive(g) then
call ZergGroup_Unload(g)
endif//end Cargo
if ZergGroup_Alive(g) then
//run individual triggers ZAtt
call ForGroup(g, function RunAttackTrg_Loop)
set groupAI=g
set g_lookForNextPointWhenMove=b
set g_zergWavePickPath=false
call TriggerExecute(gg_trg_ZergAI1)
endif
call MsgDev("MainAICargo ends ...")
set g=null
endfunction
//===========================================================================
function InitTrig_ZergAICargo takes nothing returns nothing
set gg_trg_ZergAICargo = CreateTrigger( )
call TriggerAddAction(gg_trg_ZergAICargo, function Trig_ZergAICargo_Actions)
endfunction
//HERO IS CONNECTED TO DEFENCE GROUP
globals
unit g_zergDTT2=null // ZergDefGroup_AttackedEx and ZergPool_AttackedEx
unit g_zergDTarget=null // ZGD_Fight_Loop
endglobals
//------------------------------------------------------------------------------------------------------------------
//maxDist for "attacked"=1200, for "non-attacked"=1400
function ZergDef_Attacked takes group g, integer i, integer x, integer y, integer maxDist returns boolean
set g_zergDTT2 = null
if UnitAlive(zergSpawningPool[i]) and CSUnit_Attacked(zergSpawningPool[i], 4.00) then
set g_zergDTT2 = CSUnit_GetPrimaryAttacker(zergSpawningPool[i], x, y, maxDist, CS_FILTR_any)
endif
if g_zergDTT2==null then
if CSZGroup_Attacked(g, 4.00) then
set g_zergDTT2 = CSZGroup_GetAttacker(g, x, y, maxDist, g_filtrZEnemy)//group atacker but around the pool !
endif
endif
return (g_zergDTT2 != null)
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------------------------Fight Loop --------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZGD_Fight_Loop takes group g, integer i, integer x, integer y returns nothing
local integer c=1
local unit target=g_zergDTT2
call MsgDev("Def:: Fight ("+GetUnitName(target)+"), ["+I2S(i)+"]")
call ZergGroup_SetTarget(g, target)
call ZergGroup_SetState(g, GROUP_STATE_DEF_FIGHT)
loop
call TriggerSleepAction(1.00)
exitwhen not ZergDef_Attacked(g, i, x, y, 1400)
exitwhen (not Zerg_TargetValid(target, x, y, 1400))
exitwhen c>6
set c=c+1
endloop
call ZergGroup_ResetTarget(g)
set target=null
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------------------------Move Back Loop --------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZGD_MoveBack_Loop takes group g, integer i, integer x, integer y returns nothing
local integer c=0
call MsgDev("Def:: back ["+I2S(i)+"]")
call ZergGroup_SetState(g, GROUP_STATE_DEF_BACK)
loop
call TriggerSleepAction(1.00)
set c=c+1
exitwhen c>10 or Group_InRange(g, x, y, 550)
if c>2 then //after ~3seconds
exitwhen not UnitAlive(zergSpawningPool[i])
exitwhen ZergDef_Attacked(g, i, x, y, 1200)
endif
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//--------------------------------------- Sleep Loop -------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function ZGD_SleepLoop takes group g, integer i, integer x, integer y returns nothing
local integer c=0
call ZergGroup_SetState(g, GROUP_STATE_DEF_SLEEP)
call MsgDev("Def:: sleep ["+I2S(i)+"]")
loop
exitwhen not UnitAlive(zergSpawningPool[i])
exitwhen ZergDef_Attacked(g, i, x, y, 1200)
exitwhen not Group_InRange(g, x, y, 600)
call TriggerSleepAction(1.00)
endloop
endfunction
//------------------------------------------------------------------------------------------------------------------
//---------------------MAIN AI------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------
function Trig_ZergAIdefend_Actions takes nothing returns nothing
local group g=groupAI
local integer i=ZergGroup_GetPoolNo(g)
local integer x=R2I(GetUnitX(zergSpawningPool[i]))
local integer y=R2I(GetUnitY(zergSpawningPool[i]))
local integer newPoolNo=1
call ZergGroup_SetDestinationXY(g, x, y)
loop
exitwhen (not UnitAlive(zergSpawningPool[i]))
if ZergDef_Attacked(g, i, x, y, 1200) then //globals "g_zergDTT2" set
call ZGD_Fight_Loop(g, i, x, y)
elseif not Group_InRange(g, x, y, 600) then
call ZGD_MoveBack_Loop(g, i, x, y)
else
call ZGD_SleepLoop(g, i, x, y)
endif
call TriggerSleepAction(0.50)
endloop
call MsgDev("MainAI defend ends for pool no "+I2S(i))
if g == g_zergDefendersGroup[i] and (not GAME_OVER) then // run this only for initial defenders group
call ZergPoolDies_ReconnectHeroes(i)
call ZergGroup_Reset(g) // in "ZGroupUpdate"
endif
set g=null
endfunction
//===========================================================================
function InitTrig_ZergAIdefend takes nothing returns nothing
set gg_trg_ZergAIdefend = CreateTrigger( )
call TriggerAddAction( gg_trg_ZergAIdefend, function Trig_ZergAIdefend_Actions )
endfunction
/*
[1] Zergling normal attack, targets: ground armor: small (0) 5dps 120hp
[2] Hydralisk pierce attack, targets: ground @ air armor: medium (1) 20dps 240hp
[3] Red-hydralisk pierce attack, targets: ground @ air armor: large (2) 30dps 350hp
[4] Lurker magic attack, targets: ground armor: large (1) 35dps 400hp
[5] Defiler magic attack, targets: ground @ air armor: medium (1) 17dps 350hp
[6] Ultralisk normal attack, targets: ground armor: large (6) 70dps 1000hp
[7] Mutalisk normal attack, targets: ground @ air armor: small (1) 23dps 300hp
[8] Guardian siege attack, targets: ground armor: medium (3) 66dps 900hp
[9] Overlord no-attack, transporting unit armor: small (1) 700hp
*/
function Trig_ZergAtt_Conditions takes nothing returns boolean
local unit attacker=GetAttacker()
local integer t=GetUnitTypeId(attacker)
local integer id=GetUnitUserData(attacker)
local boolean proceed=false
if GetOwningPlayer(attacker)==PLAYER_ZERG and g_zergTarget[id] != null and UnitAlive(g_zergTarget[id]) and GetTriggerUnit() != g_zergTarget[id] then
if t==ZERG_DEFILER and (not IsMagicImmune(g_zergTarget[id])) then
//defiler: magic attack, targets: ground @ air
set proceed=true
//elseif (t==ZERG_ZERGLING or t==ZERG_ULTRALISK or t==ZERG_GUARDIAN) and (not IsUnitType(g_zergTarget[id], UNIT_TYPE_FLYING)) then
elseif (t==ZERG_ZERGLING or t==ZERG_ULTRALISK) and (not IsUnitType(g_zergTarget[id], UNIT_TYPE_FLYING)) then
set proceed=true
//zergling: normal attack, targets: ground
//ultralisk: normal attack, targets: ground
//Guardian, siege attack, targets: ground
elseif t==ZERG_HYDRALISK or t==ZERG_RED_HYDRALISK or t==ZERG_MUTALISK then
set proceed=true
//hydralisk, pierce attack, targets: ground @ air
//red-hydralisk, pierce attack, targets: ground @ air
//Mutalisk, normal attack, targets: ground @ air
endif
endif
//Lurker: magic attack, targets: ground
// REDIRECT FOR LURKER IS BUGGED- he sometimes deals dmg from normal attacks, do nothing.
if proceed then
//call MsgDev("Redirecting attack "+GetUnitName(attacker)+" --> "+GetUnitName(g_zergTarget[id]))
call IssueTargetOrderById(attacker, ORDER_attack, g_zergTarget[id])
endif
/*
2 x magic
3 x normal
1 x siege
2 x pierce
*/
set attacker=null
return false
endfunction
//==================================================================
function InitTrig_ZergAttacking takes nothing returns nothing
set gg_trg_ZergAttacking = CreateTrigger( )
call TriggerRegisterPlayerUnitEvent(gg_trg_ZergAttacking, Player(0), EVENT_PLAYER_UNIT_ATTACKED, null)
call TriggerRegisterPlayerUnitEvent(gg_trg_ZergAttacking, Player(1), EVENT_PLAYER_UNIT_ATTACKED, null)
call TriggerRegisterPlayerUnitEvent(gg_trg_ZergAttacking, Player(2), EVENT_PLAYER_UNIT_ATTACKED, null)
call TriggerRegisterPlayerUnitEvent(gg_trg_ZergAttacking, Player(3), EVENT_PLAYER_UNIT_ATTACKED, null)
call TriggerAddCondition( gg_trg_ZergAttacking, Condition( function Trig_ZergAtt_Conditions ) )
endfunction
globals
constant integer ABI_DEFILER_PLAGUE='A00C'//"rain of fire" based rainoffire
constant integer ABI_DEFILER_CLOUD='A00D'//"channel" based order: ward
timer g_timerZergCloud=CreateTimer()
group g_groupZergCloudUnits=CreateGroup()
constant integer BUFF_ZERG_PLAGUE='B000'
constant integer DUMMY_ZERG_CLOUD='n004'
constant integer BUFF_ZERG_CLOUD='B001'
constant integer ABI_ZERG_CLOUD_EVASION='A005'
endglobals
//--------------------------------------------------------------------------------------------
//--------------- CLOUD -------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
function Trig_DefilerCloud_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_DEFILER_CLOUD
endfunction
//--------------------------------------------------------------------------------------------
function ZergCloudCheckGroup_Loop takes nothing returns nothing
local unit u=GetEnumUnit()
if GetUnitAbilityLevel(u, BUFF_ZERG_CLOUD)>0 then// buff preset
if GetUnitAbilityLevel(u, ABI_ZERG_CLOUD_EVASION)==0 then
call UnitAddAbility(u, ABI_ZERG_CLOUD_EVASION)
endif
else// no buff
if GetUnitAbilityLevel(u, ABI_ZERG_CLOUD_EVASION)>0 then
call UnitRemoveAbility(u, ABI_ZERG_CLOUD_EVASION)
endif
endif
set u=null
endfunction
//--------------------------------------------------------------------------------------------
function ZergCloudCheckGroup takes nothing returns nothing
call ForGroup(g_groupZergCloudUnits, function ZergCloudCheckGroup_Loop)
endfunction
//--------------------------------------------------------------------------------------------
function ZergCloudGroup_RemoveEvasion_Loop takes nothing returns nothing
call UnitRemoveAbility(GetEnumUnit(), BUFF_ZERG_CLOUD)
call UnitRemoveAbility(GetEnumUnit(), ABI_ZERG_CLOUD_EVASION)
endfunction
//--------------------------------------------------------------------------------------------
function ZergCloud_UnitInRange takes nothing returns nothing
local unit u=GetFilterUnit()
if UnitAlive(u) and (not IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (not IsUnitType(u, UNIT_TYPE_FLYING)) then
//call MsgDev("Cloud, enters: " +GetUnitName(u))
call GroupAddUnit(g_groupZergCloudUnits, u)
endif
set u=null
endfunction
//--------------------------------------------------------------------------------------------
function Trig_DefilerCloud_Actions takes nothing returns nothing
local boolexpr filtr = Filter(function ZergCloud_UnitInRange)
local trigger t=CreateTrigger()
local unit cloud=CreateUnit(GetOwningPlayer(GetTriggerUnit()), DUMMY_ZERG_CLOUD, GetSpellTargetX(), GetSpellTargetY(), 0.00)
call UnitApplyTimedLife(cloud, 'BTLF', 15.00)
call TriggerRegisterUnitInRange(t, cloud, 300.00, filtr)
call TimerStart(g_timerZergCloud, 1.00, true, function ZergCloudCheckGroup)
loop
exitwhen not UnitAlive(cloud)
call TriggerSleepAction(2.00)
endloop
if GetUnitCount(DUMMY_ZERG_CLOUD)==0 then//globaly for all players check
call ForGroup(g_groupZergCloudUnits, function ZergCloudGroup_RemoveEvasion_Loop)
call GroupClear(g_groupZergCloudUnits)
call PauseTimer(g_timerZergCloud)
endif
set filtr=null
call DestroyTrigger(t)
set t=null
set cloud=null
endfunction
//--------------------------------------------------------------------------------------------
//---------------PLAGUE--------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
function Trig_DefilerPlague_Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABI_DEFILER_PLAGUE
endfunction
//--------------------------------------------------------------------------------------------
function Trig_DefilerPlague_Actions takes nothing returns nothing
local real x=GetSpellTargetX()
local real y=GetSpellTargetY()
call AddTimedEffect(x, y, 1.50, "war3mapImported\\BloodCloud_3.mdx")
call AddTimedEffect(x, y, 1.50, "war3mapImported\\unholyStrikeX2b2.mdx")
endfunction
//--------------------------------------------------------------------------------------------
//===========================================================================
function InitTrig_DefilerSpells takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function Trig_DefilerCloud_Conditions ) )
call TriggerAddAction( t, function Trig_DefilerCloud_Actions )
set t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition(t, Condition( function Trig_DefilerPlague_Conditions ) )
call TriggerAddAction(t, function Trig_DefilerPlague_Actions )
set t=null
endfunction
//------------------------------------------------------------------------------------
function WaitForGroupStateChanged takes unit u, integer group_id, integer currentState returns nothing
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != currentState
exitwhen not UnitAlive(u)
endloop
endfunction
//------------------------------------------------------------------------------------
function WaitForUnburrow takes unit u returns nothing
loop
exitwhen IssueImmediateOrderById(u, ORDER_unbearform)
exitwhen not UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call TriggerSleepAction(1.10)
endfunction
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
function Trig_LurkerRedirectAttack takes nothing returns boolean
if GetUnitTypeId(GetAttacker()) == ZERG_LURKER then
if not g_lurkerBlockAttack[GetUnitUserData(GetAttacker())] then
call IssueImmediateOrderById(GetAttacker(), ORDER_bearform) //burrow
endif
elseif GetUnitTypeId(GetAttacker()) == ZERG_BURROW_LURKER then
call IssuePointOrderById(GetAttacker(), ORDER_carrionswarm, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
endif
return false
endfunction
//===========================================================================
function InitTrig_Behaviour takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(t, Condition( function Trig_LurkerRedirectAttack))
endfunction
//FOR DEFENDERS GROUP
//for all units except Lurker, Defiler and Overlord
function Trig_ZDef1_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
local integer i=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local real x=GetUnitX(zergSpawningPool[i])
local real y=GetUnitY(zergSpawningPool[i])
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_SLEEP)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
call IssuePointOrderById(u, ORDER_move, x, y)
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_BACK)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZDef1 takes nothing returns nothing
set gg_trg_ZDef1 = CreateTrigger( )
call TriggerAddAction( gg_trg_ZDef1, function Trig_ZDef1_Actions )
endfunction
//FOR DEFENDERS GROUP
//for Overlord
function Trig_ZDef2_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_SLEEP)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK or ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
loop
call TriggerSleepAction(2.00)
exitwhen ZergG_GetState(group_id) == GROUP_STATE_DEF_SLEEP
exitwhen not UnitAlive(u)
call IssuePointOrderById(u, ORDER_move, ZergG_GetCenterX(group_id), ZergG_GetCenterY(group_id))
endloop
endif
call TriggerSleepAction(1.00)
endloop
set u=null
endfunction
//===========================================================================
function InitTrig_ZDefO takes nothing returns nothing
set gg_trg_ZDefO = CreateTrigger( )
call TriggerAddAction( gg_trg_ZDefO, function Trig_ZDef2_Actions )
endfunction
//FOR DEFENDERS GROUP
//for Defiler
//--------------------------------------------------------------------------------------------------
// Cloud : Created cloud that gives nearby ground units 50% evasion. 300aoe, 15sec. Cast range 800
// Plague : 10dmg per second, 10sec, 300aoe. Cast range 800
//--------------------------------------------------------------------------------------------------
globals
unit g_targetForCloud=null
unit g_targetForPlague=null
endglobals
//--------------------------CLOUD------------------------------------------------------------------------
function Zerg_GetTargetForCloudEx takes real x, real y, integer unitId, boolean hero returns boolean
local unit FoG=null
set g_targetForCloud=null
//---
call GroupEnumUnitsInRange(ug, x, y, 1500.00, g_filtrZergUnits)
loop //filtr: alive, zerg unit
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
//---
if GetUnitAbilityLevel(FoG, BUFF_ZERG_CLOUD)==0 then
if hero and IsUnitType(FoG, UNIT_TYPE_HERO) then
set g_targetForCloud=FoG
exitwhen true
elseif (not hero) and GetUnitTypeId(FoG)==unitId then
set g_targetForCloud=FoG
exitwhen true
endif
endif
//---
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
//---
set FoG=null
return (g_targetForCloud != null)
endfunction
//--------------------------------------------------------------------------------------------------
// priority for hero-> then units, target should not have buff "cloud"
//--------------------------------------------------------------------------------------------------
function Zerg_GetTargetForCloud takes unit defiler returns unit
local real x=GetUnitX(defiler)
local real y=GetUnitY(defiler)
set g_targetForCloud=null
if Zerg_GetTargetForCloudEx(x, y, 0, true) then//hero
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_BURROW_LURKER, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_ULTRALISK, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_HUNTER_KILLER, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_HYDRALISK, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_DEFILER, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_ZERGLING, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_LURKER, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_BURROW_RED_HYDRALISK, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_BURROW_HYDRALISK, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_BURROW_DEFILER, false) then
return g_targetForCloud
elseif Zerg_GetTargetForCloudEx(x, y, ZERG_BURROW_ZERGLING, false) then
return g_targetForCloud
endif
return g_targetForCloud
endfunction
//-----------------------------------------------------------------------------------------------
function ZDefiler_OrderCloud takes unit defiler, real x, real y returns nothing
call IssuePointOrderById(defiler, ORDER_ward, x, y)
endfunction
//-----------------------------------------------------------------------------------------------
function ZergDefiler_CloudReady takes unit defiler returns boolean
return UnitSpellReady(defiler, ABI_DEFILER_CLOUD) and (Zerg_GetTargetForCloud(defiler) != null) // "g_targetForCloud" global set
endfunction
//-----------------------------------------------------------------------------------------------
function ZergDefiler_Cloud takes unit defiler returns nothing
local integer c=0
local unit target=g_targetForCloud
call IssueTargetOrderById(defiler, ORDER_move, target)
loop
set c=c+1
exitwhen (not UnitAlive(defiler)) or c>15 //3sec time
if UnitAlive(target) and IsUnitInRange(defiler, target, 750.00) then
call ZDefiler_OrderCloud(defiler, GetUnitX(target), GetUnitY(target))
call TriggerSleepAction(1.00)
exitwhen true
endif
call TriggerSleepAction(0.20)
endloop
set target=null
endfunction
//----------------------------------------------------------------------------------------------------------
//-----------------PLAGUE---------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
function Zerg_GetTargetForPlagueEx takes real x, real y, boolean hero returns boolean
local unit FoG=null
set g_targetForPlague=null
//---
call GroupEnumUnitsInRange(ug, x, y, 1500.00, g_filtrZEnemyNotImmune)
loop
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
//---
if GetUnitAbilityLevel(FoG, BUFF_ZERG_PLAGUE)==0 then
if hero and IsUnitType(FoG, UNIT_TYPE_HERO) then
set g_targetForPlague=FoG
exitwhen true
else
set g_targetForPlague=FoG
exitwhen true
endif
endif
//---
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
//---
set FoG=null
return (g_targetForPlague != null)
endfunction
//--------------------------------------------------------------------------------------------------
// priority for hero-> then units, target should not have buff "plague"
//--------------------------------------------------------------------------------------------------
function Zerg_GetTargetForPlague takes unit defiler returns unit
local real x=GetUnitX(defiler)
local real y=GetUnitY(defiler)
set g_targetForPlague=null
if Zerg_GetTargetForPlagueEx(x, y, true) then//hero
return g_targetForPlague
elseif Zerg_GetTargetForPlagueEx(x, y, false) then
return g_targetForPlague
endif
return g_targetForPlague
endfunction
//----------------------------------------------------------------------------------------------------------
function ZDefiler_OrderPlague takes unit defiler, real x, real y returns nothing
call IssuePointOrderById(defiler, ORDER_rainoffire, x, y)
endfunction
//-----------------------------------------------------------------------------------------------
function ZergDefiler_PlagueReady takes unit defiler returns boolean
return UnitSpellReady(defiler, ABI_DEFILER_PLAGUE) and (Zerg_GetTargetForPlague(defiler) != null) // "g_targetForPlague" global set
endfunction
//-----------------------------------------------------------------------------------------------
function ZergDefiler_Plague takes unit defiler returns nothing
local integer c=0
local unit target=g_targetForPlague
call IssueTargetOrderById(defiler, ORDER_move, target)
loop
set c=c+1
exitwhen (not UnitAlive(defiler)) or c>15 //3sec time
exitwhen IsMagicImmune(target)
if IsUnitInRange(defiler, target, 750.00) then
call ZDefiler_OrderPlague(defiler, GetUnitX(target), GetUnitY(target))
call TriggerSleepAction(1.00)
exitwhen true
endif
call TriggerSleepAction(0.20)
endloop
set target=null
endfunction
//----------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------
function Trig_ZDef3_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
local integer i=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local real x=GetUnitX(zergSpawningPool[i])
local real y=GetUnitY(zergSpawningPool[i])
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_SLEEP)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
call IssuePointOrderById(u, ORDER_move, x, y)
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_BACK)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
endif
//spells
if ZergDefiler_PlagueReady(u) then
call ZergDefiler_Plague(u)
endif
if ZergDefiler_CloudReady(u) then
call ZergDefiler_Cloud(u)
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZDefD takes nothing returns nothing
set gg_trg_ZDefD = CreateTrigger( )
call TriggerAddAction( gg_trg_ZDefD, function Trig_ZDef3_Actions )
endfunction
//FOR DEFENDERS GROUP
//for Lurker
//-----------------------------------------------------------------------------------------------------
function Trig_ZDef4_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
local integer i=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local real x=GetUnitX(zergSpawningPool[i])
local real y=GetUnitY(zergSpawningPool[i])
local integer id=GetUnitUserData(u)
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
set g_lurkerBlockAttack[id]=false
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_SLEEP)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
set g_lurkerBlockAttack[id]=true
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_move, x, y)
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_DEF_BACK)
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set g_lurkerBlockAttack[id]=false
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
endif
if ZergIsBurrowed(u) then
set target=GetClosestUnit(GetUnitX(u), GetUnitY(u), 800, g_filtrZEnemyGroundNotImmune)
if target==null then
call WaitForUnburrow(u)
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(0.20)
endif
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZDefL takes nothing returns nothing
set gg_trg_ZDefL = CreateTrigger( )
call TriggerAddAction( gg_trg_ZDefL, function Trig_ZDef4_Actions )
endfunction
// for ATTACKING Group
// for Zergling, Hydralisk, Red-Hydralisk
//----------------------------------------------------------------------------------------------------------
// it should listen for group orders - higher priority
// and control fight-behaviour (low priority)
// runs upon zergling creation (attack-group only) until unit dies
//----------------------------------------------------------------------------------------------------------
function Trig_ZAtt1_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(0.50)
endif
if ZergIsBurrowed(u) and (GetUnitPercentLife(u)>0.25 or ZergG_EnemyCanSeeInvisible(group_id)) then
call WaitForUnburrow(u)
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
elseif CSUnit_Attacked(u, 4.00) and GetUnitPercentLife(u)<0.20 and (not ZergG_EnemyCanSeeInvisible(group_id)) then
call IssueImmediateOrderById(u, ORDER_bearform) //burrow
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
//from group, orders are:
// move (consolidate) , attack-move(walk to destination) , attack-target(fight)
//new group's states:
//x,y x,y target
// GROUP_STATE_CREATING
// GROUP_STATE_CONSOLIDATE GROUP_STATE_ATTACK_MOVE GROUP_STATE_FIGHT
// ZergG_GetTarget(group_id)
// ZergG_GetDestinationX(group_id)
// ZergG_GetConsolidateX(group_id)//upon state: consolidate
// ZergG_GetState
// return LoadInteger(zergHash, GetHandleId(g), KEY_GROUP_CENTER_X)
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttZHR takes nothing returns nothing
set gg_trg_ZAttZHR = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttZHR, function Trig_ZAtt1_Actions )
endfunction
// for ATTACKING Group
// for Overlord
function Trig_ZAtt2_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
loop
exitwhen not UnitAlive(u)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_CREATING
call IssuePointOrderById(u, ORDER_move, ZergG_GetCenterX(group_id), ZergG_GetCenterY(group_id))
call TriggerSleepAction(2.00)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
loop
exitwhen not UnitAlive(u)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
call IssuePointOrderById(u, ORDER_move, ZergG_GetCenterX(group_id), ZergG_GetCenterY(group_id))
call TriggerSleepAction(2.00)
endloop
endif
call TriggerSleepAction(1.00)
endloop
set u=null
endfunction
//===========================================================================
function InitTrig_ZAttO takes nothing returns nothing
set gg_trg_ZAttO = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttO, function Trig_ZAtt2_Actions )
endfunction
// for ATTACKING Group
// for Ultralisk
function Trig_ZAtt3_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(1.00)
endif
if GetUnitPercentLife(u)>0.30 and UnitSpellReady(u, 'Atau') then
set target = GetClosestUnit(GetUnitX(u), GetUnitY(u), 450, g_filtrZEnemyGround)
if target != null then
call IssueImmediateOrderById(u, ORDER_taunt)
call TriggerSleepAction(1.00)
endif
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttU takes nothing returns nothing
set gg_trg_ZAttU = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttU, function Trig_ZAtt3_Actions )
endfunction
// for ATTACKING Group
// for Guardian
globals
unit g_guardianTA1=null
endglobals
// returns "true" if unit <u> is alive, attacked and there is attacker in given distance
function Guardian_Attacked takes unit u, real time, integer distance returns boolean
set g_guardianTA1=null
if CSUnit_Attacked(u, time) then
set g_guardianTA1=CSUnit_GetPrimaryAttacker(u, R2I(GetUnitX(u)), R2I(GetUnitY(u)), distance, CS_FILTR_onlyGround)
return true
endif
return false
endfunction
//-------------------------------------------------------------------------------------------------------
function GuardianAttackStructure_Unprovoked_Loop takes unit guardian, integer group_id, unit targetStructure returns nothing
call IssueTargetOrderById(guardian, ORDER_attack, targetStructure)
call TriggerSleepAction(0.50)
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen (not UnitAlive(guardian)) or (not UnitAlive(targetStructure))
exitwhen Guardian_Attacked(guardian, 4.00, 1000)
call TriggerSleepAction(0.50)
endloop
endfunction
//-------------------------------------------------------------------------------------------------------------------------
//attack for 7,5sec
function GuardianAttackUnit_Loop takes unit guardian, integer group_id, unit targetUnit returns nothing
local unit t=targetUnit
local integer x=R2I(GetUnitX(guardian))
local integer y=R2I(GetUnitY(guardian))
local integer count=0
call IssueTargetOrderById(guardian, ORDER_attack, t)
call TriggerSleepAction(0.50)
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen (not UnitAlive(guardian)) or (not UnitAlive(t)) or IsFlying(t)
exitwhen (not Zerg_TargetValid(t, x, y, 1500))//if target is dead / invisible / out of range / invulnerable
exitwhen count>15
set count=count+1
call TriggerSleepAction(0.50)
endloop
set t=null
endfunction
//-------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------------
function Trig_ZAtt4_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
if Guardian_Attacked(u, 4.00, 1000) then //globals variable set "g_guardianTA1"
call GuardianAttackUnit_Loop(u, group_id, g_guardianTA1)
else// no ground attacker
set target = GetClosestUnit(GetUnitX(u), GetUnitY(u), 1400, g_filtrZEnemyStructure)
if target != null then
call GuardianAttackStructure_Unprovoked_Loop(u, group_id, target)
else //no structure found
set target=ZergG_GetTarget(group_id)
if target != null then
call IssuePointOrderById(u, ORDER_attack, GetUnitX(target), GetUnitY(target))
else
call IssuePointOrderById(u, ORDER_attack, ZergG_GetCenterX(group_id), ZergG_GetCenterY(group_id))
endif
call TriggerSleepAction(0.50)
set c=0
loop
exitwhen (not UnitAlive(u))
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen Guardian_Attacked(u, 4.00, 1000)
exitwhen c>4
call TriggerSleepAction(1.00)
set c=c+1
endloop
endif
endif
endif
call TriggerSleepAction(1.00)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttG takes nothing returns nothing
set gg_trg_ZAttG = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttG, function Trig_ZAtt4_Actions )
endfunction
// for ATTACKING Group
// for Mutalisk
function Trig_ZAtt5_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttM takes nothing returns nothing
set gg_trg_ZAttM = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttM, function Trig_ZAtt5_Actions )
endfunction
// for ATTACKING Group
// for Defiler
function Trig_ZAttD_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call IssueImmediateOrderById(u, ORDER_bearform) //burrow
call TriggerSleepAction(1.10)
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(1.00)
endif
if ZergDefiler_CloudReady(u) or ZergDefiler_PlagueReady(u)then
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
//spells:
if ZergDefiler_PlagueReady(u) then
call ZergDefiler_Plague(u)
endif
if ZergDefiler_CloudReady(u) then
call ZergDefiler_Cloud(u)
endif
endif
if CSUnit_Attacked(u, 4.00) and GetUnitPercentLife(u)<0.50 and (not ZergG_EnemyCanSeeInvisible(group_id)) then
call IssueImmediateOrderById(u, ORDER_bearform) //burrow
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttD takes nothing returns nothing
set gg_trg_ZAttD = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttD, function Trig_ZAttD_Actions )
endfunction
globals
boolean array g_lurkerBlockAttack //[id]
endglobals
// for ATTACKING Group
// for Lurker
function Trig_ZAttL_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer c=0
local unit target=null
local integer id=GetUnitUserData(u)
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call IssueImmediateOrderById(u, ORDER_bearform) //burrow
call TriggerSleepAction(1.10)
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
set g_lurkerBlockAttack[id]=true
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_move, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
set g_lurkerBlockAttack[id]=false
if ZergIsBurrowed(u) then
call WaitForUnburrow(u)
endif
call IssuePointOrderById(u, ORDER_attack, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set g_lurkerBlockAttack[id]=false
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
if (not IsMagicImmune(target)) and IsGround(target) then
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(0.20)
endif
endif
if ZergIsBurrowed(u) then
set target=GetClosestUnit(GetUnitX(u), GetUnitY(u), 800, g_filtrZEnemyGroundNotImmune)
call MsgDev("L:target: "+GetUnitName(target))
if target==null then
call WaitForUnburrow(u)
set target=ZergG_GetTarget(group_id)
if (not IsMagicImmune(target)) and IsGround(target) then
call IssueTargetOrderById(u, ORDER_attack, target)
call TriggerSleepAction(0.20)
endif
endif
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_ZAttL takes nothing returns nothing
set gg_trg_ZAttL = CreateTrigger( )
call TriggerAddAction( gg_trg_ZAttL, function Trig_ZAttL_Actions )
endfunction
globals
integer array g_zFlag // [unit id]
constant integer NEUTRAL=0
constant integer INTERRUPT=1
constant integer TARGET_CHANGED=2
boolean array g_zergBehaviourTrgRunning //[unit user data]
unit g_zergBehaviourUnit=null
group g_zergBehaviourGroup=CreateGroup()
endglobals
//1.checks interrupt flag
//2.checks if target flyes: order attack-target or attack-point
//3.uses 0.20sec sleep at the end
function Zerg_AttackTarget takes unit zerg returns nothing
local integer id=GetUnitUserData(zerg)
local boolean zergCanAttackTarget = IsGround(g_zergTarget[id]) or (IsFlying(g_zergTarget[id]) and ZergUnit_CanAttackAir(zerg))
if not (g_zFlag[id]==INTERRUPT) then
if zergCanAttackTarget then
call IssueTargetOrderById(zerg, ORDER_attack, g_zergTarget[id])
else
call IssuePointOrderById(zerg, ORDER_attack, GetUnitX(g_zergTarget[id]), GetUnitY(g_zergTarget[id]))
endif
call TriggerSleepAction(0.20)
endif
endfunction
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// ZergBurrow @ ZergUnburrow - uses trigger sleep 1.10 at after order
function ZergBurrow takes unit u returns boolean
local boolean b=IssueImmediateOrderById(u, ORDER_bearform)
call TriggerSleepAction(1.10)
return b
endfunction
function ZergUnburrow takes unit u returns nothing
call IssueImmediateOrderById(u, ORDER_unbearform)
call TriggerSleepAction(1.10)
endfunction
//==============================================
function Trig_OverlordPosition_Actions takes nothing returns nothing
local unit u=g_zergBehaviourUnit
local group g=g_zergBehaviourGroup
local integer id=GetUnitUserData(u)
local integer c=0
set g_zergBehaviourTrgRunning[id]=true
loop
exitwhen g_zFlag[id]==INTERRUPT or (not UnitAlive(u))
if c==15 then // every 3 seconds
set c=0
call IssuePointOrderById(u, ORDER_move, ZergGroup_GetCenterX(g), ZergGroup_GetCenterY(g))
endif
set c=c+1
call TriggerSleepAction(0.20)
endloop
set g_zergBehaviourTrgRunning[id]=false
set g_zFlag[id]=NEUTRAL
set u=null
set g=null
endfunction
//===========================================================================
function InitTrig_Overlord takes nothing returns nothing
set gg_trg_Overlord = CreateTrigger( )
// call TriggerAddAction( gg_trg_Overlord, function Trig_OverlordPosition_Actions )
endfunction
//----------------------------------------------------------------------------------------------
// ZERG HERO ORDERS
//----------------------------------------------------------------------------------------------
function ZergHeroAttack takes unit hero, unit target returns nothing
if UnitChanneling(hero) then
loop
exitwhen (not UnitAlive(hero)) or (not UnitChanneling(hero))
call TriggerSleepAction(0.20)
endloop
endif
call IssueTargetOrderById(hero, ORDER_attack, target)
call TriggerSleepAction(0.20)
endfunction
//----------------------------------------------------------------------------------------------
function ZergHeroAttackMove takes unit hero, real x, real y returns nothing
if UnitChanneling(hero) then
loop
exitwhen (not UnitAlive(hero)) or (not UnitChanneling(hero))
call TriggerSleepAction(0.20)
endloop
endif
call IssuePointOrderById(hero, ORDER_attack, x, y)
call TriggerSleepAction(0.20)
endfunction
//----------------------------------------------------------------------------------------------
function ZergHeroMove takes unit hero, real x, real y returns nothing
if UnitChanneling(hero) then
loop
exitwhen (not UnitAlive(hero)) or (not UnitChanneling(hero))
call TriggerSleepAction(0.20)
endloop
endif
call IssuePointOrderById(hero, ORDER_move, x, y)
call TriggerSleepAction(0.20)
endfunction
function Trig_HeroOrders_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_HeroOrders takes nothing returns nothing
set gg_trg_HeroOrders = CreateTrigger( )
call TriggerAddAction( gg_trg_HeroOrders, function Trig_HeroOrders_Actions )
endfunction
// ROAR: Gives friendly nearby units % bonus to damage for 10sec
// STRIKE: Hero hits enemy with a paw, deals damage, mini stuns and knockback target.
// CLAP: Slams the ground, dealing 350dmg in 350aoe (slowing their movement and attack rate)
//---------------------------------------------------------------------------------
// CAST SPELLS
//---------------------------------------------------------------------------------
function ZergBeast_Roar takes unit target returns boolean
if GetUnitAbilityLevel(ZERG_HERO_BEAST, BUFF_BEAST_ROAR)==0 and UnitSpellReady(ZERG_HERO_BEAST, ABI_BEAST_ROAR) then
call IssueImmediateOrderById(ZERG_HERO_BEAST, ORDER_roar)
call ZergHeroAttack(ZERG_HERO_BEAST, target)
return true
endif
return false
endfunction
//----------------------------------------------------------------------------------
function ZergBeast_Strike takes unit target returns boolean
local unit u=null
local real x=0.00
local real y=0.00
local integer count=0
//try to omit main target if possible
if UnitSpellReady(ZERG_HERO_BEAST, ABI_BEAST_STRIKE) then
set x=GetUnitX(ZERG_HERO_BEAST)
set y=GetUnitY(ZERG_HERO_BEAST)
set u=GetClosestUnitInRangeEx(x, y, 350, g_filtrZEnemyGroundOrganicNotImmune, target)
if u==null and (not IsMagicImmune(target)) then
set u=target
endif
if u != null then
call IssueTargetOrderById(ZERG_HERO_BEAST, ORDER_thunderbolt, u)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_BEAST) != ORDER_thunderbolt
exitwhen count>15 //~3seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_BEAST, target)
set u=null
return true
endif
endif
set u=null
return false
endfunction
//----------------------------------------------------------------------------------
function ZergBeast_Clap takes unit target returns boolean
local real x=GetUnitX(ZERG_HERO_BEAST)
local real y=GetUnitY(ZERG_HERO_BEAST)
if UnitSpellReady(ZERG_HERO_BEAST, ABI_BEAST_CLAP) then
if (CountUnitsInRange(x, y, 330, g_filtrZEnemyGroundOrganicNotImmuneHero) > 0) then
call IssueImmediateOrderById(ZERG_HERO_BEAST, ORDER_thunderclap)
call ZergHeroAttack(ZERG_HERO_BEAST, target)
return true
endif
endif
return false
endfunction
//----------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
// zerg heroes have aura learned at level 1
//---------------------------------------------------------------------------------
function ZergBeast_LearnSkill takes nothing returns nothing
local integer randomizer=GetRandomInt(1,120)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_CLAP)// ulti
if randomizer>=1 and randomizer<=20 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
elseif randomizer>20 and randomizer<=40 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
elseif randomizer>40 and randomizer<=60 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
elseif randomizer>60 and randomizer<=80 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
elseif randomizer>80 and randomizer<=100 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
elseif randomizer>100 and randomizer<=120 then
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_STRIKE)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ROAR)
call SelectHeroSkill(ZERG_HERO_BEAST, ABI_BEAST_ENDURANCE_AURA)
endif
if GetHeroSkillPoints(ZERG_HERO_BEAST)>0 then
call ZergBeast_LearnSkill() //re-run this
endif
endfunction
//===============================================
globals
constant integer ABI_BEAST_ROAR = 'A00K'// "roar"
constant integer ABI_BEAST_STRIKE = 'A00L' // "thunderbolt"
constant integer ABI_BEAST_ENDURANCE_AURA = 'A00J' // endurance aura based
constant integer ABI_BEAST_CLAP = 'A00I' //ulti lvl 6, "thunderclap"
constant integer BUFF_BEAST_ROAR = 'Broa' //standard roar buff
endglobals
//--------------------------------------------------------------------------------------
function Trig_BeastStrike_LoopEnum takes nothing returns nothing
local unit d = GetEnumUnit()
local integer id = GetUnitUserData(d)
local real angle=0.00
local string eff=""
if spellCounter[id]==4 then
if UnitAlive(spellCaster[id]) and UnitAlive(spellTargetUnit[id]) then
set angle=Atan2(GetUnitY(spellTargetUnit[id]) - GetUnitY(spellCaster[id]), GetUnitX(spellTargetUnit[id]) - GetUnitX(spellCaster[id]))
set eff="Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl"
call KnockBack(null, spellTargetUnit[id], spellDistance[id], 2.00, angle, true, false, false, KB_TYPE_NORMAL, KB_FILTR_BOUNCE_ALLIED_ONLY, eff, "origin", 100.00)
endif
endif
//---
set spellCounter[id] = spellCounter[id] + 1
set spellDuration[id] = spellDuration[id] - 0.10
if spellDuration[id] <= 0.00 then // Clean up any data attached to this spell
set spellCaster[id] = null
set spellTargetUnit[id] = null
//---
call GroupRemoveUnit(spellGroup[3], d)
call RemoveUnit(d)
if FirstOfGroup(spellGroup[3]) == null then
call PauseTimer(spellTimer[3])
endif
endif
set d=null
endfunction
//---------------
function Trig_BeastStrike_Loop takes nothing returns nothing
call ForGroup(spellGroup[3], function Trig_BeastStrike_LoopEnum)
endfunction
//---------------
function Trig_BeastStrike_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local real lvl=I2R(GetUnitAbilityLevel(u, ABI_BEAST_STRIKE))
local real dist=500.00+(100.00*lvl)
local unit dummy=CreateUnit(GetOwningPlayer(u), DUMMY, GetUnitX(target), GetUnitY(target), 0.00)
local integer id=GetUnitUserData(dummy)
set spellCaster[id]=u
set spellTargetUnit[id]=target
set spellDistance[id]=500.00+(100.00*lvl)
set spellDuration[id] = 2.00
set spellCounter[id] = 0
if FirstOfGroup(spellGroup[3]) == null then
call TimerStart(spellTimer[3], 0.10, true, function Trig_BeastStrike_Loop)
endif
call GroupAddUnit(spellGroup[3], dummy)
set u=null
set target=null
set dummy=null
endfunction
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
function Trig_SpellsBeast_Conditions takes nothing returns boolean
if GetSpellAbilityId() == ABI_BEAST_STRIKE then
call Trig_BeastStrike_Actions()
endif
return false
endfunction
//===========================================================================
function InitTrig_SpellsBeast takes nothing returns nothing
set gg_trg_SpellsBeast = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_SpellsBeast, EVENT_PLAYER_UNIT_SPELL_CAST )
call TriggerAddCondition( gg_trg_SpellsBeast, Condition( function Trig_SpellsBeast_Conditions ) )
endfunction
// CRIPPLE - Reduces movement speed, attack rate and damage of a target enemy unit.
// ENSNARE - Causes a target enemy unit to be bound to the ground so that it cannot move .
// Air units that are ensnared can be attacked as though they were land units.
// Deals dmg upon impact.
// FRENZY (ulti) - Increases Slayer's attack rate and movement speed.
//---------------------------------------------------------------------------------
// CAST SPELLS
//---------------------------------------------------------------------------------
function ZergSlayer_Cripple takes unit target returns boolean
local integer count=0
if (not IsMagicImmune(target)) and GetUnitAbilityLevel(target, BUFF_SLAYER_CRIPPLE)==0 and UnitSpellReady(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE) then
call IssueTargetOrderById(ZERG_HERO_SLAYER, ORDER_cripple, target)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_SLAYER) != ORDER_cripple
exitwhen count>10 //~2seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_SLAYER, target)
return true
endif
return false
endfunction
//---------------------------------------------------------------------------------
function ZergSlayer_Frenzy takes unit target returns boolean
if GetUnitAbilityLevel(ZERG_HERO_SLAYER, BUFF_SLAYER_FRENZY)==0 and UnitSpellReady(ZERG_HERO_SLAYER, ABI_SLAYER_FRENZY) then
if CountUnitsInRange(GetUnitX(ZERG_HERO_SLAYER), GetUnitY(ZERG_HERO_SLAYER), 350, g_filtrZEnemy)>0 then
call IssueImmediateOrderById(ZERG_HERO_SLAYER, ORDER_frenzy)
call ZergHeroAttack(ZERG_HERO_SLAYER, target)
return true
endif
endif
return false
endfunction
//---------------------------------------------------------------------------------
//"i" is pool number
function ZergSlayer_Ensnare_Defence takes unit target, integer i returns boolean
local integer count=0
if (not IsMagicImmune(target)) and (not IsUnitType(target, UNIT_TYPE_SNARED)) and UnitSpellReady(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE) then
if IsUnitInRange(target, zergSpawningPool[i], 1100.00) then
call IssueTargetOrderById(ZERG_HERO_SLAYER, ORDER_ensnare, target)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_SLAYER) != ORDER_ensnare
exitwhen count>10 //~2seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_SLAYER, target)
return true
endif
endif
return false
endfunction
//---------------------------------------------------------------------------------
//for attacks
function ZergSlayer_Ensnare takes unit target returns boolean
local integer count=0
if (not IsMagicImmune(target)) and (not IsUnitType(target, UNIT_TYPE_SNARED)) and UnitSpellReady(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE) then
if IsUnitInRange(ZERG_HERO_SLAYER, target, 800.00) and (not IsUnitInRange(ZERG_HERO_SLAYER, target, 300.00)) then
call IssueTargetOrderById(ZERG_HERO_SLAYER, ORDER_ensnare, target)
loop
call TriggerSleepAction(0.20)
exitwhen (g_zFlag[GetUnitUserData(ZERG_HERO_SLAYER)]==INTERRUPT) or (not UnitAlive(ZERG_HERO_SLAYER))
exitwhen GetUnitCurrentOrder(ZERG_HERO_SLAYER) != ORDER_ensnare
exitwhen count>15 //~3seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_SLAYER, target)
return true
endif
endif
return false
endfunction
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
// zerg heroes have aura learned at level 1
function ZergSlayer_LearnSkill takes nothing returns nothing
local integer randomizer=GetRandomInt(1,120)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_FRENZY)// ulti
if randomizer>=1 and randomizer<=20 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
elseif randomizer>20 and randomizer<=40 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
elseif randomizer>40 and randomizer<=60 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
elseif randomizer>60 and randomizer<=80 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
elseif randomizer>80 and randomizer<=100 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
elseif randomizer>100 and randomizer<=120 then
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_UNHOLY_AURA)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_CRIPPLE)
call SelectHeroSkill(ZERG_HERO_SLAYER, ABI_SLAYER_ENSNARE)
endif
if GetHeroSkillPoints(ZERG_HERO_SLAYER)>0 then
call ZergSlayer_LearnSkill() //re-run this
endif
endfunction
//================================================
globals
constant integer ABI_SLAYER_ENSNARE = 'A00V' // "ensnare"
constant integer BUFF_SLAYER_ENSNARE_G = 'Beng' //ground
constant integer BUFF_SLAYER_ENSNARE_A = 'Bena' //air
constant integer ABI_SLAYER_CRIPPLE = 'A00U' // "cripple"
constant integer ABI_SLAYER_UNHOLY_AURA = 'A007'
constant integer ABI_SLAYER_FRENZY = 'A00T' // "frenzy" (ulti)
constant integer BUFF_SLAYER_CRIPPLE = 'B002'
constant integer BUFF_SLAYER_FRENZY = 'Bfzy' //standard
endglobals
//-----------------------------------------------------------------------------------
function Trig_SlayerEnsnare_LoopEnum takes nothing returns nothing
local unit d = GetEnumUnit()
local integer id = GetUnitUserData(d)
local boolean hasBuff1 = GetUnitAbilityLevel(spellTargetUnit[id], BUFF_SLAYER_ENSNARE_G) > 0
local boolean hasBuff2 = GetUnitAbilityLevel(spellTargetUnit[id], BUFF_SLAYER_ENSNARE_A) > 0
if spellCounter[id]>0 and (hasBuff1 or hasBuff2) then
set spellDuration[id]=0.00
call UnitDamageTarget(spellCaster[id], spellTargetUnit[id], spellDamage[id], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
endif
//---
set spellCounter[id] = spellCounter[id] + 1
set spellDuration[id] = spellDuration[id] - 0.05
if spellDuration[id] <= 0.00 then // Clean up any data attached to this spell
set spellCaster[id] = null
set spellTargetUnit[id] = null
//---
call GroupRemoveUnit(spellGroup[4], d)
call RemoveUnit(d)
if FirstOfGroup(spellGroup[4]) == null then
call PauseTimer(spellTimer[4])
endif
endif
set d=null
endfunction
//---------------
function Trig_SlayerEnsnare_Loop takes nothing returns nothing
call ForGroup(spellGroup[4], function Trig_SlayerEnsnare_LoopEnum)
endfunction
//---------------
function Trig_SlayerEnsnare_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local integer lvl=GetUnitAbilityLevel(u, ABI_SLAYER_ENSNARE)
local unit dummy=CreateUnit(GetOwningPlayer(u), DUMMY, GetUnitX(target), GetUnitY(target), 0.00)
local integer id=GetUnitUserData(dummy)
set spellCaster[id]=u
set spellTargetUnit[id]=target
set spellDamage[id]=50.00*I2R(lvl)
set spellDuration[id] = 5.00
set spellCounter[id] = 0
if FirstOfGroup(spellGroup[4]) == null then
call TimerStart(spellTimer[4], 0.05, true, function Trig_SlayerEnsnare_Loop)
endif
call GroupAddUnit(spellGroup[4], dummy)
set u=null
set target=null
set dummy=null
endfunction
//-------------------------------------------------------------------------------------
function Trig_SpellsSlayer_Conditions takes nothing returns boolean
if GetSpellAbilityId() == ABI_SLAYER_ENSNARE then
call Trig_SlayerEnsnare_Actions()
endif
return false
endfunction
//===========================================================================
function InitTrig_SpellsSlayer takes nothing returns nothing
set gg_trg_SpellsSlayer = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ(gg_trg_SpellsSlayer, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_SpellsSlayer, Condition(function Trig_SpellsSlayer_Conditions))
endfunction
// LIGHTNING-SLEEP - Creates a lightning bolt that deals 100/150/200 damage and right after puts a target to sleep for 10 seconds.
// PACT - Transfers allied target's life to the Queen to heal her. May kill target unit.
// ATTRACTION (ulti) - Purges enemy, then after 2sec attracts target near the caster.
// When target is close enough - deals 250 damage.
//---------------------------------------------------------------------------------
// CAST SPELLS
//---------------------------------------------------------------------------------
function ZergQueen_LightningSleep takes unit target returns boolean
local unit u=null
local real x=0.00
local real y=0.00
local integer count=0
//try to omit main target if possible
if UnitSpellReady(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP) then
set x=GetUnitX(ZERG_HERO_QUEEN)
set y=GetUnitY(ZERG_HERO_QUEEN)
set u=GetWeakestUnitInRangeEx(x, y, 700, g_filtrZEnemyGroundOrganicNotImmuneHero, target)
//set u=GetWeakestUnitInRangeEx(x, y, 700, g_filtrZEnemyOrganicNotImmune, target)
if u != null then
call IssueTargetOrderById(ZERG_HERO_QUEEN, ORDER_chainlightning, u)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_QUEEN) != ORDER_chainlightning
exitwhen count>10 //~2seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_QUEEN, target)
set u=null
return true
endif
endif
set u=null
return false
endfunction
//---------------------------------------------------------------------------------
function ZergQueen_Attraction takes unit target returns boolean
local integer count=0
if IsUnitType(target, UNIT_TYPE_HERO) and (not IsMagicImmune(target)) and UnitSpellReady(ZERG_HERO_QUEEN, ABI_QUEEN_ATTRACTION) then
if (not IsUnitInRange(target, ZERG_HERO_QUEEN, 300.00)) and IsUnitInRange(target, ZERG_HERO_QUEEN, 700.00) then
call IssueTargetOrderById(ZERG_HERO_QUEEN, ORDER_holybolt, target)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_QUEEN) != ORDER_holybolt
exitwhen count>15 //~3seconds max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_QUEEN, target)
return true
endif
endif
return false
endfunction
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
function ZergQueen_GetPactTarget takes nothing returns unit
local unit FoG=null
local integer t=0
local unit target=null
local group g=CreateGroup()
local real max=0.00
call GroupEnumUnitsInRange(ug, GetUnitX(ZERG_HERO_QUEEN), GetUnitY(ZERG_HERO_QUEEN), 600, g_filtrZergUnits_OrganicNotHero)
loop
set FoG = FirstOfGroup(ug)
exitwhen FoG == null
set t=GetUnitTypeId(FoG)
//---
if GetUnitPercentLife(FoG)>0.20 then
if t==ZERG_OVERLORD or t==ZERG_ZERGLING or t==ZERG_HYDRALISK or t==ZERG_HUNTER_KILLER then
//set target=FoG
call GroupAddUnit(g, FoG)
elseif t==ZERG_MUTALISK or t==ZERG_GUARDIAN or t==ZERG_ULTRALISK then
//set target=FoG
call GroupAddUnit(g, FoG)
endif
endif
//---
call GroupRemoveUnit(ug, FoG)
endloop
call GroupClear(ug)
//added 17-03-2019 :
loop
set FoG = FirstOfGroup(g)
exitwhen FoG == null
if GetWidgetLife(FoG)>max then
set max=GetWidgetLife(FoG)
set target=FoG
endif
call GroupRemoveUnit(g, FoG)
endloop
call GroupClear(g)
call DestroyGroup(g)
set g=null
set FoG=null
return target
endfunction
//-----------------------------------------------------------------------------------------------------
function ZergQueen_Pact takes unit target returns boolean
local unit u=null
local integer count=0
if (GetUnitPercentLife(ZERG_HERO_QUEEN)<0.60) and UnitSpellReady(ZERG_HERO_QUEEN, ABI_QUEEN_PACT) then
set u=ZergQueen_GetPactTarget()
if u != null then
call IssueTargetOrderById(ZERG_HERO_QUEEN, ORDER_hex, u)
loop
call TriggerSleepAction(0.20)
exitwhen GetUnitCurrentOrder(ZERG_HERO_QUEEN) != ORDER_hex
exitwhen count>10 //~2second max
set count=count+1
endloop
call ZergHeroAttack(ZERG_HERO_QUEEN, target)
set u=null
return true
endif
endif
set u=null
return false
endfunction
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
// zerg heroes have aura learned at level 1
function ZergQueen_LearnSkill takes nothing returns nothing
local integer randomizer=GetRandomInt(1,120)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_ATTRACTION)// ulti
if randomizer>=1 and randomizer<=20 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
elseif randomizer>20 and randomizer<=40 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
elseif randomizer>40 and randomizer<=60 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
elseif randomizer>60 and randomizer<=80 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
elseif randomizer>80 and randomizer<=100 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
elseif randomizer>100 and randomizer<=120 then
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_VAMPIRIC_AURA)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_PACT)
call SelectHeroSkill(ZERG_HERO_QUEEN, ABI_QUEEN_LIGHTNING_SLEEP)
endif
if GetHeroSkillPoints(ZERG_HERO_QUEEN)>0 then
call ZergQueen_LearnSkill() //re-run this
endif
endfunction
//=========================================================
globals
constant integer ABI_QUEEN_LIGHTNING_SLEEP = 'A00O' // "chainlightning"
constant integer ABI_DUMMY_QUEEN_SLEEP = 'A00N' // "sleep"
constant integer ABI_QUEEN_PACT = 'A00R' //"channel" based "hex"
constant integer ABI_QUEEN_VAMPIRIC_AURA = 'A00M'
constant integer ABI_QUEEN_ATTRACTION = 'A00Q' //"channel" based order: "holybolt"
constant integer ABI_DUMMY_QUEEN_PURGE='A00P' // "purge"
endglobals
//--------------------------------------------------------------------------------------
// LIGHTNING SLEEP
//--------------------------------------------------------------------------------------
function Trig_QueenLightningSleep_LoopEnum takes nothing returns nothing
local unit d = GetEnumUnit()
local integer id = GetUnitUserData(d)
if spellCounter[id]==5 then
call IssueTargetOrderById(d, ORDER_sleep, spellTargetUnit[id])
endif
//---
set spellCounter[id] = spellCounter[id] + 1
set spellDuration[id] = spellDuration[id] - 0.10
if spellDuration[id] <= 0.00 then // Clean up any data attached to this spell
set spellCaster[id] = null
set spellTargetUnit[id] = null
//---
call GroupRemoveUnit(spellGroup[2], d)
call RemoveUnit(d)
if FirstOfGroup(spellGroup[2]) == null then
call PauseTimer(spellTimer[2])
endif
endif
set d=null
endfunction
//--------------------------------------------------------------------------------------
function Trig_QueenLightningSleep_Loop takes nothing returns nothing
call ForGroup(spellGroup[2], function Trig_QueenLightningSleep_LoopEnum)
endfunction
//--------------------------------------------------------------------------------------
function Trig_QueenLightningSleep_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local unit dummy=CreateUnit(GetOwningPlayer(u), DUMMY, GetUnitX(target), GetUnitY(target), 0.00)
local integer id=GetUnitUserData(dummy)
call UnitAddAbility(dummy, ABI_DUMMY_QUEEN_SLEEP)
set spellCaster[id]=u
set spellTargetUnit[id]=target
set spellDuration[id] = 2.00
set spellCounter[id] = 0
if FirstOfGroup(spellGroup[2]) == null then
call TimerStart(spellTimer[2], 0.10, true, function Trig_QueenLightningSleep_Loop)
endif
call GroupAddUnit(spellGroup[2], dummy)
set u=null
set target=null
set dummy=null
endfunction
//--------------------------------------------------------------------------------------
// PACT
//--------------------------------------------------------------------------------------
function Trig_QueenDeathPact_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local integer lvl=GetUnitAbilityLevel(u, ABI_QUEEN_PACT)
local real queenMissingHP=GetUnitMissingLife(u)
local real targetLife=GetWidgetLife(target)
local real multiplier = 0.50+(0.50*I2R(lvl))
local real healValue=targetLife*multiplier
local real lifeToSubtract = queenMissingHP / multiplier
if healValue>queenMissingHP then
call SetWidgetLife(target, targetLife-lifeToSubtract)
else
call KillUnit(target)
endif
call SetWidgetLife(u, GetWidgetLife(u)+healValue)
set u=null
set target=null
endfunction
//--------------------------------------------------------------------------------------
// ATTRACTION
//--------------------------------------------------------------------------------------
function Trig_QueenAttraction_LoopEnum takes nothing returns nothing
local unit d = GetEnumUnit()
local integer id = GetUnitUserData(d)
local real x=0.00
local real y=0.00
local real angle=0.00
if (not UnitAlive(spellTargetUnit[id])) or IsMagicImmune(spellTargetUnit[id]) or IsUnitInvulnerable(spellTargetUnit[id]) then
set spellDuration[id]=0.00
elseif not UnitAlive(spellCaster[id]) then
set spellDuration[id]=0.00
elseif (spellInteger[id]==0) and (not UnitChanneling(spellCaster[id])) then
set spellDuration[id]=0.00
elseif (spellInteger[id]==0) and (not IsUnitInRange(spellTargetUnit[id], spellCaster[id], 1900.00)) then
set spellDuration[id]=0.00
endif
//we wait 2 sec for channeling time
if spellInteger[id]==0 and spellCounter[id]==40 then// 1.50sec
call UnitAddAbility(spellCaster[id], ABI_LIGHTNING_UNIT2UNIT)
call IssueTargetOrderById(spellCaster[id], ORDER_fingerofdeath, spellTargetUnit[id])
call DisableUnitMovement(spellTargetUnit[id])
set spellInteger[id]=1
elseif spellInteger[id]==1 and spellCounter[id]==64 then // 2sec
set spellInteger[id]=2
call MsgDev("start attraction")
endif
if spellInteger[id]==2 then
if IsUnitInRange(spellTargetUnit[id], spellCaster[id], 150.00) then
call MsgDev("target is near")
call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\VengeanceMissile\\VengeanceMissile.mdl", spellTargetUnit[id], "origin"))
call UnitDamageTarget(spellCaster[id], spellTargetUnit[id], spellDamage[id], true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
set spellDuration[id]=0.00
else //move target a bit
set x=GetUnitX(spellTargetUnit[id])
set y=GetUnitY(spellTargetUnit[id])
set angle=Atan2(GetUnitY(spellCaster[id])-y, GetUnitX(spellCaster[id])-x)
call SetUnitX(spellTargetUnit[id], x + 16.00 * Cos(angle))
call SetUnitY(spellTargetUnit[id], y + 16.00 * Sin(angle))
endif
endif
//---
set spellCounter[id] = spellCounter[id] + 1
set spellDuration[id] = spellDuration[id] - 0.03125
if spellDuration[id] <= 0.00 then // Clean up any data attached to this spell
call EnableUnitMovement(spellTargetUnit[id])
call UnitRemoveAbility(spellCaster[id], ABI_LIGHTNING_UNIT2UNIT)
set spellCaster[id] = null
set spellTargetUnit[id] = null
//---
call GroupRemoveUnit(spellGroup[1], d)
call RemoveUnit(d)
if FirstOfGroup(spellGroup[1]) == null then
call PauseTimer(spellTimer[1])
endif
endif
set d=null
endfunction
//--------------------------------------------------------------------------------------
function Trig_QueenAttraction_Loop takes nothing returns nothing
call ForGroup(spellGroup[1], function Trig_QueenAttraction_LoopEnum)
endfunction
//--------------------------------------------------------------------------------------
function Trig_QueenAttraction_Actions takes nothing returns nothing
local unit u=GetTriggerUnit()
local unit target=GetSpellTargetUnit()
local real Tx=GetSpellTargetX()
local real Ty=GetSpellTargetY()
local unit dummy=CreateUnit(GetOwningPlayer(u), DUMMY, Tx, Ty, 0.00)
local integer id=GetUnitUserData(dummy)
set spellCaster[id]=u
set spellTargetUnit[id]=target
set spellDuration[id] = 8.00
set spellCounter[id] = 0
set spellDamage[id] = 250.00
set spellInteger[id]=0
call UnitAddAbility(dummy, ABI_DUMMY_QUEEN_PURGE)
call IssueTargetOrderById(dummy, ORDER_purge, spellTargetUnit[id])
if FirstOfGroup(spellGroup[1]) == null then
call TimerStart(spellTimer[1], 0.03125, true, function Trig_QueenAttraction_Loop)
endif
call GroupAddUnit(spellGroup[1], dummy)
set u=null
set target=null
set dummy=null
endfunction
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------
function Trig_QueenSpell_Conditions takes nothing returns boolean
local integer spell=GetSpellAbilityId()
if spell==ABI_QUEEN_PACT then
call Trig_QueenDeathPact_Actions()
elseif spell==ABI_QUEEN_LIGHTNING_SLEEP then
call Trig_QueenLightningSleep_Actions()
elseif spell==ABI_QUEEN_ATTRACTION then
call Trig_QueenAttraction_Actions()
endif
return false
endfunction
//===========================================================================
function InitTrig_SpellsQueen takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Trig_QueenSpell_Conditions))
set t=null
endfunction
//----------------------------------------------------------------------------------------------
// zerg hero dies
//
// when hero dies --> cut off its connections, (after revive: add to def group)
//----------------------------------------------------------------------------------------------
function Trig_ZergHeroDiesRevive_Actions takes nothing returns nothing
local unit hero=GetTriggerUnit()
local integer x=1
local real delay = 45.00 + I2R(GetHeroLevel(hero))
call ZergHero_Disconnect(hero)
call TriggerSleepAction(delay)
if GAME_OVER then
return
endif
// searches for random pool without a hero; if all pools have hero(s) then it picks a pool with lowest hp
set x=ZergGetRandomPoolForHero()
call ReviveHero(hero, GetUnitX(zergSpawningPool[x]), GetUnitY(zergSpawningPool[x]), true)
call ZergHero_ConnectPool(hero, x)
set hero=null
endfunction
//------------------------------------------------------------------------------------------------
// hero level up
//------------------------------------------------------------------------------------------------
function Trig_ZergHeroLevelUp takes nothing returns nothing
//let zerg heroes follow players' heroes level
local integer lvl=g_playerHeroMaxLevel //global written in "PlayerHeroes" trigger
call SuspendHeroXP(ZERG_HERO_BEAST, false) // enable expirience gain
call SuspendHeroXP(ZERG_HERO_SLAYER, false)
call SuspendHeroXP(ZERG_HERO_QUEEN, false)
call SetHeroLevel(ZERG_HERO_BEAST, lvl, true)
call SetHeroLevel(ZERG_HERO_SLAYER, lvl, true)
call SetHeroLevel(ZERG_HERO_QUEEN, lvl, true)
//learn abilities:
call ZergQueen_LearnSkill()
call ZergBeast_LearnSkill()
call ZergSlayer_LearnSkill()
call SuspendHeroXP(ZERG_HERO_BEAST, true) // disable expirience gain
call SuspendHeroXP(ZERG_HERO_SLAYER, true)
call SuspendHeroXP(ZERG_HERO_QUEEN, true)
endfunction
//===========================================================================
function InitTrig_ZergHeroes takes nothing returns nothing
local trigger t=null
set t=CreateTrigger()
call TriggerRegisterVariableEvent(t, "eventPlayerHeroLevelUp", EQUAL, 1.00)
call TriggerAddAction(t, function Trig_ZergHeroLevelUp)
//---
set gg_trg_ZergHeroes = CreateTrigger( )
call TriggerRegisterUnitEvent( gg_trg_ZergHeroes, gg_unit_U009_0049, EVENT_UNIT_DEATH )
call TriggerRegisterUnitEvent( gg_trg_ZergHeroes, gg_unit_N003_0047, EVENT_UNIT_DEATH )
call TriggerRegisterUnitEvent( gg_trg_ZergHeroes, gg_unit_U006_0032, EVENT_UNIT_DEATH )
call TriggerAddAction( gg_trg_ZergHeroes, function Trig_ZergHeroDiesRevive_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// BEAST BAHAVIOUR - hero is a member of defenders group
//-------------------------------------------------------------------------------------------------------------------------
//exit when : hero dies, pool dies, interrupt flag
//------------------------------------------------------------------------------------
function HeroDefExitConditions takes unit u, integer id, integer poolNo returns boolean
return (not UnitAlive(u)) or (not UnitAlive(zergSpawningPool[poolNo])) or (g_zFlag[id]==INTERRUPT)
endfunction
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
function Trig_BeastDef_Actions takes nothing returns nothing
local unit u=ZERG_HERO_BEAST
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer id=GetUnitUserData(u)
local integer poolNo=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer c=0
local unit target=null
local real x=GetUnitX(zergSpawningPool[poolNo])
local real y=GetUnitY(zergSpawningPool[poolNo])
set g_zergBehaviourTrgRunning[id]=true
loop
exitwhen HeroDefExitConditions(u, id, poolNo)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_SLEEP
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
call ZergHeroMove(u, x, y)
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_BACK
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen HeroDefExitConditions(u, id, poolNo)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
endif
//spells
if ZergBeast_Roar(target) then
elseif ZergBeast_Clap(target) then
elseif ZergBeast_Strike(target) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set g_zergBehaviourTrgRunning[id]=false
set g_zFlag[id]=NEUTRAL
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_BeastDef takes nothing returns nothing
set gg_trg_BeastDef = CreateTrigger( )
call TriggerAddAction( gg_trg_BeastDef, function Trig_BeastDef_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// SLAYER BAHAVIOUR - hero is a member of defenders group
//-------------------------------------------------------------------------------------------------------------------------
function Trig_SlayerDef_Actions takes nothing returns nothing
local unit u=ZERG_HERO_SLAYER
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer id=GetUnitUserData(u)
local integer poolNo=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer c=0
local unit target=null
local real x=GetUnitX(zergSpawningPool[poolNo])
local real y=GetUnitY(zergSpawningPool[poolNo])
set g_zergBehaviourTrgRunning[id]=true
loop
exitwhen HeroDefExitConditions(u, id, poolNo)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_SLEEP
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
call ZergHeroMove(u, x, y)
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_BACK
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen HeroDefExitConditions(u, id, poolNo)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
endif
//spells
if ZergSlayer_Cripple(target) then
elseif ZergSlayer_Frenzy(target) then
elseif ZergSlayer_Ensnare_Defence(target, poolNo) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set g_zergBehaviourTrgRunning[id]=false
set g_zFlag[id]=NEUTRAL
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_SlayerDef takes nothing returns nothing
set gg_trg_SlayerDef = CreateTrigger( )
call TriggerAddAction( gg_trg_SlayerDef, function Trig_SlayerDef_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// QUEEN BAHAVIOUR - hero is a member of defenders group
//-------------------------------------------------------------------------------------------------------------------------
function Trig_QueenDef_Actions takes nothing returns nothing
local unit u=ZERG_HERO_QUEEN
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local integer id=GetUnitUserData(u)
local integer poolNo=LoadInteger(zergHash, group_id, KEY_GROUP_POOL_NO)
local integer c=0
local unit target=null
local real x=GetUnitX(zergSpawningPool[poolNo])
local real y=GetUnitY(zergSpawningPool[poolNo])
set g_zergBehaviourTrgRunning[id]=true
loop
exitwhen HeroDefExitConditions(u, id, poolNo)
if ZergG_GetState(group_id)==GROUP_STATE_DEF_SLEEP then
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_SLEEP
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_BACK then
call ZergHeroMove(u, x, y)
loop
call TriggerSleepAction(0.50)
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_BACK
exitwhen HeroDefExitConditions(u, id, poolNo)
endloop
elseif ZergG_GetState(group_id)==GROUP_STATE_DEF_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_DEF_FIGHT
exitwhen HeroDefExitConditions(u, id, poolNo)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
endif
//spells
if ZergQueen_Pact(target) then
elseif ZergQueen_Attraction(target) then
elseif ZergQueen_LightningSleep(target) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set g_zergBehaviourTrgRunning[id]=false
set g_zFlag[id]=NEUTRAL
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_QueenDef takes nothing returns nothing
set gg_trg_QueenDef = CreateTrigger( )
call TriggerAddAction( gg_trg_QueenDef, function Trig_QueenDef_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// BEAST BAHAVIOUR - hero is a member of attackers group
//-------------------------------------------------------------------------------------------------------------------------
function Trig_BeastAttack_Actions takes nothing returns nothing
local unit u=ZERG_HERO_BEAST
local integer c=0
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call ZergHeroMove(u, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call ZergHeroAttackMove(u, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
call TriggerSleepAction(1.00)
endif
//spells
if ZergBeast_Roar(target) then
elseif ZergBeast_Clap(target) then
elseif ZergBeast_Strike(target) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_BeastAttack takes nothing returns nothing
set gg_trg_BeastAttack = CreateTrigger( )
call TriggerAddAction( gg_trg_BeastAttack, function Trig_BeastAttack_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// SLAYER BAHAVIOUR - hero is a member of attackers group
//-------------------------------------------------------------------------------------------------------------------------
function Trig_SlayerAttack_Actions takes nothing returns nothing
local unit u=ZERG_HERO_SLAYER
local integer c=0
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call ZergHeroMove(u, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call ZergHeroAttackMove(u, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
call TriggerSleepAction(1.00)
endif
//spells
if ZergSlayer_Cripple(target) then
elseif ZergSlayer_Frenzy(target) then
elseif ZergSlayer_Ensnare(target) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_SlayerAttack takes nothing returns nothing
set gg_trg_SlayerAttack = CreateTrigger( )
call TriggerAddAction( gg_trg_SlayerAttack, function Trig_SlayerAttack_Actions )
endfunction
//-------------------------------------------------------------------------------------------------------------------------
// QUEEN BAHAVIOUR - hero is a member of attackers group
//-------------------------------------------------------------------------------------------------------------------------
function Trig_QueenAttack_Actions takes nothing returns nothing
local unit u=ZERG_HERO_QUEEN
local integer c=0
local integer group_id = g_zGroupId[GetUnitUserData(u)]
local unit target=null
loop
exitwhen not UnitAlive(u)
if ZergG_GetState(group_id)==GROUP_STATE_CREATING then
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CREATING)
elseif ZergG_GetState(group_id)==GROUP_STATE_CONSOLIDATE then
call ZergHeroMove(u, ZergG_GetConsolidateX(group_id), ZergG_GetConsolidateY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_CONSOLIDATE)
elseif ZergG_GetState(group_id)==GROUP_STATE_ATTACK_MOVE then
call ZergHeroAttackMove(u, ZergG_GetDestinationX(group_id), ZergG_GetDestinationY(group_id))
call WaitForGroupStateChanged(u, group_id, GROUP_STATE_ATTACK_MOVE)
elseif ZergG_GetState(group_id)==GROUP_STATE_FIGHT then
set c=0
loop
exitwhen ZergG_GetState(group_id) != GROUP_STATE_FIGHT
exitwhen not UnitAlive(u)
if c==0 then
set c=6
set target=ZergG_GetTarget(group_id)
call ZergHeroAttack(u, target)
call TriggerSleepAction(1.00)
endif
//spells
if ZergQueen_Pact(target) then
elseif ZergQueen_Attraction(target) then
elseif ZergQueen_LightningSleep(target) then
endif
set c=c-1
call TriggerSleepAction(1.00)
endloop
endif
call TriggerSleepAction(0.50)
endloop
set u=null
set target=null
endfunction
//===========================================================================
function InitTrig_QueenAttack takes nothing returns nothing
set gg_trg_QueenAttack = CreateTrigger( )
call TriggerAddAction( gg_trg_QueenAttack, function Trig_QueenAttack_Actions )
endfunction
globals
unit g_zergHeroItm=null
integer g_zergHeroItemId=0
endglobals
function Trig_ZergAddItem_Actions takes nothing returns nothing
local unit u=g_zergHeroItm
local integer itm=g_zergHeroItemId
loop
exitwhen UnitAlive(u)
call TriggerSleepAction(1.00)
endloop
call UnitAddItemById(u, itm)
set u=null
endfunction
//===========================================================================
function InitTrig_ZergAddItem takes nothing returns nothing
set gg_trg_ZergAddItem = CreateTrigger( )
call TriggerAddAction( gg_trg_ZergAddItem, function Trig_ZergAddItem_Actions )
endfunction
globals
group groupAI=CreateGroup()
boolean g_lookForNextPointWhenMove = true
boolean g_zergWavePickPath=true
integer g_waveNo_L=1 //for library
integer g_waveNo_C=1 //for cathedral
timer g_waveTimerLibrary=CreateTimer()
timer g_waveTimerCathedral=CreateTimer()
unit g_waveTarget=null
integer g_totalAttackers_Library=0
integer g_totalAttackers_Cathedral=0
endglobals
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
function ZergSaveWaveInHash takes string quantities, boolean addHero, boolean useCargo, real pause, integer h_id, integer waveNo returns nothing
call SaveStr(zergHash, h_id, KEY_WAVE_S+waveNo, quantities)
call SaveBoolean(zergHash, h_id, KEY_WAVE_H+waveNo, addHero)
call SaveBoolean(zergHash, h_id, KEY_WAVE_C+waveNo, useCargo)
call SaveReal(zergHash, h_id, KEY_WAVE_P+waveNo, pause) //how loong we wait before sending next wave
endfunction
//------------------------------------------------------------------------------------------------------------
// LIBRARY
//------------------------------------------------------------------------------------------------------------
function SaveWaveLibrary_Normal takes string quantities, boolean addHero, real pause, integer waveNo returns nothing
local integer h_id=GetHandleId(LIBRARY)
call ZergSaveWaveInHash(quantities, addHero, false, pause, h_id, waveNo)
endfunction
function SaveWaveLibrary_Cargo takes string quantities, boolean addHero, real pause, integer waveNo returns nothing
local integer h_id=GetHandleId(LIBRARY)
call ZergSaveWaveInHash(quantities, addHero, true, pause, h_id, waveNo)
endfunction
//------------------------------------------------------------------------------------------------------------
// CATHEDRAL
//------------------------------------------------------------------------------------------------------------
function SaveWaveCathedral_Normal takes string quantities, boolean addHero, real pause, integer waveNo returns nothing
local integer h_id=GetHandleId(CATHEDRAL)
call ZergSaveWaveInHash(quantities, addHero, false, pause, h_id, waveNo)
endfunction
function SaveWaveCathedral_Cargo takes string quantities, boolean addHero, real pause, integer waveNo returns nothing
local integer h_id=GetHandleId(CATHEDRAL)
call ZergSaveWaveInHash(quantities, addHero, true, pause, h_id, waveNo)
endfunction
//------------------------------------------------------------------------------------------------------------
function ZergLoadWave_S takes integer targetHandleId, integer waveNo returns string
//local string s=""
//if GAME_DIFFICULTY_NORMAL then
//set s=LoadStr(zergHash, targetHandleId, KEY_WAVE_S+waveNo)
//else
//set s=LoadStr(zergHash, targetHandleId, KEY_WAVE_S+1000+waveNo)
//endif
//return s
return LoadStr(zergHash, targetHandleId, KEY_WAVE_S+waveNo)
endfunction
//------------------------------------------------------------------------------------------------------------
function ZergLoadWave_H takes integer targetHandleId, integer waveNo returns boolean
//local boolean result=false
//if GAME_DIFFICULTY_NORMAL then
//set result = LoadBoolean(zergHash, targetHandleId, KEY_WAVE_H+waveNo)
//else
//set result = LoadBoolean(zergHash, targetHandleId, KEY_WAVE_H+1000+waveNo)
//endif
//return result
return LoadBoolean(zergHash, targetHandleId, KEY_WAVE_H+waveNo)
endfunction
//------------------------------------------------------------------------------------------------------------
function ZergLoadWave_C takes integer targetHandleId, integer waveNo returns boolean
//local boolean result=false
//if GAME_DIFFICULTY_NORMAL then
//set result = LoadBoolean(zergHash, targetHandleId, KEY_WAVE_C+waveNo)
//else
//set result = LoadBoolean(zergHash, targetHandleId, KEY_WAVE_C+1000+waveNo)
//endif
//return result
return LoadBoolean(zergHash, targetHandleId, KEY_WAVE_C+waveNo)
endfunction
//------------------------------------------------------------------------------------------------------------
function ZergLoadWave_P takes integer targetHandleId, integer waveNo returns real
local real time=999999.00
if HaveSavedReal(zergHash, targetHandleId, KEY_WAVE_P+waveNo) then
if GAME_DIFFICULTY_NORMAL then
set time = LoadReal(zergHash, targetHandleId, KEY_WAVE_P+waveNo)
else
set time = LoadReal(zergHash, targetHandleId, KEY_WAVE_P+waveNo) - 3.00
//set time = LoadReal(zergHash, targetHandleId, KEY_WAVE_P+1000+waveNo)
endif
endif
return time
endfunction
//------------------------------------------------------------------------------------------------------------
function ZergGetRandomPoolForWave takes nothing returns integer
local string s=""
local integer position=1
local integer i=1
loop
exitwhen i>6
if UnitAlive(zergSpawningPool[i]) and (not IsUnitHidden(zergSpawningPool[i])) then
set s=s+I2S(i)
endif
set i=i+1
endloop
set position=GetRandomInt(1, StringLength(s))
return S2I(SubStringBJ(s, position, position))
endfunction
//LIBRARY //prefer pool no 3,4,5
function ZergGetRandomPoolForWave_Library takes nothing returns integer
local string s=""
local integer position=1
local integer i=1
if UnitAlive(zergSpawningPool[3]) and (not IsUnitHidden(zergSpawningPool[3])) then
set s=s+"3"
endif
if UnitAlive(zergSpawningPool[4]) and (not IsUnitHidden(zergSpawningPool[4])) then
set s=s+"4"
endif
if UnitAlive(zergSpawningPool[5]) and (not IsUnitHidden(zergSpawningPool[5])) then
set s=s+"5"
endif
if s=="" then
return ZergGetRandomPoolForWave()
endif
set position=GetRandomInt(1, StringLength(s))
return S2I(SubStringBJ(s, position, position))
endfunction
//CATHEDRAL //prefer pool no 1,2,6
function ZergGetRandomPoolForWave_Cathedral takes nothing returns integer
local string s=""
local integer position=1
local integer i=1
if UnitAlive(zergSpawningPool[1]) and (not IsUnitHidden(zergSpawningPool[1])) then
set s=s+"1"
endif
if UnitAlive(zergSpawningPool[2]) and (not IsUnitHidden(zergSpawningPool[2])) then
set s=s+"2"
endif
if UnitAlive(zergSpawningPool[6]) and (not IsUnitHidden(zergSpawningPool[6])) then
set s=s+"6"
endif
if s=="" then
return ZergGetRandomPoolForWave()
endif
set position=GetRandomInt(1, StringLength(s))
return S2I(SubStringBJ(s, position, position))
endfunction
//------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------
function ZergConvertWaveQuantityStringPosition takes string s, integer position returns integer
// input format is "-01-02-03-04-05-06-07-08-09"
local integer start=(position*3) - 2
//position 1-1 , 2-4 , 3-7 , 4-10 , 5-13, 6-16 , 7-19, 8-22 , 9-25
if position>=1 and position <=9 then
return S2I(SubStringBJ(s, start+1, start+2))
endif
return 0
endfunction
// just short name version for above function:
function ZC takes string s, integer position returns integer
return ZergConvertWaveQuantityStringPosition (s, position)
endfunction
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
//===========================================================================
function InitTrig_WaveFunctions takes nothing returns nothing
endfunction
//------------------------------------------------------------------------------------------------------------
// WAVES FOR LIBRARY
//------------------------------------------------------------------------------------------------------------
function Trig_ZergSwitchLast5min takes nothing returns nothing
loop
exitwhen (g_waveNo_L>10 or g_waveNo_C>10) and TimerGetRemaining(timerGameMode)<300
call TriggerSleepAction(5.00)
endloop
set g_waveNo_L = 100
set g_waveNo_C = 100
endfunction
//---------------------------------------------------------------------------------------------
function ZergTimerWave_Library takes nothing returns nothing
if g_waveNo_L==10 and g_totalAttackers_Library>4 then //for wave 10 , wait when attackers count < 4
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==20 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==30 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==40 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==50 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==60 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
elseif g_waveNo_L==70 and g_totalAttackers_Library>4 then
call TimerStart(g_waveTimerLibrary, 5.00, false, function ZergTimerWave_Library)
//etc..
else
call TriggerExecute(gg_trg_AttackWaveLibrary)
endif
endfunction
//------------------------------------------------------------------------------------------------------------
// ----1-----------2----------3--------------4-------------5----------6-------7-----------8-----------9----
// overlord / zergling / hydralisk / red hydralisk / lurker / defiler / mutalisk / guardian / ultralisk
function Trig_WavesLibrary_Actions takes nothing returns nothing
local trigger t=CreateTrigger()
call SaveWaveLibrary_Normal("-00-03-00-00-00-00-00-00-00", false, 27, 1)
call SaveWaveLibrary_Normal("-00-04-00-00-00-00-00-00-00", false, 23, 2)
call SaveWaveLibrary_Normal("-00-04-00-00-00-00-00-00-00", false, 20, 3)
call SaveWaveLibrary_Normal("-00-02-01-00-00-00-00-00-00", false, 18, 4)
call SaveWaveLibrary_Normal("-00-03-01-00-00-00-00-00-00", false, 18, 5)
call SaveWaveLibrary_Normal("-00-04-01-00-00-00-00-00-00", false, 18, 6)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-01-00-00", false, 13, 7)
call SaveWaveLibrary_Normal("-00-03-00-00-00-00-00-00-00", false, 13, 8)
call SaveWaveLibrary_Normal("-00-01-01-00-00-01-00-00-00", false, 16, 9)
call SaveWaveLibrary_Normal("-00-03-00-00-00-00-00-00-00", true, 44, 10)
call SaveWaveLibrary_Cargo("-01-01-01-01-00-00-00-00-00", false, 22, 11)
call SaveWaveLibrary_Normal("-00-02-00-00-00-00-00-00-00", false, 10, 12)
call SaveWaveLibrary_Normal("-00-02-01-00-00-00-00-00-00", false, 12, 13)
call SaveWaveLibrary_Normal("-00-00-02-00-00-00-00-00-00", false, 12, 14)
call SaveWaveLibrary_Normal("-00-00-00-00-01-00-00-00-00", false, 11, 15)
call SaveWaveLibrary_Normal("-00-00-01-00-00-00-01-00-00", false, 12, 16)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-01-00-00", false, 9, 17)
call SaveWaveLibrary_Normal("-00-01-01-00-00-00-00-00-00", false, 10, 18)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-00-01", false, 16, 19)
call SaveWaveLibrary_Normal("-00-00-01-01-00-01-00-00-00", true, 47, 20)
call SaveWaveLibrary_Normal("-00-02-01-00-00-00-00-00-00", false, 10, 21)
call SaveWaveLibrary_Normal("-00-00-02-00-00-00-00-00-00", false, 10, 22)
call SaveWaveLibrary_Normal("-00-02-00-00-00-00-01-00-00", false, 11, 23)
call SaveWaveLibrary_Normal("-00-01-00-00-01-00-00-00-00", false, 11, 24)
call SaveWaveLibrary_Normal("-01-01-01-01-00-00-00-00-00", false, 19, 25)
call SaveWaveLibrary_Normal("-00-00-00-00-00-01-00-00-00", false, 9, 26)
call SaveWaveLibrary_Normal("-01-03-00-00-00-00-00-00-00", false, 16, 27)
call SaveWaveLibrary_Normal("-00-01-01-00-00-00-00-00-00", false, 9, 28)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-00-01", false, 15, 29)
call SaveWaveLibrary_Cargo("-01-02-01-00-00-00-00-00-00", true, 74, 30)
call SaveWaveLibrary_Normal("-00-02-00-00-00-00-00-00-00", false, 7, 31)
call SaveWaveLibrary_Normal("-00-00-01-00-01-00-00-00-00", false, 11, 32)
call SaveWaveLibrary_Normal("-00-06-01-00-00-00-00-00-00", false, 14, 33)
call SaveWaveLibrary_Normal("-00-04-03-00-00-00-02-01-00", false, 32, 34)
call SaveWaveLibrary_Normal("-00-03-00-03-00-00-01-00-00", false, 22, 35)
call SaveWaveLibrary_Normal("-01-00-03-02-01-00-00-00-00", false, 30, 36)
call SaveWaveLibrary_Normal("-00-00-00-00-00-01-00-00-01", false, 18, 37)
call SaveWaveLibrary_Cargo("-01-03-04-01-00-00-00-00-00", false, 28, 38)
call SaveWaveLibrary_Normal("-00-04-00-00-00-00-02-01-00", false, 24, 39)
call SaveWaveLibrary_Normal("-00-00-01-02-00-01-00-00-01", true, 84, 40)
call SaveWaveLibrary_Normal("-00-04-01-00-00-00-00-00-00", false, 12, 41)
call SaveWaveLibrary_Normal("-00-00-03-01-00-00-00-00-00", false, 15, 42)
call SaveWaveLibrary_Normal("-00-00-02-02-00-01-00-00-00", false, 20, 43)
call SaveWaveLibrary_Normal("-00-00-00-01-01-00-01-00-00", false, 15, 44)
call SaveWaveLibrary_Normal("-00-00-01-00-00-00-00-01-00", false, 16, 45)
call SaveWaveLibrary_Normal("-00-00-00-01-00-01-00-00-01", false, 21, 46)
call SaveWaveLibrary_Cargo("-01-00-01-01-01-00-00-00-00", false, 21, 47)
call SaveWaveLibrary_Normal("-01-00-00-00-00-00-01-00-00", false, 14, 48)
call SaveWaveLibrary_Normal("-00-00-01-00-00-00-00-00-00", false, 7, 49)
call SaveWaveLibrary_Normal("-00-00-01-00-00-00-00-00-00", true, 64, 50)
call SaveWaveLibrary_Normal("-00-00-01-00-00-00-00-00-00", true, 24, 51)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 52)
call SaveWaveLibrary_Cargo("-01-01-00-00-01-00-00-00-00", false, 16, 53)
call SaveWaveLibrary_Cargo("-01-00-01-02-00-00-00-00-00", false, 20, 54)
call SaveWaveLibrary_Normal("-00-04-00-00-00-00-00-00-00", false, 9, 55)
call SaveWaveLibrary_Normal("-00-00-04-00-00-00-00-00-00", false, 14, 56)
call SaveWaveLibrary_Normal("-00-00-00-01-01-00-00-00-00", false, 12, 57)
call SaveWaveLibrary_Normal("-00-00-00-00-01-01-01-00-00", false, 15, 58)
call SaveWaveLibrary_Normal("-00-04-00-00-00-00-00-01-00", false, 18, 59)
call SaveWaveLibrary_Normal("-00-00-00-01-00-00-00-00-01", true, 74, 60)
call SaveWaveLibrary_Normal("-01-03-02-03-00-00-00-00-00", false, 30, 61)
call SaveWaveLibrary_Normal("-00-00-02-04-01-00-00-00-01", false, 37, 62)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-03-00-00", false, 13, 63)
call SaveWaveLibrary_Normal("-00-00-00-01-01-00-00-00-00", false, 11, 64)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 65)
call SaveWaveLibrary_Normal("-00-00-00-00-00-02-00-00-01", false, 21, 66)
call SaveWaveLibrary_Normal("-00-00-03-01-01-00-02-00-01", false, 35, 67)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-01", false, 23, 68)
call SaveWaveLibrary_Normal("-00-00-00-01-01-01-00-01-01", false, 34, 69)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-02-01-02", true, 96, 70)
call SaveWaveLibrary_Cargo("-01-03-02-03-00-00-00-00-00", false, 30, 71)
call SaveWaveLibrary_Normal("-00-00-02-04-01-00-00-00-01", false, 37, 72)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-03-00-00", false, 13, 73)
call SaveWaveLibrary_Normal("-00-00-00-01-02-00-00-00-00", false, 15, 74)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 75)
call SaveWaveLibrary_Normal("-00-00-00-00-00-02-00-00-01", false, 21, 76)
call SaveWaveLibrary_Normal("-00-00-03-01-01-00-02-00-01", false, 34, 77)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-01", false, 23, 78)
call SaveWaveLibrary_Normal("-00-00-00-01-01-01-00-01-01", false, 34, 79)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-04-00-00", true, 73, 80)
call SaveWaveLibrary_Normal("-00-04-04-02-00-00-00-00-00", false, 25, 81)
call SaveWaveLibrary_Cargo("-02-10-06-00-02-01-00-00-00", false, 56, 82)
call SaveWaveLibrary_Normal("-00-00-00-00-00-01-00-00-01", false, 17, 83)
call SaveWaveLibrary_Normal("-00-00-00-04-01-00-00-01-00", false, 31, 84)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-04-00-00", false, 16, 85)
call SaveWaveLibrary_Normal("-00-00-00-00-02-01-00-00-01", false, 25, 86)
call SaveWaveLibrary_Normal("-00-12-00-00-00-00-00-00-00", false, 18, 87)
call SaveWaveLibrary_Cargo("-00-01-06-01-01-00-00-00-01", false, 37, 88)
call SaveWaveLibrary_Normal("-00-00-00-04-00-00-00-01-00", false, 27, 89)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-02-00", true, 39, 90)
call SaveWaveLibrary_Cargo("-01-03-02-03-00-00-00-00-00", false, 30, 91)
call SaveWaveLibrary_Normal("-00-00-02-04-01-00-00-00-01", false, 36, 92)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-03-00-00", false, 13, 93)
call SaveWaveLibrary_Normal("-00-00-00-01-02-00-00-00-00", false, 15, 94)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 95)
call SaveWaveLibrary_Normal("-00-00-00-00-00-02-00-00-01", false, 21, 96)
call SaveWaveLibrary_Normal("-00-00-03-01-01-00-02-00-01", false, 34, 97)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-01-01", false, 23, 98)
call SaveWaveLibrary_Normal("-00-00-00-01-01-01-00-01-01", false, 31, 99)
call SaveWaveLibrary_Normal("-00-00-00-01-00-00-00-00-00", true, 17, 100)
call SaveWaveLibrary_Normal("-00-00-00-00-01-00-01-01-00", false, 17, 101)
call SaveWaveLibrary_Normal("-00-00-01-01-00-01-00-00-01", false, 17, 102)
call SaveWaveLibrary_Normal("-00-00-00-00-01-01-01-00-00", false, 17, 103)
call SaveWaveLibrary_Normal("-00-00-01-01-00-00-00-00-00", false, 17, 104)
call SaveWaveLibrary_Normal("-00-00-00-02-00-00-01-00-02", false, 17, 105)
call SaveWaveLibrary_Normal("-00-00-00-00-02-00-00-02-00", false, 17, 106)
call SaveWaveLibrary_Normal("-00-04-00-00-00-01-00-00-00", false, 17, 107)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-00-00-01", false, 17, 108)
call SaveWaveLibrary_Normal("-00-00-00-02-00-00-02-00-00", false, 17, 109)
call SaveWaveLibrary_Normal("-00-00-02-00-00-00-00-00-01", false, 17, 110)
call SaveWaveLibrary_Normal("-00-03-01-00-00-00-00-00-00", false, 17, 111)
call SaveWaveLibrary_Normal("-00-00-00-00-01-00-00-00-00", false, 17, 112)
call SaveWaveLibrary_Normal("-00-00-00-01-00-00-00-00-00", false, 17, 113)
call SaveWaveLibrary_Normal("-00-00-00-02-00-00-01-00-00", false, 17, 114)
call SaveWaveLibrary_Normal("-00-00-00-00-00-01-00-00-00", true, 17, 115)
call SaveWaveLibrary_Normal("-00-00-00-00-01-00-00-00-01", false, 17, 116)
call SaveWaveLibrary_Normal("-00-00-00-00-00-00-01-01-00", false, 17, 117)
call SaveWaveLibrary_Normal("-00-00-00-01-01-01-00-00-01", false, 17, 118)
call SaveWaveLibrary_Normal("-00-00-00-01-01-00-01-00-00", false, 17, 119)
call SaveWaveLibrary_Normal("-00-00-00-02-00-01-00-01-01", true, 17, 120)
call MsgDev("Library waves saved.")
call TimerStart(g_waveTimerLibrary, 19.00, false, function ZergTimerWave_Library)//1st wave
call TriggerAddAction(t, function Trig_ZergSwitchLast5min)
call TriggerExecute(t)
set t=null
endfunction
//===========================================================================
function InitTrig_WavesLibrary takes nothing returns nothing
set gg_trg_WavesLibrary = CreateTrigger( )
call TriggerAddAction( gg_trg_WavesLibrary, function Trig_WavesLibrary_Actions )
endfunction
//------------------------------------------------------------------------------------------------------------
// WAVES FOR CATHEDRAL
//------------------------------------------------------------------------------------------------------------
// ----1-----------2----------3--------------4-------------5----------6-------7-----------8-----------9----
function ZergTimerWave_Cathedral takes nothing returns nothing
if g_waveNo_C==10 and g_totalAttackers_Cathedral>4 then //for wave 10 , wait when attackers count < 4
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==20 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==30 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==40 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==50 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==60 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
elseif g_waveNo_C==70 and g_totalAttackers_Cathedral>4 then
call TimerStart(g_waveTimerCathedral, 5.00, false, function ZergTimerWave_Cathedral)
//etc..
else
call TriggerExecute(gg_trg_AttackWaveCathedral)
endif
endfunction
// overlord / zergling / hydralisk / red hydralisk / lurker / defiler / mutalisk / guardian / ultralisk
function Trig_WavesCathedral_Actions takes nothing returns nothing
call SaveWaveCathedral_Normal("-00-03-00-00-00-00-00-00-00", false, 10, 1)
call SaveWaveCathedral_Normal("-00-04-00-00-00-00-00-00-00", false, 12, 2)
call SaveWaveCathedral_Normal("-00-04-00-00-00-00-00-00-00", false, 12, 3)
call SaveWaveCathedral_Normal("-00-02-01-00-00-00-00-00-00", false, 11, 4)
call SaveWaveCathedral_Normal("-00-03-01-00-00-00-00-00-00", false, 13, 5)
call SaveWaveCathedral_Normal("-00-04-01-00-00-00-00-00-00", false, 15, 6)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-01-00-00", false, 7, 7)
call SaveWaveCathedral_Normal("-00-03-00-00-00-00-00-00-00", false, 10, 8)
call SaveWaveCathedral_Normal("-00-01-01-00-00-01-00-00-00", false, 13, 9)
call SaveWaveCathedral_Normal("-00-03-00-00-00-00-00-00-00", true, 27, 10)
call SaveWaveCathedral_Cargo("-01-01-01-01-00-00-00-00-00", false, 21, 11)
call SaveWaveCathedral_Normal("-00-02-00-00-00-00-00-00-00", false, 7, 12)
call SaveWaveCathedral_Normal("-00-02-01-00-00-00-00-00-00", false, 11, 13)
call SaveWaveCathedral_Normal("-00-00-02-00-00-00-00-00-00", false, 10, 14)
call SaveWaveCathedral_Normal("-00-00-00-00-01-00-00-00-00", false, 8, 15)
call SaveWaveCathedral_Normal("-00-00-01-00-00-00-01-00-00", false, 10, 16)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-01-00-00", false, 7, 17)
call SaveWaveCathedral_Normal("-00-01-01-00-00-00-00-00-00", false, 9, 18)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-00-01", false, 14, 19)
call SaveWaveCathedral_Normal("-00-00-01-01-00-01-00-00-00", true, 32, 20)
call SaveWaveCathedral_Normal("-00-02-01-00-00-00-00-00-00", false, 11, 21)
call SaveWaveCathedral_Normal("-00-00-02-00-00-00-00-00-00", false, 10, 22)
call SaveWaveCathedral_Normal("-00-02-00-00-00-00-01-00-00", false, 11, 23)
call SaveWaveCathedral_Normal("-00-01-00-00-01-00-00-00-00", false, 10, 24)
call SaveWaveCathedral_Normal("-01-01-01-01-00-00-00-00-00", false, 21, 25)
call SaveWaveCathedral_Normal("-00-00-00-00-00-01-00-00-00", false, 7, 26)
call SaveWaveCathedral_Normal("-01-03-00-00-00-00-00-00-00", false, 18, 27)
call SaveWaveCathedral_Normal("-00-01-01-00-00-00-00-00-00", false, 9, 28)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-00-01", false, 14, 29)
call SaveWaveCathedral_Cargo("-01-02-01-00-00-00-00-00-00", true, 36, 30)
call SaveWaveCathedral_Normal("-00-02-00-00-00-00-00-00-00", false, 7, 31)
call SaveWaveCathedral_Normal("-00-00-01-00-01-00-00-00-00", false, 11, 32)
call SaveWaveCathedral_Normal("-00-06-01-00-00-00-00-00-00", false, 20, 33)
call SaveWaveCathedral_Normal("-00-04-03-00-00-00-02-01-00", false, 40, 34)
call SaveWaveCathedral_Normal("-00-03-00-03-00-00-01-00-00", false, 27, 35)
call SaveWaveCathedral_Normal("-01-00-03-02-01-00-00-00-00", false, 35, 36)
call SaveWaveCathedral_Normal("-00-00-00-00-00-01-00-00-01", false, 19, 37)
call SaveWaveCathedral_Cargo("-01-03-04-01-00-00-00-00-00", false, 36, 38)
call SaveWaveCathedral_Normal("-00-04-00-00-00-00-02-01-00", false, 30, 39)
call SaveWaveCathedral_Normal("-00-00-01-02-00-01-00-00-01", true, 48, 40)
call SaveWaveCathedral_Normal("-00-04-01-00-00-00-00-00-00", false, 15, 41)
call SaveWaveCathedral_Normal("-00-00-03-01-00-00-00-00-00", false, 18, 42)
call SaveWaveCathedral_Normal("-00-00-02-02-00-01-00-00-00", false, 23, 43)
call SaveWaveCathedral_Normal("-00-00-00-01-01-00-01-00-00", false, 17, 44)
call SaveWaveCathedral_Normal("-00-00-01-00-00-00-00-01-00", false, 16, 45)
call SaveWaveCathedral_Normal("-00-00-00-01-00-01-00-00-01", false, 23, 46)
call SaveWaveCathedral_Cargo("-01-00-01-01-01-00-00-00-00", false, 24, 47)
call SaveWaveCathedral_Normal("-01-00-00-00-00-00-01-00-00", false, 15, 48)
call SaveWaveCathedral_Normal("-00-00-01-00-00-00-00-00-00", false, 6, 49)
call SaveWaveCathedral_Normal("-00-00-01-00-00-00-00-00-00", true, 23, 50)
call SaveWaveCathedral_Normal("-01-03-01-00-00-00-00-00-00", false, 21, 51)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 52)
call SaveWaveCathedral_Cargo("-01-01-00-00-01-00-00-00-00", false, 18, 53)
call SaveWaveCathedral_Cargo("-01-00-01-02-00-00-00-00-00", false, 23, 54)
call SaveWaveCathedral_Normal("-00-04-00-00-00-00-00-00-00", false, 12, 55)
call SaveWaveCathedral_Normal("-00-00-04-00-00-00-00-00-00", false, 17, 56)
call SaveWaveCathedral_Normal("-00-00-00-01-01-00-00-00-00", false, 13, 57)
call SaveWaveCathedral_Normal("-00-00-00-00-01-01-01-00-00", false, 17, 58)
call SaveWaveCathedral_Normal("-00-04-00-00-00-00-00-01-00", false, 22, 59)
call SaveWaveCathedral_Normal("-00-00-00-01-00-00-00-00-01", true, 36, 60)
call SaveWaveCathedral_Normal("-00-00-00-03-00-00-00-00-00", true, 34, 61)
call SaveWaveCathedral_Normal("-00-00-02-04-01-00-00-00-01", false, 44, 62)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-03-00-00", false, 15, 63)
call SaveWaveCathedral_Normal("-00-00-00-01-01-00-00-00-00", false, 13, 64)
call SaveWaveCathedral_Normal("-00-00-02-00-00-00-00-01-00", false, 20, 65)
call SaveWaveCathedral_Normal("-00-00-00-00-00-02-00-00-01", false, 23, 66)
call SaveWaveCathedral_Normal("-00-00-03-01-01-00-02-00-01", false, 42, 67)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-01", false, 24, 68)
call SaveWaveCathedral_Normal("-00-00-00-01-01-01-00-01-01", false, 38, 69)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-02-01-02", true, 60, 70)
call SaveWaveCathedral_Cargo("-01-03-02-03-00-00-00-00-00", false, 38, 71)
call SaveWaveCathedral_Normal("-00-00-02-04-01-00-00-00-01", false, 44, 72)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-03-00-00", false, 15, 73)
call SaveWaveCathedral_Normal("-00-00-00-01-02-00-00-00-00", false, 17, 74)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 75)
call SaveWaveCathedral_Normal("-00-00-00-00-00-02-00-00-01", false, 23, 76)
call SaveWaveCathedral_Normal("-00-00-03-01-01-00-02-00-01", false, 42, 77)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-01", false, 24, 78)
call SaveWaveCathedral_Normal("-00-00-00-01-01-01-00-01-01", false, 38, 79)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-04-00-00", true, 36, 80)
call SaveWaveCathedral_Normal("-00-04-04-02-00-00-00-00-00", false, 34, 81)
call SaveWaveCathedral_Cargo("-02-10-06-00-02-01-00-00-00", false, 76, 82)
call SaveWaveCathedral_Normal("-00-00-00-00-00-01-00-00-01", false, 19, 83)
call SaveWaveCathedral_Normal("-00-00-00-04-01-00-00-01-00", false, 36, 84)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-04-00-00", false, 19, 85)
call SaveWaveCathedral_Normal("-00-00-00-00-02-01-00-00-01", false, 29, 86)
call SaveWaveCathedral_Normal("-00-12-00-00-00-00-00-00-00", false, 29, 87)
call SaveWaveCathedral_Cargo("-00-01-06-01-01-00-00-00-01", false, 46, 88)
call SaveWaveCathedral_Normal("-00-00-00-04-00-00-00-01-00", false, 31, 89)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-02-00", true, 40, 90)
call SaveWaveCathedral_Cargo("-01-03-02-03-00-00-00-00-00", false, 38, 91)
call SaveWaveCathedral_Normal("-00-00-02-04-01-00-00-00-01", false, 44, 92)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-03-00-00", false, 15, 93)
call SaveWaveCathedral_Normal("-00-00-00-01-02-00-00-00-00", false, 17, 94)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-00", false, 13, 95)
call SaveWaveCathedral_Normal("-00-00-00-00-00-02-00-00-01", false, 23, 96)
call SaveWaveCathedral_Normal("-00-00-03-01-01-00-02-00-01", false, 42, 97)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-01-01", false, 24, 98)
call SaveWaveCathedral_Normal("-00-00-00-01-01-01-00-01-01", false, 35, 99)
call SaveWaveCathedral_Normal("-00-00-00-01-00-00-00-01-00", false, 17, 100)
call SaveWaveCathedral_Normal("-00-00-00-00-01-00-01-00-00", false, 17, 101)
call SaveWaveCathedral_Normal("-00-00-01-01-00-01-00-00-01", false, 17, 102)
call SaveWaveCathedral_Normal("-00-00-00-00-01-01-00-00-00", false, 17, 103)
call SaveWaveCathedral_Normal("-00-00-01-01-00-00-01-00-00", true, 17, 104)
call SaveWaveCathedral_Normal("-00-00-00-02-00-00-01-00-02", false, 17, 105)
call SaveWaveCathedral_Normal("-00-00-00-00-02-00-00-02-00", false, 17, 106)
call SaveWaveCathedral_Normal("-00-04-00-00-00-01-00-00-00", false, 17, 107)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-00-00-01", false, 17, 108)
call SaveWaveCathedral_Normal("-00-00-00-02-00-00-02-00-00", false, 17, 109)
call SaveWaveCathedral_Normal("-00-00-02-00-00-00-00-00-01", false, 17, 110)
call SaveWaveCathedral_Normal("-00-03-01-00-00-00-00-00-00", false, 17, 111)
call SaveWaveCathedral_Normal("-00-00-00-00-01-00-00-00-00", true, 17, 112)
call SaveWaveCathedral_Normal("-00-00-00-01-00-00-00-00-00", false, 17, 113)
call SaveWaveCathedral_Normal("-00-00-00-02-00-00-01-00-00", false, 17, 114)
call SaveWaveCathedral_Normal("-00-00-00-00-00-01-00-00-00", false, 17, 115)
call SaveWaveCathedral_Normal("-00-00-00-00-01-00-00-00-01", false, 17, 116)
call SaveWaveCathedral_Normal("-00-00-00-00-00-00-01-01-00", false, 17, 117)
call SaveWaveCathedral_Normal("-00-00-00-01-01-01-00-00-01", false, 17, 118)
call SaveWaveCathedral_Normal("-00-00-00-01-01-00-01-00-00", false, 17, 119)
call SaveWaveCathedral_Normal("-00-00-00-02-00-01-00-01-01", true, 17, 120)
call MsgDev("Cathedral waves saved.")
call TimerStart(g_waveTimerCathedral, 15.00, false, function ZergTimerWave_Cathedral)//1st wave
endfunction
//===========================================================================
function InitTrig_WavesCathedral takes nothing returns nothing
set gg_trg_WavesCathedral = CreateTrigger( )
call TriggerAddAction( gg_trg_WavesCathedral, function Trig_WavesCathedral_Actions )
endfunction
//----------------------------------------------------------------------------------------------------------------------
// ----1-----------2----------3--------------4-------------5----------6-------7-----------8-----------9----
// overlord / zergling / hydralisk / red hydralisk / lurker / defiler / mutalisk / guardian / ultralisk
function Trig_AttackWaveLibrary_Actions takes nothing returns nothing
local integer h_id=GetHandleId(LIBRARY)
local integer poolNo=ZergGetRandomPoolForWave_Library()
local string s=ZergLoadWave_S(h_id, g_waveNo_L)
local boolean addHero=ZergLoadWave_H(h_id, g_waveNo_L)
local boolean useCargo=ZergLoadWave_C(h_id, g_waveNo_L)
local real time=ZergLoadWave_P(h_id, g_waveNo_L)
local integer wait=0
local unit hero=null
local boolean groupLoaded=false
local group g = null
if s==null then
call BJDebugMsg("Error: Library attack wave number "+I2S(g_waveNo_L)+" not found!")
return
endif
call MsgTipAttackWave(poolNo, "Attack ("+I2S(g_waveNo_L)+") against Library detected.")
call TimerStart(g_waveTimerLibrary, time, false, function ZergTimerWave_Library)
set g_waveNo_L=g_waveNo_L+1//for next wave
if useCargo then
set g = ZergCreateGroup(ATTACK_CARGO, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
else
set g = ZergCreateGroup(ATTACK, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
endif
loop
exitwhen ZergGroup_Completed(g)
if not UnitAlive(zergSpawningPool[poolNo]) then
set wait=wait+1
exitwhen wait>30
endif
call TriggerSleepAction(1.00)
endloop
set wait=0
if not ZergGroup_Alive(g) then
return
endif
//HERO
if addHero then
set hero = ZergGetHeroToAttack()
if hero != null then
call ZergAttackGroup_AddHero(g, hero)//new, hero is inside the group, connects group <--> hero
call ZergTeleportHero(hero, GetUnitX(zergSpawningPool[poolNo]), GetUnitY(zergSpawningPool[poolNo]))//uses trigger sleep 1sec
call ZGAtt_ExecTrg(hero)
endif
endif
//CARGO
if useCargo and ZergGroup_CanBeLoaded(g) then
call ZergGroup_Load(g)
loop
if ZergGroup_IsLoaded(g) then
set groupLoaded=true
exitwhen true
endif
if wait>15 then
call ZergGroup_UnloadInstant(g)
loop
exitwhen ZergGroup_IsUnloaded(g)
call TriggerSleepAction(0.50)
endloop
exitwhen true
endif
call TriggerSleepAction(1.00)
set wait=wait+1
endloop
endif
call SaveBoolean(zergHash, GetHandleId(g), KEY_GROUP_AGAINST_LIBRARY, true)
set g_totalAttackers_Library=g_totalAttackers_Library+ZergGroup_GetCount(g)
set g_waveTarget=LIBRARY
if groupLoaded then
call MsgDev("Start AI with TRANSPORT")
set groupAI=g
set g_zergWavePickPath=false
set g_lookForNextPointWhenMove=false
call TriggerExecute(gg_trg_ZergAICargo)
else
call MsgDev("Start AI")
set groupAI=g
set g_zergWavePickPath=true
set g_lookForNextPointWhenMove=true
call TriggerExecute(gg_trg_ZergAI1)
endif
set hero=null
set g=null
endfunction
//===========================================================================
function InitTrig_AttackWaveLibrary takes nothing returns nothing
set gg_trg_AttackWaveLibrary = CreateTrigger( )
call TriggerAddAction( gg_trg_AttackWaveLibrary, function Trig_AttackWaveLibrary_Actions )
endfunction
function Trig_AttackWaveCatherdal_Actions takes nothing returns nothing
local integer h_id=GetHandleId(CATHEDRAL)
local integer poolNo=ZergGetRandomPoolForWave_Cathedral()
local string s=ZergLoadWave_S(h_id, g_waveNo_C)
local boolean addHero=ZergLoadWave_H(h_id, g_waveNo_C)
local boolean useCargo=ZergLoadWave_C(h_id, g_waveNo_C)
local real time=ZergLoadWave_P(h_id, g_waveNo_C)
local integer wait=0
local unit hero=null
local boolean groupLoaded=false
local group g = null
if s==null then
call BJDebugMsg("Error: Cathedral attack wave number "+I2S(g_waveNo_C)+" not found!")
return
endif
call MsgTipAttackWave(poolNo, "Attack ("+I2S(g_waveNo_C)+") against Cathedral detected.")
call TimerStart(g_waveTimerCathedral, time, false, function ZergTimerWave_Cathedral)
set g_waveNo_C=g_waveNo_C+1//for next wave
if useCargo then
set g = ZergCreateGroup(ATTACK_CARGO, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
else
set g = ZergCreateGroup(ATTACK, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
endif
loop
exitwhen ZergGroup_Completed(g)
if not UnitAlive(zergSpawningPool[poolNo]) then
set wait=wait+1
exitwhen wait>30
endif
call TriggerSleepAction(1.00)
endloop
set wait=0
if not ZergGroup_Alive(g) then
return
endif
//HERO
if addHero then
//alive, not teleporting, has no group and its Pool has min 50% life and Pool was not attacked over last 15sec.
set hero = ZergGetHeroToAttack()
if hero != null then
call ZergAttackGroup_AddHero(g, hero)//new, hero is inside the group, connects group <--> hero
call ZergTeleportHero(hero, GetUnitX(zergSpawningPool[poolNo]), GetUnitY(zergSpawningPool[poolNo])) //uses trigger sleep 1sec
call ZGAtt_ExecTrg(hero)
endif
endif
//CARGO
if useCargo and ZergGroup_CanBeLoaded(g) then
call ZergGroup_Load(g)
loop
if ZergGroup_IsLoaded(g) then
set groupLoaded=true
exitwhen true
endif
if wait>15 then
call ZergGroup_UnloadInstant(g)
loop
exitwhen ZergGroup_IsUnloaded(g)
call TriggerSleepAction(0.50)
endloop
exitwhen true
endif
call TriggerSleepAction(1.00)
set wait=wait+1
endloop
endif
call SaveBoolean(zergHash, GetHandleId(g), KEY_GROUP_AGAINST_LIBRARY, false)
set g_totalAttackers_Cathedral=g_totalAttackers_Cathedral+ZergGroup_GetCount(g)
set g_waveTarget=CATHEDRAL
if groupLoaded then
call MsgDev("Start AI with TRANSPORT")
set groupAI=g
set g_zergWavePickPath=false
set g_lookForNextPointWhenMove=false
call TriggerExecute(gg_trg_ZergAICargo)
else
call MsgDev("Start AI")
set groupAI=g
set g_zergWavePickPath=true
set g_lookForNextPointWhenMove=true
call TriggerExecute(gg_trg_ZergAI1)
endif
set hero=null
set g=null
endfunction
//===========================================================================
function InitTrig_AttackWaveCathedral takes nothing returns nothing
set gg_trg_AttackWaveCathedral = CreateTrigger( )
call TriggerAddAction( gg_trg_AttackWaveCathedral, function Trig_AttackWaveCatherdal_Actions )
endfunction
//========= DEFENDERS CONFIGURATION =========================
// format "-01-02-03-04-03-02-01-00-00"
// ----1-----------2----------3----------------4----------5----------6---------7-----------8----------9----
// overlord / zergling / hydralisk / red hydralisk / lurker / defiler / mutalisk / guardian / ultralisk
function SetDefendersQuantity takes nothing returns nothing
set g_str_initialDefenders[1] = "-00-02-01-00-01-00-00-00-00"
set g_str_initialDefenders[2] = "-00-02-01-00-01-00-00-00-00"
set g_str_initialDefenders[3] = "-00-02-01-00-01-00-00-00-00"
set g_str_initialDefenders[4] = "-00-02-01-00-01-00-00-00-00"
set g_str_initialDefenders[5] = "-00-02-01-00-01-00-00-00-00"
set g_str_initialDefenders[6] = "-00-02-01-00-01-00-00-00-00"
set g_str_additionalDefenders[1] = "-00-00-01-00-00-00-01-00-00"
set g_str_additionalDefenders[2] = "-00-00-01-00-00-00-01-00-00"
set g_str_additionalDefenders[3] = "-00-00-01-00-00-00-01-00-00"
set g_str_additionalDefenders[4] = "-00-00-01-00-00-00-01-00-00"
set g_str_additionalDefenders[5] = "-00-00-01-00-00-00-01-00-00"
set g_str_additionalDefenders[6] = "-00-00-01-00-00-00-01-00-00"
endfunction
//===============================================================
globals
string array g_str_initialDefenders // [pool no]
string array g_str_additionalDefenders // [pool no]
integer g_zergDefTempNo=0
group array g_zergDefendersGroup
endglobals
//------------------------------------------------------------------------------------------------------------
function Zerg_CreateAdditionalDefenders takes integer poolNo returns nothing
local string s=g_str_additionalDefenders[poolNo]
local group g = ZergCreateGroup(DEFENCE, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
set groupAI=g
call TriggerExecute(gg_trg_ZergAIdefend)
set g=null
endfunction
//------------------------------------------------------------------------------------------------------------
function Zerg_CreateInitialDefenders takes integer poolNo returns nothing
local string s=g_str_initialDefenders[poolNo]
local group g = ZergCreateGroup(DEFENCE, zergSpawningPool[poolNo], ZC(s,1), ZC(s,2), ZC(s,3), ZC(s,4), ZC(s,5), ZC(s,6), ZC(s,7), ZC(s,8), ZC(s,9))
set g_zergDefendersGroup[poolNo] = g
set groupAI=g
call TriggerExecute(gg_trg_ZergAIdefend)
set g=null
endfunction
//------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------
function Trig_InitialDefenders_Actions takes nothing returns nothing
call Zerg_CreateInitialDefenders(1)
call Zerg_CreateInitialDefenders(2)
call Zerg_CreateInitialDefenders(3)
call Zerg_CreateInitialDefenders(4)
endfunction
//===========================================================================
function InitTrig_ZergDefenders takes nothing returns nothing
set gg_trg_ZergDefenders = CreateTrigger( )
call TriggerAddAction( gg_trg_ZergDefenders, function Trig_InitialDefenders_Actions )
call SetDefendersQuantity()
endfunction
function Trig_ZergCreateHeroes_Actions takes nothing returns nothing
local integer x=0
//it runs at map init so UnitUserData should be set
set g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_BEAST)]=false
set g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_SLAYER)]=false
set g_zergHeroTeleporting[GetUnitUserData(ZERG_HERO_QUEEN)]=false
call SetUnitOwner(ZERG_HERO_BEAST, PLAYER_ZERG, true)
call SetUnitOwner(ZERG_HERO_SLAYER, PLAYER_ZERG, true)
call SetUnitOwner(ZERG_HERO_QUEEN, PLAYER_ZERG, true)
call SuspendHeroXP(ZERG_HERO_BEAST, true) // disable expirience gain
call SuspendHeroXP(ZERG_HERO_SLAYER, true) // disable expirience gain
call SuspendHeroXP(ZERG_HERO_QUEEN, true) // disable expirience gain
set x=ZergGetRandomPoolForHero()
call SetUnitPositionLoc(ZERG_HERO_BEAST, zergPoolLoc[x])
call ZergHero_ConnectPool(ZERG_HERO_BEAST, x)
set x=ZergGetRandomPoolForHero()
call SetUnitPositionLoc(ZERG_HERO_SLAYER, zergPoolLoc[x])
call ZergHero_ConnectPool(ZERG_HERO_SLAYER, x)
set x=ZergGetRandomPoolForHero()
call SetUnitPositionLoc(ZERG_HERO_QUEEN, zergPoolLoc[x])
call ZergHero_ConnectPool(ZERG_HERO_QUEEN, x)
endfunction
//===========================================================================
function InitTrig_ZergCreateHeroes takes nothing returns nothing
set gg_trg_ZergCreateHeroes = CreateTrigger( )
call TriggerAddAction( gg_trg_ZergCreateHeroes, function Trig_ZergCreateHeroes_Actions )
endfunction
//--------------------------------------------------------------------------------------------------
//-----------one "call for help" for each Pool --------------------------------------------------
//--------------------------------------------------------------------------------------------------
function Trig_ZergInspectPool takes nothing returns nothing
local integer x=1
local boolean array used // initial is"false"
local real limit=GetUnitState(zergSpawningPool[1], UNIT_STATE_MAX_LIFE) * 0.25
loop
exitwhen GAME_OVER
set x=1
loop
exitwhen x>6
if (not used[x]) and UnitAlive(zergSpawningPool[x]) and (not IsUnitHidden(zergSpawningPool[x])) then
if GetWidgetLife(zergSpawningPool[x]) < limit then
call MsgDev("Pool no ("+I2S(x)+") is calling for help.")
set used[x]=true
call Zerg_CreateAdditionalDefenders(x)
endif
endif
set x=x+1
endloop
call TriggerSleepAction(5.00)
endloop
endfunction
//===========================================================================
function InitTrig_InspectPools takes nothing returns nothing
set gg_trg_InspectPools = CreateTrigger( )
call TriggerAddAction( gg_trg_InspectPools, function Trig_ZergInspectPool )
endfunction
function Trig_ExpansionPools_10min takes nothing returns nothing
if (not GAME_OVER) then
call ShowUnit(zergSpawningPool[5], true)
call SetBlightLoc(PLAYER_ZERG, zergPoolLoc[5], 728.00, true)
call Zerg_CreateInitialDefenders(5)
call ShowUnit(zergSpawningPool[6], true)
call SetBlightLoc(PLAYER_ZERG, zergPoolLoc[6], 728.00, true)
call Zerg_CreateInitialDefenders(6)
call MsgAll("|c00FF0000Two new Zerg Spawning Pools were born!|r")
call PingMinimapEx(GetUnitX(zergSpawningPool[5]), GetUnitY(zergSpawningPool[5]), 4.00, 255, 0, 0, false)
call PingMinimapEx(GetUnitX(zergSpawningPool[6]), GetUnitY(zergSpawningPool[6]), 4.00, 255, 0, 0, false)
endif
endfunction
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
function Trig_ExpansionPools_Actions takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterTimerEvent(t, 600.00, false) //10 min
call TriggerAddAction(t, function Trig_ExpansionPools_10min)
set t=null
endfunction
//===========================================================================
function InitTrig_ExpansionPools takes nothing returns nothing
set gg_trg_ExpansionPools = CreateTrigger( )
call TriggerAddAction(gg_trg_ExpansionPools, function Trig_ExpansionPools_Actions)
endfunction
function Trig_tst1_Actions takes nothing returns nothing
local unit u=gg_unit_u001_0022
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local unit dummy=CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE), DUMMY, x, y, 0.00)
call UnitAddAbility(dummy, 'Adt1')
call TriggerSleepAction(1.00)
// silenced , snared , cycloned , rooted , stunned , slowed etc
//test procerure
//1. casted enemy spell
//2. issued order to move/attack-move/burrow/unburrow
//stun
call UnitAddAbility(dummy, 'ACfb') //Issue unburrow returns true
call IssueTargetOrder(dummy, "firebolt", u)
//zerg will resume order like burrow/move/attack-move after stun expires
//cyclone
//call UnitAddAbility(dummy, 'ACcy')
//call IssueTargetOrder(dummy, "cyclone", u)
//cannot cyclone burrowed unit
//Issue burrow returns true , unit will resume order like burrow/move/attack-move after it lands on the ground.
//ensnare
//call UnitAddAbility(dummy, 'ACen')
//call IssueTargetOrder(dummy, "ensnare", u)// cannot ensnare burrowed unit
//snared unit will NOT resume orded burrow after ensnare-buff expires, //Issue unburrow returns false
//Issue move or attack-move returns true. snared unit will resume move, attack-move order after ensnare-buff expires
//silence
//call UnitAddAbility(dummy, 'ACsi')
//call IssuePointOrder(dummy, "silence", x, y) //Issue unburrow returns false
//silenced unit will NOT resume orded after silence-buff expires
//Issue move, attack-move returns true: silenced unit will move of cource
//root
//call UnitAddAbility(dummy, 'Aenr') //Issue unburrow returns false
//call IssueTargetOrder(dummy, "entanglingroots", u)
//zerg will NOT resume order after roots expires
//Issue move, attack-move returns true: rooted unit will resume move, attack-move order after roots-buff expires
call TriggerSleepAction(2.00)
call KillUnit(dummy)
if IssuePointOrderById(u, ORDER_attack, 0, 0) then
call MsgDev("issued move: true")
else
call MsgDev("issued move: false")
endif
set u=null
endfunction
//===========================================================================
function InitTrig_tst1 takes nothing returns nothing
set gg_trg_tst1 = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_tst1, Player(0), "sil", true )
call TriggerAddAction( gg_trg_tst1, function Trig_tst1_Actions )
endfunction
function Trig_runningBehaviourTest_Actions takes nothing returns nothing
local integer i=1 // i = UnitUserData
local integer count=0
local integer countO=0
local integer countZ=0
local integer countU=0
local integer countG=0
local integer countL=0
local integer countD=0
local integer countH=0
local integer countHeroBeast=0
local integer countHeroSlayer=0
local integer countHeroQueen=0
local integer unitId
local string s=""
loop //through all units in map
exitwhen i>udg_UDexMax
if g_zergBehaviourTrgRunning[i] then
set unitId=GetUnitTypeId(udg_UDexUnits[i])
if unitId==ZERG_OVERLORD then
set countO=countO+1
elseif unitId==ZERG_ZERGLING or unitId==ZERG_BURROW_ZERGLING then
set countZ=countZ+1
elseif unitId==ZERG_ULTRALISK then
set countU=countU+1
elseif unitId==ZERG_GUARDIAN then
set countG=countG+1
elseif unitId==ZERG_LURKER or unitId==ZERG_BURROW_LURKER then
set countL=countL+1
elseif unitId==ZERG_DEFILER or unitId==ZERG_BURROW_DEFILER then
set countD=countD+1
elseif unitId==ZERG_HYDRALISK or unitId==ZERG_BURROW_HYDRALISK then
set countH=countH+1
elseif unitId==ZERG_RED_HYDRALISK or unitId==ZERG_BURROW_RED_HYDRALISK then
set countH=countH+1
elseif unitId=='U009' then
set countHeroBeast=countHeroBeast+1
elseif unitId=='N003' then
set countHeroSlayer=countHeroSlayer+1
elseif unitId=='U006' then
set countHeroQueen=countHeroQueen+1
endif
set count=count+1
endif
set i=i+1
endloop
call MsgDev("Behaviour triggers running: "+I2S(count))
set s=" O("+I2S(countO)+") Z("+I2S(countZ)+") U("+I2S(countU)+") G("+I2S(countG)+") L("+I2S(countL)+") D("+I2S(countD)+") H("+I2S(countH)+")"
set s=s+" .. Beast("+I2S(countHeroBeast)+") Slayer("+I2S(countHeroSlayer)+") Queen("+I2S(countHeroQueen)+")"
call MsgDev(s)
endfunction
//===========================================================================
function InitTrig_runningBehaviourTest takes nothing returns nothing
set gg_trg_runningBehaviourTest = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_runningBehaviourTest, Player(0), "beh", true )
call TriggerAddAction( gg_trg_runningBehaviourTest, function Trig_runningBehaviourTest_Actions )
endfunction
function Trig_cheat1_Actions takes nothing returns nothing
call SetHeroLevel(g_hero[0], 10, true)
call SetHeroLevel(g_hero[1], 10, true)
call SetHeroLevel(g_hero[2], 10, true)
call SetHeroLevel(g_hero[3], 10, true)
call SetWidgetLife(g_hero[0], BlzGetUnitMaxHP(g_hero[0]))
call SetWidgetLife(g_hero[1], BlzGetUnitMaxHP(g_hero[1]))
call SetWidgetLife(g_hero[2], BlzGetUnitMaxHP(g_hero[2]))
call SetWidgetLife(g_hero[3], BlzGetUnitMaxHP(g_hero[3]))
endfunction
//===========================================================================
function InitTrig_cheat1 takes nothing returns nothing
set gg_trg_cheat1 = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_cheat1, Player(0), "hero", true )
call TriggerRegisterPlayerChatEvent( gg_trg_cheat1, Player(1), "hero", true )
call TriggerRegisterPlayerChatEvent( gg_trg_cheat1, Player(2), "hero", true )
call TriggerRegisterPlayerChatEvent( gg_trg_cheat1, Player(3), "hero", true )
call TriggerAddAction( gg_trg_cheat1, function Trig_cheat1_Actions )
endfunction
function Trig_DemoSorter_Actions takes nothing returns nothing
local integer array arr
local integer i=0
local string s
set arr[0]=GetRandomInt(1,100)
set arr[1]=GetRandomInt(1,100)
set arr[2]=GetRandomInt(1,100)
set arr[3]=GetRandomInt(1,100)
call BJDebugMsg(I2S(arr[0])+", "+I2S(arr[1])+", "+I2S(arr[2])+", "+I2S(arr[3])+", ")
//Transfer the unsorted array to mergeSortValues array
set i=0 //start index
loop
exitwhen i > 3 //end index
set MSort_Values[i] = arr[i]
set MSort_IndexInitial[i] = i
set i = i + 1
endloop
call TriggerSleepAction(2.00)
//sort:
//Tells the system to starting sorting at index 0 , and to end sorting at index 3
call MSort_Merge_Sort(0, 3, false) // "true = rosnaco, false=malejaco"
set s=R2S(MSort_Values[0])+" ("+I2S(MSort_Indices[0])+") "
set s=s+R2S(MSort_Values[1])+" ("+I2S(MSort_Indices[1])+") "
set s=s+R2S(MSort_Values[2])+" ("+I2S(MSort_Indices[2])+") "
set s=s+R2S(MSort_Values[3])+" ("+I2S(MSort_Indices[3])+") "
call BJDebugMsg(s)
endfunction
//===========================================================================
function InitTrig_DemoSorter takes nothing returns nothing
set gg_trg_DemoSorter = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_DemoSorter, Player(0), "s", true )
call TriggerAddAction( gg_trg_DemoSorter, function Trig_DemoSorter_Actions )
endfunction
scope test
globals
private group iterator=CreateGroup()
private group swap=CreateGroup()
private group temp
endglobals
private function fgSwap takes nothing returns nothing
local unit FoG
loop
set FoG=FirstOfGroup(iterator)
exitwhen FoG==null
//
call GroupAddUnit(swap,FoG)
call GroupRemoveUnit(iterator,FoG)
endloop
set temp=iterator
set iterator=swap
set swap=temp
endfunction
endscope
//my try
function GroupRemoveDeadUnits takes group g returns nothing
local unit FoG=null
loop
set FoG=FirstOfGroup(g)
exitwhen FoG==null
//
if UnitAlive(FoG) then // do not add dead or removed units
call GroupAddUnit(g_swapGroup,FoG)
endif
call GroupRemoveUnit(g,FoG)
endloop
set g_tempGroup=g
set g=g_swapGroup
set g_swapGroup=g_tempGroup
endfunction
//===========================================================================
function InitTrig_SwapGroupMethod takes nothing returns nothing
set gg_trg_SwapGroupMethod = CreateTrigger( )
endfunction
function Trig_CheckOrder_Actions takes nothing returns nothing
local integer h = GetHandleId(GetTriggerEventId())
local integer ord = GetIssuedOrderId()
if h==38 then
call DisplayTextToPlayer(GetLocalPlayer(), 0.00, 0.00, "instant " + I2S(ord) + ", " + OrderId2StringBJ(ord))
elseif h==39 then
call DisplayTextToPlayer(GetLocalPlayer(), 0.00, 0.00, "point " + I2S(ord) + ", " + OrderId2StringBJ(ord))
elseif h==40 then
call DisplayTextToPlayer(GetLocalPlayer(), 0.00, 0.00, "target " + I2S(ord) + ", " + OrderId2StringBJ(ord))
endif
endfunction
//===========================================================================
function InitTrig_CheckOrder takes nothing returns nothing
set gg_trg_CheckOrder = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_CheckOrder, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_CheckOrder, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_CheckOrder, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
call TriggerAddAction( gg_trg_CheckOrder, function Trig_CheckOrder_Actions )
endfunction
/*
MODELS:
Cathedral Submitted by Mike
Brutal Lord Submitted by Tarrasque
Nerubian Slayer Submitted by Tarrasque
Prime Matron Submitted by dickxunder
Library Submitted by Mr. Bob
Barrel Submitted by Sunchips
Barrel Submitted by communist_orc
Basket of Potatoes Submitted by Blood Raven
Beer Attachment by chilla_killa Submitted by chilla_killa
Dwarven Worker Submitted by IamMclovin
Egg Nest _ By JhOtAm Submitted by Jhotam_3Dcool&create
Haunch Submitted by HerrDave
Laborer Submitted by Dionesiist
VrykulWorker Submitted by Sellenisko
WoodBig Submitted by Ergius
Wooden Fishing Rod Submitted by MeteORA
Defiler final Submitted by killst4r
Crypt Drone Cocoon Submitted by AndrewOverload519
Guardian Submitted by RedClaw
Hydralisk Submitted by killst4r
Zerg Lurker Submitted by Cavman
Zerg Mutalisk Submitted by Cavman
some zerg models by Kam
Nerubian Devourer Submitted by Tarrasque
Market Stand [Variation3] Submitted by Ribenamania
MAP TEMPLATE
https://www.hiveworkshop.com/bundles/river-town-template.235636/
name: River Town Template, author: finlandman_co
SYSTEMS
GUI Unit Event by Bribe, version 2.5.2.0
Filtering System's API v3.4.0 by The Wrecker
GUI-Friendly Damage Detection -- v1.2.1 -- by Weep
library ORDER
library WorldBounds v2.0.0.0
IsDestructableTree by BPower
TerrainPathability BY: Rising_Dusk
Merge Sort [GUI Friendly] v1.01 by Flux
BonusMod by: Earth-Fury, Based on the work of: weaaddar, modified by Pyrogasm
MovementModifier ver 1.07 by ZibiTheWand3r3r, 18-08-2018
KnockbackSimple by ZibiTheWand3r3r v.1.03
Player Resources Monitoring ver 1.01 by ZibiTheWand3r3r
BTN
PeeKay, Illidan_09, CRAZYRUSSIAN, lllLSDlll
*/
/*
Claws and Sword cost the same and give the same damage but the sword also gives Critical Strike.
You right, I rised Sword price to 320gold.
Mutalisks should shoot glaives which could bounce later on like that of the huntress.
changed missile from Abilities\Weapons\FireBallMissile\FireBallMissile.mdl to
Abilities\Weapons\SentinelMissile\SentinelMissile.mdl
(they already had bounce)
Maybe make bosses have more interesting things to do, spells and all. I mean, they are the same always.
They have 3 active spells and 1 passive(aura).
Can't call more than 4 marksmen at a time (per player) and they all appear near the cathedral?
Players can vote for building that needs protection (obelisk ability).
You could call the red hydralisk Hunter Killer.
Changed name Red Hydralisk to Hunter Killer (good name btw)
No more hero progression after level 10 and there's almost a quarter of the game left.
For 2 tandems max 10 level will be achieved after about 25min (after 75th wave).
Two heroes defend Library and other two - Cathedral.
If player with one hero 10th level will be to fast. (no global expirience distribution)
Firebolt needs more mana than Storm Bolt and deals less damage for the same stun time. The cooldown is also bigger.
Firebolt changed.
Who is Kain in StarCraft :p? He's new bad demon with spider's gene:)
Maybe Nydus Worm/Canal instead of Spawning Pool?
These are transporting units while Spawning Pools create eggs.
https://youtu.be/7mFrz7udEqA
*/