BINDING_HEADER_AAL_112_BINDINGS = "AAL Tweaks / WoW 1.12";

AAL_INV_MAINHAND = 16
AAL_INV_OFFHAND  = 17

if print == nil then
function print(...)
  local str
  for i = 1,table.getn(arg) do
    if str then str = str.." "..tostring(arg[i])
    else str = tostring(arg[i])
    end
  end
  DEFAULT_CHAT_FRAME:AddMessage(str)
end end


-- Восстановление цели после вызова TargetUnit(...)

function AAL_RestoreTarget()
  -- `When the player changes his target there is a small delay before the global variable 'playertarget' is updated. This can be exploited and used for restoring your old target.`
  if UnitExists("playertarget") then TargetUnit("playertarget") else ClearTarget() end
end


-- Перехват сообщений об ошибках. Несколько подряд вызовов AAL_TrapErrors()
-- или AAL_UntrapErrors() эквивалентны одному вызову

function AAL_TrapErrors()
  if aal_Errors_OrigHandler == nil then
     aal_Errors_OrigHandler = UIErrorsFrame_OnEvent
  end
  aal_ErrorMsg = nil
  UIErrorsFrame_OnEvent = function(event, message)
    --print("Event:", event, message)
	if event == "UI_ERROR_MESSAGE" then aal_ErrorMsg = message
    else aal_Errors_OrigHandler(event, message)
    end
  end
end

function AAL_ClearErrorMsg()
  aal_ErrorMsg = nil
end

function AAL_ShowErrorMsg()
  if aal_ErrorMsg == nil then return end
  UIErrorsFrame:AddMessage(aal_ErrorMsg,1,0,0)
  aal_ErrorMsg = nil
end

function AAL_UntrapErrors()
  if aal_Errors_OrigHandler ~= nil then
     UIErrorsFrame_OnEvent = aal_Errors_OrigHandler
     aal_Errors_OrigHandler = nil
  end
  aal_ErrorMsg = nil
end



-- Scan Rare NPCs

local npcList = {
-- Instances
"Panzor the Invincible",
"Pyromancer Loregrain",
"Verek",
"Warder Stilgiss",
"Lord Hel'nurath",
"Tsu'zee",
"Dark Iron Ambassador",
"Bannok Grimaxe",
"Burning Felguard",
"Crystal Fang",
"Ghok Bashguud",
"Spirestone Battle Lord",
"Spirestone Butcher",
"Spirestone Lord Magus",
"Cursed Centaur",
"Meshlok the Harvester",
"Ragglesnout",
"Blind Hunter",
"Earthcaller Halmgar",
"Azshir the Sleepless",
"Fallen Champion",
"Ironspine",
"Deathsworn Captain",
"Bruegal Ironknuckle",
"Hearthsinger Forresten",
"Skul",
"Stonespine",
"Veyzhak the Cannibal",
"Zekkis",
"Brainwashed Noble",
"Marisa du'Paige",
"Miner Johnson",
"Digmaster Shovelphlange",
"Goraluk Anvilcrack",
"Jed Runewatcher",
"Boahn",
"Deviate Faerie Dragon",
"Trigore the Lasher",
"Dustwraith",
"Sandarr Dunereaver",
"Zerillis",

-- Kalimdor
"Akkrilus",
"Apothecary Falthis",
"Branch Snapper",
"Darkslayer Mordenthal",
"Eck'alom",
"Lady Vespia",
"Mist Howler",
"Mugglefin",
"Oakpaw",
"Prince Raze",
"Rorgish Jowl",
"Terrowulf Packlord",
"Ursol'lok",
"Antilos",
"Gatekeeper Rageroar",
"General Fangferror",
"Lady Sesspira",
"Magister Hawkhelm",
"Master Feardred",
"Monnos the Elder",
"Scalebeard",
"The Evalcharr",
"Varo'then's Ghost",
"Carnivous the Breaker",
"Firecaller Radison",
"Flagglemurk the Cruel",
"Lady Moongazer",
"Lady Vespira",
"Licillin",
"Lord Sinslayer",
"Shadowclaw",
"Strider Clutchmother",
"Alshirr Banebreath",
"Death Howl",
"Dessecus",
"Immolatus",
"Mongress",
"Olm the Wise",
"Ragepaw",
"The Ongar",
"Blackmoss the Fetid",
"Duskstalker",
"Fury Shelda",
"Grimmaw",
"Threggil",
"Uruson",
"Azurous",
"General Colbatann",
"Grizzle Snowpaw",
"Kashoch the Reaver",
"Lady Hederine",
"Mezzir the Howler",
"Rak'shiri",
"Captain Flat Tusk",
"Death Flayer",
"Felweaver Scornn",
"Geolord Mottle",
"Warlord Kolkanis",
"Watch Commander Zalaphil",
"Brimgore",
"Burgle Eye",
"Darkmist Widow",
"Dart",
"Drogoth the Roamer",
"Hayoc",
"Lord Angler",
"Oozeworm",
"Ripscale",
"The Rot",
"Enforcer Emilgund",
"Ghost Howl",
"Mazzranache",
"Sister Hatelash",
"Snagglespear",
"The Rake",
"Aean Swiftriver",
"Ambassador Bloodrage",
"Azzere the Skyblade",
"Brokespear",
"Brontus",
"Captain Gerogg Hammertoe",
"Digger Flameforge",
"Dishu",
"Elder Mystic Razorsnout",
"Engineer Whirleygig",
"Foreman Grills",
"Geopriest Gukk'rok",
"Gesharahan",
"Hagg Taurenbane",
"Hannah Bladeleaf",
"Heggin Stonewhisker",
"Humar the Pridelord",
"Malgin Barleybrew",
"Marcus Bel",
"Rathorian",
"Rocklance",
"Silithid Harvester",
"Sister Rathtalon",
"Sludge Beast",
"Snort the Heckler",
"Stonearm",
"Swiftmane",
"Swinegart Spearhide",
"Takk the Leaper",
"Thora Feathermoon",
"Thunderstomp",
"Achellios the Banished",
"Gibblesnik",
"Harb Foulmountain",
"Heartrazor",
"Ironeye the Invincible",
"Silithid Ravager",
"Vile Sting",
"Accursed Slitherblade",
"Crusty",
"Giggler",
"Hissperak",
"Kaskk",
"Prince Kellen",
"Antilus the Soarer",
"Arash-ethis",
"Bloodroar the Stalker",
"Diamond Head",
"Gnarl Leafbrother",
"Lady Szallah",
"Old Grizzlegut",
"Qirot",
"Snarler",
"Gretheer",
"Grubthor",
"Huricanian",
"Krellack",
"Lapress",
"Rex Ashil",
"Setis",
"Twilight Lord Everun",
"Twilight Marauder Morna",
"Twilight Prophet",
"Zora",
"Brother Ravenoak",
"Foreman Rigger",
"Nal'taszar",
"Pridewing Patriarch",
"Sentinel Amarassan",
"Sister Riven",
"Sorrow Wing",
"Taskmaster Whipfang",
"Vengeful Ancient",
"Cyclok the Mad",
"Greater Firebird",
"Haarka the Ravenous",
"Jin'Zallah the Sandbringer",
"Kregg Keelhaul",
"Murderous Blisterpaw",
"Omgorn the Lost",
"Soriid the Devourer",
"Warleader Krazzilak",
"Clutchmother Zavas",
"Gruff",
"King Mosh",
"Ravasaur Matriarch",
"Uhk'loc",

"Mushgog",
"Skarr the Unbreakable",
"The Razza",

-- Eastern Kingdoms
"Araga",
"Cranky Benj",
"Gravis Slipknot",
"Jimmy the Bleeder",
"Lo'Grosh",
"Narillasanz",
"Skhowl",
"Stone Fury",
"Darbel Montrose",
"Foulbelly",
"Geomancer Flintdagger",
"Kovork",
"Molok the Crusher",
"Nimar the Slayer",
"Prince Nazjak",
"Ruul Onestone",
"Singer",
"Zalas Witherbark",
"Deathspeaker Selendre",
"Duggan Wildhammer",
"Gish the Unmoving",
"Hed'mush the Rotting",
"High General Abbendis",
"Baron Bloodbane",
"Lord Darkscythe",
"Nerubian Overseer",
"Ranger Lord Hawkspear",
"Warlord Thresh'jin",
"Zul'Brin Warpbranch",
"Big Samras",
"Creepthess",
"Lady Zephris",
"Ro'Bark",
"Scargil",
"Tamra Stormpike",
"Foreman Jerris",
"Foreman Marcrid",
"Foulmane",
"Lord Maldazzar",
"Putridius",
"Scarlet Executioner",
"Scarlet High Clerist",
"Scarlet Interrogator",
"Scarlet Judge",
"Scarlet Smith",
"The Husk",
"Grimungous",
"Ironback",
"Jalinde Summerdrake",
"Mith'rethis the Enchanter",
"Old Cliff Jumper",
"Razortalon",
"Retherokk the Berserker",
"The Reak",
"Witherheart the Stalker",
"Zul'arek Hatefowler",
"Bayne",
"Deeb",
"Farmer Solliden",
"Fellicent's Shade",
"Lost Soul",
"Muad",
"Ressan the Needler",
"Sri'skulk",
"Tormented Spirit",
"Dalaran Spellscribe",
"Gorefang",
"Krethis Shadowspinner",
"Old Vicejaw",
"Ravenclaw Regent",
"Rot Hide Bruiser",
"Snarlmane",
"Scarshield Quartermaster",
"The Behemoth",
"Bjarn",
"Edan the Howler",
"Gibblewilt",
"Great Father Arctikus",
"Hammerspine",
"Timber",
"7:XT",
"Anathemus",
"Barnabus",
"Broken Tooth",
"Rumbler",
"Shadowforge Commander",
"Siege Golem",
"War Golem",
"Zaricotl",
"Akubar the Seer",
"Clack the Reaver",
"Deatheye",
"Dreadscorn",
"Dreadwhisper",
"Grunter",
"Magronos the Unyielding",
"Mojo the Twisted",
"Ravage",
"Spiteflayer",
"Deathmaw",
"Gorgon'och",
"Gruklash",
"Hahk'Zor",
"Hematos",
"Malfunctioning Reaver",
"Terrorspark",
"Thauris Balgarr",
"Volchan",
"Morick Darkbrew",
"Boss Galgosh",
"Emogg the Crusher",
"Grizlak",
"Gosh-Haldir",
"Large Loch Crocolisk",
"Lord Condar",
"Magosh",
"Shanda the Spinner",
"Faulty War Golem",
"Highlord Mastrogonde",
"Rekk'tilac",
"Scald",
"Shleipnarr",
"Slave Master Blackheart",
"Smoldar",
"Dragonmaw Battlemaster",
"Garneg Charskull",
"Gnawbone",
"Leech Widow",
"Ma'ruk Wyrmscale",
"Mirelow",
"Razormaw Matriarch",
"Sludginn",
"Commander Felstrom",
"Fenros",
"Lord Malathrom",
"Lupos",
"Marina DeSirrus",
"Naraxis",
"Nefaru",
"The Unknown Soldier",
"Gug Fatcandle",
"Fedfennel",
"Gruff Swiftbite",
"Morgaine the Sly",
"Mother Fang",
"Narg the Taskmaster",
"Thuros Lightfingers",
"Boulderheart",
"Chatter",
"Kazon",
"Ribchaser",
"Rohh the Silent",
"Seeker Aqualon",
"Snarlflare",
"Squiddic",
"Sewer Beast",
"Gluggle",
"High Priestess Hai'watna",
"Kurmokk",
"Lord Sakrasis",
"Mosh'Ogg Butcher",
"Rippa",
"Roloch",
"Scale Belly",
"Verifonix",
"Fingat",
"Gilmorian",
"Lord Captain Wyrmak",
"Lost One Chieftain",
"Lost One Cook",
"Molt Thorn",
"Brack",
"Foe Reaper 4000",
"Leprithus",
"Master Digger",
"Sergeant Brashclaw",
"Slark",
"Vultros",
"Jade",
}

