//TESH.scrollpos=368
//TESH.alwaysfold=0
//==============================================================================================//
// WARNING: YOU MUST PASTE THE FOLLOWING CODE IN A PLACE WHERE YOUR "INITIALIZATION TRIGGER"... //
// IS CAPABLE OF ACCESSING IT. IT'S RECOMMENDED THAT YOU PASTE IT IN YOUR MAP HEADER //
// //
// The main purpose of this is to just get rid of the bug where custom units flagged as //
// town hall doesn't count for the CripplePlayer function. I also removed a few leaks generated //
// by Blizzard. //
// //
//==============================================================================================//
// Count units flagged as UNIT_TYPE_TOWNHALL
function GetAllyKeyStructureCount takes player whichPlayer returns integer
local unit fog = null
local group g = CreateGroup()
local integer result = 0
local integer playerIndex = 0
loop
exitwhen playerIndex == bj_MAX_PLAYERS
if PlayersAreCoAllied(whichPlayer, Player(playerIndex)) then
call GroupEnumUnitsOfPlayer(g, Player(playerIndex), null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
call GroupRemoveUnit(g, fog)
if IsUnitType(fog, UNIT_TYPE_TOWNHALL) and not IsUnitType(fog, UNIT_TYPE_DEAD) and GetUnitTypeId(fog) != 0 then
set result = result + 1
endif
endloop
endif
set playerIndex = playerIndex + 1
endloop
call DestroyGroup(g)
set g = null
return result
endfunction
function CheckForVictors takes force opponentlessPlayers returns force
local integer playerIndex
local integer opponentIndex
local boolean gameOver = false
// Check to see if any players have opponents remaining.
set playerIndex = 0
loop
if (not bj_meleeDefeated[playerIndex]) then
// Determine whether or not this player has any remaining opponents.
set opponentIndex = 0
loop
// If anyone has an opponent, noone can be victorious yet.
if MeleePlayerIsOpponent(playerIndex, opponentIndex) then
call DestroyForce(opponentlessPlayers)
set opponentlessPlayers = null
return null
endif
set opponentIndex = opponentIndex + 1
exitwhen opponentIndex == bj_MAX_PLAYERS
endloop
// Keep track of each opponentless player so that we can give
// them a victory later.
call ForceAddPlayer(opponentlessPlayers, Player(playerIndex))
set gameOver = true
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
// Set the game over global flag
set bj_meleeGameOver = gameOver
return opponentlessPlayers
endfunction
// Find opponentless players
function CheckForLosersAndVictors takes nothing returns nothing
local integer playerIndex
local player indexPlayer
local force defeatedPlayers = CreateForce()
local force victoriousPlayers = null
local boolean gameOver = false
// If the game is already over, do nothing
if (bj_meleeGameOver) then
return
endif
// If the game was disconnected then it is over, in this case we
// don't want to report results for anyone as they will most likely
// conflict with the actual game results
if (GetIntegerGameState(GAME_STATE_DISCONNECTED) != 0) then
set bj_meleeGameOver = true
return
endif
// Check each player to see if he or she has been defeated yet.
set playerIndex = 0
loop
set indexPlayer = Player(playerIndex)
if (not bj_meleeDefeated[playerIndex] and not bj_meleeVictoried[playerIndex]) then
//call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "Player"+I2S(playerIndex)+" has "+I2S(MeleeGetAllyStructureCount(indexPlayer))+" ally buildings.")
if (MeleeGetAllyStructureCount(indexPlayer) <= 0) then
// Keep track of each defeated player so that we can give
// them a defeat later.
call ForceAddPlayer(defeatedPlayers, Player(playerIndex))
// Set their defeated flag now so MeleeCheckForVictors
// can detect victors.
set bj_meleeDefeated[playerIndex] = true
endif
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
// Now that the defeated flags are set, check if there are any victors
set victoriousPlayers = CheckForVictors(CreateForce())
// Defeat all defeated players
call ForForce(defeatedPlayers, function MeleeDoDefeatEnum)
// Give victory to all victorious players
call ForForce(victoriousPlayers, function MeleeDoVictoryEnum)
// If the game is over we should remove all observers
if (bj_meleeGameOver) then
call MeleeRemoveObservers()
endif
// Destroy and null handles
call DestroyForce(defeatedPlayers)
if victoriousPlayers != null then
call DestroyForce(victoriousPlayers)
set victoriousPlayers = null
endif
set defeatedPlayers = null
set indexPlayer = null
endfunction
// CRIPPLE
function CheckForCrippledPlayers takes nothing returns nothing
local integer playerIndex
local player indexPlayer
local boolean isNowCrippled
// The "finish soon" exposure of all players overrides any "crippled" exposure
if bj_finishSoonAllExposed then
return
endif
// Check each player to see if he or she has been crippled or uncrippled.
set playerIndex = 0
loop
set indexPlayer = Player(playerIndex)
set isNowCrippled = (MeleeGetAllyStructureCount(indexPlayer) > 0) and (GetAllyKeyStructureCount(indexPlayer) <= 0)
if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then
// Player became crippled; start their cripple timer.
set bj_playerIsCrippled[playerIndex] = true
call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeout)
if (GetLocalPlayer() == indexPlayer) then
// Use only local code (no net traffic) within this block to avoid desyncs.
// Show the timer window.
call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)
// Display a warning message.
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, MeleeGetCrippledWarningMessage(indexPlayer))
endif
elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then
// Player became uncrippled; stop their cripple timer.
set bj_playerIsCrippled[playerIndex] = false
call PauseTimer(bj_crippledTimer[playerIndex])
if (GetLocalPlayer() == indexPlayer) then
// Use only local code (no net traffic) within this block to avoid desyncs.
// Hide the timer window for this player.
call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)
// Display a confirmation message if the player's team is still alive.
if (MeleeGetAllyStructureCount(indexPlayer) > 0) then
if (bj_playerIsExposed[playerIndex]) then
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))
else
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))
endif
endif
endif
// If the player granted shared vision, deny that vision now.
call MeleeExposePlayer(indexPlayer, false)
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
set indexPlayer = null
endfunction
// UNIT DIES
function TriggerActionCheckLostUnit takes nothing returns nothing
if IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) then
// We only need to check for mortality if this was the last building.
if (GetPlayerStructureCount(GetOwningPlayer(GetTriggerUnit()), true) <= 0) then
call CheckForLosersAndVictors()
endif
// Check if the lost unit has crippled or uncrippled the player.
// (A team with 0 units is dead, and thus considered uncrippled.)
call CheckForCrippledPlayers()
endif
endfunction
function TriggerActionAllianceChange takes nothing returns nothing
call CheckForLosersAndVictors()
call CheckForCrippledPlayers()
endfunction
function TriggerActionCheckAddedUnit takes nothing returns nothing
// If the player was crippled, this unit may have uncrippled him/her.
if (bj_playerIsCrippled[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]) then
call CheckForCrippledPlayers()
endif
endfunction
function TriggerActionPlayerDefeated takes nothing returns nothing
local player thePlayer = GetTriggerPlayer()
call CachePlayerHeroData(thePlayer)
if (MeleeGetAllyCount(thePlayer) > 0) then
// If at least one ally is still alive and kicking, share units with
// them and proceed with death.
call ShareEverythingWithTeam(thePlayer)
if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
call MeleeDoDefeat(thePlayer)
endif
else
// If no living allies remain, swap all units and buildings over to
// neutral_passive and proceed with death.
call MakeUnitsPassiveForTeam(thePlayer)
if (not bj_meleeDefeated[GetPlayerId(thePlayer)]) then
call MeleeDoDefeat(thePlayer)
endif
endif
call CheckForLosersAndVictors()
set thePlayer = null
endfunction
function TriggerActionPlayerLeft takes nothing returns nothing
local player thePlayer = GetTriggerPlayer()
// Just show game over for observers when they leave
if (IsPlayerObserver(thePlayer)) then
call RemovePlayerPreserveUnitsBJ(thePlayer, PLAYER_GAME_RESULT_NEUTRAL, false)
set thePlayer = null
return
endif
call CachePlayerHeroData(thePlayer)
// This is the same as defeat except the player generates the message
// "player left the game" as opposed to "player was defeated".
if (MeleeGetAllyCount(thePlayer) > 0) then
// If at least one ally is still alive and kicking, share units with
// them and proceed with death.
call ShareEverythingWithTeam(thePlayer)
call MeleeDoLeave(thePlayer)
else
// If no living allies remain, swap all units and buildings over to
// neutral_passive and proceed with death.
call MakeUnitsPassiveForTeam(thePlayer)
call MeleeDoLeave(thePlayer)
endif
call CheckForLosersAndVictors()
set thePlayer = null
endfunction
function MeleeVictoryDefeat takes nothing returns nothing
local trigger trig
local integer index
local player indexPlayer
// Create a timer window for the "finish soon" timeout period, it has no timer
// because it is driven by real time (outside of the game state to avoid desyncs)
set bj_finishSoonTimerDialog = CreateTimerDialog(null)
// Set a trigger to fire when we receive a "finish soon" game event
set trig = CreateTrigger()
call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)
call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)
// Set a trigger to fire when we receive a "finish now" game event
set trig = CreateTrigger()
call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)
call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)
// Set up each player's mortality code.
set index = 0
loop
set indexPlayer = Player(index)
// Make sure this player slot is playing.
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set bj_meleeDefeated[index] = false
set bj_meleeVictoried[index] = false
// Create a timer and timer window in case the player is crippled.
set bj_playerIsCrippled[index] = false
set bj_playerIsExposed[index] = false
set bj_crippledTimer[index] = CreateTimer()
set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])
call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))
// Set a trigger to fire whenever a building is cancelled for this player.
set trig = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
call TriggerAddAction(trig, function TriggerActionCheckLostUnit)
// Set a trigger to fire whenever a unit dies for this player.
call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddAction(trig, function TriggerActionCheckLostUnit)
// Set a trigger to fire whenever a unit begins construction for this player
set trig = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(trig, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
call TriggerAddAction(trig, function TriggerActionCheckAddedUnit)
// Set a trigger to fire whenever this player defeats-out
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)
call TriggerAddAction(trig, function TriggerActionPlayerDefeated)
// Set a trigger to fire whenever this player leaves
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
call TriggerAddAction(trig, function TriggerActionPlayerLeft)
// Set a trigger to fire whenever this player changes his/her alliances.
set trig = CreateTrigger()
call TriggerRegisterPlayerAllianceChange(trig, indexPlayer, ALLIANCE_PASSIVE)
call TriggerRegisterPlayerStateEvent(trig, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)
call TriggerAddAction(trig, function TriggerActionAllianceChange)
else
set bj_meleeDefeated[index] = true
set bj_meleeVictoried[index] = false
// Handle leave events for observers
if (IsPlayerObserver(indexPlayer)) then
// Set a trigger to fire whenever this player leaves
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
call TriggerAddAction(trig, function TriggerActionPlayerLeft)
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
// Test for victory / defeat at startup, in case the user has already won / lost.
// Allow for a short time to pass first, so that the map can finish loading.
call TimerStart(CreateTimer(), 2.0, false, function TriggerActionAllianceChange)
endfunction
//==============================================================================================//
native GetUnitGoldCost takes integer unitid returns integer
native GetUnitWoodCost takes integer unitid returns integer
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// EOT System header file
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function ConvertAttackTypeReverse takes attacktype at returns integer
if at == ATTACK_TYPE_NORMAL then
return 0
elseif at == ATTACK_TYPE_MELEE then
return 1
elseif at == ATTACK_TYPE_PIERCE then
return 2
elseif at == ATTACK_TYPE_SIEGE then
return 3
elseif at == ATTACK_TYPE_MAGIC then
return 4
elseif at == ATTACK_TYPE_CHAOS then
return 5
elseif at == ATTACK_TYPE_HERO then
return 6
endif
return 0
endfunction
function ConvertDamageTypeReverse takes damagetype dt returns integer
if dt == DAMAGE_TYPE_UNKNOWN then
return 0
elseif dt == DAMAGE_TYPE_NORMAL then
return 4
elseif dt == DAMAGE_TYPE_ENHANCED then
return 5
elseif dt == DAMAGE_TYPE_FIRE then
return 8
elseif dt == DAMAGE_TYPE_COLD then
return 9
elseif dt == DAMAGE_TYPE_LIGHTNING then
return 10
elseif dt == DAMAGE_TYPE_POISON then
return 11
elseif dt == DAMAGE_TYPE_DISEASE then
return 12
elseif dt == DAMAGE_TYPE_DIVINE then
return 13
elseif dt == DAMAGE_TYPE_MAGIC then
return 14
elseif dt == DAMAGE_TYPE_SONIC then
return 15
elseif dt == DAMAGE_TYPE_ACID then
return 16
elseif dt == DAMAGE_TYPE_FORCE then
return 17
elseif dt == DAMAGE_TYPE_DEATH then
return 18
elseif dt == DAMAGE_TYPE_MIND then
return 19
elseif dt == DAMAGE_TYPE_PLANT then
return 20
elseif dt == DAMAGE_TYPE_DEFENSIVE then
return 21
elseif dt == DAMAGE_TYPE_DEMOLITION then
return 22
elseif dt == DAMAGE_TYPE_SLOW_POISON then
return 23
elseif dt == DAMAGE_TYPE_SPIRIT_LINK then
return 24
elseif dt == DAMAGE_TYPE_SHADOW_STRIKE then
return 25
elseif dt == DAMAGE_TYPE_UNIVERSAL then
return 26
endif
return 0
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// EOT System header file
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Reset all variables to null.
function EOT_Set_Default_Variables takes nothing returns nothing
set udg_EOT_Param_Source = null
set udg_EOT_Param_Target = null
set udg_EOT_Param_Duration = 0.
set udg_EOT_Param_Remaining_Duration = -1.
set udg_EOT_Param_Interval = 0.
set udg_EOT_Param_Remaining_Interval = -1.
set udg_EOT_Param_Hidden = false
set udg_EOT_Param_Buff = 0
set udg_EOT_Param_Buff_Holder = 0
set udg_EOT_Param_Buff_Holder_Level = 1
set udg_EOT_Param_Ability = 0
set udg_EOT_Param_Ability_Level = 1
set udg_EOT_Param_Type = 0
set udg_EOT_Param_Subtype = 0
set udg_EOT_Param_Subtype2 = 0
set udg_EOT_Param_Positive = false
set udg_EOT_Param_Can_Dispell = true
set udg_EOT_Param_Is_Passive = false
//set udg_EOT_Param_Is_Paused = false
set udg_EOT_Param_Special_Effect = null
set udg_EOT_Param_Special_Effect_Model = ""
set udg_EOT_Param_Special_Effect_Point = ""
set udg_EOT_Event_Null_Variables = 1
set udg_EOT_Event_Null_Variables = 0
endfunction
//Save an EOT in the cache.
function EOT_Save_To_Cache takes integer cacheId returns nothing
call SaveUnitHandle( udg_EOT_Hashtable, cacheId + 100, 1000, udg_EOT_Param_Source)
call SaveUnitHandle( udg_EOT_Hashtable, cacheId + 100, 1001, udg_EOT_Param_Target)
call SaveReal( udg_EOT_Hashtable, cacheId + 100, 1002, udg_EOT_Param_Duration)
call SaveReal( udg_EOT_Hashtable, cacheId + 100, 1003, udg_EOT_Param_Remaining_Duration)
call SaveReal( udg_EOT_Hashtable, cacheId + 100, 1004, udg_EOT_Param_Interval)
call SaveReal( udg_EOT_Hashtable, cacheId + 100, 1005, udg_EOT_Param_Remaining_Interval)
call SaveBoolean( udg_EOT_Hashtable, cacheId + 100, 1006, udg_EOT_Param_Hidden)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1007, udg_EOT_Param_Buff)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1008, udg_EOT_Param_Buff_Holder)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1009, udg_EOT_Param_Buff_Holder_Level)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1010, udg_EOT_Param_Ability)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1011, udg_EOT_Param_Ability_Level)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1012, udg_EOT_Param_Type)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1013, udg_EOT_Param_Subtype)
call SaveInteger( udg_EOT_Hashtable, cacheId + 100, 1014, udg_EOT_Param_Subtype2)
call SaveBoolean( udg_EOT_Hashtable, cacheId + 100, 1015, udg_EOT_Param_Positive)
call SaveBoolean( udg_EOT_Hashtable, cacheId + 100, 1016, udg_EOT_Param_Can_Dispell)
call SaveBoolean( udg_EOT_Hashtable, cacheId + 100, 1017, udg_EOT_Param_Is_Passive)
//call SaveBoolean( udg_EOT_Hashtable, cacheId + 100, 1018, udg_EOT_Param_Is_Paused)
call SaveEffectHandle( udg_EOT_Hashtable, cacheId + 100, 1019, udg_EOT_Param_Special_Effect)
call SaveStr( udg_EOT_Hashtable, cacheId + 100, 1020, udg_EOT_Param_Special_Effect_Model)
call SaveStr( udg_EOT_Hashtable, cacheId + 100, 1021, udg_EOT_Param_Special_Effect_Point)
endfunction
//Load an EOT from the cache.
function EOT_Load_From_Cache takes integer cacheId returns nothing
set udg_EOT_Param_Source = LoadUnitHandle( udg_EOT_Hashtable, cacheId + 100, 1000)
set udg_EOT_Param_Target = LoadUnitHandle( udg_EOT_Hashtable, cacheId + 100, 1001)
set udg_EOT_Param_Duration = LoadReal( udg_EOT_Hashtable, cacheId + 100, 1002)
set udg_EOT_Param_Remaining_Duration = LoadReal( udg_EOT_Hashtable, cacheId + 100, 1003)
set udg_EOT_Param_Interval = LoadReal( udg_EOT_Hashtable, cacheId + 100, 1004)
set udg_EOT_Param_Remaining_Interval = LoadReal( udg_EOT_Hashtable, cacheId + 100, 1005)
set udg_EOT_Param_Hidden = LoadBoolean( udg_EOT_Hashtable, cacheId + 100, 1006)
set udg_EOT_Param_Buff = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1007)
set udg_EOT_Param_Buff_Holder = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1008)
set udg_EOT_Param_Buff_Holder_Level = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1009)
set udg_EOT_Param_Ability = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1010)
set udg_EOT_Param_Ability_Level = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1011)
set udg_EOT_Param_Type = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1012)
set udg_EOT_Param_Subtype = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1013)
set udg_EOT_Param_Subtype = LoadInteger( udg_EOT_Hashtable, cacheId + 100, 1014)
set udg_EOT_Param_Positive = LoadBoolean( udg_EOT_Hashtable, cacheId + 100, 1015)
set udg_EOT_Param_Can_Dispell = LoadBoolean( udg_EOT_Hashtable, cacheId + 100, 1016)
set udg_EOT_Param_Is_Passive = LoadBoolean( udg_EOT_Hashtable, cacheId + 100, 1017)
//set udg_EOT_Param_Is_Paused = LoadBoolean( udg_EOT_Hashtable, cacheId + 100, 1018)
set udg_EOT_Param_Special_Effect = LoadEffectHandle( udg_EOT_Hashtable, cacheId + 100, 1019)
set udg_EOT_Param_Special_Effect_Model = LoadStr( udg_EOT_Hashtable, cacheId + 100, 1020)
set udg_EOT_Param_Special_Effect_Point = LoadStr( udg_EOT_Hashtable, cacheId + 100, 1021)
endfunction
//Save and Load additional data to an EOT.
//Raw values:
function EOT_Save_Integer takes integer id, integer value returns nothing
call SaveInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Real takes integer id, real value returns nothing
call SaveReal(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_String takes integer id, string value returns nothing
call SaveStr(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Boolean takes integer id, boolean value returns nothing
call SaveBoolean(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Load_Integer takes integer id returns integer
return LoadInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Real takes integer id returns real
return LoadReal(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_String takes integer id returns string
return LoadStr(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Boolean takes integer id returns boolean
return LoadBoolean(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
//Handles:
function EOT_Save_Unit takes integer id, unit value returns nothing
call SaveUnitHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Player takes integer id, player value returns nothing
call SavePlayerHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Item takes integer id, item value returns nothing
call SaveItemHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Group takes integer id, group value returns nothing
call SaveGroupHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Effect takes integer id, effect value returns nothing
call SaveEffectHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Location takes integer id, location value returns nothing
call SaveLocationHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Save_Lightning takes integer id, lightning value returns nothing
call SaveLightningHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000, value)
endfunction
function EOT_Load_Unit takes integer id returns unit
return LoadUnitHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Player takes integer id returns player
return LoadPlayerHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Item takes integer id returns item
return LoadItemHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Group takes integer id returns group
return LoadGroupHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Effect takes integer id returns effect
return LoadEffectHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Location takes integer id returns location
return LoadLocationHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
function EOT_Load_Lightning takes integer id returns lightning
return LoadLightningHandle(udg_EOT_Hashtable, udg_EOT_Param_Id, id + 1000)
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// EOT System header file end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Name | Type | is_array | initial_value |
CenterPoint | location | No | |
CP_HiddenItems | item | Yes | |
CP_HiddenItemsIndex | integer | No | |
CP_Item | item | No | |
CP_Point | location | No | |
CP_PointIsWalkable | boolean | No | |
CP_Rect | rect | No | |
D_M_Tatsumaki | real | Yes | |
DamageEventAmount | real | No | |
DamageEventSource | unit | No | |
DeathGripAngle | real | No | |
DeathGripCaster | unit | No | |
DeathGripDistance | real | No | |
DeathGripHashtable | hashtable | No | |
DeathGripPosition | location | No | |
DeathGripPosition2 | location | No | |
DeathGripRemainingTime | real | No | |
DeathGripUnitGroup | group | No | |
DetectClosestUnit | unit | No | |
DetectFinalPickedUnitLocation | location | No | |
DetectPickedUnit | unit | No | |
DetectPickedUnitDistance | real | No | |
DetectPickedUnitLocation | location | No | |
DetectShortestDistance | real | No | |
DetectTempPoint | location | No | |
DOT_Attack_Type | attacktype | No | |
DOT_Damage | real | No | |
DOT_Damage_Type | damagetype | No | |
EOT_Amount | integer | No | |
EOT_Array_Ability | abilcode | Yes | |
EOT_Array_Ability_Level | integer | Yes | |
EOT_Array_Buff | buffcode | Yes | |
EOT_Array_Buff_Holder | abilcode | Yes | |
EOT_Array_Buff_Holder_Level | integer | Yes | |
EOT_Array_Can_Dispell | boolean | Yes | |
EOT_Array_Duration | real | Yes | |
EOT_Array_Hidden | boolean | Yes | |
EOT_Array_Id | integer | Yes | |
EOT_Array_Interval | real | Yes | |
EOT_Array_Is_Passive | boolean | Yes | |
EOT_Array_On_Period_Trigger | trigger | Yes | |
EOT_Array_Positive | boolean | Yes | |
EOT_Array_Remaining_Duration | real | Yes | |
EOT_Array_Remaining_Interval | real | Yes | |
EOT_Array_Source | unit | Yes | |
EOT_Array_Special_Effect | effect | Yes | |
EOT_Array_Special_Effect_Model | string | Yes | |
EOT_Array_Special_Effect_Point | string | Yes | |
EOT_Array_Subtype | integer | Yes | |
EOT_Array_Subtype2 | integer | Yes | |
EOT_Array_Target | unit | Yes | |
EOT_Array_Type | integer | Yes | |
EOT_Event_An_EOT_Has_Expired | real | No | |
EOT_Event_An_EOT_Is_Created | real | No | |
EOT_Event_An_EOT_Is_Destroyed | real | No | |
EOT_Event_An_EOT_Is_Dispelled | real | No | |
EOT_Event_Creation_After | real | No | |
EOT_Event_Creation_Before | real | No | |
EOT_Event_Destruction_After | real | No | |
EOT_Event_Destruction_Before | real | No | |
EOT_Event_Dispell_After | real | No | |
EOT_Event_Dispell_Before | real | No | |
EOT_Event_Expire_After | real | No | |
EOT_Event_Expire_Before | real | No | |
EOT_Event_Get_Data | real | No | |
EOT_Event_Interval_After | real | No | |
EOT_Event_Interval_Before | real | No | |
EOT_Event_Null_Variables | real | No | |
EOT_Event_On_Interval | real | No | |
EOT_Event_Save_Data | real | No | |
EOT_Hashtable | hashtable | No | |
EOT_Index | integer | No | |
EOT_Param_Ability | abilcode | No | |
EOT_Param_Ability_Level | integer | No | |
EOT_Param_Buff | buffcode | No | |
EOT_Param_Buff_Holder | abilcode | No | |
EOT_Param_Buff_Holder_Level | integer | No | |
EOT_Param_Can_Dispell | boolean | No | |
EOT_Param_Destroy | boolean | No | |
EOT_Param_Destroy_Passive | boolean | No | |
EOT_Param_Duration | real | No | |
EOT_Param_Expire | boolean | No | |
EOT_Param_Force_Destroy | boolean | No | |
EOT_Param_Hidden | boolean | No | |
EOT_Param_Id | integer | No | |
EOT_Param_Interval | real | No | |
EOT_Param_Is_Passive | boolean | No | |
EOT_Param_Negative | boolean | No | |
EOT_Param_Positive | boolean | No | |
EOT_Param_Remaining_Duration | real | No | |
EOT_Param_Remaining_Interval | real | No | |
EOT_Param_Source | unit | No | |
EOT_Param_Special_Effect | effect | No | |
EOT_Param_Special_Effect_Model | string | No | |
EOT_Param_Special_Effect_Point | string | No | |
EOT_Param_Subtype | integer | No | |
EOT_Param_Subtype2 | integer | No | |
EOT_Param_Target | unit | No | |
EOT_Param_Type | integer | No | |
EOT_Timer | timer | No | |
EOT_Trigger_Create_EOT | trigger | No | |
EOT_Trigger_Destroy_EOT | trigger | No | |
EOT_Trigger_Get_Data | trigger | No | |
EOT_Trigger_Remove_EOTs | trigger | No | |
EOT_Trigger_Save_Data | trigger | No | |
EOT_Unique_Id | integer | No | |
FF_Ability_ID | abilcode | No | |
FF_Angle | real | Yes | |
FF_AoE | real | Yes | |
FF_Attack_Type | attacktype | No | |
FF_Caster | unit | Yes | |
FF_Current_Index | integervar | No | |
FF_Damage | real | Yes | |
FF_Damage_Type | damagetype | No | |
FF_DamagedUnits | group | Yes | |
FF_DestroyTree | boolean | No | |
FF_Distance | real | Yes | |
FF_Level | integer | Yes | |
FF_Max_Index | integer | No | |
FF_ReachedDist | real | Yes | |
FF_Spec | string | No | |
FF_Speed | real | Yes | |
FF_TreeDestroyer | unit | No | |
FF_TreeDestroyer_ID | unitcode | No | |
FF_Velo | real | Yes | |
IsDamageSpell | boolean | No | |
IsUnitBeingKnockedBack | boolean | Yes | |
JD_Angle | real | Yes | |
JD_Animations | string | Yes | |
JD_Distances | real | Yes | |
JD_Effect | string | Yes | |
JD_Group | group | No | |
JD_HighSettings | real | Yes | |
JD_Integers | integer | Yes | |
JD_JumpEndEvent | real | No | |
JD_JumpHigh | real | Yes | |
JD_ReachedDistance | real | Yes | |
JD_RealTimer | real | Yes | |
JD_SpeedUnits | real | Yes | |
JD_TempPoint | location | Yes | |
JD_TreesDestroy | boolean | Yes | |
JD_Unit | unit | Yes | |
JDA_Animation | string | No | |
JDA_AnimationSpeed | real | No | |
JDA_Collusion | boolean | No | |
JDA_DestroyTrees_Dash | boolean | No | |
JDA_JumpHigh_Distance | real | No | |
JDA_SpecialEffect | string | No | |
JDA_Speed | real | No | |
JDA_TargetPoint | location | No | |
JDA_Unit | unit | No | |
K2DAmphibious | boolean | Yes | |
K2DAngle | real | Yes | |
K2DBounce | boolean | Yes | |
K2DCollision | real | Yes | |
K2DCos | real | Yes | |
K2DCosD1 | real | Yes | |
K2DCosD2 | real | Yes | |
K2DCosH | real | Yes | |
K2DDebrisKiller | unit | No | |
K2DDestRadius | real | Yes | |
K2DDistanceLeft | real | Yes | |
K2DFlying | boolean | Yes | |
K2DFreeze | boolean | Yes | |
K2DFriction | real | Yes | |
K2DFXModel | string | Yes | |
K2DFXRate | real | Yes | |
K2DFXTimeLeft | real | Yes | |
K2DHeight | real | Yes | |
K2DHeightThreshold | real | Yes | |
K2DImpact | trigger | Yes | |
K2DItem | item | No | |
K2DItemOffset | boolean | No | |
K2DItemsFound | boolean | No | |
K2DKillTrees | boolean | Yes | |
K2DLastX | real | Yes | |
K2DLastY | real | Yes | |
K2DMaxDestRadius | real | No | |
K2DMaxX | real | No | |
K2DMaxY | real | No | |
K2DMinX | real | No | |
K2DMinY | real | No | |
K2DNext | integer | Yes | |
K2DOverride | boolean | Yes | |
K2DPause | boolean | Yes | |
K2DPrev | integer | Yes | |
K2DRadius | integer | Yes | |
K2DRegion | rect | No | |
K2DSimple | boolean | Yes | |
K2DSin | real | Yes | |
K2DSinD1 | real | Yes | |
K2DSinD2 | real | Yes | |
K2DSinH | real | Yes | |
K2DSource | unit | Yes | |
K2DTimeLeft | real | Yes | |
K2DTimeout | real | No | |
K2DTimer | timer | No | |
K2DUnbiasedCollision | boolean | Yes | |
K2DVelocity | real | Yes | |
K2DX | real | No | |
K2DY | real | No | |
Knockback2DAmphibious | boolean | No | |
Knockback2DAngle | real | No | |
Knockback2DBounces | boolean | No | |
Knockback2DCollision | real | No | |
Knockback2DDefaultBounce | boolean | No | |
Knockback2DDefaultDestRadius | real | No | |
Knockback2DDefaultFriction | real | No | |
Knockback2DDefaultFX | string | No | |
Knockback2DDefaultFXRate | real | No | |
Knockback2DDefaultGravity | real | No | |
Knockback2DDefaultKillTrees | boolean | No | |
Knockback2DDefaultPause | boolean | No | |
Knockback2DDestRadius | real | No | |
Knockback2DDistance | real | No | |
Knockback2DFriction | real | No | |
Knockback2DFXRate | real | No | |
Knockback2DGravity | real | No | |
Knockback2DHeight | real | No | |
Knockback2DKillTrees | boolean | No | |
Knockback2DLoopFX | string | No | |
Knockback2DOnImpact | trigger | No | |
Knockback2DOverride | boolean | No | |
Knockback2DPause | boolean | No | |
Knockback2DRobustPathing | integer | No | |
Knockback2DSimple | boolean | No | |
Knockback2DSource | unit | No | |
Knockback2DTime | real | No | |
Knockback2DTreeOrDebris | string | No | |
Knockback2DUnbiasedCollision | boolean | No | |
Knockback2DUnit | unit | No | |
LeaklessGroup | group | No | |
LH_Caster | unit | Yes | |
LH_HealMax | real | Yes | |
LH_Loop | integer | No | |
LH_Lvl | integer | Yes | |
LH_Max | integer | No | |
LoopInt | integer | No | |
MCS_AttachmentPoint1 | string | No | |
MCS_AttachmentPoint2 | string | No | |
MCS_Caster1 | unit | No | |
MCS_Caster2 | unit | Yes | |
MCS_curDuration | real | Yes | |
MCS_Deadboolean | boolean | Yes | |
MCS_Duration1 | real | No | |
MCS_Duration2 | real | Yes | |
MCS_Integer | integer | Yes | |
MCS_MindControlledGroup | group | No | |
MCS_Player | player | Yes | |
MCS_SfxAtEndString | string | No | |
MCS_SfxAtEndString2 | string | Yes | |
MCS_SfxAtStartString | modelfile | No | |
MCS_SfxContinous1 | effect | Yes | |
MCS_SfxContinous1String | string | No | |
MCS_SfxContinous2 | effect | Yes | |
MCS_SfxContinous2String | string | No | |
MCS_Target1 | unit | No | |
MCS_Target2 | unit | Yes | |
MDG_2ndDamage | real | Yes | |
MDG_Ability | abilcode | No | |
MDG_Angle | real | Yes | |
MDG_Angle2 | real | Yes | |
MDG_AoE | real | Yes | |
MDG_BaseSpeed | real | Yes | |
MDG_Caster | unit | Yes | |
MDG_CDummy | unitcode | No | |
MDG_Counter | real | Yes | |
MDG_CurDistance | real | Yes | |
MDG_CurIndex | integer | No | |
MDG_DAbility | abilcode | No | |
MDG_Damage | real | Yes | |
MDG_DamagedGroup | group | Yes | |
MDG_DamagedGroup2 | group | Yes | |
MDG_DummyCast | unit | No | |
MDG_Duration | real | Yes | |
MDG_Effect | effect | Yes | |
MDG_Effect2 | effect | Yes | |
MDG_Gap | real | Yes | |
MDG_Level | integer | Yes | |
MDG_Loc | location | Yes | |
MDG_MaxDistance | real | Yes | |
MDG_MaxIndex | integer | No | |
MDG_MDummy | unitcode | No | |
MDG_Missile | unit | Yes | |
MDG_Missile2 | unit | Yes | |
MDG_Numbers | integer | Yes | |
MDG_Player | player | Yes | |
MDG_SDummy | unitcode | No | |
MDG_SFX | string | Yes | |
MDG_SFXDummy | unit | Yes | |
MDG_Speed | real | Yes | |
MDG_Stage | integer | Yes | |
MDG_StartOffset | real | Yes | |
MDG_TempAngle | real | No | |
MDG_TempCaster | unit | No | |
MDG_TempInteger | integervar | No | |
MDG_TempLevel | integer | No | |
MDG_TempPlayer | player | No | |
MDG_TempSpeed | real | No | |
MDG_TempUnit | unit | No | |
MDG_UndamagedGroup | group | Yes | |
MDG_UndamagedGroup2 | group | Yes | |
MS_Ability | abilcode | No | |
MS_AbilityLvl | integer | Yes | |
MS_AbilityStun | abilcode | No | |
MS_AoE | real | No | |
MS_AttackType | attacktype | No | |
MS_Blue | real | No | |
MS_Caster | unit | Yes | |
MS_Counter_SFX | real | Yes | |
MS_CurrentHeight | real | No | |
MS_Damage | real | Yes | |
MS_DamageType | damagetype | No | |
MS_DestroyTreeAoE | real | No | |
MS_DestroyTrees | boolean | No | |
MS_DistanceTraveled | real | Yes | |
MS_Dummy | unitcode | No | |
MS_DummyCaster | unit | No | |
MS_FallRate_XY | real | No | |
MS_FallRate_Z | real | No | |
MS_FallTime | real | No | |
MS_Green | real | No | |
MS_KBAoE | real | No | |
MS_KBDistance | real | No | |
MS_KBTime | real | No | |
MS_LandAoE | real | No | |
MS_LandingDamage | real | No | |
MS_LoopInt | integervar | No | |
MS_M_SpawnDistance | real | No | |
MS_M_SpawnHeight | real | No | |
MS_MaxIndex | integer | No | |
MS_MaxLevel | integer | No | |
MS_Meteor_SFX | effect | Yes | |
MS_MeteorDummy | unit | Yes | |
MS_MeteorLoc | location | No | |
MS_MeteorSize | real | No | |
MS_MoveRate | real | Yes | |
MS_NodeNext | integer | Yes | |
MS_NodePrev | integer | Yes | |
MS_Owner | player | Yes | |
MS_PeriodicTimer | real | No | |
MS_RecycledSize | integer | No | |
MS_RecycledStack | integer | Yes | |
MS_Red | real | No | |
MS_RollDirection | real | Yes | |
MS_RollDistance | real | Yes | |
MS_RollTime | real | Yes | |
MS_SFX_FallFreq | real | No | |
MS_SFX_RollFreq | real | Yes | |
MS_SFXDeath | string | No | |
MS_SFXFall | string | No | |
MS_SFXKB | string | No | |
MS_SFXLand | string | No | |
MS_SFXMeteor | string | No | |
MS_SFXRoll | string | No | |
MS_Size | real | No | |
MS_Spell_ID | integer | No | |
MS_SpellCount | integer | No | |
MS_Stage | integer | Yes | |
MS_StunAoE | real | No | |
MS_TargetLoc | location | Yes | |
MS_TempDest | destructable | No | |
MS_TempHeight | real | No | |
MS_TempInt | integervar | No | |
MS_TempLoc | location | No | |
MS_TempReal | real | No | |
MS_TempUnit | unit | No | |
MS_TreeKiller | unit | No | |
PDD_allocatedAttacks | integer | No | |
PDD_allocCounter | integer | No | |
PDD_amount | real | No | |
PDD_ATTACK_TYPE_UNIVERSAL | attacktype | No | |
PDD_BRACERS_SPELL_DMG_RED | real | No | |
PDD_CODE | integer | No | |
PDD_DAMAGE_TYPE_DETECTOR | integer | No | |
PDD_damageEvent | trigger | No | |
PDD_damageEventTrigger | real | No | |
PDD_damageHandler | trigger | No | |
PDD_damageType | integer | No | |
PDD_ETHEREAL_DAMAGE_FACTOR | real | No | |
PDD_h | hashtable | No | |
PDD_PHYSICAL | integer | No | |
PDD_pureAmount | real | No | |
PDD_runAllocatedAttacks | trigger | No | |
PDD_SET_MAX_LIFE | integer | No | |
PDD_source | unit | No | |
PDD_SPELL | integer | No | |
PDD_SPELL_DMG_REDUCTION_ITEM | integer | No | |
PDD_SPELL_RESIST_AUTO_DETECT | boolean | No | |
PDD_target | unit | No | |
PDD_totalAllocs | integer | No | |
PDD_TRIGGER_CLEANUP_PERIOD | real | No | |
PDD_UNIT_MIN_LIFE | real | No | |
Player | player | No | |
Radians_QuarterPi | real | No | |
Radians_QuarterTurn | real | No | |
Radians_Turn | real | No | |
RS_Animation_Speed | real | No | |
RS_Attack_Type | attacktype | No | |
RS_Caster | unit | Yes | |
RS_Current_Index | integer | No | |
RS_Damage | real | Yes | |
RS_Damage_Type | damagetype | No | |
RS_Effect | string | Yes | |
RS_Index | integer | Yes | |
RS_Index_Size | integer | No | |
RS_Level | integer | No | |
RS_Loop | integervar | No | |
RS_Max_Index | integer | No | |
RS_Slashes | integer | Yes | |
RS_Target | unit | Yes | |
RS_Temp_Point | location | No | |
RS_Temp_Point2 | location | No | |
RS_Transparency | real | No | |
RS_Weapon_Effect | effect | Yes | |
S_caster | unit | Yes | |
S_dummy | unit | Yes | |
S_dummypoint | location | No | |
S_index1 | integer | Yes | |
S_index2 | integer | No | |
S_index3 | integervar | No | |
S_index_max | integer | No | |
S_index_size | integer | No | |
S_pause | boolean | Yes | |
S_speed | real | Yes | |
S_stopduration | real | Yes | |
S_stopgroup | group | Yes | |
S_targetpoint | location | No | |
SW_AffectAir | boolean | Yes | |
SW_AffectAlly | boolean | Yes | |
SW_AffectEnemy | boolean | Yes | |
SW_AffectGround | boolean | Yes | |
SW_AffectStructure | boolean | Yes | |
SW_Angle | real | No | |
SW_AreaCurrent | real | Yes | |
SW_AreaFinal | real | Yes | |
SW_AreaGrowth | real | Yes | |
SW_AreaInitial | real | Yes | |
SW_Attachment | string | No | |
SW_AttackType | attacktype | Yes | |
SW_Caster | unit | Yes | |
SW_Damage | real | Yes | |
SW_DamageMax | real | Yes | |
SW_DamageType | damagetype | Yes | |
SW_DamageX | real | Yes | |
SW_Distance | real | Yes | |
SW_DistanceX | real | Yes | |
SW_Dummy | unit | Yes | |
SW_ExtraEffect | trigger | Yes | |
SW_ExtraEffectCheck | boolean | Yes | |
SW_ExtraEffectTarget | trigger | Yes | |
SW_ExtraEffectTargetCheck | boolean | Yes | |
SW_Group | group | No | |
SW_GroupDone | group | Yes | |
SW_Loop | integervar | No | |
SW_LoopingSfx | boolean | Yes | |
SW_Lvl | integer | Yes | |
SW_ManaBurn | real | Yes | |
SW_Max | integer | No | |
SW_NextPoint | location | Yes | |
SW_OneInstance | boolean | Yes | |
SW_Point | location | Yes | |
SW_Speed | real | Yes | |
SW_SpeedX | real | Yes | |
SW_Wave | effect | Yes | |
SW_WaveEffect | modelfile | Yes | |
SW_WaveEffectEnd | modelfile | Yes | |
SW_WaveEffectLoop | modelfile | Yes | |
T_P_Tatsumaki | location | Yes | |
TargetPoint | location | No | |
Tauren_Shockwave | boolean | Yes | |
Tauren_WarStomp | boolean | Yes | |
TavernGroup2 | group | No | |
TavernGroup3 | group | No | |
TavernGroup4 | group | No | |
TavernInitialGroup | group | No | |
TavernInitialLoc | location | No | |
TavernInt | integer | No | |
TavernUnit | unit | Yes | |
TempAbility | abilcode | No | |
TempAbilityCopy | abilcode | Yes | |
TempAbilityCopy2 | abilcode | No | |
tempAngle_Real | real | No | |
TempBackstabAngle | real | Yes | |
TempBackstabPoint | location | Yes | |
TempBlackMarketItemPool | group | No | |
TempBRSCurrentMana | integer | Yes | |
tempCaster | unit | No | |
TempCasterUnit | unit | No | |
tempDamage_Scaling_Total | real | No | |
tempDamage_Total | real | No | |
TempDest | destructable | No | |
TempDummyUnit | unit | No | |
tempDuration_Total | real | No | |
TempEntomaPlayerUnit | unit | Yes | |
TempFaithKills | integer | Yes | |
TempFaithPlayers | force | No | |
TempFaithReqGloriousMartyrdom | boolean | Yes | |
TempGoblinSlayerPlayerCooldown | boolean | Yes | |
TempGoblinSlayerPlayerUnit | unit | Yes | |
TempGoblinSlayerPlayerUnitLoc | location | Yes | |
TempIndexCounter | integer | Yes | |
TempIndexCurrent | integervar | No | |
TempIndexMax | integer | No | |
TempIndexPoint | location | Yes | |
TempIndexUnit | unit | Yes | |
TempInt | integer | No | |
TempInt2 | integer | No | |
tempInt_Counter | integer | No | |
tempInt_Counter_2 | integer | No | |
TempInteger | integer | No | |
tempItem | item | No | |
tempKey | integer | No | |
TempKnockbackBRSDeadMaster | boolean | Yes | |
TempKnockbackDemiShockwave | boolean | Yes | |
TempKnockbackMeteoricSmash | boolean | Yes | |
TempKnockbackShieldSmash | boolean | Yes | |
TempLeaderboard | leaderboard | Yes | |
tempLevel | real | No | |
TempLoc | location | No | |
TempLocation | location | No | |
TempLoopCountAA | integer | Yes | |
TempMercRecruitPubPool | group | No | |
TempMercRecruitRuinsPool | group | No | |
TempMultiboardFaith | multiboard | Yes | |
TempMultiboardFaithAA | real | Yes | |
TempMultiboardFaithBI | real | Yes | |
TempMultiboardFaithCP | real | Yes | |
TempMultiboardFaithGM | real | Yes | |
TempMultiboardFaithRG | real | Yes | |
TempMultiboardFaithRL | real | Yes | |
TempNum | integer | No | |
TempNum2 | integer | No | |
TempOwner | player | No | |
tempPickedUnit | unit | No | |
TempPickedUnit | unit | No | |
TempPlayerUnit | unit | Yes | |
TempPoint | location | No | |
TempPoint2 | location | No | |
tempPoint_Target | location | No | |
tempPoint_Temp | location | No | |
tempPoint_Whirlpool | location | No | |
tempPull_Intensity_Total | real | No | |
tempRange_Total | real | No | |
TempReal | real | No | |
TempSoldUnitCostGold | real | No | |
TempSoldUnitCostLumber | real | No | |
TempStormCasterUnitGroup | group | No | |
TempStormPoint | location | No | |
TempStormRegion | rect | No | |
TempStormUnit | unit | No | |
TempStormUnitGroup | group | No | |
TempUnit | unit | No | |
TempUnitBRSSource | unit | No | |
TempUnitBRSSourceLevel | integer | No | |
TempUnitBRSSourcePoint | location | No | |
TempUnitBRSTarget | unit | No | |
TempUnitBuilding | unit | No | |
TempUnitFacing | real | No | |
TempUnitGroup | group | No | |
TempUnitGroupBRSSourceAura | group | No | |
TempUnitGroupBRSTargetAura | group | No | |
TempUnitGroupBRSTargetAuraNum | integer | No | |
TempUnitGroupGrenade | group | No | |
TempUnitGroupNoGrenade | group | No | |
TempUnitKilled | unit | No | |
TempUnitKiller | unit | No | |
TempUnitSold | unit | No | |
TempUnitType | unitcode | No | |
TimerTimeElapsed | timer | No | |
TimerTimeElapsedSeconds | real | No | |
TimerTimeElapsedWindow | timerdialog | No | |
TS | integervar | No | |
TS_Angle | real | Yes | |
TS_Damage | real | Yes | |
TS_Distance | real | Yes | |
TS_Group | group | Yes | |
TS_Height | real | Yes | |
TS_Hero | unit | Yes | |
TS_MaxDistance | real | Yes | |
TS_Off | boolean | Yes | |
TS_Parabola | real | Yes | |
TS_Point | location | Yes | |
TS_Radius | real | Yes | |
TS_Skip | integer | No | |
TS_Slams | integer | Yes | |
TS_Speed | real | Yes | |
TS_Target | unit | Yes | |
TS_Times | integer | No | |
UAS_Count | integer | Yes | |
UAS_GroupDmgPass | group | Yes | |
UAS_KeepCastAngle | real | Yes | |
UAS_KeepCaster | unit | Yes | |
UAS_KeepColourReal | real | Yes | |
UAS_KeepDmgPass | real | Yes | |
UAS_KeepEff | effect | Yes | |
UAS_KeepLevel | integer | Yes | |
UAS_KeepMissile | unit | Yes | |
UAS_KeepSpeed | real | Yes | |
UAS_KeepTarget | unit | Yes | |
UAS_KeepTimeDurain | real | Yes | |
UAS_KeepTimeTrigger | real | Yes | |
UAS_KeepTriggerLoop | trigger | Yes | |
UAS_KeepWorking | boolean | Yes | |
UAS_TimeLoop | real | Yes | |
UAS_WantDesCount | boolean | Yes | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
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 | |
WP_Ability_Order | string | No | |
WP_Attack_Type | attacktype | No | |
WP_Damage_Base | real | No | |
WP_Damage_Bonus | real | No | |
WP_Damage_Scaling_Base | real | No | |
WP_Damage_Scaling_Bonus | real | No | |
WP_Damage_Scaling_Max | real | No | |
WP_Damage_Type | damagetype | No | |
WP_Dummy_Loop | unit | No | |
WP_Dummy_Scale_Factor | real | No | |
WP_Dummy_Whirlpool | unit | No | |
WP_Duration_Base | real | No | |
WP_Duration_Bonus | real | No | |
WP_Duration_Max | real | No | |
WP_Effect_Center | string | No | |
WP_Effect_Hit | string | No | |
WP_Group_Counter | integer | No | |
WP_Hashtable | hashtable | No | |
WP_Interval_Integer | integer | No | |
WP_Loop_Group | group | No | |
WP_Pull_Intensity_Base | real | No | |
WP_Pull_Intensity_Bonus | real | No | |
WP_Pull_Intensity_Max | real | No | |
WP_Pull_Interval | integer | No | |
WP_Range_Base | real | No | |
WP_Range_Bonus | real | No | |
WP_Range_Max | real | No | |
WP_Spell_ID | abilcode | No | |
WP_Spell_ID_2 | abilcode | No | |
WP_Unit_Type_Dummy | unitcode | No | |
WP_Unit_Type_Whirl_Dummy | unitcode | No | |
WP_Unit_Type_Whirl_Dummy_2 | unitcode | No |
//TESH.scrollpos=121
//TESH.alwaysfold=0
////////////////////////////////////////////////////////////////////////////////////
//
// Physical Damage Detection Engine GUI v 1.3.0.0
// ----------------------------------------------
// By looking_for_help aka eey
//
// This system is able to detect, modify and deal damage. It can differentiate
// between physical and spell damage, as well as block, reduce or increase the
// applied damage to a desired value. You can also allocate damage events from
// running damage events.
//
// This is the GUI version of the system, meaning that you can use this with the
// standard editor and basically without any knowledge of JASS.
//
////////////////////////////////////////////////////////////////////////////////////
//
// Implementation
// --------------
// 1. Create all variables that this system uses (compare the variable editor).
// You don't have to set them to specific values, they get initialized
// automatically by the system so just create them.
// 2. Copy this trigger to your map. You can then add damage handlers by using
// the event "value of real variable becomes equal to 1" with the variable
// udg_PDD_damageEventTrigger. Compare the OnDamage trigger for an example usage.
// 3. Copy the two custom abilities to your map and make sure they have the
// correct ID. You can specify the ID in the function InitGlobalVariables
// above.
// 4. Go to the locust swarm ability and invert its damage return portion
// from (default) 0.75 to -0.75.
// 5. Remove the spell damage reduction ability from the spell damage reduction
// items you use (runed bracers). You can configure the resistance of this
// item in the InitGlobalVariables function, modifying the global variable
// udg_PDD_BRACERS_SPELL_DMG_RED.
//
////////////////////////////////////////////////////////////////////////////////////
//
// Important Notes
// ---------------
// 1. Life Drain does not work with this system, so you should use a triggered
// version of this spell if you want to use it.
// 2. Same for Finger of Death, if you want to use this spell bug free with this
// system, you should use a triggered version of it.
// 3. If you use damage modifiers by setting the damage amount variable, you have
// to use GetUnitLife, GetUnitMaxLife and SetUnitLife instead of GetWidgetLife,
// GetUnitState for UNIT_STATE_MAX_LIFE and SetWidgetLife in your whole map to
// ensure there occure no bugs.
// 4. The boolean udg_PDD_SPELL_RESIST_AUTO_DETECT is only neccessary set to true
// if you want to use a customized damage table with spell damage resistance
// above 100%. If this is not the case, it should be set to false, as the
// system is faster then and still works correct.
// 5. As already mentioned you can't use the spell reduction ability when using this
// system (runed bracers and elunes grace). If you want to use them, you can
// trigger them by using the damage modifiers. Runed bracers is already considered
// in this system, so you don't have to code it.
//
////////////////////////////////////////////////////////////////////////////////////
//
// System API
// ----------
// real damageEventTrigger
// - Use the event "value of real variable becomes equal to 1" to detect a damage
// event. In this event you can use the following API. Compare the OnDamage
// trigger for an example usage.
//
// unit target
// - In this global unit variable, the damaged unit is saved. Don't write any-
// thing into this variable, use it as readonly.
//
// unit source
// - In this global unit variable, the damage source is saved. Don't write any-
// thing into this variable, use it as readonly.
//
// real amount
// - In this global real variable, the amount of damage is saved. This amount
// can be modified by simply setting it to the desired amount that should be
// applied to the target. Set the amount to 0.0 to block the damage completly.
// Negative values will result in heal.
//
// integer damageType
// - In this global integer variable, the damage type of the current damage is
// saved. Use it to differentiate between physical, spell and code damage. The
// variable can takes the values PHYSICAL == 0, SPELL == 1 and CODE == 2. Don't
// write anything into this variable, use it as readonly.
//
// function GetUnitLife takes unit u returns real
// - Use this function instead of the GetWidgetLife native. It ensures that you
// get the correct health value, even when damage modifiers are applied. If
// you don't use damage modifiers at all, you don't need this function.
//
// function GetUnitMaxLife takes unit u returns real
// - Use this function instead of the GetUnitState(u, UNIT_STATE_MAX_LIFE) native.
// It will return the correct value, even when damage modifiers are applied. If
// you don't use damage modifiers at all, you don't need this function.
//
// function SetUnitLife takes unit u, real newLife returns nothing
// - Use this function instead of the SetWidgetLife(u, newLife) native if you use
// damage modifiers in your map. Same rules as for the GetUnitMaxLife and the
// GetUnitMaxLife functions.
//
// function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
// - Use this function to deal damage from a running damage event. It works exactly
// the same as the native UnitDamageTarget but is recursion safe so that you can
// realize damage reflection for example with this. Don't ever use this function
// outside of an onDamage event.
//
// function AddDamageHandler takes code damageHandler returns nothing
// - Allows you to add a damage handler function to the system. This is not
// required for GUI users, only for vanilla JASS users. GUI users should
// use the real variable damageEventTrigger to add damage handlers to this
// system as explained above.
//
// function RemoveDamageHandler takes code damageHandler returns nothing
// - Allows you to remove a damage handler function from the system dynamic-
// ally. If you added the same handler function multiple times to the sys-
// tem, this function will remove all of these equal functions. This is not
// required for GUI users, only for vanilla JASS users.
//
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Configurable globals
//////////////////////////////////////////////////////////////////////////////////
function InitGlobalVariables takes nothing returns nothing
// Put here the correct ability IDs
set udg_PDD_DAMAGE_TYPE_DETECTOR = 'A001'
set udg_PDD_SET_MAX_LIFE = 'A002'
// Here you can configure some stuff, read the documentation for further info
set udg_PDD_SPELL_DMG_REDUCTION_ITEM = 'brac'
set udg_PDD_SPELL_RESIST_AUTO_DETECT = false
set udg_PDD_ETHEREAL_DAMAGE_FACTOR = 1.66
set udg_PDD_BRACERS_SPELL_DMG_RED = 0.33
set udg_PDD_TRIGGER_CLEANUP_PERIOD = 60.0
endfunction
//////////////////////////////////////////////////////////////////////////////////
// End of configurable globals
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// User functions
//////////////////////////////////////////////////////////////////////////////////
function AddDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop to manage equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
set index = index + 1
endloop
// Store the desired damage handler function
call SaveTriggerConditionHandle(udg_PDD_h, id, index, TriggerAddCondition(udg_PDD_damageHandler, Filter(func)))
endfunction
function RemoveDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop through all equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
call TriggerRemoveCondition(udg_PDD_damageHandler, LoadTriggerConditionHandle(udg_PDD_h, id, index))
set index = index + 1
endloop
// Clean things up
call FlushChildHashtable(udg_PDD_h, id)
endfunction
function GetUnitLife takes unit u returns real
local boolean duringModification
local integer uId = GetHandleId(u)
local real health
local real storedHealth = LoadReal(udg_PDD_h, uId, 2)
local real storedDamage = LoadReal(udg_PDD_h, uId, 1)
// Check if the unit is being rescued from damage
set duringModification = GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0
if duringModification then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
endif
// Get the correct health value of the unit
if storedHealth != 0.0 then
set health = storedHealth - storedDamage
else
set health = GetWidgetLife(u) - storedDamage
endif
// Restore the rescue ability and return
if duringModification then
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
endif
return health
endfunction
function GetUnitMaxLife takes unit u returns real
local real maxHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
set maxHealth = GetUnitState(u, UNIT_STATE_MAX_LIFE)
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
return maxHealth
endif
// If the unit isn't being rescued, use the standard native
return GetUnitState(u, UNIT_STATE_MAX_LIFE)
endfunction
function SetUnitLife takes unit u, real newLife returns nothing
local integer targetId
local integer oldTimerId
local real oldHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(u, newLife)
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
// Get the unit specific timer information
set targetId = GetHandleId(u)
set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
// Update the unit specific timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
call SaveReal(udg_PDD_h, targetId, 2, newLife)
call SaveReal(udg_PDD_h, targetId, 0, newLife)
call SaveReal(udg_PDD_h, oldTimerId, 4, newLife)
endif
return
endif
// If the unit isn't being rescued, use the standard native
call SetWidgetLife(u, newLife)
endfunction
function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
// Avoid infinite loop due to recursion
if udg_PDD_damageType == udg_PDD_CODE then
return false
endif
// Avoid allocating attacks on units that are about to be killed
if ( localTarget == udg_PDD_target and GetUnitLife(localTarget) - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
return false
endif
// Store all damage parameters determined by the user
set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks + 1
call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 0, localSource)
call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 1, localTarget)
call SaveReal(udg_PDD_h, udg_PDD_allocatedAttacks, 2, localAmount)
call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 3, attack)
call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 4, ranged)
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 5, GetHandleId(localAttackType))
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 6, GetHandleId(localDamageType))
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 7, GetHandleId(localWeaponType))
// Return true if the damage was allocated
return true
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Sub functions
////////////////////////////////////////////////////////////////////////////////////
function DealFixDamage takes unit source, unit target, real pureAmount returns nothing
local real MAX_DAMAGE = 1000000.0
local real beforeHitpoints
local real newHitpoints
// Ensure the amount is positive
if pureAmount < 0 then
set pureAmount = -pureAmount
endif
// Save the targets hitpoints
set beforeHitpoints = GetWidgetLife(target)
set newHitpoints = beforeHitpoints - pureAmount
// Apply the desired, fixed amount
if newHitpoints >= udg_PDD_UNIT_MIN_LIFE then
call SetUnitState(target, UNIT_STATE_LIFE, newHitpoints)
else
if ( IsUnitType(target, UNIT_TYPE_ETHEREAL) == false ) then
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, udg_PDD_ATTACK_TYPE_UNIVERSAL, DAMAGE_TYPE_UNIVERSAL, null)
call SetWidgetLife(target, 0.0)
else
call UnitRemoveAbility(target, udg_PDD_DAMAGE_TYPE_DETECTOR)
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
call SetWidgetLife(target, 0.0)
endif
endif
endfunction
function GetUnitSpellResistance takes unit u returns real
local real originalHP
local real beforeHP
local real afterHP
local real resistance
local real DUMMY_DAMAGE = 100
local real DUMMY_FACTOR = 0.01
// Deal spell damage in order to get the units resistance
call UnitRemoveAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
set originalHP = GetWidgetLife(udg_PDD_target)
call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, 20000.0)
set beforeHP = GetWidgetLife(udg_PDD_target)
call DisableTrigger(udg_PDD_damageEvent)
call UnitDamageTarget(udg_PDD_source, udg_PDD_target, DUMMY_DAMAGE, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)
call EnableTrigger(udg_PDD_damageEvent)
set afterHP = GetWidgetLife(udg_PDD_target)
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, originalHP)
call UnitAddAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(udg_PDD_target, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
// Calculate this resistance
set resistance = DUMMY_FACTOR*(beforeHP - afterHP)
// If the resistance was greater than 100%, return it
if resistance > 1.0 then
return resistance
else
return 1.0
endif
endfunction
function UnitHasItemOfType takes unit u, integer itemId returns integer
local integer index = 0
local item indexItem
// Check if the target has a spell damage reducing item
loop
set indexItem = UnitItemInSlot(u, index)
if ( indexItem != null ) and ( GetItemTypeId(indexItem) == itemId ) then
set indexItem = null
return index + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return 0
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Damage Engine
////////////////////////////////////////////////////////////////////////////////////
function AfterDamage takes nothing returns nothing
local timer time = GetExpiredTimer()
local integer id = GetHandleId(time)
local unit localSource = LoadUnitHandle(udg_PDD_h, id, 0)
local unit localTarget = LoadUnitHandle(udg_PDD_h, id, 1)
local real pureAmount = LoadReal(udg_PDD_h, id, 2)
local real amount = LoadReal(udg_PDD_h, id, 3)
local real originalHealth = LoadReal(udg_PDD_h, id, 4)
// If the damage was modified, restore units health
if originalHealth != 0.0 then
call UnitRemoveAbility(localTarget, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(localTarget, originalHealth)
endif
// Apply the desired amount of damage
if amount > 0.0 then
call DisableTrigger(udg_PDD_damageEvent)
call DealFixDamage(localSource, localTarget, amount)
call EnableTrigger(udg_PDD_damageEvent)
else
call SetWidgetLife(localTarget, originalHealth - amount)
endif
// Clean things up
call FlushChildHashtable(udg_PDD_h, id)
call FlushChildHashtable(udg_PDD_h, GetHandleId(localTarget))
call DestroyTimer(time)
set time = null
set localSource = null
set localTarget = null
endfunction
function DamageEngine takes nothing returns nothing
local timer time
local integer id
local real health
local real rawAmount
local real originalHealth
local integer targetId
local integer oldTimerId
local real oldHealth
local real oldOriginalHealth
local real oldAmount
set rawAmount = GetEventDamage()
if rawAmount == 0.0 then
return
endif
set udg_PDD_source = GetEventDamageSource()
set udg_PDD_target = GetTriggerUnit()
// Determine the damage type
if rawAmount > 0.0 then
if udg_PDD_damageType != udg_PDD_CODE then
set udg_PDD_damageType = udg_PDD_PHYSICAL
endif
set udg_PDD_amount = rawAmount
else
if udg_PDD_damageType != udg_PDD_CODE then
set udg_PDD_damageType = udg_PDD_SPELL
endif
set udg_PDD_amount = -rawAmount
endif
// Register spell reduction above 100%
if udg_PDD_SPELL_RESIST_AUTO_DETECT then
set udg_PDD_amount = GetUnitSpellResistance(udg_PDD_target)*udg_PDD_amount
else
if ( IsUnitType(udg_PDD_target, UNIT_TYPE_ETHEREAL) and IsUnitEnemy(udg_PDD_target, GetOwningPlayer(udg_PDD_source)) and rawAmount < 0.0 ) then
set udg_PDD_amount = udg_PDD_ETHEREAL_DAMAGE_FACTOR*udg_PDD_amount
endif
endif
// Register spell damage reducing items like runed bracers
if ( IsUnitType(udg_PDD_target, UNIT_TYPE_HERO) and UnitHasItemOfType(udg_PDD_target, udg_PDD_SPELL_DMG_REDUCTION_ITEM) > 0 ) and rawAmount < 0.0 then
set udg_PDD_amount = (1 - udg_PDD_BRACERS_SPELL_DMG_RED)*udg_PDD_amount
endif
// Save health and damage variables
if udg_PDD_damageType != udg_PDD_CODE then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
endif
set udg_PDD_pureAmount = udg_PDD_amount
set originalHealth = GetWidgetLife(udg_PDD_target)
set oldTimerId = 0
// Call damage handlers
set udg_PDD_damageEventTrigger = 0.0
set udg_PDD_damageEventTrigger = 1.0
set udg_PDD_damageEventTrigger = 0.0
// If the damage was modified, apply the rescue ability
if udg_PDD_amount != udg_PDD_pureAmount then
call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, GetWidgetLife(udg_PDD_target) + udg_PDD_pureAmount)
endif
// Check if a previous timer didn't yet expire
set targetId = GetHandleId(udg_PDD_target)
set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
// If this is the case, update the timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
set oldOriginalHealth = LoadReal(udg_PDD_h, targetId, 2)
set oldAmount = LoadReal(udg_PDD_h, targetId, 1)
set originalHealth = oldOriginalHealth - oldAmount
call SaveReal(udg_PDD_h, oldTimerId, 4, oldOriginalHealth)
endif
// Call after damage event if damage was spell, modified, code or parallel
if ( rawAmount < 0.0 or udg_PDD_pureAmount != udg_PDD_amount or oldTimerId != 0 or udg_PDD_allocatedAttacks > 0 ) then
set time = CreateTimer()
set id = GetHandleId(time)
// Save handles for after damage event
call SaveUnitHandle(udg_PDD_h, id, 0, udg_PDD_source)
call SaveUnitHandle(udg_PDD_h, id, 1, udg_PDD_target)
call SaveReal(udg_PDD_h, id, 2, udg_PDD_pureAmount)
call SaveReal(udg_PDD_h, id, 3, udg_PDD_amount)
call SaveReal(udg_PDD_h, id, 4, originalHealth)
// Save this extra to manage parallel damage instances
call SaveReal(udg_PDD_h, targetId, 0, GetWidgetLife(udg_PDD_target))
call SaveReal(udg_PDD_h, targetId, 1, udg_PDD_amount)
call SaveReal(udg_PDD_h, targetId, 2, originalHealth)
call SaveInteger(udg_PDD_h, targetId, 3, id)
// Avoid healing of negative spell damage
if rawAmount < 0.0 then
call DisableTrigger(udg_PDD_damageEvent)
call DealFixDamage(udg_PDD_source, udg_PDD_target, -rawAmount)
if ( originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call DealFixDamage(udg_PDD_source, udg_PDD_target, udg_PDD_amount)
endif
call EnableTrigger(udg_PDD_damageEvent)
endif
// Guarantee unit exploding
if originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE then
if rawAmount > 0.0 then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, udg_PDD_UNIT_MIN_LIFE)
endif
endif
// Start the after damage event
call TimerStart(time, 0.0, false, function AfterDamage)
endif
// Handle allocated attacks from UnitDamageTargetEx
if udg_PDD_totalAllocs == 0 then
set udg_PDD_totalAllocs = udg_PDD_allocatedAttacks
endif
if udg_PDD_allocatedAttacks > 0 then
set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks - 1
set udg_PDD_allocCounter = udg_PDD_allocCounter + 1
call TriggerEvaluate(udg_PDD_runAllocatedAttacks)
endif
// Reset all required variables
set udg_PDD_damageType = -1
set udg_PDD_totalAllocs = 0
set udg_PDD_allocCounter = -1
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////////
function RestoreTriggers takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Re-register units that are alive
if GetUnitTypeId(enumUnit) != 0 then
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
endif
set enumUnit = null
endfunction
function ClearMemory_Actions takes nothing returns nothing
local group g = CreateGroup()
local code c = function DamageEngine
// Reset the damage event
call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
call ResetTrigger(udg_PDD_damageEvent)
call DestroyTrigger(udg_PDD_damageEvent)
set udg_PDD_damageEvent = null
// Rebuild it then
set udg_PDD_damageEvent = CreateTrigger()
call TriggerAddCondition(udg_PDD_damageEvent, Filter(c))
call ForGroup(g, function RestoreTriggers)
// Clean things up
call DestroyGroup(g)
set g = null
set c = null
endfunction
function MapInit takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Register units on map initialization
call UnitAddAbility(enumUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(enumUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
set enumUnit = null
endfunction
function UnitEntersMap takes nothing returns nothing
local unit triggerUnit = GetTriggerUnit()
// Register units that enter the map
if ( GetUnitAbilityLevel(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR) < 1 ) then
call UnitAddAbility(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(triggerUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, triggerUnit, EVENT_UNIT_DAMAGED)
endif
set triggerUnit = null
endfunction
function RunAllocatedAttacks takes nothing returns nothing
local integer localAllocAttacks = udg_PDD_allocatedAttacks + 1
// Calculate the correct sequence of allocated attacks
set localAllocAttacks = localAllocAttacks - udg_PDD_totalAllocs + 1 + 2*udg_PDD_allocCounter
// Deal code damage if the unit isn't exploding
set udg_PDD_damageType = udg_PDD_CODE
if GetUnitLife(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1)) >= udg_PDD_UNIT_MIN_LIFE then
call UnitDamageTarget(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 0), LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1), LoadReal(udg_PDD_h, localAllocAttacks, 2), LoadBoolean(udg_PDD_h, localAllocAttacks, 3), LoadBoolean(udg_PDD_h, localAllocAttacks, 4), ConvertAttackType(LoadInteger(udg_PDD_h, localAllocAttacks, 5)), ConvertDamageType(LoadInteger(udg_PDD_h, localAllocAttacks, 6)), ConvertWeaponType(LoadInteger(udg_PDD_h, localAllocAttacks, 7)))
else
call FlushChildHashtable(udg_PDD_h, localAllocAttacks - 1)
endif
// Clean things up
call FlushChildHashtable(udg_PDD_h, localAllocAttacks)
endfunction
function InitTrig_DamageEvent takes nothing returns nothing
local group g = CreateGroup()
local region r = CreateRegion()
local trigger UnitEnters = CreateTrigger()
local trigger ClearMemory = CreateTrigger()
local code cDamageEngine = function DamageEngine
local code cUnitEnters = function UnitEntersMap
local code cClearMemory = function ClearMemory_Actions
local code cRunAllocatedAttacks = function RunAllocatedAttacks
// Initialize global variables
set udg_PDD_h = InitHashtable()
set udg_PDD_damageEvent = CreateTrigger()
set udg_PDD_damageHandler = CreateTrigger()
set udg_PDD_damageType = -1
set udg_PDD_allocatedAttacks = 0
set udg_PDD_runAllocatedAttacks = CreateTrigger()
// Initialize global configurable constants
call InitGlobalVariables()
// Initialize global fixed constants
set udg_PDD_PHYSICAL = 0
set udg_PDD_SPELL = 1
set udg_PDD_CODE = 2
set udg_PDD_UNIT_MIN_LIFE = 0.406
set udg_PDD_ATTACK_TYPE_UNIVERSAL = ConvertAttackType(7)
set udg_PDD_totalAllocs = 0
set udg_PDD_allocCounter = -1
set udg_PDD_damageEventTrigger = 0.0
// Register units on map initialization
call TriggerRegisterVariableEvent(udg_PDD_damageHandler, "udg_PDD_damageEventTrigger", EQUAL, 1.0)
call TriggerAddCondition(udg_PDD_damageEvent, Filter(cDamageEngine))
call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
call ForGroup(g, function MapInit)
// Register units that enter the map
call RegionAddRect(r, GetWorldBounds())
call TriggerRegisterEnterRegion(UnitEnters, r, null)
call TriggerAddCondition(UnitEnters, Filter(cUnitEnters))
// Register trigger for allocated attacks
call TriggerAddCondition(udg_PDD_runAllocatedAttacks, Filter(cRunAllocatedAttacks))
// Clear memory leaks
call TriggerRegisterTimerEvent(ClearMemory, udg_PDD_TRIGGER_CLEANUP_PERIOD, true)
call TriggerAddCondition(ClearMemory, Filter(cClearMemory))
// Clean things up
call DestroyGroup(g)
set UnitEnters = null
set ClearMemory = null
set cDamageEngine = null
set cUnitEnters = null
set cClearMemory = null
set cRunAllocatedAttacks = null
set g = null
set r = null
endfunction
//TESH.scrollpos=273
//TESH.alwaysfold=0
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Wietlol's Effect Over Time System 2.3.2 17/07/2015
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Description:
// This system is made to create and add effects that expire over time.
// Once in a while, which is configurable using the interval variable, the event "EOT_Event_On_Interval" is called.
// You can define your own actions on the On_Interval event.
// This system can be used as a buff system and there is an implemented extension for damage over time.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// How to install:
// 1. Copy or create all variables that are used in this map into your map.
// 1a. If you use vJASS then you can enable the EOT_vJASS_variables trigger and use that one.
// 1b. If you use GUI then you can use the EOT_GUI_variables trigger to automatically import them.
// 2. Copy the EOT_System trigger and paste it into your map.
// 2a. (optional) You can also copy the DOT_Extension trigger to make use of damage over time effects.
// 3. Copy all code from the header file and paste it into your map's header file.
// 4. Create some spells with EOTs.
// 5. Enjoy your Effect Over Time Spells.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// How to use:
// Create an EOT:
// 1. Create a trigger for your spell.
// 2. Make a "Custom script: call EOT_Set_Default_Variables()".
// 3. Set the EOT_Param_Source and EOT_Param_Target to the proper units.
// 4. Set EOT_Param_Type to a variable specific for that type of EOT.
// For abilities, you can use the id of the ability (which is the same for every casting of that ability).
// You cannot use the handle id of a unit for example but you can use the unit-type id.
// When you want subtypes of an EOT, you can put those inside the EOT_Param_Subtype.
// 5. Set additional data for the EOT.
// 5a. Set EOT_Param_Duration and EOT_Param_Interval.
// If the duration is not specified or is 0 or lower, the duration is infinite.
// If the interval is not specified or is 0 or lower, the EOT will not have intervals.
// 5b. Set EOT_Param_Buff and EOT_Param_Buff_Holder.
// If EOT_Param_Buff_Holder is not specified, this EOT will not display a buff.
// If EOT_Param_Buff_Holder is specified, this EOT will have the buff "EOT_Param_Buff".
// 5c. Set EOT_Param_Special_Effect_Model and EOT_Param_Special_Effect_Point.
// If EOT_Param_Special_Effect_Model is not specified, this EOT will not have a special effect.
// If EOT_Param_Special_Effect_Point is not specifid, the attachment point "origin" will be used.
// 5d. Set EOT_Param_Abiliy and EOT_Param_Abiliy_Level.
// If EOT_Param_Abiliy is not specified or EOT_Param_Abiliy_Level is set to 0 (1 by default), this EOT will not have an ability.
// Be aware that the ability given is showed in the UI. If you do not want this, add the ability to a disabled spellbook.
// 5e. Set EOT_Param_Positive and EOT_Param_Can_Dispell.
// These variables are used as buff type variables.
// EOT_Param_Positive is false by default, meaning that the EOT has a negative attitude.
// When the EOT_Trigger_Remove_EOTs is called, you can specify if you want to remove positive, negative, both or neither of them.
// EOT_Param_Can_Dispell is true by default, meaning that the EOT can be dispelled.
// If it is set to false, the EOT will not dispell unless you set EOT_Param_Force_Destroy to true before the dispell is called.
// 5f. Set EOT_Param_Is_Passive to true if the EOT must not be removed on death.
// This is usefull for units with passive abilities.
// You can destroy these EOTs only with EOT_Param_Destroy_Passive.
// 6. Call the EOT_Trigger_Create_EOT trigger.
// 7. Create additional effects.
// Since you created an EOT, you also have an id.
// With this id, you can save data in the hashtable using the EOT_Save_Value (Value being the value type) functions.
//
// Using the EOT_System's events:
// 1. Create a trigger.
// 2. Create an event of "Game - Value Of Real Variable" and set the variable to the event you want. Leave the value to 0.
// For spells you can use:
// - EOT_Event_An_EOT_Is_Created
// - EOT_Event_An_EOT_Is_Destroyed
// - EOT_Event_An_EOT_Is_Dispelled
// - EOT_Event_An_EOT_Has_Expired
// - EOT_Event_On_Interval
// All other events are reserved for extensions and systems.
// 3. Now you have the data of your EOT in the Param variables.
// You can stop the destruction or dispell of an EOT by setting EOT_Param_Destroy to false.
// You can stop the expiring of an EOT by setting EOT_Param_Expire to false.
// (For actions on certain EOTs, you can also choose to run a trigger on the interval instead of using the event.
// this improves performance very much.)
//
// Accessing and modifying an EOT's data:
// 1. Set the EOT_Param_Target to the unit that has the EOT.
// 2. Set the EOT_Param_Type to the type of EOT that you want.
// 3. Make an If/Then/Else function.
// 3a. Create a condition of "Boolean Comparison -> Trigger - Evaluate Trigger Conditions".
// Set the trigger to EOT_Trigger_Get_Data.
// 4. Now you know if the target has the EOT or not.
// If the target has it, (which means that the condition is right,) the data of the EOT is set in the Param variables.
// 5. Now you can also save the data of the Param variables (which you can change between these two function) by calling
// the EOT_Trigger_Save_Data trigger.
//
// The additional data has some reserved slots. The first 1.000 slots are reserved for extensions or other systems.
// However when calling the EOT_Save_Value functions, the 1.000 are automatically added.
// So when making spells, you can start with 0.
// When making extensions or systems, you have to descend, starting at -1.
// The extension DOT (Damage Over Time) uses the last 3 of them (-1, -2, -3, aka 999, 998, 997).
// Extensions/Systems cannot use the same indexes as other extensions/systems.
//
// The same counts for the EOT cache.
// The first 100 cache slot are reserved.
// The extension DOT (Damage Over Time) does not use an EOT cache.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Feature list:
// This system:
// - allows you to create an effect over time on a unit.
// - allows you to give a unit a buff as long as the eot lasts.
// - allows you to give a unit an ability as long as the eot lasts.
// - allows you to run a piece of code once in a while as long as the eot lasts.
// - allows you to attach a special effect to an eot.
// - allows you to change the parameters of the eot.
// - allows you to get the data, change the data and save the data of every eot that is active.
// - allows you to create your own extensions to make better use of the system.
// - allows you to save the data of an eot in the cache. The first 100 are reserved for systems and extensions.
// This can be used for either presets, already having the references to units, and creation/modification of other eot's inside an eot's function.
// - allows you to save additional data to an eot.
// The first 1000 are reserved for systems and extensions.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Variable explaination:
//////////////////////////
// General:
// - EOT_Trigger_Create_EOT - trigger
// This is the function that creates an eot on a unit.
//
// - EOT_Trigger_Destroy_EOT - trigger
// This is the function that destroys the specified eot on the targeted unit.
//
// - EOT_Trigger_Get_Data - trigger
// This is the function that retrieves all the data of the specified eot on the targeted unit.
//
// - EOT_Trigger_Save_Data - trigger
// This is the function that saves all the variables to the specified eot on the targeted unit.
//
// - EOT_Trigger_Remove_EOTs - trigger
// This is the function that removes all or filtered eots on the targeted unit.
//
// - EOT_Hashtable - hashtable
// This is the hashtable that is used by the Effect Over Time System.
//
// - EOT_Index - integer
// This integer is used as an indexing number in loops.
//
// - EOT_Amount - integer
// This is the amount of EOTs that are active.
//
// - EOT_Unique_Id - integer
// This is a unique number that increases for each EOT.
//
// - EOT_Param_Destroy - booleam
// This boolean tells if the EOT must be destroyed.
//
// - EOT_Param_Expire - boolean
// This boolean tells if the EOT is expired and if it has to be destroyed.
// This one is additional to EOT_Destroy because expired EOTs might be able to keep going
// on certain conditions while destroyed EOTs may not.
//
// - EOT_Param_Force_Destroy - boolean
// This boolean tells if the destruction of an EOT must go through Can_Dispell values.
// It can also be used as an additional Destroy variable.
//
// - EOT_Param_Destroy_Passive - boolean
// This boolean tells if the Destroy function must remove a passive effect.
// This is the only way to remove the passive effects.
//
//////////////////////////
// Events:
// Events must be called with "Real value becomes equal to 0"
// - EOT_Event_An_EOT_Is_Created - real (event simulator)
// This event is ran when an eot is created.
// EOT_Event_Creation_Before and EOT_Event_Creation_After are reserved for other systems and extensions.
//
// - EOT_Event_An_EOT_Is_Destroyed - real (event simulator)
// This event is ran when an eot is destroyed.
// If an EOT is destroyed in any possible way (expired, dispelled, bugs, etc.) then this event will see it.
// EOT_Event_Destruction_Before and EOT_Event_Destruction_After are reserved for other systems and extensions.
//
// - EOT_Event_An_EOT_Is_Dispelled - real (event simulator)
// This event is ran when an eot is dispelled.
// Dispelling can be done via Remove_EOTs function
// or on the next interval by having their buff removed. (non-hidden only)
// EOT_Event_Dispell_Before and EOT_Event_Dispell_After are reserved for other systems and extensions.
//
// - EOT_Event_An_EOT_Has_Expired - real (event simulator)
// This event is ran when an eot has properly expired.
// EOT_Event_Expire_Before and EOT_Event_Expire_After are reserved for other systems and extensions.
//
// - EOT_Event_On_Interval - real (event simulator)
// This event is ran when the interval is activated.
// EOT_Event_Interval_Before and EOT_Event_Interval_After are reserved for other systems and extensions.
//
// - EOT_Event_Get_Data - real (event simulator)
// This event is made for extensions to know when a trigger called the "Get Data" function.
//
// - EOT_Event_Save_Data - real (event simulator)
// This event is made for extensions to know when a trigger called the "Save Data" function.
//
// - EOT_Event_Null_Variables - real (event simulator)
// This event is made for extensions to know when a trigger called the "Null Variables" function.
//
// - EOT_Event_EOT_Changed_Target - real (event simulator)
// This event fires when an EOT is changing targets.
// The target in the array under the index is the old target and the target in the param is the new target.
//
//////////////////////////
// Parameters:
// - EOT_Array_... - ... array
// These variables are the parameters of EOTs saved for each active EOT.
//
// - EOT_Param_Id - integer
// This is a unique Id of the EOT.
// This value can be used to save additional data to an EOT.
// This is similar to a handle id... but then an EOT id.
//
// - EOT_Param_Source - unit
// This is the source of the eot.
// This unit gets the credit for the kills, or whatever the eot is doing.
//
// - EOT_Param_Target - unit
// This is the unit on which the eot runs.
//
// - EOT_Param_Duration - real
// This is the duration of the eot.
// Be aware that this is not the remaining duration.
//
// - EOT_Param_Remaining_Duration - real
// This is the remaining duration of the eot.
//
// - EOT_Param_Interval - real
// This is the duration between each call of the trigger of the eot.
// Be aware that this is not the remaining interval.
//
// - EOT_Param_Remaining_Interval - real
// This is the remaining duration between each call of the trigger of the eot.
//
// - EOT_Param_Hidden - boolean
// If the eot is hidden, it will not display a buff.
// When removing all eots, you can filter out hidden eots.
//
// - EOT_Param_Buff - buff (integer in JASS)
// This is the buff that the target has if the eot is not hidden.
//
// - EOT_Param_Buff_Holder - ability (integer in JASS)
// This is the ability that makes the buff for the target.
//
// - EOT_Param_Buff_Holder_Level - integer
// This is the level for the ability that makes the buff.
// This can be used to show different buffs or use an effect that is on that ability.
//
// - EOT_Param_Ability - ability (integer in JASS)
// This ability is given to the target and removed when the eot ends.
//
// - EOT_Param_Ability_Level - integer
// This is the level of the EOT_Param_Ability.
//
// - EOT_Param_Positive - boolean
// This determines if the effect is positive or negative.
// This is used to filter out positive or negative effects.
// This is also used by the Remove_EOTs to know if positive EOTs should be removed.
//
// - EOT_Param_Negative - boolean
// This is used by the Remove_EOTs to know if negative EOTs should be removed.
//
// - EOT_Param_Special_Effect - special effect (effect in JASS)
// This is a special effect that is attached to the target.
// You should not make the effect yourself but rather define the model and attachment point.
//
// - EOT_Param_Special_Effect_Model - string
// This is the filepath of the model that is used to create the special effect.
//
// - EOT_Param_Special_Effect_Point - string
// This is the attachment point for the special effect.
//
// - EOT_Param_Type - integer
// This variable is a simple integer that can be used as the type of EOT.
// The easiest way to make this is to set it to an ability id which created the EOT.
//
// - EOT_Param_Subtype - integer
// This variable is a simple integer that can be used to give one type multiple subtypes.
//
// - EOT_Param_Subtype2 - integer
// This variable is a simple integer that can be used to give and EOT even better MUI-ness.
//
// - EOT_Param_Is_Paused - integer
// Paused EOTs will not expire or call the interval.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Changelog:
// 2.3.1 - 17/07/2015 - Fixed death bug and added OnPeriodTrigger
// - Fixed a bug where an EOT was not removed when a unit died.
// - Re-added the option to run a trigger on the periods.
// - Removed AEM implementation.
//
// 2.3 - 17/04/2015 - Better Events
// - Added AEM Events implementation.
// - Improved Death checks.
// - Created EOT_Does_Exist().
//
// 2.2.2 - 25/03/2015 - Ultimate MUI-ness
// - Added Subtype2 as an additional type. This can be used as sourceid for example to have even better MUI-ness.
// - Added the event "EOT_Event_EOT_Changed_Target".
// - Added the paused functionality.
//
// 2.2.1 - 01/03/2015 - Fixed dead unit crash.
// - Fixed a bug where the game would crash when a dead unit would gain an EOT.
//
// 2.2 - 20/02/2015 - Added Is_Passive and fixed a few bugs.
// - Changed the variable type of EOT_Type from real to integer.
// This is because a real has a much lower maximum than an integer.
// The maximum would be a little bit below the value of ability ids.
// Subtypes can be declared in the new variable: EOT_Subtype.
// - Fixed a bug where the Id would be changed to the highest current Id. When an eot would be destroyed.
// - Added Is_Passive and Destroy_Passive.
// The Is_Passive is used for passive abilities.
// They can only be removed using a manual Destroy call while Destroy_Passive is turned on.
//
// 2.1 - 13/02/2015 - Finished the system. All upcoming updates are fixes.
// Code:
// - Replaced redundant code with "EOT_Check_For_New_Target".
// - Changed the name of "EOT_Null_Variables" to "EOT_Set_Default_Variables" which makes more sense.
// - Added a disabled trigger with all GUI variables.
// - Now has a better order of which event/check is called first in the looping action.
// - Now you don't have to set the hidden parameter in the creation. Just leaving the buff open is enough.
// - Removed some bugs where ids would be changed.
//
// 2.0.1 - 10/02/2015 - Fixed event simulators.
// Code:
// - The events now run on 0 and are separated to remove non-calling bugs.
//
// 2.0 - 10/02/2015 - Rewritten the system from timers to arrays.
//
// Documentation:
// - Updated for new functions and variables.
// Code:
// - Rewritten the whole code.
// - Ripped the code into triggers only.
// - Added hashtable functions in the header.
// - Added cache functions in the header.
// - Damage transferred to an extension to remove a lot of empty values in the arrays.
// Added Features:
// - Now has a cache where you can save the current EOT in or load a saved EOT from.
// This can be used as presets or when you want to create a new one during the interval.
// - Now you can save additional data to an EOT.
// - Events are now handled better to function with extensions properly and create
// - You can now leave unnecessary data open. The variables are set to their standard values.
// - You can now set the level of the buff holder.
// - Added the Force_Destroy variable which allows you to break through the Can_Dispell value.
// Bug Fixes:
// - The EOT is not removed if you set a too high interval.
// - The Special Effect is now recreated properly if the EOT changed targets, effect-model or attachment point.
// - The EOT is now removed immediately when the buff is removed.
//
// 1.2 - 27/01/2015 - Update of simplified system.
//
// Documentation:
// - Added the complete documentation.
// Code:
// - Put all code of the system in one trigger with exception of the configuration and made it more readable.
// - Completed the buff system.
// Added Features:
// - Added an ability that is active on the unit as long as the eot exists.
// - Automatically removes or adds existing eots depending on a configurable, eot-dependant variable.
// - Now allows the player to change the target of the effect over time.
// Bug Fixes:
// - Fixed a bug where an eot which would not last until the next interval would be removed at that moment
// rather than when the duration expires.
//
// 1.1 - 20/01/2015 - Update of reworked system.
//
// Added Features:
// - Added the Get_Data and Save_Data functions.
// Bug Fixes:
// - Fixed a bug where an eot which was already active on the target would have been removed when the first expired.
//
// 1.0 - First official release on the Hive.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Known bugs:
// - The buffs of EOTs are aura buffs. This means that they are not dispelled by buff dispell abilities by default.
// To be able to dispell the buffs you have to trigger all buff dispel abilities.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// These functions are used by this system only.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Check if the EOT has a new target. If so transfer buff, ability and special effect to the new target.
function EOT_Check_For_New_Target takes integer index returns nothing
//Check for new target.
if udg_EOT_Param_Target != udg_EOT_Array_Target[index] then
//remove and add ability
call UnitRemoveAbility(udg_EOT_Array_Target[index], udg_EOT_Array_Ability[index])
if udg_EOT_Param_Ability > 0 and udg_EOT_Param_Ability_Level > 0 then
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Ability)
call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
endif
//remove and add buff
call UnitRemoveAbility(udg_EOT_Array_Target[index], udg_EOT_Array_Buff[index])
if udg_EOT_Param_Buff_Holder > 0 and udg_EOT_Param_Buff_Holder_Level > 0 then
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Buff_Holder_Level)
call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
endif
//remove and add special effect.
call DestroyEffect(udg_EOT_Param_Special_Effect)
if udg_EOT_Param_Special_Effect_Model != "" then
if udg_EOT_Param_Special_Effect_Point == "" then
set udg_EOT_Param_Special_Effect_Point = "origin"
endif
set udg_EOT_Param_Special_Effect = AddSpecialEffectTarget(udg_EOT_Param_Special_Effect_Model, udg_EOT_Param_Target, udg_EOT_Param_Special_Effect_Point)
endif
endif
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This code is the actions of this system.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is the loop for every 0.03 seconds of gametime.
function EOT_Interval takes nothing returns nothing
local integer i
set i = 0
loop
set udg_EOT_Index = i
exitwhen udg_EOT_Index > udg_EOT_Amount
//Set global variables.
set udg_EOT_Param_Destroy = false
set udg_EOT_Param_Expire = false
set udg_EOT_Param_Force_Destroy = false
set udg_EOT_Param_Id = udg_EOT_Array_Id[udg_EOT_Index]
set udg_EOT_Param_Source = udg_EOT_Array_Source[udg_EOT_Index]
set udg_EOT_Param_Target = udg_EOT_Array_Target[udg_EOT_Index]
set udg_EOT_Param_Duration = udg_EOT_Array_Duration[udg_EOT_Index]
set udg_EOT_Param_Remaining_Duration = udg_EOT_Array_Remaining_Duration[udg_EOT_Index]
set udg_EOT_Param_Interval = udg_EOT_Array_Interval[udg_EOT_Index]
set udg_EOT_Param_Remaining_Interval = udg_EOT_Array_Remaining_Interval[udg_EOT_Index]
set udg_EOT_Param_Hidden = udg_EOT_Array_Hidden[udg_EOT_Index]
set udg_EOT_Param_Buff = udg_EOT_Array_Buff[udg_EOT_Index]
set udg_EOT_Param_Buff_Holder = udg_EOT_Array_Buff_Holder[udg_EOT_Index]
set udg_EOT_Param_Buff_Holder_Level = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]
set udg_EOT_Param_Ability = udg_EOT_Array_Ability[udg_EOT_Index]
set udg_EOT_Param_Ability_Level = udg_EOT_Array_Ability_Level[udg_EOT_Index]
set udg_EOT_Param_Type = udg_EOT_Array_Type[udg_EOT_Index]
set udg_EOT_Param_Subtype = udg_EOT_Array_Subtype[udg_EOT_Index]
set udg_EOT_Param_Positive = udg_EOT_Array_Positive[udg_EOT_Index]
set udg_EOT_Param_Can_Dispell = udg_EOT_Array_Can_Dispell[udg_EOT_Index]
set udg_EOT_Param_Is_Passive = udg_EOT_Array_Is_Passive[udg_EOT_Index]
set udg_EOT_Param_Special_Effect = udg_EOT_Array_Special_Effect[udg_EOT_Index]
set udg_EOT_Param_Special_Effect_Model = udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]
set udg_EOT_Param_Special_Effect_Point = udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]
//Decrease remaining duration.
set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Remaining_Duration - 0.03
if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 and udg_EOT_Param_Is_Passive then
if udg_EOT_Param_Remaining_Duration <= 0. and udg_EOT_Param_Remaining_Duration > -1 then
set udg_EOT_Param_Expire = true
//Call the expire event.
set udg_EOT_Event_Expire_Before = 1 //<<< don't use
set udg_EOT_Event_Expire_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Has_Expired = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Has_Expired = 0 //<<< use this
set udg_EOT_Event_Expire_After = 1 //<<< don't use
set udg_EOT_Event_Expire_After = 0 //<<< use this
call EOT_Check_For_New_Target(i)
endif
else
set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Remaining_Interval - 0.03
if GetUnitTypeId(udg_EOT_Param_Target) == 0 or (GetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff) == 0 and not(udg_EOT_Param_Hidden)) or IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) then
if GetUnitTypeId(udg_EOT_Param_Target) == 0 or IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) then
set udg_EOT_Param_Destroy_Passive = true
set udg_EOT_Param_Destroy = true
elseif not udg_EOT_Param_Can_Dispell then
//This eot may not be dispelled.
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
//call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
else
set udg_EOT_Param_Destroy = true
//Call the dispell event.
set udg_EOT_Event_Dispell_Before = 1 //<<< don't use
set udg_EOT_Event_Dispell_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Is_Dispelled = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Is_Dispelled = 0 //<<< use this
set udg_EOT_Event_Dispell_After = 1 //<<< don't use
set udg_EOT_Event_Dispell_After = 0 //<<< use this
endif
call EOT_Check_For_New_Target(i)
endif
if not(udg_EOT_Param_Destroy) then
if udg_EOT_Param_Remaining_Interval <= 0. and udg_EOT_Param_Remaining_Interval > -1. and (udg_EOT_Param_Remaining_Interval <= udg_EOT_Param_Remaining_Duration or udg_EOT_Param_Duration == -1.) then
set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Remaining_Interval + udg_EOT_Param_Interval
set udg_EOT_Event_Interval_Before = 1 //<<< don't use
set udg_EOT_Event_Interval_Before = 0 //<<< use this
set udg_EOT_Event_On_Interval = 1 //<<< don't use
set udg_EOT_Event_On_Interval = 0 //<<< use this
set udg_EOT_Event_Interval_After = 1 //<<< don't use
set udg_EOT_Event_Interval_After = 0 //<<< use this
//Check for new target.
call EOT_Check_For_New_Target(i)
endif
endif
if not(udg_EOT_Param_Destroy) then
//Check if EOT has expired.
if udg_EOT_Param_Remaining_Duration <= 0. and udg_EOT_Param_Remaining_Duration > -1. then
set udg_EOT_Param_Expire = true
//Call the expire event.
set udg_EOT_Event_Expire_Before = 1 //<<< don't use
set udg_EOT_Event_Expire_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Has_Expired = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Has_Expired = 0 //<<< use this
set udg_EOT_Event_Expire_After = 1 //<<< don't use
set udg_EOT_Event_Expire_After = 0 //<<< use this
call EOT_Check_For_New_Target(i)
endif
endif
//Update ability level.
if udg_EOT_Param_Ability > 0 then
call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
endif
//Update buff.
if not(udg_EOT_Param_Hidden) then
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
//call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
endif
endif
//Update new values.
set udg_EOT_Array_Source[i] = udg_EOT_Param_Source
set udg_EOT_Array_Target[i] = udg_EOT_Param_Target
set udg_EOT_Array_Duration[i] = udg_EOT_Param_Duration
set udg_EOT_Array_Remaining_Duration[i] = udg_EOT_Param_Remaining_Duration
set udg_EOT_Array_Interval[i] = udg_EOT_Param_Interval
set udg_EOT_Array_Remaining_Interval[i] = udg_EOT_Param_Remaining_Interval
set udg_EOT_Array_Hidden[i] = udg_EOT_Param_Hidden
set udg_EOT_Array_Buff[i] = udg_EOT_Param_Buff
set udg_EOT_Array_Buff_Holder[i] = udg_EOT_Param_Buff_Holder
set udg_EOT_Array_Buff_Holder_Level[i] = udg_EOT_Param_Buff_Holder_Level
set udg_EOT_Array_Ability[i] = udg_EOT_Param_Ability
set udg_EOT_Array_Ability_Level[i] = udg_EOT_Param_Ability_Level
set udg_EOT_Array_Type[i] = udg_EOT_Param_Type
set udg_EOT_Array_Subtype[i] = udg_EOT_Param_Subtype
set udg_EOT_Array_Positive[i] = udg_EOT_Param_Positive
set udg_EOT_Array_Can_Dispell[i] = udg_EOT_Param_Can_Dispell
set udg_EOT_Array_Is_Passive[i] = udg_EOT_Param_Is_Passive
set udg_EOT_Array_Special_Effect[i] = udg_EOT_Param_Special_Effect
set udg_EOT_Array_Special_Effect_Model[i] = udg_EOT_Param_Special_Effect_Model
set udg_EOT_Array_Special_Effect_Point[i] = udg_EOT_Param_Special_Effect_Point
//Destroy.
if udg_EOT_Param_Destroy or udg_EOT_Param_Expire or udg_EOT_Param_Force_Destroy then
call TriggerExecute(udg_EOT_Trigger_Destroy_EOT)
set i = i - 1
endif
//Next EOT.
set i = i + 1
endloop
call EOT_Set_Default_Variables()
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This code is the functions that this system has.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This function checks if the EOT exists.
function EOT_Does_Exist takes nothing returns boolean
set udg_EOT_Index = 0
loop
exitwhen udg_EOT_Index > udg_EOT_Amount
if udg_EOT_Param_Target == udg_EOT_Array_Target[udg_EOT_Index] and udg_EOT_Param_Type == udg_EOT_Array_Type[udg_EOT_Index] and udg_EOT_Param_Subtype == udg_EOT_Array_Subtype[udg_EOT_Index] then
return true
endif
set udg_EOT_Index = udg_EOT_Index + 1
endloop
return false
endfunction
//This function creates a new EOT.
function EOT_Create_EOT takes nothing returns nothing
//Requires:
// - udg_EOT_Param_Source : unit
// - udg_EOT_Param_Target : unit
// - udg_EOT_Param_Type : integer
//Optional:
// - udg_EOT_Param_Subtype : integer
// - udg_EOT_Param_Duration : real
// - udg_EOT_Param_Interval : real
// - udg_EOT_Param_Buff : integer (buff)
// - udg_EOT_Param_Buff_Holder : integer (ability)
// - udg_EOT_Param_Buff_Holder_Level : integer
// - udg_EOT_Param_Ability : integer (ability)
// - udg_EOT_Param_Ability_Level : integer
// - udg_EOT_Param_Positive : boolean
// - udg_EOT_Param_Can_Dispell : boolean
// - udg_EOT_Param_Is_Passive : boolean
// - udg_EOT_Param_Special_Effect_Model : string
// - udg_EOT_Param_Special_Effect_Point : string
//If target is dead then don't do SHIT!
if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 then
return
endif
//If the duration is 0 or lower then dset the duration to -1 (infinite).
if udg_EOT_Param_Duration <= 0. then
set udg_EOT_Param_Duration = -1.
endif
//Update the old EOT if that one existed.
if EOT_Does_Exist() then
set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Duration
call TriggerExecute(udg_EOT_Trigger_Save_Data)
return
endif
//Add the buff if applyable.
if udg_EOT_Param_Buff_Holder > 0 and udg_EOT_Param_Buff_Holder_Level > 0 then
set udg_EOT_Param_Hidden = false
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
//call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder, udg_EOT_Param_Buff_Holder_Level) << removed because of bug with auras.
call UnitRemoveAbility(udg_EOT_Param_Target, udg_EOT_Param_Buff_Holder)
else
set udg_EOT_Param_Hidden = true
endif
//Add the ability if applyable.
if udg_EOT_Param_Ability > 0 and udg_EOT_Param_Ability_Level > 0 then
call UnitAddAbility(udg_EOT_Param_Target, udg_EOT_Param_Ability)
call SetUnitAbilityLevel(udg_EOT_Param_Target, udg_EOT_Param_Ability, udg_EOT_Param_Ability_Level)
endif
//Make a special effect.
if udg_EOT_Param_Special_Effect_Model != "" then
if udg_EOT_Param_Special_Effect_Point == "" or udg_EOT_Param_Special_Effect_Point == null then
set udg_EOT_Param_Special_Effect_Point = "origin"
endif
set udg_EOT_Param_Special_Effect = AddSpecialEffectTarget(udg_EOT_Param_Special_Effect_Model, udg_EOT_Param_Target, udg_EOT_Param_Special_Effect_Point)
endif
set udg_EOT_Param_Remaining_Duration = udg_EOT_Param_Duration
set udg_EOT_Param_Remaining_Interval = udg_EOT_Param_Interval
set udg_EOT_Amount = udg_EOT_Amount + 1
set udg_EOT_Unique_Id = udg_EOT_Unique_Id + 1
set udg_EOT_Param_Id = udg_EOT_Unique_Id
call SaveInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, 0, udg_EOT_Amount)
//Call the event.
set udg_EOT_Event_Creation_Before = 1 //<<< don't use
set udg_EOT_Event_Creation_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Is_Created = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Is_Created = 0 //<<< use this
set udg_EOT_Event_Creation_After = 1 //<<< don't use
set udg_EOT_Event_Creation_After = 0 //<<< use this
set udg_EOT_Array_Id[udg_EOT_Amount] = udg_EOT_Param_Id
set udg_EOT_Array_Source[udg_EOT_Amount] = udg_EOT_Param_Source
set udg_EOT_Array_Target[udg_EOT_Amount] = udg_EOT_Param_Target
set udg_EOT_Array_Duration[udg_EOT_Amount] = udg_EOT_Param_Duration
set udg_EOT_Array_Remaining_Duration[udg_EOT_Amount] = udg_EOT_Param_Remaining_Duration
set udg_EOT_Array_Interval[udg_EOT_Amount] = udg_EOT_Param_Interval
set udg_EOT_Array_Remaining_Interval[udg_EOT_Amount] = udg_EOT_Param_Remaining_Interval
set udg_EOT_Array_Hidden[udg_EOT_Amount] = udg_EOT_Param_Hidden
set udg_EOT_Array_Buff[udg_EOT_Amount] = udg_EOT_Param_Buff
set udg_EOT_Array_Buff_Holder[udg_EOT_Amount] = udg_EOT_Param_Buff_Holder
set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount] = udg_EOT_Param_Buff_Holder_Level
set udg_EOT_Array_Ability[udg_EOT_Amount] = udg_EOT_Param_Ability
set udg_EOT_Array_Ability_Level[udg_EOT_Amount] = udg_EOT_Param_Ability_Level
set udg_EOT_Array_Type[udg_EOT_Amount] = udg_EOT_Param_Type
set udg_EOT_Array_Subtype[udg_EOT_Amount] = udg_EOT_Param_Subtype
set udg_EOT_Array_Positive[udg_EOT_Amount] = udg_EOT_Param_Positive
set udg_EOT_Array_Can_Dispell[udg_EOT_Amount] = udg_EOT_Param_Can_Dispell
set udg_EOT_Array_Is_Passive[udg_EOT_Amount] = udg_EOT_Param_Is_Passive
set udg_EOT_Array_Special_Effect[udg_EOT_Amount] = udg_EOT_Param_Special_Effect
set udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount] = udg_EOT_Param_Special_Effect_Model
set udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount] = udg_EOT_Param_Special_Effect_Point
//Start the timer if this is the only EOT.
if udg_EOT_Amount == 0 then
call TimerStart(udg_EOT_Timer, 0.03, true, function EOT_Interval)
endif
return
endfunction
//This function destroys an EOT.
function EOT_Destroy_EOT takes nothing returns boolean
//Requires:
// - udg_EOT_Index : integer
set udg_EOT_Param_Destroy = true
//Call the destroy event.
set udg_EOT_Event_Destruction_Before = 1 //<<< don't use
set udg_EOT_Event_Destruction_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Is_Destroyed = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Is_Destroyed = 0 //<<< use this
set udg_EOT_Event_Destruction_After = 1 //<<< don't use
set udg_EOT_Event_Destruction_After = 0 //<<< use this
//Destroy the EOT.
if not(udg_EOT_Param_Is_Passive) or udg_EOT_Param_Destroy_Passive then
if udg_EOT_Param_Destroy or udg_EOT_Param_Force_Destroy then
call DestroyEffect(udg_EOT_Array_Special_Effect[udg_EOT_Index])
call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Buff_Holder[udg_EOT_Index])
call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Buff[udg_EOT_Index])
call UnitRemoveAbility(udg_EOT_Array_Target[udg_EOT_Index], udg_EOT_Array_Ability[udg_EOT_Index])
call FlushChildHashtable(udg_EOT_Hashtable, udg_EOT_Array_Id[udg_EOT_Index])
set udg_EOT_Array_Id[udg_EOT_Index] = udg_EOT_Array_Id[udg_EOT_Amount]
call SaveInteger(udg_EOT_Hashtable, udg_EOT_Array_Id[udg_EOT_Index], 0, udg_EOT_Index)
set udg_EOT_Array_Source[udg_EOT_Index] = udg_EOT_Array_Source[udg_EOT_Amount]
set udg_EOT_Array_Target[udg_EOT_Index] = udg_EOT_Array_Target[udg_EOT_Amount]
set udg_EOT_Array_Duration[udg_EOT_Index] = udg_EOT_Array_Duration[udg_EOT_Amount]
set udg_EOT_Array_Remaining_Duration[udg_EOT_Index] = udg_EOT_Array_Remaining_Duration[udg_EOT_Amount]
set udg_EOT_Array_Interval[udg_EOT_Index] = udg_EOT_Array_Interval[udg_EOT_Amount]
set udg_EOT_Array_Remaining_Interval[udg_EOT_Index] = udg_EOT_Array_Remaining_Interval[udg_EOT_Amount]
set udg_EOT_Array_Hidden[udg_EOT_Index] = udg_EOT_Array_Hidden[udg_EOT_Amount]
set udg_EOT_Array_Buff[udg_EOT_Index] = udg_EOT_Array_Buff[udg_EOT_Amount]
set udg_EOT_Array_Buff_Holder[udg_EOT_Index] = udg_EOT_Array_Buff_Holder[udg_EOT_Amount]
set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index] = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount]
set udg_EOT_Array_Ability[udg_EOT_Index] = udg_EOT_Array_Ability[udg_EOT_Amount]
set udg_EOT_Array_Ability_Level[udg_EOT_Index] = udg_EOT_Array_Ability_Level[udg_EOT_Amount]
set udg_EOT_Array_Type[udg_EOT_Index] = udg_EOT_Array_Type[udg_EOT_Amount]
set udg_EOT_Array_Subtype[udg_EOT_Index] = udg_EOT_Array_Subtype[udg_EOT_Amount]
set udg_EOT_Array_Positive[udg_EOT_Index] = udg_EOT_Array_Positive[udg_EOT_Amount]
set udg_EOT_Array_Can_Dispell[udg_EOT_Index] = udg_EOT_Array_Can_Dispell[udg_EOT_Amount]
set udg_EOT_Array_Is_Passive[udg_EOT_Index] = udg_EOT_Array_Is_Passive[udg_EOT_Amount]
set udg_EOT_Array_Special_Effect[udg_EOT_Index] = udg_EOT_Array_Special_Effect[udg_EOT_Amount]
set udg_EOT_Array_Special_Effect_Model[udg_EOT_Index] = udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount]
set udg_EOT_Array_Special_Effect_Point[udg_EOT_Index] = udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount]
set udg_EOT_Array_Id[udg_EOT_Amount] = 0
set udg_EOT_Array_Source[udg_EOT_Amount] = null
set udg_EOT_Array_Target[udg_EOT_Amount] = null
set udg_EOT_Array_Duration[udg_EOT_Amount] = 0.
set udg_EOT_Array_Remaining_Duration[udg_EOT_Amount] = 0.
set udg_EOT_Array_Interval[udg_EOT_Amount] = 0.
set udg_EOT_Array_Remaining_Interval[udg_EOT_Amount] = 0.
set udg_EOT_Array_Hidden[udg_EOT_Amount] = false
set udg_EOT_Array_Buff[udg_EOT_Amount] = 0
set udg_EOT_Array_Buff_Holder[udg_EOT_Amount] = 0
set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Amount] = 0
set udg_EOT_Array_Ability[udg_EOT_Amount] = 0
set udg_EOT_Array_Ability_Level[udg_EOT_Amount] = 0
set udg_EOT_Array_Type[udg_EOT_Amount] = 0
set udg_EOT_Array_Subtype[udg_EOT_Amount] = 0
set udg_EOT_Array_Positive[udg_EOT_Amount] = false
set udg_EOT_Array_Can_Dispell[udg_EOT_Amount] = false
set udg_EOT_Array_Is_Passive[udg_EOT_Amount] = false
set udg_EOT_Array_Special_Effect[udg_EOT_Amount] = null
set udg_EOT_Array_Special_Effect_Model[udg_EOT_Amount] = ""
set udg_EOT_Array_Special_Effect_Point[udg_EOT_Amount] = ""
set udg_EOT_Amount = udg_EOT_Amount - 1
if udg_EOT_Amount < 0 then
call PauseTimer(udg_EOT_Timer)
endif
set udg_EOT_Param_Destroy = false
set udg_EOT_Param_Force_Destroy = false
set udg_EOT_Param_Destroy_Passive = false
return true
endif
endif
set udg_EOT_Param_Destroy = false
set udg_EOT_Param_Force_Destroy = false
set udg_EOT_Param_Destroy_Passive = false
return false
endfunction
//This function retrieves the data of an EOT and set the Param variables to that data.
function EOT_Get_Data takes nothing returns boolean
//Requires:
// - udg_EOT_Param_Target : unit
// - udg_EOT_Param_Type : integer
// - udg_EOT_Param_Subtype : integer
set udg_EOT_Index = 0
loop
exitwhen udg_EOT_Index > udg_EOT_Amount
if udg_EOT_Param_Target == udg_EOT_Array_Target[udg_EOT_Index] and udg_EOT_Param_Type == udg_EOT_Array_Type[udg_EOT_Index] and udg_EOT_Param_Subtype == udg_EOT_Array_Subtype[udg_EOT_Index] then
set udg_EOT_Param_Id = udg_EOT_Array_Id[udg_EOT_Index]
set udg_EOT_Param_Source = udg_EOT_Array_Source[udg_EOT_Index]
set udg_EOT_Param_Duration = udg_EOT_Array_Duration[udg_EOT_Index]
set udg_EOT_Param_Remaining_Duration = udg_EOT_Array_Remaining_Duration[udg_EOT_Index]
set udg_EOT_Param_Interval = udg_EOT_Array_Interval[udg_EOT_Index]
set udg_EOT_Param_Remaining_Interval = udg_EOT_Array_Remaining_Interval[udg_EOT_Index]
set udg_EOT_Param_Hidden = udg_EOT_Array_Hidden[udg_EOT_Index]
set udg_EOT_Param_Buff = udg_EOT_Array_Buff[udg_EOT_Index]
set udg_EOT_Param_Buff_Holder = udg_EOT_Array_Buff_Holder[udg_EOT_Index]
set udg_EOT_Param_Buff_Holder_Level = udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index]
set udg_EOT_Param_Ability = udg_EOT_Array_Ability[udg_EOT_Index]
set udg_EOT_Param_Ability_Level = udg_EOT_Array_Ability_Level[udg_EOT_Index]
set udg_EOT_Param_Positive = udg_EOT_Array_Positive[udg_EOT_Index]
set udg_EOT_Param_Can_Dispell = udg_EOT_Array_Can_Dispell[udg_EOT_Index]
set udg_EOT_Param_Is_Passive = udg_EOT_Array_Is_Passive[udg_EOT_Index]
set udg_EOT_Param_Special_Effect = udg_EOT_Array_Special_Effect[udg_EOT_Index]
set udg_EOT_Param_Special_Effect_Model = udg_EOT_Array_Special_Effect_Model[udg_EOT_Index]
set udg_EOT_Param_Special_Effect_Point = udg_EOT_Array_Special_Effect_Point[udg_EOT_Index]
set udg_EOT_Event_Get_Data = 1 //<<< don't use
set udg_EOT_Event_Get_Data = 0 //<<< use this
return true
endif
set udg_EOT_Index = udg_EOT_Index + 1
endloop
return false
endfunction
//This function saves the data stored in the Param variables to the EOT.
function EOT_Save_Data takes nothing returns nothing
//Requires:
// - udg_EOT_Param_Id : integer
//If target is dead then don't do SHIT!
if IsUnitType(udg_EOT_Param_Target, UNIT_TYPE_DEAD) and GetUnitTypeId(udg_EOT_Param_Target) != 0 then
return
endif
set udg_EOT_Index = LoadInteger(udg_EOT_Hashtable, udg_EOT_Param_Id, 0)
//Check for new target.
call EOT_Check_For_New_Target(udg_EOT_Index)
set udg_EOT_Array_Source[udg_EOT_Index] = udg_EOT_Param_Source
set udg_EOT_Array_Duration[udg_EOT_Index] = udg_EOT_Param_Duration
set udg_EOT_Array_Remaining_Duration[udg_EOT_Index] = udg_EOT_Param_Remaining_Duration
set udg_EOT_Array_Interval[udg_EOT_Index] = udg_EOT_Param_Interval
set udg_EOT_Array_Remaining_Interval[udg_EOT_Index] = udg_EOT_Param_Remaining_Interval
set udg_EOT_Array_Hidden[udg_EOT_Index] = udg_EOT_Param_Hidden
set udg_EOT_Array_Buff[udg_EOT_Index] = udg_EOT_Param_Buff
set udg_EOT_Array_Buff_Holder[udg_EOT_Index] = udg_EOT_Param_Buff_Holder
set udg_EOT_Array_Buff_Holder_Level[udg_EOT_Index] = udg_EOT_Param_Buff_Holder_Level
set udg_EOT_Array_Ability[udg_EOT_Index] = udg_EOT_Param_Ability
set udg_EOT_Array_Ability_Level[udg_EOT_Index] = udg_EOT_Param_Ability_Level
set udg_EOT_Array_Type[udg_EOT_Index] = udg_EOT_Param_Type
set udg_EOT_Array_Subtype[udg_EOT_Index] = udg_EOT_Param_Subtype
set udg_EOT_Array_Positive[udg_EOT_Index] = udg_EOT_Param_Positive
set udg_EOT_Array_Can_Dispell[udg_EOT_Index] = udg_EOT_Param_Can_Dispell
set udg_EOT_Array_Is_Passive[udg_EOT_Index] = udg_EOT_Param_Is_Passive
set udg_EOT_Array_Special_Effect[udg_EOT_Index] = udg_EOT_Param_Special_Effect
set udg_EOT_Array_Special_Effect_Model[udg_EOT_Index] = udg_EOT_Param_Special_Effect_Model
set udg_EOT_Array_Special_Effect_Point[udg_EOT_Index] = udg_EOT_Param_Special_Effect_Point
set udg_EOT_Event_Save_Data = 1 //<<< don't use
set udg_EOT_Event_Save_Data = 0 //<<< use this
endfunction
//This function removes EOTs that are filtered by the Hidden, Positive and Negative variables.
function EOT_Remove_EOTs takes nothing returns nothing
//Requires:
// - udg_EOT_Param_Target : unit
// - udg_EOT_Param_Hidden : boolean
// - udg_EOT_Param_Positive : boolean
// - udg_EOT_Param_Negative : boolean
//Optional:
// - udg_EOT_Param_Force_Destroy : boolean
local unit target = udg_EOT_Param_Target
local boolean hidden = udg_EOT_Param_Hidden
local boolean positive = udg_EOT_Param_Positive
local boolean negative = udg_EOT_Param_Negative
local integer i = 0
loop
exitwhen i > udg_EOT_Amount
set udg_EOT_Param_Target = target
set udg_EOT_Param_Ability = udg_EOT_Array_Ability[i]
if TriggerEvaluate(udg_EOT_Trigger_Get_Data) then
if not(udg_EOT_Param_Is_Passive) and (udg_EOT_Param_Can_Dispell or udg_EOT_Param_Force_Destroy) then
if udg_EOT_Param_Hidden == hidden then
if (udg_EOT_Param_Positive and positive) or (not(udg_EOT_Param_Positive) and negative) then
//Call the dispell event.
set udg_EOT_Event_Dispell_Before = 1 //<<< don't use
set udg_EOT_Event_Dispell_Before = 0 //<<< use this
set udg_EOT_Event_An_EOT_Is_Dispelled = 1 //<<< don't use
set udg_EOT_Event_An_EOT_Is_Dispelled = 0 //<<< use this
set udg_EOT_Event_Dispell_After = 1 //<<< don't use
set udg_EOT_Event_Dispell_After = 0 //<<< use this
call TriggerExecute(udg_EOT_Trigger_Destroy_EOT)
set i = i - 1
endif
endif
endif
endif
set i = i + 1
endloop
set udg_EOT_Param_Force_Destroy = false
set target = null
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This code is the initialization of the system and it's functions.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This is the initial function.
function InitTrig_EOT_System takes nothing returns nothing
//Create the global variables.
set udg_EOT_Hashtable = InitHashtable()
set udg_EOT_Amount = -1
set udg_EOT_Unique_Id = -1
call EOT_Set_Default_Variables()
//Create the interval timer.
set udg_EOT_Timer = CreateTimer()
//Create the "Create_EOT" function.
//This function does not have to return a boolean.
set udg_EOT_Trigger_Create_EOT = CreateTrigger()
call TriggerAddAction(udg_EOT_Trigger_Create_EOT, function EOT_Create_EOT)
//Create the "Destroy_EOT" function.
//Returns true if destroyed and false if the EOT cannot be found.
set udg_EOT_Trigger_Destroy_EOT = CreateTrigger()
call TriggerAddCondition(udg_EOT_Trigger_Destroy_EOT, Filter(function EOT_Destroy_EOT))
call TriggerAddAction(udg_EOT_Trigger_Destroy_EOT, function EOT_Destroy_EOT)
//Create the "Get_Data" function.
set udg_EOT_Trigger_Get_Data = CreateTrigger()
call TriggerAddCondition(udg_EOT_Trigger_Get_Data, Filter(function EOT_Get_Data))
call TriggerAddAction(udg_EOT_Trigger_Get_Data, function EOT_Get_Data)
//Create the "Save_Data" function.
//This function does not have to return a boolean.
set udg_EOT_Trigger_Save_Data = CreateTrigger()
call TriggerAddAction(udg_EOT_Trigger_Save_Data, function EOT_Save_Data)
//Create the "Remove_EOTs" function.
//This function does not have to return a boolean.
set udg_EOT_Trigger_Remove_EOTs = CreateTrigger()
call TriggerAddAction(udg_EOT_Trigger_Remove_EOTs, function EOT_Remove_EOTs)
endfunction
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// EOT System end
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//TESH.scrollpos=0
//TESH.alwaysfold=0
function DOT_Deal_Damage takes nothing returns boolean
if udg_DOT_Damage == 0. then
return false
endif
call UnitDamageTarget(udg_EOT_Param_Source, udg_EOT_Param_Target, udg_DOT_Damage, true, false, udg_DOT_Attack_Type, udg_DOT_Damage_Type, WEAPON_TYPE_WHOKNOWS)
return false
endfunction
function DOT_Save_Data takes nothing returns boolean
call EOT_Save_Real(-1, udg_DOT_Damage)
call EOT_Save_Integer(-2, ConvertAttackTypeReverse(udg_DOT_Attack_Type))
call EOT_Save_Integer(-3, ConvertDamageTypeReverse(udg_DOT_Damage_Type))
return false
endfunction
function DOT_Get_Data takes nothing returns boolean
set udg_DOT_Damage = EOT_Load_Real(-1)
set udg_DOT_Attack_Type = ConvertAttackType(EOT_Load_Integer(-2))
set udg_DOT_Damage_Type = ConvertDamageType(EOT_Load_Integer(-3))
return false
endfunction
function DOT_Reset_Data takes nothing returns boolean
set udg_DOT_Damage = 0.
set udg_DOT_Attack_Type = ConvertAttackType(0)
set udg_DOT_Damage_Type = ConvertDamageType(0)
return false
endfunction
//===========================================================================
function InitTrig_DOT_Extension takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Interval_After", EQUAL, 0)
call TriggerAddCondition(t, Filter(function DOT_Deal_Damage))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Creation_Before", EQUAL, 0)
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Save_Data", EQUAL, 0)
call TriggerAddCondition(t, Filter(function DOT_Save_Data))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Interval_Before", EQUAL, 0)
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Get_Data", EQUAL, 0)
call TriggerAddCondition(t, Filter(function DOT_Get_Data))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_EOT_Event_Null_Variables", EQUAL, 0)
call TriggerAddCondition(t, Filter(function DOT_Reset_Data))
set t = null
endfunction
//TESH.scrollpos=205
//TESH.alwaysfold=0
function K2DItemCheckXY takes real x, real y returns boolean
call SetItemPosition(udg_K2DItem, x, y)
return GetWidgetX(udg_K2DItem) == x and GetWidgetY(udg_K2DItem) == y
endfunction
function K2DItemCheckAxis takes real x, real y returns boolean
local real x2 = x*udg_K2DRadius[udg_UDex]
local real y2 = y*udg_K2DRadius[udg_UDex]
set x = udg_K2DX + x2
set y = udg_K2DY + y2
if K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
set x = udg_K2DX - x2
set y = udg_K2DY - y2
return K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endif
return false
endfunction
function K2DItemCheck takes nothing returns boolean
local boolean result = K2DItemCheckXY(udg_K2DX, udg_K2DY)
//Only perform additional pathing checks if the unit has a larger collision.
if result and udg_Knockback2DRobustPathing > 0 and udg_K2DRadius[udg_UDex] > 0 then
//Check horizontal axis of unit to make sure nothing is going to collide
set result = K2DItemCheckAxis(udg_K2DCosH[udg_UDex], udg_K2DSinH[udg_UDex])
//Check vertical axis of unit to ensure nothing will collide
set result = result and K2DItemCheckAxis(udg_K2DCos[udg_UDex], udg_K2DSin[udg_UDex])
if result and udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
//Check diagonal axis of unit if more thorough pathing is desired
set result = K2DItemCheckAxis(udg_K2DCosD1[udg_UDex], udg_K2DSinD1[udg_UDex])
set result = result and K2DItemCheckAxis(udg_K2DCosD2[udg_UDex], udg_K2DSinD2[udg_UDex])
endif
endif
//Reset item so it won't interfere with the map
call SetItemPosition(udg_K2DItem, udg_K2DMaxX, udg_K2DMaxY)
call SetItemVisible(udg_K2DItem, false)
return result
endfunction
function K2DItemFilter takes nothing returns boolean
//Check for visible items, temporarily hide them and add them to the filter.
if IsItemVisible(GetFilterItem()) then
call SetItemVisible(GetFilterItem(), false)
return true
endif
return false
endfunction
function K2DItemCode takes nothing returns nothing
//Perform the item-pathing check only once, then unhide those filtered items
if not udg_K2DItemsFound then
set udg_K2DItemsFound = true
set udg_K2DItemOffset = K2DItemCheck()
endif
call SetItemVisible(GetEnumItem(), true)
endfunction
function K2DKillDest takes nothing returns nothing
local real x
local real y
//Handle destruction of debris
set bj_destRandomCurrentPick = GetEnumDestructable()
if GetWidgetLife(bj_destRandomCurrentPick) > 0.405 and IssueTargetOrder(udg_K2DDebrisKiller, udg_Knockback2DTreeOrDebris, bj_destRandomCurrentPick) then
set x = GetWidgetX(bj_destRandomCurrentPick) - udg_K2DX
set y = GetWidgetY(bj_destRandomCurrentPick) - udg_K2DY
if x*x + y*y <= udg_K2DDestRadius[udg_UDex] then
call KillDestructable(bj_destRandomCurrentPick)
endif
endif
endfunction
function K2DEnumDests takes nothing returns nothing
call MoveRectTo(udg_K2DRegion, udg_K2DX, udg_K2DY)
if udg_K2DKillTrees[udg_UDex] then
call SetUnitX(udg_K2DDebrisKiller, udg_K2DX)
call SetUnitY(udg_K2DDebrisKiller, udg_K2DY)
call EnumDestructablesInRect(udg_K2DRegion, null, function K2DKillDest)
endif
endfunction
function Knockback2DCheckXY takes real x, real y returns boolean
set udg_K2DX = x + udg_K2DVelocity[udg_UDex]*udg_K2DCos[udg_UDex]
set udg_K2DY = y + udg_K2DVelocity[udg_UDex]*udg_K2DSin[udg_UDex]
if udg_K2DSimple[udg_UDex] then
//A "pull" effect or a missile system does not require complex pathing.
if udg_K2DX <= udg_K2DMaxX and udg_K2DX >= udg_K2DMinX and udg_K2DY <= udg_K2DMaxY and udg_K2DY >= udg_K2DMinY then
call K2DEnumDests()
return true
endif
return false
elseif udg_K2DFlying[udg_UDex] then
return not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLYABILITY)
elseif not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_WALKABILITY) then
call K2DEnumDests()
set udg_K2DItemOffset = false
call EnumItemsInRect(udg_K2DRegion, Filter(function K2DItemFilter), function K2DItemCode)
if udg_K2DItemsFound then
//If items were found, the check was already performed.
set udg_K2DItemsFound = false
else
//Otherwise, perform the check right now.
set udg_K2DItemOffset = K2DItemCheck()
endif
return udg_K2DItemOffset
endif
return udg_K2DAmphibious[udg_UDex] and not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLOATABILITY)
endfunction
function Knockback2DApplyAngle takes real angle returns nothing
set angle = ModuloReal(angle, udg_Radians_Turn)
set udg_K2DCos[udg_UDex] = Cos(angle)
set udg_K2DSin[udg_UDex] = Sin(angle)
set udg_K2DAngle[udg_UDex] = angle
if udg_Knockback2DRobustPathing > 0 then
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosH[udg_UDex] = Cos(angle)
set udg_K2DSinH[udg_UDex] = Sin(angle)
if udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
set angle = ModuloReal(angle + udg_Radians_QuarterPi, udg_Radians_Turn)
set udg_K2DCosD1[udg_UDex] = Cos(angle)
set udg_K2DSinD1[udg_UDex] = Sin(angle)
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosD2[udg_UDex] = Cos(angle)
set udg_K2DSinD2[udg_UDex] = Sin(angle)
endif
endif
endfunction
function Knockback2DLooper takes nothing returns nothing
local integer i = 0
local unit u
local real x
local real y
call PauseUnit(udg_K2DDebrisKiller, false)
loop
set i = udg_K2DNext[i]
exitwhen i == 0
set udg_UDex = i
set udg_K2DTimeLeft[i] = udg_K2DTimeLeft[i] - udg_K2DTimeout
set udg_K2DDistanceLeft[i] = udg_K2DDistanceLeft[i] - udg_K2DVelocity[i]
set u = udg_UDexUnits[i]
if udg_K2DTimeLeft[i] > 0.00 then
if udg_K2DTimeLeft[i] < udg_K2DHeightThreshold[i] and udg_K2DHeightThreshold[i] != 0.00 then
call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)/udg_K2DHeightThreshold[i])
set udg_K2DHeightThreshold[i] = 0.00
endif
if udg_K2DPause[i] then
set x = udg_K2DLastX[i]
set y = udg_K2DLastY[i]
else
set x = GetUnitX(u)
set y = GetUnitY(u)
endif
if not Knockback2DCheckXY(x, y) then
if not udg_K2DFreeze[i] and IsTriggerEnabled(udg_K2DImpact[i]) and TriggerEvaluate(udg_K2DImpact[i]) then
call TriggerExecute(udg_K2DImpact[i])
endif
if udg_K2DBounce[i] then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_K2DAngle[i] + bj_PI)
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
set udg_K2DX = x
set udg_K2DY = y
endif
endif
else
set udg_K2DX = x
set udg_K2DY = y
set udg_K2DFreeze[i] = true
endif
endif
call SetUnitX(u, udg_K2DX)
call SetUnitY(u, udg_K2DY)
set udg_K2DLastX[i] = udg_K2DX
set udg_K2DLastY[i] = udg_K2DY
if udg_K2DFXModel[i] != "" then
set udg_K2DFXTimeLeft[i] = udg_K2DFXTimeLeft[i] - udg_K2DTimeout
if udg_K2DFXTimeLeft[i] <= 0.00 then
set udg_K2DFXTimeLeft[i] = udg_K2DFXRate[i]
if udg_K2DFlying[i] then
call DestroyEffect(AddSpecialEffectTarget(udg_K2DFXModel[i], u, "origin"))
else
call DestroyEffect(AddSpecialEffect(udg_K2DFXModel[i], udg_K2DX, udg_K2DY))
endif
endif
endif
if udg_K2DCollision[i] >= 0.00 then
set udg_Knockback2DSource = u
call GroupEnumUnitsInRange(bj_lastCreatedGroup, udg_K2DX, udg_K2DY, 200.00, null)
call GroupRemoveUnit(bj_lastCreatedGroup, u)
loop
set udg_Knockback2DUnit = FirstOfGroup(bj_lastCreatedGroup)
exitwhen udg_Knockback2DUnit == null
call GroupRemoveUnit(bj_lastCreatedGroup, udg_Knockback2DUnit)
if IsUnitInRange(udg_Knockback2DUnit, u, udg_K2DCollision[i]) and udg_K2DFlying[i] == IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_FLYING) and (not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_STRUCTURE)) and not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_DEAD) and (udg_K2DUnbiasedCollision[i] or IsUnitAlly(udg_Knockback2DUnit, GetOwningPlayer(u))) and TriggerEvaluate(gg_trg_Knockback_2D) then
set udg_Knockback2DAngle = bj_RADTODEG * Atan2(GetUnitY(udg_Knockback2DUnit) - udg_K2DY, GetUnitX(udg_Knockback2DUnit) - udg_K2DX)
set udg_Knockback2DDistance = udg_K2DDistanceLeft[i]
set udg_Knockback2DBounces = udg_K2DBounce[i]
set udg_Knockback2DCollision = udg_K2DCollision[i]
if udg_K2DHeight[i] != 0.00 then
set udg_Knockback2DHeight = GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)
endif
set udg_Knockback2DLoopFX = udg_K2DFXModel[i]
set udg_Knockback2DTime = udg_K2DTimeLeft[i]
set udg_Knockback2DUnbiasedCollision = udg_K2DUnbiasedCollision[i]
call TriggerExecute(gg_trg_Knockback_2D)
set udg_Knockback2DSource = u //in case of a recursive knockback
endif
endloop
endif
set udg_K2DVelocity[i] = udg_K2DVelocity[i] - udg_K2DFriction[i]
else
call TriggerExecute(gg_trg_Knockback_2D_Destroy)
endif
endloop
set u = null
//Disable dummy after the loop finishes so it doesn't interfere with the map
call PauseUnit(udg_K2DDebrisKiller, true)
endfunction
//===========================================================================
function StartKnockback2DTimer takes nothing returns nothing
call TimerStart(udg_K2DTimer, udg_K2DTimeout, true, function Knockback2DLooper)
endfunction
function InitTrig_Knockback_2D_System takes nothing returns nothing
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ListModule
//===========================================================================
// Information:
//==============
//
// This library provides the List module, which allows you to easily create
// a linked list of all of the allocated instances of a struct-type. Iterating
// through a linked list is about 12% faster than iteratating through an array
// in JASS. There is no faster method to iterate through a list of structs than
// the method used by this module. Aside from the marginal speed gain, the best
// use of this library is to hide some ugly low-level code from your structs.
// Rather than manually building and maintaining a list of struct instances,
// just implement the List module, and your code will become much prettier.
//
//===========================================================================
// How to use the List module:
//=============================
//
// Using the List module is pretty simple. First, implement it in your
// struct (preferably at the top to avoid unnecessary TriggerEvaluate calls).
// In the struct's create method, you must call listAdd(). In the onDestroy
// method, you must also call listRemove(). An example is shown below:
/*
struct Example
implement List
static method create takes nothing returns Example
local Example this = allocate()
call listAdd() //This method adds the instance to the list.
return this
endmethod
method onDestroy takes nothing returns nothing
call listRemove() //This method removes the instance from the list.
endmethod
endstruct
*/
// The requirement to call listAdd() and listRemove() will be done away
// with once JassHelper supports module onDestroy and module onCreate, but
// for now, it is not too much of a burden.
//
// Once this is done, your struct will gain all of the methods detailed
// in the API section. Below is an example of how to iterate through the list
// of allocated structs of the implementing struct-type:
/*
function IterationExample takes nothing returns nothing
local Example e = Example.first
loop
exitwhen e == 0
//Do something with e here.
set e = e.next
endloop
//Use .last and .prev instead to iterate backwards.
endmethod
*/
//
//===========================================================================
// List module API:
//==================
//
// (readonly)(static) first -> thistype
// This member contains the first instance of thistype in the list.
//
// (readonly)(static) last -> thistype
// This member contains the last instance of thistype in the list.
//
// (readonly)(static) count -> integer
// This member contains the number of allocated structs of thistype.
//
// (readonly) next -> thistype
// This member contains the next instance of thistype in the list.
//
// (readonly) prev -> thistype
// This member contains the previous instance of thistype in the list.
//
// listAdd()
// This method adds this instance to the list of structs of thistype.
// This should be called on each instance after it is allocated (within
// the create method).
//
// listRemove()
// This method removes this instance from the list of structs of thistype.
// This should be called on each instance before it is destroyed (within
// the onDestroy method).
//
// (static) listDestroy()
// This method destroys all the structs of thistype within the list.
//
//===========================================================================
module List
private static boolean destroying = false
private boolean inlist = false
readonly static integer count = 0
readonly thistype next = 0
readonly thistype prev = 0
static method operator first takes nothing returns thistype
return thistype(0).next
endmethod
static method operator last takes nothing returns thistype
return thistype(0).prev
endmethod
method listRemove takes nothing returns nothing
if not inlist then
return
endif
set inlist = false
set prev.next = next
set next.prev = prev
set count = count - 1
endmethod
method listAdd takes nothing returns nothing
if inlist or destroying then
return
endif
set inlist = true
set last.next = this
set prev = last
set thistype(0).prev = this
set count = count + 1
endmethod
static method listDestroy takes nothing returns nothing
local thistype this = last
set destroying = true
loop
exitwhen this == 0
call destroy()
set this = prev
endloop
set destroying = false
endmethod
endmodule
endlibrary
//TESH.scrollpos=32
//TESH.alwaysfold=0
library AirplaneSystem requires ListModule, optional AutoIndex
/*
.~@ FINGOLFINS AIRPLANE MOVEMENT SYSTEM @~.
INSTRUCTIONS:
- Implement AutoIndex as specified in its description
- Create your airplane units as you would with any normal unit
- Set the turn speed of your airplanes to something below 0.1 (use shift-click)
- Register plane types by adding this line to the initPlaneTypes function:
call registerPlaneType('xxxx')
where 'xxxx' is the id of your airplane.
*/
//=======================//
//======= GLOBALS =======//
//=======================//
globals
private constant real UPDATE_INTERVAL = 0.03125 //I SUBMIT TO THIS FOLLY
private constant real ORDER_INTERVAL = 1 // HOW OFTEN ORDERS ARE REFRESHED
private constant real DEFAULT_FACING = 270
private constant integer MAX_PLAYERS = 12
//LOWER NUMBERS = LESS INERTIA. SET TO ZERO TO REMOVE INERTIA COMPLETELY. THIS VALUE MUST BE LOWER THAN 1!
private constant real AIR_FRICTION = 0.945
//A CONSTANT MULTIPILER TO THE UNIT SPEED, TO CIRCUMVENT THE HARDCODED SPEED LIMIT OF WC3.
private constant real SPEED_FACTOR = 1.6
//MAX DISTANCE TO MAP BORDER WHERE PLANES CAN TRAVEL
private constant real BORDER_WIDTH = 200
//MAP BOUNDS
private real MAP_MAX_X
private real MAP_MAX_Y
private real MAP_MIN_X
private real MAP_MIN_Y
private constant integer ORDER_SMART = OrderId("smart")
private constant integer ORDER_MOVE = OrderId("move")
private constant integer ORDER_ATTACK = OrderId("attack")
private constant integer TYPES_KEY = StringHash("Airplane Types")
private constant integer INSTANCES_KEY = StringHash("Airplane Instances")
private hashtable Hash = InitHashtable()
endglobals
native UnitAlive takes unit id returns boolean
//=======================//
//===== SYSTEM CODE =====//
//=======================//
function IsUnitPlane takes unit whichunit returns boolean
return HaveSavedInteger(Hash, TYPES_KEY, GetUnitTypeId(whichunit))
endfunction
private function RegisterPlaneType takes integer unitid returns nothing
call SaveInteger(Hash, TYPES_KEY, unitid, 1)
endfunction
private function InitPlaneTypes takes nothing returns nothing
//REGISTER YOUR PLANE TYPES LIKE THIS
call RegisterPlaneType('h00L')
endfunction
struct Plane
implement List
unit plane = null
unit target = null
real vx = 0
real vy = 0
real tx = 0
real ty = 0
real speed = 0
integer order = 0
private static timer t1
private static timer t2
private static method get takes unit whichunit returns thistype
return LoadInteger(Hash, INSTANCES_KEY, GetHandleId(whichunit))
endmethod
method onDestroy takes nothing returns nothing
//DON'T GIVE ME CRAP ABOUT USING onDestroy(), IT POSES NO PERFORMANCE ISSUE IN THIS CASE.
call .listRemove()
call RemoveSavedInteger(Hash, INSTANCES_KEY, GetHandleId(.plane))
if .count == 0 then
call PauseTimer(.t1)
call PauseTimer(.t2)
endif
endmethod
private static method updateOrder takes nothing returns nothing
local thistype this = .first
local thistype temp
local real x
local real y
if .count == 0 then
call PauseTimer(.t1)
call PauseTimer(.t2)
endif
loop
exitwhen this == 0
set temp = .next
if GetUnitTypeId(.plane) == 0 then
//DESTROY THE STRUCT WHEN THE PLANE NO LONGER EXISTS
call .destroy()
else
if .target != null then
if UnitAlive(.target) == false or GetUnitTypeId(.target) == 0 then
set .target = null
set .tx = GetUnitX(.plane)
set .ty = GetUnitY(.plane)
set .order = ORDER_ATTACK
else
call IssueTargetOrderById(.plane, .order, .target)
endif
else
if .order == ORDER_MOVE or .order == ORDER_SMART then
set x = GetUnitX(.plane)
set y = GetUnitY(.plane)
if (x - .tx)*(x - .tx) + (y - .ty)*(y - .ty) < 10000 then
//ALLOW THE UNIT TO ATTACK ONCE IT HAS REACHED ITS DESTINATION
set .order = ORDER_ATTACK
endif
endif
call IssuePointOrderById(.plane, .order, .tx, .ty)
endif
endif
set this = temp
endloop
endmethod
private static method updatePosition takes nothing returns nothing
local thistype this = .first
local real x = 0
local real y = 0
local real f = 0
loop
exitwhen this == 0
set f = GetUnitFacing(.plane)*bj_DEGTORAD
//ADD FRICTION FIRST INCASE IT IS ZEROED
set .vx = (.vx * AIR_FRICTION) + .speed * Cos(f)
set .vy = (.vy * AIR_FRICTION) + .speed * Sin(f)
set x = GetUnitX(.plane)+.vx
set y = GetUnitY(.plane)+.vy
//ENFORCE BOUNDS
if x > MAP_MAX_X then
set x = MAP_MAX_X
elseif x < MAP_MIN_X then
set x = MAP_MIN_X
endif
if y > MAP_MAX_Y then
set y = MAP_MAX_Y
elseif y < MAP_MIN_Y then
set y = MAP_MIN_Y
endif
call SetUnitX(.plane, x)
call SetUnitY(.plane, y)
set this = .next
endloop
endmethod
private static method onOrderTarget takes nothing returns boolean
local thistype this = thistype.get(GetTriggerUnit())
if this == 0 then
return false
endif
set .target = GetOrderTargetUnit()
set .tx = GetUnitX(.target)
set .ty = GetUnitY(.target)
set .order = GetIssuedOrderId()
return false
endmethod
private static method onOrderPoint takes nothing returns boolean
local real x = GetOrderPointX()
local real y = GetOrderPointY()
local thistype this = thistype.get(GetTriggerUnit())
if this == 0 then
return false
endif
set .tx = x
set .ty = y
set .target = null
set .order = GetIssuedOrderId()
return false
endmethod
static method create takes unit whichunit returns thistype
local thistype this = thistype.allocate()
call .listAdd()
call SaveInteger(Hash, INSTANCES_KEY, GetHandleId(whichunit), this)
//=========SOME MATH TRIVIA!=========//
//The acceleration is given by the following differential equation:
// v(t)' = a = v(t) - v(t)*(1-R), where R = AIR_FRICTION
//And it's solution:
//v(t) = (a/(1-R)*(1 + e^-(1-R)t)
//Calculating the limit when (t -> infinity) gives:
//vmax = a/(1-R)
//vmax*(1-R) = a (in this case 'vmax' is known and 'a' is unknown)
//===========END OF TRIVIA===========//
set .plane = whichunit
set .speed = GetUnitDefaultMoveSpeed(.plane)*(1-AIR_FRICTION)*UPDATE_INTERVAL*SPEED_FACTOR
set .tx = GetUnitX(.plane) + 500 * Cos(DEFAULT_FACING*bj_DEGTORAD)
set .ty = GetUnitY(.plane) + 500 * Sin(DEFAULT_FACING*bj_DEGTORAD)
set .order = ORDER_SMART
call SetUnitMoveSpeed(.plane, 0.01)
call SetUnitFacing(.plane, DEFAULT_FACING)
call SetUnitFlyHeight(.plane, 0, 0)
call SetUnitFlyHeight(.plane, GetUnitDefaultFlyHeight(.plane), GetUnitDefaultFlyHeight(.plane)/3)
if .count == 1 then
call TimerStart(.t1, UPDATE_INTERVAL, true, function thistype.updatePosition)
call TimerStart(.t2, ORDER_INTERVAL, true, function thistype.updateOrder)
endif
return this
endmethod
private static method onUnitEntersMap takes nothing returns boolean
call thistype.onIndex(GetFilterUnit())
return false
endmethod
private static method onIndex takes unit u returns nothing
if IsUnitPlane(u) then
call .create(u)
endif
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local rect r = GetWorldBounds()
local region map = CreateRegion()
local group g = CreateGroup()
set MAP_MAX_X = GetRectMaxX(r)-BORDER_WIDTH
set MAP_MAX_Y = GetRectMaxY(r)-BORDER_WIDTH
set MAP_MIN_X = GetRectMinX(r)+BORDER_WIDTH
set MAP_MIN_Y = GetRectMinY(r)+BORDER_WIDTH
set Plane.t1 = CreateTimer()
set Plane.t2 = CreateTimer()
call InitPlaneTypes()
loop
exitwhen i > MAX_PLAYERS
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
set i = i+1
endloop
call TriggerAddCondition(t, Condition(function Plane.onOrderTarget))
set t = CreateTrigger()
set i = 0
loop
exitwhen i > MAX_PLAYERS
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null)
set i = i+1
endloop
call TriggerAddCondition(t, Condition(function Plane.onOrderPoint))
static if (LIBRARY_AutoIndex) then
call OnUnitIndexed(Plane.onIndex)
else
set t = CreateTrigger()
call RegionAddRect(map, r)
call TriggerRegisterEnterRegion(t, map, function Plane.onUnitEntersMap)
set i = 0
loop
exitwhen i > MAX_PLAYERS
call GroupEnumUnitsOfPlayer(g, Player(i), function Plane.onUnitEntersMap)
set i = i+1
endloop
endif
call DestroyGroup(g)
call RemoveRect(r)
set g = null
set r = null
set t = null
set map = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=9
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// **
// ** **
// **************************************************************************
library ChargeConfig
globals
//CHECK THE CHARGEEXEC TRIGGER FOR MORE OPTIONS
//ID CONFIGURATIONS FOR SPELLS AND DUMMY UNITS
//ID of the Charge spell
constant integer SPELLID = 'A03N'
//ID of the dummy unit used for the attack at the end of the charge. Set this to 0 for no unit
constant integer DUMMYID = 'h000'
//ID of the spell to be casted by the dummy unit once the charge is complete (Has to be a spell with
//a Target). Set this to 0 for no spell. The Spell effect depends on the level of the Charge Spell
//So it's advisable to set the number of levels of this spell at the same value of the level of the
//Charge Spell
constant integer DUMMYSPELLID = 'A03O'
//Order String for the spell to be casted by the dummy unit
constant string SPELLORDERID = "thunderbolt"
//SPECIAL EFFECTS CONFIGURATION
//You can set this to a non existand model (or change the code of the spell) if you don't want that
//effect
//Special Effect attached on the unit (in this example it will look like a red trail)
constant string ATTACHEDEFFECT = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
//Special Effect created by the unit while walking
constant string WALKEFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
//Special Effect used at the end of the Charge
constant string ENDINGEFFECT = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
//NUMERICAL SETTINGS
//Charge Starting Speed
constant real STARTSPEED = 20.00
//Max Speed that can be reached by the Caster unit while charging
constant real MAXSPEED = 100.00
//Damage Dealt at the end of the Charge (0 for no damage). DEPENDS ON LEVEL
constant real CHARGEDAMAGE = 125.00
//Minimum Distance at where a unit can Charge (0 for no min distance)
//Make sure the dummy spell has a longer distance than this
constant real MINDISTANCE = 400.00
//Maximum Distance at where a unit can Charge (0 for no max distance)
//This is mainly used to interrupt the charge if the target unit gets teleported somewhere else
//Make sure the dummy spell has a distance equal or less than this number
constant real MAXDISTANCE = 1200.00
//KNOCKBACK SETTINGS
//Theese settings refer to the Knock trigger which is not made by me but by Silvenon. If you want
//to know more about this script, got to
//http://www.hiveworkshop.com/forums/jass-functions-413/knockback-unit-35545/
//Special Effect created by the knockback
constant string KNOCKEFFECT = "Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl"
//The Distance of the Knockback effect. DEPENDS ON LEVEL
constant real KNOCKDISTANCE = 50.00
//The Duration of the Knockback effect
constant real KNOCKDURATION = 1.5
//Tree Destroying effect
//If you want trees destroyed behind your target while he's knocked back, then set this to true
//Otherwise set this to false. See the Knock Trigger for more configuration options
constant boolean KNOCKTREECHECK = true
//Knockback Effect
//This is the effect played on the Knocked Back Unit. If you set this to 0 then no effect will be played
//If you set this to 1 then the effect set on the KnockEffect() function is played as a periodic effect
//If you set this to 2 then the effect will be attached on the unit and destroyed once the knocback ends
constant integer KNOCKPLAYEFFECT = 1
//Attachement point of the effect played during the knockback. Default is "chest"
constant string KNOCKATTACH = "Foot"
//You may want to check the ChargeExec trigger for more Configuration Options
//PATCCHECKER SETTINGS
//ID of the dummy unit used for the path checker function (has to be an invulnerable locusted unit with No model)
constant integer PATHCHECKERID = 'h000'
//ID of the permanent windwalk spell used for the path checker function
constant integer SPELLPATHID = 'A03P'
endglobals
function KnockTree takes nothing returns real
if (KNOCKTREECHECK==true) then
return 150.00
endif
return 0.00
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Charge **
// ** ————————————— **
// ** **
// ** A simple Charge Spell **
// ** **
// ** By: Majin **
// **
// ** **
// **************************************************************************
library ChargeExec requires Knockback
struct ChargeLoop
private real ChargeTargetx
private real ChargeTargety
private real ChargeEndx
private real ChargeEndy
private real ChargeLocx
private real ChargeLocy
private real ChargeNextx
private real ChargeNexty
private unit ChargeTarget
private unit ChargeCaster
private real ChargeAngle
private real ChargeDistance
private effect ChargeEffect
private timer ChargeTimer
private boolean ChargeCond = false
private integer SpellLvl
//START OF CONFIGURATION METHODS
//With this method you can set the "acceleration rate" (Physicists Forgive me) of the charge.
//You can use any kind of numeric function (for example this.ChargeDistance * 2.00 will double
//The speed at every loop)
private method ChangeDistance takes nothing returns real
return this.ChargeDistance + 1.00
endmethod
//END OF CONFIGURATION METHODS
//START OF CUSTOMIZABLE METHODS
//This method sets the conditions when to activate the AlmostCharge method. In particular
//You may be interested in changing the distance at where the condition is true.
//In this Example it will be activated when the Caster is 16x times the Charge Speed Far away
//From the target
private method AlmostChargeCond takes nothing returns boolean
return ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) < ( this.ChargeDistance * 16.00 )) and this.ChargeCond == false)
endmethod
//Actions to take when the Charge is almost completed. In this example the caster will play
//The slam animation (Being a Blademaster, it will jump in the air while attacking)
private method AlmostCharge takes nothing returns nothing
set this.ChargeCond = true
call SetUnitTimeScale( this.ChargeCaster, 2.00 )
call SetUnitAnimation( this.ChargeCaster, "attack" )
call QueueUnitAnimation( this.ChargeCaster, "stand")
endmethod
//Actions to take when the Caster reaches its target and the charge is completed.
//In this example the target unit will be stunned and you will see a Thunderclap effect on the ground
private method CompleteCharge takes nothing returns nothing
local effect tempEffect
local unit dummy
local real angle=GetAngle(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy)
set this.ChargeLocx = this.ChargeNextx
set this.ChargeLocy = this.ChargeNexty
set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
call DestroyEffect(AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy ))
call SetUnitX( this.ChargeCaster, this.ChargeEndx )
call SetUnitY( this.ChargeCaster, this.ChargeEndy )
set dummy = CreateUnit( GetOwningPlayer(this.ChargeCaster), DUMMYID, this.ChargeLocx, this.ChargeLocy, 0 )
call UnitAddAbility( dummy, DUMMYSPELLID )
call SetUnitAbilityLevel(dummy, DUMMYSPELLID, this.SpellLvl)
call IssueTargetOrder( dummy, SPELLORDERID, this.ChargeTarget )
call UnitApplyTimedLife( dummy, 'BTLF', 1.00)
call DestroyEffect(AddSpecialEffect( ENDINGEFFECT, this.ChargeLocx, this.ChargeLocy ))
call UnitDamageTarget( this.ChargeCaster, this.ChargeTarget, CHARGEDAMAGE*this.SpellLvl, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
call PauseUnit( this.ChargeCaster, false )
//This is the Knockback effect, see the Knock Trigger for more customization options
call KnockbackEx(this.ChargeTarget, KNOCKDISTANCE*this.SpellLvl, angle, KNOCKDURATION, KnockTree(), KNOCKPLAYEFFECT, KNOCKEFFECT, KNOCKATTACH)
call IssueTargetOrder( this.ChargeCaster, "attack", this.ChargeTarget )
set dummy = null
endmethod
//What to do during the charge, the unit is moved, an effect is placed on the ground and
//the charging speed is increased
private method ContinueCharge takes nothing returns nothing
call DestroyEffect(AddSpecialEffect( WALKEFFECT, this.ChargeLocx, this.ChargeLocy ))
call SetUnitX(this.ChargeCaster, this.ChargeNextx)
call SetUnitY(this.ChargeCaster, this.ChargeNexty)
call SetUnitFacing(this.ChargeCaster, bj_RADTODEG * GetAngle(this.ChargeNextx, this.ChargeNexty, this.ChargeTargetx, this.ChargeTargety))
set this.ChargeLocx = this.ChargeNextx
set this.ChargeLocy = this.ChargeNexty
set this.ChargeNextx = PolarProjectionx(this.ChargeLocx, this.ChargeDistance, this.ChargeAngle)
set this.ChargeNexty = PolarProjectiony(this.ChargeLocy, this.ChargeDistance, this.ChargeAngle)
if (this.ChargeDistance <= MAXSPEED) then
set this.ChargeDistance = this.ChangeDistance()
endif
endmethod
//END OF CUSTOMIZABLE METHODS
//START OF OTHER METHODS
//This is the main method executed during the charge
public static method ChargeActions takes nothing returns nothing
local ChargeLoop l=GetTimerInt(GetExpiredTimer())
set l.ChargeTargetx = GetUnitX(l.ChargeTarget)
set l.ChargeTargety = GetUnitY(l.ChargeTarget)
set l.ChargeEndx = PolarProjectionx(l.ChargeTargetx, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
set l.ChargeEndy = PolarProjectiony(l.ChargeTargety, 100.00, GetAngle(l.ChargeTargetx, l.ChargeTargety, l.ChargeLocx, l.ChargeLocy))
set l.ChargeAngle = GetAngle(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy)
if ( l.AlmostChargeCond() ) then
//What to do when the caster is about to reach the target
call l.AlmostCharge()
endif
//If the Target gets too far away (by teleportation, for example) then stops the Charge
if ( GetDistance(l.ChargeLocx, l.ChargeLocy, l.ChargeEndx, l.ChargeEndy) >= MAXDISTANCE and (MAXDISTANCE != 0.00) ) then
call l.StopCharge()
endif
if ( l.ChargeConditions() ) then
//If the unit hasn't reached the target yet, then execute this
call l.ContinueCharge()
call TimerAttach(l.ChargeTimer,0.03,l,function ChargeLoop.ChargeActions)
else
if ( l.ChargeCompleted() ) then
//What to do if the charge is succesfully completed
call l.CompleteCharge()
endif
call l.StopCharge()
endif
endmethod
//Actions to take once the Charge is being stopped (either because it wasn't possible to complete
//the charge or because the caster reached its target)
private method StopCharge takes nothing returns nothing
set this.ChargeCond = false
call SetUnitPathing(this.ChargeCaster, true)
call PauseUnit(this.ChargeCaster, false)
call SetUnitAnimation(this.ChargeCaster, "stand")
call SetUnitTimeScale(this.ChargeCaster, 1.00)
call DestroyEffect(this.ChargeEffect)
call this.destroy()
endmethod
private method ChargeCompleted takes nothing returns boolean
if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) <= this.ChargeDistance*1.10) and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
return true
endif
endif
endif
return false
endmethod
private method ChargeConditions takes nothing returns boolean
if ((GetDistance(this.ChargeLocx, this.ChargeLocy, this.ChargeEndx, this.ChargeEndy) > this.ChargeDistance*1.10) and IsPointWalkable(this.ChargeNextx, this.ChargeNexty)) then
if ((IsTerrainPathable(this.ChargeNextx, this.ChargeNexty, PATHING_TYPE_WALKABILITY) == false ) and ( (GetUnitState(this.ChargeTarget, UNIT_STATE_LIFE)<=0) == false )) then
if(((GetUnitState(this.ChargeCaster, UNIT_STATE_LIFE) <= 0) == false)) then
return true
endif
endif
endif
return false
endmethod
private method onDestroy takes nothing returns nothing
call ReleaseTimer(this.ChargeTimer)
set this.ChargeTarget = null
set this.ChargeCaster = null
set this.ChargeEffect = null
endmethod
static method create takes real pChargeTargetx, real pChargeTargety, real pChargeEndx, real pChargeEndy, real pChargeLocx, real pChargeLocy, real pChargeNextx, real pChargeNexty, unit pChargeTarget, unit pChargeCaster, real pChargeAngle, real pChargeDistance, effect pChargeEffect, timer pChargeTimer returns ChargeLoop
local ChargeLoop l = ChargeLoop.allocate()
set l.ChargeTargetx = pChargeTargetx
set l.ChargeTargety = pChargeTargety
set l.ChargeEndx = pChargeEndx
set l.ChargeEndy = pChargeEndy
set l.ChargeLocx = pChargeLocx
set l.ChargeLocy = pChargeLocy
set l.ChargeNextx = pChargeNextx
set l.ChargeNexty = pChargeNexty
set l.ChargeTarget = pChargeTarget
set l.ChargeCaster = pChargeCaster
set l.ChargeAngle = pChargeAngle
set l.ChargeDistance = pChargeDistance
set l.ChargeEffect = pChargeEffect
set l.ChargeTimer = pChargeTimer
set l.SpellLvl = GetUnitAbilityLevel(l.ChargeCaster, SPELLID)
return l
endmethod
//END OF OTHER METHODS
endstruct
endlibrary
//TRIGGER OF THE CHARGE SPELL
scope Charge initializer InitTrig
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELLID
endfunction
private function CheckActions takes nothing returns nothing
local real ChargeLocx = GetUnitX(GetTriggerUnit())
local real ChargeLocy = GetUnitY(GetTriggerUnit())
local real ChargeEndx = GetUnitX(GetSpellTargetUnit())
local real ChargeEndy = GetUnitY(GetSpellTargetUnit())
local sound s
if ( GetDistance(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy) <= (MINDISTANCE) ) then
call DisplayTextToPlayer( GetOwningPlayer(GetTriggerUnit()), 0, 0, "|cffFFCC00Target is too close!|r" )
set s = CreateSound("Sound\\Interface\\Error.wav", false, false, true, 12700, 12700, "")
call StartSound(s)
call KillSoundWhenDone(s)
set s = null
call IssueImmediateOrder( GetTriggerUnit(), "stop" )
endif
endfunction
private function InitActions takes nothing returns nothing
local timer ChargeTimer = NewTimer()
local effect ChargeEffect
local unit ChargeCaster = GetTriggerUnit()
local unit ChargeTarget = GetSpellTargetUnit()
local real ChargeDistance = STARTSPEED
local real ChargeLocx = GetUnitX(ChargeCaster)
local real ChargeLocy = GetUnitY(ChargeCaster)
local real ChargeTargetx = GetUnitX(ChargeTarget)
local real ChargeTargety = GetUnitY(ChargeTarget)
local real ChargeEndx = PolarProjectionx(ChargeTargetx, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
local real ChargeEndy = PolarProjectiony(ChargeTargety, 100.00, GetAngle(ChargeTargetx, ChargeTargety, ChargeLocx, ChargeLocy))
local real ChargeAngle = GetAngle(ChargeLocx, ChargeLocy, ChargeEndx, ChargeEndy)
local real ChargeNextx = PolarProjectionx(ChargeLocx, ChargeDistance, ChargeAngle)
local real ChargeNexty = PolarProjectiony(ChargeLocy, ChargeDistance, ChargeAngle)
local ChargeLoop stru
set ChargeEffect = AddSpecialEffectTarget(ATTACHEDEFFECT, ChargeCaster, "chest" )
set stru = ChargeLoop.create(ChargeTargetx, ChargeTargety, ChargeEndx, ChargeEndy, ChargeLocx, ChargeLocy, ChargeNextx, ChargeNexty, ChargeTarget, ChargeCaster, ChargeAngle, ChargeDistance, ChargeEffect, ChargeTimer)
call SetUnitPathing(ChargeCaster, false)
call SetUnitTimeScale(ChargeCaster, 3)
call IssueImmediateOrder(ChargeCaster, "stop" )
call PauseUnit(ChargeCaster, true)
call SetUnitAnimationByIndex(ChargeCaster,1)
call TimerAttach(ChargeTimer,0,stru,function ChargeLoop.ChargeActions)
set ChargeTimer = null
set ChargeEffect = null
set ChargeCaster = null
set ChargeTarget = null
endfunction
private function InitTrig takes nothing returns nothing
local trigger ChargeCheck = CreateTrigger()
local trigger ChargeInit = CreateTrigger()
local filterfunc f = Filter(function AntiLeak)
local integer i = 0
loop
exitwhen i == 16
call TriggerRegisterPlayerUnitEvent(ChargeCheck,Player(i),EVENT_PLAYER_UNIT_SPELL_CAST,truefilter)
call TriggerRegisterPlayerUnitEvent(ChargeInit,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,truefilter)
set i = i + 1
endloop
call TriggerAddCondition(ChargeCheck, Condition(function Conditions))
call TriggerAddAction(ChargeCheck, function CheckActions)
call TriggerAddCondition(ChargeInit, Condition(function Conditions))
call TriggerAddAction(ChargeInit, function InitActions)
set ChargeCheck = null
set ChargeInit = null
set f = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Mathematical Functions **
// ** ————————————— **
// ** **
// ** Functions used instead of BJs to calculate some values **
// ** **
// ** By: Majin **
// **
// ** **
// **************************************************************************
library Math
function GetDistance takes real ax, real ay, real bx, real by returns real
return SquareRoot((bx-ax)*(bx-ax)+(by-ay)*(by-ay))
endfunction
function PolarProjectionx takes real ax, real dist, real angle returns real
return ax + dist * Cos(angle)
endfunction
function PolarProjectiony takes real ay, real dist, real angle returns real
return ay + dist * Sin(angle)
endfunction
function GetAngle takes real ax, real ay, real bx, real by returns real
return Atan2(by-ay, bx-ax)
endfunction
function RAbs takes real a returns real
if (a >= 0) then
return a
else
return -a
endif
endfunction
function AntiLeak takes nothing returns boolean
return true
endfunction
endlibrary
//TESH.scrollpos=18
//TESH.alwaysfold=0
//Functions used to handle timers. Credits to Vexorian and Captain Griffen
//Check http://www.wc3c.net/showthread.php?t=89072 for more informations
library HandleTimers
globals
private timer array timers
private integer N = 0
endglobals
function NewTimer takes nothing returns timer
if (N==0) then
return CreateTimer()
endif
set N=N-1
return timers[N]
endfunction
function ReleaseTimer takes timer t returns nothing
call PauseTimer(t)
if (N==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
set timers[N]=t
set N=N+1
endif
endfunction
function TimerAttach takes timer t, real time, real value, code func returns nothing
call TimerStart(t, value, false, null)
call PauseTimer(t)
call TimerStart(t, time, false, func)
endfunction
// ONLY call on an expired timer.
function GetTimerInt takes timer t returns integer
return R2I(TimerGetRemaining(t) + 0.5)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
// **************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores other units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// **
// ** **
// **************************************************************************
library Walkable initializer init requires ChargeConfig, Math
globals
unit pathchecker
rect pathrect
filterfunc truefilter
endglobals
function HideItems takes nothing returns nothing
call SetItemVisible(GetEnumItem(), false)
endfunction
function UnHideItems takes nothing returns nothing
call SetItemVisible(GetEnumItem(), true)
endfunction
function IsPointWalkable takes real x, real y returns boolean
local boolean b
call SetUnitPosition(pathchecker,x,y)
set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
if (b==false) then
call MoveRectTo(pathrect, x, y)
call EnumItemsInRect(pathrect,truefilter,function HideItems)
call SetUnitPosition(pathchecker,x,y)
set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
call EnumItemsInRect(pathrect,truefilter,function UnHideItems)
endif
return b
endfunction
function init takes nothing returns nothing
local real x = GetRectMinX(bj_mapInitialPlayableArea)
local real y = GetRectMinY(bj_mapInitialPlayableArea)
set pathrect=Rect(x,y,x+200.00,y+200.00)
set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
set truefilter=Filter(function AntiLeak)
call UnitAddAbility(pathchecker, SPELLPATHID)
call IssueImmediateOrder( pathchecker, "windwalk" )
endfunction
endlibrary
//TESH.scrollpos=194
//TESH.alwaysfold=0
library Knockback initializer Init requires HandleTimers, Walkable
// **************************************************************************
// ** **
// ** Knockback(Ex) **
// ** ————————————— **
// ** **
// ** A function made for efficient knockbacking **
// ** **
// ** By: Silvenon **
// ** **
// **************************************************************************
//=======================================//
//Credits to PitzerMike for this function//
//=======================================//
private function TreeFilter takes nothing returns boolean
local destructable d = GetFilterDestructable()
local boolean i = IsDestructableInvulnerable(d)
local unit u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMYID, GetWidgetX(d), GetWidgetY(d), 0)
local boolean result = false
call UnitAddAbility(u, 'Ahrl')
if i then
call SetDestructableInvulnerable(d, false)
endif
set result = IssueTargetOrder(u, "harvest", d)
call RemoveUnit(u)
if i then
call SetDestructableInvulnerable(d, true)
endif
set u = null
set d = null
return result
endfunction
//===========================================================================
globals
private timer Tim = CreateTimer()
private integer Total = 0
private boolexpr Cond = null
private integer array Ar
private boolean array BoolAr
private real MAX_X
private real MAX_Y
private real MIN_X
private real MIN_Y
endglobals
private constant function Interval takes nothing returns real
return 0.04
endfunction
private function KillTree takes nothing returns nothing
if BoolAr[0] then
call KillDestructable(GetEnumDestructable())
else
set BoolAr[1] = true
endif
endfunction
public struct Data
unit u
real d1
real d2
real sin
real cos
real r
string s = ""
effect e = null
static method create takes unit u, integer q, real d, real a, real r, integer t, string s, string p returns Data
local Data dat = Data.allocate()
set dat.u = u
set dat.d1 = 2 * d / (q + 1)
set dat.d2 = dat.d1 / q
set dat.sin = Sin(a)
set dat.cos = Cos(a)
set dat.r = r
if s != "" and s != null then
if t == 2 then
if p != "" and p != null then
set dat.e = AddSpecialEffectTarget(s, u, p)
else
set dat.e = AddSpecialEffectTarget(s, u, "chest")
endif
elseif t == 1 then
set dat.s = s
endif
endif
call SetUnitPosition(u, GetUnitX(u), GetUnitY(u))
call PauseUnit(u, true)
if Total == 0 then
call TimerStart(Tim, Interval(), true, function Data.Execute)
endif
set Total = Total + 1
set Ar[Total - 1] = dat
return dat
endmethod
static method Execute takes nothing returns nothing
local Data dat
local integer i = 0
local real x
local real y
local rect r
local real rad
loop
exitwhen i >= Total
set dat = Ar[i]
if dat.s != "" and dat.s != null then
set x = GetUnitX(dat.u)
set y = GetUnitY(dat.u)
call DestroyEffect(AddSpecialEffect(dat.s, x, y))
set x = x + dat.d1 * dat.cos
set y = y + dat.d1 * dat.sin
else
set x = GetUnitX(dat.u) + dat.d1 * dat.cos
set y = GetUnitY(dat.u) + dat.d1 * dat.sin
endif
if dat.r != 0 then
set BoolAr[0] = dat.r > 0
set rad = dat.r
if not BoolAr[0] then
set rad = rad * (-1)
endif
set r = Rect(x - rad, y - rad, x + rad, y + rad)
call EnumDestructablesInRect(r, Cond, function KillTree)
call RemoveRect(r)
set r = null
endif
if (x < MAX_X and y < MAX_Y and x > MIN_X and y > MIN_Y) and not BoolAr[1] and (IsPointWalkable(x, y)) then
call SetUnitX(dat.u, x)
call SetUnitY(dat.u, y)
endif
set dat.d1 = dat.d1 - dat.d2
if dat.d1 <= 0 or (x > MAX_X or y > MAX_Y or x < MIN_X or y < MIN_Y) or BoolAr[1] or not(IsPointWalkable(x, y)) then
set Ar[i] = Ar[Total - 1]
set Total = Total - 1
call dat.destroy()
endif
set i = i + 1
endloop
if Total == 0 then
call PauseTimer(Tim)
endif
endmethod
method onDestroy takes nothing returns nothing
if .e != null then
call DestroyEffect(.e)
endif
call PauseUnit(.u, false)
set BoolAr[0] = false
set BoolAr[1] = false
endmethod
endstruct
function KnockbackEx takes unit u, real d, real a, real w, real r, integer t, string s, string p returns nothing
call Data.create(u, R2I(w / Interval()), d, a, r, t, s, p)
endfunction
function Knockback takes unit u, real d, real a, real w returns nothing
call Data.create(u, R2I(w / Interval()), d, a, 0, 0, "", "")
endfunction
private function Init takes nothing returns nothing
set Cond = Filter(function TreeFilter)
set BoolAr[0] = false
set BoolAr[1] = false
set MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 64
set MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 64
set MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 64
set MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 64
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Meteor Strike
v2.01
by KILLCIDE
Did my absolute best to not make this similar to the Chaos Meteor from DotA D:
Requirements:
--------
- Check Walkability
- dummy.mdx
- GUI Knockback 2D
- GUI Unit Indexer
Credits:
-------
- Bribe for GUI Knockback 2D & GUI Unit Indexer
- PurgeandFire for Check Walkability
- Vexorian for the dummy.mdx
How to Install:
--------------
1. Under Preferences, make sure you have "Automatically create unknown variables while pasting trigger data" checked
2. Import dummy.mdx, then copy and paste the dummy unit and two custom abilities into your map
NOTE: If you already have dummy.mdx imported into your map, you DO NOT have to reimport it
If you already have a global dummy unit in your map, you can skip this step
3. Copy and paste the Resources folder into your map
NOTE: If you already have a resource in the Resources folder imported into your map, you DO NOT have to reimport it
4. Copy and paste the Meteor Strike folder into your map
5. Go to the MS Config trigger, and change the Ability, AbilityStun, & Dummy variables to the corresponding objects you just imported
Changelog:
---------
- v2.01 (March 22, 2016): Added an optional Meteor Strike folder that is integrated with GUI Spell System
Added Bribe's new knockback system update
Fixed bug of meteor falling at a completely different location when casted directly on top of the caster
Removed unnecesary NodeLast[] variable for linked list; last spell instance now stores into NodePrev[0]
Removed If/Then/Else that would set NodeLast = NodePrev[Spell_ID] if NodeLast == Spell_ID
- v2.00 (January 25, 2016): Added a filter for air units (both knockback and damage)
Changed data structure to linked listing
- v1.03 (December 05, 2015): Changed spell to now use one global dummy caster instead of one dummy caster per spell instance
Changed RollDirection to now be indexed with spell instance
Removed a lot of unnecessary calculations for FallRate and MoveRate (now done on init)
- v1.02 (December 03, 2015): Added multi-level support for rolling travel time & SFXRoll frequency
Changed MS Init trigger name to MS Cast
Fixed Owner[] variable to now use Triggering Player instead of Owner of (Unit)
Fixed a small bug where dummies for SFXFall were not being removed
Fixed Create a Unit functions to now reference MS_Dummy instead of actual dummy unit-type
Fixed self-made tree destroy system to be much safer by adding harvest ability to the created treeKiller
Removed Damage[] variable so that calculations are now done on map init instead of on cast
Removed unnecessary function call when turning off MS Loop (Turn off (This trigger) -> (Turn off MS Loop))
- v1.01 (December 02, 2015): Added Bribe's new knockback system update
Added a landing damage mechanic
Removed damage interval mechanic; spell now deals damage constantly as it rolls
- v1.00 (December 01, 2015): Uploaded onto Hive
//TESH.scrollpos=82
//TESH.alwaysfold=0
function IsUnitMovementTracked takes integer i returns boolean
return udg_UMovPrev[i] != 0 or udg_UMovNext[0] == i
endfunction
function UnitMovementRegister takes nothing returns boolean
local integer i = udg_UDex
if not IsUnitMovementTracked(i) and TriggerEvaluate(gg_trg_Is_Unit_Moving_Config) then
set udg_UMovPrev[udg_UMovNext[0]] = i
set udg_UMovNext[i] = udg_UMovNext[0]
set udg_UMovNext[0] = i
set udg_UnitMovingX[i] = GetUnitX(udg_UDexUnits[i])
set udg_UnitMovingY[i] = GetUnitY(udg_UDexUnits[i])
endif
return false
endfunction
function UnitMovementUnregister takes nothing returns boolean
local integer i = udg_UDex
if IsUnitMovementTracked(i) then
set udg_UnitMoving[i] = false
set udg_UMovNext[udg_UMovPrev[i]] = udg_UMovNext[i]
set udg_UMovPrev[udg_UMovNext[i]] = udg_UMovPrev[i]
set udg_UMovPrev[i] = 0
endif
return false
endfunction
function RunUnitMovementEvent takes integer i, real e returns nothing
local integer pdex = udg_UDex
if e == 1.00 then
set udg_UnitMoving[i] = true
else
set udg_UnitMoving[i] = false
endif
set udg_UDex = i
set udg_UnitMovingEvent = e
set udg_UnitMovingEvent = 0.00
set udg_UDex = pdex
endfunction
//===========================================================================
// This function runs periodically to check if units are actually moving.
//
function UnitMovementTracker takes nothing returns nothing
local integer i = 0
local integer n
local real x
local real y
loop
set i = udg_UMovNext[i]
exitwhen i == 0
set x = GetUnitX(udg_UDexUnits[i])
set y = GetUnitY(udg_UDexUnits[i])
if x != udg_UnitMovingX[i] or y != udg_UnitMovingY[i] then
set udg_UnitMovingX[i] = x
set udg_UnitMovingY[i] = y
if not udg_UnitMoving[i] then
if GetUnitTypeId(udg_UDexUnits[i]) != 0 then
call RunUnitMovementEvent(i, 1.00)
else
set n = udg_UDex
set udg_UDex = i
set i = udg_UMovPrev[i] //avoid skipping checks
call UnitMovementUnregister()
set udg_UDex = n
endif
endif
elseif udg_UnitMoving[i] then
call RunUnitMovementEvent(i, 2.00)
endif
endloop
endfunction
//===========================================================================
function InitTrig_Is_Unit_Moving takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerAddCondition(t, Filter(function UnitMovementRegister))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
call TriggerAddCondition(t, Filter(function UnitMovementUnregister))
if gg_trg_Is_Unit_Moving_Config != null then
call TriggerExecute(gg_trg_Is_Unit_Moving_Config)
else
call ExecuteFunc("Trig_Is_Unit_Moving_Config_Actions")
endif
call TimerStart(CreateTimer(), udg_UnitMovementInterval, true, function UnitMovementTracker)
endfunction