//
Name | Type | is_array | initial_value |
library StartGame initializer Init requires UserInterface
globals
Camera array PlayerCamera
unit array PlayerHero
endglobals
private function Init takes nothing returns nothing
local integer i = 0
local integer array urace
local User user
set urace[1] = 'Hpal'
set urace[2] = 'Obla'
set urace[3] = 'Ulic'
set urace[4] = 'Edem'
call FogEnable(false)
call FogMaskEnable(false)
loop
exitwhen i == User.AmountPlaying
set user = User.fromPlaying(i)
set PlayerCamera[user.id] = Camera.create()
// create hero
set PlayerHero[user.id] = CreateUnitAtLoc(user.handle, urace[GetHandleId(GetPlayerRace(user.handle))], GetStartLocationLoc(GetPlayerStartLocation(user.handle)), 180)
//call ShowUnit(PlayerHero[user.id], false)
// get vision from dummy player
call SetPlayerAllianceStateBJ(CAMERA_DUMMY_PLAYER, user.handle, bj_ALLIANCE_ALLIED_VISION)
call SetPlayerAllianceStateBJ(user.handle, CAMERA_DUMMY_PLAYER, bj_ALLIANCE_ALLIED_VISION)
if (User.Local == user.handle) then
call ClearSelection()
call SelectUnit(PlayerHero[user.id], true)
endif
set i = i + 1
endloop
endfunction
endlibrary
library ItemDatabase initializer InventoryInitDB
globals
private hashtable gcbag
private integer TypeTextureBlank = 'dbnk'
endglobals
function GetItemTexture takes integer typeitem returns integer
//local string hi = I2S(typeitem)
local integer hi = typeitem
local string tex
if HaveSavedString(gcbag, StringHash("Texture"), hi) then
set tex = LoadStr(gcbag, StringHash("Texture"), hi)
if HaveSavedInteger(gcbag, StringHash("IconDest"), StringHash(tex)) then
return LoadInteger(gcbag, StringHash("IconDest"), StringHash(tex))
endif
endif
return TypeTextureBlank
endfunction
function GetItemCost takes integer typeitem returns integer
//local string hi = I2S(typeitem)
local integer hi = typeitem
if HaveSavedInteger(gcbag, StringHash("Cost"), hi) then
return LoadInteger(gcbag, StringHash("Cost"), hi)
endif
return -1
endfunction
function GetItemDescription takes integer typeitem returns string
//local string hi = I2S(typeitem)
local integer hi = typeitem
if HaveSavedString(gcbag, StringHash("Description"), hi) then
return LoadStr(gcbag, StringHash("Description"), hi)
endif
return null
endfunction
function GetItemHasCharges takes integer typeitem returns boolean
//local string hi = I2S(typeitem)
local integer hi = typeitem
if HaveSavedBoolean(gcbag, StringHash("Charge"), hi) then
return LoadBoolean(gcbag, StringHash("Charge"), hi)
endif
return false
endfunction
function InventoryInitItemDB_Func takes integer ItemType, string Texture, string Description, integer Cost, boolean Charge returns nothing
//local string ItemTypeStr = I2S(ItemType)
local integer ItemTypeStr = ItemType
call SaveStr(gcbag, StringHash("Texture"), ItemTypeStr, Texture)
call SaveStr(gcbag, StringHash("Description"), ItemTypeStr, Description)
call SaveInteger(gcbag, StringHash("Cost"), ItemTypeStr, Cost)
call SaveBoolean(gcbag, StringHash("Charge"), ItemTypeStr, Charge)
endfunction
function InventoryInitDestDB_Func takes integer TypeDest, string Texture returns nothing
call SaveInteger(gcbag, StringHash("IconDest"), StringHash(Texture), TypeDest)
endfunction
function InventoryInitIconDB_Func takes integer TypeUnit, string Texture returns nothing
call SaveStr(gcbag, StringHash("Texture"), TypeUnit, Texture)
endfunction
private function InventoryInitDB takes nothing returns nothing
set gcbag = InitHashtable()
//---------------------------------------------------------------------------------------------------+
// |
// Item |
// |
//---------------------------------------------------------------------------------------------------+
//__________
call InventoryInitItemDB_Func('afac', "BTNAlleriaFlute.blp" , "Increases nearby ranged units' damage by <AIar,DataA1,%>%. |nDoes not stack with Trueshot Aura.", 400, false)
call InventoryInitItemDB_Func('spsh', "BTNSpellShieldAmulet.blp", "Blocks a negative spell that an enemy casts on the Hero once every <ANss,Cool1> seconds.", 400, false)
call InventoryInitItemDB_Func('ajen', "BTNJanggo.blp" , "Grants the Hero and friendly nearby units increased attack rate and movement speed. |nDoes not stack with Endurance Aura.", 500, false)
call InventoryInitItemDB_Func('bgst', "BTNBelt.blp" , "Increases the Strength of the Hero by 6 when worn.", 500, false)
call InventoryInitItemDB_Func('belv', "BTNBoots.blp" , "Increases the Agility of the Hero by 6 when worn.", 500, false)
call InventoryInitItemDB_Func('bspd', "BTNBootsOfSpeed.blp" , "Increases the movement speed of the Hero when worn.", 150, false)
call InventoryInitItemDB_Func('cnob', "BTNCirclet.blp" , "Increases the Strength, Agility and Intelligence of the Hero by 2 when worn.", 175, false)
call InventoryInitItemDB_Func('ratc', "BTNClawsOfAttack.blp" , "Increases the attack damage of the Hero by 12 when worn.", 500, false)
call InventoryInitItemDB_Func('rat6', "BTNClawsOfAttack.blp" , "Increases the attack damage of the Hero by 6 when worn.", 100, false)
call InventoryInitItemDB_Func('rat9', "BTNClawsOfAttack.blp" , "Increases the attack damage of the Hero by 9 when worn.", 400, false)
call InventoryInitItemDB_Func('clfm', "BTNCloakOfFlames.blp" , "Engulfs the Hero in fire which deals <AIcf,DataA1> damage per second to nearby enemy land units. |nDoes not stack with Immolation.", 600, false)
call InventoryInitItemDB_Func('clsd', "BTNCloak.blp" , "Provides the Hero with invisibility at night when worn. An invisible Hero is untargetable by the enemy unless detected. If the Hero moves, attacks, uses an ability, or casts a spell, the invisibility effect is lost.", 100, false)
call InventoryInitItemDB_Func('crys', "BTNCrystalBall.blp" , "Reveals a targeted area. Invisible units are also revealed by the Crystal Ball's effect. |nLasts <AIta,Dur1> seconds.", 500, false)
call InventoryInitItemDB_Func('dsum', "BTNDarkSummoning.blp" , "Teleports <AUds,DataA1> of the player's units within the targeted area to the location of the Hero when used.", 400, false)
call InventoryInitItemDB_Func('lgdh', "BTNHornOfDoom.blp" , "Grants the Hero and friendly nearby units increased life regeneration and movement speed. |nDoes not stack with Unholy Aura.", 400, false)
call InventoryInitItemDB_Func('hval', "BTNHelmOfValor.blp" , "Increases the Strength and Agility of the Hero by 4 when worn.", 500, false)
call InventoryInitItemDB_Func('rst1', "BTNGauntletsOfOgrePower.blp", "Increases the Strength of the Hero by 3 when worn.", 100, false)
call InventoryInitItemDB_Func('gcel', "BTNGlove.blp" , "Increases the attack speed of the Hero by <AIsx,DataA1,%>% when worn.", 100, false)
call InventoryInitItemDB_Func('hcun', "BTNHoodOfCunning.blp" , "Increases the Agility and Intelligence of the Hero by 4 when worn.", 500, false)
call InventoryInitItemDB_Func('rhth', "BTNPeriapt1.blp" , "Increases the hit points of the Hero by <AIl2,DataA1> when worn.", 500, false)
call InventoryInitItemDB_Func('kpin', "BTNPipeOfInsight.blp" , "Grants the Hero and friendly nearby units a bonus to mana regeneration. |nDoes not stack with Brilliance Aura.", 500, false)
call InventoryInitItemDB_Func('rin1', "BTNMantleOfIntelligence.blp", "Increases the Intelligence of the Hero by 3 when worn.", 100, false)
call InventoryInitItemDB_Func('mcou', "BTNMedalionOfCourage.blp", "Increases the Strength and Intelligence of the Hero by 4 when worn.", 500, false)
call InventoryInitItemDB_Func('odef', "BTNOrbOfDarkness.blp" , "Adds <AIdf,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attack also becomes ranged when attacking air and will create a Dark Minion when it is the killing blow on an enemy unit. The Dark Minion lasts <ANbs,DataC1> seconds.", 500, false)
call InventoryInitItemDB_Func('penr', "BTNPendantOfEnergy.blp" , "Increases the mana capacity of the Hero by <AImb,DataA1> when worn.", 400 , false)
call InventoryInitItemDB_Func('pmna', "BTNPendantOfMana.blp" , "Increases the mana capacity of the Hero by <AIbm,DataA1> when worn.", 500, false)
call InventoryInitItemDB_Func('prvt', "BTNPeriapt.blp" , "Increases the hit points of the Hero by <AIlf,DataA1> when worn.", 350, false)
call InventoryInitItemDB_Func('rde1', "BTNRingGreen.blp" , "Increases the armor of the Hero by 2 when worn.", 150, false)
call InventoryInitItemDB_Func('rde2', "BTNRingGreen.blp" , "Increases the armor of the Hero by 3 when worn.", 400, false)
call InventoryInitItemDB_Func('rde3', "BTNRingGreen.blp" , "Increases the armor of the Hero by 4 when worn.", 500, false)
call InventoryInitItemDB_Func('rlif', "BTNRingSkull.blp" , "Increases the Hero's hit point regeneration by <Arel,DataA1> hit points per second.", 200, false)
call InventoryInitItemDB_Func('ciri', "BTNRobeOfTheMagi.blp" , "Increases the Intelligence of the Hero by 6 when worn.", 500, false)
call InventoryInitItemDB_Func('brac', "BTNRunedBracers.blp" , "Reduces Magic damage dealt to the Hero by <AIsr,DataB1,%>%.", 400, false)
call InventoryInitItemDB_Func('sbch', "BTNBoneChimes.blp" , "Grants a melee Hero and friendly nearby melee units life stealing attacks which take <AIav,DataA1,%>% of the damage they deal and convert it into life. |nDoes not stack with Vampiric Aura.", 450, false)
call InventoryInitItemDB_Func('rag1', "BTNSlippersOfAgility.blp", "Increases the Agility of the Hero by 3 when worn.", 100, false)
call InventoryInitItemDB_Func('rwiz', "BTNSobiMask.blp" , "Increases the Hero's rate of mana regeneration by <AIrm,DataA1,%>% when worn.", 400, false)
call InventoryInitItemDB_Func('ssil', "BTNStaffOfSilence.blp" , "Stops all enemies in a target area from casting spells.", 500, false)
call InventoryInitItemDB_Func('stel', "BTNStaffOfTeleportation.blp", "Teleports the Hero to the targeted allied land unit or structure.", 100, false)
call InventoryInitItemDB_Func('evtl', "BTNTalisman.blp" , "Causes attacks against the wearer to miss <AIev,DataA1,%>% of the time. |nDoes not stack with Evasion or Drunken Brawler.", 400, false)
call InventoryInitItemDB_Func('lhst', "BTNLionHorn.blp" , "Grants the Hero and friendly nearby units <AIad,DataA1> bonus armor. |nDoes not stack with Devotion Aura.", 400, false)
call InventoryInitItemDB_Func('ward', "BTNDrum.blp" , "Increases the attack damage of nearby friendly units by <AIcd,DataA1,%>% when worn. |nDoes not stack with Command Aura.", 500, false)
//_______ ______
call InventoryInitItemDB_Func('wild', "BTNAmuletOftheWild.blp" , "Summons a Furbolg Warrior. The Furbolg lasts <AIuw,Dur1> seconds.", 750, true)
call InventoryInitItemDB_Func('ankh', "BTNAnkh.blp" , "Automatically brings the Hero back to life with <AIrc,DataB1> hit points when the Hero wearing the Ankh dies.", 800, true)
call InventoryInitItemDB_Func('fgsk', "BTNBookOfTheDead.blp" , "Summons <AIfs,DataA1> Skeleton Warriors and <AIfs,DataB1> Skeleton Archers to fight for you. |nLasts <AIfs,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('fgdg', "BTNDoomGuard.blp" , "Summons a Doom Guard to fight for you. |nLasts <AIfu,Dur1> seconds.", 750, true)
call InventoryInitItemDB_Func('whwd', "BTNHealingWard.blp" , "Drops a ward that heals nearby friendly units for <Ahwd,Dur1> seconds. |nContains <whwd,uses> charges.", 600, true)
call InventoryInitItemDB_Func('hlst', "BTNHealthStone.blp" , "Increases the life regeneration rate of the Hero by <Arll,DataA1> hit points per second when worn. Can be consumed for <AIh2,DataA1> health.", 450, true)
call InventoryInitItemDB_Func('shar', "BTNIceShard.blp" , "Summons an Ice Revenant. The Ice Revenant lasts <AIir,Dur1> seconds.", 750, true)
call InventoryInitItemDB_Func('infs', "BTNInfernalStone.blp" , "Calls an Infernal down from the sky, dealing <AIin,DataA1> damage and stunning enemy land units for <AIin,Dur1> seconds in an area. The Infernal lasts <AIin,DataB1> seconds.", 750, true)
call InventoryInitItemDB_Func('mnst', "BTNManaStone.blp" , "Increases the mana regeneration rate of the Hero by <AIrn,DataA1,%>% when worn. Can be consumed for <AIm2,DataA1> mana.", 450, true)
call InventoryInitItemDB_Func('pdiv', "BTNPotionOfDivinity.blp" , "Turns the Hero invulnerable for <AIdv,Dur1> seconds.", 600, true)
call InventoryInitItemDB_Func('pghe', "BTNPotionGreen.blp" , "Heals <AIh2,DataA1> hit points when used.", 400, true)
call InventoryInitItemDB_Func('pgma', "BTNPotionBlueBig.blp" , "Restores <AIm2,DataA1> mana when used.", 400, true)
call InventoryInitItemDB_Func('pnvu', "BTNGreaterInvulneralbility.blp", "Makes the Hero invulnerable to damage for <AIvu,Dur1> seconds when used. An invulnerable Hero may not be the target of spells or effects.", 400, true)
call InventoryInitItemDB_Func('pomn', "BTNPotionOfOmniscience.blp", "Reveals the entire map for <AIrv,Dur1> seconds when used.", 400, true)
call InventoryInitItemDB_Func('pres', "BTNPotionOfRestoration.blp", "Restores <AIre,DataA1> hit points and <AIre,DataB1> mana of the Hero when used.", 600, true)
call InventoryInitItemDB_Func('fgrd', "BTNRedDragon.blp" , "Summons a Red Drake to fight for you. |nLasts <AIfd,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('rej3', "BTNRejuvPotion.blp" , "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp3,DataA1> hit points and <AIp3,DataB1> mana of the Hero over <AIp3,Dur1> seconds.", 400, true)
call InventoryInitItemDB_Func('sand', "BTNSnazzyScrollPurple.blp", "Raises <AIan,DataA1> nearby dead units to fight for <AIan,Dur1> seconds.", 750, true)
call InventoryInitItemDB_Func('sres', "BTNScrollOfHealing.blp" , "Restores <AIra,DataA1> hit points and <AIra,DataB1> mana of friendly non-mechanical units in an area around your Hero.", 750, true)
call InventoryInitItemDB_Func('srrc', "BTNSnazzyScroll.blp" , "Brings <AIrs,DataA1> of your nearby dead units back to life.", 750, true)
call InventoryInitItemDB_Func('sror', "BTNSnazzyScrollGreen.blp", "Gives friendly nearby units a <AIrr,DataA1,%>% bonus to damage for <AIrr,Dur1> seconds.", 400, true)
call InventoryInitItemDB_Func('wswd', "BTNSentryWard.blp" , "Drops a Sentry Ward to spy upon an area for <AIsw,Dur1> seconds. |nContains <wswd,uses> charges.", 150, true)
call InventoryInitItemDB_Func('fgfh', "BTNFelHound.blp" , "Summons a Fel Stalker to fight for you. |nLasts <AIfh,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('fgrg', "BTNRockGolem.blp" , "Summons a Rock Golem to fight for you. |nLasts <AIfr,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('totw', "BTNStone.blp" , "This mystic stone summons a Furbolg to fight for you. |nContains <totw,uses> charges. |nLasts <AIff,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('will', "BTNWand.blp" , "Create an illusory double of the targeted unit when used. The illusory double deals no damage to enemy units, takes <AIil,DataB1> times the damage from enemy attacks, and will disappear after <AIil,Dur1> seconds or when its hit points reach zero. |nContains <will,uses> charges.", 150, true)
call InventoryInitItemDB_Func('wlsd', "BTNStarWand.blp" , "Allows the Hero to cast Lightning Shield on a target unit. Lightning Shield surrounds a unit with electricity, dealing <AIls,DataA1> damage per second to nearby units. |nContains <wlsd,uses> charges. |nLasts <AIls,Dur1> seconds.", 150, true)
call InventoryInitItemDB_Func('woms', "BTNWandOfManaSteal.blp" , "Steals mana from a target unit and gives it to the Hero. |nContains <woms,uses> charges.", 400, true)
call InventoryInitItemDB_Func('wshs', "BTNWandOfShadowSight.blp", "Gives the player vision of a target unit until that unit is dispelled. |nContains <wshs,uses> charges.", 150, true)
call InventoryInitItemDB_Func('wcyc', "BTNWandOfCyclone.blp" , "Allows the Hero to cast Cyclone. Cyclone tosses a target enemy unit into the air, rendering it unable to attack, move or cast spells. |nContains <wcyc,uses> charges. |nLasts <AIcy,Dur1> seconds.", 450, true)
//___________
//_________
call InventoryInitItemDB_Func('ratf', "BTNClawsOfAttack.blp" , "Increases the attack damage of the Hero by 15 when worn.", 800, false)
call InventoryInitItemDB_Func('ckng', "BTNHelmutPurple.blp" , "Increases the Strength, Intelligence, and Agility of the Hero by 5 when worn.", 1000, false)
call InventoryInitItemDB_Func('desc', "BTNDaggerOfEscape.blp" , "Allows the Hero to teleport a short distance.", 400, false)
call InventoryInitItemDB_Func('modt', "BTNMaskOfDeath.blp" , "While wearing this mask, a Hero will recover hit points equal to <AIva,DataA1,%>% of the attack damage dealt to an enemy unit.", 1000, false)
call InventoryInitItemDB_Func('ofro', "BTNOrbOfFrost.blp" , "Adds <AIob,DataA1> bonus cold damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air and slow the movement speed and attack rate of the enemy for <AIob,Dur1> seconds.", 800, false)
call InventoryInitItemDB_Func('rde4', "BTNRingGreen.blp" , "Increases the armor of the Hero by 5 when worn.", 800, false)
call InventoryInitItemDB_Func('tkno', "BTNTomeRed.blp" , "Increases the level of the Hero by <AIlm,DataA1> when used.", 1200, false)
//__________ _______
call InventoryInitItemDB_Func('pclr', "BTNPotionOfClarity.blp" , "|cff87ceebNon-Combat Consumable|r|nRegenerates the Hero's mana by <AIpr,DataB1> over <AIpr,Dur1> seconds when used.", 160, true)
call InventoryInitItemDB_Func('hslv', "BTNHealingSalve.blp" , "|cff87ceebNon-Combat Consumable|r|nRegenerates a target unit's hit points by <AIrl,DataA1> over <AIrl,Dur1> seconds when used. |nContains <hslv,uses> charges.", 100, true)
call InventoryInitItemDB_Func('tsct', "BTNHumanWatchTower.blp" , "Creates a Scout Tower at a target location.", 30, true)
call InventoryInitItemDB_Func('plcl', "BTNLesserClarityPotion.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates the Hero's mana by <AIpl,DataB1> over <AIpl,Dur1> seconds when used.", 70, true)
call InventoryInitItemDB_Func('mcri', "BTNMechanicalCritter.blp", "Creates a player-controlled critter that can be used to scout enemies.", 50, true)
call InventoryInitItemDB_Func('moon', "BTNMoonStone.blp" , "Causes an eclipse that blocks out the sun and creates an artificial night. |nLasts <AIct,Dur1> seconds.", 50, true)
call InventoryInitItemDB_Func('phea', "BTNPotionGreenSmall.blp" , "Heals <AIh1,DataA1> hit points when used.", 150, true)
call InventoryInitItemDB_Func('pinv', "BTNLesserInvisibility.blp", "|cff87ceebNon-Combat Consumable|r|nRenders the Hero invisible for <AIv1,Dur1> seconds when used. An invisible Hero is untargetable by the enemy unless detected. If the Hero attacks, uses an ability, or casts a spell, the invisibility effect is lost.", 100, true)
call InventoryInitItemDB_Func('pnvl', "BTNLesserInvulneralbility.blp", "Makes the Hero invulnerable to damage for <AIvl,Dur1> seconds when used. An invulnerable Hero may not be the target of spells or effects.", 150, true)
call InventoryInitItemDB_Func('rnec', "BTNRodOfNecromancy.blp" , "Creates two Skeleton Warriors from a corpse. |nContains <rnec,uses> charges.", 150, true)
call InventoryInitItemDB_Func('pman', "BTNPotionBlueSmall.blp" , "Restores <AIm1,DataA1> mana when used.", 200, true)
call InventoryInitItemDB_Func('skul', "BTNSacrificialSkull.blp" , "Creates an area of Blight at a target location.", 50, true)
call InventoryInitItemDB_Func('shea', "BTNScrollOfTownPortal.blp", "Heals <AIha,DataA1> hit points to all friendly non-mechanical units around the Hero when used.", 250, true)
call InventoryInitItemDB_Func('sman', "BTNScrollOfProtection.blp", "Restores <AImr,DataA1> mana to all friendly units in an area around your Hero.", 150, true)
call InventoryInitItemDB_Func('spro', "BTNScroll.blp" , "Increases the armor of all friendly units in an area around your Hero by <AIda,DataA1> for <AIda,Dur1> seconds.", 150, true)
call InventoryInitItemDB_Func('sreg', "BTNScrollOfRegenerationGreen.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates the hit points of all friendly non-mechanical units in an area around your Hero by <AIsl,DataA1> over <AIsl,Dur1> seconds when used.", 100, true)
call InventoryInitItemDB_Func('shas', "BTNScrollOfHaste.blp" , "Increases the movement speed of the Hero and nearby allied units to the maximum movement speed. |nLasts <AIsa,Dur1> seconds.", 50, true)
call InventoryInitItemDB_Func('stwp', "BTNScrollUber.blp" , "Teleports the Hero and any of its nearby troops to a target friendly town hall.", 350, true)
call InventoryInitItemDB_Func('silk', "BTNSpiderSilkBroach.blp" , "Binds a target enemy air unit in webbing, forcing the target to the ground. Webbed units can be hit as though they were land units. |nContains <silk,uses> charges.", 50, true)
call InventoryInitItemDB_Func('sneg', "BTNStaffOfNegation.blp" , "Dispels all magical effects in a target area. |n|cffffcc00Deals <AIdi,DataB1> damage to summoned units.|r", 200, true)
call InventoryInitItemDB_Func('ssan', "BTNStaffOfSanctuary.blp" , "Teleports a target unit to your highest level town hall, stunning the unit and regenerating <ANsa,DataE1> hit points per second. Lasts until the unit is fully healed.", 250, true)
call InventoryInitItemDB_Func('tcas', "BTNTinyCastle.blp" , "Creates a Castle at a target location.", 800, true)
call InventoryInitItemDB_Func('tgrh', "BTNGreathall.blp" , "Creates a Great Hall at a target location. Human, Night Elf, and Undead players will get their racial equivalent town hall.", 600, true)
call InventoryInitItemDB_Func('tret', "BTNTomeOfRetraining.blp" , "Unlearns all of the Hero's spells, allowing the Hero to learn different skills.", 300, true)
call InventoryInitItemDB_Func('vamp', "BTNPotionOfVampirism.blp", "Adds <AIpv,DataA1> bonus damage and a life-stealing attack to the Hero. |nLasts <AIpv,Dur1> seconds.", 75, true)
call InventoryInitItemDB_Func('wneg', "BTNWandSkull.blp" , "Dispels all magical effects in a target area. |nContains <wneg,uses> charges. |n|cffffcc00Deals <AIdi,DataB1> damage to summoned units.|r", 200, true)
call InventoryInitItemDB_Func('wneu', "BTNWandOfNeutralization.blp", "Hurls forth a stream of neutralizing magic that bounces up to <AIdc,DataC1> times, dispelling units in its wake. |nContains <wneu,uses> charges.", 150, true)
//______ ___ ________
call InventoryInitItemDB_Func('kybl', "BTNBloodKey.blp" , "This key is covered in blood.", 200, false)
call InventoryInitItemDB_Func('ches', "BTNCheese.blp" , "Cheese cheese cheese cheese!", 250, false)
call InventoryInitItemDB_Func('bzbe', "BTNVialEmpty.blp" , "A special vial adept at containing the magical healing waters of a Fountain of Life.", 200, false)
call InventoryInitItemDB_Func('engs', "BTNEnchantedGemstone.blp", "This artifact of the Kelani Magi is said to hold the power to make constructs out of pure energy. When the Kelani fell to ruin, the Razormane Quillboars were quick to scavenge and covet these beautiful and powerful objects.", 200, false)
call InventoryInitItemDB_Func('bzbf', "BTNVialFull.blp" , "A special vial adept at containing the magical healing waters of a Fountain of Life.", 200, false)
call InventoryInitItemDB_Func('gmfr', "BTNGem.blp" , "A fragment of a gem from a powerful ring.", 200, false)
call InventoryInitItemDB_Func('ledg', "BTNSorceressMaster.blp" , "This Ledger looks to be full of boring facts and figures.", 200, false)
call InventoryInitItemDB_Func('kygh', "BTNGhostKey.blp" , "This key is rather insubstantial.", 200, false)
call InventoryInitItemDB_Func('gopr', "BTNGlyph.blp" , "Created by ancient druids, this glyph has the power to heal the land.", 250, false)
call InventoryInitItemDB_Func('azhr', "BTNHeartOfAszune.blp" , "Legends say that the imprisoned spirit of Aszune seeks out her heart to this very day.", 200, false)
call InventoryInitItemDB_Func('cnhn', "BTNHornOfCenarius.blp" , "This ancient relic of the Night Elves is said to hold the power to call the spirits of all Night Elves. It imbues its owner with <AIl1,DataA1> hit points, and a <Arel,DataA1> hit point per second regeneration bonus.", 200, false)
call InventoryInitItemDB_Func('dkfw', "BTNBarrel.blp" , "A keg filled to the brim with the strongest drink available this side of Khaz Modan!", 200, false)
call InventoryInitItemDB_Func('k3m3', "BTN3M3.blp" , "Cut from the sapphire Body of Enulaia, it opens the soul of the Gate Keeper.", 200, false)
call InventoryInitItemDB_Func('mgtk', "BTNBlood&GhostKey.blp" , "This magical chain of keys can open many doors.", 200, false)
call InventoryInitItemDB_Func('mort', "BTNSpy.blp" , "The letter is magically sealed. On the front, written in large scrawling letters is the word Thrall.", 200, false)
call InventoryInitItemDB_Func('kymn', "BTNMoonKey.blp" , "This key glows faintly.", 200, false)
call InventoryInitItemDB_Func('k3m1', "BTN3M1.blp" , "Cut from the emerald Eye of Jennala, it opens the mind of the Gate Keeper.", 200, false)
call InventoryInitItemDB_Func('jpnt', "BTNScrollOfProtection.blp", "A note from Thrall, for Jaina Proudmoore.", 200, false)
call InventoryInitItemDB_Func('k3m2', "BTN3M2.blp" , "Cut from the amethyst Stone of Hannalee, it opens the heart of the Gate Keeper.", 200, false)
call InventoryInitItemDB_Func('phlt', "BTNUndeadShrine.blp" , "There is no phatter lewt than this.", 500, false)
call InventoryInitItemDB_Func('sclp', "BTNSelectHeroOn.blp" , "Unlocks a secret level!", 75, false)
call InventoryInitItemDB_Func('sorf', "BTNOrbOfDarkness.blp" , "A fragment of a powerful artifact.", 200, false)
call InventoryInitItemDB_Func('shwd', "BTNShimmerWeed.blp" , "Wondrous plant said to have miraculous mind-expanding properties.", 200, false)
call InventoryInitItemDB_Func('skrt', "BTNOrbOfCorruption.blp" , "This ancient artifact entraps the souls of those who die violently, forcing them to relive the last moments of their lives for eternity.", 250, false)
call InventoryInitItemDB_Func('glsk', "BTNGuldanSkull.blp" , "Once a powerful user of Demonic magics, the Demons answered his calls, and found a greater use for his head.", 200, false)
call InventoryInitItemDB_Func('kysn', "BTNSunKey.blp" , "This key glows brightly.", 200, false)
call InventoryInitItemDB_Func('sehr', "BTNHeartOfSearinox.blp" , "The still beating heart of Searinox can be used to imbue an Orb with the fiery powers of a Dragon.", 200, false)
call InventoryInitItemDB_Func('thle', "BTNThunderLizardEgg.blp" , "This massive egg will not hatch without a parent to warm it.", 200, false)
call InventoryInitItemDB_Func('dphe', "BTNThunderLizardEgg.blp" , "A rare egg of a Thunder Hawk.", 200, false)
call InventoryInitItemDB_Func('dthb', "BTNManaFlareOff.blp" , "An exotic plant well known for its unstable and dangerous properties.", 200, false)
call InventoryInitItemDB_Func('ktrm', "BTNUrnOfKelThuzad.blp" , "Formerly the container of King Terenas' ashes, this magically enchanted Urn was chosen by Tichondrius to preserve Kel'Thuzad's remains.", 200, false)
call InventoryInitItemDB_Func('wtlg', "BTNWirtsLeg.blp" , "Could it be that a portal opened up and expelled the remains of our dearest pal from the world of Diablo to here? If so, was it a player, or a Demon? Just how many worlds have the Burning Legion conquered? Could the Demons of the Burning Legion and those of Sanctuary be one and the same? The mind wobbles.", 200, false)
call InventoryInitItemDB_Func('wolg', "BTNWirtsOtherLeg.blp" , "Perhaps the overzealous adventurer pried this off before his journey here thinking it might give him one last opportunity at bovine slaughter. Little did he know where it would lead him.", 200, false)
//_____
call InventoryInitItemDB_Func('amrc', "BTNAmulet.blp" , "Teleports <AIrt,DataA1> of the player's units within the targeted area to the location of the Hero when used.", 250, true)
call InventoryInitItemDB_Func('axas', "BTNWitchDoctorMaster.blp", "|cffff8c00Artifact|r|nSummons <AIsh,DataB1> Troll Berserkers to fight for you. Also grants the Hero and friendly nearby units increased attack rate and movement speed.|n|cffffcc00History|r|n|cffffdeadNames of generations of Witch Doctors are carved into this staff. The wielder can call upon them for wisdom and guidance in times of peril.|r", 3000, false)
call InventoryInitItemDB_Func('anfg', "BTNClayFigurine.blp" , "Increases the Intelligence of the Hero by 1 when carried.", 150, false)
call InventoryInitItemDB_Func('pams', "BTNSnazzyPotion.blp" , "Gives the Hero immunity to magical spells for <AIxs,Dur1> seconds.", 100, true)
call InventoryInitItemDB_Func('arsc', "BTNBansheeAdept.blp" , "A powerful scroll that restores <AIha,DataA1> hit points, <AImr,DataA1> mana, and grants <AIda,DataA1> bonus armor to nearby friendly units.", 1000, true)
call InventoryInitItemDB_Func('arsh', "BTNArcaniteArmor.blp" , "Reduces damage from ranged attacks to <AIdd,DataA1,%>%. Also increases the Hero's armor by <AId5,DataA1> when worn.", 3500, false)
call InventoryInitItemDB_Func('asbl', "BTNDaggerOfEscape.blp" , "Adds <AItj,DataA1> bonus damage to the attack of the Hero when carried. The Hero's attacks also deal <AIsz,DataA1> damage per second, and slow the movement speed and attack rate of the enemy.", 2000, false)
call InventoryInitItemDB_Func('btst', "BTNOrcBattleStandard.blp", "The Battle Standard of Thrall's Orcs, carry it with pride.", 1000, false)
call InventoryInitItemDB_Func('blba', "BTNArmorGolem.blp" , "Grants nearby units <AIad,DataA1> bonus defense. Enhances the Hero's armor by <AId7,DataA1>.", 3500, false)
call InventoryInitItemDB_Func('bfhr', "BTNPhilosophersStone.blp", "|cff8b00ffUnique|r|nIncreases the Hero's agility by <AIaz,DataA1> when worn.", 2500, false)
call InventoryInitItemDB_Func('brag', "BTNRingPurple.blp" , "Increases the Agility of the Hero by 1 when worn.", 50, false)
call InventoryInitItemDB_Func('cosl', "BTNUsedSoulGem.blp" , "|cffff8c00Artifact|r|nBrings <AIrx,DataA1> of your nearby dead units back to life. |n|cffffcc00History|r|n|cffffdeadCrafted by the Titans as gifts to their favored creations, the Celestial Orb of Souls channels the powers of the light to bring back to life those who have recently fallen.|r", 10000, false)
call InventoryInitItemDB_Func('rat3', "BTNClawsOfAttack.blp" , "Increases the attack damage of the Hero by 3 when worn.", 50, false)
call InventoryInitItemDB_Func('stpg', "BTNPenguin.blp" , "This penguin squeak-toy was first created by the goblin tinkerer Salzhigh for the centaur. Regarding it with some awe (having never seen a penguin before) the centaur purchased them as idols and worshipped them at altars.", 450, false)
call InventoryInitItemDB_Func('crdt', "BTNRevenant.blp" , "|cffff8c00Artifact|r|nGrants the ability to fire bolts of pain that deal <AIfz,DataC1> damage. Also increases the Hero's hit points by <AIlf,DataA1> and mana by <AImz,DataA1> when worn.|n|cffffcc00History|r|n|cffffdeadThe Deathlords are rumored to have been mighty Paladins once. One of their order turned from the light when he slaughtered his own family, believing they were impure.|r", 6400, false)
call InventoryInitItemDB_Func('dtsb', "BTNSorceressMaster.blp" , "|cffff8c00Artifact|r|nGrants the ability to portal to your home town. Also reduces spell damage by <AIsr,DataB1,%>% and increases the Hero's mana by <AImv,DataA1> while equipped.|n|cffffcc00History|r|n|cffffdeadDrek'Thar's old spellbook is filled with pages stolen from Kirin Tor mages that were slain in battle.|r", 3350, false)
call InventoryInitItemDB_Func('drph', "BTNDust.blp" , "Increases the Intelligence of the Hero by 1 when carried.", 50, false)
call InventoryInitItemDB_Func('dust', "BTNDustOfAppearance.blp" , "Reveals enemy invisible units in an area around the Hero. |nContains <dust,uses> charges. |nLasts <AItb,Dur1> seconds.", 750, true)
call InventoryInitItemDB_Func('shen', "BTNThoriumArmor.blp" , "Increases the Hero's armor by <AId2,DataA1> and hit points by <AIlz,DataA1> when worn.", 650, false)
call InventoryInitItemDB_Func('envl', "BTNVialFull.blp" , "Regenerates <AIp3,DataA1> hit points and <AIp3,DataB1> mana of the Hero over <AIp3,Dur1> seconds. |nContains <envl,uses> charges.", 450, true)
call InventoryInitItemDB_Func('esaz', "BTNHeartOfAszune.blp" , "Legends speak of an intelligent Orc who found the Heart of Aszune. This is the essence of her heart, precious to the Night Elves. It has the power to heal the Hero that wields it. This item is permanent.", 600, false)
call InventoryInitItemDB_Func('frhg', "BTNAdvancedUnholyStrength.blp", "Increases armor by <AId5,DataA1> and attack rate by <AIs2,DataA1,%>% when worn.", 3500, false)
call InventoryInitItemDB_Func('fgun', "BTNFlare.blp" , "Reveals a target area on the map. |nContains <fgun,uses> charges.", 125, false)
call InventoryInitItemDB_Func('fwss', "BTNGrimWard.blp" , "This ancient Frost Wyrm skull has been equipped with handles, turning it into a powerful shield. Increases armor by 2 when worn and reduces Magic damage dealt to the Hero by <AIsr,DataB1,%>%.", 750, false)
call InventoryInitItemDB_Func('frgd', "BTNThoriumMelee.blp" , "Adds <AIft,DataA1> bonus cold damage to the attack of a Hero and <AId5,DataA1> bonus armor when carried. The Hero's attacks also slow the movement speed and attack rate of the enemy.", 1400, false)
call InventoryInitItemDB_Func('gemt', "BTNGem.blp" , "Allows the Hero to detect hidden or invisible units in the Hero's line of sight when carried.", 200, false)
call InventoryInitItemDB_Func('gvsm', "BTNSpellSteal.blp" , "|cff8b00ffUnique|r|nGrants the ability to control summoned units. Also increases the intelligence of the Hero by <AIa6,DataA1> when worn.", 1400, false)
call InventoryInitItemDB_Func('gobm', "BTNGoblinLandMine.blp" , "Places a hidden land mine at a target point. Enemy units that move near the land mine will activate the mine, destroying the mine and causing area of effect damage to nearby units. |nContains <gobm,uses> charges.", 225, true)
call InventoryInitItemDB_Func('tels', "BTNTelescope.blp" , "Provides an increase to the Hero's line of sight radius at night when carried.", 200, false)
call InventoryInitItemDB_Func('rej4', "BTNGreaterRejuvPotion.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp4,DataA1> hit points and <AIp4,DataB1> mana of the Hero over <AIp4,Dur1> seconds.", 450, true)
call InventoryInitItemDB_Func('rej6', "BTNGreaterRejuvScroll.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp6,DataA1> hit points and <AIp6,DataB1> mana of the Hero and nearby friendly units over <AIp6,Dur1> seconds.", 500, true)
call InventoryInitItemDB_Func('grsl', "BTNNecromancerMaster.blp", "|cff87ceebUnique Consumable|r|nThis powerful book permanently increases the hit points of the Hero by <AIpx,DataA1> each time it is used. |nContains <grsl,uses> charges.", 1350, true)
call InventoryInitItemDB_Func('hbth', "BTNUnholyAura.blp" , "|cff8b00ffUnique|r|nGrants the ability to go Berserk, causing the Hero to attack <AIxk,DataB1,%>% faster but take <AIxk,DataC1,%>% more damage. Also increases strength and agility by 4 when worn.", 4200, false)
call InventoryInitItemDB_Func('sfog', "BTNHornOfFog.blp" , "Allows the Hero to channel the Cloud ability, which stops an area of enemy towers from attacking for <AIfg,Dur1> seconds.", 200, false)
call InventoryInitItemDB_Func('flag', "BTNHumanCaptureFlag.blp" , "An object that is often captured in special scenarios as a win condition.", 1000, false)
call InventoryInitItemDB_Func('iwbr', "BTNNatureTouchGrow.blp" , "Increases the Strength of the Hero by 1 when carried.", 50, false)
call InventoryInitItemDB_Func('jdrn', "BTNRingJadeFalcon.blp" , "Increases the Agility of the Hero by 1 when worn.", 50, false)
call InventoryInitItemDB_Func('kgal', "BTNBarrel.blp" , "Increases hit point and mana regeneration.", 850, false)
call InventoryInitItemDB_Func('klmm', "BTNSpiritWalkerAdeptTraining.blp", "|cffff8c00Artifact|r|nIncreases the attack damage of the Hero by <AItx,DataA1> when carried. Also causes the Hero's attacks to steal life.|n|cffffcc00History|r|n|cffffdeadWhen Dethorin found his lady, Allurana, in the arms of another, he went to the Barrens and cried out. An axe burst forth from the sands as if in answer. Dethorin slew Allurana and her lover, then hurled the axe with all his might into the deep dark sea.|r", 7500, false)
call InventoryInitItemDB_Func('rej2', "BTNLesserRejuvPotion.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp2,DataA1> hit points and <AIp2,DataB1> mana of the Hero over <AIp2,Dur1> seconds.", 150, true)
call InventoryInitItemDB_Func('rej5', "BTNLesserRejuvScroll.blp", "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp5,DataA1> hit points and <AIp5,DataB1> mana of the Hero and nearby friendly units over <AIp5,Dur1> seconds.", 400, true)
call InventoryInitItemDB_Func('lnrn', "BTNRingLionHead.blp" , "Increases the Agility of the Hero by 1 when worn.", 50, false)
call InventoryInitItemDB_Func('mlst', "BTNHammer.blp" , "Increases the Strength of the Hero by 1 when carried.", 50, false)
call InventoryInitItemDB_Func('mnsf', "BTNBrilliance.blp" , "Increases the mana of the Hero by <AI2m,DataA1>. Also grants the Hero and friendly nearby units a bonus to mana regeneration.", 1800, false)
call InventoryInitItemDB_Func('rej1', "BTNMinorRejuvPotion.blp" , "|cff87ceebNon-Combat Consumable|r|nRegenerates <AIp1,DataA1> hit points and <AIp1,DataB1> mana of the Hero over <AIp1,Dur1> seconds.", 100, true)
call InventoryInitItemDB_Func('lure', "BTNMonsterLure.blp" , "Creates a ward that draws nearby creeps to it.", 200, true)
call InventoryInitItemDB_Func('nspi', "BTNNecklace.blp" , "Renders the Hero invulnerable to magic.", 1000, false)
call InventoryInitItemDB_Func('nflg', "BTNNightElfCaptureFlag.blp", "An object that is often captured in special scenarios as a win condition.", 1000, false)
call InventoryInitItemDB_Func('ocor', "BTNOrbOfCorruption.blp" , "Adds <AIcb,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air and reduce the armor of enemy units for <AIcb,Dur1> seconds.", 400, false)
call InventoryInitItemDB_Func('ofir', "BTNOrbOfFire.blp" , "Adds <AIfb,DataA1> bonus fire damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air and do splash damage to nearby enemy units.", 400, false)
call InventoryInitItemDB_Func('gldo', "BTNUsedSoulGem.blp" , "Adds <AIgd,DataA1> bonus fire damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air and do splash damage to nearby enemy units.", 450, false)
call InventoryInitItemDB_Func('olig', "BTNOrbOfLightning.blp" , "Adds <AIlb,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air, dispel magic and slow the movement speed of the enemy for <AIlp,Dur1> seconds. |n|cffffcc00Deals <AIlp,DataC1> bonus damage to summoned units.", 450, false)
call InventoryInitItemDB_Func('oli2', "BTNOrbOfLightning.blp" , "Adds <AIll,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air, and have a chance to dispel magic and slow the movement speed of the enemy for <AIlp,Dur1> seconds. |n|cffffcc00Deals <AIpg,DataC1> bonus damage to summoned units.", 400, false)
call InventoryInitItemDB_Func('oslo', "BTNOrbofSlowness.blp" , "Adds <AIsb,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air, and have a chance to slow a target enemy unit's movement speed by <AIos,DataA1,%>% and attack rate by <AIos,DataB1,%>% for <AIos,Dur1> seconds.", 550, false)
call InventoryInitItemDB_Func('oven', "BTNOrbOfVenom.blp" , "Adds <AIpb,DataA1> bonus damage to the attack of a Hero when carried. The Hero's attacks also become ranged when attacking air and poison enemy units for <Apo2,Dur1> seconds.", 400, false)
call InventoryInitItemDB_Func('oflg', "BTNOrcCaptureFlag.blp" , "An object that is often captured in special scenarios as a win condition.", 1000, false)
call InventoryInitItemDB_Func('pgin', "BTNGreaterInvisibility.blp", "|cff87ceebNon-Combat Consumable|r|nRenders the Hero invisible for <AIv2,Dur1> seconds when used. An invisible Hero is untargetable by the enemy unless detected. If the Hero attacks, uses an ability, or casts a spell, the invisibility effect is lost.", 200, true)
call InventoryInitItemDB_Func('pspd', "BTNPotionRed.blp" , "Increases the movement speed of the Hero by <AIsp,DataA1,%>% for <AIsp,Dur1> seconds.", 75, true)
call InventoryInitItemDB_Func('rde0', "BTNRingGreen.blp" , "Increases the armor of the Hero by 1 when worn.", 50, false)
call InventoryInitItemDB_Func('rnsp', "BTNGoldRing.blp" , "Increases the Strength, Agility and Intelligence of the Hero by 1 when worn.", 100, false)
call InventoryInitItemDB_Func('ram1', "BTNRingJadeFalcon.blp" , "A powerful artifact with a sliver of a fragmented gem inset. Increases the Strength, Agility and Intelligence of the Hero by 1.", 125, false)
call InventoryInitItemDB_Func('ram4', "BTNRingJadeFalcon.blp" , "A powerful artifact with a wondrous gem inset. Increases the Strength, Agility and Intelligence of the Hero by 3 and gives nearby friendly units a bonus to mana regeneration.", 750, false)
call InventoryInitItemDB_Func('ram2', "BTNRingJadeFalcon.blp" , "A powerful artifact with a part of a fragmented gem inset. Increases the Strength, Agility and Intelligence of the Hero by 2.", 300, false)
call InventoryInitItemDB_Func('ram3', "BTNRingJadeFalcon.blp" , "A powerful artifact with most of a fragmented gem inset. Increases the Strength, Agility and Intelligence of the Hero by 3.", 550, false)
call InventoryInitItemDB_Func('rugt', "BTNImprovedUnholyStrength.blp", "Increases the strength and armor of the Hero by 3 when worn.", 725, false)
call InventoryInitItemDB_Func('rump', "BTNGatherGold.blp" , "This heavy pick can be swung with force. Increases the Hero's attack damage by <AItg,DataA1> and gives a <AIbx,DataA1>% chance to stun the enemy.", 100, false)
call InventoryInitItemDB_Func('horl', "BTNGlyph.blp" , "A powerful artifact, sacred to the orc shaman. |nGrants the Hero and friendly nearby units increased attack rate and movement speed. |nDoes not stack with Endurance Aura.", 950, false)
call InventoryInitItemDB_Func('schl', "BTNPriestAdept.blp" , "Grants the ability to heal a friendly unit. Also grants the Hero and friendly nearby units <AIgx,DataA1,%>% increased hit point regeneration.", 4200, false)
call InventoryInitItemDB_Func('ccmd', "BTNScepterOfMastery.blp" , "Transfers control of the targeted non-Hero unit to the player who uses the Scepter. The transfer of control is permanent. |nCannot be used on Heroes or on creeps higher than level <AIco,DataA1>. |nContains <ccmd,uses> charges.", 1000, true)
call InventoryInitItemDB_Func('rots', "BTNWitchDoctorAdept.blp" , "|cff87ceebUnique Consumable|r|nSummons <AIwm,DataA1> Murlocs to fight for you. Also increases the Hero's strength, agility, and intelligence by 2. |nContains <rots,uses> charges.", 1000, true)
call InventoryInitItemDB_Func('scul', "BTNBansheeMaster.blp" , "Animates <AIan,DataA1> nearby corpses to fight for you. Lasts <AIan,Dur1> seconds.", 950, true)
call InventoryInitItemDB_Func('srbd', "BTNArcaniteMelee.blp" , "Adds <AIfw,DataA1> bonus fire damage to the attack of a Hero when carried. The Hero's attacks also do splash damage to nearby enemy units, and have a <AIcs,DataA1>% chance to deal <AIcs,DataB1> times their normal damage.", 1650, false)
call InventoryInitItemDB_Func('srtl', "BTNOrcMeleeUpThree.blp" , "|cffff8c00Artifact|r|nIncreases the attack rate of the Hero by <AIsx,DataA1,%>% and attack damage by <AItf,DataA1>.|n|cffffcc00History|r|n|cffffdeadThis weapon was crafted on Draenor for Kash'drakor and used in the Blood River war that ended with the annihilation of the Dark Scar clan. Nazgrel is the last living relative of Kash'drakor.|r", 5500, false)
call InventoryInitItemDB_Func('sor1', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 1.", 50, false)
call InventoryInitItemDB_Func('sora', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 10, armor by 3 and grants enhanced hit point regeneration.", 1250, false)
call InventoryInitItemDB_Func('sor2', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 2.", 100, false)
call InventoryInitItemDB_Func('sor3', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 3.", 200, false)
call InventoryInitItemDB_Func('sor4', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 4 and armor by 1.", 300, false)
call InventoryInitItemDB_Func('sor5', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 5 and armor by 1.", 350, false)
call InventoryInitItemDB_Func('sor6', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 6 and armor by 1.", 400, false)
call InventoryInitItemDB_Func('sor7', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 7 and armor by 2.", 550, false)
call InventoryInitItemDB_Func('sor8', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 8 and armor by 2.", 700, false)
call InventoryInitItemDB_Func('sor9', "BTNOrbOfDarkness.blp" , "This artifact was imbued with special powers by the Orc Shadow Council. It increases your attack damage by 9, armor by 2 and grants enhanced hit point regeneration.", 900, false)
call InventoryInitItemDB_Func('shcw', "BTNShamanMaster.blp" , "|cff8b00ffUnique|r|nThese are given to shaman upon the completion of their training. Increases attack damage by <AIlx,DataA1>. The Hero's attacks also have a chance to dispel magic and slow the movement speed of the enemy for <AIpg,Dur1> seconds.", 950, false)
call InventoryInitItemDB_Func('shtm', "BTNEntrapmentWard.blp" , "This powerful Orc artifact channels Shamanic powers through its user, allowing them to cast Purge.", 600, false)
call InventoryInitItemDB_Func('shhn', "BTNHumanArmorUpThree.blp", "|cff8b00ffUnique|r|nGrants nearby friendly units a <AIcd,DataA1,%>% bonus to attack damage. Also increases the armor of the Hero by <AId8,DataA1> when worn.", 3350, false)
call InventoryInitItemDB_Func('shdt', "BTNLightningShield.blp" , "|cffff8c00Artifact|r|nEngulfs the Hero in fire which deals <AIcf,DataA1> damage per second to nearby enemy land units. Also increases the Hero's armor by <AId0,DataA1>, hit points by <AIlf,DataA1>, and mana by <AImz,DataA1> when worn. |n|cffffcc00History|r|n|cffffdeadWhen Arthas took up the sword against his own people in Stratholme, the Deathlords committed the same heinous act in many other cities across Lordaeron.|r", 9000, false)
call InventoryInitItemDB_Func('shrs', "BTNMonsterLure.blp" , "A tasty roast with a shimmerweed base. Heals <AIhx,DataA1> hit points when eaten. |nContains <shrs,uses> charges.", 150, true)
call InventoryInitItemDB_Func('sksh', "BTNGrimWard.blp" , "Increases the Strength of the Hero by 1 when carried.", 200, false)
call InventoryInitItemDB_Func('soul', "BTNUsedSoulGem.blp" , "A soul, trapped by the enchantments of a Soul Gem.", 1000, false)
call InventoryInitItemDB_Func('gsou', "BTNSoulGem.blp" , "Traps the targeted enemy Hero inside the Soul Gem when used. The enemy Hero is returned to play when the bearer of the Soul Gem is killed. While an enemy Hero is trapped, the bearer of the Soul Gem is revealed to the enemy through the Fog of War.", 1000, true)
call InventoryInitItemDB_Func('sbok', "BTNSpellBookBLS.blp" , "A book full of random spells.", 325, false)
call InventoryInitItemDB_Func('sprn', "BTNRingVioletSpider.blp" , "Increases the Agility of the Hero by 1 when worn.", 50, false)
call InventoryInitItemDB_Func('spre', "BTNStaffOfPreservation.blp", "Teleports a target friendly unit to its highest level town hall.", 200, false)
call InventoryInitItemDB_Func('stre', "BTNWandSkull.blp" , "Animates a nearby corpse to fight your enemies. Lasts <AInd,Dur1> seconds.", 200, false)
call InventoryInitItemDB_Func('stwa', "BTNOrcMeleeUpOne.blp" , "Increases the attack damage of the Hero by <AItj,DataA1> when carried.", 600, false)
call InventoryInitItemDB_Func('thdm', "BTNEnchantedGemstone.blp", "|cff8b00ffUnique|r|nCasts bolts of lightning that deal damage to multiple targets.", 1190, false)
call InventoryInitItemDB_Func('tbak', "BTNAltarOfKings.blp" , "Creates a Altar of Kings at a target location.", 180, true)
call InventoryInitItemDB_Func('tbar', "BTNHumanBarracks.blp" , "Creates a Barracks at a target location.", 160, true)
call InventoryInitItemDB_Func('tbsm', "BTNBlacksmith.blp" , "Creates a Blacksmith at a target location.", 200, true)
call InventoryInitItemDB_Func('tfar', "BTNFarm.blp" , "Creates a Farm at a target location.", 75, true)
call InventoryInitItemDB_Func('tlum', "BTNHumanLumberMill.blp" , "Creates a Lumber Mill at a target location.", 150, true)
call InventoryInitItemDB_Func('tgxp', "BTNManual3.blp" , "Gives the Hero <AIe2,DataA1> bonus experience points when used.", 1000, true)
call InventoryInitItemDB_Func('tmsc', "BTNNecromancerAdept.blp" , "|cff8b00ffUnique|r|nGrants the ability to sacrifice a friendly non-Hero unit to restore hit points. Also increases the Hero's mana by <AImz,DataA1> while equipped.", 1250, false)
call InventoryInitItemDB_Func('tmmt', "BTNEntrapmentWard.blp" , "Increases the Strength of the Hero by 1 when carried.", 50, false)
call InventoryInitItemDB_Func('uflg', "BTNUndeadCaptureFlag.blp", "An object that is often captured in special scenarios as a win condition.", 1000, false)
call InventoryInitItemDB_Func('vddl', "BTNShadowPact.blp" , "Increases the Intelligence of the Hero by 1 when carried.", 50, false)
//---------------------------------------------------------------------------------------------------+
// |
// Dest |
// |
//---------------------------------------------------------------------------------------------------+
//________
call InventoryInitDestDB_Func('D000', "BTNSpellShieldAmulet.blp")
call InventoryInitDestDB_Func('D001', "BTNAmuletOftheWild.blp")
call InventoryInitDestDB_Func('D002', "BTNPendantOfMana.blp")
call InventoryInitDestDB_Func('D003', "BTNAmulet.blp")
call InventoryInitDestDB_Func('D004', "BTNPendantOfEnergy.blp")
call InventoryInitDestDB_Func('D005', "BTNSnazzyPotion.blp")
call InventoryInitDestDB_Func('D006', "BTNArcaniteArmor.blp")
call InventoryInitDestDB_Func('D007', "BTNOrcMeleeUpOne.blp")
call InventoryInitDestDB_Func('D008', "BTNDrum.blp")
call InventoryInitDestDB_Func('D009', "BTNClawsOfAttack.blp")
call InventoryInitDestDB_Func('D00A', "BTNBarrel.blp")
call InventoryInitDestDB_Func('D00B', "BTNRingPurple.blp")
call InventoryInitDestDB_Func('D00C', "BTNCirclet.blp")
call InventoryInitDestDB_Func('D00D', "BTNNatureTouchGrow.blp")
call InventoryInitDestDB_Func('D00E', "BTNBlood&GhostKey.blp")
call InventoryInitDestDB_Func('D00F', "BTNWirtsOtherLeg.blp")
call InventoryInitDestDB_Func('D00G', "BTNBundleOfLumber.blp")
call InventoryInitDestDB_Func('D00H', "BTNGoblinLandMine.blp")
call InventoryInitDestDB_Func('D00I', "BTNTelescope.blp")
call InventoryInitDestDB_Func('D00J', "BTNOrcMeleeUpThree.blp")
call InventoryInitDestDB_Func('D00K', "BTNSpy.blp")
call InventoryInitDestDB_Func('D00L', "BTNArmorGolem.blp")
call InventoryInitDestDB_Func('D00M', "BTNClayFigurine.blp")
call InventoryInitDestDB_Func('D00N', "BTNHealingWard.blp")
call InventoryInitDestDB_Func('D00O', "BTNUsedSoulGem.blp")
call InventoryInitDestDB_Func('D00P', "BTNWandOfCyclone.blp")
call InventoryInitDestDB_Func('D00Q', "BTNWand.blp")
call InventoryInitDestDB_Func('D00R', "BTNPriestAdept.blp")
call InventoryInitDestDB_Func('D00S', "BTNStarWand.blp")
call InventoryInitDestDB_Func('D00T', "BTNWitchDoctorAdept.blp")
call InventoryInitDestDB_Func('D00U', "BTNWandSkull.blp")
call InventoryInitDestDB_Func('D00V', "BTNRodOfNecromancy.blp")
call InventoryInitDestDB_Func('D00W', "BTNWandOfManaSteal.blp")
call InventoryInitDestDB_Func('D00X', "BTNWandOfNeutralization.blp")
call InventoryInitDestDB_Func('D00Y', "BTNWandOfShadowSight.blp")
call InventoryInitDestDB_Func('D00Z', "BTNMechanicalCritter.blp")
call InventoryInitDestDB_Func('D010', "BTNPenguin.blp")
call InventoryInitDestDB_Func('D011', "BTNSacrificialSkull.blp")
call InventoryInitDestDB_Func('D012', "BTNEnchantedGemstone.blp")
call InventoryInitDestDB_Func('D013', "BTNThoriumArmor.blp")
call InventoryInitDestDB_Func('D014', "BTNShimmerWeed.blp")
call InventoryInitDestDB_Func('D015', "BTNPotionOfVampirism.blp")
call InventoryInitDestDB_Func('D016', "BTNPotionOfOmniscience.blp")
call InventoryInitDestDB_Func('D017', "BTNPotionBlueSmall.blp")
call InventoryInitDestDB_Func('D018', "BTNLesserInvisibility.blp")
call InventoryInitDestDB_Func('D019', "BTNGreaterInvulneralbility.blp")
call InventoryInitDestDB_Func('D01A', "BTNRejuvPotion.blp")
call InventoryInitDestDB_Func('D01B', "BTNPotionOfClarity.blp")
call InventoryInitDestDB_Func('D01C', "BTNPotionRed.blp")
call InventoryInitDestDB_Func('D01D', "BTNGrimWard.blp")
call InventoryInitDestDB_Func('D01E', "BTNGlyph.blp")
call InventoryInitDestDB_Func('D01F', "BTNHumanCaptureFlag.blp")
call InventoryInitDestDB_Func('D01G', "BTNUndeadCaptureFlag.blp")
call InventoryInitDestDB_Func('D01H', "BTNNightElfCaptureFlag.blp")
call InventoryInitDestDB_Func('D01I', "BTNOrcBattleStandard.blp")
call InventoryInitDestDB_Func('D01J', "BTNOrcCaptureFlag.blp")
call InventoryInitDestDB_Func('D01K', "BTNHumanWatchTower.blp")
call InventoryInitDestDB_Func('D01L', "BTNBlacksmith.blp")
call InventoryInitDestDB_Func('D01M', "BTNHumanLumberMill.blp")
call InventoryInitDestDB_Func('D01N', "BTNFarm.blp")
call InventoryInitDestDB_Func('D01O', "BTNHumanBarracks.blp")
call InventoryInitDestDB_Func('D01P', "BTNAltarOfKings.blp")
call InventoryInitDestDB_Func('D01Q', "BTNTinyCastle.blp")
call InventoryInitDestDB_Func('D01R', "BTNRockGolem.blp")
call InventoryInitDestDB_Func('D01S', "BTNSoulGem.blp")
call InventoryInitDestDB_Func('D01T', "BTNPeriapt1.blp")
call InventoryInitDestDB_Func('D01U', "BTNMoonStone.blp")
call InventoryInitDestDB_Func('D01V', "BTNHealthStone.blp")
call InventoryInitDestDB_Func('D01W', "BTNDarkSummoning.blp")
call InventoryInitDestDB_Func('D01X', "BTNManaStone.blp")
call InventoryInitDestDB_Func('D01Y', "BTNInfernalStone.blp")
call InventoryInitDestDB_Func('D01Z', "BTNGem.blp")
call InventoryInitDestDB_Func('D020', "BTNHoodOfCunning.blp")
call InventoryInitDestDB_Func('D021', "BTNBoots.blp")
call InventoryInitDestDB_Func('D022', "BTNDaggerOfEscape.blp")
call InventoryInitDestDB_Func('D023', "BTN3M3.blp")
call InventoryInitDestDB_Func('D024', "BTNGhostKey.blp")
call InventoryInitDestDB_Func('D025', "BTNNecromancerAdept.blp")
call InventoryInitDestDB_Func('D026', "BTNTomeOfRetraining.blp")
call InventoryInitDestDB_Func('D027', "BTNNecromancerMaster.blp")
call InventoryInitDestDB_Func('D028', "BTNTomeRed.blp")
call InventoryInitDestDB_Func('D029', "BTNTome.blp")
call InventoryInitDestDB_Func('D02A', "BTNBookOfTheDead.blp")
call InventoryInitDestDB_Func('D02B', "BTNTomeBrown.blp")
call InventoryInitDestDB_Func('D02C', "BTNSpellBookBLS.blp")
call InventoryInitDestDB_Func('D02D', "BTNShamanMaster.blp")
call InventoryInitDestDB_Func('D02E', "BTNRingJadeFalcon.blp")
call InventoryInitDestDB_Func('D02F', "BTNRingGreen.blp")
call InventoryInitDestDB_Func('D02G', "BTNRingLionHead.blp")
call InventoryInitDestDB_Func('D02H', "BTNRingVioletSpider.blp")
call InventoryInitDestDB_Func('D02I', "BTNGoldRing.blp")
call InventoryInitDestDB_Func('D02J', "BTNRingSkull.blp")
call InventoryInitDestDB_Func('D02K', "BTNManaFlareOff.blp")
call InventoryInitDestDB_Func('D02L', "BTNHelmutPurple.blp")
call InventoryInitDestDB_Func('D02M', "BTNRevenant.blp")
call InventoryInitDestDB_Func('D02N', "BTNBoneChimes.blp")
call InventoryInitDestDB_Func('D02O', "BTNAnkh.blp")
call InventoryInitDestDB_Func('D02P', "BTNSpiritWalkerAdeptTraining.blp")
call InventoryInitDestDB_Func('D02Q', "BTNBloodKey.blp")
call InventoryInitDestDB_Func('D02R', "BTNShadowPact.blp")
call InventoryInitDestDB_Func('D02S', "BTNThoriumMelee.blp")
call InventoryInitDestDB_Func('D02T', "BTNPotionGreenSmall.blp")
call InventoryInitDestDB_Func('D02U', "BTNHealingSalve.blp")
call InventoryInitDestDB_Func('D02V', "BTNMoonKey.blp")
call InventoryInitDestDB_Func('D02W', "BTN3M1.blp")
call InventoryInitDestDB_Func('D02X', "BTNMantleOfIntelligence.blp")
call InventoryInitDestDB_Func('D02Y', "BTNSobiMask.blp")
call InventoryInitDestDB_Func('D02Z', "BTNMaskOfDeath.blp")
call InventoryInitDestDB_Func('D030', "BTNMedalionOfCourage.blp")
call InventoryInitDestDB_Func('D031', "BTNManual.blp")
call InventoryInitDestDB_Func('D032', "BTNDust.blp")
call InventoryInitDestDB_Func('D033', "BTNHammer.blp")
call InventoryInitDestDB_Func('D034', "BTNSpiderSilkBroach.blp")
call InventoryInitDestDB_Func('D035', "BTNMinorRejuvPotion.blp")
call InventoryInitDestDB_Func('D036', "BTNSentryWard.blp")
call InventoryInitDestDB_Func('D037', "BTNWirtsLeg.blp")
call InventoryInitDestDB_Func('D038', "BTNArcaniteMelee.blp")
call InventoryInitDestDB_Func('D039', "BTNCloakOfFlames.blp")
call InventoryInitDestDB_Func('D03A', "BTNRobeOfTheMagi.blp")
call InventoryInitDestDB_Func('D03B', "BTNNecklace.blp")
call InventoryInitDestDB_Func('D03C', "BTNUndeadShrine.blp")
call InventoryInitDestDB_Func('D03D', "BTNFlare.blp")
call InventoryInitDestDB_Func('D03E', "BTNIceShard.blp")
call InventoryInitDestDB_Func('D03F', "BTNLesserInvulneralbility.blp")
call InventoryInitDestDB_Func('D03G', "BTNLesserRejuvPotion.blp")
call InventoryInitDestDB_Func('D03H', "BTNLesserClarityPotion.blp")
call InventoryInitDestDB_Func('D03I', "BTNFelHound.blp")
call InventoryInitDestDB_Func('D03J', "BTNAdvancedUnholyStrength.blp")
call InventoryInitDestDB_Func('D03K', "BTNGlove.blp")
call InventoryInitDestDB_Func('D03L', "BTNSpellSteal.blp")
call InventoryInitDestDB_Func('D03M', "BTNCloak.blp")
call InventoryInitDestDB_Func('D03N', "BTNVialFull.blp")
call InventoryInitDestDB_Func('D03O', "BTNDustOfAppearance.blp")
call InventoryInitDestDB_Func('D03P', "BTNStaffOfSilence.blp")
call InventoryInitDestDB_Func('D03Q', "BTNStaffOfPreservation.blp")
call InventoryInitDestDB_Func('D03R', "BTNBrilliance.blp")
call InventoryInitDestDB_Func('D03S', "BTNStaffOfNegation.blp")
call InventoryInitDestDB_Func('D03T', "BTNWitchDoctorMaster.blp")
call InventoryInitDestDB_Func('D03U', "BTNStaffOfSanctuary.blp")
call InventoryInitDestDB_Func('D03V', "BTNStaffOfTeleportation.blp")
call InventoryInitDestDB_Func('D03W', "BTNBelt.blp")
call InventoryInitDestDB_Func('D03X', "BTNMonsterLure.blp")
call InventoryInitDestDB_Func('D03Y', "BTNVialEmpty.blp")
call InventoryInitDestDB_Func('D03Z', "BTNGatherGold.blp")
call InventoryInitDestDB_Func('D040', "BTNLionHorn.blp")
call InventoryInitDestDB_Func('D041', "BTNHornOfCenarius.blp")
call InventoryInitDestDB_Func('D042', "BTNHornOfFog.blp")
call InventoryInitDestDB_Func('D043', "BTNGauntletsOfOgrePower.blp")
call InventoryInitDestDB_Func('D044', "BTNRune.blp")
call InventoryInitDestDB_Func('D045', "BTNRunedBracers.blp")
call InventoryInitDestDB_Func('D046', "BTNImprovedUnholyStrength.blp")
call InventoryInitDestDB_Func('D047', "BTNBootsOfSpeed.blp")
call InventoryInitDestDB_Func('D048', "BTNScrollUber.blp")
call InventoryInitDestDB_Func('D049', "BTNScrollOfHealing.blp")
call InventoryInitDestDB_Func('D04A', "BTNSnazzyScroll.blp")
call InventoryInitDestDB_Func('D04B', "BTNSnazzyScrollPurple.blp")
call InventoryInitDestDB_Func('D04C', "BTNScroll.blp")
call InventoryInitDestDB_Func('D04D', "BTNSnazzyScrollGreen.blp")
call InventoryInitDestDB_Func('D04E', "BTNScrollOfTownPortal.blp")
call InventoryInitDestDB_Func('D04F', "BTNScrollOfProtection.blp")
call InventoryInitDestDB_Func('D04G', "BTNGreaterRejuvScroll.blp")
call InventoryInitDestDB_Func('D04H', "BTNLesserRejuvScroll.blp")
call InventoryInitDestDB_Func('D04I', "BTNBansheeMaster.blp")
call InventoryInitDestDB_Func('D04J', "BTNScrollOfRegenerationGreen.blp")
call InventoryInitDestDB_Func('D04K', "BTNBansheeAdept.blp")
call InventoryInitDestDB_Func('D04L', "BTNScrollOfHaste.blp")
call InventoryInitDestDB_Func('D04M', "BTNSelectHeroOn.blp")
call InventoryInitDestDB_Func('D04N', "BTNHeartOfAszune.blp")
call InventoryInitDestDB_Func('D04O', "BTNHeartOfSearinox.blp")
call InventoryInitDestDB_Func('D04P', "BTNPhilosophersStone.blp")
call InventoryInitDestDB_Func('D04Q', "BTNScepterOfMastery.blp")
call InventoryInitDestDB_Func('D04R', "BTNSunKey.blp")
call InventoryInitDestDB_Func('D04S', "BTNDoomGuard.blp")
call InventoryInitDestDB_Func('D04T', "BTNOrbofSlowness.blp")
call InventoryInitDestDB_Func('D04U', "BTNOrbOfFrost.blp")
call InventoryInitDestDB_Func('D04V', "BTNOrbOfLightning.blp")
call InventoryInitDestDB_Func('D04W', "BTNOrbOfFire.blp")
call InventoryInitDestDB_Func('D04X', "BTNOrbOfCorruption.blp")
call InventoryInitDestDB_Func('D04Y', "BTNOrbOfDarkness.blp")
call InventoryInitDestDB_Func('D04Z', "BTNOrbOfVenom.blp")
call InventoryInitDestDB_Func('D050', "BTNChestOfGold.blp")
call InventoryInitDestDB_Func('D051', "BTNCheese.blp")
call InventoryInitDestDB_Func('D052', "BTNTalisman.blp")
call InventoryInitDestDB_Func('D053', "BTNPeriapt.blp")
call InventoryInitDestDB_Func('D054', "BTNStone.blp")
call InventoryInitDestDB_Func('D055', "BTNEntrapmentWard.blp")
call InventoryInitDestDB_Func('D056', "BTNHornOfDoom.blp")
call InventoryInitDestDB_Func('D057', "BTNSlippersOfAgility.blp")
call InventoryInitDestDB_Func('D058', "BTNUrnOfKelThuzad.blp")
call InventoryInitDestDB_Func('D059', "BTNSorceressMaster.blp")
call InventoryInitDestDB_Func('D05A', "BTNAlleriaFlute.blp")
call InventoryInitDestDB_Func('D05B', "BTNPipeOfInsight.blp")
call InventoryInitDestDB_Func('D05C', "BTNCrystalBall.blp")
call InventoryInitDestDB_Func('D05D', "BTNPotionGreen.blp")
call InventoryInitDestDB_Func('D05E', "BTN3M2.blp")
call InventoryInitDestDB_Func('D05F', "BTNJanggo.blp")
call InventoryInitDestDB_Func('D05G', "BTNGuldanSkull.blp")
call InventoryInitDestDB_Func('D05H', "BTNGreathall.blp")
call InventoryInitDestDB_Func('D05I', "BTNHelmOfValor.blp")
call InventoryInitDestDB_Func('D05J', "BTNUnholyAura.blp")
call InventoryInitDestDB_Func('D05K', "BTNHumanArmorUpThree.blp")
call InventoryInitDestDB_Func('D05L', "BTNLightningShield.blp")
call InventoryInitDestDB_Func('D05M', "BTNPotionOfRestoration.blp")
call InventoryInitDestDB_Func('D05N', "BTNPotionBlueBig.blp")
call InventoryInitDestDB_Func('D05O', "BTNGreaterInvisibility.blp")
call InventoryInitDestDB_Func('D05P', "BTNPotionOfDivinity.blp")
call InventoryInitDestDB_Func('D05Q', "BTNGreaterRejuvPotion.blp")
call InventoryInitDestDB_Func('D05R', "BTNManual3.blp")
call InventoryInitDestDB_Func('D05S', "BTNThunderLizardEgg.blp")
call InventoryInitDestDB_Func('D05T', "BTNRedDragon.blp")
endfunction
endlibrary
library Example initializer CreateInterfaces requires StartGame
globals
// configuration
private constant real BACKGROUND_X = 0.32
private constant real BACKGROUND_Y = 0.32
private constant real BACKGROUND_W = 140.
private constant real BACKGROUND_H = 70.
private constant real BACKGROUND_SIZE = 0.26
// end config
BasicWindow array PlayerWindow
private UIPicture array Background
private UIButton array Buttons[15][20]
private UIButton array DoubleClickButton
private UIText array Text
private constant real BUTTON_W = .1
private constant real BUTTON_H = .1 * SCREEN_ASPECT_RATIO
private boolean array Displayed
private UIButton array LastButton
endglobals
private function OnLeftClick takes nothing returns boolean
local UIButton btn = GetTriggerButton()
local integer pid = btn.customValue
local player p = GetClickingPlayer()
if (User.Local == p) then
call SelectUnit(PlayerHero[pid], true)
endif
if (btn == DoubleClickButton[pid] and LastButton[pid] != 0) then
call BJDebugMsg("[" + User[p].nameColored + "] Double-Click: Button #" + I2S(LastButton[pid]))
set LastButton[pid] = 0
else
call BJDebugMsg("[" + User[p].nameColored + "] Left-Click: Button #" + I2S(btn))
endif
set LastButton[pid] = btn
return false
endfunction
private function OnRightClick takes nothing returns boolean
local UIButton btn = GetTriggerButton()
local integer pid = btn.customValue
local player p = GetClickingPlayer()
call BJDebugMsg("[" + User[p].nameColored + "] Right-Click: Button #" + I2S(btn))
return false
endfunction
struct BasicWindow
// we use an array instead of struct members
// to create for each player only once
static UIPicture array Background
static UIButton array Buttons[15][20] // size for 15 players, 20 buttons
static UIText array Text
readonly boolean displayed
readonly User user
readonly Camera camera
readonly thistype next
readonly thistype prev
readonly integer buttons
method addButton takes real x, real y, integer texture returns UIButton
set Buttons[user.id][.buttons] = UIButton.create(x, y, BUTTON_W, BUTTON_H, 0.5, texture)
//set Buttons[user.id][.buttons].onLeftClick = Filter(function OnLeftClick)
set Buttons[user.id][.buttons].onRightClick = Filter(function OnRightClick)
set Buttons[user.id][.buttons].customValue = .user.id
set Buttons[user.id][.buttons].selectUnit = PlayerHero[.user.id] // unit to re-select when selecting dummy
set .buttons = .buttons + 1
return Buttons[user.id][.buttons-1]
endmethod
static method create takes User user, Camera cam returns thistype
local thistype this = thistype.allocate()
local integer i = 0
set this.camera = cam
set this.user = user
set this.buttons = 0
// create only once per player
if (Background[user.id] == 0) then
// create background
set Background[user.id] = CreateWindow(BACKGROUND_X, BACKGROUND_Y, BACKGROUND_SIZE, BACKGROUND_W, BACKGROUND_H, GetPlayerRace(user.handle))
// create title
set Text[user.id] = UIText.createEx(user.handle, BACKGROUND_X + 0.15, BACKGROUND_Y, 1)
call SetTextTagText(Text[user.id].text, "Custom User Interface v1.0", 12 * 0.0023)
// create double click detector (not officially supported)
set DoubleClickButton[user.id] = this.addButton(BACKGROUND_X + 0.28, 0.24, 'B002')
// create top button
call this.addButton(BACKGROUND_X + 0.28, 0.06, 'B000')
// create bottom button
call this.addButton(BACKGROUND_X + 0.28, -0.12, 'B001')
endif
return this
endmethod
method show takes boolean flag returns nothing
local integer i = this.user.id
local integer n = 0
local player p = this.user.handle
// show only to one player for performance
call Background[i].showPlayer(p, flag, PlayerCamera[i])
call Text[i].show(flag, PlayerCamera[i])
loop
exitwhen n == .buttons
call Buttons[i][n].showPlayer(p, flag, PlayerCamera[i])
set n = n + 1
endloop
endmethod
method update takes nothing returns nothing
local integer i = this.user.id
local integer n = 0
// update only the elements we need
call Background[i].update()
call Text[i].update()
loop
exitwhen n == .buttons
call Buttons[i][n].update()
set n = n + 1
endloop
endmethod
endstruct
private function OnUpdate takes nothing returns nothing
local User user = User(User.LocalId)
local integer id = user.id
local Camera cam = PlayerCamera[id]
local real x = GetUnitX(PlayerHero[id])
local real y = GetUnitY(PlayerHero[id])
local BasicWindow window = PlayerWindow[id]
call cam.setPosition(x, y, UserInterface_GetTerrainZ(x, y))
if (cam.applyCameraForPlayer(user.handle, false)) then
//call Interface.updateAll(true, true, true)
call window.update()
endif
endfunction
private function CreateInterfaces takes nothing returns nothing
local User user = User.first
local BasicWindow window
loop
exitwhen user == User.NULL
// create a basic window for all playing players
set window = BasicWindow.create(user, PlayerCamera[user.id])
set PlayerWindow[user.id] = window
call window.show(true)
set user = user.next
endloop
call TimerStart(CreateTimer(), 0.01, true, function OnUpdate)
endfunction
endlibrary
library UserInterface initializer Init requires optional UnitDex/*or any unit indexer*/, Camera
/***************************************************************
*
* v1.0.6, by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*
* - Create UI elements based on dummy units.
*
* - Elements are overlay onto the current camera keeping you in gameplay.
*
* - The camera can be modified to any view including third person, however
* it must be locked.
*
* - Dynamic textures are applied to dummies through an ability based off
* off War Clib, using destructables with their replaceable texture field
* set to the desired texture. (more: http://www.wc3c.net/showthread.php?p=1043980)
*
* - Detect left and right clicks.
*
* - Works in multiplayer (and single) without lag.
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Copy the script to your map and save it (requires JassHelper *or* JNGP)
* 2. Copy the object editor data and paste the correct raw codes into the configuration.
* _________________________________________________________________________
* 2. API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* struct UIButton
*
* static method create takes real minx, real maxy, real W, real H, real z, integer texture returns thistype
* static method updateAll takes nothing returns nothing
* static method click takes unit u, boolean isLeft returns boolean
* static method clickEx takes real x, real y, boolean isLeft returns boolean
* static method clickPeriodicSelect takes player p, boolean isLeft returns boolean
*
* method destroy takes nothing returns nothing
* method update takes nothing returns nothing
* method show takes boolean flag, Camera Cam returns nothing
* method showPlayer takes player p, boolean flag, Camera cam returns nothing
* method isClicked takes real x, real y returns boolean
* method clickL takes nothing returns nothing
* method clickR takes nothing returns nothing
* method setPosition takes real minx, real maxy returns nothing
* method setTexture takes integer texture returns nothing
*
* -----------------------
*
* integer customValue
* integer animIndex
* trigger triggerL
* trigger triggerR
* filterfunc onLeftClick
* filterfunc onRightClick
*
*
* struct UIPicture
*
* static method create takes real minx, real maxy, real w, real h, real z, integer texture returns thistype
* static method createEx takes real minx, real maxy, real z, real scale, integer unitId, real modelWidth, real modelHeight, integer texture returns thistype
* static method updateAll takes nothing returns nothing
* method destroy takes nothing returns nothing
* method update takes nothing returns nothing
* method show takes boolean show, Camera Cam returns nothing
* method showPlayer takes player p, boolean flag, Camera cam returns nothing
* method setPosition takes real minx, real maxy returns nothing
* method setTexture takes integer texture returns nothing
*
* -----------------------
*
* integer customValue
* integer animIndex
*
* struct UIText
*
* static method create takes real minx, real maxy, real z returns thistype
* static method updateAll takes nothing returns nothing
*
* method destroy takes nothing returns nothing
* method update takes nothing returns nothing
* method setPosition takes real minx, real maxy returns nothing
* method show takes boolean show, Camera Cam returns nothing
*
* -----------------------
*
* integer customValue
*
* function GetTriggerButton takes nothing returns UIButton
* function GetClickingPlayer takes nothing returns player
* function GetCameraDeltaZ takes nothing returns real
* function CreateWindow takes real x, real y, real size, real width, real height, race playerRace returns UIPicture
*
* public function ApplySkin takes unit u, integer texture returns boolean
*
***************************************************************/
// configuration
private module InterfaceConfig
// dummy unit with pitch angle animations
static constant integer DUMMY_TYPE = 'uidm'
// model used in CreateWindow function
static constant integer WINDOW_DUMMY = 'uiwn'
// destructable ID of the human border texture. the
// rest of the races should have consecutive ids.
static constant integer RACE_BORDERS_START = 'D201'
// run a timer to check for unit selections.
// faster but more cpu intensive.
static constant boolean LEFT_CLICK_TIMER = true
// really low timer intervals remove the flicker
// effect, most of the time.
static constant real LEFT_CLICK_TIMER_RATE = 0.01
// in multiplayer, IsUnitSelected is synchronous
// so it doesn't instantly return false when you use
// SelectUnit(u, false). So we must disable the button
// for the clicking player for a brief period or else
// the event will be spammed.
static constant real LEFT_CLICK_DELAY = 0.6
// ability id's
static constant integer DESTROYER_FORM_ID = 'Aave'
static constant integer LOCUST_ID = 'Aloc'
// ability used to change dummy unit textures
static constant integer SKIN_CHANGE_ABILITY = 'Skin'
static constant integer GHOST_ABILITY = 'Aeth'
// dummy player
static constant player PLAYER = CAMERA_DUMMY_PLAYER // from Camera library
endmodule
// end configuration
globals
public destructable DummyTree = null
private trigger Trig = CreateTrigger()
private UIButton ClickedButton = 0
private player ClickingPlayer = null
private location DummyLoc = Location(0,0)
endglobals
function GetTriggerButton takes nothing returns UIButton
return ClickedButton
endfunction
function GetClickingPlayer takes nothing returns player
return ClickingPlayer
endfunction
public function Eval takes filterfunc func returns boolean
call TriggerClearConditions(Trig)
call TriggerAddCondition(Trig, func)
return TriggerEvaluate(Trig)
endfunction
public function GetTerrainZ takes real x, real y returns real
call MoveLocation(DummyLoc, x, y)
return GetLocationZ(DummyLoc)
endfunction
// adjusts
public function FindModelAnimIndex takes real w, real h, real z returns integer
local real W = w*SCREEN_WIDTH*z
local real H = h*SCREEN_HEIGHT*z
local real anim
if (H<W) then
set anim = 10*(W/H-1)
return UIMath_R2I_N(anim)
else
set anim = 10*(H/W-1)
if anim >= 0.5 then
return 100+UIMath_R2I_N(anim)
endif
endif
return 0
endfunction
public function FindModelSize takes real w, real h, real z returns real
local real W = w*SCREEN_WIDTH*z
local real H = h*SCREEN_HEIGHT*z
if (H<W) then
return 0.5*H
endif
return 0.5*W
endfunction
private function LocalReal takes player p, real forPlayer, real default returns real
if (User.Local == p) then
return forPlayer
endif
return default
endfunction
public function ApplySkin takes unit u, integer texture returns boolean
local boolean out = false
if (texture != 0) then
call UnitAddAbility(u, Interface.SKIN_CHANGE_ABILITY)
set DummyTree = CreateDestructable(texture,GetUnitX(u),GetUnitY(u),0,0,1)
set out = IssueTargetOrder(u, "grabtree", DummyTree)
call RemoveDestructable(DummyTree)
set DummyTree = null
call UnitRemoveAbility(u, Interface.SKIN_CHANGE_ABILITY)
endif
return out
endfunction
struct UIButton
integer customValue
integer animIndex
trigger triggerL
trigger triggerR
filterfunc onLeftClick
filterfunc onRightClick
boolean disabled
unit selectUnit
static boolean useDelay = false
readonly static thistype array AllShow
readonly static integer CountShow = 0
readonly integer index
readonly Camera camera
readonly real scale
readonly real centerx
readonly real centery
readonly real minx
readonly real maxx
readonly real miny
readonly real maxy
readonly real width
readonly real height
readonly real z
readonly unit picture
readonly effect model
readonly boolean displayed
readonly integer texture
private integer unitId
private static thistype array Unit2Button
static method create takes real minx, real maxy, real W, real H, real z, integer texture returns thistype
local thistype this = thistype.allocate()
set .texture = texture
set .customValue = 0
set .camera = 0
set .width = W
set .height = H
set .minx = minx
set .maxx = minx+W
set .maxy = maxy
set .miny = maxy-H
set .z = 100.2+z
set .centerx = minx+W/2.0
set .centery = maxy-H/2.0
set .displayed = false
set .scale = FindModelSize(W, H, .z)
set .triggerL = null
set .triggerR = null
set .onLeftClick = null
set .onRightClick = null
set .selectUnit = null
set .picture = CreateUnit(Interface.PLAYER, Interface.DUMMY_TYPE, 0, 0, 0)
// apply texture
call ApplySkin(.picture, texture)
set .animIndex = FindModelAnimIndex(W, H, .z)
call SetUnitAnimationByIndex(.picture, .animIndex)
call UnitAddAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitRemoveAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitAddAbility(.picture, Interface.SKIN_CHANGE_ABILITY)
call UnitAddAbility(.picture, Interface.GHOST_ABILITY)
set this.unitId = GetUnitUserData(.picture)
set Unit2Button[this.unitId] = this
call SetUnitScale(.picture, 0, 0, 0)
return this
endmethod
method destroy takes nothing returns nothing
call RemoveUnit(.picture)
if .displayed then
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
set .CountShow = .CountShow - 1
endif
endmethod
method update takes nothing returns nothing
local VECTOR3 Pos
if (.displayed) then
set Pos = .camera.win2World(.centerx, .centery, .z)
call SetUnitX(.picture, Pos.x)
call SetUnitY(.picture, Pos.y)
call SetUnitFlyHeight(.picture, Pos.z-GetTerrainZ(Pos.x, Pos.y), 0)
call Pos.destroy()
endif
endmethod
method show takes boolean flag, Camera Cam returns nothing
if Cam != -1 then
set .camera = Cam
endif
if flag != .displayed then
if flag then
set .AllShow[.CountShow] = this
set .index = .CountShow
set .CountShow = .CountShow + 1
call .update()
call SetUnitAnimationByIndex(.picture, .animIndex)
call SetUnitScale(.picture, .scale, 0, 0)
else
set .CountShow = .CountShow - 1
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
call SetUnitX(.picture, 0)
call SetUnitY(.picture, 0)
call SetUnitScale(.picture, 0, 0, 0)
endif
endif
set .displayed = flag
endmethod
method showPlayer takes player p, boolean flag, Camera cam returns nothing
call .show(flag, cam)
if (flag) then
call SetUnitScale(.picture, LocalReal(p, .scale, 0), 0, 0)
endif
endmethod
method isClicked takes real x, real y returns boolean
return .minx < x and x < .maxx and .miny < y and y < .maxy
endmethod
method clickL takes nothing returns nothing
set ClickedButton = this
if (.triggerL != null and TriggerEvaluate(.triggerL)) then
call TriggerExecute(.triggerL)
endif
if (.onLeftClick != null) then
call Eval(.onLeftClick)
endif
endmethod
method clickR takes nothing returns nothing
set ClickedButton = this
if (.triggerR != null and TriggerEvaluate(.triggerR)) then
call TriggerExecute(.triggerR)
endif
if (.onRightClick != null) then
call Eval(.onRightClick)
endif
endmethod
method setPosition takes real minx, real maxy returns nothing
set .minx = minx
set .maxx = minx+.width
set .maxy = maxy
set .miny = maxy-.height
set .centerx = minx+.width/2.0
set .centery = maxy-.height/2.0
if .displayed then
call .update()
endif
endmethod
method setTexture takes integer texture returns nothing
call SetUnitX(.picture, 0)
call SetUnitY(.picture, 0)
call ApplySkin(.picture, texture)
if .displayed then
call .update()
endif
set .texture = texture
endmethod
static method updateAll takes nothing returns nothing
local integer i = .CountShow
loop
exitwhen i < 0
call .AllShow[i].update()
set i = i - 1
endloop
endmethod
static method click takes unit u, boolean isLeft returns boolean
local thistype b
if GetUnitTypeId(u) == Interface.DUMMY_TYPE then
set b = Unit2Button[GetUnitUserData(u)]
if b > 0 and b.displayed then
call SelectUnit(u, false)
if isLeft then
call b.clickL()
else
call b.clickR()
endif
return true
endif
endif
return false
endmethod
static method clickEx takes real x, real y, boolean isLeft returns boolean
local integer i = .CountShow
loop
exitwhen i < 0
if .AllShow[i].isClicked(x, y) then
if isLeft then
call .AllShow[i].clickL()
else
call .AllShow[i].clickR()
endif
return true
endif
set i = i - 1
endloop
return false
endmethod
private static method enableButtonCallback takes nothing returns nothing
local timer t = GetExpiredTimer()
static if (LIBRARY_TimerUtils) then
local thistype btn = thistype(GetTimerData(t))
else
local thistype btn = thistype(R2I(TimerGetRemaining(t) + 0.5))
endif
set btn.disabled = false
set t = null
endmethod
static method clickPeriodicSelect takes player p, boolean isLeft returns boolean
local integer i = .CountShow
local timer t
loop
exitwhen i < 0
if (IsUnitSelected(.AllShow[i].picture, p)) then
if (not .AllShow[i].disabled) then
if isLeft then
call .AllShow[i].clickL()
else
call .AllShow[i].clickR()
endif
if (thistype.useDelay) then // static if doesn't work..
set .AllShow[i].disabled = true
static if (LIBRARY_TimerUtils) then
call TimerStart(NewTimerEx(.AllShow[i]), Interface.LEFT_CLICK_DELAY, false, function thistype.enableButtonCallback)
else
set t = CreateTimer()
call TimerStart(t, .AllShow[i], false, null)
call PauseTimer(t)
call TimerStart(t, Interface.LEFT_CLICK_DELAY, false, function thistype.enableButtonCallback)
set t = null
endif
endif
return true
endif
call SelectUnit(.AllShow[i].picture, false)
if (.AllShow[i].selectUnit != null and User.Local == p) then
call SelectUnit(.AllShow[i].selectUnit, true)
endif
endif
set i = i - 1
endloop
return false
endmethod
endstruct
struct UIPicture
integer customValue
integer animIndex
readonly static thistype array AllShow
readonly static integer CountShow = 0
readonly integer index
readonly Camera camera
readonly real scale
readonly real centerx
readonly real centery
readonly real width
readonly real height
readonly real z
readonly unit picture
readonly boolean displayed
readonly integer texture
static method create takes real minx, real maxy, real w, real h, real z, integer texture returns thistype
local thistype this = thistype.allocate()
set .texture = texture
set .customValue = 0
set .camera = 0
set .width = w
set .height = h
set .centerx = minx+w/2.0
set .centery = maxy-h/2.0
set .z = 100.2+z
set .displayed = false
set .picture = CreateUnit(Interface.PLAYER, Interface.DUMMY_TYPE, 0, 0, 0)
set .animIndex = FindModelAnimIndex(w, h, .z)
set .scale = FindModelSize(w, h, .z)
call ApplySkin(.picture, texture)
call SetUnitAnimationByIndex(.picture, .animIndex)
call UnitAddAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitRemoveAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitAddAbility(.picture, Interface.LOCUST_ID)
call UnitRemoveAbility(.picture, Interface.LOCUST_ID)
// hide unit
call SetUnitScale(.picture, 0, 0, 0)
return this
endmethod
static method createEx takes real minx, real maxy, real z, real scale, integer unitId, real modelWidth, real modelHeight, integer texture returns thistype
local thistype this = thistype.allocate()
set .customValue = 0
set .camera = 0
set .z = 100.2 + z
set .width = (modelWidth*scale) / (SCREEN_WIDTH*.z)
set .height = (modelHeight*scale) / (SCREEN_HEIGHT*.z)
set .scale = scale
set .centerx = minx+.width/2.0
set .centery = maxy-.height/2.0
set .displayed = false
set .picture = CreateUnit(Interface.PLAYER, unitId, 0, 0, 270)
call ApplySkin(.picture, texture)
call UnitAddAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitRemoveAbility(.picture, Interface.DESTROYER_FORM_ID)
call UnitAddAbility(.picture, Interface.LOCUST_ID)
call UnitRemoveAbility(.picture, Interface.LOCUST_ID)
// hide unit
call SetUnitScale(.picture, 0, 0, 0)
return this
endmethod
method destroy takes nothing returns nothing
call RemoveUnit(.picture)
if .displayed then
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
set .CountShow = .CountShow - 1
endif
endmethod
method update takes nothing returns nothing
local VECTOR3 Pos
if (this.displayed) then
set Pos = this.camera.win2World(.centerx, .centery, .z)
call SetUnitX(.picture, Pos.x)
call SetUnitY(.picture, Pos.y)
call SetUnitFlyHeight(.picture, Pos.z - GetTerrainZ(Pos.x, Pos.y), 0)
call Pos.destroy()
endif
endmethod
method show takes boolean show, Camera Cam returns nothing
if Cam != -1 then
set this.camera = Cam
endif
if show != .displayed then
if show then
set .AllShow[.CountShow] = this
set .index = .CountShow
set .CountShow = .CountShow + 1
call .update()
call SetUnitAnimationByIndex(.picture, .animIndex)
call SetUnitScale(.picture, .scale, 0, 0)
else
set .CountShow = .CountShow - 1
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
call SetUnitX(.picture, 0)
call SetUnitY(.picture, 0)
call SetUnitScale(.picture, 0, 0, 0)
endif
endif
set .displayed = show
endmethod
method showPlayer takes player p, boolean flag, Camera cam returns nothing
call .show(flag, cam)
if (flag) then
call SetUnitScale(.picture, LocalReal(p, .scale, 0), 0, 0)
endif
endmethod
method setPosition takes real minx, real maxy returns nothing
set .centerx = minx+.width/2.0
set .centery = maxy-.height/2.0
if .displayed then
call .update()
endif
endmethod
method setTexture takes integer texture returns nothing
call SetUnitX(.picture, 0)
call SetUnitY(.picture, 0)
call ApplySkin(.picture, texture)
if .displayed then
call .update()
endif
set .texture = texture
endmethod
static method updateAll takes nothing returns nothing
local integer i = .CountShow
loop
exitwhen i < 0
call .AllShow[i].update()
set i = i - 1
endloop
endmethod
endstruct
struct UIText
integer customValue
readonly unit dummy
readonly static thistype array AllShow
readonly static integer CountShow = 0
readonly integer index
readonly Camera camera
readonly real minx
readonly real maxy
readonly real z
readonly texttag text
readonly boolean displayed
static method create takes real minx, real maxy, real z returns thistype
local thistype this = thistype.allocate()
set .customValue = 0
set .camera = 0
set .minx = minx
set .maxy = maxy
set .z = 100 + z
set .displayed = false
set .text = CreateTextTag()
set .dummy = CreateUnit(Interface.PLAYER, Interface.DUMMY_TYPE, 0, 0, 0)
call SetUnitScale(.dummy, 0, 0, 0)
call UnitAddAbility(.dummy, Interface.LOCUST_ID)
call UnitRemoveAbility(.dummy, Interface.LOCUST_ID)
call SetTextTagVisibility(.text, false)
call SetTextTagPosUnit(.text, .dummy, 0)
return this
endmethod
static method createEx takes player p, real minx, real maxy, real z returns thistype
local thistype this = thistype.allocate()
set .customValue = 0
set .camera = 0
set .minx = minx
set .maxy = maxy
set .z = 100 + z
set .displayed = false
set .dummy = CreateUnit(Interface.PLAYER, Interface.DUMMY_TYPE, 0, 0, 0)
if (User.Local == p) then
set .text = CreateTextTag()
endif
call SetUnitScale(.dummy, 0, 0, 0)
call UnitAddAbility(.dummy, Interface.LOCUST_ID)
call UnitRemoveAbility(.dummy, Interface.LOCUST_ID)
call SetTextTagVisibility(.text, false)
call SetTextTagPosUnit(.text, .dummy, 0)
return this
endmethod
method destroy takes nothing returns nothing
call DestroyTextTag(.text)
if .displayed then
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
set .CountShow = .CountShow - 1
endif
endmethod
method update takes nothing returns nothing
local VECTOR3 Pos = .camera.win2World(.minx, .maxy, .z)
call SetUnitX(.dummy, Pos.x)
call SetUnitY(.dummy, Pos.y)
call SetTextTagPosUnit(.text, .dummy, (Pos.z-GetTerrainZ(Pos.x,Pos.y))-14.8)
call Pos.destroy()
endmethod
method setPosition takes real minx, real maxy returns nothing
set .minx = minx
set .maxy = maxy
if .displayed then
call .update()
endif
endmethod
method show takes boolean show, Camera Cam returns nothing
if Cam != -1 then
set .camera = Cam
endif
call SetTextTagVisibility(.text, show)
if show != .displayed then
if show then
set .AllShow[.CountShow] = this
set .index = .CountShow
set .CountShow = .CountShow + 1
call .update()
else
set .CountShow = .CountShow - 1
set .AllShow[.index] = .AllShow[.CountShow]
set .AllShow[.index].index = .index
endif
endif
set .displayed = show
endmethod
static method updateAll takes nothing returns nothing
local integer i = .CountShow
loop
exitwhen i < 0
call .AllShow[i].update()
set i = i - 1
endloop
endmethod
endstruct
struct Interface extends array
implement InterfaceConfig
static method getRaceBorders takes race r returns integer
return RACE_BORDERS_START + (GetHandleId(r)-1)
endmethod
static method updateAll takes boolean but, boolean pic, boolean tex returns nothing
if but then
call UIButton.updateAll()
endif
if pic then
call UIPicture.updateAll()
endif
if tex then
call UIText.updateAll()
endif
endmethod
endstruct
function CreateWindow takes real x, real y, real size, real width, real height, race playerRace returns UIPicture
return UIPicture.createEx(x, y, /*z=*/2, size, Interface.WINDOW_DUMMY, width, height, Interface.getRaceBorders(playerRace))
endfunction
private function InterfaceClickR takes nothing returns nothing
local unit clicker = GetTriggerUnit()
local unit btnUnit = GetOrderTargetUnit()
set ClickingPlayer = GetOwningPlayer(clicker)
if (UIButton.click(btnUnit, false)) then
call PauseUnit(clicker, true)
call IssueImmediateOrderById(clicker, 851973)
call PauseUnit(clicker, false)
endif
set clicker = null
endfunction
private function InterfaceClickL takes nothing returns nothing
set ClickingPlayer = GetTriggerPlayer()
call UIButton.click(GetTriggerUnit(), true)
endfunction
private function InterfaceClickL_Timer takes nothing returns nothing
local integer i = 0
local integer c = UIButton.CountShow
local User user = User.first
loop
exitwhen user == User.NULL
set ClickingPlayer = user.handle
call UIButton.clickPeriodicSelect(user.handle, true)
set user = user.next
endloop
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
local User user = User.first
loop
exitwhen user == User.NULL
call TriggerRegisterPlayerUnitEvent(t, user.handle, EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER, null)
static if (not Interface.LEFT_CLICK_TIMER) then
call TriggerRegisterPlayerUnitEvent(t2, user.handle, EVENT_PLAYER_UNIT_SELECTED, null)
endif
set user = user.next
endloop
call TriggerAddAction(t, function InterfaceClickR)
static if (Interface.LEFT_CLICK_TIMER) then
call TimerStart(CreateTimer(), Interface.LEFT_CLICK_TIMER_RATE, true, function InterfaceClickL_Timer)
else
call TriggerAddAction(t2, function InterfaceClickL)
endif
set UIButton.useDelay = Interface.LEFT_CLICK_TIMER
endfunction
endlibrary
library UnitDex uses optional WorldBounds, optional GroupUtils
/***************************************************************
*
* v1.2.1, by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* UnitDex assigns every unit an unique integer. It attempts to make that number within the
* maximum array limit so you can associate it with one.
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map, save it, then restart the editor and comment out the line below.
*/
///! external ObjectMerger w3a Adef uDex anam "Detect Leave" ansf "(UnitDex)" aart "" acat "" arac 0
/* ________________________________________________________________________
* 2. Configuration
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
private module UnitDexConfig
// The raw code of the leave detection ability.
static constant integer DETECT_LEAVE_ABILITY = 'uDex'
// Allow debug messages (debug mode must also be on)
static constant boolean ALLOW_DEBUGGING = true
// Uncomment the lines below to define a filter for units being indexed
/*static method onFilter takes unit u returns boolean
return true
endmethod*/
endmodule
/* _________________________________________________________________________
* 3. Function API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Every function inlines except for UnitDexRemove
*
* function GetUnitId takes unit whichUnit returns integer
* function GetUnitById takes integer index returns unit
*
* function UnitDexEnable takes boolean flag returns nothing
* function UnitDexRemove takes unit u, boolean runEvents returns boolean
*
* function IsUnitIndexed takes unit u returns boolean
* function IsIndexingEnabled takes nothing returns boolean
*
* function GetIndexedUnit takes nothing returns unit
* function GetIndexedUnitId takes nothing returns integer
*
* function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns indexevent
* function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
* function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
*
* function OnUnitIndex takes code func returns triggercondition
* function OnUnitDeidex takes code func returns triggercondition
* _________________________________________________________________________
* 4. Struct API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* UnitDex.Enabled = false // toggle the indexer
* UnitDex.Initialized // returns true if the preload timer has finished
* UnitDex.Count // returns the amount of units indexed
* UnitDex.Unit[0] // access the UnitDex array directly
* UnitDex.Group // a unit group containing every indexed unit (for enumeration)
* UnitDex.LastIndex // returns the last indexed unit's id
* _________________________________________________________________________
* 5. Public Variables
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* These are to be used with the "eventtype" argument of the event API:
*
* constant integer EVENT_UNIT_INDEX = 0
* constant integer EVENT_UNIT_DEINDEX = 1
* _________________________________________________________________________
* 6. Examples
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Associate a unit with a variable
*
* set UnitFlag[GetUnitId(yourUnit)] = true
*
* 2. Allocate a struct instance using a units assigned ID
*
* local somestruct data = GetUnitId(yourUnit)
*
* 3. Detect when a unit leaves the map
*
* function Exit takes nothing returns nothing
* call BJDebugMsg("The unit " + GetUnitName(GetIndexedUnit()) + " has left the map.")
* endfunction
*
* call OnUnitDeindex(function Exit)
* // or
* call RegisterUnitIndexEvent(Filter(function Exit), EVENT_UNIT_DEINDEX)
*
*
* _________________________________________________________________________
* 7. How it works
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Enumerate all preplaced units
* 2. TriggerRegisterEnterRegion native to detect when a unit enters the map
* 3. Assign each unit that enters the map a unique integer
* 4. Give every unit an ability based off of defend. There is no native to accurately
* detect when a unit leaves the map but when a unit dies or is removed from the game
* they are issued the "undefend" order
* 5. Catch the "undefend" order and remove unit from the queue
* _________________________________________________________________________
* 8. Notes
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* - This system is compatable with GUI because it utilizes UnitUserData (custom values for units).
* - The object merger line should be commented out after saving and restarting.
* - All public functions are inlined except UnitDexRemove.
*
* -http://www.hiveworkshop.com/forums/submissions-414/unitdex-lightweight-unit-indexer-248209/
*
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*/
globals
// Event types
constant integer EVENT_UNIT_INDEX = 0
constant integer EVENT_UNIT_DEINDEX = 1
// System variables
private trigger array IndexTrig
private integer Index = 0
private real E=-1
private boolexpr FilterEnter
endglobals
function GetUnitId takes unit whichUnit returns integer
return GetUnitUserData(whichUnit)
endfunction
function GetUnitById takes integer index returns unit
return UnitDex.Unit[index]
endfunction
function GetIndexedUnit takes nothing returns unit
return UnitDex.Unit[UnitDex.LastIndex]
endfunction
function GetIndexedUnitId takes nothing returns integer
return UnitDex.LastIndex
endfunction
function IsUnitIndexed takes unit u returns boolean
return (GetUnitById(GetUnitId(u)) != null)
endfunction
function UnitDexEnable takes boolean flag returns nothing
set UnitDex.Enabled = flag
endfunction
function IsIndexingEnabled takes nothing returns boolean
return UnitDex.Enabled
endfunction
function RegisterUnitIndexEvent takes boolexpr func, integer eventtype returns triggercondition
return TriggerAddCondition(IndexTrig[eventtype], func)
endfunction
function RemoveUnitIndexEvent takes triggercondition c, integer eventtype returns nothing
call TriggerRemoveCondition(IndexTrig[eventtype], c)
endfunction
function TriggerRegisterUnitIndexEvent takes trigger t, integer eventtype returns nothing
call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "E", EQUAL, eventtype)
endfunction
function OnUnitIndex takes code func returns triggercondition
return TriggerAddCondition(IndexTrig[EVENT_UNIT_INDEX], Filter(func))
endfunction
function OnUnitDeindex takes code func returns triggercondition
return TriggerAddCondition(IndexTrig[EVENT_UNIT_DEINDEX], Filter(func))
endfunction
function UnitDexRemove takes unit u, boolean runEvents returns boolean
return UnitDex.Remove(u, runEvents)
endfunction
/****************************************************************/
private keyword UnitDexCore
struct UnitDex extends array
static boolean Enabled = true
readonly static integer LastIndex
readonly static boolean Initialized=false
readonly static group Group=CreateGroup()
readonly static unit array Unit
readonly static integer Count = 0
readonly static integer array List
implement UnitDexConfig
private static integer Counter = 0
implement UnitDexCore
endstruct
/****************************************************************/
private module UnitDexCore
static method Remove takes unit u, boolean runEvents returns boolean
local integer i
if (IsUnitIndexed(u)) then
set i = GetUnitId(u)
set UnitDex.List[i] = Index
set Index = i
call GroupRemoveUnit(UnitDex.Group, u)
call SetUnitUserData(u, 0)
if (runEvents) then
set UnitDex.LastIndex = i
set E = EVENT_UNIT_DEINDEX
call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
set E = -1
endif
set UnitDex.Unit[i] = null
set UnitDex.Count = UnitDex.Count - 1
return true
endif
return false
endmethod
private static method onGameStart takes nothing returns nothing
local integer i = 0
static if (not LIBRARY_GroupUtils) then // Check if GroupUtils exists so we can use it's enumeration group.
local group ENUM_GROUP = CreateGroup() // If not, create the group.
endif
// Index preplaced units
loop
call GroupEnumUnitsOfPlayer(ENUM_GROUP, Player(i), FilterEnter)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
static if (not LIBRARY_GroupUtils) then
call DestroyGroup(ENUM_GROUP)
set ENUM_GROUP = null
endif
// run init triggers
set i = 1
loop
exitwhen i > Counter
set LastIndex = i
call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
set E = EVENT_UNIT_INDEX
set E = -1
set i = i + 1
endloop
set LastIndex = Counter
set Initialized = true
set FilterEnter = null
call DestroyTimer(GetExpiredTimer())
endmethod
private static method onEnter takes nothing returns boolean
local unit u = GetFilterUnit()
local integer i = GetUnitId(u)
local integer t = Index
if (i == 0 and thistype.Enabled) then
// If a filter was defined pass the unit through it.
static if (thistype.onFilter.exists) then
if (not thistype.onFilter(u)) then
set u = null
return false // check failed
endif
endif
// Handle debugging
static if (thistype.DEBUG_MODE and thistype.ALLOW_DEBUGGING) then
if (t == 0 and Counter+1 >= JASS_MAX_ARRAY_SIZE) then
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "UnitDex: Maximum number of units reached!")
set u = null
return false
endif
endif
// Add to group of indexed units
call GroupAddUnit(thistype.Group, u)
// Give unit the leave detection ability
call UnitAddAbility(u, thistype.DETECT_LEAVE_ABILITY)
call UnitMakeAbilityPermanent(u, true, thistype.DETECT_LEAVE_ABILITY)
// Allocate index
if (Index != 0) then
set Index = List[t]
else
set Counter = Counter + 1
set t = Counter
endif
set List[t] = -1
set LastIndex = t
set thistype.Unit[t] = u
set Count = Count + 1
// Store the index
call SetUnitUserData(u, t)
if (thistype.Initialized) then
// Execute custom events registered with RegisterUnitIndexEvent
call TriggerEvaluate(IndexTrig[EVENT_UNIT_INDEX])
// Handle TriggerRegisterUnitIndexEvent
set E = EVENT_UNIT_INDEX
// Reset so the event can occur again
set E = -1
endif
endif
set u = null
return false
endmethod
private static method onLeave takes nothing returns boolean
local unit u
local integer i
// Check if order is undefend.
if (thistype.Enabled and GetIssuedOrderId() == 852056) then
set u = GetTriggerUnit()
// If unit was killed (not removed) then don't continue
if (GetUnitAbilityLevel(u, thistype.DETECT_LEAVE_ABILITY) != 0) then
set u = null
return false
endif
set i = GetUnitId(u)
// If unit has been indexed then deindex it
if (i > 0 and i <= Counter and u == GetUnitById(i)) then
// Recycle the index
set List[i] = Index
set Index = i
set LastIndex = i
// Remove to group of indexed units
call GroupRemoveUnit(thistype.Group, u)
// Execute custom events without any associated triggers
call TriggerEvaluate(IndexTrig[EVENT_UNIT_DEINDEX])
// Handle TriggerRegisterUnitIndexEvent
set E = EVENT_UNIT_DEINDEX
// Remove entry
call SetUnitUserData(u, 0)
set thistype.Unit[i] = null
// Decrement unit count
set Count = Count - 1
// Reset so the event can occur again
set E = -1
endif
set u = null
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local player p
local unit u
static if (not LIBRARY_WorldBounds) then // Check if WorldBounts exists, if not then define the necessary vars
local region reg = CreateRegion() // If WorldBounds wasn't found, create the region manually
local rect world = GetWorldBounds()
endif
set FilterEnter = Filter(function thistype.onEnter)
// Begin to index units when they enter the map
static if (LIBRARY_WorldBounds) then
call TriggerRegisterEnterRegion(CreateTrigger(), WorldBounds.worldRegion, FilterEnter)
else
call RegionAddRect(reg, world)
call TriggerRegisterEnterRegion(CreateTrigger(), reg, FilterEnter)
call RemoveRect(world)
set world = null
endif
call TriggerAddCondition(t, Filter(function thistype.onLeave))
set IndexTrig[EVENT_UNIT_INDEX] = CreateTrigger()
set IndexTrig[EVENT_UNIT_DEINDEX] = CreateTrigger()
loop
set p = Player(i)
// Detect "undefend"
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, null)
// Hide the detect ability from players
call SetPlayerAbilityAvailable(p, thistype.DETECT_LEAVE_ABILITY, false)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TimerStart(CreateTimer(), 0, false, function thistype.onGameStart)
endmethod
endmodule
endlibrary
library PlayerUtils
/**************************************************************
*
* v1.2.8 by TriggerHappy
*
* This library provides a struct which caches data about players
* as well as provides functionality for manipulating player colors.
*
* Constants
* ------------------
*
* force FORCE_PLAYING - Player group of everyone who is playing.
*
* Struct API
* -------------------
* struct User
*
* static method fromIndex takes integer i returns User
* static method fromLocal takes nothing returns User
* static method fromPlaying takes integer id returns User
*
* static method operator [] takes integer id returns User
* static method operator count takes nothing returns integer
*
* method operator name takes nothing returns string
* method operator name= takes string name returns nothing
* method operator color takes nothing returns playercolor
* method operator color= takes playercolor c returns nothing
* method operator defaultColor takes nothing returns playercolor
* method operator hex takes nothing returns string
* method operator nameColored takes nothing returns string
*
* method toPlayer takes nothing returns player
* method colorUnits takes playercolor c returns nothing
*
* readonly string originalName
* readonly boolean isPlaying
* readonly static player Local
* readonly static integer LocalId
* readonly static integer AmountPlaying
* readonly static playercolor array Color
* readonly static player array PlayingPlayer
*
**************************************************************/
globals
// automatically change unit colors when changing player color
private constant boolean AUTO_COLOR_UNITS = true
// use an array for name / color lookups (instead of function calls)
private constant boolean ARRAY_LOOKUP = false
// this only applies if ARRAY_LOOKUP is true
private constant boolean HOOK_SAFETY = false // disable for speed, but only use the struct to change name/color safely
constant force FORCE_PLAYING = CreateForce()
private string array Name
private string array Hex
private string array OriginalHex
private playercolor array CurrentColor
endglobals
private keyword PlayerUtilsInit
struct User extends array
static constant integer NULL = 15
readonly player handle
readonly integer id
readonly thistype next
readonly thistype prev
readonly string originalName
readonly boolean isPlaying
readonly static thistype first
readonly static thistype last
readonly static player Local
readonly static integer LocalId
readonly static integer AmountPlaying = 0
readonly static playercolor array Color
static if not (LIBRARY_GroupUtils) then
readonly static group ENUM_GROUP = CreateGroup()
endif
private static thistype array PlayingPlayer
private static integer array PlayingPlayerIndex
// similar to Player(#)
static method fromIndex takes integer i returns thistype
return thistype(i)
endmethod
// similar to GetLocalPlayer
static method fromLocal takes nothing returns thistype
return thistype(thistype.LocalId)
endmethod
// access active players array
static method fromPlaying takes integer index returns thistype
return PlayingPlayer[index]
endmethod
static method operator [] takes player p returns thistype
return thistype(GetPlayerId(p))
endmethod
method toPlayer takes nothing returns player
return this.handle
endmethod
method operator name takes nothing returns string
static if (ARRAY_LOOKUP) then
return Name[this]
else
return GetPlayerName(this.handle)
endif
endmethod
method operator name= takes string newName returns nothing
call SetPlayerName(this.handle, newName)
static if (ARRAY_LOOKUP) then
static if not (HOOK_SAFETY) then
set Name[this] = newName
endif
endif
endmethod
method operator color takes nothing returns playercolor
static if (ARRAY_LOOKUP) then
return CurrentColor[this]
else
return GetPlayerColor(this.handle)
endif
endmethod
method operator hex takes nothing returns string
return OriginalHex[GetHandleId(this.color)]
endmethod
method operator color= takes playercolor c returns nothing
call SetPlayerColor(this.handle, c)
static if (ARRAY_LOOKUP) then
set CurrentColor[this] = c
static if not (HOOK_SAFETY) then
static if (AUTO_COLOR_UNITS) then
call this.colorUnits(color)
endif
endif
endif
endmethod
method operator defaultColor takes nothing returns playercolor
return Color[this]
endmethod
method operator nameColored takes nothing returns string
return hex + this.name + "|r"
endmethod
method colorUnits takes playercolor c returns nothing
local unit u
call GroupEnumUnitsOfPlayer(ENUM_GROUP, this.handle, null)
loop
set u = FirstOfGroup(ENUM_GROUP)
exitwhen u == null
call SetUnitColor(u, c)
call GroupRemoveUnit(ENUM_GROUP, u)
endloop
endmethod
static method onLeave takes nothing returns boolean
local thistype p = thistype[GetTriggerPlayer()]
local integer i = .PlayingPlayerIndex[p.id]
// clean up
call ForceRemovePlayer(FORCE_PLAYING, p.toPlayer())
// recycle index
set .AmountPlaying = .AmountPlaying - 1
set .PlayingPlayerIndex[i] = .PlayingPlayerIndex[.AmountPlaying]
set .PlayingPlayer[i] = .PlayingPlayer[.AmountPlaying]
if (.AmountPlaying == 1) then
set p.prev.next = User.NULL
set p.next.prev = User.NULL
else
set p.prev.next = p.next
set p.next.prev = p.prev
endif
set .last = .PlayingPlayer[.AmountPlaying]
set p.isPlaying = false
return false
endmethod
implement PlayerUtilsInit
endstruct
private module PlayerUtilsInit
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local thistype p
set thistype.Local = GetLocalPlayer()
set thistype.LocalId = GetPlayerId(thistype.Local)
set OriginalHex[0] = "|cffff0303"
set OriginalHex[1] = "|cff0042ff"
set OriginalHex[2] = "|cff1ce6b9"
set OriginalHex[3] = "|cff540081"
set OriginalHex[4] = "|cfffffc01"
set OriginalHex[5] = "|cfffe8a0e"
set OriginalHex[6] = "|cff20c000"
set OriginalHex[7] = "|cffe55bb0"
set OriginalHex[8] = "|cff959697"
set OriginalHex[9] = "|cff7ebff1"
set OriginalHex[10] = "|cff106246"
set OriginalHex[11] = "|cff4e2a04"
set thistype.first = User.NULL
loop
exitwhen i == 12
set p = User(i)
set p.handle = Player(i)
set p.id = i
set thistype.Color[i] = GetPlayerColor(p.handle)
set CurrentColor[i] = thistype.Color[i]
if (GetPlayerController(p.handle) == MAP_CONTROL_USER and GetPlayerSlotState(p.handle) == PLAYER_SLOT_STATE_PLAYING) then
set .PlayingPlayer[AmountPlaying] = p
set .PlayingPlayerIndex[i] = .AmountPlaying
set .last = i
if (.first == User.NULL) then
set .first = i
set User(i).next = User.NULL
set User(i).prev = User.NULL
else
set User(i).prev = PlayingPlayer[AmountPlaying-1].id
set PlayingPlayer[AmountPlaying-1].next = User(i)
set User(i).next = User.NULL
endif
set p.isPlaying = true
call TriggerRegisterPlayerEvent(t, p.handle, EVENT_PLAYER_LEAVE)
call ForceAddPlayer(FORCE_PLAYING, p.handle)
set Hex[p] = OriginalHex[GetHandleId(thistype.Color[i])]
set .AmountPlaying = .AmountPlaying + 1
endif
set Name[p] = GetPlayerName(p.handle)
set p.originalName=Name[p]
set i = i + 1
endloop
call TriggerAddCondition(t, Filter(function thistype.onLeave))
endmethod
endmodule
//===========================================================================
static if (ARRAY_LOOKUP) then
static if (HOOK_SAFETY) then
private function SetPlayerNameHook takes player whichPlayer, string name returns nothing
set Name[GetPlayerId(whichPlayer)] = name
endfunction
private function SetPlayerColorHook takes player whichPlayer, playercolor color returns nothing
local User p = User[whichPlayer]
set Hex[p] = OriginalHex[GetHandleId(color)]
set CurrentColor[p] = color
static if (AUTO_COLOR_UNITS) then
call p.colorUnits(color)
endif
endfunction
hook SetPlayerName SetPlayerNameHook
hook SetPlayerColor SetPlayerColorHook
endif
endif
endlibrary
library Camera requires UIMath, PlayerUtils
globals
// configuration
// location on the map where the terrain is the default level
constant real CHECK_DELTAZ_X = 584
constant real CHECK_DELTAZ_Y = -768
constant real SCREEN_WIDTH = 0.544
constant real SCREEN_HEIGHT = 0.302
constant real SCREEN_ASPECT_RATIO = SCREEN_WIDTH/SCREEN_HEIGHT
constant integer CAMERA_DUMMY_TYPE = 'uidm'
constant player CAMERA_DUMMY_PLAYER = Player(bj_PLAYER_NEUTRAL_EXTRA)
// endconfig
public unit array DummyUnit
private real DeltaZ = 0
endglobals
function GetCameraDeltaZ takes nothing returns real
return DeltaZ
endfunction
private function Matrix4Perspective1 takes MATRIX4 Output, real fovy, real Aspect, real zn, real zf returns MATRIX4
return Output.SetValues(2*zn/fovy,0,0,0,0,2*zn/Aspect,0,0,0,0,zf/(zf-zn),1,0,0,zn*zf/(zn-zf),0)
endfunction
private function Matrix4Perspective2 takes MATRIX4 Output, real n, real f, real r, real l, real t, real b returns MATRIX4
return Output.SetValues(2*n/(r-l), 0, (r+l)/(r-l), 0, 0, 2*n/(t-b), (t+b)/(t-b), 0, 0, 0, -(f+n)/(f-n), -2*f*n/(f-n), 0, 0, -1, 0)
endfunction
private function Matrix4Look takes MATRIX4 Output, VECTOR3 PosCamera, VECTOR3 AxisX, VECTOR3 AxisY, VECTOR3 AxisZ returns MATRIX4
return Output.SetValues(AxisX.x,AxisY.x,AxisZ.x,0,AxisX.y,AxisY.y,AxisZ.y,0,AxisX.z,AxisY.z,AxisZ.z,0,-Vec3Dot(AxisX, PosCamera),-Vec3Dot(AxisY, PosCamera),-Vec3Dot(AxisZ, PosCamera),1)
endfunction
struct Camera
VECTOR3 eye
VECTOR3 at
unit target
real distance
real yaw
real pitch
real roll
VECTOR3 axisX
VECTOR3 axisY
VECTOR3 axisZ
private MATRIX4 view
private MATRIX4 projection
private boolean change
integer customValue
method win2World takes real X, real Y, real Range returns VECTOR3
local VECTOR3 Output = VECTOR3.create()
set Output.x = .eye.x+.axisZ.x*Range+X*.axisX.x*SCREEN_WIDTH*Range+Y*.axisY.x*SCREEN_HEIGHT*Range
set Output.y = .eye.y+.axisZ.y*Range+X*.axisX.y*SCREEN_WIDTH*Range+Y*.axisY.y*SCREEN_HEIGHT*Range
set Output.z = .eye.z+.axisZ.z*Range+X*.axisX.z*SCREEN_WIDTH*Range+Y*.axisY.z*SCREEN_HEIGHT*Range
return Output
endmethod
method world2Win takes real X, real Y, real Z returns VECTOR3
local VECTOR3 Pos = VECTOR3.New_1(X, Y, Z)
local boolean b
call Vec3Transform_2(Pos, Pos, .view)
set b = Pos.z < 0
call Vec3Transform_2(Pos, Pos, .projection)
if b then
set Pos.z = -Pos.z
endif
return Pos
endmethod
private method updateDistanceYawPitch takes nothing returns nothing
local real dx = .at.x-.eye.x
local real dy = .at.y-.eye.y
local real dz = .at.z-.eye.z
local real len2d
set .distance = SquareRoot(dx*dx+dy*dy+dz*dz)
set .yaw = Atan2(dy, dx)
set len2d = SquareRoot(dx*dx+dy*dy)
set .pitch = Atan2(dz, len2d)
endmethod
private method updateAxisMatrix takes nothing returns nothing
local MATRIX3 mat
call Vec3Normalize(.axisZ, Vec3Subtract(.axisZ, .at, .eye))
set mat = Matrix3RotationAxis(MATRIX3.create(), .axisZ, -.roll)
call Vec3Normalize(.axisX, Vec3Cross(.axisX, .axisZ, VECTOR3.oneZ))
call Vec3Transform_1(.axisY, Vec3Cross(.axisY, .axisX, .axisZ), mat)
call Vec3Transform_1(.axisX, .axisX, mat)
call Matrix4Look(.view, .eye, .axisX, .axisY, .axisZ)
call mat.destroy()
endmethod
method applyCameraForPlayer takes player p, boolean ignoreChange returns boolean
if GetLocalPlayer() == p then
call SetCameraField(CAMERA_FIELD_ROTATION, .yaw*bj_RADTODEG, 0)
call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, .pitch*bj_RADTODEG, 0)
call SetCameraField(CAMERA_FIELD_ROLL, .roll*bj_RADTODEG, 0)
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, .distance, 0)
call SetCameraTargetController(DummyUnit[GetPlayerId(p)], .at.x, .at.y, false)
call SetCameraField(CAMERA_FIELD_ZOFFSET, .at.z-DeltaZ, 0)
endif
if .change or ignoreChange then
set .change = false
return true
endif
return false
endmethod
method setPosition takes real x, real y, real z returns nothing
local real dx = x-.at.x
local real dy = y-.at.y
local real dz = z-.at.z
set .eye.x = .eye.x+dx
set .eye.y = .eye.y+dy
set .eye.z = .eye.z+dz
set .at.x = x
set .at.y = y
set .at.z = z
set .change = true
endmethod
method setEyeAndAt takes real ex, real ey, real ez, real tx, real ty, real tz returns nothing
set .eye.x = ex
set .eye.y = ey
set .eye.z = ez
set .at.x = tx
set .at.y = ty
set .at.z = tz
call .updateDistanceYawPitch()
call .updateAxisMatrix()
set .change = true
endmethod
method setYawPitchRoll takes real yaw, real pitch, real roll, boolean EyeLock returns nothing
local real Z = .distance*Sin(pitch)
local real XY = .distance*Cos(pitch)
local real X = XY*Cos(yaw)
local real Y = XY*Sin(yaw)
set .yaw = yaw
set .pitch = pitch
set .roll = roll
if EyeLock then
set .at.x = .eye.x+X
set .at.y = .eye.y+Y
set .at.z = .eye.z+Z
else
set .eye.x = .at.x-X
set .eye.y = .at.y-Y
set .eye.z = .at.z-Z
endif
call .updateAxisMatrix()
set .change = true
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set .customValue = 0
set .change = true
set .eye = VECTOR3.New_1(0.0,-922.668,DeltaZ+1367.912)
set .at = VECTOR3.New_1(0, 0, DeltaZ)
set .distance = 0
set .yaw = 0
set .pitch = 0
set .roll = 0
set .axisX = VECTOR3.create()
set .axisY = VECTOR3.create()
set .axisZ = VECTOR3.create()
set .view = MATRIX4.create()
set .projection = Matrix4Perspective2(MATRIX4.create(), 0.5, 10000, -SCREEN_WIDTH/2, SCREEN_WIDTH/2, -SCREEN_HEIGHT/2, SCREEN_HEIGHT/2)
call .updateDistanceYawPitch()
call .updateAxisMatrix()
return this
endmethod
method destroy takes nothing returns nothing
call .eye.destroy()
call .at.destroy()
call .axisX.destroy()
call .axisY.destroy()
call .axisZ.destroy()
call .view.destroy()
call .projection.destroy()
call this.destroy()
endmethod
endstruct
globals
private real TempX = 0
private real TempY = 0
endglobals
private function InitDeltaZ takes nothing returns nothing
local timer t = GetExpiredTimer()
set TempX = GetCameraTargetPositionX()
set TempY = GetCameraTargetPositionY()
call SetCameraPosition(CHECK_DELTAZ_X, CHECK_DELTAZ_Y)
set DeltaZ = GetCameraTargetPositionZ()
call SetCameraPosition(TempX, TempY)
static if (LIBRARY_TimerUtils) then
call ReleaseTimer(t)
else
call DestroyTimer(t)
endif
set t = null
endfunction
private module CamInitModule
private static method onInit takes nothing returns nothing
local integer i = 0
local User user
loop
exitwhen i == User.AmountPlaying
set user = User.fromPlaying(i)
set DummyUnit[user.id] = CreateUnit(CAMERA_DUMMY_PLAYER, CAMERA_DUMMY_TYPE, 0, 0, 0)
call ShowUnit(DummyUnit[user.id], false)
call PauseUnit(DummyUnit[user.id], true)
set i = i + 1
endloop
// init delta z
static if (LIBRARY_TimerUtils) then
call TimerStart(NewTimer(), 0., false, function InitDeltaZ)
else
call TimerStart(CreateTimer(), 0., false, function InitDeltaZ)
endif
endmethod
endmodule
private struct CamInit
implement CamInitModule
endstruct
endlibrary
library UIMath initializer Init
public function R2I_N takes real r returns integer
local integer i = R2I(r)
if (r < I2R(i)+0.5) then
return i
else
return i+1
endif
endfunction
struct VECTOR3
static VECTOR3 Zero
static VECTOR3 oneX
static VECTOR3 oneY
static VECTOR3 oneZ
real x
real y
real z
static method New_0 takes nothing returns VECTOR3
local VECTOR3 this = VECTOR3.create()
set .x = 0
set .y = 0
set .z = 0
return this
endmethod
static method New_1 takes real x, real y, real z returns VECTOR3
local VECTOR3 this = VECTOR3.create()
set .x = x
set .y = y
set .z = z
return this
endmethod
static method New_2 takes VECTOR3 v returns VECTOR3
local VECTOR3 this = VECTOR3.create()
set .x = v.x
set .y = v.y
set .z = v.z
return this
endmethod
method SetValues takes real x, real y, real z returns VECTOR3
set .x = x
set .y = y
set .z = z
return this
endmethod
method Length takes nothing returns real
return SquareRoot(.x*.x+.y*.y+.z*.z)
endmethod
method LengthSq takes nothing returns real
return .x*.x+.y*.y+.z*.z
endmethod
method ToString takes nothing returns string
return "Vector3 id "+I2S(this) + "\nx = "+R2S(.x)+" y = "+R2S(.y)+" z = "+R2S(.z)
endmethod
endstruct
function Vec3Add takes VECTOR3 Output, VECTOR3 v1, VECTOR3 v2 returns VECTOR3
set Output.x = v1.x + v2.x
set Output.y = v1.y + v2.y
set Output.z = v1.z + v2.z
return Output
endfunction
function Vec3Subtract takes VECTOR3 Output, VECTOR3 v1, VECTOR3 v2 returns VECTOR3
set Output.x = v1.x - v2.x
set Output.y = v1.y - v2.y
set Output.z = v1.z - v2.z
return Output
endfunction
function Vec3Scale takes VECTOR3 Output, VECTOR3 v, real r returns VECTOR3
set Output.x = v.x * r
set Output.y = v.y * r
set Output.z = v.z * r
return Output
endfunction
function Vec3Division takes VECTOR3 Output, VECTOR3 v, real r returns VECTOR3
set Output.x = v.x / r
set Output.y = v.y / r
set Output.z = v.z / r
return Output
endfunction
function Vec3Length takes VECTOR3 v returns real
return SquareRoot(v.x*v.x+v.y*v.y+v.z*v.z)
endfunction
function Vec3LengthSq takes VECTOR3 v returns real
return v.x*v.x+v.y*v.y+v.z*v.z
endfunction
function Vec3Normalize takes VECTOR3 Output, VECTOR3 v returns VECTOR3
local real len = SquareRoot(v.x*v.x+v.y*v.y+v.z*v.z)
set Output.x = v.x/len
set Output.y = v.y/len
set Output.z = v.z/len
return Output
endfunction
function Vec3Dot takes VECTOR3 v1, VECTOR3 v2 returns real
return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z
endfunction
function Vec3Cross takes VECTOR3 Output, VECTOR3 v1, VECTOR3 v2 returns VECTOR3
local real y = v1.z * v2.x - v1.x * v2.z
local real z = v1.x * v2.y - v1.y * v2.x
set Output.x = v1.y * v2.z - v1.z * v2.y
set Output.y = y
set Output.z = z
return Output
endfunction
function Vec3Transform_1 takes VECTOR3 Output, VECTOR3 v, MATRIX3 m returns VECTOR3
local real y = v.x*m.m12+v.y*m.m22+v.z*m.m32
local real z = v.x*m.m13+v.y*m.m23+v.z*m.m33
set Output.x = v.x*m.m11+v.y*m.m21+v.z*m.m31
set Output.y = y
set Output.z = z
return Output
endfunction
function Vec3Transform_2 takes VECTOR3 Output, VECTOR3 v, MATRIX4 m returns VECTOR3
local real y = v.x*m.m12+v.y*m.m22+v.z*m.m32+m.m42
local real z = v.x*m.m13+v.y*m.m23+v.z*m.m33+m.m43
local real w = v.x*m.m14+v.y*m.m24+v.z*m.m34+m.m44
set Output.x = (v.x*m.m11+v.y*m.m21+v.z*m.m31+m.m41)/w
set Output.y = y/w
set Output.z = z/w
return Output
endfunction
struct MATRIX3
static MATRIX3 Zero
static MATRIX3 E
real m11
real m12
real m13
real m21
real m22
real m23
real m31
real m32
real m33
static method New_0 takes nothing returns MATRIX3
local MATRIX3 this = MATRIX3.create()
set .m11 = 0
set .m12 = 0
set .m13 = 0
set .m21 = 0
set .m22 = 0
set .m23 = 0
set .m31 = 0
set .m32 = 0
set .m33 = 0
return this
endmethod
static method New_1 takes real r11, real r12, real r13, real r21, real r22, real r23, real r31, real r32, real r33 returns MATRIX3
local MATRIX3 this = MATRIX3.create()
set .m11 = r11
set .m12 = r12
set .m13 = r13
set .m21 = r21
set .m22 = r22
set .m23 = r23
set .m31 = r31
set .m32 = r32
set .m33 = r33
return this
endmethod
static method New_2 takes MATRIX3 m returns MATRIX3
local MATRIX3 this = MATRIX3.create()
set .m11 = m.m11
set .m12 = m.m12
set .m13 = m.m13
set .m21 = m.m21
set .m22 = m.m22
set .m23 = m.m23
set .m31 = m.m31
set .m32 = m.m32
set .m33 = m.m33
return this
endmethod
method SetValues takes real r11, real r12, real r13, real r21, real r22, real r23, real r31, real r32, real r33 returns MATRIX3
set .m11 = r11
set .m12 = r12
set .m13 = r13
set .m21 = r21
set .m22 = r22
set .m23 = r23
set .m31 = r31
set .m32 = r32
set .m33 = r33
return this
endmethod
method ToString takes nothing returns string
return "Matrux3 id "+I2S(this)+"\n"+R2S(.m11)+" "+R2S(.m12)+" "+R2S(.m13)+"\n"+R2S(.m21)+" "+R2S(.m22)+" "+R2S(.m23)+"\n"+R2S(.m31)+" "+R2S(.m32)+" "+R2S(.m33)
endmethod
endstruct
function Matrix3Multiply takes MATRIX3 Output, MATRIX3 M1, MATRIX3 M2 returns MATRIX3
return Output.SetValues(M1.m11*M2.m11+M1.m21*M2.m12+M1.m31*M2.m13,M1.m12*M2.m11+M1.m22*M2.m12+M1.m32*M2.m13,M1.m13*M2.m11+M1.m23*M2.m12+M1.m33*M2.m13,M1.m11*M2.m21+M1.m21*M2.m22+M1.m31*M2.m23,M1.m12*M2.m21+M1.m22*M2.m22+M1.m32*M2.m23,M1.m13*M2.m21+M1.m23*M2.m22+M1.m33*M2.m23,M1.m11*M2.m31+M1.m21*M2.m32+M1.m31*M2.m33,M1.m12*M2.m31+M1.m22*M2.m32+M1.m32*M2.m33,M1.m13*M2.m31+M1.m23*M2.m32+M1.m33*M2.m33)
endfunction
function Matrix3Scaling takes MATRIX3 Output, real x, real y, real z returns MATRIX3
return Output.SetValues(x,0,0,0,y,0,0,0,z)
endfunction
function Matrix3RotationX takes MATRIX3 Output, real a returns MATRIX3
return Output.SetValues(1,0,0,0,Cos(a),-Sin(a),0,Sin(a),Cos(a))
endfunction
function Matrix3RotationY takes MATRIX3 Output, real a returns MATRIX3
return Output.SetValues(Cos(a),0,Sin(a),0,1,0,-Sin(a),0,Cos(a))
endfunction
function Matrix3RotationZ takes MATRIX3 Output, real a returns MATRIX3
return Output.SetValues(Cos(a),-Sin(a),0,Sin(a),Cos(a),0,0,0,1)
endfunction
function Matrix3RotationAxis takes MATRIX3 Output, VECTOR3 v, real a returns MATRIX3
local real cosa = Cos(a)
local real sina = Sin(a)
return Output.SetValues(cosa+(1-cosa)*v.x*v.x,(1-cosa)*v.x*v.y-sina*v.z,(1-cosa)*v.x*v.z+sina*v.y,(1-cosa)*v.y*v.x+sina*v.z,cosa+(1-cosa)*v.y*v.y,(1-cosa)*v.y*v.z-sina*v.x,(1-cosa)*v.z*v.x-sina*v.y,(1-cosa)*v.z*v.y+sina*v.x,cosa+(1-cosa)*v.z*v.z)
endfunction
function Matrix3RotationYawPitchRoll takes MATRIX3 Output, real Yaw, real Pitch, real Roll returns MATRIX3
local real cosa = Cos(Yaw)
local real sina = Sin(Yaw)
local real cosb = Cos(Pitch)
local real sinb = Sin(Pitch)
local real cosy = Cos(Roll)
local real siny = Sin(Roll)
return Output.SetValues(cosa*cosb,cosa*sinb*siny-sina*cosy,cosa*sinb*cosy+sina*siny,sina*cosb,sina*sinb*siny+cosa*cosy,sina*sinb*cosy-cosa*siny,-sinb,cosb*siny,cosb*cosy)
endfunction
struct MATRIX4
static MATRIX4 Zero
static MATRIX4 E
real m11
real m12
real m13
real m14
real m21
real m22
real m23
real m24
real m31
real m32
real m33
real m34
real m41
real m42
real m43
real m44
static method New_0 takes nothing returns MATRIX4
local MATRIX4 this = MATRIX4.create()
set .m11 = 0
set .m12 = 0
set .m13 = 0
set .m14 = 0
set .m21 = 0
set .m22 = 0
set .m23 = 0
set .m24 = 0
set .m31 = 0
set .m32 = 0
set .m33 = 0
set .m34 = 0
set .m41 = 0
set .m42 = 0
set .m43 = 0
set .m44 = 0
return this
endmethod
static method New_1 takes real r11, real r12, real r13, real r14, real r21, real r22, real r23, real r24, real r31, real r32, real r33, real r34, real r41, real r42, real r43, real r44 returns MATRIX4
local MATRIX4 this = MATRIX4.create()
set .m11 = r11
set .m12 = r12
set .m13 = r13
set .m14 = r14
set .m21 = r21
set .m22 = r22
set .m23 = r23
set .m24 = r24
set .m31 = r31
set .m32 = r32
set .m33 = r33
set .m34 = r34
set .m41 = r41
set .m42 = r42
set .m43 = r43
set .m44 = r44
return this
endmethod
static method New_2 takes MATRIX4 m returns MATRIX4
local MATRIX4 this = MATRIX4.create()
set .m11 = m.m11
set .m12 = m.m12
set .m13 = m.m13
set .m14 = m.m14
set .m21 = m.m21
set .m22 = m.m22
set .m23 = m.m23
set .m24 = m.m24
set .m31 = m.m31
set .m32 = m.m32
set .m33 = m.m33
set .m34 = m.m34
set .m41 = m.m41
set .m42 = m.m42
set .m43 = m.m43
set .m44 = m.m44
return this
endmethod
static method New_3 takes MATRIX3 m returns MATRIX4
local MATRIX4 this = MATRIX4.create()
set .m11 = m.m11
set .m12 = m.m12
set .m13 = m.m13
set .m14 = 0
set .m21 = m.m21
set .m22 = m.m22
set .m23 = m.m23
set .m24 = 0
set .m31 = m.m31
set .m32 = m.m32
set .m33 = m.m33
set .m34 = 0
set .m41 = 0
set .m42 = 0
set .m43 = 0
set .m44 = 1
return this
endmethod
method SetValues takes real r11, real r12, real r13, real r14, real r21, real r22, real r23, real r24, real r31, real r32, real r33, real r34, real r41, real r42, real r43, real r44 returns MATRIX4
set .m11 = r11
set .m12 = r12
set .m13 = r13
set .m14 = r14
set .m21 = r21
set .m22 = r22
set .m23 = r23
set .m24 = r24
set .m31 = r31
set .m32 = r32
set .m33 = r33
set .m34 = r34
set .m41 = r41
set .m42 = r42
set .m43 = r43
set .m44 = r44
return this
endmethod
method ToString takes nothing returns string
return "Matrux4 id "+I2S(this)+"\n"+R2S(.m11)+" "+R2S(.m12)+" "+R2S(.m13)+" "+R2S(.m14)+"\n"+R2S(.m21)+" "+R2S(.m22)+" "+R2S(.m23)+" "+R2S(.m24)+"\n"+R2S(.m31)+" "+R2S(.m32)+" "+R2S(.m33)+" "+R2S(.m34)+"\n"+R2S(.m41)+" "+R2S(.m42)+" "+R2S(.m43)+" "+R2S(.m44)
endmethod
endstruct
function Matrix4Multiply takes MATRIX4 Output, MATRIX4 M1, MATRIX4 M2 returns MATRIX4
return Output.SetValues(M1.m11*M2.m11+M1.m21*M2.m12+M1.m31*M2.m13+M1.m41*M2.m14,M1.m12*M2.m11+M1.m22*M2.m12+M1.m32*M2.m13+M1.m42*M2.m14,M1.m13*M2.m11+M1.m23*M2.m12+M1.m33*M2.m13+M1.m43*M2.m14,M1.m14*M2.m11+M1.m24*M2.m12+M1.m34*M2.m13+M1.m44*M2.m14,M1.m11*M2.m21+M1.m21*M2.m22+M1.m31*M2.m23+M1.m41*M2.m24,M1.m12*M2.m21+M1.m22*M2.m22+M1.m32*M2.m23+M1.m42*M2.m24,M1.m13*M2.m21+M1.m23*M2.m22+M1.m33*M2.m23+M1.m43*M2.m24,M1.m14*M2.m21+M1.m24*M2.m22+M1.m34*M2.m23+M1.m44*M2.m24,M1.m11*M2.m31+M1.m21*M2.m32+M1.m31*M2.m33+M1.m41*M2.m34,M1.m12*M2.m31+M1.m22*M2.m32+M1.m32*M2.m33+M1.m42*M2.m34,M1.m13*M2.m31+M1.m23*M2.m32+M1.m33*M2.m33+M1.m43*M2.m34,M1.m14*M2.m31+M1.m24*M2.m32+M1.m34*M2.m33+M1.m44*M2.m34,M1.m11*M2.m41+M1.m21*M2.m42+M1.m31*M2.m43+M1.m41*M2.m44,M1.m12*M2.m41+M1.m22*M2.m42+M1.m32*M2.m43+M1.m42*M2.m44,M1.m13*M2.m41+M1.m23*M2.m42+M1.m33*M2.m43+M1.m43*M2.m44,M1.m14*M2.m41+M1.m24*M2.m42+M1.m34*M2.m43+M1.m44*M2.m44)
endfunction
private function Init takes nothing returns nothing
set VECTOR3.Zero = VECTOR3.New_0()
set VECTOR3.oneX = VECTOR3.New_1(1,0,0)
set VECTOR3.oneY = VECTOR3.New_1(0,1,0)
set VECTOR3.oneZ = VECTOR3.New_1(0,0,1)
set MATRIX3.Zero = MATRIX3.New_0()
set MATRIX3.E = MATRIX3.New_1(1,0,0,0,1,0,0,0,1)
set MATRIX4.Zero = MATRIX4.New_0()
set MATRIX4.E = MATRIX4.New_1(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* -------------
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
globals
// High enough so the unit is no longer visible, low enough so the
// game doesn't crash...
//
// I think you need 0.0 or soemthing negative prior to patch 1.22
//
private constant real EXTRA = 700.0
endglobals
//=========================================================================================
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
local real x2=x
local real y2=y
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
if (x != x2) then
call SetUnitX(u,x)
endif
if (y != y2) then
call SetUnitY(u,y)
endif
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
//this is not necessary but I'll do it anyway:
set t=null
set r=null
set rc=null
endfunction
endlibrary