function AAL_TargetRareNPC()
  --ClearTarget()
  local npc
  UIErrorsFrame:UnregisterEvent("UI_ERROR_MESSAGE")
  for i = 1, 1000 do
    npc = npcList[i]
    if npc == nil then break end
    TargetByName(npc, true)
    if UnitName("target") == npc --[[UnitExists("target")]] then
       table.remove(npcList, i)
       table.insert(npcList, npc)
       --DEFAULT_CHAT_FRAME:AddMessage("Your sixth sense reveals nearby presense of "..npc, 0.59,0.68,0.92)
       break
    end
  end
  UIErrorsFrame:RegisterEvent("UI_ERROR_MESSAGE")
  if npc == nil then
     UIErrorsFrame:AddMessage("Your sixth sense reveals no one",1,0,0)
  end
end


-- EQUIPMENT SUPPORT CODE

function AAL_GetBagsFreeSpace()
  local free = 0
  for bagID = 0,4 do
  for i = 1, GetContainerNumSlots(bagID) do
    local link = GetContainerItemLink(bagID, i)
    if link == nil then free = free + 1; end
  end
  end
  return free
end


function AAL_FindInBagsByTexture(icon)
  if icon == nil then return nil end
  for bagID = 0,4 do
  for i = 1, GetContainerNumSlots(bagID) do
    local link = GetContainerItemLink(bagID, i)
    if link ~= nil then
       local _,_, itemId = string.find(link, "item:(%d+):");
       local _,_,_,_,class,subclass,_,eqloc,texture = GetItemInfo( itemId )
       if texture == icon then
          return bagID,i,eqloc
       end
    end
  end
  end
  return nil
end


function AAL_StopAction()
  -- перерывает такие как Frostbolt, убирает целеуказание таких как Blizzard,
  -- но не умеет прерывать channeling таких как Blizzard
  if SpellStopCasting() then return 3; end

  -- работает только если в Action slot'ы помещены действия Attack и Auto Shot/Shoot
  for i = 1, 120 do
    if IsAttackAction(i)--[[melee]] and IsCurrentAction(i) then UseAction(i); return 1; end
    if IsAutoRepeatAction(i)--[[ranged]] then UseAction(i); return 2; end
  end
  return nil;
end



-- SPELLS/ITEMS CODE

function AAL_ScanSpells()
  -- предшествующее множество не удаляем, т.к. обычно это не нужно
  -- добавляем все активные способности заново
  for i = 1, 5000 do
    local spell, rank = GetSpellName(i, BOOKTYPE_SPELL)
    if spell == nil then
       --print("Spells scanned: ", i-1)
       return
    end
    if not IsSpellPassive(i, BOOKTYPE_SPELL) then
       -- Предполагается, что последний по порядку rank будет самым высоким
       aal_Abilities[spell] = i
       if rank and rank ~= "" then
          aal_Abilities[ spell.."("..rank..")" ] = i
       end
    end
  end
end


function AAL_ScanInventory()
  local maxInvN = ContainerIDToInventoryID(1)-1
  -- удаляем все вещи, относящиеся к экипировке
  for name,i in pairs(aal_Abilities) do
      if i <= 0 and i >= -maxInvN then
         --print("Inv.Remove:", name)
         aal_Abilities[name] = nil
      end
  end
  -- добавляем вещи экипировки
  for i = 0, maxInvN do
    local link = GetInventoryItemLink("player",i)
    if link ~= nil then
       local _,_, itemId = string.find(link, "item:(%d+):");
       -- !!! GetItemInfo может возвратить nil, если в кэше нет данных!
       local name,_,_,_,_,isubtype = GetItemInfo( itemId )
       --print("AAL_ScanInventory:", i, "=", name)
       if name == nil then
          print("AAL_ScanInventory: item unresolved at slot", i, "itemId:", itemId)
       else
          aal_Abilities[name] = -i
          if i == 18 then aal_RangedWeaponType = isubtype end
       end
    end
  end
end


function AAL_ScanBag(bagID)
  local negStart = - (1000 + bagID*100)
  -- удаляем все вещи, относящиеся к данной сумке
  for name,i in pairs(aal_Abilities) do
      if i <= negStart and i > negStart - 100 then
         --print("AAL_ScanBag: remove", name)
         aal_Abilities[name] = nil
      end
  end
  -- добавляем вещи из данной сумки (исключая те, что требуют экипировки, но не могут быть экипированы в бою)
  for i = 1, GetContainerNumSlots(bagID) do
    local link = GetContainerItemLink(bagID, i)
    if link ~= nil then
       local _,_, itemId = string.find(link, "item:(%d+):");
       local name,_,_,_,_,_,_,invType = GetItemInfo( itemId )
       local allowedInvTypes = { [""]=true, ["INVTYPE_WEAPONMAINHAND"]=true, ["INVTYPE_WEAPONOFFHAND"]=true, ["INVTYPE_SHIELD"]=true, ["INVTYPE_2HWEAPON"]=true, ["INVTYPE_HOLDABLE"]=true, ["INVTYPE_RANGED"]=true, ["INVTYPE_AMMO"]=true, ["INVTYPE_THROWN"]=true };
       --print("AAL_ScanBag: Bag #", bagID, ":", negStart - i, "=", name)
       if name == nil then
          print("AAL_ScanBag: item unresolved at bag", bagID, "slot", i, "itemId:", itemId)
       elseif invType and allowedInvTypes[ invType ] then
          aal_Abilities[name] = negStart - i
       end
    end
  end
end


function AAL_GetEquippedItem(slot)
  local link = GetInventoryItemLink("player", slot)
  if link == nil then return nil; end
  local _,_, itemId = string.find(link, "item:(%d+):");
  if itemId == nil then return nil; end
  return GetItemInfo( itemId )
end

function AAL_GetContainerItem(bagID, slot)
  local link = GetContainerItemLink(bagID, slot)
  if link == nil then return nil; end
  local _,_, itemId = string.find(link, "item:(%d+):");
  if itemId == nil then return nil; end
  return GetItemInfo( itemId )
end




function AAL_IsActiveSpell(spell) -- работает для Warrior Stances, Rogue Steallh, но не Paladin Auras, и не для channeled
  local index = aal_Abilities[spell]
  if index == nil then return false; end
  return IsCurrentCast(index, BOOKTYPE_SPELL)
end


function AAL_GetForm()
  for i = 1, 100 do
    local _, form, active = GetShapeshiftFormInfo(i)
    if form == nil then return nil; end
    if active ~= nil then
       if form == "Bear Form" or form == "Dire Bear Form" or form == "Aquatic Form" or
          form == "Cat Form" or form == "Travel Form" or form == "Moonkin Form"
          or form == "Tree Form"
       then
          return form
       elseif form == "Battle Stance" or form == "Defensive Stance" or form == "Berserker Stance" then
          return nil, form
       end
    end
  end
  -- не отслеживаются Shadowform, Hook of the Master Angler, Ghost Wolf и др. формы
  return nil
