//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
AntiBuildingCheck | group | No | |
AT_Counter | integer | No | |
AT_Group | group | No | |
AT_Point | location | Yes | |
AT_Timer | timer | Yes | |
AT_Timer_Copy | timer | Yes | |
BuildTrigger | trigger | Yes | |
CanSetMode | boolean | No | |
CenterPos | location | No | |
CommandGroup | group | No | |
ConquerGr | group | No | |
CookhouseCheckGroup | group | No | |
Count_Time | integer | No | |
Counter | integer | No | |
CTFFlag | item | No | |
DominationGr | group | No | |
ExtraModeLeaderboard | leaderboard | No | |
ExtraModeSet | boolean | No | |
Facility_Group | group | Yes | |
GeneratorDefendedBuilding | unit | Yes | |
GeneratorDefending | unit | Yes | |
GeneratorDefendingCounter | integer | No | |
GoldInTargetedMine | unit | No | |
i | integer | No | |
IDP_GoAhead | boolean | No | |
IDP_LimitDistance | real | No | |
IDP_RallyPoint | location | No | |
IDP_StrucPoint | location | No | |
IDP_Units | unitcode | Yes | |
IsObserver | boolean | Yes | |
KOTH_Gr | group | No | |
KOTH_PLGR | force | No | |
KOTH_UnitCount | integer | Yes | |
KOTHGrCheckEnemies | group | No | |
KOTHGrCheckFriends | group | No | |
Leaderboard | leaderboard | No | |
ManaBombGr | group | No | |
MapWidth | real | No | |
MB_TempCount | integer | No | |
MB_TempEffect | effect | Yes | |
MortarBomb | unit | Yes | |
ObsLeaderboard | leaderboard | No | |
Oddball | item | No | |
PDD_allocatedAttacks | integer | No | |
PDD_allocCounter | integer | No | |
PDD_amount | real | No | |
PDD_ATTACK_TYPE_UNIVERSAL | attacktype | No | |
PDD_BRACERS_SPELL_DMG_RED | real | No | |
PDD_CODE | integer | No | |
PDD_DAMAGE_TYPE_DETECTOR | integer | No | |
PDD_damageEvent | trigger | No | |
PDD_damageEventTrigger | real | No | |
PDD_damageHandler | trigger | No | |
PDD_damageType | integer | No | |
PDD_ETHEREAL_DAMAGE_FACTOR | real | No | |
PDD_h | hashtable | No | |
PDD_PHYSICAL | integer | No | |
PDD_pureAmount | real | No | |
PDD_runAllocatedAttacks | trigger | No | |
PDD_SET_MAX_LIFE | integer | No | |
PDD_source | unit | No | |
PDD_SPELL | integer | No | |
PDD_SPELL_DMG_REDUCTION_ITEM | integer | No | |
PDD_SPELL_RESIST_AUTO_DETECT | boolean | No | |
PDD_target | unit | No | |
PDD_totalAllocs | integer | No | |
PDD_TRIGGER_CLEANUP_PERIOD | real | No | |
PDD_UNIT_MIN_LIFE | real | No | |
PlayerGroupMode | force | No | |
ResearchedMagicSentry | boolean | Yes | |
ResearchedPath | boolean | Yes | |
S_Hours | string | No | |
S_Minutes | string | No | |
S_Seconds | string | No | |
Score_Buildings | integer | Yes | |
Score_CTF | integer | Yes | |
Score_Domination | integer | Yes | |
Score_KOTH | integer | Yes | |
Score_KOTHChecked | boolean | Yes | |
Score_Oddball | integer | Yes | |
SeasonSet | boolean | No | |
SeasonsXCount | integer | No | |
SeasonsYCount | integer | No | |
SetModeTimer | timer | No | |
StoreUnit_Counter | integer | Yes | |
StoreUnit_FoodCap | integer | No | |
StoreUnit_HP | real | Yes | |
StoreUnit_Mana | real | Yes | |
StoreUnit_Storage | unitcode | Yes | |
StoreUnitBeginCount | integer | No | |
StoreUnitConstant | integer | Yes | |
StoreUnitFinishCount | integer | No | |
t | trigger | No | |
T_Hours | integer | No | |
T_Minutes | integer | No | |
T_Seconds | integer | No | |
Temp_PlayerN | integer | No | |
TempAngle | real | No | |
TempDistance | real | No | |
TempInt | integer | No | |
TempLoc | location | No | |
TempNum | integer | No | |
TempObsCommInt | integer | No | |
TempPlayer | player | No | |
TempPoint | location | No | |
TempPt1 | location | No | |
TempPt2 | location | No | |
TempPt3 | location | No | |
TempPt4 | location | No | |
TempSeasonnYPoint | location | No | |
TempTree | unit | No | |
TempUnit | unit | No | |
TempYPoint | location | No | |
TilesCheckAreaIncrement | integer | No | |
Time | string | No | |
Time_Elapsed | timer | No | |
Time_W | timerdialog | No | |
TimeL | leaderboard | No | |
TopCornerPoint | location | No | |
TowerLoc | location | No | |
TownhallMain | unit | Yes | |
Tree | destructable | Yes | |
Tree_Copy | destructable | Yes | |
TreeCount | integer | No | |
TreeDummy | unit | Yes | |
TreePreservation | boolean | Yes | |
Upgrade_Constr_Speed | integer | Yes | |
Void_Rift | unit | No | |
Void_Rift_Loc | location | No | |
Void_Rift_NextP | location | No | |
Void_Rift_Search | group | No | |
Void_Rift_SelfLoc | location | No | |
Void_Rift_Units | group | No | |
Weather | weathereffect | No | |
WeatherSet | boolean | No | |
WyvernTeamColorB | real | Yes | |
WyvernTeamColorG | real | Yes | |
WyvernTeamColorR | real | Yes |
//TESH.scrollpos=486
//TESH.alwaysfold=0
// MY NOTES FOR VERSION 1.5 AND THEIR FIXES:
// > removed spiked barricades from LUMBER MILL// update all descriptions
// > moved ensnare fro mblacksmith to barraacks with castle requriement
// > edited Captain's priority
// > Now Castle requires any of the four Altar of Kings
// > increased all mines
// > farms now can load peasants instead of peons as it should be
// >added battle stations ability to the Magical Farms
// add zepelin
// ghost has some bug> remove worker classif
// > Sorceress' Corporeal Foorm fixed
// > In ethereal form, fixed Sorceress abilities
// > Chaplain's Cyclone now requires priest adept training as should
// > On chaplain rearranged ability positions
// add the effect back onto the magical farms
// > Fixed the collision shape of the Wall Tower
//> Edited tooltips of PRiest, Chaplain and Sorceress
// > Fixed Mortar Team Tooltip
//----------------------------------------------
// VERSION 1.6:
// bULLET Storm Buff moved from blacksmith to barracks
// Added requirement for Blacksmith to Ensnare Upgrade
// The default active ability of Chaplain is now Replanish Mana
// Arcane Fire now Requires Power Blst
// Dragonshawk rider's attack 1 now does not attack structures as it should be
// The buff of Heroic Presence of the Captain is now fixed
// Magical Farm's attack is now visible as missile
// added goblin zepelin and goblin sapper to workshop
// Ghost's sight range increaseed to 1000 for both
// To chaplain added the used upgrades
// Caster Upgrade Tooltips of Sorceress, Priest and Chaplain are fixed
//----------------------------------------------
// VERSION 1.7:
// - swapped posession and holy protection
// - added holy armor ability to priest
// - wall tower can now be lowered
// - Chaplain renamed to shadow priest.
// -Battle Stations now checks for dependencies
//- Pillage is now used by footmen and captains too
// - Gryphon Riders now can use Shamanism upgrade and that teaches them 3 ward abilities.
// - Mortar Bomb is moved to the Workshop
// Soem changes in Priest, Shadow Priest and Sorceress
//----------------------------------------------
// VERSION 1.8:
// - added cooldown to Illusion
// - added golbi nshredder to Lumber MIll
// - ineer repairs also work for mechanical units
// - Arcane Fire's buff is fixed and has its color
// DRagonhawk Rider can now use Recall abiility, and Blink and Recall require an ugprade.
// - Arcane burns also requires upgrade now
// - Blood Elf Engineer is made to look like peasant and has the same abilities as a peasant.
// - Peasant's work animation oes not loop anymore
//----------------------------------------------
// VERSION 1.9:
// - ghost no longer has collision
// - Sorceress in ethereal form has the same abilities (fix)
// - fixed hotkey yand mana of Recall
// - Shredder tooltip changed to build
// - Added Godsight ability to Castle which allows to revveal the whole map
// - Edited the tooltip of Knight
// - Edited Mortar Team tooltip
// Added to Mortar Team Kaboom! and Goblin Land Mine
// - Increaswed damage of mortar bomb to 700
// - Magical Farm has lower scale and has an effect overhead when you research Magic Sentry
// - Fixed the tooltip of Shadow Priest
//----------------------------------------------
// VERSION 1.10:
// - enabled attack of engineer
// - fixed tooltip of Spell
// - added unload all ability to magical farm
// - Gryphon rider now can dismount to shaman and grypho nand can take stone form.
//----------------------------------------------
// VERSION 1.11:
// - To Spell Breaker added MAna Bomb and Mana Flare
// - Fixed food required by gryphon and shaman
//----------------------------------------------
// VERSION 1.12:
// - removed Blight growth from Mining FAcility
// - Added Arcane REpellent (anti-air blocker) building on engineer.
// - Now Arcane Vault can also switch between race shops!
//----------------------------------------------
// VERSION 1.14:
// - Engineer is slightly bigger and has tinting color
// - added effect on the magical farms after they are upgraded with Magic Sentry
// - Fixed the bug of Wall Tower, where after morphing you couldn't select it normally.
// - updated descriptions of Spell Breaker and Mortar Team
//----------------------------------------------
// VERSION 15:
// - Changed gold cost for Magical Farm
// - Fixed the bug of Shadow Priest's Curse
// - Fixed the requirement of Tier 3 items in all races shops
// - Mana Bomb effect and cooldown fixed
// - Added an effect on Arcane Repellent
// - Fixed the Build icon of the peasants
// - Fixed teh bug of Mortar bomb where if the mortar teams dies whiile channeling, you won't be able to make new mortar bombs
// - Added building used upogrades on Arcane Repellent
// - Added Arcane Heat on Arcane Repellent
//----------------------------------------------
// VERSION 16:
// - edited map description
// - Unmounted Gryphon has portrait now]
//----------------------------------------------
// VERSION 17:
// - edited the tooltip or Engineer and Arcane Repellent.
// - REmoved Ward Classifiction from Wall Towers
//----------------------------------------------
// VERSION 18:
// - added Sky-Fury Tower to upgrades of Human Tower
// - added Cold Tower to upgrades of Human Tower
// - changed the pathing map of Arcane Repellent and Wall Tower (Lowered)
// - added an upgraded version of Arcanen REpellent with red glow effect
// - Updated some tooltips
// - All towers now have fortified armor type
// Peasant or Engineer no longer retain build ability when turning into ghost.
//----------------------------------------------
// VERSION 19:
// - the sound of human build error is fixed
//----------------------------------------------
// VERSION 20:
// - added team number next to the player name
// - now Magical Farm will not have disabled abilities, but instead will upgrade when research is completed.
// - edited the tooltip of change building type
// - Replaced the sound made when loading peasants in Mining Facility
// - To human tower added upgrade Death Tower
// - Added research to increase all towers range and sight
// - Now instead of training the Engineer you promote him from the peasant
// - Ghost has less hit points now (125)
// - Added Fortress Tower to Engineer
//----------------------------------------------
// VERSION 21:
// - Added the missing inner repairs ability to Arcane Repellent
// - changed the hotkey of spirit link to stop the hotkeys conflict with Replenish Mana
// - changed the hotkey of Moortar Bomb to stop the hotkeys conflict with Kaboom
// = Edited the tooltip of Mortar Bomb
// - The icon of Heroic Presence's buff is no longer passive
// - Now if you select a race different from human, the starting units will turn into human
// - Arcane Heat's tooltip is fixed
// - Added Overload Ability to Arcane Repellent (Upgraed)
// - Added Demolish ability to Engineer
// - Replaced undead lumber error with human
// - Bullet storm now has the right buff
// - Changed the model of the trees
//----------------------------------------------
// VERSION 22:
// - Cold tower now can also freeze buildings that it attacks
// - Fixed the model of Hospital: attachment point and extended foundation(for when placed on hills)
// - Peasants now can also Pillage
// - added tutorial message on Start
// - Added item to create stone path on the ground in all shops
// - Added -obs commmand
// - Engineer can build Path, Library, Bank
// - To enginer added the missing used upgrades
// - Changed the portrait of Hospital
// - Tooltip fixes
// - Updated the icon of Wall Tower
// - Updated the icon of Mining Facility
// - Updated the icon of Arcnae Repellent
// - Rearranged the buildings in Enigneer
// - Changed the model of the trees
// - other
//----------------------------------------------
// VERSION 23:
// - increased the size of selection of the Bank and the Hospital
// - Items bought from the bank go into the heroes, not on the ground now
// - Change altar type ability is renamed
// - Added the missing attachments points to the models of the Library and the Hospital
// - Lowered the height of the Library model
//----------------------------------------------
// VERSION 24:
// - added Arcane Shot ability and research for Rifleman
// - Rifleman's Bullet Storm renamed to Rapid Fire
// - Raised the price of Library and Bank
// - Now Cyclone really requires Shamaism upgrae
// - Edited tooltip of Spiked Barricades
// - Added cluster rocket ability and upgrade for Siege Engine
// - The Mortar bomb upgrade has changed hotkey
// - Fixed the birth animation of Hospital
//----------------------------------------------
// VERSION 25:
// - Library's model and icon is updated. Now the roof bricks will be team colored (credit to Rodrigooo from Hiveworkshop https://www.hiveworkshop.com/threads/model-edit-request-team-color-on-building.329060/#post-3460407
// - Mining Facility hotkey changed because it had conflict with Fortress hotkey
// - Illusion's hotkey is fixed
// - Sorceress' Ethereal Form hotkeys changed
// - Footman's Promote To Captain hotkey changed and set
// - Rifleman's Arcane Shot second icon fixed
// - Rifleman's Rapid fire tooltip and hotkey fixed
// - Priest's Holy Protection's Buff's Icon is fixed
// - Priest's Holy Protection targeting includes self
// - Priest's Holy Protection Buff and target models updated
// - Shadow Priest's Plague description typo is fixed
// - Shadow Priest's Spawn Spiders hotkey changed
// - Hyper Injection Hotkey fixed
//----------------------------------------------
// VERSION 26:
// - (fix) Promote to captain tooltip fixed
// - (fix) Mining Facility's Soundset is changed to Mine
// - (new) To Arcane Sanctum added Terror unit which is an invisible attacker that spreads plague
//----------------------------------------------
// VERSION 27:
// - (fix) plague spreader (now Callback)'s caster effect fixed
// - (fix) Riflemen's mana regen fixed when upgraded with arcane shot
// - (NEW) Placed 4 more Gold Mines, for the players that are not in the corners
// - (fix) Replaced the icon of Path Generator
// - (NEW) Added an upgrade that will make all buildings spread stone path. (decorative)
// - (fix) Fixed the position of the starting location of bottom middle player
// - (fix) at top left corner rearranged the neutral buildings so that you dont have stuck units
// - (fix) Updated the tooltip of Horror,Terror,Nightmare
// - (fix) For players who pick undead race, the ghoul turns into 2 peasants now
// - (fix) For players who pick another race, added call to arms to town hall
// - (fix) changed the dummy mining-facility-creator into a non-building so that it doesnt cause bug when a player gets defeated
// - (NEW) added Pack Horse unit to town halls, which is a carrier that also provides food and can turn into knight with a footman
// - (NEW) added Force Field ability to Flying Machine
// - (fix) In an attempt to fix teh bug with the Magical farm where you cannot build it sometimes, the the Arcane Sentry upgrade now will change building availability for the magical farm
// - (fix) fixed the construction loop sound effect on some human buildings
//----------------------------------------------
// VERSION 28:
// - (fix) returned the attack to Horror
// - (fix) other
// - (fix) fixed the attachment for for spiked barricades of the library
// - (fix) Priest and Shadow Priest Tooltip Fixes
// - (fix) Mortar Bomb's upgrade tooltip fixed and the unit is no longer selectable
// - (fix) Cold Tower description fixed
// - (NEW) Added Assassin unit to Barracks
// - (fix) Attempted to fix the magical farm bug by recreating the unit
// - (fix) Hotkeys of Spiked Barricades and Stone Path upgrades changed to avoid hotkey conflict
// - (change) Library now requires Castle and is more expensive. This is to stop the player from having op heroes fast.
// - (fix) - The requirements of the heroes of the tavern are fixed for only human
//----------------------------------------------
// VERSION 29:
// - (fix) Mining Facility now can also be demolished by the Engineer
// - (fix) Mining Facility's armor increased from 2 to 5 to be the same the other buildings
// - (fix) Mining Facility now uses the Improved Masonry upgrade like the other buiildings
// - (fix) Magical Farm's food produced fixed back to 10
// - (fix) Frenzy's mana required fixed from 0 to 40
// - (fix) Dragonhawk Rider's Recall now also summons mechanical units
// - (fix) Cold Tower and Chaos Tower will no longer remove Stone Path
// - (fix) Ghost will no longer be shown as an idle worker
// - (fix) to Sky-Fury Tower, Chaos Tower and Cold Tower added the required Magic Sentry upgrade as it should be
// - (NEW) Added spirit wyvern unit to Gryphon Aviary
//----------------------------------------------
// VERSION 30:
// -(fix) Ghost reverted to being idle worker, because the otehr way was buggy
// -(fix) Ghost form hotkey changed
// -(fix) added a trigger to force add Magic Sentry effect on Cold Tower, Death tower and Sky-Fury Tower
// - (change)Spirit Wyvern is now classified as summoned.
//----------------------------------------------
// VERSION 31:
// - (fix) changed hotkey of dispel maagic
// - (fix) fixed the bug where footmen and knights would not get upgrade to their attack with iron forged swords. This is because the Medical Training upgrade was causing the bug.
//----------------------------------------------
// VERSION 32:
// - (NEW) - added Power Generator building to Engineer
// - (fix) - tooltip fixes
// - (change) - Shamanism is more expensive and has more research time
// - (fix) added overhead attachment to Library
//----------------------------------------------
// VERSION 32a:
// - (fix) - fixed teh bug with teh power gnerator defend where it would leave building invulnerable
//----------------------------------------------
// VERSION 33:
// - (fix) - changed the button position of sky-fury tower
// - (fix) - now when the generator stops casting automatically Defend Building, the building will become vulnerable
// - (change) - exchanged the hotkeys of dispel and judgement
// - (NEW) - added Mage Tower to Tower upgrades
// - (NEW) - added Human Battleship to Gryhpoon Aviary
// - (NEW) - Siege machine can be transformed into Infiltrator that is a unit without an attack, but very hard to kill and has cargo capacity.
// - (NEW) - added upgrade for capacity of Infiltrator and Battleship
// - (fix) - when you surrender with -obs, all buildings become vulnerable (power generator related)
// - (fix) - recreated Sorceress (Ethereal) because it had an ID conflict with an item
// - (fix) - fixed the sprite attachment points of Wall Tower (Lowered)
// - (fix) - tooltip fixes
// - (fix) - Instant Poison now really stuns for 3 seconds.
// - (change) - removed the special effect from God Sight ability
// - (change) - Added a solution to the tooltip of Mining faciliity that tells you what to do if you can't load peasants inside.
// - (change) - Magic Sentry upgrade is now more expensive and takes more times to complete
//----------------------------------------------
// VERSION 34:
// - (fix) changed hotkey of rapid fire upgrade
// - (fix) - fixed tooltip of battleship and Hospital
// - (fix) - Added the missing Unload ability to Battleship
// - (fix) - Siege engine's tooltip now says that it can transform into infiltrator.
// - (fix) - Reduced the attack range of Battleship Spawn and lowered the height of his selection circle and increased his stock delay to 10 seconds
// - (fix) - Battleship's food increased to 12 because he is too powerful
// - (fix) - fixed the attack of the upgraded cargo hold for Battleship
// - (fix) - In order to promote Engineer unit I made one of your peasant to become an engineer when the game begins
// - (NEW) - New building - Cookhouse
// - (NEW) - New building - Plantation
// - (NEW) - added a window that shows time passed. Decorative.
// - (channge) - Battleship spawn now has variable attack
// - (channge) - PAck horse moved to Plantation
// - (fix) - Fixed food of Captain and Pack Horse
// - (fix) - Footman's Mount Horse now works
// - (fix) - Removed blight dispel from Mining Facility
// - (fix) - the Load ability of Mining Facility and Plantation now has in its tooltip Peasant instead of Wisp
//----------------------------------------------
// VERSION 35:
// - now all gold mines have 35k gold
// - Promote to engineer requires Blacksmith now
// - Next to the name of the depleted Plantation tehr is "(Depleted)"
// - The items of the Bank are now visible only to the player ("made" instead of "sold")
//- Defend building has edited tooltip
// - Spyrit Wyvern now has team color
// - Fixed the basis of the models of Library, Plantation, Bank, Hospital, Power Generator
// - NEW ability - Dispel Sentry for Flying Machine
//----------------------------------------------
// VERSION 35b:
// - (NEW) - NEW ability - Anti-building Ward for Flying Machine
// - (fix) - Ethereal sorceress fixed name
// - (fix) - now when the mortar team cancels mortar bomb there will be a message
// - (fix) - Fixed bank's trading
// - (fix) - fixed bank's model
// - (fix) - Manually added 35k gold to each mine, because the trigger wasnt working for some reason
// - (change) - Battleship's supply made to 16. His spawns take 2 supply and deals less damage, and his attack cooldown increased to 3 seconds.
// - (fix) - arcane repellent now can also be demolished by the engineer
//----------------------------------------------
// VERSION 36:
// - (fix) nerfed Battleship?
// - (fix) remade the holy protection buff
// - (fix) when you pick another race the workers can build properly
// - (fix) the human towers' attack will no longer show that there is an upgrade to attack when there isn't
// - (NEW) New tower upgrade: Command Tower - normal attack and can send a lot of troops to battle
// - (change) - changed teh icon of Promote to Engineer and Engineer
//----------------------------------------------
// VERSION 37:
// (fix) - changed the hotkey of Command Tower
// (fix) - removed some ashenvale trees
// - (fix) fixed the sprite attachment points of command tower
// - (fix) recreated the trigger that stops you to build if there is a nearby anti-building ward
// - (fix) - hotkey of Power Blast upgrade changned
// - (DELAYED) - added new unit: Shade that can transform into targeted non-hero unit
// - (NEW) - added modes with commands
// - (NEW) - when you surrender with -obs or be defeated and become an observer, a leaderboard will be shown with the observing players
//----------------------------------------------
// VERSION 38:
// - (NEW) - NEW BUILDING: Enhancer
// - (NEW) - NEW BUILDING: Spy Tower upgrade
// - (Change) - Battle Shout and Heroic Presence now applies only to organic units
// - (fix) - attempt to fix the message for cancelled mortar bomb when it fires
//----------------------------------------------
// VERSION 39:
// - (fix) - spy tower's price is set, and it requires now arcane sanctum
// - (fix) - Enhancer's hotkey is changed
// - (fix) - Enhancer's aura also puts effect overhead of self
// - (fix) - fixed Enhancer's birth animation to include the construction basis
// - (NEW) - Enhancer also provides mana regen now
// - (NEW) - Added map terrain modes based on seasons - Spring, Summer, Winter. By default it's Autumn.
// - (NEW) - Added map weatehr commands.
//----------------------------------------------
// VERSION 40:
// - (NEW) - new weather modes: hell, desert, glacier
// - (fix) - attempt to fix the bug of observers leaderboad where leaving players appeared
// - (fix) - to fix the bug where enhancer will give aura while not finished construction, his abilities are added after the construction finishes
// - (NEW) - New unit: SHADE - can copy any unit for the same price
// - (change) Arcane Shot upgrade moved to Barracks with sanctum requirement and
// - (NEW) new unit added to Sanctum: Shade - which can transform into any non-hero organic unit
// - (fix) - assassin's hotkey changed
//----------------------------------------------
// VERSION 41:
// - (change) - Sky-fury tower now has th_ same attack and attack speed and cost like the Canon Tower
// - (change) - Tower Range upgrade now gives 100 more range
// - (fix) - assassin can no longer attack air
// - (fix) - removed some more ashenvale trees from the map
// - (fix) -now you can set only 1 mode of game. (not extra)
// - (NEW) - new unit: Barbarian (transformed from Knight) - same as knight, but has siege attack
// - (NEW) - new extra modes. Now you can set 1 of each 4 options for modes.
// - (NEW) - new weather mode: storm - heavy rain combined with wind
//----------------------------------------------
// VERSION 41b:
// - (fix) - marketplace trigger will be disabled in certain modes
// - (fix) - Attempt to fix the sometimes 'cant build with engineer' bug
// - (fix) - in -ctf mode all teleportation methods are disabled. Scroll of Town Portal, Recall,
// - (fix) - ctf mode will always pinpoint the location of the flag
// - (fix) - domination - attempt to fix the changing of the otwner of the checkpoint towers
// (NEW) - modes: onlyheroes and omnlyheroesandnoengineer
// VERSION 41c:
// - related fixes
//----------------------------------------------
//----------------------------------------------
// VERSION 42:
// (FIX)= Mortar Bomb: The message for cancelled mortar bomb will no longer appear after it has been fired.
// (FIX) = sky-fury tower's health increased to be equal to Cannon Tower's and reduced his attack to match cannon tower's.
// (FIX) = On all buildings, the buffs' icons are now visible
// (NEW) = Mage tower has new ability: Death Ward
// (NEW) = Mage tower has new ability: Store Unit
// (NEW) = Mage tower has new ability: Respawn Units
// (NEW) = Mage tower has new ability: Summon Death Storm
// (CHANGE) = in the middle of the map, added rock tiles to prevent building, and removed the lamp. (for non-modified terrain)
// (NEW) = when buildings are repairing themselves, there will be an effect overhead
// (NEW) = added an upgrade that increases mortar bomb's damage by 200 and then 400
// (NEW) = Enhancer has a new ability: Overload: further increases the armor of all affected buildings.
// (NEW) Enhaner has a new ability: Overheat: stun all enemy units around for 5 seconds.
//-----------------------------------------------------------------------------
// (IDEA) = Enhancer can change the attack type of a targeted friendly unit.
//-----------------------------------------------------------------------------
//----------------------------------------------
// VERSION 43:
// - (CHANGE) Mage Tower's Teleportation spells use red version of the effect
// - (FIX) = tooltip fixes
// - (CHANGE) = Death Storm is now targeted as a hero in order to avoid certain bugs
// - (CHANGE) = Death Storm now has no collision size to avoid certain bugs
// - (FIX) = Divine Armor's tooltip fixed, to show for Death Storm that i can be damaged by magic attacks
// - (CHANGE) = Flying Machine now has mana and all his abilities require mana
// - (NEW) = Flying Machine has a new ability: The PeCamaker - disables enemy buildings' attack for 25 secs
// - (CHANGE) = Flying Machine's Dispel Sentry's cooldown lowered to 15 seconds.
// - (FIX) = Flying Machine's Anti-Building aura bility is fixed and now summosn the ward correctly.
//----------------------------------------------
// VERSION 44:
// - (NEW) New buildings: Archway.
// - (FIX) Peasnat's tooltip updated.
//----------------------------------------------
// VERSION 45:
// - (FIX) - anti-building ward ability recreated because it caused ID Conflict, rendering it unusable
// - (FIX) - attempt to fix Overheat Ability
// - (FIX) - Archway's model maintenance
// - (CHANGE) - Mortar Bomb now requires Castle
// - (NEW) - NEW TOWER AVAILABLE - SHOCK TOWER
// - (FIX) - Command tower's upgrade changed
//----------------------------------------------
// VERSION 45a:
// - (FIX) Shock Tower now can attack buildings and its ability has the correct name
// - (NEW) Mercenary Camp now has 12 total units
//----------------------------------------------
// VERSION 45b:
// - (FIX) Mage tower tooltip typo fix
// - (FIX) Shade's Copy abilities now check if the transformation would go above food cap
// - (FIX) Mortar bomb's castle requirement Removed
// - (FIX) Store unit's range increased to 1000 and it no longer targets enemy units
// - (CHANGE) Shock Tower's Shock renamed to Shock Attack
// - (FIX) Shock Tower' now has the missing Magic Sentry Effect overhead
// - (CHANGE) Enhancer's Overload now also gives bonus attack and mana regen
// - (FIX) Enhancer will not have auras until it finishes construction
// - (NEW) When mortar team is channeling Mortar Bomb there will be a special effect attched onto him for the duration of the cast.
//----------------------------------------------
// VERSION 45c:
// - (FIX) Fixed Barbarian's tranformation in the presence of a Cookhouse (missing ability)
// VERSION 45d:
// - (FIX) NOW REALLY FIXED IT
// VERSION 45e:
//- (CHANGE) The long-awaited requested model came, so I change with it the effect of Peacemaker + its icon
// VERSION 45f:
// (NEW) All creep camps now have random creeps isntead of the usual!
//---------------------------
// VERSION 46:
//---------------------------
// (CHANGE) Captain's transformation time reduced to 0.1 second
// (CHANGE) Charge's cooldown increased to 45 seconds.
//(CHANGE) - Cloud now also affects ground enemy units.
// (NEW) - added an ability to mage tower called "Instant Deployment". Buildings affected by it, teleport their trained troops to their rally points. Has limited range.
// (NEW) - New unit: Epic Dragonhawk Rider - similar to Dragonhawk Rider, but has other abilities, a magic attack and is more expensive.
// (NEW) - Abilities for the Epic Dragonhawk Rider:
// new ability: Mist - similar to cloud, but instead blocks range attack of enemy air units
// new ability: ground shackles - similar to aerial chackes, channel it to keep a unit stunned and drain its life. Cannot cast on heroes.
// new ability: Phase Shift (from the night elves)
// new ability: Hide (taken from the night elves)
// new ability: alter time - saves the current position and teleports the unit back to it after a small delay.\
// new ability: Counter-Ambush - makes buildings around invulnerable for 45 seconds. Channeled.
// new ability: Create Caos-Forged Dragonhawk - Merge 2 Epic Dragonhawk Riders to creaate a chaos-forged dragonhawk rider with chaos attack and lightning projectile
// NEW UNIT: Chaos-forged Dragonhawk Rider - mergin 2 epic dragonhawk riders. Can corrupt a town hall
// NEW BUILDINGS: Corrupted Town Hall
// NEW UNIT: Corrupted Peasant - chaos attack, fast
// (NEW) -added new ability to Barbarian - conquer - channels over 60 seconds in melee range to take control over a neutral or an enemy building.
// (NEW) NEW UNIT: Anciennt Builder - can instantly turn into a targeted friendly building
// (FIX) Arcane Sanctum's tooltip updated
// (FIX)Shade's hotkey change
// (NEW) NEW UNIT: Sentry (at barracks)
//---------------------------
// VERSION 46a:
//---------------------------
// (FIX) Added one exception check for ancient builder
// (FIX) Conquer will be interrupted if you make the barbarian invisible or is attacked
// (FIX) Ancient Builder's tooltip
// (FIX) Added unit inventory to missing units (shadow priest, shaman)
// (CHANGE) Removed the transparency from Epic Dragonhawk Rider
//---------------------------
// VERSION 1.47:
//---------------------------
// new unit: Swan Knight - piercing + more damage
// put goblin laboratory to every neutral building place
//---------------------------
// 1.48:
//---------------------------
//- swan spirit trains faster now
//- icons for swan knight changed
//- removed laboratories
//- goblin merchant is now merged into the arcane vault types
//- marketplaces are removed
//- mercenary camps are removed and instead the hall can train a Summoner that serves the same purpose
//---------------------------
// 1.48a:
// - the summoning portals are not invulnerable now and the units's stock recharge is edited to stop you from abusing.
// - set the hotkeys for all summoning portals
// - the summoner can now turn into void rift that serves as a portal to other rifts.
// - the portal buildings now have overhead attachment
//---------------------------
// 1.49:
// - new tower: Siege Tower
// - Void Rift's Void Jump now has a nice animation effect
// - Fixed ID conflicts of the abilities that change the type of the Vault.
// - changed the icon of Enhancer
// - added 4 new upgrades:
//::Construction Expertise/Mastery
//::Arcane Shielding/Improved Arcane Shielding
//::Improved Gather Speed
//::Discipline - allows most units to be trained faster
// - changed the health bar to 1/4
// - summoner now requries only castle
//---------------------------
//// 1.50:
// - chaanged tehe texture of the brick tiles created from the upgrade and the upgrade's icon
//---------------------------
// 1.51
// - the model of the farm is changed
// - food is renamed to housing with new icon and any mentiosn of food are renamed
// - pack horse no longer gives food
// - housing provided by houses reduced to 8
//---------------------------
// 1.5.2:
// - FIX - the altar of kings can now also change to altar of kungs for undead, as expected
// - FIX - the tooltips and hotkeys of Satyr Summoning Portal, Revenant Summoning Portal and Trolls Summoning Portal are fixed and working
// - FIX - now yo ucan change vault type from goblin to any, as intended
// - FIX - Can build Arcane Repellent and Power Generator when having requirements met.
// - FIX - the upgrade "construction expertise"'s level 2's tooltip changed to "construction mastery"
// - FIX - Control Magic Tooltip edit
// - FIX - the upgrade arcane shielding now requires ANY Arcane SAnctum, not only the initial
// - Removed Arcane Vault requirement from Library
//--------------------------
//TESH.scrollpos=0
//TESH.alwaysfold=0
//------------------------------------
//----CREDITS-------------------------
//------------------------------------
//------------------------------------
//------------------------------------
// General Frank for making the forbidden aura and the forbidden overhead buff
// Rodrigooo for editing the library model to have team color
// Warseeker for the Anti-Building Code
//------------------------------------
// Various credits for models and icons
//------------------------------------
// Most of the models are edited by me, because they had flaws
//TESH.scrollpos=7
//TESH.alwaysfold=0
function CancelBuild takes nothing returns nothing
if IsUnitSelected(GetEnumUnit(), Player(udg_i)) == true and UnitHasBuffBJ(GetEnumUnit(), 'arrx') == true then //'BUfa' = Frost Armor Buff
call ForceUICancelBJ( Player(udg_i) )
call DisplayTimedTextToPlayer(Player(udg_i), 0, 0, 60, "|cffff0000Build order failed. There is an Anti-Building Ward nearby.|r")
else
endif
endfunction
function BuildActions takes nothing returns nothing
set udg_i = 0
set udg_t = GetTriggeringTrigger()
loop
exitwhen udg_i>11
if udg_t == udg_BuildTrigger[udg_i] then
set bj_wantDestroyGroup = true
call ForGroupBJ( GetUnitsOfPlayerAndTypeId(Player(udg_i), 'hpea'), function CancelBuild) //'hpea' = Peasant
call ForGroupBJ( GetUnitsOfPlayerAndTypeId(Player(udg_i), 'engi'), function CancelBuild)
return
endif
set udg_i = udg_i + 1
endloop
endfunction
function InitTrig_Prevent_Build takes nothing returns nothing
local integer i = 0
loop
exitwhen i>11
set udg_BuildTrigger[i] = CreateTrigger()
call TriggerAddAction(udg_BuildTrigger[i], function BuildActions)
if GetLocalPlayer() == Player(i) then
call TriggerRegisterGameEvent(udg_BuildTrigger[i], EVENT_GAME_BUILD_SUBMENU)
endif
set i = i + 1
endloop
endfunction
////////////////////////////////////////////////////////////////////////////////////
//
// Physical Damage Detection Engine GUI v 1.3.0.0
// ----------------------------------------------
// By looking_for_help aka eey
//
// This system is able to detect, modify and deal damage. It can differentiate
// between physical and spell damage, as well as block, reduce or increase the
// applied damage to a desired value. You can also allocate damage events from
// running damage events.
//
// This is the GUI version of the system, meaning that you can use this with the
// standard editor and basically without any knowledge of JASS.
//
////////////////////////////////////////////////////////////////////////////////////
//
// Implementation
// --------------
// 1. Create all variables that this system uses (compare the variable editor).
// You don't have to set them to specific values, they get initialized
// automatically by the system so just create them.
// 2. Copy this trigger to your map. You can then add damage handlers by using
// the event "value of real variable becomes equal to 1" with the variable
// udg_PDD_damageEventTrigger. Compare the OnDamage trigger for an example usage.
// 3. Copy the two custom abilities to your map and make sure they have the
// correct ID. You can specify the ID in the function InitGlobalVariables
// above.
// 4. Go to the locust swarm ability and invert its damage return portion
// from (default) 0.75 to -0.75.
// 5. Remove the spell damage reduction ability from the spell damage reduction
// items you use (runed bracers). You can configure the resistance of this
// item in the InitGlobalVariables function, modifying the global variable
// udg_PDD_BRACERS_SPELL_DMG_RED.
//
////////////////////////////////////////////////////////////////////////////////////
//
// Important Notes
// ---------------
// 1. Life Drain does not work with this system, so you should use a triggered
// version of this spell if you want to use it.
// 2. Same for Finger of Death, if you want to use this spell bug free with this
// system, you should use a triggered version of it.
// 3. If you use damage modifiers by setting the damage amount variable, you have
// to use GetUnitLife, GetUnitMaxLife and SetUnitLife instead of GetWidgetLife,
// GetUnitState for UNIT_STATE_MAX_LIFE and SetWidgetLife in your whole map to
// ensure there occure no bugs.
// 4. The boolean udg_PDD_SPELL_RESIST_AUTO_DETECT is only neccessary set to true
// if you want to use a customized damage table with spell damage resistance
// above 100%. If this is not the case, it should be set to false, as the
// system is faster then and still works correct.
// 5. As already mentioned you can't use the spell reduction ability when using this
// system (runed bracers and elunes grace). If you want to use them, you can
// trigger them by using the damage modifiers. Runed bracers is already considered
// in this system, so you don't have to code it.
//
////////////////////////////////////////////////////////////////////////////////////
//
// System API
// ----------
// real damageEventTrigger
// - Use the event "value of real variable becomes equal to 1" to detect a damage
// event. In this event you can use the following API. Compare the OnDamage
// trigger for an example usage.
//
// unit target
// - In this global unit variable, the damaged unit is saved. Don't write any-
// thing into this variable, use it as readonly.
//
// unit source
// - In this global unit variable, the damage source is saved. Don't write any-
// thing into this variable, use it as readonly.
//
// real amount
// - In this global real variable, the amount of damage is saved. This amount
// can be modified by simply setting it to the desired amount that should be
// applied to the target. Set the amount to 0.0 to block the damage completly.
// Negative values will result in heal.
//
// integer damageType
// - In this global integer variable, the damage type of the current damage is
// saved. Use it to differentiate between physical, spell and code damage. The
// variable can takes the values PHYSICAL == 0, SPELL == 1 and CODE == 2. Don't
// write anything into this variable, use it as readonly.
//
// function GetUnitLife takes unit u returns real
// - Use this function instead of the GetWidgetLife native. It ensures that you
// get the correct health value, even when damage modifiers are applied. If
// you don't use damage modifiers at all, you don't need this function.
//
// function GetUnitMaxLife takes unit u returns real
// - Use this function instead of the GetUnitState(u, UNIT_STATE_MAX_LIFE) native.
// It will return the correct value, even when damage modifiers are applied. If
// you don't use damage modifiers at all, you don't need this function.
//
// function SetUnitLife takes unit u, real newLife returns nothing
// - Use this function instead of the SetWidgetLife(u, newLife) native if you use
// damage modifiers in your map. Same rules as for the GetUnitMaxLife and the
// GetUnitMaxLife functions.
//
// function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
// - Use this function to deal damage from a running damage event. It works exactly
// the same as the native UnitDamageTarget but is recursion safe so that you can
// realize damage reflection for example with this. Don't ever use this function
// outside of an onDamage event.
//
// function AddDamageHandler takes code damageHandler returns nothing
// - Allows you to add a damage handler function to the system. This is not
// required for GUI users, only for vanilla JASS users. GUI users should
// use the real variable damageEventTrigger to add damage handlers to this
// system as explained above.
//
// function RemoveDamageHandler takes code damageHandler returns nothing
// - Allows you to remove a damage handler function from the system dynamic-
// ally. If you added the same handler function multiple times to the sys-
// tem, this function will remove all of these equal functions. This is not
// required for GUI users, only for vanilla JASS users.
//
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// Configurable globals
//////////////////////////////////////////////////////////////////////////////////
function InitGlobalVariables takes nothing returns nothing
// Put here the correct ability IDs
set udg_PDD_DAMAGE_TYPE_DETECTOR = 'A000'
set udg_PDD_SET_MAX_LIFE = 'A001'
// Here you can configure some stuff, read the documentation for further info
set udg_PDD_SPELL_DMG_REDUCTION_ITEM = 'brac'
set udg_PDD_SPELL_RESIST_AUTO_DETECT = false
set udg_PDD_ETHEREAL_DAMAGE_FACTOR = 1.66
set udg_PDD_BRACERS_SPELL_DMG_RED = 0.33
set udg_PDD_TRIGGER_CLEANUP_PERIOD = 60.0
endfunction
//////////////////////////////////////////////////////////////////////////////////
// End of configurable globals
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
// User functions
//////////////////////////////////////////////////////////////////////////////////
function AddDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop to manage equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
set index = index + 1
endloop
// Store the desired damage handler function
call SaveTriggerConditionHandle(udg_PDD_h, id, index, TriggerAddCondition(udg_PDD_damageHandler, Filter(func)))
endfunction
function RemoveDamageHandler takes code func returns nothing
local integer id = GetHandleId(Condition(func))
local integer index = 0
// Loop through all equal damage handlers
loop
exitwhen ( LoadTriggerConditionHandle(udg_PDD_h, id, index) == null )
call TriggerRemoveCondition(udg_PDD_damageHandler, LoadTriggerConditionHandle(udg_PDD_h, id, index))
set index = index + 1
endloop
// Clean things up
call FlushChildHashtable(udg_PDD_h, id)
endfunction
function GetUnitLife takes unit u returns real
local boolean duringModification
local integer uId = GetHandleId(u)
local real health
local real storedHealth = LoadReal(udg_PDD_h, uId, 2)
local real storedDamage = LoadReal(udg_PDD_h, uId, 1)
// Check if the unit is being rescued from damage
set duringModification = GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0
if duringModification then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
endif
// Get the correct health value of the unit
if storedHealth != 0.0 then
set health = storedHealth - storedDamage
else
set health = GetWidgetLife(u) - storedDamage
endif
// Restore the rescue ability and return
if duringModification then
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
endif
return health
endfunction
function GetUnitMaxLife takes unit u returns real
local real maxHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
set maxHealth = GetUnitState(u, UNIT_STATE_MAX_LIFE)
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
return maxHealth
endif
// If the unit isn't being rescued, use the standard native
return GetUnitState(u, UNIT_STATE_MAX_LIFE)
endfunction
function SetUnitLife takes unit u, real newLife returns nothing
local integer targetId
local integer oldTimerId
local real oldHealth
// Check if the unit is being rescued from damage
if GetUnitAbilityLevel(u, udg_PDD_SET_MAX_LIFE) > 0 then
call UnitRemoveAbility(u, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(u, newLife)
call UnitAddAbility(u, udg_PDD_SET_MAX_LIFE)
// Get the unit specific timer information
set targetId = GetHandleId(u)
set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
// Update the unit specific timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
call SaveReal(udg_PDD_h, targetId, 2, newLife)
call SaveReal(udg_PDD_h, targetId, 0, newLife)
call SaveReal(udg_PDD_h, oldTimerId, 4, newLife)
endif
return
endif
// If the unit isn't being rescued, use the standard native
call SetWidgetLife(u, newLife)
endfunction
function UnitDamageTargetEx takes unit localSource, unit localTarget, real localAmount, boolean attack, boolean ranged, attacktype localAttackType, damagetype localDamageType, weapontype localWeaponType returns boolean
// Avoid infinite loop due to recursion
if udg_PDD_damageType == udg_PDD_CODE then
return false
endif
// Avoid allocating attacks on units that are about to be killed
if ( localTarget == udg_PDD_target and GetUnitLife(localTarget) - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
return false
endif
// Store all damage parameters determined by the user
set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks + 1
call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 0, localSource)
call SaveUnitHandle(udg_PDD_h, udg_PDD_allocatedAttacks, 1, localTarget)
call SaveReal(udg_PDD_h, udg_PDD_allocatedAttacks, 2, localAmount)
call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 3, attack)
call SaveBoolean(udg_PDD_h, udg_PDD_allocatedAttacks, 4, ranged)
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 5, GetHandleId(localAttackType))
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 6, GetHandleId(localDamageType))
call SaveInteger(udg_PDD_h, udg_PDD_allocatedAttacks, 7, GetHandleId(localWeaponType))
// Return true if the damage was allocated
return true
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Sub functions
////////////////////////////////////////////////////////////////////////////////////
function DealFixDamage takes unit source, unit target, real pureAmount returns nothing
local real MAX_DAMAGE = 1000000.0
local real beforeHitpoints
local real newHitpoints
// Ensure the amount is positive
if pureAmount < 0 then
set pureAmount = -pureAmount
endif
// Save the targets hitpoints
set beforeHitpoints = GetWidgetLife(target)
set newHitpoints = beforeHitpoints - pureAmount
// Apply the desired, fixed amount
if newHitpoints >= udg_PDD_UNIT_MIN_LIFE then
call SetUnitState(target, UNIT_STATE_LIFE, newHitpoints)
else
if ( IsUnitType(target, UNIT_TYPE_ETHEREAL) == false ) then
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, udg_PDD_ATTACK_TYPE_UNIVERSAL, DAMAGE_TYPE_UNIVERSAL, null)
call SetWidgetLife(target, 0.0)
else
call UnitRemoveAbility(target, udg_PDD_DAMAGE_TYPE_DETECTOR)
call SetWidgetLife(target, 1.0)
call UnitDamageTarget(source, target, MAX_DAMAGE, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
call SetWidgetLife(target, 0.0)
endif
endif
endfunction
function GetUnitSpellResistance takes unit u returns real
local real originalHP
local real beforeHP
local real afterHP
local real resistance
local real DUMMY_DAMAGE = 100
local real DUMMY_FACTOR = 0.01
// Deal spell damage in order to get the units resistance
call UnitRemoveAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
set originalHP = GetWidgetLife(udg_PDD_target)
call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, 20000.0)
set beforeHP = GetWidgetLife(udg_PDD_target)
call DisableTrigger(udg_PDD_damageEvent)
call UnitDamageTarget(udg_PDD_source, udg_PDD_target, DUMMY_DAMAGE, true, false, null, DAMAGE_TYPE_UNIVERSAL, null)
call EnableTrigger(udg_PDD_damageEvent)
set afterHP = GetWidgetLife(udg_PDD_target)
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, originalHP)
call UnitAddAbility(udg_PDD_target, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(udg_PDD_target, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
// Calculate this resistance
set resistance = DUMMY_FACTOR*(beforeHP - afterHP)
// If the resistance was greater than 100%, return it
if resistance > 1.0 then
return resistance
else
return 1.0
endif
endfunction
function UnitHasItemOfType takes unit u, integer itemId returns integer
local integer index = 0
local item indexItem
// Check if the target has a spell damage reducing item
loop
set indexItem = UnitItemInSlot(u, index)
if ( indexItem != null ) and ( GetItemTypeId(indexItem) == itemId ) then
set indexItem = null
return index + 1
endif
set index = index + 1
exitwhen index >= bj_MAX_INVENTORY
endloop
set indexItem = null
return 0
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Damage Engine
////////////////////////////////////////////////////////////////////////////////////
function AfterDamage takes nothing returns nothing
local timer time = GetExpiredTimer()
local integer id = GetHandleId(time)
local unit localSource = LoadUnitHandle(udg_PDD_h, id, 0)
local unit localTarget = LoadUnitHandle(udg_PDD_h, id, 1)
local real pureAmount = LoadReal(udg_PDD_h, id, 2)
local real amount = LoadReal(udg_PDD_h, id, 3)
local real originalHealth = LoadReal(udg_PDD_h, id, 4)
// If the damage was modified, restore units health
if originalHealth != 0.0 then
call UnitRemoveAbility(localTarget, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(localTarget, originalHealth)
endif
// Apply the desired amount of damage
if amount > 0.0 then
call DisableTrigger(udg_PDD_damageEvent)
call DealFixDamage(localSource, localTarget, amount)
call EnableTrigger(udg_PDD_damageEvent)
else
call SetWidgetLife(localTarget, originalHealth - amount)
endif
// Clean things up
call FlushChildHashtable(udg_PDD_h, id)
call FlushChildHashtable(udg_PDD_h, GetHandleId(localTarget))
call DestroyTimer(time)
set time = null
set localSource = null
set localTarget = null
endfunction
function DamageEngine takes nothing returns nothing
local timer time
local integer id
local real health
local real rawAmount
local real originalHealth
local integer targetId
local integer oldTimerId
local real oldHealth
local real oldOriginalHealth
local real oldAmount
set rawAmount = GetEventDamage()
if rawAmount == 0.0 then
return
endif
set udg_PDD_source = GetEventDamageSource()
set udg_PDD_target = GetTriggerUnit()
// Determine the damage type
if rawAmount > 0.0 then
if udg_PDD_damageType != udg_PDD_CODE then
set udg_PDD_damageType = udg_PDD_PHYSICAL
endif
set udg_PDD_amount = rawAmount
else
if udg_PDD_damageType != udg_PDD_CODE then
set udg_PDD_damageType = udg_PDD_SPELL
endif
set udg_PDD_amount = -rawAmount
endif
// Register spell reduction above 100%
if udg_PDD_SPELL_RESIST_AUTO_DETECT then
set udg_PDD_amount = GetUnitSpellResistance(udg_PDD_target)*udg_PDD_amount
else
if ( IsUnitType(udg_PDD_target, UNIT_TYPE_ETHEREAL) and IsUnitEnemy(udg_PDD_target, GetOwningPlayer(udg_PDD_source)) and rawAmount < 0.0 ) then
set udg_PDD_amount = udg_PDD_ETHEREAL_DAMAGE_FACTOR*udg_PDD_amount
endif
endif
// Register spell damage reducing items like runed bracers
if ( IsUnitType(udg_PDD_target, UNIT_TYPE_HERO) and UnitHasItemOfType(udg_PDD_target, udg_PDD_SPELL_DMG_REDUCTION_ITEM) > 0 ) and rawAmount < 0.0 then
set udg_PDD_amount = (1 - udg_PDD_BRACERS_SPELL_DMG_RED)*udg_PDD_amount
endif
// Save health and damage variables
if udg_PDD_damageType != udg_PDD_CODE then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
endif
set udg_PDD_pureAmount = udg_PDD_amount
set originalHealth = GetWidgetLife(udg_PDD_target)
set oldTimerId = 0
// Call damage handlers
set udg_PDD_damageEventTrigger = 0.0
set udg_PDD_damageEventTrigger = 1.0
set udg_PDD_damageEventTrigger = 0.0
// If the damage was modified, apply the rescue ability
if udg_PDD_amount != udg_PDD_pureAmount then
call UnitAddAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, GetWidgetLife(udg_PDD_target) + udg_PDD_pureAmount)
endif
// Check if a previous timer didn't yet expire
set targetId = GetHandleId(udg_PDD_target)
set oldHealth = LoadReal(udg_PDD_h, targetId, 0)
// If this is the case, update the timer information
if oldHealth != 0.0 then
set oldTimerId = LoadInteger(udg_PDD_h, targetId, 3)
set oldOriginalHealth = LoadReal(udg_PDD_h, targetId, 2)
set oldAmount = LoadReal(udg_PDD_h, targetId, 1)
set originalHealth = oldOriginalHealth - oldAmount
call SaveReal(udg_PDD_h, oldTimerId, 4, oldOriginalHealth)
endif
// Call after damage event if damage was spell, modified, code or parallel
if ( rawAmount < 0.0 or udg_PDD_pureAmount != udg_PDD_amount or oldTimerId != 0 or udg_PDD_allocatedAttacks > 0 ) then
set time = CreateTimer()
set id = GetHandleId(time)
// Save handles for after damage event
call SaveUnitHandle(udg_PDD_h, id, 0, udg_PDD_source)
call SaveUnitHandle(udg_PDD_h, id, 1, udg_PDD_target)
call SaveReal(udg_PDD_h, id, 2, udg_PDD_pureAmount)
call SaveReal(udg_PDD_h, id, 3, udg_PDD_amount)
call SaveReal(udg_PDD_h, id, 4, originalHealth)
// Save this extra to manage parallel damage instances
call SaveReal(udg_PDD_h, targetId, 0, GetWidgetLife(udg_PDD_target))
call SaveReal(udg_PDD_h, targetId, 1, udg_PDD_amount)
call SaveReal(udg_PDD_h, targetId, 2, originalHealth)
call SaveInteger(udg_PDD_h, targetId, 3, id)
// Avoid healing of negative spell damage
if rawAmount < 0.0 then
call DisableTrigger(udg_PDD_damageEvent)
call DealFixDamage(udg_PDD_source, udg_PDD_target, -rawAmount)
if ( originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE ) then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call DealFixDamage(udg_PDD_source, udg_PDD_target, udg_PDD_amount)
endif
call EnableTrigger(udg_PDD_damageEvent)
endif
// Guarantee unit exploding
if originalHealth - udg_PDD_amount < udg_PDD_UNIT_MIN_LIFE then
if rawAmount > 0.0 then
call UnitRemoveAbility(udg_PDD_target, udg_PDD_SET_MAX_LIFE)
call SetWidgetLife(udg_PDD_target, udg_PDD_UNIT_MIN_LIFE)
endif
endif
// Start the after damage event
call TimerStart(time, 0.0, false, function AfterDamage)
endif
// Handle allocated attacks from UnitDamageTargetEx
if udg_PDD_totalAllocs == 0 then
set udg_PDD_totalAllocs = udg_PDD_allocatedAttacks
endif
if udg_PDD_allocatedAttacks > 0 then
set udg_PDD_allocatedAttacks = udg_PDD_allocatedAttacks - 1
set udg_PDD_allocCounter = udg_PDD_allocCounter + 1
call TriggerEvaluate(udg_PDD_runAllocatedAttacks)
endif
// Reset all required variables
set udg_PDD_damageType = -1
set udg_PDD_totalAllocs = 0
set udg_PDD_allocCounter = -1
endfunction
////////////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////////////
function RestoreTriggers takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Re-register units that are alive
if GetUnitTypeId(enumUnit) != 0 then
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
endif
set enumUnit = null
endfunction
function ClearMemory_Actions takes nothing returns nothing
local group g = CreateGroup()
local code c = function DamageEngine
// Reset the damage event
call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
call ResetTrigger(udg_PDD_damageEvent)
call DestroyTrigger(udg_PDD_damageEvent)
set udg_PDD_damageEvent = null
// Rebuild it then
set udg_PDD_damageEvent = CreateTrigger()
call TriggerAddCondition(udg_PDD_damageEvent, Filter(c))
call ForGroup(g, function RestoreTriggers)
// Clean things up
call DestroyGroup(g)
set g = null
set c = null
endfunction
function MapInit takes nothing returns nothing
local unit enumUnit = GetEnumUnit()
// Register units on map initialization
call UnitAddAbility(enumUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(enumUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, enumUnit, EVENT_UNIT_DAMAGED)
set enumUnit = null
endfunction
function UnitEntersMap takes nothing returns nothing
local unit triggerUnit = GetTriggerUnit()
// Register units that enter the map
if ( GetUnitAbilityLevel(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR) < 1 ) then
call UnitAddAbility(triggerUnit, udg_PDD_DAMAGE_TYPE_DETECTOR)
call UnitMakeAbilityPermanent(triggerUnit, true, udg_PDD_DAMAGE_TYPE_DETECTOR)
call TriggerRegisterUnitEvent(udg_PDD_damageEvent, triggerUnit, EVENT_UNIT_DAMAGED)
endif
set triggerUnit = null
endfunction
function RunAllocatedAttacks takes nothing returns nothing
local integer localAllocAttacks = udg_PDD_allocatedAttacks + 1
// Calculate the correct sequence of allocated attacks
set localAllocAttacks = localAllocAttacks - udg_PDD_totalAllocs + 1 + 2*udg_PDD_allocCounter
// Deal code damage if the unit isn't exploding
set udg_PDD_damageType = udg_PDD_CODE
if GetUnitLife(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1)) >= udg_PDD_UNIT_MIN_LIFE then
call UnitDamageTarget(LoadUnitHandle(udg_PDD_h, localAllocAttacks, 0), LoadUnitHandle(udg_PDD_h, localAllocAttacks, 1), LoadReal(udg_PDD_h, localAllocAttacks, 2), LoadBoolean(udg_PDD_h, localAllocAttacks, 3), LoadBoolean(udg_PDD_h, localAllocAttacks, 4), ConvertAttackType(LoadInteger(udg_PDD_h, localAllocAttacks, 5)), ConvertDamageType(LoadInteger(udg_PDD_h, localAllocAttacks, 6)), ConvertWeaponType(LoadInteger(udg_PDD_h, localAllocAttacks, 7)))
else
call FlushChildHashtable(udg_PDD_h, localAllocAttacks - 1)
endif
// Clean things up
call FlushChildHashtable(udg_PDD_h, localAllocAttacks)
endfunction
function InitTrig_DamageEvent takes nothing returns nothing
local group g = CreateGroup()
local region r = CreateRegion()
local trigger UnitEnters = CreateTrigger()
local trigger ClearMemory = CreateTrigger()
local code cDamageEngine = function DamageEngine
local code cUnitEnters = function UnitEntersMap
local code cClearMemory = function ClearMemory_Actions
local code cRunAllocatedAttacks = function RunAllocatedAttacks
// Initialize global variables
set udg_PDD_h = InitHashtable()
set udg_PDD_damageEvent = CreateTrigger()
set udg_PDD_damageHandler = CreateTrigger()
set udg_PDD_damageType = -1
set udg_PDD_allocatedAttacks = 0
set udg_PDD_runAllocatedAttacks = CreateTrigger()
// Initialize global configurable constants
call InitGlobalVariables()
// Initialize global fixed constants
set udg_PDD_PHYSICAL = 0
set udg_PDD_SPELL = 1
set udg_PDD_CODE = 2
set udg_PDD_UNIT_MIN_LIFE = 0.406
set udg_PDD_ATTACK_TYPE_UNIVERSAL = ConvertAttackType(7)
set udg_PDD_totalAllocs = 0
set udg_PDD_allocCounter = -1
set udg_PDD_damageEventTrigger = 0.0
// Register units on map initialization
call TriggerRegisterVariableEvent(udg_PDD_damageHandler, "udg_PDD_damageEventTrigger", EQUAL, 1.0)
call TriggerAddCondition(udg_PDD_damageEvent, Filter(cDamageEngine))
call GroupEnumUnitsInRect(g, GetWorldBounds(), null)
call ForGroup(g, function MapInit)
// Register units that enter the map
call RegionAddRect(r, GetWorldBounds())
call TriggerRegisterEnterRegion(UnitEnters, r, null)
call TriggerAddCondition(UnitEnters, Filter(cUnitEnters))
// Register trigger for allocated attacks
call TriggerAddCondition(udg_PDD_runAllocatedAttacks, Filter(cRunAllocatedAttacks))
// Clear memory leaks
call TriggerRegisterTimerEvent(ClearMemory, udg_PDD_TRIGGER_CLEANUP_PERIOD, true)
call TriggerAddCondition(ClearMemory, Filter(cClearMemory))
// Clean things up
call DestroyGroup(g)
set UnitEnters = null
set ClearMemory = null
set cDamageEngine = null
set cUnitEnters = null
set cClearMemory = null
set cRunAllocatedAttacks = null
set g = null
set r = null
endfunction