//TESH.scrollpos=595
//TESH.alwaysfold=0
//########################################################################
//## HERO SAVE SYSTEM BY DIE_BACKE ##
//## SCRIPTED BY: BACKE ##
//## THANKS FOR HELP GO TO: BUSTER, MUESLIROCKER, KAD_WE, PEPPAR ##
//## VERSION: 1.3.1 ##
//########################################################################
//-----------PA-----------
//Die PA-Funktionen sind Funktionen, die keine Parameterkontrollen durchführen. Diese Funktionen
//müssen unter allen Umständen mit gültigen Parametern aufgerufen werden! Damit man sich daran erinnert,
//tragen alle Diese Funktionen das Suffix "PA".
//-----------..function for returning the index of a substring..----------
//**********NATIVE FUNCTION**********
//returns the index of the first letter of the first occurence of the searchtext in the text.
//returns -1 if not found
function IndexOfSubstring takes string text, string searchtext returns integer
local integer i = 1
if (StringLength(text) >= StringLength(searchtext)) then
loop
exitwhen (i > (StringLength(text) - StringLength(searchtext) + 1))
if (SubStringBJ(text, i, i + StringLength(searchtext) - 1) == searchtext) then
return i - 1
endif
set i = i + 1
endloop
endif
return -1
endfunction
//As above, but only for single-lettered searchstrings
//never pass searchChar with more or less than 1 letter! If this might occure, use IndexOfChar instead
function IndexOfCharPA takes string text, string searchChar returns integer
local integer i = 0
local integer textlength = StringLength(text)
//loop through the letters
loop
exitwhen (i >= textlength)
//if the letter at index i is the searched letter
if (SubStringBJ(text, i, i) == searchChar) then
return i
endif
set i = i + 1
endloop
//letter was not found
return -1
endfunction
//---..Converter from Alphanumeric strings to Integers and vice-versa..---
//**********REQUIRES IndexOfSubstring()**********
function Int2Alphanumeric takes integer int, string alphabet returns string
local string alphanumeric = ""
local integer index = 0
if ((int < 0) or (int > 0x7FFFFFFF)) then
return "|cffff0000Invalid parameter passed to function Int2Alphanumeric()!|r"
endif
loop
set index = ModuloInteger(int, StringLength(alphabet)) + 1
set int = int / StringLength(alphabet)
set alphanumeric = SubStringBJ(alphabet, index, index) + alphanumeric
exitwhen (int == 0)
endloop
return alphanumeric
endfunction
function Alphanumeric2Int takes string str, string alphabet returns integer
local integer int = 0
local integer index = 1
loop
set int = int + ( ( IndexOfSubstring( alphabet, SubString(str, StringLength(str) - 1, StringLength(str)) ) ) * index )
exitwhen StringLength(str) == 1
set str = SubStringBJ( str, 1, StringLength(str) - 1 )
set index = index * StringLength(alphabet)
endloop
return int
endfunction
//---------------------------..ascii converter..--------------------------
//**********NATIVE FUNCTION**********
function AsciiIntegerToChar takes integer i returns string
if i == 0 then
return null
elseif i >= 8 and i <= 10 then
return SubString("\b\t\n", i - 8, i - 7)
elseif i >= 12 and i <= 13 then
return SubString("\f\r", i - 12, i - 11)
elseif i >= 32 and i <= 127 then
return SubString(" !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", i - 32, i - 31)
endif
return ""
endfunction
function AsciiCharToInteger takes string char returns integer
local string charMap = " !\"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
local string u = SubString(char, 0, 1)
local string c
local integer i = 0
if u == "" or u == null then
return 0
elseif u == "\b" then // Backspace?
return 8
elseif u == "\t" then // Horizontal Tab?
return 9
elseif u == "\n" then // Newline
return 10
elseif u == "\f" then // Form feed?
return 12
elseif u == "\r" then // Carriage return
return 13
endif
loop
set c = SubString(charMap, i, i + 1)
exitwhen c == ""
if c == u then
return i + 32
endif
set i = i + 1
endloop
return 0
endfunction
//---------------------------..ItemID Converter..-------------------------
//**********REQUIRES AsciiIntegerToChar()**********
//**********REQUIRES AsciiCharToInteger()**********
function Id takes string IdString returns integer
local string array bytes
local integer index = 1
loop
exitwhen index == 5
set bytes[index] = SubStringBJ(IdString, index, index)
set index = index + 1
endloop
set index = 1
loop
exitwhen index == 5
set bytes[index] = Int2Alphanumeric(AsciiCharToInteger(bytes[index]), "01")
set index = index + 1
endloop
set index = 1
loop
exitwhen index == 5
loop
exitwhen StringLength(bytes[index]) == 8
set bytes[index] = "0" + bytes[index]
endloop
set index = index + 1
endloop
return Alphanumeric2Int(bytes[1] + bytes[2] + bytes[3] + bytes[4], "01")
endfunction
function Id2String takes integer Idint returns string
local string result = Int2Alphanumeric(Idint, "01")
local integer index = 1
local string array bytes
if ( StringLength(result) > 32 ) then
return "0000"
endif
loop
exitwhen StringLength(result) == 32
set result = "0" + result
endloop
loop
set bytes[index] = SubStringBJ(result, 1, 8)
exitwhen index == 4
set result = SubStringBJ(result, 9, StringLength(result))
set index = index + 1
endloop
set index = 1
loop
exitwhen index == 5
set bytes[index] = AsciiIntegerToChar(Alphanumeric2Int(bytes[index], "01"))
set index = index + 1
endloop
return bytes[1] + bytes[2] + bytes[3] + bytes[4]
endfunction
//-------------------..Code for creating the hero-key..-------------------
//**********REQUIRES IndexOfCharPA()**********
//**********REQUIRES Int2Alphanumeric()**********
function CreateKey takes string text, integer keylength, string alphabet returns string
local integer product = 0
local integer i
local integer textlength
if ( keylength == 0 ) then
return ""
endif
set textlength = StringLength(text)
set i = 0
//sum up all the letters
loop
set product = product + ( (IndexOfSubstring(alphabet, SubString(text, i, i + 1)) + keylength) * (i * i) )
set i = i + 1
exitwhen (i >= textlength)
endloop
return Int2Alphanumeric(ModuloInteger(product, R2I(Pow(I2R(StringLength(alphabet)), I2R(keylength)))), alphabet)
endfunction
//-----..Code for translating the charmap to alphabet and vice-versa..----
//**********REQUIRES IndexOfSubstring()**********
function Alphabet2Charmap takes string alphabet, string charmap, string text returns string
local integer length = StringLength(text)
local integer index = 0
local string result = ""
loop
exitwhen (StringLength(result) == length)
set index = (IndexOfSubstring(alphabet, SubStringBJ(text, 1, 1)) + 1)
set result = result + SubStringBJ(charmap, index, index)
set text = SubStringBJ(text, 2, StringLength(text))
endloop
return result
endfunction
//-----------------------..Optimize the hero data..-----------------------
//makes the IDs of unit and items shorter by deleting unused parts
function OptimizeId takes string IdString, integer configuration returns string
return SubStringBJ(IdString, StringLength(IdString) - configuration + 1, StringLength(IdString))
endfunction
function OptimizeUnitId takes integer unitId, integer configuration returns string
if ( configuration == 0 ) then
return ""
endif
//return OptimizeId(UnitId2String(unitId), configuration)
return Id2String(unitId)
endfunction
function OptimizeItemId takes integer itemId, integer configuration returns string
if ( configuration == 0 ) then
return ""
elseif ( itemId == 0 ) then
return OptimizeId("####", configuration)
endif
return OptimizeId(Id2String(itemId), configuration)
endfunction
//this one is for integer
function OptimizeInt takes integer Int, integer configuration, string alphabet returns string
local string biggestletter = SubString(alphabet, StringLength(alphabet) - 1, StringLength(alphabet))
local string zero = SubString(alphabet, 0, 1)
local string localstring = Int2Alphanumeric(Int, alphabet)
if ( configuration == 0 ) then
return ""
elseif ( StringLength(localstring) > configuration ) then
set localstring = ""
loop
exitwhen StringLength(localstring) == configuration
set localstring = localstring + biggestletter
endloop
return localstring
elseif ( StringLength(localstring) <= configuration ) then
loop
exitwhen (StringLength(localstring) == configuration)
set localstring = zero + localstring
endloop
return localstring
endif
return "" // error: this shouldn't happen
endfunction
//----------------------..Unoptimize the hero data..----------------------
function UnoptimizeUnitId takes string unitIdString, string prefix returns string
if ( StringLength(unitIdString) == 4 ) then
return unitIdString
endif
return SubStringBJ(prefix, 1, 4 - StringLength(unitIdString)) + unitIdString
endfunction
function UnoptimizeItemId takes string itemIdString returns integer
//if the string has the token for "no item"
if ( SubStringBJ(itemIdString, StringLength(itemIdString), StringLength(itemIdString)) == "#" ) then
return 0
//if the string is already 4 letters long
elseif ( StringLength(itemIdString) == 4 ) then
return Id(itemIdString)
endif
//else, complete the string, and convert it to integer
return Id(SubStringBJ("I000", 1, 4 - StringLength(itemIdString)) + itemIdString)
endfunction
//------------------..Code for generating the save-code..-----------------
function SaveHeroByCode takes unit hero, string saveversion returns string
//--------General Locals--------
local integer index //used as run variable for loops
local gamecache cache = udg_save_cache
local string alphabet = GetStoredString(cache, saveversion, "alphabet")
local string charmap = GetStoredString(cache, saveversion, "charmap")
local string savecode = ""
//--------Config Locals--------
local integer unitidConf
local integer itemidConf
local integer expConf
local integer strConf
local integer agiConf
local integer intConf
local integer goldConf
local integer lumberConf
//local integer lifeConf
//local integer maxlifeConf
//local integer manaConf
//local integer maxmanaConf
local integer customCnt //Not the config of a value, but the number of custom values
local integer array customConf
local integer playernameConf
local integer keyConf
//--------Data Locals--------
local string unitid
local string array itemid
local string exp
local string str
local string agi
local string int
local string gold
local string lumber
local string array custom
local string playername
//--------Get Config--------
set unitidConf = GetStoredInteger(cache, saveversion, "unitid")
set itemidConf = GetStoredInteger(cache, saveversion, "itemid")
set expConf = GetStoredInteger(cache, saveversion, "exp")
set strConf = GetStoredInteger(cache, saveversion, "str")
set agiConf = GetStoredInteger(cache, saveversion, "agi")
set intConf = GetStoredInteger(cache, saveversion, "int")
set goldConf = GetStoredInteger(cache, saveversion, "gold")
set lumberConf = GetStoredInteger(cache, saveversion, "lumber")
//set lifeConf = GetStoredInteger(cache, saveversion, "life")
//set maxlifeConf = GetStoredInteger(cache, saveversion, "maxlife")
//set manaConf = GetStoredInteger(cache, saveversion, "mana")
//set maxmanaConf = GetStoredInteger(cache, saveversion, "maxmana")
set customCnt = GetStoredInteger(cache, saveversion, "customs")
set index = 0
loop
exitwhen index >= customCnt
set customConf[index] = GetStoredInteger(cache, saveversion, "custom" + I2S(index))
set index = index + 1
endloop
set playernameConf = GetStoredInteger(cache, saveversion, "playername")
set keyConf = GetStoredInteger(cache, saveversion, "key")
call TriggerSleepAction(0.05)
//--------Get Hero Data--------
set unitid = OptimizeUnitId(GetUnitTypeId(hero), unitidConf)
set index = 0
loop
set itemid[index] = OptimizeItemId(GetItemTypeId(UnitItemInSlot(hero, index)), itemidConf)
exitwhen index >= 5
set index = index + 1
endloop
call TriggerSleepAction(0.05)
set exp = OptimizeInt(GetHeroXP(hero), expConf, alphabet)
set str = OptimizeInt(GetHeroStr(hero, true), strConf, alphabet)
set agi = OptimizeInt(GetHeroAgi(hero, true), agiConf, alphabet)
set int = OptimizeInt(GetHeroInt(hero, true), intConf, alphabet)
set gold = OptimizeInt(GetPlayerState(GetOwningPlayer(hero), PLAYER_STATE_RESOURCE_GOLD), goldConf, alphabet)
set lumber = OptimizeInt(GetPlayerState(GetOwningPlayer(hero), PLAYER_STATE_RESOURCE_LUMBER), lumberConf, alphabet)
call TriggerSleepAction(0.05)
set index = 0
loop
exitwhen index >= customCnt
set custom[index] = OptimizeInt(udg_save_customs[index], customConf[index], alphabet)
set index = index + 1
endloop
call TriggerSleepAction(0.05)
set playername = CreateKey(GetPlayerName(GetOwningPlayer(hero)), playernameConf, alphabet)
//--------Assemble Savecode--------
set savecode = unitid + itemid[0] + itemid[1] + itemid[2] + itemid[3] + itemid[4] + itemid[5]
set savecode = savecode + exp + str + agi + int + gold + lumber
set index = 0
loop
exitwhen index >= customCnt
set savecode = savecode + custom[index]
set index = index + 1
endloop
set savecode = savecode + playername
call TriggerSleepAction(0.05)
//--------Create Key--------
set savecode = savecode + CreateKey(savecode, keyConf, alphabet)
//--------Encrypt--------
set savecode = Alphabet2Charmap(alphabet, charmap, savecode)
//--------Return Result--------
return savecode
endfunction
function LoadHeroByCode takes string savecode, location respawnloc, player owner, string saveversion returns nothing
//--------General Locals--------
local integer index //used as run variable for loops
local gamecache cache = udg_save_cache
local string alphabet = GetStoredString(cache, saveversion, "alphabet")
local string charmap = GetStoredString(cache, saveversion, "charmap")
local integer codelength = 0
//--------Config Locals--------
local integer unitidConf
local integer itemidConf
local integer expConf
local integer strConf
local integer agiConf
local integer intConf
local integer goldConf
local integer lumberConf
//local integer lifeConf
//local integer maxlifeConf
//local integer manaConf
//local integer maxmanaConf
local integer customCnt //Not the config of a value, but the number of custom values
local integer array customConf
local integer playernameConf
local integer keyConf
//--------Data Locals--------
local integer unitid
local integer array itemid
local integer exp
local integer str
local integer agi
local integer int
local integer gold
local integer lumber
local integer array custom
//--------Get Config--------
call DisplayTextToForce(GetPlayersAll(), "Loading Hero...")
call DisplayTextToForce(GetPlayersAll(), "Getting Configuration")
set unitidConf = GetStoredInteger(cache, saveversion, "unitid")
set itemidConf = GetStoredInteger(cache, saveversion, "itemid")
set expConf = GetStoredInteger(cache, saveversion, "exp")
set strConf = GetStoredInteger(cache, saveversion, "str")
set agiConf = GetStoredInteger(cache, saveversion, "agi")
set intConf = GetStoredInteger(cache, saveversion, "int")
set goldConf = GetStoredInteger(cache, saveversion, "gold")
set lumberConf = GetStoredInteger(cache, saveversion, "lumber")
//set lifeConf = GetStoredInteger(cache, saveversion, "life")
//set maxlifeConf = GetStoredInteger(cache, saveversion, "maxlife")
//set manaConf = GetStoredInteger(cache, saveversion, "mana")
//set maxmanaConf = GetStoredInteger(cache, saveversion, "maxmana")
set customCnt = GetStoredInteger(cache, saveversion, "customs")
set index = 0
loop
exitwhen index >= customCnt
set customConf[index] = GetStoredInteger(cache, saveversion, "custom" + I2S(index))
set codelength = codelength + customConf[index] //Used for Codelength Verification
set index = index + 1
endloop
set playernameConf = GetStoredInteger(cache, saveversion, "playername")
set keyConf = GetStoredInteger(cache, saveversion, "key")
call TriggerSleepAction(0.05)
//--------Verify Codelenght--------
//call DisplayTextToForce(GetPlayersAll(), "Verifying Codelenght")
set codelength = codelength + unitidConf + (itemidConf * 6) + expConf
set codelength = codelength + strConf + agiConf + intConf + goldConf + lumberConf
set codelength = codelength + playernameConf + keyConf
if ( codelength != StringLength(savecode) ) then
call DisplayTextToForce(GetPlayersAll(), "INVALID CODE! MISSMATCHING STRINGLENGTH! " + I2S(codelength) + " is the correct length, and not " + I2S(StringLength(savecode)) + "!")
return
endif
//--------Decrypt--------
//call DisplayTextToForce(GetPlayersAll(), "Decrypting")
set savecode = Alphabet2Charmap(charmap, alphabet, savecode)
call TriggerSleepAction(0.05)
//--------Verify Key--------
//call DisplayTextToForce(GetPlayersAll(), "Verifying Key")
//set codelength = StringLength(savecode) //already sure
if (keyConf >= 0) then
if (CreateKey(SubStringBJ(savecode, 1, codelength - keyConf), keyConf, alphabet) != SubStringBJ(savecode, (codelength - keyConf) + 1, codelength)) then
call DisplayTextToForce(GetPlayersAll(), "INVALID CODE! MISSMATCHING KEY! Check your code (might be a writing mistake)!")
return
endif
set savecode = SubStringBJ(savecode, 1, codelength - keyConf)
endif
//--------Verify Playername--------
//call DisplayTextToForce(GetPlayersAll(), "Verifying Playername")
set codelength = StringLength(savecode)
if (playernameConf >= 0) then
if (SubStringBJ(savecode, (codelength - playernameConf) + 1, codelength) != CreateKey(GetPlayerName(owner), playernameConf, alphabet)) then
call DisplayTextToForce(GetPlayersAll(), "INVALID CODE! MISSMATCHING PLAYERNAME! Only the player, who saved, can load a hero again!")
return
endif
set savecode = SubStringBJ(savecode, 1, codelength - playernameConf)
endif
call TriggerSleepAction(0.05)
//--------Get Hero Data--------
call DisplayTextToForce(GetPlayersAll(), "Getting Hero Data")
//call DisplayTextToForce(GetPlayersAll(), " UnitID")
if (unitidConf > 0) then
set unitid = Id(UnoptimizeUnitId(SubStringBJ(savecode, 1, unitidConf), GetStoredString(cache, saveversion, "unittypeprefix")))
set savecode = SubStringBJ(savecode, unitidConf + 1, StringLength(savecode))
endif
//call DisplayTextToForce(GetPlayersAll(), " Items")
if (itemidConf > 0) then
set index = 0
loop
set itemid[index] = UnoptimizeItemId(SubStringBJ(savecode, 1, itemidConf))
set savecode = SubStringBJ(savecode, itemidConf + 1, StringLength(savecode))
exitwhen index >= 5
set index = index + 1
endloop
endif
call TriggerSleepAction(0.05)
//call DisplayTextToForce(GetPlayersAll(), " xp")
if (expConf > 0) then
set exp = Alphanumeric2Int(SubStringBJ(savecode, 1, expConf), alphabet)
set savecode = SubStringBJ(savecode, expConf + 1, StringLength(savecode))
endif
//call DisplayTextToForce(GetPlayersAll(), " str")
if (strConf > 0) then
set str = Alphanumeric2Int(SubStringBJ(savecode, 1, strConf), alphabet)
set savecode = SubStringBJ(savecode, strConf + 1, StringLength(savecode))
endif
//call DisplayTextToForce(GetPlayersAll(), " agi")
if (agiConf > 0) then
set agi = Alphanumeric2Int(SubStringBJ(savecode, 1, agiConf), alphabet)
set savecode = SubStringBJ(savecode, agiConf + 1, StringLength(savecode))
endif
//call DisplayTextToForce(GetPlayersAll(), " int")
if (intConf > 0) then
set int = Alphanumeric2Int(SubStringBJ(savecode, 1, intConf), alphabet)
set savecode = SubStringBJ(savecode, intConf + 1, StringLength(savecode))
endif
call TriggerSleepAction(0.05)
//call DisplayTextToForce(GetPlayersAll(), " gold")
if (goldConf > 0) then
set gold = Alphanumeric2Int(SubStringBJ(savecode, 1, goldConf), alphabet)
set savecode = SubStringBJ(savecode, goldConf + 1, StringLength(savecode))
endif
//call DisplayTextToForce(GetPlayersAll(), " lumber")
if (lumberConf > 0) then
set lumber = Alphanumeric2Int(SubStringBJ(savecode, 1, lumberConf), alphabet)
set savecode = SubStringBJ(savecode, lumberConf + 1, StringLength(savecode))
endif
call TriggerSleepAction(0.05)
//call DisplayTextToForce(GetPlayersAll(), " customs")
set index = 0
loop
exitwhen index >= customCnt
set custom[index] = Alphanumeric2Int(SubStringBJ(savecode, 1, customConf[index]), alphabet)
set savecode = SubStringBJ(savecode, customConf[index] + 1, StringLength(savecode))
set index = index + 1
endloop
call TriggerSleepAction(0.05)
//--------Place Hero--------
//call DisplayTextToForce(GetPlayersAll(), "Place Hero")
if (unitidConf > 0) then
call CreateUnitAtLocSaveLast(owner, unitid, respawnloc, 90.00)
if (expConf > 0) then
call SetHeroXP(GetLastCreatedUnit(), exp, false)
endif
if (itemidConf > 0) then
set index = 0
loop
call UnitAddItemById( GetLastCreatedUnit(), itemid[index])
exitwhen index >= 5
set index = index + 1
endloop
endif
if (strConf > 0) then
call ModifyHeroStat(bj_HEROSTAT_STR, GetLastCreatedUnit(), bj_MODIFYMETHOD_SET, str)
endif
if (agiConf > 0) then
call ModifyHeroStat(bj_HEROSTAT_AGI, GetLastCreatedUnit(), bj_MODIFYMETHOD_SET, agi)
endif
if (intConf > 0) then
call ModifyHeroStat(bj_HEROSTAT_INT, GetLastCreatedUnit(), bj_MODIFYMETHOD_SET, int)
endif
endif
call TriggerSleepAction(0.05)
//--------Set Resources--------
//call DisplayTextToForce(GetPlayersAll(), "Set Resource")
if (goldConf > 0) then
call SetPlayerStateBJ(owner, PLAYER_STATE_RESOURCE_GOLD, gold)
endif
if (lumberConf > 0) then
call SetPlayerStateBJ(owner, PLAYER_STATE_RESOURCE_LUMBER, lumber)
endif
call TriggerSleepAction(0.05)
//--------Set Customs--------
//call DisplayTextToForce(GetPlayersAll(), "Set Customs")
set index = 0
loop
exitwhen index >= customCnt
set udg_save_customs[index] = custom[index]
set index = index + 1
endloop
endfunction
Name | Type | is_array | initial_value |
A_AoE | real | No | |
A_AoE2 | real | No | |
A_Bool | boolean | No | |
A_Bool2 | boolean | No | |
A_Damage | real | No | |
A_Duration | real | No | |
A_Int | integer | No | |
A_Int2 | integer | No | |
A_Int3 | integer | No | |
A_Real | real | No | |
A_Real2 | real | No | |
A_Real3 | real | No | |
A_Speed | real | No | |
A_UType | unitcode | No | |
Acraninfusion_upgrade | integer | Yes | |
agility_boolean | boolean | Yes | |
agility_cache | integer | Yes | |
agility_integer | integer | Yes | |
agility_real | real | Yes | |
Amount | real | No | |
Anatomie_boolean | boolean | Yes | |
Anatomie_hits | integer | Yes | |
Ancient_of_war_lightning | lightning | No | |
Ancient_of_war_spirit | unit | Yes | |
Ancient_of_war_spirit_2 | unit | No | |
Ancientspiritsspawn | boolean | Yes | |
Ancientwardistance | real | Yes | |
backpack_unit | unit | Yes | |
battle_cry_real | real | Yes | 1.00 |
Battlecry | group | No | |
battlefury | boolean | Yes | |
Battlefuryhits | integer | Yes | |
Benutzbareinteger | integer | Yes | |
benutzbarereals | real | Yes | |
Bladeknightviciousstrikebonus | unit | Yes | |
blizzard_forest_spirit | unit | No | |
blizzardcountdown | integer | No | |
Boss_in_combat | boolean | Yes | |
Bossadds | unit | Yes | |
Bossfight1 | integer | No | |
Bossfight1integer | integer | No | |
Bossresets | integer | Yes | |
Brutalhitreal | real | Yes | 3.92 |
Brutalhitsilence | boolean | Yes | |
Caster | unit | No | |
Clapofbalance | unit | No | |
Clapofbalancegroup | group | No | |
Cloud_of_vengeance_real | real | Yes | 2.00 |
Cloud_of_vengeance_real_heal | real | Yes | 4.00 |
Cloudofvengeanceregion | rect | Yes | |
Combination_boolean | boolean | Yes | |
combopoints | integer | Yes | |
Combopoints_boni | integer | Yes | 3 |
Combopointsbonus | integer | Yes | 4 |
curse_of_justice_boolean | boolean | Yes | |
curse_of_justice_reference | unit | Yes | |
curse_of_justive_group | group | No | |
damage_meter | real | Yes | |
damage_meter_string | string | Yes | |
damage_meter_time | real | Yes | 1.00 |
Damageabfrage | real | Yes | |
Demonguardpoint | location | No | |
Demonguardrainofire | unit | No | |
Distance_ancient_war | real | No | |
divine_shield_improved_real | real | Yes | 4.50 |
divine_shield_improved_real_2 | real | Yes | |
Dot1 | integer | No | |
Dot2 | integer | No | |
Dot3 | integer | No | |
Dot4 | integer | No | |
Dps | real | Yes | |
dps_brechnung | real | Yes | |
dps_time | real | Yes | |
EarthArmour | group | No | |
elite_reset | integer | No | |
Elitegroups | group | Yes | |
Elixirbonus | unit | Yes | |
empowered_holy_light | boolean | Yes | |
EntaglingDummy | group | No | |
Eredar_dummy | unit | No | |
Evasionbladeknight | integer | Yes | |
fire_golem_real | real | Yes | |
fire_nova_real | real | Yes | 2.10 |
firebolt_replenishment_boolean | boolean | Yes | |
Firebolt_upgrade | real | Yes | 4.00 |
Fireboltperiodcaster | unit | Yes | |
Firenovagroup | group | No | |
Firenovareal | real | Yes | 2.00 |
Firenovaunit | unit | No | |
Firenovaunit2 | unit | No | |
Focusunitgroup | group | No | |
Forest_spirit_region | rect | Yes | |
Frost_armor_real | real | Yes | |
Frost_armor_real_2 | real | Yes | |
Frost_armor_unit_boolean | boolean | Yes | |
Frost_armor_upgrade_boolean | boolean | Yes | |
furtive_hit_boolean | boolean | Yes | |
furtive_hit_real | real | Yes | 1.60 |
GDD__Integers | integer | Yes | |
GDD__LeftMapGroup | group | No | |
GDD__TriggerArray | trigger | Yes | |
GDD__UnitArray | unit | Yes | |
GDD_Damage | real | No | |
GDD_DamagedUnit | unit | No | |
GDD_DamageSource | unit | No | |
GDD_Event | real | No | |
growing_boolean | boolean | Yes | |
growing_real | real | Yes | |
Hashtable | hashtable | No | |
Healingrain | unit | Yes | |
Healingwave | unit | No | |
Healwoundsboolean | boolean | Yes | |
Healwoundsboolean_perfect | boolean | Yes | |
heldeninmap | integer | No | |
hero | unit | Yes | |
hero_item_soulbound | unit | Yes | |
Heroresets | integer | Yes | |
holy_balance_group | group | Yes | |
holy_balance_improved_boolean | boolean | Yes | |
holy_balance_improved_unit | unit | Yes | |
holy_balance_integer_improved | integer | Yes | |
holy_balance_real_improved | real | Yes | |
holy_balance_timer | timer | Yes | |
holy_light_real | real | Yes | 10.00 |
holy_smite_real | real | Yes | 1.50 |
Holylight | group | No | |
Holylight_multiplier | real | Yes | 1.00 |
Holylightshieldboolean | boolean | Yes | |
holylightshieldinteger | integer | No | |
Holylightshieldunit | unit | Yes | |
holylightshieldunitdamagecount | real | Yes | |
HolyProtection | group | Yes | |
HolyProtetection | unit | Yes | |
HydroJetCasters | group | No | |
HydroJetProjectiles | group | No | |
Ice_age | boolean | Yes | |
Ice_age_2 | boolean | Yes | |
Ice_age_special_effect | effect | Yes | |
Ice_age_units | unit | Yes | |
ImpalingRoots | group | Yes | |
ImpalingRootsHit | group | Yes | |
improved_healing_wave_boolean | boolean | Yes | |
improved_healing_wave_effect | boolean | Yes | |
improved_healing_wave_real | real | Yes | |
improved_inner_fire | boolean | Yes | |
improved_natures_touch_boolean | boolean | Yes | |
improved_stealth_boolean | boolean | Yes | |
incinerate | integer | Yes | |
inner_strengh_boolean | boolean | Yes | |
inner_strengh_real | real | Yes | |
Instability_boolean | boolean | Yes | |
integer_elite | integer | No | |
integer_ylyey | integer | No | |
Itemdropinteger | integer | No | |
Klathuaim | effect | No | |
Klathucast | integer | No | |
Klathuregions | rect | Yes | |
kobold_magician_lightning | lightning | Yes | |
L | location | No | |
Laststandbuff | group | Yes | |
Laststandunit | unit | Yes | |
Laststandupgrade | boolean | Yes | |
leaderboard | leaderboard | No | |
lethalslashcaster | unit | Yes | |
Lethalslashreal | real | Yes | 4.50 |
Lifefacelesstrigger | integer | No | |
Lightninfinfuisonbuff | unit | Yes | |
lightning_infusion_boolean | boolean | Yes | |
lightning_infusion_real | real | Yes | 0.42 |
LiquidElementals | group | No | |
Loadeditems | item | Yes | |
loop_integer | integer | Yes | |
Lostspiritblizzard | unit | No | |
Lostspiritdamagegroup | group | No | |
Lostspiritdamagetaken | integer | No | |
Lostspiritpoint | location | No | |
Makruratidalkill | integer | No | |
mana_frostarmor | real | No | |
mana_manipulator_real | real | Yes | |
master_of_balance | boolean | Yes | |
Master_of_frost_boolean | boolean | Yes | |
Master_of_frost_real | real | Yes | |
Master_of_frost_real_2 | real | Yes | |
master_of_stealthiness | boolean | Yes | |
mighty_slam_debuff | group | Yes | |
mighty_slam_real | real | Yes | 1.95 |
Mightyslamhealboolean | boolean | Yes | |
Mountaingiantboolean | boolean | No | |
movementreal | real | No | |
Mui_array_integer | integer | No | |
Mui_array_integer_2 | integer | No | |
multiboard | multiboard | No | |
NatureSpirits | group | No | |
Naturestouch | destructable | Yes | |
Naturestouchunit | unit | Yes | |
NatureWards | group | No | |
Nerubaintower | unit | Yes | |
OrbsOfWater | group | No | |
order | integer | No | |
Paladinchance | integer | No | |
player_load | boolean | Yes | |
player_new | boolean | Yes | |
player_new_floating | texttag | Yes | |
player_new_floating_2 | texttag | Yes | |
player_new_floating_3 | texttag | Yes | |
player_new_floating_4 | texttag | Yes | |
PlayerColors | string | Yes | |
Playernumber | integer | No | |
Playernumber2 | integer | No | |
power_word_pain_real | real | Yes | 2.00 |
powerword_pain_real | real | Yes | 0.50 |
Powerwordpaincaster | unit | Yes | |
Priestsinnerfire | integer | Yes | |
Pulverize_integer | integer | Yes | |
Queenofsufferingcopy | unitcode | No | |
Questinteger | integer | No | |
Questintegers | integer | Yes | |
Quests | quest | Yes | |
Questsymbols | effect | Yes | |
Ragebetterlearned | boolean | Yes | |
RageWhirlwinddamage | real | Yes | 0.50 |
Randomnumber | integer | No | |
Region1skilltrees | rect | Yes | |
Region2skilltrees | rect | Yes | |
region_list | rect | Yes | |
region_treeofages_max | integer | No | 4 |
Relentlessassault | unit | Yes | |
Relentlessassaultleech | unit | Yes | |
replenishment_firebolt | integer | Yes | |
revenant_of_fire | effect | No | |
revenant_of_fire_point | location | No | |
risen_one_lightning | lightning | No | |
risen_one_point | location | No | |
Roll | integer | No | |
Runedshield | integer | Yes | |
SandStorm | group | No | |
save_cache | gamecache | No | |
save_customs | integer | Yes | |
seven_clouds | boolean | Yes | |
Shadowbladedamage | real | Yes | 2.50 |
Shadowbladedamage_2 | real | Yes | 1.85 |
Shadowbladedebuff | unit | No | |
Shadowbladegroup | group | No | |
Shockwaves | unit | Yes | UnitNull |
Shockwavevariable | integer | Yes | |
Skeletonguardian | unit | Yes | |
Skeletonguardianarea | integer | No | |
Skeletonguardiangroup | group | No | |
Skeletonguardianspecial | effect | Yes | |
slow_improved_boolean | boolean | Yes | |
slow_improved_unit | unit | Yes | |
Slowunit | unit | Yes | |
SpellLevel | integer | No | |
Spellpower | integer | Yes | |
Spellweakness | unit | Yes | |
stoneface_real | real | Yes | |
stoneface_real_temp | real | No | |
stoneface_string | string | No | |
stoneface_unit | unit | No | |
Summonerphasen | integer | No | 0 |
Summonerspawn | integer | No | |
Summonon | boolean | No | |
Tankfocus | unit | No | |
temp_integer | integer | No | |
temp_point | location | No | |
temp_point2 | location | No | |
temp_point_Ougholdy | location | No | |
temp_real | real | No | |
temp_region | rect | No | |
temp_specialeffect | effect | No | |
temp_specialeffect_Ancientofwa | effect | No | |
temp_specialeffect_Ougholdy | effect | No | |
temp_specialeffect_ylyey | effect | No | |
temp_unit | unit | No | |
temp_unit_ancient | unit | No | |
temp_unit_boss | unit | Yes | |
temp_unit_elite | unit | Yes | |
temp_unitgroup | group | No | |
temp_unitgroup_ancient | group | No | |
temp_ylyey_unit | unit | No | |
tempGroup | group | No | |
TempGroup | group | No | |
TempHandle | handle | No | |
TempInteger | integervar | No | |
TempPoint | location | No | |
TempPoint2 | location | No | |
TempPoint3 | location | No | |
TempUnit | unit | No | |
TempUnit2 | unit | No | |
Text_Duration | real | No | |
TextSize_dmg | real | No | |
TextSize_spells | real | No | |
Thefacelessregions | location | Yes | |
Tidalspawn | boolean | No | |
tidalspawneffect | effect | No | |
Tidalspawninteger | integer | No | |
Tidalspawnunit | unit | Yes | |
Timerwarriorbuffinnerfire | timer | Yes | |
touch_of_god_boolean | boolean | Yes | |
Treantling | location | No | |
Treantling2 | integer | No | 1 |
TreeSpirits | group | No | |
Trollwarlordability | location | No | |
Trollwarlordgroup | group | No | |
Undead_frenzy_boolean | boolean | Yes | |
Undead_frenzy_buff_integer | integer | Yes | |
Undeadfrenzydebuff | group | Yes | |
unit_type_respawn | unitcode | Yes | |
unit_type_respawn_integer | integer | No | |
Unitcombatgroup | integer | Yes | |
Unitgroupattack | integer | No | |
Unitgroupmovement | group | No | |
Unitsplayer | unit | Yes | |
Variable | integer | No | |
verydel_boolean_barbarian | boolean | No | |
verydel_boolean_paladin | boolean | No | |
verydel_boolean_sorceress | boolean | No | |
verydel_boolean_spiritwalker | boolean | No | |
verydel_boolean_undeadstalker | boolean | No | |
Verydel_hits | integer | No | |
verydel_integer | integer | No | |
verydel_integer_2 | integer | No | |
verydel_unit | unit | No | |
veteran_point | location | No | |
veteran_point_2 | location | No | |
veteran_region | rect | No | |
veteran_unit_type | unitcode | No | |
Viciousstrikeboolean | boolean | Yes | |
Viciousstrikereal | real | Yes | 3.00 |
Vicioustrikeperiodcaster | unit | Yes | |
Voidnumber | integer | No | |
Voidsinstance4 | group | Yes | |
Voidspawn | location | No | |
Voidssize | integer | No | |
Warriorfrostarmor | boolean | Yes | |
Warriorinnerfire | boolean | Yes | |
WaterWaves | group | No | |
Weathereffectsave | weathereffect | Yes | |
Weathereffecttree | integer | No | |
WhirlPools | group | No | |
Whirlwind | group | No | |
whirlwind_real | real | Yes | |
Whirlwindboolean | boolean | Yes | |
Whirlwinddebuff | unit | No | |
Whirlwindreal | real | Yes | 2.00 |
Ylyey_lightning_effect | lightning | Yes |
//TESH.scrollpos=15
//TESH.alwaysfold=0
// GUI-Friendly Damage Detection -- v1.2.1 -- by Weep
// http:// www.thehelper.net/forums/showthread.php?t=137957
//
// Requires: only this trigger and its variables.
//
// -- What? --
// This snippet provides a leak-free, GUI-friendly implementation of an "any unit takes
// damage" event. It requires no JASS knowledge to use.
//
// It uses the Game - Value Of Real Variable event as its method of activating other
// triggers, and passes the event responses through a few globals.
//
// -- Why? --
// The traditional GUI method of setting up a trigger than runs when any unit is damaged
// leaks trigger events. This snippet is easy to implement and removes the need to do
// you own GUI damage detection setup.
//
// -- How To Implement --
// 0. Before you copy triggers that use GDD into a new map, you need to copy over GDD
// with its GDD Variable Creator trigger, or there will be a problem: the variables
// won't be automatically created correctly.
//
// 1. Be sure "Automatically create unknown variables while pasting trigger data" is
// enabled in the World Editor general preferences.
// 2. Copy this trigger category ("GDD") and paste it into your map.
// (Alternately: create the variables listed in the globals block below, create a
// trigger named "GUI Friendly Damage Detection", and paste in this entire text.)
// 3. Create your damage triggers using Game - Value Of Real Variable as the event,
// select GDD_Event as the variable, and leave the rest of the settings to the default
// "becomes Equal to 0.00".
// The event responses are the following variables:
// GDD_Damage is the amount of damage, replacing Event Response - Damage Taken.
// GDD_DamagedUnit is the damaged unit, replacing Event Response - Triggering Unit.
// Triggering Unit can still be used, if you need to use waits.
// Read the -- Notes -- section below for more info.
// GDD_DamageSource is the damaging unit, replacing Event Response - Damage Source.
//
// -- Notes --
// GDD's event response variables are not wait-safe; you can't use them after a wait in
// a trigger. If you need to use waits, Triggering Unit (a.k.a. GetTriggerUnit()) can
// be used in place of GDD_DamageSource. There is no usable wait-safe equivalent to
// Event Damage or Damage Source; you'll need to save the values yourself.
//
// Don't write any values to the variables used as the event responses, or it will mess
// up any other triggers using this snippet for their triggering. Only use their values.
//
// This uses arrays, so can detect damage for a maximum of 8190 units at a time, and
// cleans up data at a rate of 33.33 per second, by default. This should be enough for
// most maps, but if you want to change the rate, change the value returned in the
// GDD_RecycleRate function at the top of the code, below.
//
// By default, GDD will not register units that have Locust at the moment of their
// entering the game, and will not recognize when they take damage (which can only
// happen if the Locust ability is later removed from the unit.) To allow a unit to have
// Locust yet still cause GDD damage events if Locust is removed, you can either design
// the unit to not have Locust by default and add it via triggers after creation, or
// edit the GDD_Filter function at the top of the code, below.
//
// -- Credits --
// Captain Griffin on wc3c.net for the research and concept of GroupRefresh.
//
// Credit in your map not needed, but please include this README.
//
// -- Version History --
// 1.2.1: Minor code cleaning. Added configuration functions. Updated documentation.
// 1.2.0: Made this snippet work properly with recursive damage.
// 1.1.1: Added a check in order to not index units with the Locust ability (dummy units).
// If you wish to check for damage taken by a unit that is unselectable, do not
// give the unit-type Locust in the object editor; instead, add the Locust ability
// 'Aloc' via a trigger after its creation, then remove it.
// 1.1.0: Added a check in case a unit gets moved out of the map and back.
// 1.0.0: First release.
//===================================================================
// Configurables.
function GDD_RecycleRate takes nothing returns real //The rate at which the system checks units to see if they've been removed from the game
return 0.03
endfunction
function GDD_Filter takes unit u returns boolean //The condition a unit has to pass to have it registered for damage detection
return GetUnitAbilityLevel(u, 'Aloc') == 0 //By default, the system ignores Locust units, because they normally can't take damage anyway
endfunction
//===================================================================
// This is just for reference.
// If you use JassHelper, you could uncomment this section instead of creating the variables in the trigger editor.
// globals
// real udg_GDD_Event = 0.
// real udg_GDD_Damage = 0.
// unit udg_GDD_DamagedUnit
// unit udg_GDD_DamageSource
// trigger array udg_GDD__TriggerArray
// integer array udg_GDD__Integers
// unit array udg_GDD__UnitArray
// group udg_GDD__LeftMapGroup = CreateGroup()
// endglobals
//===================================================================
// System code follows. Don't touch!
function GDD_Event takes nothing returns boolean
local unit damagedcache = udg_GDD_DamagedUnit
local unit damagingcache = udg_GDD_DamageSource
local real damagecache = udg_GDD_Damage
set udg_GDD_DamagedUnit = GetTriggerUnit()
set udg_GDD_DamageSource = GetEventDamageSource()
set udg_GDD_Damage = GetEventDamage()
set udg_GDD_Event = 1.
set udg_GDD_Event = 0.
set udg_GDD_DamagedUnit = damagedcache
set udg_GDD_DamageSource = damagingcache
set udg_GDD_Damage = damagecache
set damagedcache = null
set damagingcache = null
return false
endfunction
function GDD_AddDetection takes nothing returns boolean
// if(udg_GDD__Integers[0] > 8190) then
// call BJDebugMsg("GDD: Too many damage events! Decrease number of units present in the map or increase recycle rate.")
// ***Recycle rate is specified in the GDD_RecycleRate function at the top of the code. Smaller is faster.***
// return
// endif
if(IsUnitInGroup(GetFilterUnit(), udg_GDD__LeftMapGroup)) then
call GroupRemoveUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
elseif(GDD_Filter(GetFilterUnit())) then
set udg_GDD__Integers[0] = udg_GDD__Integers[0]+1
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = GetFilterUnit()
set udg_GDD__TriggerArray[udg_GDD__Integers[0]] = CreateTrigger()
call TriggerRegisterUnitEvent(udg_GDD__TriggerArray[udg_GDD__Integers[0]], udg_GDD__UnitArray[udg_GDD__Integers[0]], EVENT_UNIT_DAMAGED)
call TriggerAddCondition(udg_GDD__TriggerArray[udg_GDD__Integers[0]], Condition(function GDD_Event))
endif
return false
endfunction
function GDD_PreplacedDetection takes nothing returns nothing
local group g = CreateGroup()
local integer i = 0
loop
call GroupEnumUnitsOfPlayer(g, Player(i), Condition(function GDD_AddDetection))
set i = i+1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call DestroyGroup(g)
set g = null
endfunction
function GDD_GroupRefresh takes nothing returns nothing
// Based on GroupRefresh by Captain Griffen on wc3c.net
if (bj_slotControlUsed[5063] == true) then
call GroupClear(udg_GDD__LeftMapGroup)
set bj_slotControlUsed[5063] = false
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetEnumUnit())
endfunction
function GDD_Recycle takes nothing returns nothing
if(udg_GDD__Integers[0] <= 0) then
return
elseif(udg_GDD__Integers[1] <= 0) then
set udg_GDD__Integers[1] = udg_GDD__Integers[0]
endif
if(GetUnitTypeId(udg_GDD__UnitArray[udg_GDD__Integers[1]]) == 0) then
call DestroyTrigger(udg_GDD__TriggerArray[udg_GDD__Integers[1]])
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = null
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = udg_GDD__TriggerArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[1]] = udg_GDD__UnitArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = null
set udg_GDD__Integers[0] = udg_GDD__Integers[0]-1
endif
set udg_GDD__Integers[1] = udg_GDD__Integers[1]-1
endfunction
function GDD_LeaveMap takes nothing returns boolean
local boolean cached = bj_slotControlUsed[5063]
if(udg_GDD__Integers[2] < 64) then
set udg_GDD__Integers[2] = udg_GDD__Integers[2]+1
else
set bj_slotControlUsed[5063] = true
call ForGroup(udg_GDD__LeftMapGroup, function GDD_GroupRefresh)
set udg_GDD__Integers[2] = 0
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
set bj_slotControlUsed[5063] = cached
return false
endfunction
// ===========================================================================
function InitTrig_GUI_Friendly_Damage_Detection takes nothing returns nothing
local region r = CreateRegion()
call RegionAddRect(r, GetWorldBounds())
call TriggerRegisterEnterRegion(CreateTrigger(), r, Condition(function GDD_AddDetection))
call TriggerRegisterLeaveRegion(CreateTrigger(), r, Condition(function GDD_LeaveMap))
call GDD_PreplacedDetection()
call TimerStart(CreateTimer(), GDD_RecycleRate(), true, function GDD_Recycle)
set r = null
endfunction
//TESH.scrollpos=429
//TESH.alwaysfold=0
//------------------------------------------------------------------------------------------------------//
// ZTS - ZWIEBELCHEN'S THREAT SYSTEM v. 2.4 //
//------------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------//
// //
// Requires: vJass Pre-Processor //
// //
// Special thanks to TEC-Ghost, who inspired me on creating this system. //
//------------------------------------------------------------------------------------------------------//
// MANUAL //
//------------------------------------------------------------------------------------------------------//
// 1. How to Install:
//
// - Create a trigger called "ZTS"
// - Convert it to custom Text
// - Replace everything inside with this code
//
//
// 2. How to set it up:
//
// 2.1 Constants
//
// There are a bunch of global constants below this manual, you can edit to your liking.
// I commented everything you need to know about those constants right beside them. If you need additional information,
// please tell me, so I can improve this manual. However, I think most of it should be pretty clear.
//
// 2.2. Gameplay Constants
//
// It is recommended to edit certain Gameplay Constants entries, to use the full potential of
// the system.
// The most important entries are: (with selected "Show Raw-Data")
// CallForHelp --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
// You don't have to do it if your threat-system controlled units are neutral hostile
// CreepCallForHelp --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
// GuardDistance --> Set this to something higher than ReturnRange (see below)
// MaxGuardDistance --> Set this to something higher than ReturnRange (see below)
// GuardReturnTime --> Set this to something very high, so that the standard AI doesn't interfere (i.e. 60 seconds)
//
// 2.3. Damage Detection
//
// Of course, a threat system is pretty useless without a trigger, that adds threat depending on
// the damage dealt by a player unit.
// I recommend using a damage detection script like IDDS:
// (http://www.wc3c.net/showthread.php?t=100618)
// Check up the demo map for a very simple (but leaking) damage detection trigger
// The only function you actually need then is:
// call ModifyThreat(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), true)
// The function does all required checks on its own. There is no need to run something else.
//
// 3. How to use it:
//
// 3.1. Core functions
//
// call ZTS_AddThreatUnit(unit npc) returns nothing:
//
// This function registers the unit as an AI-controlled unit.
// ThreatUnits will automaticly attack the highest-in-threat attacker.
// When adding a ThreatUnit, its current position gets saved and be considered camp-position.
// It will always return to this position if pulled to far or on victory.
// Nearby units will be considered in the same camp group. Camp members will always retreat and attack together.
//
// call ZTS_AddPlayerUnit(unit pu) returns nothing:
//
// Units add by this way will generate threat on ThreatUnits.
// If the unit is not registered as a PlayerUnit, it will not be attacked by ThreatUnits.
//
// call ZTS_RemoveThreatUnit(unit npc) returns nothing:
//
// Removes a ThreatUnit from the system. The unit will no longer be controlled by the threat system.
// Also, the threat list for that unit will be cleared.
// Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
// call ZTS_RemovePlayerUnit(unit pu) returns nothing:
//
// Removes a player unit from the system. The unit will no longer generate threat on ThreatUnits.
// The unit will also be instantly removed from all threat lists.
// If the unit was the last unit in combat with the same hostile camp, all units
// of that camp group will immediately return to their camp positions.
// You can use this, followed by AddPlayerUnit to that unit out of combat and reset all threat.
// Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
// call ZTS_ModifyThreat(unit pu, unit npc, real amount, boolean add) returns nothing:
//
// Adds, sets or substracts threat from npc's threat list caused by pu.
// Set 'add' to true to add or substract amount from the current value.
// Set 'add' to false to set the new threat value to amount.
// To reduce threat, use negative amount values with add == true.
// Remember: If a unit has 0 threat, it is still considered in-combat -
// this also means, that adding "0" to the units threat causes them to attack!
//
// call ZTS_ApplyHealThreat(unit pu, unit ally, real amount, boolean add, boolean divide) returns nothing:
//
// Adds Healing Threat to all units, that have ally on threat-list
// This can be abused to apply global threat to a unit by passing the same unit to p and ally.
// Parameter divide = true means that the amount is split by the number of units attacking the target;
// for example if 3 units are currently attacking the targeted ally, it adds amount/3 threat from pu to all of them.
// Parameter divide = false means that every attacking unit gets 'amount' of threat applied.
// use add = false to set the amount of threat to 'amount', instead of increasing/decreasing it
// negative values are allowed in combination with 'add' to reduce threat.
// You can also use this with add = false and amount = 0 with pu = ally to set total threat generated back to zero for this unit.
//
//
// 3.2. Getter functions
//
// call ZTS_GetCombatState(unit PU) returns boolean:
//
// Returns the combat state of a player unit.
// Returns true, if the unit is registered and in combat.
// Returns false, if the unit is not registered or out of combat.
//
//
// call ZTS_GetThreatUnitPosition(unit NPC, unit PU) returns integer:
//
// Returns the position of unit PU in unit NPC's threat list
// Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
// call ZTS_GetThreatUnitAmount(unit NPC, unit PU) returns real:
//
// Returns the amount of threat unit PU has in unit NPC's threat list
// Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
// call ZTS_GetThreatSlotUnit(unit NPC, integer position) returns unit:
//
// Returns the unit in threat-slot position
// Returns null if the NPC does not feature a threat list, the number is too large
// or in case of invalid input data
//
// call ZTS_GetThreatSlotAmount(unit NPC, integer position) returns real:
//
// Returns the threat amount of the threat-slot position
// Returns "0" if the NPC does not feature a threat list, the number is too large
// or in case of invalid input data
//
// call ZTS_GetAttackers(unit U) returns group:
//
// If used on a ThreatUnit, this returns a group of all units in threat list;
// if used on a PlayerUnit, this returns a group of all units aggroed.
// Returns an empty group, in case of invalid input data or empty lists.
//
//
// 3.3. Advanced User features
//
// call ZTS_IsEvent() returns boolean
//
// When using "A unit is issued an order without target" or "A unit is issued a target order" events,
// this function returns true when the order was issued by the threat system.
// You can use this to setup your own spell-AI for units.
// Let's say you want the unit to cast Summon Water Elemental whenever the cooldown is ready:
// Just use the mentioned events and add:
// Custom script: if not ZTS_IsEvent() then
// Custom script: return
// Custom script: endif
// at the beginning of you trigger's actions and you're done.
// You can now issue the order to the triggering unit:
// Unit - Order (Triggering unit) to Human Archmage - Summon Water Elemental
// In combination with some of the Getter functions, you can trigger nice spell AI like this.
// NOTE: ZTS_IsEvent will only return true once(!) for every fired event, so if you need it again inside that trigger,
// make sure to save it to a variable.
//
//------------------------------------------------------------------------------------------------------//
library ZTS initializer InitThreatSystem
globals
private constant real UpdateIntervall = 0.5 //The intervall for issueing orders and performing AttackRange check. recommended value: 0.5
private constant real HelpRange = 375 //The range between units considered being in the same camp. If a unit of the same camp gets attacked, all others will help.
//Set CallForHelp to something lower in Gameplay Constants.
private constant real OrderReturnRange = 3000 //The range the unit's target can be away from the original camping position, before being ordered to return.
private constant real ReturnRange = 1800 //The range the unit can move away from the original camping position, before being ordered to return.
private constant real TimeToPort = 1 //This timer expires once a unit tries to return to its camping position.
//If it reaches 0 before reaching the camp position, the unit will be teleported immediately.
private constant boolean HealUnitsOnReturn = true //If this is true, returning units will be healed to 100% health.
// Do not edit below here!
//------------------------------------------------------------------------------------------------------//
private boolexpr BOOLEXPR = null
private constant timer Updater = CreateTimer()
private constant group NPCgroup = CreateGroup()
private constant hashtable NPClist = InitHashtable()
private constant hashtable PUlist = InitHashtable()
//temporary variables for enumerations and forgroups
private unit TSub = null
private unit TMod = null
private constant group TGroupSub = CreateGroup()
private unit THealer = null
private real THealthreat = 0
private boolean TBool = false
private constant group TGroupUpd = CreateGroup()
private group TGroupGet = null
private boolean EventBool = false
endglobals
public function IsEvent takes nothing returns boolean
if EventBool then
set EventBool = false
return true
endif
return false
endfunction
private function Pos2Key takes integer position returns integer //converts threat list position into hashtable childkey
return 8+(position*2)
endfunction
private function Key2Pos takes integer key returns integer //converts hashtable childkey into threat list position
return (key-8)/2
endfunction
public function GetCombatState takes unit u returns boolean
if GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD) then //unit dead or null
return false
elseif HaveSavedInteger(NPClist, GetHandleId(u), 0) then //unit is npc
return LoadInteger(NPClist, GetHandleId(u), 0) > 0
elseif HaveSavedHandle(PUlist, GetHandleId(u), 0) then //unit is player unit
return LoadInteger(PUlist, GetHandleId(u), 1) > 0
endif
return false
endfunction
public function GetThreatUnitPosition takes unit npc, unit pu returns integer
if GetUnitTypeId(npc) == 0 or IsUnitType(npc, UNIT_TYPE_DEAD) or GetUnitTypeId(pu) == 0 or IsUnitType(pu, UNIT_TYPE_DEAD) then //units dead or null
return 0
elseif not (HaveSavedInteger(NPClist, GetHandleId(npc), 0) and HaveSavedHandle(PUlist, GetHandleId(pu), 0)) then //units not added
return 0
elseif HaveSavedInteger(PUlist, GetHandleId(pu), GetHandleId(npc)) then
return LoadInteger(PUlist, GetHandleId(pu), GetHandleId(npc))
endif
return 0
endfunction
public function GetThreatUnitAmount takes unit npc, unit pu returns real
if GetUnitTypeId(npc) == 0 or IsUnitType(npc, UNIT_TYPE_DEAD) or GetUnitTypeId(pu) == 0 or IsUnitType(pu, UNIT_TYPE_DEAD) then //units dead or null
return 0.
elseif not (HaveSavedInteger(NPClist, GetHandleId(npc), 0) and HaveSavedHandle(PUlist, GetHandleId(pu), 0)) then //units not added
return 0.
elseif HaveSavedInteger(PUlist, GetHandleId(pu), GetHandleId(npc)) then
return LoadReal(NPClist, GetHandleId(npc), Pos2Key(LoadInteger(PUlist, GetHandleId(pu), GetHandleId(npc)))+1)
endif
return 0.
endfunction
public function GetThreatSlotUnit takes unit npc, integer position returns unit
if GetUnitTypeId(npc) == 0 or IsUnitType(npc, UNIT_TYPE_DEAD) or position <= 0 then //unit dead or null or invalid slot
return null
elseif not HaveSavedInteger(NPClist, GetHandleId(npc), 0) then //unit not added
return null
elseif HaveSavedHandle(NPClist, GetHandleId(npc), Pos2Key(position)) then
return LoadUnitHandle(NPClist, GetHandleId(npc), Pos2Key(position))
endif
return null
endfunction
public function GetThreatSlotAmount takes unit npc, integer position returns real
if GetUnitTypeId(npc) == 0 or IsUnitType(npc, UNIT_TYPE_DEAD) or position <= 0 then //unit dead or null or invalid slot
return 0.
elseif not HaveSavedInteger(NPClist, GetHandleId(npc), 0) then //unit not added
return 0.
elseif HaveSavedReal(NPClist, GetHandleId(npc), Pos2Key(position)+1) then
return LoadReal(NPClist, GetHandleId(npc), Pos2Key(position)+1)
endif
return 0.
endfunction
private function GetAttackersSub takes nothing returns nothing
call GroupAddUnit(TGroupGet, GetEnumUnit())
endfunction
public function GetAttackers takes unit u returns group
local group g = CreateGroup()
local integer key = 10
local integer max
if GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD) then //unit dead or null
return g
endif
if HaveSavedInteger(NPClist, GetHandleId(u), 0) then //unit is npc
set max = Pos2Key(LoadInteger(NPClist, GetHandleId(u), 5))
loop
exitwhen key > max
call GroupAddUnit(g, LoadUnitHandle(NPClist, GetHandleId(u), key))
set key = key+2
endloop
elseif HaveSavedHandle(PUlist, GetHandleId(u), 0) then //unit is player unit
set TGroupGet = g
call ForGroup(LoadGroupHandle(PUlist, GetHandleId(u), 0), function GetAttackersSub)
set g = TGroupGet
set TGroupGet = null
endif
return g
endfunction
private function Swap takes integer npcID, integer key1, integer key2 returns nothing
local unit u = LoadUnitHandle(NPClist, npcID, key1)
local real r = LoadReal(NPClist, npcID, key1+1)
call SaveUnitHandle(NPClist, npcID, key1, LoadUnitHandle(NPClist, npcID, key2))
call SaveReal(NPClist, npcID, key1+1, LoadReal(NPClist, npcID, key2+1))
call SaveInteger(PUlist, GetHandleId(LoadUnitHandle(NPClist, npcID, key1)), npcID, Key2Pos(key1)) //update position list
call SaveUnitHandle(NPClist, npcID, key2, u)
call SaveReal(NPClist, npcID, key2+1, r)
call SaveInteger(PUlist, GetHandleId(u), npcID, Key2Pos(key2)) //update position list
set u = null
endfunction
private function CampThreat takes nothing returns nothing
local integer npcID = GetHandleId(GetEnumUnit())
local integer puID = GetHandleId(TMod)
local integer key
local integer listlength
if GetEnumUnit() == TSub then
return
elseif HaveSavedInteger(PUlist, puID, npcID) then //original pu unit already listed in EnumUnit's threat list
return
elseif LoadInteger(NPClist, npcID, 0) > 1 or IsUnitType(GetEnumUnit(), UNIT_TYPE_DEAD) then //do not add threat to dead or units that are status: returning
return
endif
set listlength = LoadInteger(NPClist, npcID, 5)+1
call SaveInteger(NPClist, npcID, 5, listlength) //add to list length of EnumUnit
set key = Pos2Key(listlength)
call SaveUnitHandle(NPClist, npcID, key, TMod) //add original pu unit to end of EnumUnit's threat list
call SaveReal(NPClist, npcID, key+1, 0)
call SaveInteger(PUlist, puID, npcID, listlength) //add EnumUnit to slot list
call GroupAddUnit(LoadGroupHandle(PUlist, puID, 0), GetEnumUnit()) //add EnumUnit to slot list group
call SaveInteger(PUlist, puID, 1, LoadInteger(PUlist, puID, 1)+1) //increase group size count
if LoadInteger(NPClist, npcID, 0) == 0 then
call SaveInteger(NPClist, npcID, 0, 1) //set unit status: combat
call GroupAddUnit(NPCgroup, GetEnumUnit()) //add the unit to incombat group
endif
endfunction
public function ModifyThreat takes unit pu, unit npc, real amount, boolean add returns nothing
local integer npcID = GetHandleId(npc)
local integer puID = GetHandleId(pu)
local integer key
local integer listlength
local integer i = 0
local real newamount
local real oldamount = 0
local boolean b = false
if not (HaveSavedInteger(NPClist, npcID, 0) and HaveSavedHandle(PUlist, puID, 0)) then //units not added
return
elseif IsUnitType(pu, UNIT_TYPE_DEAD) or IsUnitType(npc, UNIT_TYPE_DEAD) then //units dead
return
elseif GetUnitTypeId(pu) == 0 or GetUnitTypeId(npc) == 0 then //null units
return
elseif LoadInteger(NPClist, npcID, 0) > 1 then //do not add threat to units that are status: returning
return
endif
if not HaveSavedInteger(PUlist, puID, npcID) then //pu not listed in npc's threat list
set listlength = LoadInteger(NPClist, npcID, 5)+1
call SaveInteger(NPClist, npcID, 5, listlength) //add to list length of npc
set key = Pos2Key(listlength)
call SaveUnitHandle(NPClist, npcID, key, pu) //add pu to end of npc's threat list
call SaveInteger(PUlist, puID, npcID, listlength) //add npc to slot list
call GroupAddUnit(LoadGroupHandle(PUlist, puID, 0), npc) //add npc to slot list group
call SaveInteger(PUlist, puID, 1, LoadInteger(PUlist, puID, 1)+1) //increase group size count
if LoadInteger(NPClist, npcID, 0) == 0 then
call SaveInteger(NPClist, npcID, 0, 1) //set unit status: combat
call GroupAddUnit(NPCgroup, npc) //add the unit to incombat group
endif
set b = true
else
set key = Pos2Key(LoadInteger(PUlist, puID, npcID))
set oldamount = LoadReal(NPClist, npcID, key+1)
endif
if add then
set newamount = oldamount+amount
else
set newamount = amount
endif
if newamount < 0 then
set newamount = 0
endif
call SaveReal(NPClist, npcID, key+1, newamount)
if newamount > oldamount then //check lower keys
loop
if HaveSavedReal(NPClist, npcID, key-1-i) then
if LoadReal(NPClist, npcID, key-1-i) < newamount then //lower key amount is smaller
call Swap(npcID, key-2-i, key-i)
else
exitwhen true
endif
set i = i + 2
else
exitwhen true
endif
endloop
elseif newamount < oldamount then //check higher keys
loop
if HaveSavedReal(NPClist, npcID, key+3+i) then
if LoadReal(NPClist, npcID, key+3+i) > newamount then //upper key amount is larger
call Swap(npcID, key+2+i, key+i)
else
exitwhen true
endif
set i = i + 2
else
exitwhen true
endif
endloop
endif
if b then //set all units of the same camp to status: combat and apply 0 threat from pu to them
set TSub = npc
set TMod = pu
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampThreat)
endif
endfunction
public function AddPlayerUnit takes unit u returns nothing
local integer ID = GetHandleId(u)
if HaveSavedInteger(NPClist, ID, 0) or HaveSavedHandle(PUlist, ID, 0) then //unit already added
return
elseif GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD) then //unit dead or null
return
endif
call SaveGroupHandle(PUlist, ID, 0, CreateGroup()) //slot list group
call SaveInteger(PUlist, ID, 1, 0) //list group count
endfunction
private function AcquireTarget takes nothing returns boolean
local unit npc = GetTriggerUnit()
local unit pu
if GetEventTargetUnit() != null then
set pu = GetEventTargetUnit()
else
set pu = GetOrderTargetUnit()
endif
if IsUnitEnemy(pu, GetOwningPlayer(npc)) then
if LoadInteger(NPClist, GetHandleId(npc), 0) == 0 then //pull out of combat units only
call ModifyThreat(pu, npc, 0, true)
endif
endif
set pu = null
set npc = null
return false
endfunction
private function FilterUnitsWithCampGroup takes nothing returns boolean
return HaveSavedHandle(NPClist, GetHandleId(GetFilterUnit()), 4) and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false and LoadInteger(NPClist, GetHandleId(GetFilterUnit()), 0) <= 1
endfunction
public function AddThreatUnit takes unit u returns nothing
local integer ID = GetHandleId(u)
local group g = null
local trigger t = null
if HaveSavedInteger(NPClist, ID, 0) or HaveSavedHandle(PUlist, ID, 0) then //unit already added
return
elseif GetUnitTypeId(u) == 0 or IsUnitType(u, UNIT_TYPE_DEAD) then //unit dead or null
return
endif
call SaveInteger(NPClist, ID, 0, 0) //status
call SaveReal(NPClist, ID, 1, GetUnitX(u)) //return X
call SaveReal(NPClist, ID, 2, GetUnitY(u)) //return Y
call SaveReal(NPClist, ID, 3, TimeToPort) //return countdown
call SaveInteger(NPClist, ID, 5, 0) //list length
set t = CreateTrigger()
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_ACQUIRED_TARGET)
call TriggerAddCondition(t, Condition(function AcquireTarget))
call SaveTriggerHandle(NPClist, ID, 6, t) //acquire target event trigger
call GroupEnumUnitsInRange(TGroupSub, GetUnitX(u), GetUnitY(u), HelpRange, Condition(function FilterUnitsWithCampGroup))
if FirstOfGroup(TGroupSub) != null then
set g = LoadGroupHandle(NPClist, GetHandleId(FirstOfGroup(TGroupSub)), 4)
else //no unit in range has a camp group assigned, so create a new one
set g = CreateGroup()
endif
call GroupAddUnit(g, u)
call SaveGroupHandle(NPClist, ID, 4, g) //camp group
set t = null
set g = null
endfunction
public function RemoveThreatUnit takes unit u returns nothing
local integer ID = GetHandleId(u)
local integer OtherID
local group g = null
local integer key = 10
if not HaveSavedInteger(NPClist, ID, 0) then //unit not added
return
elseif GetUnitTypeId(u) == 0 then
return
endif
if LoadInteger(NPClist, ID, 0) > 1 then //unit status is: returning
call IssueImmediateOrder(u, "stop")
call SetUnitInvulnerable(u, false)
if IsUnitPaused(u) then
call PauseUnit(u, false)
endif
endif
loop //remove the entry in the player unit's position list and list group and decrease list group count
if HaveSavedHandle(NPClist, ID, key) then
set OtherID = GetHandleId(LoadUnitHandle(NPClist, ID, key))
call RemoveSavedInteger(PUlist, OtherID, ID)
call GroupRemoveUnit(LoadGroupHandle(PUlist, OtherID, 0), u)
call SaveInteger(PUlist, OtherID, 1, LoadInteger(PUlist, OtherID, 1)-1)
set key = key+2
else //last entry reached
exitwhen true
endif
endloop
set g = LoadGroupHandle(NPClist, ID, 4)
call GroupRemoveUnit(g, u)
if FirstOfGroup(g) == null then //camp group is empty
call DestroyGroup(g)
endif
call DestroyTrigger(LoadTriggerHandle(NPClist, ID, 6))
call FlushChildHashtable(NPClist, ID)
if IsUnitInGroup(u, NPCgroup) then
call GroupRemoveUnit(NPCgroup, u) //remove unit from incombat group
endif
set g = null
endfunction
private function RemovePlayerUnitEntries takes nothing returns nothing
local integer ID = GetHandleId(TSub)
local integer OtherID = GetHandleId(GetEnumUnit())
local integer key = Pos2Key(LoadInteger(PUlist, ID, OtherID))
loop //remove the entry in u's threat list and fill the gap
if HaveSavedHandle(NPClist, OtherID, key+2) then //move up next entry
call SaveUnitHandle(NPClist, OtherID, key, LoadUnitHandle(NPClist, OtherID, key+2))
call SaveReal(NPClist, OtherID, key+1, LoadReal(NPClist, OtherID, key+3))
call SaveInteger(PUlist, GetHandleId(LoadUnitHandle(NPClist, OtherID, key)), OtherID, Key2Pos(key)) //update position in player unit list
set key = key+2
else //last entry reached
call RemoveSavedHandle(NPClist, OtherID, key)
call RemoveSavedReal(NPClist, OtherID, key+1)
call SaveInteger(NPClist, OtherID, 5, Key2Pos(key-2)) //decrease list length
exitwhen true
endif
endloop
endfunction
public function RemovePlayerUnit takes unit u returns nothing
local integer ID = GetHandleId(u)
if not HaveSavedHandle(PUlist, ID, 0) then //unit not added
return
elseif GetUnitTypeId(u) == 0 then
return
endif
set TSub = u
call ForGroup(LoadGroupHandle(PUlist, ID, 0), function RemovePlayerUnitEntries)
call DestroyGroup(LoadGroupHandle(PUlist, ID, 0))
call FlushChildHashtable(PUlist, ID)
endfunction
private function HealThreatSub takes nothing returns nothing
call ModifyThreat(THealer, GetEnumUnit(), THealthreat, TBool)
endfunction
public function ApplyHealThreat takes unit pu, unit ally, real amount, boolean add, boolean divide returns nothing
local integer puID = GetHandleId(pu)
local integer allyID = GetHandleId(ally)
if not (HaveSavedHandle(PUlist, puID, 0) and HaveSavedHandle(PUlist, allyID, 0)) then //units not added
return
elseif IsUnitType(pu, UNIT_TYPE_DEAD) or IsUnitType(ally, UNIT_TYPE_DEAD) then //units dead
return
elseif GetUnitTypeId(pu) == 0 or GetUnitTypeId(ally) == 0 then //null units
return
endif
if divide and LoadInteger(PUlist, allyID, 1) > 1 then
set THealthreat = amount/LoadInteger(PUlist, allyID, 1)
else
set THealthreat = amount
endif
set TBool = add
set THealer = pu
call ForGroup(LoadGroupHandle(PUlist, allyID, 0), function HealThreatSub)
endfunction
private function CampCommand takes nothing returns nothing
local unit u = GetEnumUnit()
local integer ID = GetHandleId(u)
local integer OtherID
local integer status = LoadInteger(NPClist, ID, 0)
local integer key = 10
if status == 1 then
call SaveInteger(NPClist, GetHandleId(u), 0, 2) //set status: returning
loop //remove the entry in the player unit's position list and list group and decrease list group count
if HaveSavedHandle(NPClist, ID, key) then
set OtherID = GetHandleId(LoadUnitHandle(NPClist, ID, key))
call RemoveSavedInteger(PUlist, OtherID, ID)
call GroupRemoveUnit(LoadGroupHandle(PUlist, OtherID, 0), u)
call SaveInteger(PUlist, OtherID, 1, LoadInteger(PUlist, OtherID, 1)-1)
call RemoveSavedHandle(NPClist, ID, key)
call RemoveSavedReal(NPClist, ID, key+1)
set key = key+2
else //last entry reached
exitwhen true
endif
endloop
call SaveInteger(NPClist, ID, 5, 0) //also set list length to zero
call IssueImmediateOrder(u, "stop") //cancels even spellcast with casting time
call IssuePointOrder(u, "move", LoadReal(NPClist, ID, 1), LoadReal(NPClist, ID, 2))
call SaveReal(NPClist, ID, 3, TimeToPort)
call SetUnitInvulnerable(u, true)
if HealUnitsOnReturn then
call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_MAX_LIFE))
call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))
endif
elseif status == 3 then
call SaveInteger(NPClist, GetHandleId(u), 0, 0) //set status: out of combat
call SetUnitInvulnerable(u, false)
call PauseUnit(u, false)
if HealUnitsOnReturn then
call SetUnitState(u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_MAX_LIFE))
call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA))
endif
call GroupRemoveUnit(NPCgroup, u) //remove from combat group
endif
set u = null
endfunction
private function CampStatus takes nothing returns nothing
if LoadInteger(NPClist, GetHandleId(GetEnumUnit()), 0) != 3 then
set TBool = false
endif
endfunction
private function IssueOrder takes nothing returns nothing
local unit npc = GetEnumUnit()
local integer npcID = GetHandleId(npc)
local integer status = LoadInteger(NPClist, npcID, 0)
local integer i = 0
local boolean b = true
local unit target = null
if status == 1 then //unit in combat
if IsUnitInRangeXY(npc, LoadReal(NPClist, npcID, 1), LoadReal(NPClist, npcID, 2), ReturnRange) and HaveSavedHandle(NPClist, npcID, 10) then
set target = LoadUnitHandle(NPClist, npcID, 10)
if IsUnitInRangeXY(target, LoadReal(NPClist, npcID, 1), LoadReal(NPClist, npcID, 2), OrderReturnRange) then
if GetUnitCurrentOrder(npc) == 851983 or GetUnitCurrentOrder(npc) == 0 or GetUnitCurrentOrder(npc) == 851971 then //attack order or no order or smart order
set EventBool = true
call IssueTargetOrder(npc, "smart", target)
set EventBool = false
endif
else //target of unit to far away from camp position
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampCommand) //set camp returning
endif
else //unit left return range or killed all player units
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampCommand) //set camp returning
endif
elseif status == 2 then //unit is returning
if LoadReal(NPClist, npcID, 3) > 0 then
if not IsUnitInRangeXY(npc, LoadReal(NPClist, npcID, 1), LoadReal(NPClist, npcID, 2), 35) then
call IssuePointOrder(npc, "move", LoadReal(NPClist, npcID, 1), LoadReal(NPClist, npcID, 2))
call SaveReal(NPClist, npcID, 3, LoadReal(NPClist, npcID, 3) - UpdateIntervall)
call SetUnitInvulnerable(npc, true)
else //unit within close range to camp position
if GetUnitCurrentOrder(npc) == 851986 then //move order
call SaveReal(NPClist, npcID, 3, LoadReal(NPClist, npcID, 3) - UpdateIntervall)
call SetUnitInvulnerable(npc, true)
else //Something blocks the exact spot or the unit has arrived
call SaveInteger(NPClist, npcID, 0, 3) //set status: returned
set TBool = true
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampStatus)
if TBool then //all units in camp have status: returned to camp position
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampCommand) //set camp ooc
else
call PauseUnit(npc, true) //make sure it doesn't move or attack when invulnerable
endif
endif
endif
else //counter expired - perform instant teleport
call SetUnitPosition(npc, LoadReal(NPClist, npcID, 1), LoadReal(NPClist, npcID, 2))
call SaveInteger(NPClist, npcID, 0, 3) //set status: returned
set TBool = true
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampStatus)
if TBool then //all units in camp have status: returned to camp position
call ForGroup(LoadGroupHandle(NPClist, npcID, 4), function CampCommand) //set camp ooc
else
call PauseUnit(npc, true) //make sure it doesn't move or attack when invulnerable
endif
endif
endif
set npc = null
set target = null
endfunction
private function Update takes nothing returns nothing
call ForGroup(NPCgroup, function IssueOrder) //issues orders to all units in combat
endfunction
private function rettrue takes nothing returns boolean
return true
endfunction
private function RemovedUnitFound takes unit u returns nothing
if HaveSavedInteger(NPClist, GetHandleId(u), 0) then
call RemoveThreatUnit(u)
endif
if HaveSavedHandle(PUlist, GetHandleId(u), 0) then
call RemovePlayerUnit(u)
endif
endfunction
hook RemoveUnit RemovedUnitFound
private function OnDeath takes nothing returns nothing
if HaveSavedInteger(NPClist, GetHandleId(GetTriggerUnit()), 0) then
call RemoveThreatUnit(GetTriggerUnit())
endif
if HaveSavedHandle(PUlist, GetHandleId(GetTriggerUnit()), 0) then
call RemovePlayerUnit(GetTriggerUnit())
endif
endfunction
private function InitThreatSystem takes nothing returns nothing
local trigger t = CreateTrigger()
local integer index = 0
set BOOLEXPR=Condition(function rettrue) //prevent booleanexpressions from leaking
call TimerStart(Updater, UpdateIntervall, true, function Update)
loop
call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_DEATH, BOOLEXPR)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddAction(t, function OnDeath)
set t = null
endfunction
endlibrary
//TESH.scrollpos=39
//TESH.alwaysfold=0
globals
leaderboard udg_HandleBoard
group DebugGroup = CreateGroup()
endglobals
function HandleCounter_L2I takes location P returns integer
return GetHandleId(P)
endfunction
function HandleCounter_Update takes nothing returns nothing
local unit U
local integer i = 0
local integer j = 1
local integer id
local location array P
local real result=0
loop
exitwhen i >= 50
set i = i + 1
set P[i] = Location(0,0)
set id = HandleCounter_L2I(P[i])
set result = result + (id-0x100000)
endloop
set result = result/i-i/2
loop
call RemoveLocation(P[i])
set P[i] = null
exitwhen i <= 1
set i = i - 1
endloop
call GroupEnumUnitsSelected(DebugGroup, Player(0), null)
set U = FirstOfGroup(DebugGroup)
call LeaderboardSetItemValue(udg_HandleBoard, 0, R2I(result))
call LeaderboardSetItemLabel(udg_HandleBoard, 1, "Combat status")
if ZTS_GetCombatState(U) then
call LeaderboardSetItemValue(udg_HandleBoard, 1, 1)
else
call LeaderboardSetItemValue(udg_HandleBoard, 1, 0)
endif
if GetOwningPlayer(U) == Player(PLAYER_NEUTRAL_AGGRESSIVE) then
loop
exitwhen j > 6
if ZTS_GetThreatSlotUnit(U, j) != null then
call LeaderboardSetItemLabel(udg_HandleBoard, 1+j, "Slot "+I2S(j)+" - "+GetPlayerName(GetOwningPlayer(ZTS_GetThreatSlotUnit(U, j)))+":")
call LeaderboardSetItemValue(udg_HandleBoard, 1+j, R2I(ZTS_GetThreatSlotAmount(U, j)))
else
call LeaderboardSetItemLabel(udg_HandleBoard, 1+j, "Slot "+I2S(j)+" - "+"<empty>"+":")
call LeaderboardSetItemValue(udg_HandleBoard, 1+j, 0)
endif
set j = j + 1
endloop
endif
set U = null
endfunction
function HandleCounter_Actions takes nothing returns nothing
set udg_HandleBoard = CreateLeaderboard()
call LeaderboardSetLabel(udg_HandleBoard, "threat-table for selected:")
call PlayerSetLeaderboard(GetLocalPlayer(),udg_HandleBoard)
call LeaderboardDisplay(udg_HandleBoard,true)
call LeaderboardAddItem(udg_HandleBoard,"(Debug) Handles",0,Player(0))
call LeaderboardAddItem(udg_HandleBoard, "Combat Status", 0, Player(1))
call LeaderboardAddItem(udg_HandleBoard, "Slot 1", 0, Player(2))
call LeaderboardAddItem(udg_HandleBoard, "Slot 2", 0, Player(3))
call LeaderboardAddItem(udg_HandleBoard, "Slot 3", 0, Player(4))
call LeaderboardAddItem(udg_HandleBoard, "Slot 4", 0, Player(5))
call LeaderboardAddItem(udg_HandleBoard, "Slot 5", 0, Player(6))
call LeaderboardAddItem(udg_HandleBoard, "Slot 6", 0, Player(7))
call LeaderboardSetSizeByItemCount(udg_HandleBoard,7)
call HandleCounter_Update()
call TimerStart(GetExpiredTimer(),0.05,true,function HandleCounter_Update)
set udg_leaderboard = udg_HandleBoard
endfunction
//===========================================================================
function InitTrig_Debug_Board takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function HandleCounter_Actions)
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Threat_durch_schaden_Actions takes nothing returns nothing
call ZTS_ModifyThreat( GetTriggerUnit(), GetEventDamageSource(), R2I(GetEventDamage ()), true)
endfunction
//===========================================================================
function InitTrig_Threat_durch_schaden takes nothing returns nothing
set gg_trg_Threat_durch_schaden = CreateTrigger( )
call TriggerAddAction( gg_trg_Threat_durch_schaden, function Trig_Threat_durch_schaden_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_regeneration_Actions takes nothing returns nothing
local integer index
set index = 0
loop
if ( ZTS_GetCombatState(udg_hero[index]) == false ) then
call SetUnitLifePercentBJ( udg_hero[index], GetUnitLifePercent(udg_hero[index]) + 8 )
call SetUnitManaPercentBJ( udg_hero[index], GetUnitManaPercent(udg_hero[index]) + 8 )
else
endif
set index = index + 1
exitwhen index == 7
endloop
endfunction
//===========================================================================
function InitTrig_regeneration takes nothing returns nothing
set gg_trg_regeneration = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_regeneration, 2 )
call TriggerAddAction( gg_trg_regeneration, function Trig_regeneration_Actions )
endfunction
//TESH.scrollpos=16
//TESH.alwaysfold=0
function Trig_dps_time_Actions takes nothing returns nothing
if ( ZTS_GetCombatState(udg_hero[1]) == true ) then
set udg_damage_meter_time[1] = ( udg_damage_meter_time[1] + 0.50 )
else
endif
if ( ZTS_GetCombatState(udg_hero[2]) == true ) then
set udg_damage_meter_time[2] = ( udg_damage_meter_time[2] + 0.50 )
else
endif
if ( ZTS_GetCombatState(udg_hero[3]) == true ) then
set udg_damage_meter_time[3] = ( udg_damage_meter_time[3] + 0.50 )
else
endif
if ( ZTS_GetCombatState(udg_hero[4]) == true ) then
set udg_damage_meter_time[4] = ( udg_damage_meter_time[4] + 0.50 )
else
endif
if ( ZTS_GetCombatState(udg_hero[5]) == true ) then
set udg_damage_meter_time[5] = ( udg_damage_meter_time[5] + 0.50 )
else
endif
if ( ZTS_GetCombatState(udg_hero[6]) == true ) then
set udg_damage_meter_time[6] = ( udg_damage_meter_time[6] + 0.50 )
else
endif
endfunction
//===========================================================================
function InitTrig_dps_time takes nothing returns nothing
set gg_trg_dps_time = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_dps_time, 0.50 )
call TriggerAddAction( gg_trg_dps_time, function Trig_dps_time_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_ShowHIde_Actions takes nothing returns nothing
call LeaderboardDisplay(udg_leaderboard, false)
endfunction
//===========================================================================
function InitTrig_ShowHIde takes nothing returns nothing
set gg_trg_ShowHIde = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_ShowHIde, Player(0), "hide", true )
call TriggerAddAction( gg_trg_ShowHIde, function Trig_ShowHIde_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_ShowHIde_2_Actions takes nothing returns nothing
call LeaderboardDisplay(udg_leaderboard, true)
endfunction
//===========================================================================
function InitTrig_ShowHIde_2 takes nothing returns nothing
set gg_trg_ShowHIde_2 = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_ShowHIde_2, Player(0), "show", true )
call TriggerAddAction( gg_trg_ShowHIde_2, function Trig_ShowHIde_2_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function Trig_Hide_from_the_beginning_Actions takes nothing returns nothing
call LeaderboardDisplay(udg_leaderboard, false)
endfunction
//===========================================================================
function InitTrig_Hide_from_the_beginning takes nothing returns nothing
set gg_trg_Hide_from_the_beginning = CreateTrigger( )
call TriggerRegisterTimerEventSingle( gg_trg_Hide_from_the_beginning, 1 )
call TriggerAddAction( gg_trg_Hide_from_the_beginning, function Trig_Hide_from_the_beginning_Actions )
endfunction