end


function AAL_IsAura(...)
  for j = 0, 100 do
    local k = GetPlayerBuff(j, "HELPFUL|HARMFUL|PASSIVE")
    if k <= -1 then break end
    local buffIcon = GetPlayerBuffTexture(k)
    for i = 1,table.getn(arg) do
      if string.find(buffIcon, arg[i], 1,true) then return k,i; end
    end
  end
  return nil
end


local function IsBuffOrDebuff(Func, arg)
  local t = "target"
  local arg1 = arg[1]
  local k1 = 1
  if arg1 == "pet" or arg1 == "player" or arg1 == "target" then t = arg1; k1 = 2; end

  if k1 > table.getn(arg) or not UnitExists(t) then return nil end

  for i = 1, 100 do
    local uicon = Func(t, i) -- UnitBuff или UnitDebuff
    if uicon == nil then break end
    for k = k1,table.getn(arg) do
      local icon = arg[k]
      if icon ~= nil and string.find(uicon, icon, 1,true) then return k-k1+1; end
    end
  end
  return nil
end


function AAL_IsBuff(...)
  return IsBuffOrDebuff(UnitBuff, arg)
end

function AAL_IsDebuff(...)
  return IsBuffOrDebuff(UnitDebuff, arg)
end

function AAL_IsDebuffStunned()
  return AAL_IsDebuff(
"Ability_ThunderBolt", -- Concussion Blow
"Spell_Holy_SealOfMight", -- Hammer of Justice
"Ability_CheapShot", -- Cheap Shot
"Ability_Gouge", -- Gouge | Rend
"Ability_Rogue_KidneyShot", -- Kidney Shot
"Ability_Golem_StormBolt" -- Scatter Shot
  )
end

function AAL_IsDebuffSlowed()
  return AAL_IsDebuff(
"Ability_ThunderBolt", -- Concussion Blow
"Spell_Holy_SealOfMight", -- Hammer of Justice
"Ability_CheapShot", -- Cheap Shot
"Ability_Gouge", -- Gouge | Rend
"Ability_Rogue_KidneyShot" -- Kidney Shot
,
"Spell_Frost_Stun", -- Concussive Shot
"Ability_Rogue_Trip", -- Wing Clip
"Ability_ShockWave", -- Hamstring
"Spell_Frost_FrostBolt02", -- Frostbolt
"Spell_Frost_FrostArmor02", -- Frost/Ice Armor
"Spell_Shadow_GrimWard" -- Curse of Exhaustion
  )
end


function AAL_IsDispellableDebuff(target, ...)
  if not UnitExists(target) then return nil end

  for i = 1, 100 do
    local uicon,_,dispelType = UnitDebuff(target, i)
    if uicon == nil then break end
    for k = 1,table.getn(arg) do
      -- Can be "Magic", "Curse", "Poison", "Disease" or nil if not dispellable
      if dispelType == arg[k] then return k; end
    end
  end
  return nil
end


function AAL_IsActBar(slot, ...)
  local slotIcon = GetActionTexture(slot)
  if slotIcon == nil then return nil; end
  for k = 1,table.getn(arg) do
     if string.find(slotIcon, arg[k], 1,true) then return k; end
  end
  return false
end


function AAL_UseOrCreateItem(...)
  local item
  for i = 1, table.getn(arg), 2 do
    item = arg[i]
    if aal_Abilities[ item ] ~= nil and AAL_Cast(arg[i]) then return -i/2;
    elseif AAL_Cast(arg[i+1]) then return i/2;
    end
  end
  UIErrorsFrame:AddMessage("Cannot create "..item,1,0,0)
  return nil
end

function AAL_CreateItems(...)
  local item
  for i = 1, table.getn(arg), 2 do
    item = arg[i]
    if aal_Abilities[ item ] == nil and AAL_Cast(arg[i+1]) then return i/2; end
  end
  UIErrorsFrame:AddMessage("Cannot create "..item,1,0,0)
  return nil
end



function AAL_IsCD(spellName)
  local index = aal_Abilities[spellName]
  if index == nil then return nil; end
  local _, duration = GetSpellCooldown(index, BOOKTYPE_SPELL)
  return duration > 0;
end

function AAL_IsGCD()
  return AAL_IsCD("Find Treasure") -- предполагается, что всегда есть у игрока
end


function AAL_RemainingCD(spellName)
  local i = aal_Abilities[spellName]
  if i == nil then return -99999; end
  local startTime, CD = GetSpellCooldown(i, BOOKTYPE_SPELL)
  return CD == 0 and 0  or  CD - (GetTime() - startTime);
end



