//TESH.scrollpos=1023
//TESH.alwaysfold=0
function SaveLoad_InitialSetup takes nothing returns nothing
local integer i = 0
local integer j = 0
loop
set udg_SaveLoad_Compress[i + 48] = j
set udg_SaveLoad_Uncompress[i] = i + 48
set j = j + 1
set i = i + 1
exitwhen i >= 10
endloop
set i = 0
loop
set udg_SaveLoad_Compress[i + 97] = j
set udg_SaveLoad_Compress[i + 65] = j + 26
set udg_SaveLoad_Uncompress[i + 10] = i + 97
set udg_SaveLoad_Uncompress[i + 26 + 10] = i + 65
set j = j + 1
set i = i + 1
exitwhen i >= 26
endloop
endfunction
function SaveLoad_Id2CId takes integer n returns integer
local integer i = n / (256 * 256 * 256)
local integer r
set n = n - i * (256 * 256 * 256)
set r = udg_SaveLoad_Compress[i]
set i = n / (256 * 256)
set n = n - i * (256 * 256)
set r = r * 64 + udg_SaveLoad_Compress[i]
set i = n / 256
set r = r * 64 + udg_SaveLoad_Compress[i]
return r * 64 + udg_SaveLoad_Compress[n - i * 256]
endfunction
function SaveLoad_CId2Id takes integer n returns integer
local integer i = n / (64 * 64 * 64)
local integer r
set n = n - i * (64 * 64 * 64)
set r = udg_SaveLoad_Uncompress[i]
set i = n / (64 * 64)
set n = n - i * (64 * 64)
set r = r * 256 + udg_SaveLoad_Uncompress[i]
set i = n / 64
set r = r * 256 + udg_SaveLoad_Uncompress[i]
return r * 256 + udg_SaveLoad_Uncompress[n - i * 64]
endfunction
function SaveLoad_Unit2Integer takes unit u returns integer
local integer i = 0
local integer n = GetUnitTypeId(u)
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
loop
set i = i + 1
exitwhen i > udg_SaveLoad_Heroes_LastIndex
if udg_SaveLoad_Heroes[i] == n then
return i
endif
endloop
return SaveLoad_Id2CId(n)
endfunction
function SaveLoad_Integer2Unit takes integer i returns integer
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
if i <= udg_SaveLoad_Heroes_LastIndex then
return udg_SaveLoad_Heroes[i]
endif
return SaveLoad_CId2Id(i)
endfunction
function SaveLoad_Item2Integer takes item t returns integer
local integer i = 0
local integer n = GetItemTypeId(t)
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
loop
set i = i + 1
exitwhen i > udg_SaveLoad_Items_LastIndex
if udg_SaveLoad_Items[i] == n then
return i
endif
endloop
return SaveLoad_Id2CId(n)
endfunction
function SaveLoad_Integer2Item takes integer i returns integer
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
if i <= udg_SaveLoad_Items_LastIndex then
return udg_SaveLoad_Items[i]
endif
return SaveLoad_CId2Id(i)
endfunction
function SaveLoad_Ability2Integer takes integer a returns integer
local integer i = 0
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
loop
set i = i + 1
exitwhen i > udg_SaveLoad_Abilities_LastIndex
if udg_SaveLoad_Abilities[i] == a then
return i
endif
endloop
return SaveLoad_Id2CId(a)
endfunction
function SaveLoad_Integer2Ability takes integer i returns integer
if udg_SaveLoad_Initialized == false then
set udg_SaveLoad_Initialized = true
call SaveLoad_InitialSetup()
endif
if i <= udg_SaveLoad_Abilities_LastIndex then
return udg_SaveLoad_Abilities[i]
endif
return SaveLoad_CId2Id(i)
endfunction
function SaveLoad_Color takes string s returns string
local integer i = StringLength(s)
local string c
local string r = ""
loop
set i = i - 1
set c = SubString(s,i,i + 1)
if c == "0" or c == "1" or c == "2" or c == "3" or c == "4" or c == "5" or c == "6" or c == "7" or c == "8" or c == "9" then
set r = "|cffff9999" + c + "|r" + r
elseif c == "-" then
set r = "|cffdddddd-|r" + r
elseif c == "a" or c == "b" or c == "c" or c == "d" or c == "e" or c == "f" or c == "g" or c == "h" or c == "i" or c == "j" or c == "k" or c == "l" or c == "m" or c == "n" or c == "o" or c == "p" or c == "q" or c == "r" or c == "s" or c == "t" or c == "u" or c == "v" or c == "w" or c == "x" or c == "y" or c == "z" then
set r = "|cff99ff99" + c + "|r" + r
elseif c == "A" or c == "B" or c == "C" or c == "D" or c == "E" or c == "F" or c == "G" or c == "H" or c == "I" or c == "J" or c == "K" or c == "L" or c == "M" or c == "N" or c == "O" or c == "P" or c == "Q" or c == "R" or c == "S" or c == "T" or c == "U" or c == "V" or c == "W" or c == "X" or c == "Y" or c == "Z" then
set r = "|cff9999ff" + c + "|r" + r
else
set r = c + r
endif
exitwhen i <= 0
endloop
return r
endfunction
function SaveLoad_EncodeChar takes string n returns integer
local integer i = 0
local string s1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local string s2 = "abcdefghijklmnopqrstuvwxyz"
local string s3 = "0123456789"
loop
if SubString(s1,i,i + 1) == n then
return i
endif
if SubString(s2,i,i + 1) == n then
return i
endif
set i = i + 1
exitwhen i >= 26
endloop
set i = 0
loop
if SubString(s3,i,i + 1) == n then
return i
endif
set i = i + 1
exitwhen i >= 10
endloop
return 0
endfunction
function SaveLoad_EncodeVerify takes string buffer returns integer
local integer i = 0
local integer j = 0
local string name = GetPlayerName(GetTriggerPlayer())
if udg_SaveLoad_UsePlayername == true then
loop
set j = j + SaveLoad_EncodeChar(SubString(name,i,i + 1))
set i = i + 1
exitwhen i >= StringLength(name)
endloop
endif
set i = 0
loop
set j = j + SaveLoad_EncodeChar(SubString(buffer,i,i + 1))
set i = i + 1
exitwhen i >= StringLength(buffer)
endloop
return j
endfunction
function SaveLoad_EncodeValues takes nothing returns string
local integer i
local integer j
local integer k
local integer l
local integer m
local integer CodeLength = StringLength(udg_SaveLoad_Alphabet)
local integer array a
local string buffer = ""
local string c = ""
local integer skip = 0
local integer CONST = 1000000
local string abc = "0123456789"
set i = 0
loop
set i = i + 1
exitwhen i > udg_SaveCount
set buffer = buffer + I2S(udg_Save[i]) + "-"
endloop
set buffer = buffer + I2S(SaveLoad_EncodeVerify(buffer))
if udg_Save[1] == 0 then
set buffer = "-" + buffer
endif
set i = 0
loop
set a[i] = 0
set i = i + 1
exitwhen i >= 100
endloop
set m = 0
set i = 0
loop
set j = 0
loop
set a[j] = a[j] * 11
set j = j + 1
exitwhen j > m
endloop
set l = 0
set c = SubString(buffer,i,i + 1)
loop
exitwhen SubString(abc,l,l + 1) == c
set l = l + 1
exitwhen l > 9
endloop
set a[0] = a[0] + l
set j = 0
loop
set k = a[j] / CONST
set a[j] = a[j] - k * CONST
set a[j + 1] = a[j + 1] + k
set j = j + 1
exitwhen j > m
endloop
if k > 0 then
set m = m + 1
endif
set i = i + 1
exitwhen i >= StringLength(buffer)
endloop
set buffer = ""
loop
exitwhen m < 0
set j = m
loop
exitwhen j <= 0
set k = a[j] / CodeLength
set a[j - 1] = a[j - 1] + (a[j] - k * CodeLength) * CONST
set a[j] = k
set j = j - 1
endloop
set k = a[j] / CodeLength
set i = a[j] - k * CodeLength
set buffer = buffer + SubString(udg_SaveLoad_Alphabet,i,i + 1)
set a[j] = k
if a[m] == 0 then
set m = m - 1
endif
endloop
set i = StringLength(buffer)
set skip = 0
set c = ""
loop
set i = i - 1
set c = c + SubString(buffer,i,i + 1)
set skip = skip + 1
if skip == 4 and i > 0 then
set c = c + "-"
set skip = 0
endif
exitwhen i <= 0
endloop
return c
endfunction
function SaveLoad_DecodeValues takes string s returns boolean
local integer i
local integer j
local integer k
local integer l
local integer SaveCode = 0
local integer m
local integer array a
local string buffer = ""
local integer CodeLength = StringLength(udg_SaveLoad_Alphabet)
local integer skip = -1
local integer CONST = 1000000
local string abc = "0123456789-"
local string c
set i = 0
loop
set a[i] = 0
set i = i + 1
exitwhen i >= 100
endloop
set m = 0
set i = 0
loop
set j = 0
loop
set a[j] = a[j] * CodeLength
set j = j + 1
exitwhen j > m
endloop
set skip = skip + 1
if skip == 4 then
set skip = 0
set i = i + 1
endif
set l = CodeLength
set c = SubString(s,i,i + 1)
loop
set l = l - 1
exitwhen l < 1
exitwhen SubString(udg_SaveLoad_Alphabet,l,l + 1) == c
endloop
set a[0] = a[0] + l
set j = 0
loop
set k = a[j] / CONST
set a[j] = a[j] - k * CONST
set a[j + 1] = a[j + 1] + k
set j = j + 1
exitwhen j > m
endloop
if k > 0 then
set m = m + 1
endif
set i = i + 1
exitwhen i >= StringLength(s)
endloop
loop
exitwhen m < 0
set j = m
loop
exitwhen j <= 0
set k = a[j] / 11
set a[j - 1] = a[j - 1] + (a[j] - k * 11) * CONST
set a[j] = k
set j = j - 1
endloop
set k = a[j] / 11
set i = a[j] - k * 11
set buffer = SubString(abc,i,i + 1) + buffer
set a[j] = k
if a[m] == 0 then
set m = m - 1
endif
endloop
set i = 0
set j = 0
loop
loop
exitwhen i >= StringLength(buffer)
exitwhen i > 0 and SubString(buffer,i,i + 1) == "-" and SubString(buffer,i - 1,i) != "-"
set i = i + 1
endloop
if i < StringLength(buffer) then
set k = i
endif
set SaveCode = SaveCode + 1
set udg_Save[SaveCode] = S2I(SubString(buffer,j,i))
set j = i + 1
set i = i + 1
exitwhen i >= StringLength(buffer)
endloop
set j = SaveLoad_EncodeVerify(SubString(buffer,0,k))
set udg_SaveCount = SaveCode - 1
if j == udg_Save[SaveCode] then
return true
endif
return false
endfunction
function SaveLoad_Encode takes nothing returns string
if udg_SaveLoad_CaseSensitive == false then
set udg_SaveLoad_Alphabet = StringCase(udg_SaveLoad_Alphabet,true)
endif
return SaveLoad_Color(SaveLoad_EncodeValues())
endfunction
function SaveLoad_Decode takes string s returns boolean
if udg_SaveLoad_CaseSensitive == false then
set udg_SaveLoad_Alphabet = StringCase(udg_SaveLoad_Alphabet,true)
set s = StringCase(s,true)
endif
if SaveLoad_DecodeValues(s) then
return true
endif
return false
endfunction
// This is here because default WE trigger ordering sucks
////////////////////////////////////////////////////////////////////////////////////
//
// 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 = 'PDDS'
set udg_PDD_SET_MAX_LIFE = 'LIFE'
// 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
Name | Type | is_array | initial_value |
Arthas | unit | No | |
BlockingPool | integer | No | 0 |
BonusesFound | integer | No | |
BonusesTotal | integer | No | |
CameraPoint | location | No | |
CameraPoint2 | location | No | |
cinSkip | boolean | No | |
Code | string | No | |
CodeError | boolean | No | |
DemonsArray | unit | Yes | |
DiffInteger | integer | No | |
Doom1IsHome | boolean | No | true |
Doom1NearHome | boolean | No | true |
Doom2IsHome | boolean | No | true |
Doom2NearHome | boolean | No | true |
DoomGuard | unit | No | |
DoomInCombat | boolean | No | false |
DummyOwner | player | No | |
EntangledGoldMine | unit | No | UnitNull |
EXTAS | integer | No | |
EXTRAStotal | integer | No | |
Falric | unit | No | |
FSChanneling | boolean | No | |
FSCX | real | No | |
FSCY | real | No | |
FSDistance | real | Yes | |
FSDTotal | real | Yes | |
FSLevel | integer | No | |
FSShard | unit | Yes | |
FSTotal | integer | No | |
FSTX | real | Yes | |
FSTY | real | Yes | |
Furion | unit | No | |
GAMEOVER | boolean | No | false |
GameSelection | boolean | No | |
HellCaller | unit | No | |
HellCallerAbilities | abilcode | Yes | |
Hero1 | unit | No | |
Hero1Inventory | string | No | |
Hero2 | unit | No | |
Hero2Inventory | string | No | |
HiddenPlayerUnits | group | No | |
HintDruidTimer | timer | No | |
HintImmolationTimer | timer | No | |
Illidan | unit | No | |
IllidanFlyHeight | real | No | |
IllidanHasSkull | boolean | No | false |
IllidanSelected | boolean | No | false |
Infernal1 | unit | No | UnitNull |
Infernal2 | unit | No | UnitNull |
InsaneMode | boolean | No | |
Intro_Cin_Skip | boolean | No | false |
LevelsPlayedWithThisCode | integer | No | |
LocalPlayer | player | No | |
Loramus | unit | No | |
MageAlive | boolean | No | |
MageSpellsTable | hashtable | No | |
OrbAA | real | Yes | |
OrbAT | real | Yes | |
OrbCount | integer | No | |
OrbCounter | real | No | |
OrbDamage | real | Yes | |
OrbDistance | real | Yes | |
OrbMasteryLevel | integer | Yes | |
Orbs | unit | Yes | |
OrbsAttached | integer | No | |
OrbStatus | integer | Yes | |
OrbSZ | real | Yes | |
OrbTU | unit | Yes | |
OrbTX | real | Yes | |
OrbTY | real | Yes | |
OrbTZ | real | Yes | |
Outro_Cin_Skip | boolean | No | false |
OverallScoreLimit | integer | Yes | |
OverallScoreMax | integer | No | |
P1New | boolean | No | |
P1Skip | boolean | No | |
P2New | boolean | No | |
P2Skip | boolean | 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 | |
Player1 | player | No | Player01 |
Player2 | player | No | Player02 |
PlayerHere | boolean | No | false |
PyroBurnTime | real | No | |
PyroDistance | real | No | |
PyroDU | unit | No | |
PyroLevel | integer | No | |
PyroTU | unit | No | |
PyroTX | real | No | |
PyroTY | real | No | |
PyroTZ | real | No | |
QuestKillReqKill | questitem | No | |
QuestKillTicho | quest | No | |
QuestSkullofGuldan | quest | No | |
QuestSkullReqDemongate | questitem | No | |
QuestSkullReqSkull | questitem | No | |
RankInteger | integer | No | |
ResearchMax | integer | No | |
ResearchString | string | Yes | |
ResearchType | techcode | Yes | |
Save | integer | Yes | |
SaveCount | integer | No | |
SaveLoad_Abilities | abilcode | Yes | |
SaveLoad_Abilities_LastIndex | integer | No | |
SaveLoad_Alphabet | string | No | |
SaveLoad_CaseSensitive | boolean | No | |
SaveLoad_Compress | integer | Yes | |
SaveLoad_Heroes | unitcode | Yes | |
SaveLoad_Heroes_LastIndex | integer | No | |
SaveLoad_Initialized | boolean | No | |
SaveLoad_Items | itemcode | Yes | |
SaveLoad_Items_LastIndex | integer | No | |
SaveLoad_Uncompress | integer | Yes | |
SaveLoad_UsePlayername | boolean | No | |
ScoreBonuses | integer | No | |
ScoreExtra | integer | No | |
ScoreLimit | integer | Yes | |
ScoreMax | integer | No | |
ScoreRank | string | No | |
ScoreSecret | integer | No | |
ScoreSideQuest | integer | No | |
ScoreSubquest | integer | No | |
ScoreTime | integer | No | |
ScoreTotal | integer | No | |
SecretsFound | integer | No | |
SecretsTotal | integer | No | |
SelectionGroup | group | No | |
SelectionGroup2 | group | No | |
SideQuestTotal | integer | No | |
Skull_Cin_Skip | boolean | No | false |
SoulArmor | effect | No | |
SpawnDemons | boolean | No | true |
SubquestsCompleted | integer | No | |
SubquestsTotal | integer | No | |
SumRank | integer | No | |
TechHash | hashtable | No | |
TichGuards | group | No | |
TichIsHOme | boolean | No | true |
TichManaPool | boolean | No | true |
TichNearHome | boolean | No | true |
Tichondrius | unit | No | |
TimeMax | real | No | |
TimeMin | real | No | |
TimeRange | real | No | |
TimerHours | integer | No | |
TimerMinutes | integer | No | |
TimerSeconds | integer | No | |
TimerString | string | No | |
TimerStringHours | string | No | |
TimerStringMinutes | string | No | |
TimerStringSeconds | string | No | |
TimerTotal | integer | No | |
TimerUnderAttack | timer | No | |
TimeTotal | integer | No | |
tipEu | boolean | No | |
Tyrande | unit | No | |
UnlimitedPower | boolean | No | |
Validate | boolean | No |
//TESH.scrollpos=11
//TESH.alwaysfold=0
function callback takes nothing returns nothing
local group g = CreateGroup()
local real x = GetUnitX(gg_unit_Utic_0055)
local real y = GetUnitY(gg_unit_Utic_0055)
local real xmin = GetRectMinX(gg_rct_Tich_Guards) - 32
local real xmax = GetRectMaxX(gg_rct_Tich_Guards) + 32
local real ymin = GetRectMinY(gg_rct_Tich_Guards) - 32
local real ymax = GetRectMaxY(gg_rct_Tich_Guards) + 32
local unit u
call GroupEnumUnitsInRect(g, gg_rct_Tich_Guards, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsUnitAlly(u, udg_Player1) and IsUnitAlly(u, udg_Player2) and not (GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD)) then
set udg_PlayerHere = true
call DestroyGroup(g)
set g = null
set u = null
return
endif
call GroupRemoveUnit(g, u)
endloop
set udg_PlayerHere = false
if x > xmin and x < xmax and y > ymin and y < ymax then
call SetUnitState(gg_unit_Utic_0055, UNIT_STATE_MANA, GetUnitState(gg_unit_Utic_0055, UNIT_STATE_MANA) + 5)
call SetUnitLife(gg_unit_Utic_0055, GetUnitLife(gg_unit_Utic_0055) + 5)
endif
call DestroyGroup(g)
set g = null
set u = null
return
endfunction
function InitTrig_Mana_Pool takes nothing returns nothing
call TimerStart(CreateTimer(), 1, true, function callback)
endfunction
//TESH.scrollpos=21
//TESH.alwaysfold=0
function TakePositions takes nothing returns nothing
local unit doom1 = gg_unit_nbal_0003
local unit doom2 = gg_unit_nbal_0007
local unit tichy = gg_unit_Utic_0055
local real x1 = GetUnitX(doom1)
local real y1 = GetUnitY(doom1)
local real x1min1 = GetRectMinX(gg_rct_DoomHome1) - 32
local real x1max1 = GetRectMaxX(gg_rct_DoomHome1) + 32
local real y1min1 = GetRectMinY(gg_rct_DoomHome1) - 32
local real y1max1 = GetRectMaxY(gg_rct_DoomHome1) + 32
local real x1min2 = GetRectMinX(gg_rct_DoomGoHome) - 32
local real x1max2 = GetRectMaxX(gg_rct_DoomGoHome) + 32
local real y1min2 = GetRectMinY(gg_rct_DoomGoHome) - 32
local real y1max2 = GetRectMaxY(gg_rct_DoomGoHome) + 32
local real x2 = GetUnitX(doom2)
local real y2 = GetUnitY(doom2)
local real x2min1 = GetRectMinX(gg_rct_DoomHome2) - 32
local real x2max1 = GetRectMaxX(gg_rct_DoomHome2) + 32
local real y2min1 = GetRectMinY(gg_rct_DoomHome2) - 32
local real y2max1 = GetRectMaxY(gg_rct_DoomHome2) + 32
local real x2min2 = GetRectMinX(gg_rct_DoomGoHome) - 32
local real x2max2 = GetRectMaxX(gg_rct_DoomGoHome) + 32
local real y2min2 = GetRectMinY(gg_rct_DoomGoHome) - 32
local real y2max2 = GetRectMaxY(gg_rct_DoomGoHome) + 32
local real x3 = GetUnitX(tichy)
local real y3 = GetUnitY(tichy)
local real x3min1 = GetRectMinX(gg_rct_TichHome) - 32
local real x3max1 = GetRectMaxX(gg_rct_TichHome) + 32
local real y3min1 = GetRectMinY(gg_rct_TichHome) - 32
local real y3max1 = GetRectMaxY(gg_rct_TichHome) + 32
local real x3min2 = GetRectMinX(gg_rct_DoomGoHome) - 32
local real x3max2 = GetRectMaxX(gg_rct_DoomGoHome) + 32
local real y3min2 = GetRectMinY(gg_rct_DoomGoHome) - 32
local real y3max2 = GetRectMaxY(gg_rct_DoomGoHome) + 32
if udg_PlayerHere or udg_DoomInCombat then
return
endif
if x1 > x1min1 and x1 < x1max1 and y1 > y1min1 and y1 < y1max1 then
call SetUnitFacingTimed(doom1, 279.20, 1.00)
elseif x1 > x1min2 and x1 < x1max2 and y1 > y1min2 and y1 < y1max2 then
call IssuePointOrder(doom1, "attack", GetRectCenterX(gg_rct_DoomHome1), GetRectCenterY(gg_rct_DoomHome1))
endif
if x2 > x2min1 and x2 < x2max1 and y2 > y2min1 and y2 < y2max1 then
call SetUnitFacingTimed(doom2, 174.16, 1.00)
elseif x2 > x2min2 and x2 < x2max2 and y2 > y2min2 and y2 < y2max2 then
call IssuePointOrder(doom2, "attack", GetRectCenterX(gg_rct_DoomHome2), GetRectCenterY(gg_rct_DoomHome2))
endif
if x3 > x3min1 and x3 < x3max1 and y3 > y3min1 and y3 < y3max1 then
call SetUnitFacingTimed(tichy, 225.57, 1.00)
elseif x3 > x3min2 and x3 < x3max2 and y3 > y3min2 and y3 < y3max2 then
call IssuePointOrder(tichy, "attack", GetRectCenterX(gg_rct_TichHome), GetRectCenterY(gg_rct_TichHome))
endif
endfunction
function InitTrig_Doom_Take_Positions takes nothing returns nothing
call TimerStart(CreateTimer(), 2, true, function TakePositions)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function New takes nothing returns nothing
local player p = GetTriggerPlayer()
if not (udg_P1New or udg_P2New) then
if p == udg_Player1 then
set udg_P1New = true
else
set udg_P2New = true
endif
elseif (p == udg_Player1 and udg_P2New) or (p == udg_Player2 and udg_P1New) then
call DisableTrigger(GetTriggeringTrigger())
call DisableTrigger(gg_trg_GameMode)
call DisableTrigger(gg_trg_Loading)
call EnableTrigger(gg_trg_GiveResource)
call EnableTrigger(gg_trg_ExchangeUnits)
set udg_GameSelection = false
call StartSound(gg_snd_GoodJob)
call TriggerSleepAction(1)
call TriggerExecute(gg_trg_Map_Initialization)
endif
endfunction
function InitTrig_New takes nothing returns nothing
set gg_trg_New = CreateTrigger()
call DisableTrigger(gg_trg_New)
call TriggerRegisterPlayerChatEvent(gg_trg_New, udg_Player1, "-new", true)
call TriggerRegisterPlayerChatEvent(gg_trg_New, udg_Player2, "-new", true)
call TriggerAddAction(gg_trg_New, function New)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function StartText takes nothing returns nothing
if udg_GameSelection then
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "|cff338844-=NIGHT ELF CHAPTER 6=-|r")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "A Destiny of Flame and Sorrow")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, " ")
if udg_CodeError then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "The code you entered is not compatible with this chapter.")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "You can type '-load' again, followed your code, to try again.")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "Type '-load' followed by the code received in the previous chapter to load your score.")
endif
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "Alternatively, both players can type '-new' to start a new game.")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, " ")
if udg_InsaneMode then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "|cffffcc00Gamemode: |r|cffff0000INSANE|r")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, " ")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "To decrease the difficulty type '-normal'.")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "|cffffcc00Gamemode: |r|cff00cc00NORMAL|r")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, " ")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "To increase the difficulty type '-insane'.")
endif
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 600, "|cff32CD32NOTE|r - This is NOT used if you are loading a code. The code transfers the difficulty along with everything else.")
endif
endfunction
function InitTrig_Starttext takes nothing returns nothing
set gg_trg_Starttext = CreateTrigger()
call TriggerAddAction(gg_trg_Starttext, function StartText)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function GameMode takes nothing returns boolean
local string s = GetEventPlayerChatString()
if s == "-normal" and udg_InsaneMode then
set udg_InsaneMode = false
elseif s == "-insane" and not udg_InsaneMode then
set udg_InsaneMode = true
endif
call ExecuteFunc("StartText")
return false
endfunction
function InitTrig_GameMode takes nothing returns nothing
set gg_trg_GameMode = CreateTrigger()
call DisableTrigger(gg_trg_GameMode)
call TriggerRegisterPlayerChatEvent(gg_trg_GameMode, udg_Player1, "-normal", true)
call TriggerRegisterPlayerChatEvent(gg_trg_GameMode, udg_Player1, "-insane", true)
call TriggerRegisterPlayerChatEvent(gg_trg_GameMode, udg_Player2, "-normal", true)
call TriggerRegisterPlayerChatEvent(gg_trg_GameMode, udg_Player2, "-insane", true)
call TriggerAddCondition(gg_trg_GameMode, Condition(function GameMode))
endfunction
//TESH.scrollpos=21
//TESH.alwaysfold=0
function GiveResource takes nothing returns nothing
local playerstate ps
local integer i
local integer a
local player p1 = GetTriggerPlayer()
local player p2
local string tmp
local string resource
local string message = GetEventPlayerChatString()
local string gold = SubString(message, 0, 6)
local string lumber = SubString(message, 0, 8)
if gold == "-gold " or lumber == "-lumber " then
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
if gold == "-gold " then
set resource = "gold"
set ps = PLAYER_STATE_RESOURCE_GOLD
set a = S2I(SubString(message, 6, StringLength(message)))
else
set resource = "lumber"
set ps = PLAYER_STATE_RESOURCE_LUMBER
set a = S2I(SubString(message, 8, StringLength(message)))
endif
set i = GetPlayerState(p1, ps)
if a > i then
set a = i
endif
if a > 0 then
set tmp = I2S(a)
call SetPlayerState(p1, ps, i - a)
call SetPlayerState(p2, ps, GetPlayerState(p2, ps) + a)
call DisplayTextToPlayer(p2, 0, 0, "|cffcc6600ALLIES|r - " + tmp + " " + resource + " received from " + GetPlayerName(p1) + ".")
call DisplayTextToPlayer(p1, 0, 0, "|cffcc6600ALLIES|r - " + tmp + " " + resource + " sent to " + GetPlayerName(p2) + ".")
if GetLocalPlayer() == p2 then
call StartSound(gg_snd_ItemReceived)
endif
else
call DisplayTextToPlayer(p1, 0, 0, "|cffcc6600ALLIES|r - Not enough " + resource + ".")
endif
endif
set ps = null
set p1 = null
set p2 = null
endfunction
function InitTrig_GiveResource takes nothing returns nothing
set gg_trg_GiveResource = CreateTrigger()
call DisableTrigger(gg_trg_GiveResource)
call TriggerRegisterPlayerChatEvent(gg_trg_GiveResource, udg_Player1, "-gold ", false)
call TriggerRegisterPlayerChatEvent(gg_trg_GiveResource, udg_Player2, "-gold ", false)
call TriggerRegisterPlayerChatEvent(gg_trg_GiveResource, udg_Player1, "-lumber ", false)
call TriggerRegisterPlayerChatEvent(gg_trg_GiveResource, udg_Player2, "-lumber ", false)
call TriggerAddAction(gg_trg_GiveResource, function GiveResource)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function ExchangeUnits takes nothing returns nothing
local player p1 = GetTriggerPlayer()
local player p2
local group units = CreateGroup()
local boolean b1
local boolean b2
local boolean b3
local boolean b4
local integer food = 0
local integer uyes = 0
local integer uall = 0
local integer fUsed
local integer fMax
local integer i
local unit u
local unit u1
local unit u2
local string result
local string result2
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
// Gonna get reused
set fUsed = GetPlayerState(p2, PLAYER_STATE_RESOURCE_FOOD_USED)
set fMax = GetPlayerState(p2, PLAYER_STATE_RESOURCE_FOOD_CAP)
call GroupEnumUnitsSelected(units, p1, null)
set u = FirstOfGroup(units)
loop
set u = FirstOfGroup(units)
exitwhen u == null
set i = GetUnitFoodUsed(u)
// Kinda confusing but better than a mile long line, trust me
set b1 = GetUnitFoodMade(u) == 0 and IsUnitType(u, UNIT_TYPE_STRUCTURE)
set b2 = i + fUsed <= fMax and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
set b3 = not (IsUnitType(u, UNIT_TYPE_HERO) or IsUnitType(u, UNIT_TYPE_SUMMONED) or IsUnitType(u, UNIT_TYPE_PEON))
set b4 = GetOwningPlayer(u) == p1 and GetUnitTypeId(u) != 'eate'
if (b1 or b2) and b3 and b4 then
set uyes = uyes + 1
set food = food + i
call SetUnitOwner(u, p2, true)
set u1 = LoadUnitHandle(udg_TechHash, 0, GetHandleId(u))
if u1 != null then
call SetUnitOwner(u1, p1, true)
endif
set u2 = LoadUnitHandle(udg_TechHash, 1, GetHandleId(u))
if u2 != null then
call SetUnitOwner(u2, p1, true)
endif
call PingMinimap(GetUnitX(u), GetUnitY(u), 3)
endif
set uall = uall + 1
call GroupRemoveUnit(units, u)
endloop
if uyes == uall and uall != 0 then
call StartSound(gg_snd_Rescue)
set result = "|cffcc6600ALLIES|r - All " + I2S(uall) + " units were exchanged successfully"
set result2 = "|cffcc6600ALLIES|r - " + I2S(uyes) + " units were exchanged to you"
if food > 0 then
set result = result + " - a total of " + I2S(food) + " food."
set result2 = result2 + " - a total of " + I2S(food) + " food."
else
set result = result + "."
set result2 = result2 + "."
endif
elseif uyes != 0 then
call StartSound(gg_snd_Rescue)
set result = "|cffcc6600ALLIES|r - " + I2S(uyes) + "/" + I2S(uall) + " units were successfully exchanged"
set result2 = "|cffcc6600ALLIES|r - " + I2S(uyes) + " units were exchanged to you"
if (food > 0) then
set result = result + " - a total of " + I2S(food) + " food"
set result2 = result2 + " - a total of " + I2S(food) + " food"
else
set result = result + "."
set result2 = result2 + "."
endif
elseif uall != 0 then
if udg_LocalPlayer == p1 then
call StartSound(gg_snd_Error)
endif
set result = "|cffcc6600ALLIES|r - No units could be exchanged."
set result2 = "Empty"
else
if udg_LocalPlayer == p1 then
call StartSound(gg_snd_Error)
endif
set result = "|cffcc6600ALLIES|r - No units selected."
set result2 = "Empty"
endif
call DisplayTextToPlayer(p1, 0, 0, " ")
call DisplayTextToPlayer(p2, 0, 0, " ")
call DisplayTextToPlayer(p1, 0, 0, result)
if result2 != "Empty" then
call DisplayTextToPlayer(p2, 0, 0, result2)
endif
if not udg_tipEu then
set udg_tipEu = true
call TriggerSleepAction(bj_QUEUE_DELAY_HINT)
call StartSound(gg_snd_Hint)
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, " ")
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|cff32CD32HINT|r - You cannot exchange Wisps, Heroes, Tree of Life/Tree of Ages/Tree of Eternity, Altars and Moon Wells.")
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Units must also obey the food limit.")
endif
call DestroyGroup(units)
set units = null
set u = null
set u1 = null
set u2 = null
set p1 = null
set p2 = null
endfunction
function InitTrig_ExchangeUnits takes nothing returns nothing
set gg_trg_ExchangeUnits = CreateTrigger()
call DisableTrigger(gg_trg_ExchangeUnits)
call TriggerRegisterPlayerChatEvent(gg_trg_ExchangeUnits, udg_Player1, "-exchange", true)
call TriggerRegisterPlayerChatEvent(gg_trg_ExchangeUnits, udg_Player2, "-exchange", true)
call TriggerAddAction(gg_trg_ExchangeUnits, function ExchangeUnits)
endfunction
//TESH.scrollpos=54
//TESH.alwaysfold=0
function ConstructionComplete takes nothing returns boolean
local player p1 = GetTriggerPlayer()
local player p2
local unit u1 = GetTriggerUnit()
local unit u2
local integer id = GetUnitTypeId(u1)
local integer i
local integer hid = GetHandleId(u1)
local real x = GetUnitX(u1)
local real y = GetUnitY(u1)
local string s = "constructed"
if id == 'etol' or id == 'etoa' or id == 'etoe' or id == 'eate' or id == 'eaom' or id == 'edob' then
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
if id == 'etoa' or id == 'etoe' then
set s = "upgraded to"
endif
set u2 = LoadUnitHandle(udg_TechHash, 0, hid)
if not (u2 == null) then
call RemoveUnit(u2)
endif
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|cff6666ccTECHTREE|r - " + GetPlayerName(p1) + " has " + s + " a "+GetUnitName(u1) + " for both players.")
set i = id - 'e'*256*256*256 + 'z'*256*256*256
set u2 = CreateUnit(p2, i, x, y, 0)
call SaveUnitHandle(udg_TechHash, 0, hid, u2)
call SetUnitX(u2, x)
call SetUnitY(u2, y)
endif
set p1 = null
set p2 = null
set u1 = null
set u2 = null
return false
endfunction
function BuildingDies takes nothing returns boolean
local unit u1 = GetTriggerUnit()
local unit u2
local integer id = GetUnitTypeId(u1)
if id == 'etol' or id == 'etoa' or id == 'etoe' or id == 'eate' or id == 'eaom' or id == 'edob' then
set u2 = LoadUnitHandle(udg_TechHash, 0, GetHandleId(u1))
if not (u2 == null) then
call RemoveUnit(u2)
endif
endif
set u1 = null
set u2 = null
return false
endfunction
function InitTrig_TechShare takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local unit u
local real x
local real y
set udg_TechHash = InitHashtable()
//On Completion
call TriggerRegisterPlayerUnitEvent(t1, udg_Player1, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, null)
call TriggerRegisterPlayerUnitEvent(t1, udg_Player2, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, null)
call TriggerRegisterPlayerUnitEvent(t1, udg_Player1, EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
call TriggerRegisterPlayerUnitEvent(t1, udg_Player2, EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
call TriggerAddCondition(t1, Condition(function ConstructionComplete))
//On Death
call TriggerRegisterPlayerUnitEvent(t2, udg_Player1, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(t2, udg_Player2, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddCondition(t2, Condition(function BuildingDies))
//Blue TOA
set x = GetUnitX(gg_unit_etoa_0189)
set y = GetUnitY(gg_unit_etoa_0189)
set u = CreateUnit(udg_Player2, 'ztoa', x, y, 0)
call SetUnitX(u, x)
call SetUnitY(u, y)
call SaveUnitHandle(udg_TechHash, 0, GetHandleId(gg_unit_etoa_0189), u)
//Teal TOL
set x = GetUnitX(gg_unit_etol_0001)
set y = GetUnitY(gg_unit_etol_0001)
set u = CreateUnit(udg_Player1, 'ztol', x, y, 0)
call SetUnitX(u, x)
call SetUnitY(u, y)
call SaveUnitHandle(udg_TechHash, 0, GetHandleId(gg_unit_etol_0001), u)
//Teal AOW
set x = GetUnitX(gg_unit_eaom_0045)
set y = GetUnitY(gg_unit_eaom_0045)
set u = CreateUnit(udg_Player1, 'zaom', x, y, 0)
call SetUnitX(u, x)
call SetUnitY(u, y)
call SaveUnitHandle(udg_TechHash, 0, GetHandleId(gg_unit_eaom_0045), u)
//Teal HH
set x = GetUnitX(gg_unit_edob_0103)
set y = GetUnitY(gg_unit_edob_0103)
set u = CreateUnit(udg_Player1, 'zdob', x, y, 0)
call SetUnitX(u, x)
call SetUnitY(u, y)
call SaveUnitHandle(udg_TechHash, 0, GetHandleId(gg_unit_edob_0103), u)
endfunction
//TESH.scrollpos=105
//TESH.alwaysfold=0
function ResearchStart takes nothing returns boolean
local player p1 = GetTriggerPlayer()
local player p2
local integer i
local integer t = GetResearched()
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
call SetPlayerTechMaxAllowed(p2, t, GetPlayerTechCount(p1, t, true))
set p1 = null
set p2 = null
return false
endfunction
function ResearchComplete takes nothing returns boolean
local player p1 = GetTriggerPlayer()
local player p2
local integer t = GetResearched()
local integer i
local integer tn
local integer t1
local integer t2
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
set i = 1
loop
exitwhen i > udg_ResearchMax
if udg_ResearchType[i] == t then
set t1 = GetPlayerTechMaxAllowed(p1, t)
set t2 = GetPlayerTechMaxAllowed(p2, t)
// In one of the players transfered the building that doing the research
// Without this, it wouldn't let the other player research the next level(s)
if t1 >= t2 then
set tn = GetPlayerTechCount(p1, t, true)
call SetPlayerTechMaxAllowed(p1, t, t1)
call SetPlayerTechResearched(p1, t, tn)
call SetPlayerTechMaxAllowed(p2, t, t1)
call SetPlayerTechResearched(p2, t, tn)
else
set tn = GetPlayerTechCount(p2, t, true)
call SetPlayerTechMaxAllowed(p1, t, t2)
call SetPlayerTechResearched(p1, t, tn)
call SetPlayerTechMaxAllowed(p2, t, t2)
call SetPlayerTechResearched(p2, t, tn)
endif
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|cff9966ccRESEARCH|r - " + GetPlayerName(p1) + " has researched " + udg_ResearchString[(i - 1)*3 + tn] + " for both players.")
call StartSound(gg_snd_Hint)
exitwhen true
endif
set i = i + 1
endloop
set p1 = null
set p2 = null
return false
endfunction
function ResearchCancel takes nothing returns boolean
local player p1 = GetTriggerPlayer()
local player p2
local integer t = GetResearched()
local integer i
local integer t1
local integer t2
if p1 == udg_Player1 then
set p2 = udg_Player2
else
set p2 = udg_Player1
endif
set i = 1
loop
exitwhen i > udg_ResearchMax
if udg_ResearchType[i] == t then
set t1 = GetPlayerTechMaxAllowed(p1, t)
set t2 = GetPlayerTechMaxAllowed(p2, t)
// In one of the players transfered the building that doing the research
// Without this, it wouldn't let the other player research the next level(s)
if t1 >= t2 then
call SetPlayerTechMaxAllowed(p1, t, t1)
call SetPlayerTechMaxAllowed(p2, t, t1)
else
call SetPlayerTechMaxAllowed(p1, t, t2)
call SetPlayerTechMaxAllowed(p2, t, t2)
endif
exitwhen true
endif
set i = i + 1
endloop
set p1 = null
set p2 = null
return false
endfunction
function InitTrig_ResearchShare takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t1, udg_Player1, EVENT_PLAYER_UNIT_RESEARCH_START, null)
call TriggerRegisterPlayerUnitEvent(t1, udg_Player2, EVENT_PLAYER_UNIT_RESEARCH_START, null)
call TriggerAddCondition(t1, Condition(function ResearchStart))
call TriggerRegisterPlayerUnitEvent(t2, udg_Player1, EVENT_PLAYER_UNIT_RESEARCH_FINISH, null)
call TriggerRegisterPlayerUnitEvent(t2, udg_Player2, EVENT_PLAYER_UNIT_RESEARCH_FINISH, null)
call TriggerAddCondition(t2, Condition(function ResearchComplete))
call TriggerRegisterPlayerUnitEvent(t3, udg_Player1, EVENT_PLAYER_UNIT_RESEARCH_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(t3, udg_Player2, EVENT_PLAYER_UNIT_RESEARCH_CANCEL, null)
call TriggerAddCondition(t3, Condition(function ResearchCancel))
set t1 = null
set t2 = null
set t3 = null
endfunction
//TESH.scrollpos=15
//TESH.alwaysfold=0
function CinematicSkip takes nothing returns boolean
local player p = GetTriggerPlayer()
if udg_Intro_Cin_Skip or udg_Skull_Cin_Skip or udg_Outro_Cin_Skip then
if not (udg_P1Skip or udg_P2Skip) then
if p == udg_Player1 then
set udg_P1Skip = true
else
set udg_P2Skip = true
endif
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|cffcc6600ALLIES|r - " + GetPlayerName(p) + " wishes to skips this cinematic.")
elseif (p == udg_Player1 and udg_P2Skip) or (p == udg_Player2 and udg_P1Skip) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|cffcc6600ALLIES|r - Cinematic skipped.")
set udg_cinSkip = true
set udg_P1Skip = false
set udg_P2Skip = false
if udg_Intro_Cin_Skip then
call TriggerExecute(gg_trg_Intro_Cin_Skip)
set udg_Intro_Cin_Skip = false
elseif udg_Skull_Cin_Skip then
call TriggerExecute(gg_trg_Skull_Cin_Skip)
set udg_Skull_Cin_Skip = false
elseif udg_Outro_Cin_Skip then
call TriggerExecute(gg_trg_Outro_Cin_Skip)
set udg_Outro_Cin_Skip = false
endif
endif
endif
return false
endfunction
function InitTrig_CinematicSkip takes nothing returns nothing
set gg_trg_CinematicSkip = CreateTrigger()
call TriggerRegisterPlayerEvent(gg_trg_CinematicSkip, udg_Player1, EVENT_PLAYER_END_CINEMATIC)
call TriggerRegisterPlayerEvent(gg_trg_CinematicSkip, udg_Player2, EVENT_PLAYER_END_CINEMATIC)
call TriggerAddCondition(gg_trg_CinematicSkip, Condition(function CinematicSkip))
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function OnDeath takes nothing returns boolean
local integer i
local integer j
if GetTriggerUnit() == gg_unit_H002_0060 then
set udg_MageAlive = false
set i = 0
loop
exitwhen i >= udg_OrbCount
if udg_OrbStatus[i] == 0 then
call KillUnit(udg_Orbs[i])
set j = i
loop
exitwhen j >= udg_OrbCount
set udg_Orbs[j] = udg_Orbs[j + 1]
set udg_OrbTU[j] = udg_OrbTU[j + 1]
set udg_OrbAA[j] = udg_OrbAA[j + 1]
set udg_OrbAT[j] = udg_OrbAT[j + 1]
set udg_OrbDistance[j] = udg_OrbDistance[j + 1]
set udg_OrbSZ[j] = udg_OrbSZ[j + 1]
set udg_OrbDamage[j] = udg_OrbDamage[j + 1]
set udg_OrbTX[j] = udg_OrbTX[j + 1]
set udg_OrbTY[j] = udg_OrbTY[j + 1]
set udg_OrbTZ[j] = udg_OrbTZ[j + 1]
set udg_OrbMasteryLevel[j] = udg_OrbMasteryLevel[j + 1]
set udg_OrbStatus[j] = udg_OrbStatus[j + 1]
set j = j + 1
endloop
set i = i - 1
endif
set i = i + 1
endloop
endif
return false
endfunction
function OnRevive takes nothing returns boolean
if GetTriggerUnit() == gg_unit_H002_0060 then
set udg_MageAlive = true
set udg_Orbs[0] = CreateUnit(Player(2), 'ofir', 0, 0, 0)
if UnitAddAbility(udg_Orbs[0],'Amrf') and UnitRemoveAbility(udg_Orbs[0],'Amrf') then
endif
set udg_Orbs[1] = CreateUnit(Player(2), 'ofro', 0, 0, 0)
if UnitAddAbility(udg_Orbs[1],'Amrf') and UnitRemoveAbility(udg_Orbs[1],'Amrf') then
endif
set udg_Orbs[2] = CreateUnit(Player(2), 'olig', 0, 0, 0)
if UnitAddAbility(udg_Orbs[2],'Amrf') and UnitRemoveAbility(udg_Orbs[2],'Amrf') then
endif
set udg_OrbAA[0] = 0
set udg_OrbAA[1] = 0
set udg_OrbAA[2] = 0
set udg_OrbStatus[0] = 0
set udg_OrbStatus[1] = 0
set udg_OrbStatus[2] = 0
set udg_OrbsAttached = 3
set udg_OrbCount = 3
endif
return false
endfunction
function OnReAddOrb takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = LoadInteger(udg_MageSpellsTable, GetHandleId(t), 0)
local integer i = udg_OrbCount
if udg_MageAlive then
set udg_Orbs[i] = CreateUnit(Player(2), id, GetUnitX(udg_Orbs[i]), GetUnitY(udg_Orbs[i]), 0)
if UnitAddAbility(udg_Orbs[i],'Amrf') and UnitRemoveAbility(udg_Orbs[i],'Amrf') then
endif
set udg_OrbAA[i] = 0
set udg_OrbStatus[i] = 0
set udg_OrbCount = udg_OrbCount + 1
set udg_OrbsAttached = udg_OrbsAttached + 1
endif
call FlushChildHashtable(udg_MageSpellsTable, GetHandleId(t))
call DestroyTimer(t)
endfunction
function OnDamage takes nothing returns boolean
local integer i
local integer uid
local real dx
local real dy
local timer t
local unit u
if udg_PDD_source == gg_unit_H002_0060 and udg_PDD_damageType == udg_PDD_PHYSICAL then
set i = 0
loop
exitwhen i >= udg_OrbCount
if udg_OrbStatus[i] == 0 then
set udg_OrbDamage[i] = udg_PDD_amount
set udg_OrbStatus[i] = 1
set udg_OrbMasteryLevel[i] = GetUnitAbilityLevel(gg_unit_H002_0060, 'A003')
set dx = GetUnitX(udg_Orbs[i])
set dy = GetUnitY(udg_Orbs[i])
set udg_OrbTU[i] = udg_PDD_target
set udg_OrbTX[i] = GetUnitX(udg_OrbTU[i])
set udg_OrbTY[i] = GetUnitY(udg_OrbTU[i])
call SetUnitFacing(udg_Orbs[i], Atan2(udg_OrbTY[i] - dy, udg_OrbTX[i] - dx))
set udg_OrbTZ[i] = GetUnitFlyHeight(udg_OrbTU[i])
set udg_OrbSZ[i] = 100
set udg_OrbDistance[i] = 0
set udg_OrbsAttached = udg_OrbsAttached - 1
set t = CreateTimer()
call UnitRemoveAbility(gg_unit_H002_0060, 'A005')
call UnitRemoveAbility(gg_unit_H002_0060, 'A006')
call UnitRemoveAbility(gg_unit_H002_0060, 'A007')
set uid = GetUnitTypeId(udg_Orbs[i])
set u = CreateUnit(udg_DummyOwner, 'u002', GetUnitX(gg_unit_H002_0060), GetUnitY(gg_unit_H002_0060), 0)
if uid == 'ofir' then
call UnitAddAbility(u, 'A006')
call IssueTargetOrder(u, "acidbomb", gg_unit_H002_0060)
call UnitApplyTimedLife(u, 'BTLF', 1)
elseif uid == 'ofro' then
call UnitAddAbility(u, 'A007')
call IssueTargetOrder(u, "acidbomb", gg_unit_H002_0060)
call UnitApplyTimedLife(u, 'BTLF', 1)
elseif uid == 'olig' then
call UnitAddAbility(u, 'A005')
call IssueTargetOrder(u, "acidbomb", gg_unit_H002_0060)
call UnitApplyTimedLife(u, 'BTLF', 1)
endif
call SaveInteger(udg_MageSpellsTable, GetHandleId(t), 0, GetUnitTypeId(udg_Orbs[i]))
call TimerStart(t, 1.5, false, function OnReAddOrb)
exitwhen true
endif
set i = i + 1
endloop
set udg_PDD_amount = 0
endif
return false
endfunction
function OnMainLoop takes nothing returns nothing
// Short variable names make the code much more readable, imo
// Especially when you turn a 10 letter id into a 1 letter id
local integer i = 0
local integer j = 0
local integer k = 0
local unit tu
local unit du
local unit u
local real A
local real B
local real tx
local real ty
local real tz
local real dx
local real dy
local real dz
local real dl
local real dt
local real na
local real nx
local real ny
local real nz
local real mx
local real my
local real mz
local real a
local real b
local real x
local real y
local real d
local real t
local boolean bool
local location loc
loop
exitwhen i >= udg_OrbCount
if udg_OrbStatus[i] == 0 then
set udg_OrbAT[i] = (bj_PI * 2 * j)/udg_OrbsAttached
if udg_OrbAT[i] != udg_OrbAA[i] then
set d = udg_OrbAA[i] - udg_OrbAT[i]
if d >= -0.1745 and d <= 0.1745 then
set udg_OrbAA[i] = udg_OrbAT[i]
else
if Sin(d) < 0 then
set udg_OrbAA[i] = udg_OrbAA[i] + 0.1745
else
set udg_OrbAA[i] = udg_OrbAA[i] - 0.1745
endif
if udg_OrbAA[i] >= 2*bj_PI then
set udg_OrbAA[i] = udg_OrbAA[i] - 2*bj_PI
elseif udg_OrbAA[i] < 0 then
set udg_OrbAA[i] = udg_OrbAA[i] + 2*bj_PI
endif
endif
endif
set mx = GetUnitX(gg_unit_H002_0060)
set my = GetUnitY(gg_unit_H002_0060)
set x = Cos(udg_OrbAA[i] + udg_OrbCounter)*33 + mx
set y = Sin(udg_OrbAA[i] + udg_OrbCounter)*33 + my
call SetUnitFacing(udg_Orbs[i], udg_OrbAA[i] + bj_PI/4)
call SetUnitPosition(udg_Orbs[i], x, y)
call SetUnitX(udg_Orbs[i], x)
call SetUnitY(udg_Orbs[i], y)
set loc = Location(mx, my)
set mz = GetLocationZ(loc)
call MoveLocation(loc, x, y)
call SetUnitFlyHeight(udg_Orbs[i], mz - GetLocationZ(loc) + 125, 0)
call RemoveLocation(loc)
set j = j + 1
elseif udg_OrbStatus[i] == 1 then
set du = udg_Orbs[i]
set tu = udg_OrbTU[i]
set dx = GetUnitX(du)
set dy = GetUnitY(du)
set bool = GetUnitTypeId(tu) == 0 or IsUnitType(tu, UNIT_TYPE_DEAD)
if bool then
set tx = udg_OrbTX[i]
set ty = udg_OrbTY[i]
set tz = udg_OrbTZ[i]
else
set tx = GetUnitX(tu)
set ty = GetUnitY(tu)
set tz = GetUnitFlyHeight(tu)
endif
set dl = SquareRoot((dx - tx)*(dx - tx) + (dy - ty)*(dy - ty))
if dl <= 30 then
// Finish
// The height is a quadratic function, so its always at ground level in the end
call SetUnitX(du, tx)
call SetUnitY(du, ty)
call SetUnitFlyHeight(du, tz, 0)
set udg_OrbCount = udg_OrbCount - 1
if not bool then
call UnitDamageTarget(gg_unit_H002_0060, tu, udg_OrbDamage[i], false, false, null, null, null)
if udg_OrbMasteryLevel[i] > 0 then
set t = GetUnitTypeId(du)
if t == 'ofir' then
call UnitDamageTarget(gg_unit_H002_0060, tu, udg_OrbMasteryLevel[i] * udg_OrbDamage[i] / 10 , false, false, null, null, null)
elseif t == 'ofro' then
set u = CreateUnit(udg_DummyOwner, 'u002', tx, ty, 0)
call UnitAddAbility(u, 'A002')
call SetUnitAbilityLevel(u, 'A002', udg_OrbMasteryLevel[i])
call IssueTargetOrder(u, "frostnova", tu)
call UnitApplyTimedLife(u, 'BTLF', 1)
elseif t == 'olig' then
set u = CreateUnit(udg_DummyOwner, 'u002', tx, ty, 0)
call UnitAddAbility(u, 'A001')
call SetUnitAbilityLevel(u, 'A001', udg_OrbMasteryLevel[i])
call IssueTargetOrder(u, "thunderbolt", tu)
call UnitApplyTimedLife(u, 'BTLF', 1)
endif
endif
endif
call KillUnit(du)
set k = i
loop
exitwhen k >= udg_OrbCount
set udg_Orbs[k] = udg_Orbs[k + 1]
set udg_OrbTU[k] = udg_OrbTU[k + 1]
set udg_OrbAA[k] = udg_OrbAA[k + 1]
set udg_OrbAT[k] = udg_OrbAT[k + 1]
set udg_OrbDistance[k] = udg_OrbDistance[k + 1]
set udg_OrbSZ[k] = udg_OrbSZ[k + 1]
set udg_OrbDamage[k] = udg_OrbDamage[k + 1]
set udg_OrbTX[k] = udg_OrbTX[k + 1]
set udg_OrbTY[k] = udg_OrbTY[k + 1]
set udg_OrbTZ[k] = udg_OrbTZ[k + 1]
set udg_OrbMasteryLevel[k] = udg_OrbMasteryLevel[k + 1]
set udg_OrbStatus[k] = udg_OrbStatus[k + 1]
set k = k + 1
endloop
set i = i - 1
else
set na = Atan2(ty - dy, tx - dx)
set nx = dx + Cos(na) * 20
set ny = dy + Sin(na) * 20
call SetUnitX(du, nx)
call SetUnitY(du, ny)
call SetUnitFacing(du, na)
set udg_OrbDistance[i] = udg_OrbDistance[i] + 20
set dt = udg_OrbDistance[i] + dl
set x = udg_OrbDistance[i] / dt
set A = (2*(100+tz)-2*dt)/(dt*dt)
set B = (tz-100-A*dt*dt)/dt
set nz = A*udg_OrbDistance[i]*udg_OrbDistance[i] + B*udg_OrbDistance[i] + 100
call SetUnitFlyHeight(du, nz, 0)
set udg_OrbTX[i] = tx
set udg_OrbTY[i] = ty
set udg_OrbTZ[i] = tz
endif
endif
set i = i + 1
endloop
set udg_OrbCounter = udg_OrbCounter + 0.06
if udg_OrbCounter >= 2*bj_PI then
set udg_OrbCounter = 0
endif
set tu = null
set du = null
endfunction
function OnFrostShockOrder takes nothing returns boolean
set udg_FSChanneling = false
return false
endfunction
function OnFrostShockLoop takes nothing returns nothing
local integer i = 0
local integer k
local real A
local real B
local real a
local real x1
local real y1
local real x2
local real y2
local real z
local unit u
local unit d
local group g
loop
exitwhen i >= udg_FSTotal
set x1 = GetUnitX(udg_FSShard[i])
set y1 = GetUnitY(udg_FSShard[i])
if udg_FSDTotal[i] - udg_FSDistance[i] > 20 then
set a = GetUnitFacing(udg_FSShard[i])*bj_DEGTORAD
set x2 = 20*Cos(a) + x1
set y2 = 20*Sin(a) + y1
// One of Moyack's formulae
// Should be using this one instead of the others
// but I will change that later - difference is negligable
set A = (150-2*udg_FSDTotal[i])/(udg_FSDTotal[i]*udg_FSDTotal[i])
set B = (-75-A*udg_FSDTotal[i]*udg_FSDTotal[i])/udg_FSDTotal[i]
set z = A*udg_FSDistance[i]*udg_FSDistance[i] + B*udg_FSDistance[i] + 100
call SetUnitX(udg_FSShard[i], x2)
call SetUnitY(udg_FSShard[i], y2)
call SetUnitFlyHeight(udg_FSShard[i], z, 0)
set udg_FSDistance[i] = udg_FSDistance[i] + 20
else
call KillUnit(udg_FSShard[i])
set g = CreateGroup()
call GroupEnumUnitsInRange(g, udg_FSCX, udg_FSCY, 200, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
set a = (udg_FSLevel - 1)*5 + 25
if IsUnitType(u, UNIT_TYPE_STRUCTURE) then
set a = a/2
else
set d = CreateUnit(udg_DummyOwner, 'u002', x1, y1, 0)
call UnitAddAbility(d, 'A00M')
call SetUnitAbilityLevel(d, 'A00M', udg_FSLevel)
call IssueTargetOrder(d, "acidbomb", u)
call UnitApplyTimedLife(d, 'BTLF', 1)
endif
call UnitDamageTarget(gg_unit_H002_0060, u, a, false, false, null, null, null)
call GroupRemoveUnit(g, u)
endloop
call DestroyGroup(g)
set k = i
loop
exitwhen k >= udg_FSTotal
set udg_FSShard[k] = udg_FSShard[k + 1]
set udg_FSDTotal[k] = udg_FSDTotal[k + 1]
set udg_FSDistance[k] = udg_FSDistance[k + 1]
set udg_FSTX[k] = udg_FSTX[k + 1]
set udg_FSTY[k] = udg_FSTY[k + 1]
set k = k + 1
endloop
set i = i - 1
set udg_FSTotal = udg_FSTotal - 1
endif
set i = i + 1
endloop
endfunction
function OnFrostShockCreate takes nothing returns nothing
local real a
local real d
local real x
local real y
if udg_FSChanneling then
set a = GetRandomReal(0, 2*bj_PI)
set d = GetRandomReal(0, 150)
set x = GetUnitX(gg_unit_H002_0060)
set y = GetUnitY(gg_unit_H002_0060)
set udg_FSTX[udg_FSTotal] = d*Cos(a) + udg_FSCX
set udg_FSTY[udg_FSTotal] = d*Sin(a) + udg_FSCY
set udg_FSShard[udg_FSTotal] = CreateUnit(udg_DummyOwner, 'ofro', x, y, Atan2(udg_FSTY[udg_FSTotal] - y, udg_FSTX[udg_FSTotal] - x)*bj_RADTODEG)
if UnitAddAbility(udg_FSShard[udg_FSTotal],'Amrf') and UnitRemoveAbility(udg_FSShard[udg_FSTotal],'Amrf') then
endif
call SetUnitX(udg_FSShard[udg_FSTotal], x)
call SetUnitY(udg_FSShard[udg_FSTotal], y)
set udg_FSDistance[udg_FSTotal] = 0
set udg_FSDTotal[udg_FSTotal] = SquareRoot((udg_FSTX[udg_FSTotal] - x)*(udg_FSTX[udg_FSTotal] - x) + (udg_FSTY[udg_FSTotal] - y)*(udg_FSTY[udg_FSTotal] - y))
set udg_FSTotal = udg_FSTotal + 1
endif
call DestroyTimer(GetExpiredTimer())
endfunction
function OnPyroBurnLoop takes nothing returns nothing
set udg_PyroBurnTime = udg_PyroBurnTime + 1
call UnitDamageTarget(gg_unit_H002_0060, udg_PyroTU, udg_PyroLevel*10, false, false, null, null, null)
if udg_PyroBurnTime >= 7 then
call DestroyTimer(GetExpiredTimer())
endif
endfunction
function OnPyroLoop takes nothing returns nothing
// Short variable names make the code much more readable, imo
// Especially when you turn a 10 letter id into a 1 letter id
local unit tu = udg_PyroTU
local unit du = udg_PyroDU
local real tx
local real ty
local real tz
local real dx = GetUnitX(du)
local real dy = GetUnitY(du)
local real dz
local real dl
local real dt
local real na
local real nx
local real ny
local real nz
local real a
local real b
local real x
local boolean bool
set bool = GetUnitTypeId(udg_PyroTU) == 0 or IsUnitType(udg_PyroTU, UNIT_TYPE_DEAD)
if bool then
set tx = udg_PyroTX
set ty = udg_PyroTY
set tz = udg_PyroTZ
else
set tx = GetUnitX(tu)
set ty = GetUnitY(tu)
set tz = GetUnitFlyHeight(tu)
endif
set dl = SquareRoot((dx - tx)*(dx - tx) + (dy - ty)*(dy - ty))
if dl <= 22.5 then
// Finish
// The height is a quadratic function, so its always at ground level in the end
call SetUnitX(du, tx)
call SetUnitY(du, ty)
call SetUnitFlyHeight(udg_PyroDU, tz, 0)
if not bool then
call UnitDamageTarget(gg_unit_H002_0060, tu, udg_PyroLevel*50 + 25, false, false, null, null, null)
set udg_PyroBurnTime = 0
set du = CreateUnit(udg_DummyOwner, 'u002', GetUnitX(tu), GetUnitY(tu), 0)
call UnitAddAbility(du, 'A00K')
call IssueTargetOrder(du, "acidbomb", tu)
call UnitApplyTimedLife(du, 'BTLF', 1)
call TimerStart(CreateTimer(), 1.0, true, function OnPyroBurnLoop)
endif
call KillUnit(udg_PyroDU)
call DestroyTimer(GetExpiredTimer())
else
set na = Atan2(ty - dy, tx - dx)
set nx = dx + Cos(na)*15
set ny = dy + Sin(na)*15
call SetUnitX(du, nx)
call SetUnitY(du, ny)
set udg_PyroDistance = udg_PyroDistance + 15
set dt = udg_PyroDistance + dl
set x = udg_PyroDistance/dt
set nz = 0.8 * (dt - udg_PyroDistance) * (udg_PyroDistance / dt)
call SetUnitFlyHeight(du, nz, 0)
set udg_PyroTX = tx
set udg_PyroTY = ty
set udg_PyroTZ = tz
endif
set tu = null
set du = null
endfunction
function OnSpellCast takes nothing returns boolean
local integer id = GetSpellAbilityId()
local integer tid
local integer i
local unit u
local unit tu
local real dx
local real dy
if id == 'PYRO' then
set u = GetTriggerUnit()
set tu = GetSpellTargetUnit()
set udg_PyroLevel = GetUnitAbilityLevel(u, 'PYRO')
set dx = GetUnitX(u)
set dy = GetUnitY(u)
set udg_PyroTX = GetUnitX(tu)
set udg_PyroTY = GetUnitY(tu)
set udg_PyroDU = CreateUnit(udg_DummyOwner, 'u000', dx, dy, Atan2(udg_PyroTY - dy, udg_PyroTX - dx))
set udg_PyroTZ = GetUnitFlyHeight(udg_PyroDU)
set udg_PyroTU = tu
call SetUnitX(udg_PyroDU, dx)
call SetUnitY(udg_PyroDU, dy)
set udg_PyroDistance = 0
call TimerStart(CreateTimer(), 0.03125, true, function OnPyroLoop)
elseif id == 'A008' then
set i = 0
set udg_FSLevel = GetUnitAbilityLevel(gg_unit_H002_0060, 'A008')
set udg_FSTotal = 0
set udg_FSCX = GetSpellTargetX()
set udg_FSCY = GetSpellTargetY()
set udg_FSChanneling = true
loop
exitwhen i == udg_FSLevel + 5
call TimerStart(CreateTimer(), 0.25*i, false, function OnFrostShockCreate)
set i = i + 1
endloop
endif
set u = null
set tu = null
return false
endfunction
function InitTrig_Mage_Spells takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
local trigger t4 = CreateTrigger()
// Manually called because it is in the header
call InitTrig_DamageEvent()
call TriggerAddCondition(t1, Condition(function OnSpellCast))
call TriggerRegisterPlayerUnitEvent(t1, udg_Player2, EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerAddCondition(t2, Condition(function OnDeath))
call TriggerRegisterPlayerUnitEvent(t2, udg_Player2, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerAddCondition(t3, Condition(function OnRevive))
call TriggerRegisterPlayerUnitEvent(t3, udg_Player2, EVENT_PLAYER_HERO_REVIVE_FINISH, null)
call TriggerAddCondition(t4, Condition(function OnFrostShockOrder))
call TriggerRegisterUnitEvent(t4, gg_unit_H002_0060, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(t4, gg_unit_H002_0060, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterUnitEvent(t4, gg_unit_H002_0060, EVENT_UNIT_ISSUED_ORDER)
call AddDamageHandler(function OnDamage)
call TimerStart(CreateTimer(), 0.03125, true, function OnMainLoop)
call TimerStart(CreateTimer(), 0.03125, true, function OnFrostShockLoop)
// Init needed variables
set udg_MageSpellsTable = InitHashtable()
set udg_DummyOwner = Player(15)
set udg_FSTotal = 0
set udg_OrbCounter = 0
set udg_MageAlive = true
// Create starting orbs
set udg_Orbs[0] = CreateUnit(Player(2), 'ofir', 0, 0, 0)
if UnitAddAbility(udg_Orbs[0],'Amrf') and UnitRemoveAbility(udg_Orbs[0],'Amrf') then
endif
set udg_Orbs[1] = CreateUnit(Player(2), 'ofro', 0, 0, 0)
if UnitAddAbility(udg_Orbs[1],'Amrf') and UnitRemoveAbility(udg_Orbs[1],'Amrf') then
endif
set udg_Orbs[2] = CreateUnit(Player(2), 'olig', 0, 0, 0)
if UnitAddAbility(udg_Orbs[2],'Amrf') and UnitRemoveAbility(udg_Orbs[2],'Amrf') then
endif
set udg_OrbAA[0] = 0
set udg_OrbAA[1] = 0
set udg_OrbAA[2] = 0
set udg_OrbStatus[0] = 0
set udg_OrbStatus[1] = 0
set udg_OrbStatus[2] = 0
set udg_OrbsAttached = 3
set udg_OrbCount = 3
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function FOD_Cast takes nothing returns boolean
local unit u
local unit u1
local real damage = 500
if udg_InsaneMode then
set damage = 700
endif
if GetSpellAbilityId() == 'ANfd' then
set u = GetTriggerUnit()
set u1 = GetSpellTargetUnit()
if GetUnitLife(u1) <= damage then
call SetUnitExploded(u1, true)
endif
call UnitDamageTarget(u, u1, damage, true, true, null, null, null)
endif
set u = null
set u1 = null
return false
endfunction
function InitTrig_FOD takes nothing returns nothing
set gg_trg_FOD = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_FOD, Player(6), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
call TriggerAddCondition(gg_trg_FOD, Condition(function FOD_Cast))
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function OnReviveHC takes nothing returns boolean
local integer level
if GetRevivingUnit() == udg_HellCaller and GetHeroLevel(udg_HellCaller) < 15 then
set level = GetHeroLevel(udg_HellCaller) + 1
call SetHeroLevel(udg_HellCaller, level, false)
call SelectHeroSkill(udg_HellCaller, udg_HellCallerAbilities[level - 10])
call SelectHeroSkill(udg_HellCaller, udg_HellCallerAbilities[level - 5])
endif
return false
endfunction
function InitTrig_HeroReviveHC takes nothing returns nothing
set gg_trg_HeroReviveHC = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_HeroReviveHC, Player(11), EVENT_PLAYER_HERO_REVIVE_FINISH, null)
call TriggerAddCondition(gg_trg_HeroReviveHC, Condition(function OnReviveHC))
endfunction