aal_StunImmune = { -- SELECT name FROM creature_template WHERE mechanic_immune_mask&2048 AND rank!=3 AND minlevel>1 ORDER by name
["Aggi Rumblestomp"]=true,
["Alliance Spirit Guide"]=true,
["Aluntir"]=true,
["Alzzin the Wildshaper"]=true,
["Ambassador Flamelash"]=true,
["Ancient Core Hound"]=true,
["Anger'rel"]=true,
["Antu'sul"]=true,
["Anub'shiah"]=true,
["Arakis"]=true,
["Arcanist Doan"]=true,
["Arch Druid Renferal"]=true,
["Archivist Galford"]=true,
["Archmage Arugal"]=true,
["Atal'ai Deathwalker's Spirit"]=true,
["Atal'ai Skeleton"]=true,
["Avalanchion"]=true,
["Avatar of Hakkar"]=true,
["Axtroz"]=true,
["Bael'Gar"]=true,
["Balnazzar"]=true,
["Baron Charr"]=true,
["Baron Rivendare"]=true,
["Baron Silverlaine"]=true,
["Baroness Anastari"]=true,
["Bazil Thredd"]=true,
["Bazzalan"]=true,
["Befouled Water Elemental"]=true,
["Bile Sludge"]=true,
["Blackwing Spellbinder"]=true,
["Blazing Elemental"]=true,
["Blighthound"]=true,
["Blood Steward of Kirtonos"]=true,
["Bloodmage Thalnos"]=true,
["Boiling Elemental"]=true,
["Brain Wash Totem"]=true,
["Burning Felguard"]=true,
["Cannon Master Willey"]=true,
["Captain Balinda Stonehearth"]=true,
["Captain Galvangar"]=true,
["Captain Kromcrush"]=true,
["Cenarion Hold Infantry"]=true,
["Chief Ukorz Sandscalp"]=true,
["Cho'Rush the Observer"]=true,
["Chromatic Drakonid"]=true,
["Chronalis"]=true,
["Colossal Anubisath Warbringer"]=true,
["Commander Dardosh"]=true,
["Commander Duffy"]=true,
["Commander Karl Philips"]=true,
["Commander Louis Philips"]=true,
["Commander Malgor"]=true,
["Commander Mulfort"]=true,
["Commander Randolph"]=true,
["Commander Springvale"]=true,
["Core Hound"]=true,
["Core Rager"]=true,
["Corporal Noreg Stormpike"]=true,
["Corrupted Fire Nova Totem V"]=true,
["Corrupted Healing Stream Totem V"]=true,
["Corrupted Stoneskin Totem VI"]=true,
["Corrupted Windfury Totem III"]=true,
["Crystal Fang"]=true,
["Darkmaster Gandling"]=true,
["Death Talon Captain"]=true,
["Death Talon Dragonspawn"]=true,
["Death Talon Flamescale"]=true,
["Death Talon Hatcher"]=true,
["Death Talon Seether"]=true,
["Death Talon Wyrmguard"]=true,
["Death Talon Wyrmkin"]=true,
["Demetria"]=true,
["Demon Portal"]=true,
["Dextren Ward"]=true,
["Doctor Theolen Krastinov"]=true,
["Doom'rel"]=true,
["Dope'rel"]=true,
["Dreamscythe"]=true,
["Drek'Thar"]=true,
["Dun Baldar North Marshal"]=true,
["Dun Baldar North Warmaster"]=true,
["Dun Baldar South Marshal"]=true,
["Dun Baldar South Warmaster"]=true,
["Earth Elemental"]=true,
["East Frostwolf Marshal"]=true,
["East Frostwolf Warmaster"]=true,
["Elemental Protection Totem"]=true,
["Elemental Slave"]=true,
["Emperor Dagran Thaurissan"]=true,
["Enraged Felguard"]=true,
["Enraged Rock Elemental"]=true,
["Eviscerator"]=true,
["Fallout Slime"]=true,
["Fenrus the Devourer"]=true,
["Fineous Darkvire"]=true,
["Fire Elemental"]=true,
["Flamewaker Elite"]=true,
["Flamewaker Healer"]=true,
["Frostwolf Explosives Expert"]=true,
["Frostwolf Mine Layer"]=true,
["Frostwolf Stable Master"]=true,
["Frostwolf Wolf Rider Commander"]=true,
["Gaelden Hammersmith"]=true,
["Gelihast"]=true,
["General Angerforge"]=true,
["Ghok Bashguud"]=true,
["Gizrul the Slavener"]=true,
["Glob of Viscidus"]=true,
["Gloom'rel"]=true,
["Golem Lord Argelmach"]=true,
["Gorosh the Dervish"]=true,
["Grand Crusader Dathrohan"]=true,
["Grand Inquisitor Isillien"]=true,
["Greater Obsidian Elemental"]=true,
["Greater Rock Elemental"]=true,
["Grizzle"]=true,
["Grol the Destroyer"]=true,
["Grunnda Wolfheart"]=true,
["Guardian of Icecrown"]=true,
["Guse's War Rider"]=true,
["Halycon"]=true,
["Hamhock"]=true,
["Hate'rel"]=true,
["Hazzas"]=true,
["Hearthsinger Forresten"]=true,
["Hedrum the Creeper"]=true,
["Herod"]=true,
["High Inquisitor Fairbanks"]=true,
["High Inquisitor Whitemane"]=true,
["High Interrogator Gerstahn"]=true,
["Highlord Omokk"]=true,
["Highlord Taelan Fordring"]=true,
["Hive'Regal Hunter-Killer"]=true,
["Hive'Zara Larva"]=true,
["Horde Spirit Guide"]=true,
["Houndmaster Grebmar"]=true,
["Houndmaster Loksey"]=true,
["Hurley Blackbreath"]=true,
["Hydromancer Velratha"]=true,
["Hydrospawn"]=true,
["Iceblood Marshal"]=true,
["Iceblood Warmaster"]=true,
["Icewing Marshal"]=true,
["Icewing Warmaster"]=true,
["Ichman's Gryphon"]=true,
["Illusion of Jandice Barov"]=true,
["Illyanna Ravenoak"]=true,
["Immol'thar"]=true,
["Imperial Qiraji Destroyer"]=true,
["Inferno Elemental"]=true,
["Instructor Malicia"]=true,
["Ironaya"]=true,
["Irondeep Peon"]=true,
["Isalien"]=true,
["Ivus the Forest Lord"]=true,
["Jammal'an the Prophet"]=true,
["Jandice Barov"]=true,
["Jarien"]=true,
["Jed Runewatcher"]=true,
["Jergosh the Invoker"]=true,
["Jeztor's War Rider"]=true,
["Jotek"]=true,
["Kam Deepfury"]=true,
["Keetar"]=true,
["King Gordok"]=true,
["King Mosh"]=true,
["Kirtonos the Herald"]=true,
["Kormok"]=true,
["Korrak the Bloodrager"]=true,
["Lady Illucia Barov"]=true,
["Lady Sarevess"]=true,
["Lava Spawn"]=true,
["Lesser Rock Elemental"]=true,
["Lesser Water Elemental"]=true,
["Lethtendris"]=true,
["Lieutenant Greywand"]=true,
["Lieutenant Grummus"]=true,
["Lieutenant Largent"]=true,
["Lieutenant Lewis"]=true,
["Lieutenant Lonadin"]=true,
["Lieutenant Mancuso"]=true,
["Lieutenant Murp"]=true,
["Lieutenant Rugba"]=true,
["Lieutenant Spencer"]=true,
["Lieutenant Stouthandle"]=true,
["Lieutenant Stronghoof"]=true,
["Lieutenant Vol'talar"]=true,
["Lokholar the Ice Lord"]=true,
["Lord Alexei Barov"]=true,
["Lord Hel'nurath"]=true,
["Lord Incendius"]=true,
["Lorekeeper Polkelt"]=true,
["Magister Kalendris"]=true,
["Magistrate Barthilas"]=true,
["Magma Elemental"]=true,
["Magmus"]=true,
["Magrami Spectre"]=true,
["Maleki the Pallid"]=true,
["Malor the Zealous"]=true,
["Marduk Blackpool"]=true,
["Masha Swiftcut"]=true,
["Molten Destroyer"]=true,
["Molten Elemental"]=true,
["Molten Giant"]=true,
["Mor Grayhoof"]=true,
["Morloch"]=true,
["Morphaz"]=true,
["Mother Smolderweb"]=true,
["Mountaineer Boombellow"]=true,
["Mulverick's War Rider"]=true,
["Murgot Deepforge"]=true,
["Mushgog"]=true,
["Narillasanz"]=true,
["Nathanos Blightcaller"]=true,
["Necro Stalker"]=true,
["Nekrum Gutchewer"]=true,
["Nerub'enkan"]=true,
["Nessy"]=true,
["Number Two"]=true,
["Obsidian Elemental"]=true,
["Odo the Blindwatcher"]=true,
["Oggleflint"]=true,
["Ok'thor the Breaker"]=true,
["Onyxian Warder"]=true,
["Panzor the Invincible"]=true,
["Pimgib"]=true,
["Plagued Deathhound"]=true,
["Plugger Spazzring"]=true,
["Powerful Healing Ward"]=true,
["Primalist Thurloga"]=true,
["Prince Tortheldrin"]=true,
["Princess Tempestria"]=true,
["Princess Theradras"]=true,
["Pusillin"]=true,
["Pyromancer Loregrain"]=true,
["Qiraji Brigadier General Pax-lish"]=true,
["Qiraji Captain Ka'ark"]=true,
["Qiraji Lieutenant"]=true,
["Qiraji Lieutenant General"]=true,
["Qiraji Lieutenant Jo-rel"]=true,
["Qiraji Major"]=true,
["Qiraji Major He'al-ie"]=true,
["Qiraji Officer Zod"]=true,
["Quartermaster Zigris"]=true,
-- ["Ras Frostwhisper"]=true,
-- ["Rattlegore"]=true,
["Razelikh the Defiler"]=true,
["Razorclaw the Butcher"]=true,
["Rethilgore"]=true,
["Rexxar"]=true,
["Ribbly Screwspigot"]=true,
["Rock Elemental"]=true,
["Ruuzlu"]=true,
["Scalding Elemental"]=true,
["Scarlet Commander Mograine"]=true,
["Scorching Elemental"]=true,
["Scorn"]=true,
["Scryer"]=true,
["Sea Elemental"]=true,
["Seeth'rel"]=true,
["Sergeant Bly"]=true,
["Sever"]=true,
["Sewage Slime"]=true,
["Shade of Eranikus"]=true,
["Shade of Taerar"]=true,
["Shadow Hunter Vosh'gajin"]=true,
["Shadowpriest Sezz'ziz"]=true,
["Shandris Feathermoon"]=true,
["Skarr the Unbreakable"]=true,
["Slidore's Gryphon"]=true,
["Smith Regzar"]=true,
["Solakar Flamewreath"]=true,
["Somnus"]=true,
["Sothos"]=true,
["Soul Weaver"]=true,
["Spectral Rider"]=true,
["Spirestone Battle Lord"]=true,
["Spirestone Butcher"]=true,
["Spirestone Lord Magus"]=true,
["Spirit Shade"]=true,
["Stomper Kreeg"]=true,
["Stonehearth Marshal"]=true,
["Stonehearth Warmaster"]=true,
["Stonespine"]=true,
["Stormpike Explosives Expert"]=true,
["Stormpike Mine Layer"]=true,
["Stormpike Ram Rider Commander"]=true,
["Stormpike Stable Master"]=true,
["Summoned Water Elemental"]=true,
["Taragaman the Hungerer"]=true,
["Targorr the Dread"]=true,
["Taskmaster Snivvle"]=true,
["Tendris Warpwood"]=true,
["The Cleaner"]=true,
["The Duke of Cynders"]=true,
["The Duke of Fathoms"]=true,
["The Duke of Shards"]=true,
["The Duke of Zephyrs"]=true,
-- ["The Ravenian"]=true,
["The Razza"]=true,
["The Unforgiven"]=true,
["The Windreaver"]=true,
["Theka the Martyr"]=true,
["Timmy the Cruel"]=true,
["Tower Point Marshal"]=true,
["Tower Point Warmaster"]=true,
["Tsu'zee"]=true,
["Twilight Elementalist"]=true,
["Umi Thorson"]=true,
["Undead Postman"]=true,
["Unrelenting Rider"]=true,
["Unstoppable Abomination"]=true,
["Urok Doomhowl"]=true,
["Vanndar Stormpike"]=true,
["Varimathras"]=true,
["Vectus"]=true,
["Venom Stalker"]=true,
["Verek"]=true,
["Vile'rel"]=true,
["Vipore's Gryphon"]=true,
["War Master Voone"]=true,
["Warden Thelwater"]=true,
["Warder Stilgiss"]=true,
["Water Elemental"]=true,
["Weaver"]=true,
["West Frostwolf Marshal"]=true,
["West Frostwolf Warmaster"]=true,
["Wing Commander Guse"]=true,
["Wing Commander Ichman"]=true,
["Wing Commander Jeztor"]=true,
["Wing Commander Mulverick"]=true,
["Wing Commander Slidore"]=true,
["Witch Doctor Zum'rah"]=true,
["Wolf Master Nandos"]=true,
["Xil'xix"]=true,
["Xorothian Dreadsteed"]=true,
["Zevrim Thornhoof"]=true,
}


aal_FireImmune = { -- SELECT name FROM creature_template WHERE resistance2>=400 AND maxlevel>1 ORDER BY name
["Ambassador Infernus"]=true,
["Angered Infernal"]=true,
["Arch Druid Fandral Staghelm"]=true,
["Baron Charr"]=true,
["Baron Geddon"]=true,
["Black Drakonid"]=true,
["Blazerunner"]=true,
["Blazing Elemental"]=true,
["Blazing Fireguard"]=true,
["Blazing Invader"]=true,
["Burning Destroyer"]=true,
["Burning Exile"]=true,
["Burning Ravager"]=true,
["Burning Servant"]=true,
["Burning Spirit"]=true,
["Chieftain Nek'rosh"]=true,
["Corrupted Fire Nova Totem V"]=true,
["Corrupted Infernal"]=true,
["Crimson Templar"]=true,
["Dessecus"]=true,
["Ebonroc"]=true,
["Ember"]=true,
["Entropic Beast"]=true,
["Entropic Horror"]=true,
["Faulty War Golem"]=true,
["Felcular"]=true,
["Fire Elemental"]=true,
["Fireguard"]=true,
["Fireguard Destroyer"]=true,
["Firelord"]=true,
["Firemaw"]=true,
["Firewalker"]=true,
["Flamegor"]=true,
["Flameguard"]=true,
["Garneg Charskull"]=true,
["Huricanian"]=true,
["Ilifar"]=true,
["Illusion of Jandice Barov"]=true,
["Infernal"]=true,
["Infernal Bodyguard"]=true,
["Infernal Sentry"]=true,
["Infernal Servant"]=true,
["Inferno Elemental"]=true,
["Lava Spawn"]=true,
["Lesser Infernal"]=true,
["Living Blaze"]=true,
["Living Flame"]=true,
["Lord Incendius"]=true,
["Lord Roccor"]=true,
["Massive Infernal"]=true,
["Minor Manifestation of Fire"]=true,
["Mordresh Fire Eye"]=true,
["Narillasanz"]=true,
["Nefarian"]=true,
["Onyxia"]=true,
["Overmaster Pyron"]=true,
["Plague Slime (Red)"]=true,
["Prince Skaldrenox"]=true,
["Pyroguard Emberseer"]=true,
["Ragnaros"]=true,
["Razelikh the Defiler"]=true,
["Red Drakonid"]=true,
["Risen Aberration"]=true,
["Rogue Flame Spirit"]=true,
["Rumbler"]=true,
["Scald"]=true,
["Scorched Guardian"]=true,
["Scorching Elemental"]=true,
["Searing Infernal"]=true,
["Smoldar"]=true,
["Son of Flame"]=true,
["Spectral Deathknight"]=true,
["Spectral Horse"]=true,
["Spectral Rider"]=true,
["Spectral Trainee"]=true,
["Teremus the Devourer"]=true,
["The Husk"]=true,
["The Windreaver"]=true,
["Vaelastrasz the Corrupt"]=true,
}


aal_NatureImmune = { -- SELECT name FROM creature_template WHERE resistance3>=400 AND maxlevel>1 ORDER BY name
["Arcane Feedback"]=true,
["Arcane Torrent"]=true,
["Arch Druid Fandral Staghelm"]=true,
["Barbed Lasher"]=true,
["Bloodfeather Wind Witch"]=true,
["Bloodpetal Lasher"]=true,
["Bloodtalon Taillasher"]=true,
["Branch Snapper"]=true,
["Bristleback Water Seeker"]=true,
["Cyclok the Mad"]=true,
["Cyclone Warrior"]=true,
["Cyclonian"]=true,
["Dessecus"]=true,
["Deviate Lasher"]=true,
["Dust Devil"]=true,
["Dust Stormer"]=true,
["Emeriss"]=true,
["Faulty War Golem"]=true,
["Gnarl Leafbrother"]=true,
["Green Drakonid"]=true,
["Gusting Vortex"]=true,
["Hive'Zara Tail Lasher"]=true,
["Huricanian"]=true,
["Illusion of Jandice Barov"]=true,
["Lethon"]=true,
["Living Storm"]=true,
["Lord Kri"]=true,
["Lord Roccor"]=true,
["Mannoroc Lasher"]=true,
["Margol the Rager"]=true,
["Monnos the Elder"]=true,
["Plague Slime (Green)"]=true,
["Prince Thunderaan"]=true,
["Princess Yauj"]=true,
["Qiraji Lasher"]=true,
["Razormane Water Seeker"]=true,
["Risen Aberration"]=true,
["Rumbler"]=true,
["Scorpashi Lasher"]=true,
["Scorpid Tail Lasher"]=true,
["Smoldar"]=true,
["Spectral Deathknight"]=true,
["Spectral Horse"]=true,
["Spectral Rider"]=true,
["Spectral Trainee"]=true,
["Stinglasher"]=true,
["Stone Fury"]=true,
["Strength of Earth Totem"]=true,
["Strength of Earth Totem II"]=true,
["Strength of Earth Totem III"]=true,
["Strength of Earth Totem IV"]=true,
["Strength of Earth Totem V"]=true,
["Swirling Vortex"]=true,
["Taerar"]=true,
["The Husk"]=true,
["The Windreaver"]=true,
["Thundering Exile"]=true,
["Trigore the Lasher"]=true,
["Vem"]=true,
["Vorsha the Lasher"]=true,
["Whirling Invader"]=true,
["Whirlwind Ripper"]=true,
["Whirlwind Shredder"]=true,
["Whirlwind Stormwalker"]=true,
["Wind Howler"]=true,
["Windfury Wind Witch"]=true,
["Ysondre"]=true,
}

aal_FrostImmune = { -- SELECT name FROM creature_template WHERE resistance4>=400 AND maxlevel>1 ORDER BY name
["Aku'mai Servant"]=true,
["Aqua Guardian"]=true,
["Aquementas"]=true,
["Arch Druid Fandral Staghelm"]=true,
["Azure Templar"]=true,
["Baron Aquanis"]=true,
["Befouled Water Elemental"]=true,
["Blackwater Deckhand"]=true,
["Bleak Worg"]=true,
["Blighted Horror"]=true,
["Blighted Surge"]=true,
["Blue Drakonid"]=true,
["Boiling Elemental"]=true,
["Bristleback Water Seeker"]=true,
["Corrupt Minor Manifestation of Water"]=true,
["Corrupt Water Spirit"]=true,
["Cresting Exile"]=true,
["Dessecus"]=true,
["Discordant Surge"]=true,
["Duke Hydraxis"]=true,
["Eck'alom"]=true,
["Elder Saltwater Crocolisk"]=true,
["Faulty War Golem"]=true,
["Felcular"]=true,
["Frostmaul Giant"]=true,
["Huricanian"]=true,
["Hydraxian Honor Guard"]=true,
["Hydroling"]=true,
["Hydrospawn"]=true,
["Ilifar"]=true,
["Illusion of Jandice Barov"]=true,
["Irradiated Horror"]=true,
["Islen Waterseer"]=true,
["Kashoch the Reaver"]=true,
["Lesser Water Elemental"]=true,
["Lord Roccor"]=true,
["Lord Skwol"]=true,
["Manifestation of Water"]=true,
["Minor Manifestation of Water"]=true,
["Muck Splash"]=true,
["Noxxion"]=true,
["Noxxion's Spawn"]=true,
["Noxxious Essence"]=true,
["Noxxious Scion"]=true,
["Plague Monstrosity"]=true,
["Plague Ravager"]=true,
["Plague Slime (Blue)"]=true,
["Princess Tempestria"]=true,
["Razormane Water Seeker"]=true,
["Risen Aberration"]=true,
["Rumbler"]=true,
["Saltwater Crocolisk"]=true,
["Sapphiron"]=true,
["Scalding Elemental"]=true,
["Sea Elemental"]=true,
["Sea Spray"]=true,
["Seeker Aqualon"]=true,
["Shadowfang Whitescalp"]=true,
["Smoldar"]=true,
["Spectral Deathknight"]=true,
["Spectral Horse"]=true,
["Spectral Rider"]=true,
["Spectral Trainee"]=true,
["Summoned Guardian"]=true,
["Summoned Water Elemental"]=true,
["The Husk"]=true,
["The Windreaver"]=true,
["Tideress"]=true,
["Toxic Horror"]=true,
["Tsunaman"]=true,
["Vengeful Surge"]=true,
["Viscous Fallout"]=true,
["Water Elemental"]=true,
["Water Spirit"]=true,
["Watery Invader"]=true,
}

aal_ShadowImmune = { -- SELECT name FROM creature_template WHERE resistance5>=400 AND maxlevel>1 ORDER BY name
["Arch Druid Fandral Staghelm"]=true,
["Argus Shadow Mage"]=true,
["Ariyell Skyshadow"]=true,
["Arugal's Voidwalker"]=true,
["Aspect of Shadow"]=true,
["Balgaras the Foul"]=true,
["Balthule Shadowstrike"]=true,
["Black Drakonid"]=true,
["Bloodhound Mastiff"]=true,
["Boneflayer Ghoul"]=true,
["Brokespear"]=true,
["Burning Blade Shadowmage"]=true,
["Burning Felhound"]=true,
["Burning Imp"]=true,
["Cannibal Ghoul"]=true,
["Captive Abomination"]=true,
["Captive Ghoul"]=true,
["Celebras the Cursed"]=true,
["Corruptor"]=true,
["Crimson Cannon"]=true,
["Dark Sprite"]=true,
["Death's Head Necromancer"]=true,
["Demon Portal Guardian"]=true,
["Dessecus"]=true,
["Deth'ryll Satyr"]=true,
["Diseased Ghoul"]=true,
["Dreadscorn"]=true,
["Elder Shadowhorn Stag"]=true,
["Elder Shadowmaw Panther"]=true,
["Faulty War Golem"]=true,
["Felcular"]=true,
["Felguard Elite"]=true,
["Felguard Sentry"]=true,
["Felhound"]=true,
["Felslayer"]=true,
["Flamekin Rager"]=true,
["Flamekin Spitter"]=true,
["Flamekin Sprite"]=true,
["Flamekin Torcher"]=true,
["Fleshflayer Ghoul"]=true,
["Flint Shadowmore"]=true,
["Frostmane Shadowcaster"]=true,
["Geenia Sunshadow"]=true,
["Ghoul Berserker"]=true,
["Ghoul Ravener"]=true,
["Gibbering Ghoul"]=true,
["Gimrizz Shadowcog"]=true,
["Hakkari Shadow Hunter"]=true,
["Hakkari Shadowcaster"]=true,
["Hederine Initiate"]=true,
["Hederine Slayer"]=true,
["Highlord Mograine"]=true,
["Hive'Zora Abomination"]=true,
["Huricanian"]=true,
["Ilifar"]=true,
["Ilkrud Magthrull"]=true,
["Illusion of Jandice Barov"]=true,
["Immol'thar"]=true,
["Insane Ghoul"]=true,
["Jabbering Ghoul"]=true,
["Jugkar Grim'rod"]=true,
["Kaela Shadowspear"]=true,
["Kirsta Deepshadow"]=true,
["Klinfran the Crazed"]=true,
["Krethis Shadowspinner"]=true,
["Kurzen Shadow Hunter"]=true,
["Lady Hederine"]=true,
["Lady Sevine"]=true,
["Legion Hound"]=true,
["Lesser Felguard"]=true,
["Ley Hunter"]=true,
["Lieutenant Fangore"]=true,
["Lord Grayson Shadowbreaker"]=true,
["Lord Roccor"]=true,
["Lost Whelp"]=true,
["Mad Voidwalker"]=true,
["Mage Hunter"]=true,
["Magregan Deepshadow"]=true,
["Mana Eater"]=true,
["Mannoroc Lasher"]=true,
["Marauding Skeleton"]=true,
["Massive Infernal"]=true,
["Master Feardred"]=true,
["Master Sergeant Moonshadow"]=true,
["Mindless Skeleton"]=true,
["Molt Thorn"]=true,
["Moora"]=true,
["Mossflayer Shadowhunter"]=true,
["Mutanus the Devourer"]=true,
["Narret Shadowgrove"]=true,
["Necro Knight Guardian"]=true,
["Necromancer"]=true,
["Nelson the Nice"]=true,
["Nessa Shadowsong"]=true,
["Nether Maiden"]=true,
["Orcish Orphan"]=true,
["Outcast Necromancer"]=true,
["Plague Ghoul"]=true,
["Plague Slime"]=true,
["Poison Sprite"]=true,
["Precious the Devourer"]=true,
["Pusillin"]=true,
["Rabid Shadowhide Gnoll"]=true,
["Ragged Ghoul"]=true,
["Rakaiah"]=true,
["Rascal Sprite"]=true,
["Rattlecage Skeleton"]=true,
["Razelikh the Defiler"]=true,
["Risen Aberration"]=true,
["Rocklance"]=true,
["Rokar Bladeshadow"]=true,
["Rotten Ghoul"]=true,
["Rotting Ancestor"]=true,
["Rotting Ghoul"]=true,
["Rumbler"]=true,
["Sahvan Bloodshadow"]=true,
["Salia"]=true,
["Sandfury Shadowcaster"]=true,
["Sandfury Shadowhunter"]=true,
["Scholomance Necromancer"]=true,
["Scourge Summoning Crystal"]=true,
["Searing Ghoul"]=true,
["Sentinel Melyria Frostshadow"]=true,
["Sergeant Major Skyshadow"]=true,
["Servant of Alexi Barov"]=true,
["Servant of Allistarj"]=true,
["Servant of Grol"]=true,
["Servant of Razelikh"]=true,
["Servant of Sevine"]=true,
["Shadow"]=true,
["Shadow Charger"]=true,
["Shadow Fissure"]=true,
["Shadow Hunter Vosh'gajin"]=true,
["Shadow Lord Fel'dan"]=true,
["Shadow of Lexlort"]=true,
["Shadow Panther"]=true,
["Shadow Priest Allister"]=true,
["Shadow Priest Sarvis"]=true,
["Shadow Priestess Shai"]=true,
["Shadow Priestess Vandis"]=true,
["Shadow Sprite"]=true,
["Shadowed Spirit"]=true,
["Shadowfang Darksoul"]=true,
["Shadowfang Glutton"]=true,
["Shadowfang Moonwalker"]=true,
["Shadowfang Ragetooth"]=true,
["Shadowfang Whitescalp"]=true,
["Shadowfang Wolfguard"]=true,
["Shadowforge Ambusher"]=true,
["Shadowforge Archaeologist"]=true,
["Shadowforge Chanter"]=true,
["Shadowforge Citizen"]=true,
["Shadowforge Commander"]=true,
["Shadowforge Darkweaver"]=true,
["Shadowforge Digger"]=true,
["Shadowforge Flame Keeper"]=true,
["Shadowforge Geologist"]=true,
["Shadowforge Peasant"]=true,
["Shadowforge Relic Hunter"]=true,
["Shadowforge Ruffian"]=true,
["Shadowforge Senator"]=true,
["Shadowforge Sharpshooter"]=true,
["Shadowforge Surveyor"]=true,
["Shadowforge Tunneler"]=true,
["Shadowforge Warrior"]=true,
["Shadowhide Warrior"]=true,
["Shadowhorn Stag"]=true,
["Shadowmage"]=true,
["Shadowmage Vivian Lagrave"]=true,
["Shadowmaw Panther"]=true,
["Shadowpriest Sezz'ziz"]=true,
["Shadowsilk Poacher"]=true,
["Shadowy Assassin"]=true,
["Simone the Seductress"]=true,
["Skeletal Shadowcaster"]=true,
["Skeleton"]=true,
["Sky Shadow"]=true,
["Slavering Ghoul"]=true,
["Smoldar"]=true,
["Smolderthorn Shadow Hunter"]=true,
["Smolderthorn Shadow Priest"]=true,
["Soulless Ghoul"]=true,
["Spectral Deathknight"]=true,
["Spectral Horse"]=true,
["Spectral Rider"]=true,
["Spectral Trainee"]=true,
["Splinterbone Skeleton"]=true,
["Splintered Skeleton"]=true,
["Storm Shadowhoof"]=true,
["Sul'lithuz Abomination"]=true,
["Summoned Felhunter"]=true,
["Summoned Skeleton"]=true,
["Summoned Succubus"]=true,
["Summoned Voidwalker"]=true,
["Tarkreu Shadowstalker"]=true,
["Telurinon Moonshadow"]=true,
["Terrorspark"]=true,
["Terrowulf Shadow Weaver"]=true,
["The Cleaner"]=true,
["The Husk"]=true,
["The Windreaver"]=true,
["Thorn Eater Ghoul"]=true,
["Threggil"]=true,
["Thuzadin Necromancer"]=true,
["Thuzadin Shadowcaster"]=true,
["Tortured Druid"]=true,
["Tortured Sentinel"]=true,
["Tristane Shadowstone"]=true,
["Twilight Shadowmage"]=true,
["Verek"]=true,
["Verog the Dervish"]=true,
["Vicious Grell"]=true,
["Wandering Eye of Kilrogg"]=true,
["Wandering Skeleton"]=true,
["Wastewander Shadow Mage"]=true,
["Winterax Shadow Hunter"]=true,
["Yarrog Baneshadow"]=true,
["Zanzil Skeleton"]=true,
}


aal_ArcaneImmune = { -- SELECT name FROM creature_template WHERE resistance6>=400 AND maxlevel>1 ORDER BY name
["Arcane Aberration"]=true,
["Arcane Chimaerok"]=true,
["Arcane Nullifier X-21"]=true,
["Arch Druid Fandral Staghelm"]=true,
["Azuregos"]=true,
["Bronze Drakonid"]=true,
["Dessecus"]=true,
["Felcular"]=true,
["Huricanian"]=true,
["Ilifar"]=true,
["Illusion of Jandice Barov"]=true,
["Lord Roccor"]=true,
["Malfunctioning Reaver"]=true,
["Mana Burst"]=true,
["Mana Fiend"]=true,
["Mana Remnant"]=true,
["Mana Surge"]=true,
["Residual Monstrosity"]=true,
["Rift Spawn"]=true,
["Risen Aberration"]=true,
["Smoldar"]=true,
["Spectral Deathknight"]=true,
["Spectral Horse"]=true,
["Spectral Rider"]=true,
["Spectral Trainee"]=true,
["The Husk"]=true,
["The Windreaver"]=true,
}


local SpellBlockerBuffs = {
  ["Renew"] = "Spell_Holy_Renew",
  ["Rejuvenation"] = "Spell_Nature_Rejuvenation",
}
local SpellBlockerDebuffs = {
  ["Divine Shield"] = "Spell_Holy_RemoveCurse", -- Forbearance
  ["Divine Protection"] = "Spell_Holy_RemoveCurse", -- Forbearance
  ["Blessing of Protection"] = "Spell_Holy_RemoveCurse", -- Forbearance
  ["Power Word: Shield"] = "Spell_Holy_AshesToAshes", -- Weakened Soul
}

local SpellSchool = {
  -- 1: Holy
  ["Lesser Heal"]=1, ["Smite"]=1, ["Renew"]=1, ["Resurrection"]=1, ["Cure Disease"]=1, ["Heal"]=1, ["Desperate Prayer"]=1, ["Flash Heal"]=1, ["Holy Fire"]=1, ["Holy Nova"]=1, ["Prayer of Healing"]=1, ["Abolish Disease"]=1, ["Greater Heal"]=1, ["Lightwell"]=1,
  -- 2: Fire
  ["Fire Blast"]=2, ["Fireball"]=2, ["Scorch"]=2,
  -- 3: Nature
  ["Insect Swarm"]=3, ["Serpent Sting"]=3, ["Faerie Fire"]=3,
  -- 4: Frost
  ["Frostbolt"]=4,
  -- 5: Shadow
  ["Shadow Word: Pain"]=5, ["Curse of Agony"]=5, ["Corruption"]=5, ["Death Coil"]=5, ["Drain Life"]=5, ["Drain Mana"]=5, ["Mana Burn"]=5,
  -- 6: Arcane
  ["Hunter's Mark"]=6, ["Arcane Shot"]=6, ["Concussive Shot"]=6, ["Moonfire"]=6, ["Polymorph"]=6,
}


function AAL_Cast(...)
  local onSelf = false
  local chkRange = 0 -- не проверять по расстоянию
  local failure = nil -- возвращаемое значение для случая, когда ничего не найдено
  local function failure_set_false() failure = false; end -- если что-то найдено, но не применено

  for i = 1,table.getn(arg) do
    local name = arg[i]
    if name == nil then --break
    elseif type(name) == "boolean" then onSelf = name
    elseif type(name) == "number" then chkRange = name
    --elseif name == "/gcd" then if failure==false break
    else
      -- Односимвольный префикс .*-$ категории энергии, например в AAL_Cast(".20 Frostbolt")
      local prefix = string.sub(name,1,1)
      if prefix < "0" then name = string.sub(name,2); end

      -- Число перед названием действия исключает его применение если
      -- мана/ярость/энергия/жизнь меньше заданной величины
      local reqPercent
      local p1, p2 = string.find(name, "^%d+ +")
      if p1 ~= nil then
         reqPercent = tonumber(string.sub(name,p1,p2))
         name = string.sub(name, p2+1)
      end

      local basename = name
      if string.sub(name,-8,-3) == "(Rank " then basename = string.sub(name,1,-9); end

      local index
      local actionSlot
      local firstchr = string.sub(name,1,1)
      if firstchr >= '0' and firstchr <= '9' then -- номер слота, например AAL_Cast("8")
         actionSlot = tonumber(name)
      else
         index = aal_Abilities[ name ]
         actionSlot = aal_AbiSlots[ name ]
      end

      local function notInRange()
        local slotB = aal_AbiSlots[ basename ]
        return slotB and IsActionInRange(slotB) == 0
      end

      local function notEnoughPower(hardmin, pwt, isPwtRequired)
        if reqPercent == nil and actionSlot ~= nil then return false; end
        if UnitPowerType("player") ~= pwt then
           if actionSlot ~= nil then return false; end
           return isPwtRequired
        end
        local m = UnitMana("player")
        if reqPercent == nil --[[and actionSlot == nil]] then return m < hardmin; end
        return m < reqPercent * UnitManaMax("player") / 100
      end

      if index == nil and actionSlot == nil then
         --print("AAL_Cast: not found", name)
      elseif failure_set_false() then
      elseif actionSlot ~= nil and not IsUsableAction(actionSlot) then
         -- IsUsableAction() проверяет ману, но не CD и не расстояние
         --print("AAL_Cast: not usable", name)
      elseif notInRange() then
         -- Полагаем, что расстояние одинаково для всех Rank'ов
         --print("AAL_Cast: not in range", basename)
      elseif chkRange > 0 and not CheckInteractDistance("target", chkRange)    -- AAL_Cast(3, ...)  можно, если цель ближе 10 ярдов
          or chkRange < 0 and CheckInteractDistance("target", -chkRange) then  -- AAL_Cast(-3, ...) можно, если цель дальше 10 ярдов
         --print("AAL_Cast: too far or too close", name)

      elseif prefix == "." and notEnoughPower(10, 0, true) then  -- mana
      elseif prefix == "*" and notEnoughPower(10, 1, true) then  -- rage
      elseif prefix == "-" and notEnoughPower(25, 3, false) then -- energy
      elseif prefix == "$" and UnitHealth("player")*100 / UnitHealthMax("player") < reqPercent then -- health

      elseif index == nil then
         local _, duration = GetActionCooldown(actionSlot)
         local tname = UnitName("target")
         if duration <= 0
            and not (tname and (
             actionSlot == AAL_ASL_STING and aal_NatureImmune[tname] or
             actionSlot == AAL_ASL_CURSE and aal_ShadowImmune[tname]
             )) then
            UseAction(actionSlot)
            return i
         end
      else

         if index > 0 then
            local _, duration = GetSpellCooldown(index, BOOKTYPE_SPELL)
            local t = "target"
            if onSelf or not UnitExists(t) then t = "player"; end
            local school = SpellSchool[ basename ];
            if duration <= 0
               and not AAL_IsBuff( t, SpellBlockerBuffs[basename] )
               and not AAL_IsDebuff( t, SpellBlockerDebuffs[basename])
               and not (prefix=="." and AAL_IsDebuff("player", --[[Silenced]] "Spell_Fire_SoulBurn","Spell_Holy_Silence","Spell_Shadow_Teleport"--[[,"Spell_Shadow_ImpPhaseShift"]],"INV_Misc_Dust_02"--[[Sandtrap]]))
               and not (school==1 and AAL_IsActiveSpell("Shadowform"))
               and not (school==2 and aal_FireImmune  [ UnitName(t) ])
               and not (school==3 and aal_NatureImmune[ UnitName(t) ])
               and not (school==4 and aal_FrostImmune [ UnitName(t) ])
               and not (school==5 and aal_ShadowImmune[ UnitName(t) ])
               and not (school==6 and aal_ArcaneImmune[ UnitName(t) ])
               then
               --print("AAL_Cast: cast", name)
               --AAL_TrapErrors()

               if string.find(name, " (", 1,true) then CastSpell(index, BOOKTYPE_SPELL) -- в WoW 1.12 CastSpellByName не работает корректно для названий вроде "Create Soulstone (Minor)"
               else CastSpellByName(name, onSelf)
               end
               --if SpellIsTargeting() and SpellCanTargetUnit("player") then SpellTargetUnit("player"); end

               --if aal_ErrorMsg ~= ERR_OUT_OF_MANA and aal_ErrorMsg ~= ERR_OUT_OF_ENERGY and aal_ErrorMsg ~= ERR_OUT_OF_RAGE then
                  --AAL_UntrapErrors()
                  return i
               --end
               --AAL_ShowErrorMsg()
               --AAL_UntrapErrors()
            end
         elseif index > -1000 then
            index = -index
            local start = GetInventoryItemCooldown("player", index)
            if start == 0 then
               UseInventoryItem(index)
               return i
            end
         else
            local bagID = math.floor((-index-1000)/100)
            index = math.mod(-index, 100)
            local start = GetContainerItemCooldown(bagID, index)
            if start == 0 then
               local _,_,_,reqLevel = AAL_GetContainerItem(bagID, index)
               if reqLevel~=nil and reqLevel <= UnitLevel("player") then
                  UseContainerItem(bagID, index, onSelf)
                  return i
               end
            end
         end
      end
    end
  end
  return failure
end



function AAL_PetCast(...)
  for k = 1,table.getn(arg) do
    local name = arg[k]
    local iFound

    for i = 1, 5000 do
      local spell, rank = GetSpellName(i, BOOKTYPE_PET)
      if spell == nil then break end

      if iFound ~= nil and spell ~= name then
         -- Предполагается, что rank'и идут подряд и последний по порядку будет самым высоким
         break
      end
      if not IsSpellPassive(i, BOOKTYPE_PET) then
         local ranked
         if rank and rank ~= "" then ranked = spell.."("..rank..")" end

         if (ranked == nil and name == spell) or name == ranked then
            iFound = i
            break
         end
         if name == spell then iFound = i; end
      end
    end

    if iFound ~= nil then
       local _, duration = GetSpellCooldown(iFound, BOOKTYPE_PET)
       --print("AAL_PetCast Found:", "#"..k, name, "["..iFound.."]", duration)
       if duration <= 0 then
          -- AAL_TrapErrors() -- не получается таким способом перехватывать ошибки действий Pet'а
          CastSpell(iFound, BOOKTYPE_PET)
          -- if aal_ErrorMsg == nil then 
             -- AAL_UntrapErrors()
             return k
          -- end
          --  print("AAL_PetCast: Error Trapped!");
          -- AAL_UntrapErrors()
       end
    end
  end
  return nil
end

function AAL_GetPetAction(name)
  for i = 1, 5000 do
    local r = {GetPetActionInfo(i)}
    if r[1] == nil then break end
    if r[1] == name then return i, r[1],r[2],r[3],r[4],r[5],r[6],r[7] end
  end
  return nil
end


function AAL_Actions(...)
  -- NB: Перехват PlaySound для запрета звук.эффекта не помогает, так же,
  -- как и SetCVar("SoundVolume","0"), поскольку эффект всё равно
  -- начинает воспроизводиться (с нулевой громкостью)
  local slot = 1
  for i = 1,table.getn(arg) do
    local name = arg[i]
    if name == nil then break end
    if type(name) ~= "string" then
       slot = name
    elseif string.sub(name,1,1) == "?" and (GetActionTexture(slot) ~= nil or string.sub(name,2,2) < "A" or string.sub(name,2,2) > "Z") then
       -- место будет сохранять то, что поставил пользователь
       slot = slot + 1
    else
      if string.sub(name,1,1) == "?" then name = string.sub(name,2); end
      local index
      local sepPos
      repeat
        sepPos = string.find(name, "/", 1, true)
        if sepPos == nil then
           index = aal_Abilities[ name ]
        else
           local head = string.sub(name, 1, sepPos-1)
           index = aal_Abilities[ head ]
           if index ~= nil then name = head
           else name = string.sub(name, sepPos+1) -- tail, проверять дальше
           end
        end
      until index ~= nil or sepPos == nil

      if index == nil then
         --if name ~= "" then print("AAL_Actions: not found", name); end
         -- сделать место пустым
         PickupAction(slot)
         slot = slot + 1
         ClearCursor()
      else
         --print("AAL_Actions: found", name)
         if index > 0 then
            PickupSpell(index, BOOKTYPE_SPELL)
         elseif index > -1000 then
            PickupInventoryItem(-index)
         else
            local bagID = math.floor((-index-1000)/100)
            index = math.mod(-index, 100)
            PickupContainerItem(bagID, index)
         end
         PlaceAction(slot)
         if aal_AbiSlots[name] == nil then
            -- слоты 97..108 могут меняться при shapeshift
            -- TODO: здесь надо бы искать old_name исходя из slot: aal_AbiSlots[old_name] = nil
            aal_AbiSlots[name] = slot
            if string.sub(name,-6)==" Sting" then
               aal_AbiSlots["Serpent Sting"] = slot
               aal_AbiSlots["Scorpid Sting"] = slot
               aal_AbiSlots["Viper Sting"] = slot
               aal_AbiSlots["Wyvern Sting"] = slot
            end
         end
         slot = slot + 1
         ClearCursor()
      end
    end
  end
end


function AAL_Macro(name, body, slot)
  local index = GetMacroIndexByName(name)
  if index < 1 then
     -- local numglobal,numperchar = GetNumMacros();
     index = CreateMacro(name, 188--[[numglobal+1]], body, 1, 0)
  else
     EditMacro(index, name, 188--[[index]], body, 1, 0)
  end
  if slot then
     PickupMacro(index)
     PlaceAction(slot)
     aal_AbiSlots[name] = slot
  end
end


local function EventHandler()
  --print("Event:", event, arg1)
  if not this.EventInitOnce and event == "UPDATE_TICKET" then
     AAL_ScanInventory()
     AAL_ScanBag(0)
     AAL_ScanBag(1)
     AAL_ScanBag(2)
     AAL_ScanBag(3)
     AAL_ScanBag(4)
     AAL_ScanSpells()
     this:RegisterEvent("AUCTION_HOUSE_SHOW")
     this:RegisterEvent("SPELLS_CHANGED")
     this:RegisterEvent("BAG_UPDATE")
     this:RegisterEvent("UNIT_INVENTORY_CHANGED")
     this:RegisterEvent("UNIT_MODEL_CHANGED")
     -- this:RegisterEvent("UNIT_MANA") -- для проверки регенерации маны
     this.EventInitOnce = true

     AAL_LoadActions(true)

     -- Чтобы запускать макросы в WoW 1.12, их надо помещать в слоты действий
     -- WoW 1.12 поддерживает 120 слотов действий, но использует только 1..108
     AAL_Macro("MACRO Speed3", ".modify aspeed 3", 120)
     AAL_Macro("MACRO Speed1", ".modify aspeed 1", 119)
     AAL_Macro("MACRO GM On", ".gm on", 118)
     AAL_Macro("MACRO GM Off", ".gm off", 117)
     AAL_Macro("MACRO Kill", ".die", 116)
     AAL_Macro("MACRO Respawn", ".respawn", 115)
     AAL_Macro("MACRO Cooldown", ".cooldown", 114)

  elseif event == "AUCTION_HOUSE_SHOW" then
     -- Меняет цену по умолчанию на аукционе на 1/2 цены продажи торговцам и убирает депозит
     -- Подразумеваеся:
     -- 1) однопользовательская игра с аукционом в режиме склада (Warehouse)
     -- 2) работает Blizzard_AuctionUI.lua
     CalculateAuctionDeposit = function() return 0; end

     AuctionSellItemButton_OnEvent = function()
       if event == "NEW_AUCTION_UPDATE" then
           local name, texture, count, quality, canUse, price = GetAuctionSellItemInfo();
           AuctionsItemButton:SetNormalTexture(texture);
           AuctionsItemButtonName:SetText(name);
           if ( count > 1 ) then
               AuctionsItemButtonCount:SetText(count);
               AuctionsItemButtonCount:Show();
           else
               AuctionsItemButtonCount:Hide();
           end
           if AuctionFrameAuctions.duration == 120 then price = 10;
           elseif AuctionFrameAuctions.duration == 1440 then price = floor(price / 4);
           else price = floor(price * 0.5);
           end
           MoneyInputFrame_SetCopper(StartPrice, price);
           UpdateDeposit();
           MoneyInputFrame_SetCopper(BuyoutPrice, 0);
       end
     end

  elseif event == "SPELLS_CHANGED" then
     -- вызывается при Login, при листании книги умений, при смене оружия (другая иконка Attack)
     AAL_ScanSpells()
  elseif event == "BAG_UPDATE" and arg1 >= 0 and arg1 <= 4 then
     AAL_ScanBag(arg1)
  elseif event == "UNIT_INVENTORY_CHANGED" then
     AAL_ScanInventory()
  elseif event == "UNIT_MODEL_CHANGED" and arg1 == "player" then
     AAL_LoadActions(false)
  elseif event == "UNIT_MANA" and arg1 == "player" then
     local newMana = UnitMana(arg1)
     local newTime = GetTime()
     if aal_oldMana ~= nil then
        print("Mana_diff ", newMana - aal_oldMana,"in", newTime - aal_oldTime, "sec")
     end
     aal_oldMana = newMana
     aal_oldTime = newTime
  end
end


-- Быстрый поиск по названию в многостраничной книге умений мультиклассового персонажа
-- и управление опциями автоматических действий из "командной строки"

function AAL_SlashSB(msg)
  while true do
    local _, _, opt, val, tail = string.find(msg, "^ *(%a+)([+-]?) *(.*)")
    val = (val ~= "-")

    if     opt == "mr" then aalcfg.magres  = val
    elseif opt == "nb" then aalcfg.noblock = val
    elseif opt == "nc" then aalcfg.nocleave= val
    elseif opt == "nd" then aalcfg.nodrink = val
    else break
    end
    msg = tail
  end

  if msg == "" then
     print("/b: Opens Spellbook at specific spell name, e.g. /b Seal of")
     print("     opts  magres:", aalcfg.magres and "mr+" or "mr-",
      " noblock:", aalcfg.noblock and "nb+" or "nb-",
      " nocleave:", aalcfg.nocleave and "nc+" or "nc-",
      " nodrink:", aalcfg.nodrink and "nd+" or "nd-")
     return
  end

  local k = aal_Abilities[msg]
  if k and k > 0 then -- точное соответствие
  else
     msg = string.lower(msg)
     k = nil
     local pos_k = 9999
     for i = 1, 5000 do
       local spell, rank = GetSpellName(i, BOOKTYPE_SPELL)
       if not spell then break end
       local pos = string.find(string.lower(spell.." "..rank), msg, 1,true)
       if pos and pos < pos_k then
          pos_k = pos
          k = i -- найдена подстрока; выбирается вариант, где она ближе к началу названия
       end
     end
  end
  if not k then print("/b: the Spellbook has no spell \""..msg.."\""); return end
  for tab=1, 100 do
    local tabname,_,i,nSpells = GetSpellTabInfo(tab)
    if not tabname then break end
    if k <= i + nSpells then
       local page = ceil((k-i)/SPELLS_PER_PAGE)
       SpellBookFrame.bookType = BOOKTYPE_SPELL
       SpellBookSkillLineTab_OnClick(tab)
       SPELLBOOK_PAGENUMBERS[tab] = page
       if SpellBookFrame:IsVisible() then SpellBookFrame_Update(1)
       else ToggleSpellBook( SpellBookFrame.bookType )
       end
       break
    end
  end
end


-- ONLOAD CODE

SlashCmdList["AALsb"] = AAL_SlashSB;
SLASH_AALsb1 = "/b";

GAR_LOOK_DEG = 0
SetConsoleKey("NUMLOCK")
ChatFrameEditBox:SetAltArrowKeyMode(false)

-- ассоциативный массив "имя" --> число >0 spell, <0 снаряжение, <-1000 вещи в сумках
-- даёт возможность быстро проверить наличие действия и индекс доступа
aal_Abilities = {}
aal_AbiSlots = {}

local f = CreateFrame("Frame") --, "aal_fMain", UIParent)
f.EventInitOnce = nil
f:RegisterEvent("UPDATE_TICKET")
f:SetScript("OnEvent", EventHandler)

