/*
function B2S takes boolean bool returns string
if(bool)then
return "true"
endif
return "false"
endfunction
function Player2S takes player p returns string
return "Player("+I2S(GetPlayerId(p))+")"
endfunction
function Unit2S takes unit u returns string
return GetUnitName(u)+ "_"+I2S(GetHandleId(u)-0x100000)
endfunction
*/
Name | Type | is_array | initial_value |
AfterDamageEvent | real | No | |
AGI_DEFENSE_BASE | real | No | 5.00 |
AGI_DEFENSE_BONUS | real | No | 0.10 |
AlreadyPausedUnits | group | No | |
AOEDamageEvent | real | No | |
AOEDamageSource | unit | No | |
ARMOR_TYPE_ETHEREAL | integer | No | |
ARMOR_TYPE_FLESH | integer | No | |
ARMOR_TYPE_METAL | integer | No | |
ARMOR_TYPE_NONE | integer | No | |
ARMOR_TYPE_STONE | integer | No | |
ARMOR_TYPE_WOOD | integer | No | |
ArmorTypeDebugStr | string | Yes | |
AssassinPackSize | integer | No | |
AssassinTimer | timer | No | |
ATTACK_TYPE_CHAOS | integer | No | |
ATTACK_TYPE_HERO | integer | No | |
ATTACK_TYPE_MAGIC | integer | No | |
ATTACK_TYPE_NORMAL | integer | No | |
ATTACK_TYPE_PIERCE | integer | No | |
ATTACK_TYPE_SIEGE | integer | No | |
ATTACK_TYPE_SPELLS | integer | No | |
AttackTypeDebugStr | string | Yes | |
BAmr_Attribute | real | Yes | |
BAmr_Boolean | boolean | Yes | |
BAmr_Config_ABSORBTION | real | No | |
BAmr_Config_ATT_BONUS | real | Yes | |
BAmr_Config_BASE_HP | real | No | |
BAmr_Config_BUFF | buffcode | No | |
BAmr_Config_FLAVOR | integer | No | |
BAmr_Config_FLAVOR_PATH | string | Yes | |
BAmr_Config_LVL_HP_BONUS | real | Yes | |
BAmr_Config_PERIODIC | real | No | |
BAmr_Config_RESIST_PHYSICAL | real | No | |
BAmr_Config_RESIST_SPELL | real | No | |
BAmr_Config_SEG_VALUE | real | Yes | |
BAmr_Config_SEGMENT_SPAWNED | integer | No | |
BAmr_Config_SPEF | effect | No | |
BAmr_Config_SPEF_PATH | string | Yes | |
BAmr_Config_SPEF_VALUE | real | Yes | |
BAmr_Config_SPELL_ID | abilcode | No | |
BAmr_Current_Rot_Speed | real | Yes | |
BAmr_DMG_Event | real | No | |
BAmr_Enchanted_Unit | unit | Yes | |
BAmr_Health | real | Yes | |
BAmr_Index | integer | No | |
BAmr_Loop | integer | No | |
BAmr_Loop_Segment | integer | No | |
BAmr_Max | real | Yes | |
BAmr_Point | location | Yes | |
BAmr_Real | real | Yes | |
BAmr_Seg_CValue | integer | No | |
BAmr_Seg_CValue_DeIndex | integer | No | |
BAmr_Segment_Missile | effect | Yes | |
BAmr_Segment_Missile_State | string | Yes | |
BAmr_Spef_Current_Height | real | Yes | |
BAmr_Total | real | Yes | |
BAmr_Unit | unit | Yes | |
Banehallow | unit | No | |
Beast_Attack_Ability_Level | integer | No | |
Beast_Attack_Atribute | integer | No | |
Beast_Attack_Atribute_Damage | real | No | |
Beast_Attack_Caster | unit | No | |
Beast_Attack_Damage_Splitter | integer | No | |
Beast_Attack_Life_Damage | real | No | |
Beast_Attack_Location | location | No | |
Beast_Attack_Location2 | location | No | |
Beast_Attack_Max_Life | real | No | |
Beast_Attack_Target | unit | No | |
Beast_Attack_Total_Damage | real | No | |
BoostLevel | integer | No | |
Boss1Point | location | No | |
BossUnits | group | No | |
BuildingDeadPackSize | integer | No | |
CargoEvent | real | No | |
CargoTransportGroup | group | Yes | |
CargoTransportUnit | unit | Yes | |
ChallengerNumber | integer | No | |
CheckDeathInList | boolean | Yes | |
CheckDeathList | integer | Yes | |
CheckDeathTimer | timer | No | |
CinermaticArthas | unit | No | |
CleanedItem | item | Yes | |
ClockTimer | timer | No | |
ConfirmDialog | dialog | No | |
ConnectedPlayers | force | No | |
CONVERTED_ATTACK_TYPE | attacktype | Yes | |
CONVERTED_DAMAGE_TYPE | damagetype | Yes | |
CountdownTimer | timer | No | |
CreepTimer | timer | No | |
CreepTimerW | timerdialog | No | |
DAMAGE_TYPE_ACID | integer | No | |
DAMAGE_TYPE_COLD | integer | No | |
DAMAGE_TYPE_DEATH | integer | No | |
DAMAGE_TYPE_DEFENSIVE | integer | No | |
DAMAGE_TYPE_DEMOLITION | integer | No | |
DAMAGE_TYPE_DISEASE | integer | No | |
DAMAGE_TYPE_DIVINE | integer | No | |
DAMAGE_TYPE_ENHANCED | integer | No | |
DAMAGE_TYPE_FIRE | integer | No | |
DAMAGE_TYPE_FORCE | integer | No | |
DAMAGE_TYPE_LIGHTNING | integer | No | |
DAMAGE_TYPE_MAGIC | integer | No | |
DAMAGE_TYPE_MIND | integer | No | |
DAMAGE_TYPE_NORMAL | integer | No | |
DAMAGE_TYPE_PLANT | integer | No | |
DAMAGE_TYPE_POISON | integer | No | |
DAMAGE_TYPE_SHADOW_STRIKE | integer | No | |
DAMAGE_TYPE_SLOW_POISON | integer | No | |
DAMAGE_TYPE_SONIC | integer | No | |
DAMAGE_TYPE_SPIRIT_LINK | integer | No | |
DAMAGE_TYPE_UNIVERSAL | integer | No | |
DAMAGE_TYPE_UNKNOWN | integer | No | |
DamageEvent | real | No | |
DamageEventAmount | real | No | |
DamageEventAOE | integer | No | |
DamageEventAOEGroup | group | No | |
DamageEventArmorPierced | real | No | |
DamageEventArmorT | integer | No | |
DamageEventAttackT | integer | No | |
DamageEventDamageT | integer | No | |
DamageEventDefenseT | integer | No | |
DamageEventLevel | integer | No | |
DamageEventOverride | boolean | No | |
DamageEventPrevAmt | real | No | |
DamageEventSource | unit | No | |
DamageEventTarget | unit | No | |
DamageEventType | integer | No | |
DamageEventWeaponT | integer | No | |
DamageFilterAttackT | integer | No | |
DamageFilterDamageT | integer | No | |
DamageFilterMinAmount | real | No | |
DamageFilterSource | unit | No | |
DamageFilterSourceB | buffcode | No | |
DamageFilterSourceT | unitcode | No | |
DamageFilterTarget | unit | No | |
DamageFilterTargetB | buffcode | No | |
DamageFilterTargetT | unitcode | No | |
DamageFilterType | integer | No | |
DamageModifierEvent | real | No | |
DamageReturnAbsolutes | real | Yes | |
DamageReturnAllowedPlayers | force | No | |
DamageReturnCodeMultiplier | real | No | |
DamageReturnComputeTimes | real | Yes | |
DamageReturnExpireTime | real | No | |
DamageReturnFactor | real | No | |
DamageReturnInputUnit | unit | No | |
DamageReturnMeleeMultiplier | real | No | |
DamageReturnOutputAbsolute | real | No | |
DamageReturnOutputPercentage | real | No | |
DamageReturnPercentages | real | Yes | |
DamageReturnRangedMultiplier | real | No | |
DamageReturnSpellMultiplier | real | No | |
DamageReturnTempInteger | integer | No | |
DamageReturnUnitIndex | integer | No | |
DamageScalingUser | real | No | |
DamageScalingWC3 | real | No | |
DamageTypeBlocked | integer | No | |
DamageTypeCode | integer | No | |
DamageTypeCriticalStrike | integer | No | |
DamageTypeDebugStr | string | Yes | |
DamageTypeExplosive | integer | No | |
DamageTypeHeal | integer | No | |
DamageTypePure | integer | No | |
DamageTypePureExplosive | integer | No | |
DamageTypeReduced | integer | No | |
DarkBossArmorIncPerPlayer | real | No | |
DarkBossArmorIncPerSqrtDiff | real | No | |
DarkBossArmorInit | real | No | |
DarkBossStatsIncPerPlayer | integer | No | |
DarkBossStatsIncPerSqrtDiff | integer | No | |
DarkBossStatsInit | integer | No | |
DarkCome | rect | Yes | |
DarkHeroAbilities | abilcode | Yes | |
DarkHeroArmorIncPerSqrtDiffLvl | real | No | |
DarkHeroArmorInit | real | No | |
DarkHeroStatsIncPerSqrtDiffLvl | integer | No | |
DarkHeroStatsInit | integer | No | |
DarkHeroType | unitcode | Yes | |
DarkTowerDestroyedCount | integer | Yes | 0 |
DarkUnitType | unitcode | Yes | |
DeathEvent | real | No | |
DEFENSE_ARMOR | real | No | 0.06 |
DEFENSE_TYPE_DIVINE | integer | No | |
DEFENSE_TYPE_FORTIFIED | integer | No | |
DEFENSE_TYPE_HEAVY | integer | No | |
DEFENSE_TYPE_HERO | integer | No | |
DEFENSE_TYPE_LIGHT | integer | No | |
DEFENSE_TYPE_MEDIUM | integer | No | |
DEFENSE_TYPE_NORMAL | integer | No | |
DEFENSE_TYPE_UNARMORED | integer | No | |
DefensePoint | location | No | |
DefenseTypeDebugStr | string | Yes | |
DetectRemoveAbility | abilcode | No | |
DetectTransformAbility | abilcode | No | |
Difficulty | integer | No | 1 |
DotaHashtable | hashtable | No | |
DragonAttackPeriod | real | No | |
DragonAttackPoint | location | Yes | |
DragonAttackTypes | unitcode | Yes | |
DragonPackSize | integer | No | |
DragonTimer | timer | No | |
DualHeroChange | boolean | Yes | |
DualHeroPoint | location | Yes | |
EasyItem__ERRORMESSAGE | string | No | |
EasyItem__ERRORSOUND | string | No | |
EasyItem__ShopChargedItemCount | integer | No | |
EasyItem__ShopDummyCharges | itemcode | Yes | |
EasyItem__ShopRealCharges | itemcode | Yes | |
EasyItem__SPLIT | boolean | No | |
EasyItem__SPLITDROP | boolean | No | |
EasyItem__SPLITSIZE | integer | No | |
EasyItem__SPLITSTACK | boolean | No | |
EasyItem__SPLITSTACKDELAY | real | No | |
EasyItem__USEITEMLEVEL | boolean | No | |
EasyItem_integer | integer | Yes | |
EasyItem_item | item | No | |
EasyItem_items | item | Yes | |
EasyItem_loopIndex | integer | No | |
EasyItem_point | location | Yes | |
EasyItem_sound | sound | No | |
EasyItem_string | string | Yes | |
EasyItem_timer | timer | No | |
EasyItem_unit | unit | No | |
EasyItem_units | unit | Yes | |
EffectCenter | effect | No | |
EffectIn1 | effect | Yes | |
EffectIn2 | effect | Yes | |
EffectIn3 | effect | Yes | |
EffectIn4 | effect | Yes | |
EffectOut1 | effect | Yes | |
EffectOut2 | effect | Yes | |
EnhancedDamageTarget | unit | No | |
ExtremeGroup | group | No | |
ExtremePowerupPeriod | real | No | |
FarmEventCooldown | real | No | |
FarmEventDuration | real | No | |
FarmEventMaxFrequency | real | No | |
FarmEventRespawnPending | boolean | Yes | |
FarmEventSpawns | group | Yes | |
FarmEventTimer | timer | Yes | |
FarmUnitType | unitcode | Yes | |
FarmUnitTypeIndex | integer | Yes | |
FinalBossCenter | location | No | |
FinalWaveArmorIncPerPlayer | real | No | |
FinalWaveArmorIncPerSqrtDiff | real | No | |
FinalWaveArmorInit | real | No | |
FinalWaveCooldown | real | No | |
FinalWaveStatsIncPerPlayer | integer | No | |
FinalWaveStatsIncPerSqrtDiff | integer | No | |
FinalWaveStatsInit | integer | No | |
GameLevel | integer | Yes | 0 |
GameLevelCooldowns | real | Yes | |
GlobalTempAbilityCode | abilcode | No | |
GlobalTempBoolean | boolean | No | |
GlobalTempForce | force | No | |
GlobalTempGroup | group | No | |
GlobalTempInteger | integer | No | |
GlobalTempInteger1 | integer | No | |
GlobalTempItem | item | No | |
GlobalTempItem1 | item | No | |
GlobalTempPlayer | player | No | |
GlobalTempPlayer1 | player | No | |
GlobalTempPoint | location | No | |
GlobalTempReal | real | No | |
GlobalTempReal1 | real | No | |
GlobalTempRegion | rect | No | |
GlobalTempString | string | No | |
GlobalTempUnit | unit | No | |
GlobalTempUnitType | unitcode | No | |
HeroAttackInterval | real | No | |
HeroBaseDamage | integer | No | |
HeroDefense | real | No | |
HeroMaxHP | integer | No | |
Host | player | No | |
IceGates | destructable | Yes | |
IcePillars | unit | Yes | |
IceTowers | unit | Yes | |
IceWayOpened | boolean | Yes | |
InitialPlayers | force | No | |
InnerCircleHeroCount | integer | No | 11 |
IsDamageAttack | boolean | No | |
IsDamageCode | boolean | No | |
IsDamageMelee | boolean | No | |
IsDamageRanged | boolean | No | |
IsDamageSpell | boolean | No | |
IsUnitAlive | boolean | Yes | |
IsUnitBeingUnloaded | boolean | Yes | |
IsUnitNew | boolean | Yes | |
IsUnitPreplaced | boolean | Yes | |
IsUnitReincarnating | boolean | Yes | |
IsUnitRemoved | boolean | Yes | |
IsUnitTransforming | boolean | Yes | |
ItemAbilities | abilcode | Yes | |
ItemAbilityCount | integer | No | |
ItemCleanupFlag | boolean | No | |
ItemCleanupTimer | timer | No | |
ItemsToClean | integer | No | |
KillerOfUnit | unit | Yes | |
Kills | integer | Yes | 0 |
Knockback_Loc1 | location | No | |
Knockback_Loc2 | location | No | |
Knockback_Target | unit | No | |
KnockbackAngle | real | No | |
KnockbackDistance | real | No | |
KnockbackSpeed | real | No | |
KnockbackTable | hashtable | No | |
KnockbackUnits | group | No | |
LethalDamageEvent | real | No | |
LethalDamageHP | real | No | |
LevelDragonTypes | unitcode | Yes | |
LifeStealAllowedPlayers | force | No | |
LifeStealCodeMultiplier | real | No | |
LifeStealComputeTimes | real | Yes | |
LifeStealExpireTime | real | No | |
LifeStealFactor | real | No | |
LifeStealInputUnit | unit | No | |
LifeStealMeleeMultiplier | real | No | |
LifeStealOutputPercentage | real | No | |
LifeStealPercentages | real | Yes | |
LifeStealRangedMultiplier | real | No | |
LifeStealSpellMultiplier | real | No | |
LifeStealUnitIndex | integer | No | |
LightHeroes | unit | Yes | |
LightHeroesAddedStats | integer | Yes | |
LightHeroRestTime | real | No | 0.00 |
LightHeroRestTimers | timer | Yes | |
LightHeroSaveDirection | real | Yes | 0 |
LightHeroSavePoint | location | Yes | |
LightHeroTimerW | timerdialog | Yes | |
LightningSwordEventDuration | real | No | |
LocalTempAbilityCode | abilcode | No | |
LocalTempGroup | group | No | |
LocalTempIndex | integer | No | |
LocalTempIndex1 | integer | No | |
LocalTempInteger | integer | No | |
LocalTempInteger1 | integer | No | |
LocalTempItem | item | No | |
LocalTempItem1 | item | No | |
LocalTempPlayer | player | No | |
LocalTempPlayer1 | player | No | |
LocalTempPoint | location | No | |
LocalTempPoint1 | location | No | |
LocalTempPoint2 | location | No | |
LocalTempReal | real | No | |
LocalTempString | string | No | |
LocalTempTimer | timer | No | |
LocalTempUnit | unit | No | |
LocalTempUnit1 | unit | No | |
Loop | integer | No | |
ModeEasy | boolean | No | |
ModeRandom | boolean | No | |
ModeSame | boolean | No | |
MUAdditionalAbilities | abilcode | Yes | |
MUAdditionalAbilitiesCount | integer | No | |
MUAttackSpeedBonusPercent | real | No | |
MUBaseDamageBonus | integer | No | |
MUBaseDamageBonusPercent | real | No | |
MUDefenseBonus | real | No | |
MUDefenseBonusPercent | real | No | |
MUI_3 | integervar | No | |
MUMaxHPBonus | integer | No | |
MUMaxHPBonusPercent | real | No | |
MUPrevAdditionalAbilities | abilcode | Yes | |
MUPrevAdditionalAbilitiesCount | integer | No | |
MUPrevAttackSpeedBonusPercent | real | No | |
MUPrevBaseDamageBonus | integer | No | |
MUPrevBaseDamageBonusPercent | real | No | |
MUPrevDefenseBonus | real | No | |
MUPrevDefenseBonusPercent | real | No | |
MUPrevMaxHPBonus | integer | No | |
MUPrevMaxHPBonusPercent | real | No | |
Muradin | unit | No | |
MuradinEventCooldown | real | No | |
MuradinEventDuration | real | No | |
MURefreshTrigger | trigger | No | |
MURegisteredPlayers | force | No | |
MusicPoint | integer | No | 1 |
MUTempIndex | integer | No | |
MUTempReal | real | No | |
MUTempUnit | unit | No | |
MUTempUnitGroup | group | No | |
NeutralHeroType | unitcode | Yes | |
NextDamageIsAttack | boolean | No | |
NextDamageIsMelee | boolean | No | |
NextDamageIsRanged | boolean | No | |
NextDamageType | integer | No | |
NextDamageWeaponT | integer | No | |
OptionGameButtonEasy | button | No | |
OptionGameButtonExtreme | button | No | |
OptionGameButtonNormal | button | No | |
OptionGameDialog | dialog | No | |
OptionHeroButtonDual | button | No | |
OptionHeroButtonDualRandom | button | No | |
OptionHeroButtonDualSame | button | No | |
OptionHeroButtonNormal | button | No | |
OptionHeroButtonRandom | button | No | |
OptionHeroButtonSame | button | No | |
OptionHeroDialog | dialog | No | |
OuterCircleHeroCount | integer | No | 19 |
PickMockHeroes | unit | Yes | |
PlayerColors | string | Yes | |
PlayerCount | integer | No | |
PlayerScore | integer | Yes | 0 |
PlayerSelections | group | Yes | |
POINT | location | No | |
PowerUpDummy | group | No | |
Quests | quest | Yes | |
RandomHero | integer | Yes | 0 |
RandomNumber | integer | Yes | |
RemovedPlayerIndex | integer | No | |
RingOfSuperiorityEventDuration | real | No | |
RosHashtable | hashtable | No | |
RunePoint | location | No | |
RuneTypeCount | integer | No | |
RuneTypes | itemcode | Yes | |
Scream_Ability_Level | integer | No | |
Scream_Area_of_Effect | real | No | |
Scream_Base_Area_of_Effect | real | No | |
Scream_Base_Damage | real | No | |
Scream_Bounus_Area_of_Effect | real | No | |
Scream_Caster | unit | No | |
Scream_Damage_Group | group | No | |
Scream_Dummy_Ability | abilcode | No | |
Scream_Location | location | No | |
Scream_Owner | player | No | |
Scream_Sound | sound | No | |
Scream_Sound_Volume | real | No | |
Scream_Total_Damage | real | No | |
SelectAreaCenter | location | No | |
SelectedHero | unit | Yes | |
SilentAssassinAttackPeriod | real | No | |
SilentAssassinTypes | unitcode | Yes | |
SPAgainstHeroModifier | real | No | |
SPAttributeDamageModifier | real | Yes | |
Special23ArmorIncPerSqrtDiff | real | No | |
Special23ArmorInit | real | No | |
Special23StatsIncPerSqrtDiff | integer | No | |
Special23StatsInit | integer | No | |
Special4Challenger | integer | No | |
Special4Group | group | No | |
Special5Challenger | integer | No | |
Special5Group | group | No | |
Special67ArmorIncPerSqrtDiff | real | No | |
Special67ArmorInit | real | No | |
Special67StatsIncPerSqrtDiff | integer | No | |
Special67StatsInit | integer | No | |
Special8Group | group | No | |
SpecialArea | rect | Yes | |
SpecialArenaCenter | location | No | |
Specials04Check | boolean | Yes | false |
Specials05Check | boolean | Yes | false |
SpecialsButtonExtreme1 | button | No | |
SpecialsButtonExtreme2 | button | No | |
SpecialsButtonExtreme3 | button | No | |
SpecialsButtonExtreme4 | button | No | |
SpecialsDialog | dialog | No | |
SpecialsExit | button | No | |
SpecialsNo | button | No | |
SpecialsYes | button | No | |
SpecialTimer | timer | No | |
SpecialTimerW | timerdialog | No | |
SpellDummyEffect | effect | Yes | |
SpellDummyUnit | unit | Yes | |
SPTempReal | real | No | |
StartPoint | location | No | |
SummonerOfUnit | unit | Yes | |
SuperItemTypeCount | integer | No | |
SuperItemTypes | itemcode | Yes | |
Survival2Center | location | No | |
SurvivalBountyPerPlayer | integer | No | |
SurvivalCome | rect | Yes | |
SurvivalWave | integer | No | |
TCAAvalancheCaster | unit | No | |
TCAFixAbilityCount | integer | No | |
TCAFixAbilityList | abilcode | Yes | |
TCAFixDeathTriggers | trigger | Yes | |
TCAFixOrderIssuedTriggers | trigger | Yes | |
TCAFixRegisteredUnits | group | No | |
TCAFixResumeHoldPosTrigger | trigger | No | |
TCAFixTargetAcquiredTriggers | trigger | Yes | |
TCAFixTempBoolean | boolean | No | |
TCAFixTempBoolean1 | boolean | No | |
TCAFixTempInteger | integer | No | |
TCAFixTempInteger1 | integer | No | |
TCAFixTempPoint | location | No | |
TCAFixTempPoint1 | location | No | |
TCAFixTempString0 | string | No | |
TCAFixTempString1 | string | No | |
TCAFixTempString2 | string | No | |
TCAFixTempUnit | unit | No | |
TCAFixUnitAttackedTrigger | trigger | No | |
TCAFixUnitHoldPositionBroken | boolean | Yes | |
TCAFixUnitHoldsPosition | boolean | Yes | |
TCAFixUnitLastAcquireTime | real | Yes | |
TCAFixUnitLastAttackTime | real | Yes | |
TCAFixUnitPatrols | boolean | Yes | |
TCATempIndex | integer | No | |
TempAvalancheDamages | real | No | |
TempTossCaster | unit | No | |
TempTossDamages | real | No | |
TempTossProjectedUnit | unit | No | |
TomesCount | integer | No | 3 |
UDex | integer | No | |
UDexLastRecycled | integer | No | |
UDexMax | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexUnits | unit | Yes | |
UG | group | No | |
UNIT | unit | No | |
UnitAttackInterval | real | No | |
UnitBaseDamage | integer | No | |
UnitDefense | real | No | |
UnitInAction | boolean | Yes | |
UnitInActionEvent | real | No | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitMaxHP | integer | No | |
UnitQuantity | integer | Yes | 0 |
UnitRace | integer | Yes | 0 |
UnitSelectionEvent | real | No | |
UnitSelectionPlayerId | integer | No | |
UnitType | integer | Yes | 0 |
UnitTypeEvent | real | No | |
UnitTypeOf | unitcode | Yes | |
VictoryCooldown | real | No | |
ViewCircle | fogmodifier | Yes | |
WaveCome | rect | Yes | |
WaveKills | integer | Yes | 0 |
WaveNumber | integer | No | |
WavePeriod | real | No | |
WaveTimer | timer | No | |
WaveTimerW | timerdialog | No | |
WaveUnitType | unitcode | Yes | |
WayCount | integer | No | 0 |
WayGates | destructable | Yes | |
WayNecropolis | unit | Yes | |
WayOpened | boolean | Yes | false |
WayTowers | unit | Yes | |
WEAPON_TYPE_AM_CHOP | integer | No | |
WEAPON_TYPE_CH_SLICE | integer | No | |
WEAPON_TYPE_CL_SLICE | integer | No | |
WEAPON_TYPE_CM_SLICE | integer | No | |
WEAPON_TYPE_MH_BASH | integer | No | |
WEAPON_TYPE_MH_CHOP | integer | No | |
WEAPON_TYPE_MH_SLICE | integer | No | |
WEAPON_TYPE_MH_STAB | integer | No | |
WEAPON_TYPE_ML_CHOP | integer | No | |
WEAPON_TYPE_ML_SLICE | integer | No | |
WEAPON_TYPE_MM_BASH | integer | No | |
WEAPON_TYPE_MM_CHOP | integer | No | |
WEAPON_TYPE_MM_SLICE | integer | No | |
WEAPON_TYPE_MM_STAB | integer | No | |
WEAPON_TYPE_NONE | integer | No | |
WEAPON_TYPE_RH_BASH | integer | No | |
WEAPON_TYPE_WH_BASH | integer | No | |
WEAPON_TYPE_WH_SLICE | integer | No | |
WEAPON_TYPE_WL_BASH | integer | No | |
WEAPON_TYPE_WL_SLICE | integer | No | |
WEAPON_TYPE_WL_STAB | integer | No | |
WEAPON_TYPE_WM_BASH | integer | No | |
WEAPON_TYPE_WM_SLICE | integer | No | |
WEAPON_TYPE_WM_STAB | integer | No | |
WeaponTypeDebugStr | string | Yes | |
WorldMaxX | real | No | |
WorldMaxY | real | No |
library DebugLogger requires TimeUtils
globals
// --------------------------------------------------------------------
// Enum log levels
// --------------------------------------------------------------------
constant integer LVL_DEBUG = 0
constant integer LVL_INFO = 1
constant integer LVL_WARN = 2
constant integer LVL_ERROR = 3
private constant integer LVL_NONE = 999 // Only for internal reference, do not use
private string array LevelTags [4]
private string array ColorTags [4]
// --------------------------------------------------------------------
// Config: display
// --------------------------------------------------------------------
private integer DISPLAY_LEVEL = LVL_NONE // Everything of lower level is not displayed
private constant real DISPLAY_TIME = 3.00 // Display time in seconds
// --------------------------------------------------------------------
// Config: write
// --------------------------------------------------------------------
private integer WRITE_LEVEL = LVL_NONE
private integer WRITENOW_LEVEL = LVL_NONE
private constant integer FILE_MAX_ENTRIES = 500 // Min 1, Max 8192
private constant string OUTPUT_FILE_NAME = "XndHeroSiegeLog" // Output file prefix. File number & .txt extensions are automatically added.
// --------------------------------------------------------------------
// Internal
// --------------------------------------------------------------------
private string array WriteLogs
private integer FirstWriteLogIndex = -1 // Start iterator (for read)
private integer LastWriteLogIndex = -1 // End iterator (for read & write)
private integer FileIndex = 0
endglobals
static if (FILTER_USERS) then
// --------------------------------------------------------------------
// DebugUserFilter: logs will display only to the players matching it
// Does not impact log writing in text file.
// --------------------------------------------------------------------
private function DebugUserFilter takes nothing returns boolean
local integer index = 0
loop
if ( GetPlayerName(GetEnumPlayer()) == ONLY_USERS[index] ) then
return true
endif
set index = index + 1
exitwhen (index >= ONLY_USERS.size)
endloop
return false
endfunction
endif
// --------------------------------------------------------------------
// SetLogLevel: set display & write log level
// --------------------------------------------------------------------
function SetLogLevel takes integer displayLevel, integer writeLevel, integer writeNowLevel returns nothing
set DISPLAY_LEVEL = displayLevel
set WRITE_LEVEL = writeLevel
set WRITENOW_LEVEL = writeNowLevel
endfunction
// --------------------------------------------------------------------
// WriteInFile: write up to last 8191 logs to the output file
// --------------------------------------------------------------------
function WriteInFile takes nothing returns nothing
local integer index
// There are logs to write in file
call PreloadGenClear()
call PreloadGenStart()
call Preload("Log file")
if ( (FirstWriteLogIndex != -1) and (LastWriteLogIndex != -1) ) then
set index = FirstWriteLogIndex
loop
call Preload(WriteLogs[index])
set index = index + 1
if ( index == 8191 ) then
set index = 0
endif
exitwhen index == LastWriteLogIndex
endloop
else
call Preload("<Empty log file>")
endif
call PreloadGenEnd(OUTPUT_FILE_NAME + "-" + I2S(FileIndex) + ".txt" )
endfunction
// --------------------------------------------------------------------
// DisplayLog: displays log as text
// --------------------------------------------------------------------
private function DisplayLog takes integer level, string message returns nothing
call DisplayTimedTextToForce( GetPlayersAll() , DISPLAY_TIME, LevelTags[level] + " " + "|c00" + ColorTags[level] + message +"|r" )
endfunction
// --------------------------------------------------------------------
// SavePrintLog: format logs and save them internally.
// If reached max file entry: prints file and goes to next file index.
// If level >= WRITENOW_LEVEL, then calls the WriteInFile() function.
// --------------------------------------------------------------------
private function SavePrintLog takes integer level, string message returns nothing
local string printMessage = ""
local real elapsedTime = TimerGetElapsed(udg_ClockTimer)
local string elapsedTimeString = FormatTime(elapsedTime)
if (FILE_MAX_ENTRIES == LastWriteLogIndex + 1 ) then
// Write this log file to disk and go to the next log file
call WriteInFile()
set FileIndex = FileIndex + 1
set FirstWriteLogIndex = -1
set LastWriteLogIndex = -1
endif
// Move last cursor
set LastWriteLogIndex = ModuloInteger(LastWriteLogIndex + 1, 8191)
// Move first cursor (when it is pushed front by last cursor)
if ( -1 == FirstWriteLogIndex ) then
set FirstWriteLogIndex = 0 // Start
elseif ( FirstWriteLogIndex == LastWriteLogIndex ) then
set FirstWriteLogIndex = ModuloInteger(FirstWriteLogIndex + 1, 8191) // Rolling logs
endif
// Print formating
set printMessage = LevelTags[level] + " [" + elapsedTimeString + "] " + message
// Save logs in a string array
set WriteLogs[LastWriteLogIndex] = printMessage
if (level >= WRITENOW_LEVEL) then
// Write this log file to disk
call WriteInFile()
endif
endfunction
// --------------------------------------------------------------------
// DebugLog: API function to push a new log.
// --------------------------------------------------------------------
function DebugLog takes integer level, string message returns nothing
if ( level >= DISPLAY_LEVEL ) then
call DisplayLog(level, message)
endif
if ( level >= WRITE_LEVEL ) then
call SavePrintLog(level, message)
endif
endfunction
// ----------------------------------------------------------------------------
// onInit: system initializer
// ----------------------------------------------------------------------------
private module M
private static method onInit takes nothing returns nothing
set LevelTags[LVL_DEBUG] = "[DEBUG]"
set LevelTags[LVL_INFO] = "[INFO] "
set LevelTags[LVL_WARN] = "[WARN] "
set LevelTags[LVL_ERROR] = "[ERROR]"
set ColorTags[LVL_DEBUG] = "999999"
set ColorTags[LVL_INFO] = "fffff"
set ColorTags[LVL_WARN] = "ff7f00"
set ColorTags[LVL_ERROR] = "ff0000"
endmethod
endmodule
private struct S extends array
implement M
endstruct
endlibrary
// Just set the log levels when REPLAY is detected
library LogDuringReplay requires DebugLogger, GameStatus
private module LogDuringReplayInit
private static method onInit takes nothing returns nothing
if ( GAME_STATUS_REPLAY == GetGameStatus() ) then
call SetLogLevel(LVL_ERROR, LVL_DEBUG, LVL_DEBUG)
endif
endmethod
endmodule
private struct LogDuringReplay
implement LogDuringReplayInit
endstruct
endlibrary
// -------------------------------------------------------------------------------
// Library: automatically log the execution of all global triggers
// -------------------------------------------------------------------------------
library DebugLoggerAutomation requires DebugLogger
// -------------------------------------------------------------------------------
// DECLARE_LOG_ACTION: macro that creates a log function especially for a trigger.
// -------------------------------------------------------------------------------
//! textmacro DECLARE_LOG_ACTION takes GLOBALVARIABLENAME
globals
private boolean Tracked_$GLOBALVARIABLENAME$ = false
endglobals
// Create a log action function just for this trigger
function Log_$GLOBALVARIABLENAME$ takes nothing returns nothing
local string debugStr = "$GLOBALVARIABLENAME$ executed" // Base text
local unit triggerUnit = GetTriggerUnit()
local destructable triggerDestructable = GetTriggerDestructable()
local player triggerPlayer = GetTriggerPlayer()
// Add parameters value
if (null != triggerUnit) then
set debugStr = debugStr + " - unit=" + GetUnitName(triggerUnit)
if (null == triggerPlayer) then
set triggerPlayer = GetOwningPlayer(triggerUnit)
endif
endif
if (null != triggerDestructable) then
set debugStr = debugStr + " - destructable=" + GetDestructableName(triggerDestructable)
endif
if (null != triggerPlayer) then
set debugStr = debugStr + " - player=" + GetPlayerName(triggerPlayer)
endif
call DebugLog(LVL_DEBUG, debugStr)
endfunction
//! endtextmacro
// -------------------------------------------------------------------------------
// ADD_LOG_ACTION: macro that adds the log function to a trigger action list.
// -------------------------------------------------------------------------------
//! textmacro ADD_LOG_ACTION takes GLOBALVARIABLENAME
if (whichTrigger == $GLOBALVARIABLENAME$) then
if (not Tracked_$GLOBALVARIABLENAME$) then
call DebugLog(LVL_DEBUG, "Tracking $GLOBALVARIABLENAME$ executions")
set Tracked_$GLOBALVARIABLENAME$ = true
call TriggerAddAction($GLOBALVARIABLENAME$, function Log_$GLOBALVARIABLENAME$) // Beware : recursive call
else
// Termination case to avoid infinite recursitivy
endif
return
endif
//! endtextmacro
// -------------------------------------------------------------------------------
// LOG_NATIVE: macro that adds a log function to a native (with a hook)
// -------------------------------------------------------------------------------
//! textmacro LOG_NATIVE takes NATIVE, PARAMETERS, LOG_LEVEL
public function on$NATIVE$ takes $PARAMETERS$ returns nothing
call DebugLog(LVL_$LOG_LEVEL$, "$NATIVE$")
endfunction
hook $NATIVE$ on$NATIVE$
//! endtextmacro
// -------------------------------------------------------------------------------
// Logged native declarations
// -------------------------------------------------------------------------------
//! runtextmacro LOG_NATIVE ("GetLocalPlayer", "nothing", "WARN")
//! runtextmacro LOG_NATIVE ("GetPlayerSlotState", "player whichPlayer", "WARN")
//! runtextmacro LOG_NATIVE ("GetPlayerController", "player whichPlayer", "WARN")
/* Natives that may be watched for desync debugging
GetDestructableName
GetSoundDuration
GetSoundFileDuration
GetCameraBoundMinX
GetCameraBoundMinX
GetCameraBoundMinX
GetCameraBoundMinX
GetCameraField
GetCameraTargetPositionX
GetCameraTargetPositionY
GetCameraTargetPositionZ
GetCameraTargetPositionLoc
GetCameraEyePositionX
GetCameraEyePositionY
GetCameraEyePositionZ
GetCameraEyePositionLoc
GetObjectName
IsMultiboardMinimized
GetLocalPlayer
GetLocationZ
GetLocalizedString
GetLocalizedHotkey
GetUnitName
BlzGetLocalUnitZ
BlzGetUnitZ
GetItemName
BlzGetItemDescription
BlzGetItemTooltip
BlzGetItemExtendedTooltip
SmartCameraPanBJ
GetPlayerSlotState
GetPlayerController
BlzGetLocalSpecialEffectX
BlzGetLocalSpecialEffectY
BlzGetLocalSpecialEffectZ
*/
// -------------------------------------------------------------------------------
// Log functions declaration
// -------------------------------------------------------------------------------
// List generated with Notepad++ or script from war3map.j
//! runtextmacro DECLARE_LOG_ACTION("udg_MURefreshTrigger")
//! runtextmacro DECLARE_LOG_ACTION("udg_TCAFixUnitAttackedTrigger")
//! runtextmacro DECLARE_LOG_ACTION("udg_TCAFixResumeHoldPosTrigger")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Dota_Initialization")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Framework")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Avalanche")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CraggyExterior")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GrabTree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Grow")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Toss")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MathsLib")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Logarithm")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ArmorLib")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameClock_VariableCreator")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TimeUtils")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Item_Cleanup")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ItemTimedLife")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Unit_Event_Config")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Unit_Event")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Unit_In_Action")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Unit_Inaction")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Damage_Engine_Config")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Damage_Engine")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Open_List")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Events_for_Cancel_List_ESC")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Cancel_List_ESC")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Cancel_List_Item")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Documentation")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EasyItemStacknSplit")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EasyItemStacknSplitGUI_config")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EasyItemStacknSplitGUI")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MinionsUpgrade")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LifeSteal_Configuration")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LifeSteal_Execute")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DamageReturn_Configuration")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DamageReturn_Execute")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DamageReturn_ApplyArmor")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_InvisibleBuffCorrector")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BossRegister")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BossUnregister")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Functions")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BossRearFlankAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DefendAgainstDamage")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Initialization")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Beast_Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_KnockbackUnits")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BAmr_Config")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BAmr_Cast")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BAmr_Block")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BAmr_Periodic")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BoneArmorAOE_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BoneArmorAOE_GUI")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Scream")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CleaveFix")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TCAFix_Config")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TCAFix_UnitIndexed")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TCAFix_UnitLearnsSkill")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TCAFix_UnitDeindexed")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EtherealFix_OnDamage")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HealFix_Unblock")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GrabTreeFix_Unblock")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_PauseAllUnits")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_UnpauseAllUnits")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Init_sequence")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Alliances")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Buildings")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DarkUnitVars")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Flags")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Hashtables")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Items")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_NeutralUnitVars")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Points")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Quests")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Regions")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Times")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DarkUnits")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Music")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_NeutralUnits")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Invulnerables")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Shops")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Check")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_StartGame")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OptionsGame")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OptionsDifficulty")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OptionsHeroes")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OptionsTimeOut")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ModeNormal")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ModeRandom")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ModeExtreme")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ModeEasy")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ReviveTrees")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CastleUnderAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_StopAttackCastle")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinHelp")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinAttacked")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BuyLevels")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BuyTomes")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CloseWay")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ExtremeLevel")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Fog")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Info")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Kick")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OpenWay")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Random")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Rebuy")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Repick")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RepickTip")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Host")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FullRestoration")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SuperItems")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LeaderBoard")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LeaderBoardAdd")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect1a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect1b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect2a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect2b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect3a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect3b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect4a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect4b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect5a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect5b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect6a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect6b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect7a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect7b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect8a")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSelect8b")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSetup")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroDead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ControlSharing")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EasyPowerUp")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroSetupDual")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroDeadDual")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroChange")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroChangeShared")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroStats")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroLevel")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroMoveItem")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroUseItem")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroAcquireItem")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroLoseItem")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DualHeroCooldown")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_BoostLevel")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EnableHeroAbilities")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EnableItemAbilities")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Level20Abilities")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Armor")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ArtifactCollector")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttributeBonusPerLevel")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AuraOfBlight")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Bomb")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CooldownsReduction")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CriticalStrikeAura")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_CursedClaws")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DamageDealtMalus")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DamageTakenMalus")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DebilitationAura")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Doom")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Earthquake")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EarthquakeStop")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Ensnare")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FanOfKnives_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FanOfKnives")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FrostParalysisAura")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Hex_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Hex")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HolyLight")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Immolation")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ImmolationGhost")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_InnerFire")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_KnightsChallenge")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LifeRegenerationAura")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LightFrenzy")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LightningAttackOnOff")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MagicDefenseOnOff")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MorphingCopyStats")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_OwlScout")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_PermanentLightning")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Polymorph_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Polymorph")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RealmOfSoul")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RefreshCooldownChance")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RuneClockCreate")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RuneClockDestroy")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RunicWeaponCreate")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ShadowStrike_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ShadowStrike")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ShockWave_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ShockWave")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpiritPig")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpiritualPresence")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_StormBolt_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_StormBolt")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ThunderClap_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ThunderClap")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_TrueTank")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WardsMastery")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WarStomp_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WarStomp")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Whirlwind")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttackStart")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Kills100")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Kills500")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Kills1000")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Kills2000")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttackCome")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttackCheck")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttackTower")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_AttackNecropolis")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_ExtremePowerUp")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_DragonAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_HeroAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_LightningAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SilentAssassin")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Rune")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameLevel1")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WarnBeforeGameLevel2")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameLevel2")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameLevel3")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameLevel4")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveTimer")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveAttack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveKills20")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveKills40")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveKills60")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_WaveKills80")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FinalWaveReady")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_FinalWaveStart")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival1Ready")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival1Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival1Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival2Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival2Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival3Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Survival3Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss1Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss1Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss2Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss2Leave")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss3Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss4Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss5Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss6Come")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss6Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss6Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss7Come")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss7Colour")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss7Power")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Boss7Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special4Agree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special4Won")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special4Failed")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special5Agree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special5EnableAbilities")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special5Won")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special5Failed")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Timer")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Stop")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Leave")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8AntiHack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special8Move")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinClap_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinClap")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinBolt_JASS")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_MuradinBolt")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Timer")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Attack")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Corpse")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Stop")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special1Dead")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special2Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special2Stop")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special2Won")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special2TimeOut")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special2Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3Start")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3Stop")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3Count")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3Won")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3TimeOut")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special3Teleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special6Agree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Special7Agree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXDialog")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXStart")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXDisagree")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXRevive")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXTeleport")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXPause")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXResume")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_SpecialXCancel")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Victory")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_YouLose")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EndGame")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_Disconnect")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_RemovePlayer")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_EndPitch")
//! runtextmacro DECLARE_LOG_ACTION("gg_trg_GameStatus")
// -------------------------------------------------------------------------------
// Adds log actions as 1st action for each trigger with a hook on TriggerAddAction
// -------------------------------------------------------------------------------
function onTriggerAddAction takes trigger whichTrigger, code actionFunc returns nothing
// List generated with Notepad++ or script from war3map.j
//! runtextmacro ADD_LOG_ACTION("udg_MURefreshTrigger")
//! runtextmacro ADD_LOG_ACTION("udg_TCAFixUnitAttackedTrigger")
//! runtextmacro ADD_LOG_ACTION("udg_TCAFixResumeHoldPosTrigger")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Dota_Initialization")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Framework")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Avalanche")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CraggyExterior")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GrabTree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Grow")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Toss")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MathsLib")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Logarithm")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ArmorLib")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameClock_VariableCreator")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TimeUtils")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Item_Cleanup")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ItemTimedLife")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Unit_Event_Config")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Unit_Event")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Unit_In_Action")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Unit_Inaction")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Damage_Engine_Config")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Open_List")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Events_for_Cancel_List_ESC")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Cancel_List_ESC")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Cancel_List_Item")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Documentation")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EasyItemStacknSplit")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EasyItemStacknSplitGUI_config")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EasyItemStacknSplitGUI")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MinionsUpgrade")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LifeSteal_Configuration")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LifeSteal_Execute")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DamageReturn_Configuration")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DamageReturn_Execute")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DamageReturn_ApplyArmor")
//! runtextmacro ADD_LOG_ACTION("gg_trg_InvisibleBuffCorrector")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BossRegister")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BossUnregister")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Functions")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BossRearFlankAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DefendAgainstDamage")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Initialization")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Beast_Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_KnockbackUnits")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BAmr_Config")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BAmr_Cast")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BAmr_Block")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BAmr_Periodic")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BoneArmorAOE_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BoneArmorAOE_GUI")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Scream")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CleaveFix")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TCAFix_Config")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TCAFix_UnitIndexed")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TCAFix_UnitLearnsSkill")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TCAFix_UnitDeindexed")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EtherealFix_OnDamage")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HealFix_Unblock")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GrabTreeFix_Unblock")
//! runtextmacro ADD_LOG_ACTION("gg_trg_PauseAllUnits")
//! runtextmacro ADD_LOG_ACTION("gg_trg_UnpauseAllUnits")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Init_sequence")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Alliances")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Buildings")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DarkUnitVars")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Flags")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Hashtables")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Items")
//! runtextmacro ADD_LOG_ACTION("gg_trg_NeutralUnitVars")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Points")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Quests")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Regions")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Times")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DarkUnits")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Music")
//! runtextmacro ADD_LOG_ACTION("gg_trg_NeutralUnits")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Invulnerables")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Shops")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Check")
//! runtextmacro ADD_LOG_ACTION("gg_trg_StartGame")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OptionsGame")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OptionsDifficulty")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OptionsHeroes")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OptionsTimeOut")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ModeNormal")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ModeRandom")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ModeExtreme")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ModeEasy")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ReviveTrees")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CastleUnderAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_StopAttackCastle")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinHelp")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinAttacked")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BuyLevels")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BuyTomes")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CloseWay")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ExtremeLevel")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Fog")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Info")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Kick")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OpenWay")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Random")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Rebuy")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Repick")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RepickTip")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Host")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FullRestoration")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SuperItems")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LeaderBoard")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LeaderBoardAdd")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect1a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect1b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect2a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect2b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect3a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect3b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect4a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect4b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect5a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect5b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect6a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect6b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect7a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect7b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect8a")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSelect8b")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSetup")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroDead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ControlSharing")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EasyPowerUp")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroSetupDual")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroDeadDual")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroChange")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroChangeShared")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroStats")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroLevel")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroMoveItem")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroUseItem")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroAcquireItem")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroLoseItem")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DualHeroCooldown")
//! runtextmacro ADD_LOG_ACTION("gg_trg_BoostLevel")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EnableHeroAbilities")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EnableItemAbilities")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Level20Abilities")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Armor")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ArtifactCollector")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttributeBonusPerLevel")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AuraOfBlight")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Bomb")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CooldownsReduction")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CriticalStrikeAura")
//! runtextmacro ADD_LOG_ACTION("gg_trg_CursedClaws")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DamageDealtMalus")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DamageTakenMalus")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DebilitationAura")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Doom")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Earthquake")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EarthquakeStop")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Ensnare")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FanOfKnives_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FanOfKnives")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FrostParalysisAura")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Hex_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Hex")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HolyLight")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Immolation")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ImmolationGhost")
//! runtextmacro ADD_LOG_ACTION("gg_trg_InnerFire")
//! runtextmacro ADD_LOG_ACTION("gg_trg_KnightsChallenge")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LifeRegenerationAura")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LightFrenzy")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LightningAttackOnOff")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MagicDefenseOnOff")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MorphingCopyStats")
//! runtextmacro ADD_LOG_ACTION("gg_trg_OwlScout")
//! runtextmacro ADD_LOG_ACTION("gg_trg_PermanentLightning")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Polymorph_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Polymorph")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RealmOfSoul")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RefreshCooldownChance")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RuneClockCreate")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RuneClockDestroy")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RunicWeaponCreate")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ShadowStrike_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ShadowStrike")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ShockWave_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ShockWave")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpiritPig")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpiritualPresence")
//! runtextmacro ADD_LOG_ACTION("gg_trg_StormBolt_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_StormBolt")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ThunderClap_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ThunderClap")
//! runtextmacro ADD_LOG_ACTION("gg_trg_TrueTank")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WardsMastery")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WarStomp_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WarStomp")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Whirlwind")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttackStart")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Kills100")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Kills500")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Kills1000")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Kills2000")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttackCome")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttackCheck")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttackTower")
//! runtextmacro ADD_LOG_ACTION("gg_trg_AttackNecropolis")
//! runtextmacro ADD_LOG_ACTION("gg_trg_ExtremePowerUp")
//! runtextmacro ADD_LOG_ACTION("gg_trg_DragonAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_HeroAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_LightningAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SilentAssassin")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Rune")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameLevel1")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WarnBeforeGameLevel2")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameLevel2")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameLevel3")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameLevel4")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveTimer")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveAttack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveKills20")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveKills40")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveKills60")
//! runtextmacro ADD_LOG_ACTION("gg_trg_WaveKills80")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FinalWaveReady")
//! runtextmacro ADD_LOG_ACTION("gg_trg_FinalWaveStart")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival1Ready")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival1Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival1Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival2Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival2Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival3Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Survival3Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss1Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss1Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss2Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss2Leave")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss3Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss4Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss5Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss6Come")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss6Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss6Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss7Come")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss7Colour")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss7Power")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Boss7Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special4Agree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special4Won")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special4Failed")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special5Agree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special5EnableAbilities")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special5Won")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special5Failed")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Timer")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Stop")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Leave")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8AntiHack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special8Move")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinClap_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinClap")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinBolt_JASS")
//! runtextmacro ADD_LOG_ACTION("gg_trg_MuradinBolt")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Timer")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Attack")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Corpse")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Stop")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special1Dead")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special2Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special2Stop")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special2Won")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special2TimeOut")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special2Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3Start")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3Stop")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3Count")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3Won")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3TimeOut")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special3Teleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special6Agree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Special7Agree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXDialog")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXStart")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXDisagree")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXRevive")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXTeleport")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXPause")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXResume")
//! runtextmacro ADD_LOG_ACTION("gg_trg_SpecialXCancel")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Victory")
//! runtextmacro ADD_LOG_ACTION("gg_trg_YouLose")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EndGame")
//! runtextmacro ADD_LOG_ACTION("gg_trg_Disconnect")
//! runtextmacro ADD_LOG_ACTION("gg_trg_RemovePlayer")
//! runtextmacro ADD_LOG_ACTION("gg_trg_EndPitch")
//! runtextmacro ADD_LOG_ACTION("gg_trg_GameStatus")
call DebugLog(LVL_DEBUG, "Trigger not tracked.")
endfunction
hook TriggerAddAction onTriggerAddAction
function onTriggerAddCondition takes trigger whichTrigger, boolexpr condition returns nothing
// For developers who made JASS triggers and used Condition to execute code instead of Action for performances reasons.
// REQUIRES: uncomment the line "// hook TriggerAddCondition onTriggerAddCondition"
endfunction
// hook TriggerAddCondition onTriggerAddCondition
endlibrary
// -------------------------------------------------------------------------------
// Conditions - begin ------------------------------------------------------------
function AlwaysTrueCondition takes nothing returns boolean
return true
endfunction
function IsUnitUnknownOrDead takes unit loc_unit01 returns boolean
return GetUnitTypeId(loc_unit01)<1 or IsUnitType(loc_unit01,UNIT_TYPE_DEAD)==true
endfunction
function IsCourrierType takes unit loc_unit01 returns boolean
//return GetUnitTypeId(loc_unit01)=='n00I' or GetUnitTypeId(loc_unit01)=='n022' or GetUnitTypeId(loc_unit01)=='n021' or GetUnitTypeId(loc_unit01)=='n023' or GetUnitTypeId(loc_unit01)=='n024' or GetUnitTypeId(loc_unit01)=='n025' or GetUnitTypeId(loc_unit01)=='e01H' or GetUnitTypeId(loc_unit01)=='e01Z' or GetUnitTypeId(loc_unit01)=='n00M' or GetUnitTypeId(loc_unit01)=='n0HV'
return false
endfunction
function IsInvalidTargetType takes unit loc_unit01 returns boolean
//local integer loc_integer01=GetUnitTypeId(loc_unit01)
//return loc_integer01=='n004' or loc_integer01=='n01G' or loc_integer01=='n01C' or loc_integer01=='n018' or loc_integer01=='e00K' or loc_integer01=='e00I' or loc_integer01=='e00L' or loc_integer01=='e01J'
return false
endfunction
// TODO : update when trees are added
function IsTreeDestructableType takes destructable loc_destructable01 returns boolean
//return GetDestructableTypeId(loc_destructable01)=='NTtc' or GetDestructableTypeId(loc_destructable01)=='NTtw' or GetDestructableTypeId(loc_destructable01)=='ATtr' or GetDestructableTypeId(loc_destructable01)=='B002' or GetDestructableTypeId(loc_destructable01)=='B003' or GetDestructableTypeId(loc_destructable01)=='B005'
return false
endfunction
function TargetFilterNoAncients takes nothing returns boolean
return IsUnitEnemy(udg_TempTossProjectedUnit,GetOwningPlayer(GetFilterUnit()))and(GetUnitAbilityLevel(GetFilterUnit(),'A069')==0 and IsUnitUnknownOrDead(GetFilterUnit())==false)and(IsUnitType(GetFilterUnit(),UNIT_TYPE_ANCIENT)==false or IsInvalidTargetType(GetFilterUnit()))
endfunction
function IsUnitFlying takes unit loc_unit01 returns boolean
//return GetUnitTypeId(loc_unit01)=='H00F' or GetUnitTypeId(loc_unit01)=='H00E' or GetUnitTypeId(loc_unit01)=='H00G' or GetUnitTypeId(loc_unit01)=='O017'
return false
endfunction
// Conditions - end --------------------------------------------------------------
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
// Maths - begin -----------------------------------------------------------------
function MathsAtan2 takes real loc_real01,real loc_real02,real loc_real03,real loc_real04 returns real
return bj_RADTODEG*Atan2(loc_real04-loc_real02,loc_real03-loc_real01)
endfunction
// Coord X1, Coord Y1, Coord X2, Coord Y2
function DistanceBetweenPointsByCoord takes real loc_real01,real loc_real02,real loc_real03,real loc_real04 returns real
return SquareRoot(((loc_real01-loc_real03)*(loc_real01-loc_real03))+((loc_real02-loc_real04)*(loc_real02-loc_real04)))
endfunction
function DistanceBetweenUnits takes unit loc_unit01,unit loc_unit02 returns real
local real loc_real01=GetUnitX(loc_unit01)
local real loc_real02=GetUnitY(loc_unit01)
local real loc_real03=GetUnitX(loc_unit02)
local real loc_real04=GetUnitY(loc_unit02)
if loc_unit01==null or loc_unit02==null then
return I2R(9999999999)
else
return SquareRoot((loc_real01-loc_real03)*(loc_real01-loc_real03)+(loc_real02-loc_real04)*(loc_real02-loc_real04))
endif
return 1.0
endfunction
// Maths - end -------------------------------------------------------------------
// -------------------------------------------------------------------------------
// -------------------------------------------------------------------------------
// Actions - begin ---------------------------------------------------------------
function TriggerRegisterAllPlayersUnitEvent takes trigger loc_trigger01,playerunitevent loc_playerunitevent01 returns nothing
local integer loc_integer01=0
loop
call TriggerRegisterPlayerUnitEvent(loc_trigger01,Player(loc_integer01),loc_playerunitevent01,Condition(function AlwaysTrueCondition))
set loc_integer01=loc_integer01+1
exitwhen loc_integer01==12
endloop
endfunction
function DamageUnit takes unit loc_unit01,unit loc_unit02,integer loc_integer01,real loc_real01 returns nothing
if loc_integer01==0 then
return
endif
if loc_integer01==1 then
call UnitDamageTarget(loc_unit01,loc_unit02,loc_real01,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_FIRE,WEAPON_TYPE_WHOKNOWS)
elseif loc_integer01==2 then
call UnitDamageTarget(loc_unit01,loc_unit02,loc_real01,true,true,ATTACK_TYPE_HERO,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
elseif loc_integer01==3 then
call UnitDamageTarget(loc_unit01,loc_unit02,loc_real01,true,true,ATTACK_TYPE_HERO,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
elseif loc_integer01==4 then
call UnitDamageTarget(loc_unit01,loc_unit02,loc_real01,true,true,ATTACK_TYPE_PIERCE,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
endif
endfunction
function DisplayError takes player loc_player01,string loc_string01 returns nothing
local sound loc_sound01=CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
if(GetLocalPlayer()==loc_player01)then
call StartSound(loc_sound01)
endif
if(loc_string01!="")and(loc_string01!=null)then
call ClearTextMessages()
call DisplayTimedTextToPlayer(loc_player01,0.50,-1.00,2.00,"|cffffcc00"+loc_string01+"|r")
endif
call KillSoundWhenDone(loc_sound01)
endfunction
function DestroyTreeDestructable takes nothing returns nothing
if IsTreeDestructableType(GetEnumDestructable())then
call KillDestructable(GetEnumDestructable())
endif
endfunction
// Coord X, Coord Y, HalfRangeX, HalfRangeY
function DestroyTreeDestructablesInRegion takes real loc_real01,real loc_real02,real loc_real03 returns nothing
local rect loc_rect01=Rect(loc_real01-loc_real03,loc_real02-loc_real03,loc_real01+loc_real03,loc_real02+loc_real03)
call EnumDestructablesInRectAll(loc_rect01,function DestroyTreeDestructable)
call RemoveRect(loc_rect01)
set loc_rect01=null
endfunction
function StopUnitSilent takes unit loc_unit01 returns nothing
call PauseUnit(loc_unit01,true)
call IssueImmediateOrder(loc_unit01,"stop")
call PauseUnit(loc_unit01,false)
endfunction
function UnitAddPermanentAbility takes unit loc_unit01,integer loc_integer01 returns nothing
call UnitAddAbility(loc_unit01,loc_integer01)
call UnitMakeAbilityPermanent(loc_unit01,true,loc_integer01)
endfunction
function SetAllPlayersAbilityAvailable takes integer loc_integer01 returns nothing
local integer loc_integer02=0
loop
exitwhen loc_integer02>8
call SetPlayerAbilityAvailable(Player(loc_integer02),loc_integer01,false)
set loc_integer02=loc_integer02+1
endloop
endfunction
function SaveUnitInCacheFinish takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
call DebugLog(LVL_DEBUG, "SaveUnitInCacheFinish")
call SaveInteger(udg_DotaHashtable,(GetHandleId(((LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(14)))))),(((LoadInteger(udg_DotaHashtable,(loc_integer01),(33))))),(2))
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DisableTrigger(loc_trigger01)
set loc_trigger01=null
return false
endfunction
function SaveUnitInCacheWithDelay takes unit loc_unit01,integer loc_integer01,real loc_real01 returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerAddCondition(loc_trigger01,Condition(function SaveUnitInCacheFinish))
call TriggerRegisterTimerEvent(loc_trigger01,loc_real01,false)
call SaveInteger(udg_DotaHashtable,(GetHandleId((loc_unit01))),((loc_integer01)),(1))
call SaveUnitHandle(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(14),(loc_unit01))
call SaveInteger(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(33),(loc_integer01))
set loc_trigger01=null
endfunction
// Actions - end -----------------------------------------------------------------
// -------------------------------------------------------------------------------
function AvalancheAdditionalDamageTossedUnit takes nothing returns boolean
if((LoadInteger(udg_DotaHashtable,(GetHandleId((GetFilterUnit()))),((4268))))==1)and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(udg_TCAAvalancheCaster))==true then
call DamageUnit(udg_TCAAvalancheCaster,GetFilterUnit(),1,udg_TempAvalancheDamages)
endif
return false
endfunction
function AvalancheAdditionalDamageTossedUnitPeriodic takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(14)))
local real loc_real01=(LoadReal(udg_DotaHashtable,(loc_integer01),(6)))
local real loc_real02=(LoadReal(udg_DotaHashtable,(loc_integer01),(7)))
local unit loc_unit02=CreateUnit(GetOwningPlayer(loc_unit01),'n00E',loc_real01,loc_real02,0)
local integer loc_integer02=GetUnitAbilityLevel(loc_unit01,'A06E')
local group loc_group01=CreateGroup()
call DebugLog(LVL_DEBUG, "AvalancheAdditionalDamageTossedUnitPeriodic")
call UnitAddAbility(loc_unit02,'A06F')
set udg_TCAAvalancheCaster=loc_unit01
if loc_integer02==1 then
set udg_TempAvalancheDamages=75
elseif loc_integer02==2 then
set udg_TempAvalancheDamages=100
elseif loc_integer02==3 then
set udg_TempAvalancheDamages=210
elseif loc_integer02==4 then
set udg_TempAvalancheDamages=230
endif
call SetUnitAbilityLevel(loc_unit02,'A06F',loc_integer02)
call GroupEnumUnitsInRange(loc_group01,loc_real01,loc_real02,299,Condition(function AvalancheAdditionalDamageTossedUnit))
call DestroyGroup(loc_group01)
if GetTriggerEvalCount(loc_trigger01)>6 then
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DisableTrigger(loc_trigger01)
endif
set loc_trigger01=null
set loc_unit01=null
set loc_unit02=null
set loc_group01=null
return false
endfunction
function AvalancheEffect takes nothing returns nothing
local unit loc_unit01=GetTriggerUnit()
local trigger loc_trigger01=CreateTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local location loc_location01=GetSpellTargetLoc()
local unit loc_unit02=CreateUnit(GetOwningPlayer(loc_unit01),'n00E',GetUnitX(loc_unit01),GetUnitY(loc_unit01),0)
local integer loc_integer02=GetUnitAbilityLevel(loc_unit01,'A06E')
call DebugLog(LVL_DEBUG, "AvalancheEffect")
call UnitAddAbility(loc_unit02,'A06H')
call SetUnitAbilityLevel(loc_unit02,'A06H',loc_integer02)
call IssuePointOrder(loc_unit02,"clusterrockets",GetLocationX(loc_location01),GetLocationY(loc_location01))
call TriggerRegisterTimerEvent(loc_trigger01,0.25,true)
call TriggerAddCondition(loc_trigger01,Condition(function AvalancheAdditionalDamageTossedUnitPeriodic))
call SaveUnitHandle(udg_DotaHashtable,(loc_integer01),(14),(loc_unit01))
call SaveReal(udg_DotaHashtable,(loc_integer01),(6),((GetLocationX(loc_location01))*1.0))
call SaveReal(udg_DotaHashtable,(loc_integer01),(7),((GetLocationY(loc_location01))*1.0))
call TriggerEvaluate(loc_trigger01)
call RemoveLocation(loc_location01)
set loc_unit01=null
set loc_location01=null
set loc_trigger01=null
set loc_unit02=null
endfunction
function AvalancheSkill takes nothing returns boolean
if GetSpellAbilityId()=='A06E' then
call DebugLog(LVL_DEBUG, "SpellEffect - Avalanche")
call AvalancheEffect()
endif
return false
endfunction
function AvalancheEffectRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(loc_trigger01,Condition(function AvalancheSkill))
set loc_trigger01=null
endfunction
function CraggyExteriorEffect takes nothing returns boolean
local unit loc_unit01=GetTriggerUnit()
local unit loc_unit02=GetAttacker()
local integer loc_integer01=GetUnitAbilityLevel(loc_unit01,'A066')
local unit loc_unit03
call DebugLog(LVL_DEBUG, "CraggyExteriorEffect")
if GetRandomInt(1,100)<=loc_integer01*6 and DistanceBetweenUnits(loc_unit01,loc_unit02)<325 then
set loc_unit03=CreateUnit(GetOwningPlayer(loc_unit01),'n00E',GetUnitX(loc_unit02),GetUnitY(loc_unit02),0)
call UnitAddAbility(loc_unit03,'A067')
call SetUnitAbilityLevel(loc_unit03,'A067',loc_integer01)
call IssueTargetOrder(loc_unit03,"thunderbolt",loc_unit02)
set loc_unit03=null
endif
set loc_unit01=null
set loc_unit02=null
return false
endfunction
function CraggyExteriorEffectRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
local unit loc_unit01=GetTriggerUnit()
call TriggerRegisterUnitEvent(loc_trigger01,loc_unit01,EVENT_UNIT_ATTACKED)
call TriggerAddCondition(loc_trigger01,Condition(function CraggyExteriorEffect))
set loc_trigger01=null
set loc_unit01=null
endfunction
function CraggyExteriorSkill takes nothing returns boolean
if GetLearnedSkill()=='A066' and GetUnitAbilityLevel(GetTriggerUnit(),'A066')==1 and IsUnitIllusion(GetTriggerUnit())==false then
call DebugLog(LVL_DEBUG, "CraggyExteriorSkill")
call CraggyExteriorEffectRegister()
endif
return false
endfunction
function CraggyExteriorSkillRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_HERO_SKILL)
call TriggerAddCondition(loc_trigger01,Condition(function CraggyExteriorSkill))
set loc_trigger01=null
endfunction
function SetAllPlayerGrabTreeAvailable takes nothing returns nothing
local unit loc_unit01=GetTriggerUnit()
call SetAllPlayersAbilityAvailable('A2KK')
endfunction
function GrabTreeCountSuccessfulAttacks takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local integer loc_integer02=(LoadInteger(udg_DotaHashtable,(loc_integer01),(375)))
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(2)))
local integer loc_integer03
if GetTriggerEventId()==EVENT_UNIT_DAMAGED then
if GetEventDamageSource()==loc_unit01 and GetEventDamage()>20 then
set loc_integer03=(LoadInteger(udg_DotaHashtable,(GetHandleId(loc_unit01)),(674))) // Get number of attacks already made
if((LoadInteger(udg_DotaHashtable,(GetHandleId((loc_unit01))),((4297))))==1)==false then
call SaveUnitInCacheWithDelay(loc_unit01,4297,0.1)
call SaveInteger(udg_DotaHashtable,(GetHandleId(loc_unit01)),(674),(loc_integer03+1)) // Save number or attacks made
endif
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DestroyTrigger(loc_trigger01)
endif
else
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DestroyTrigger(loc_trigger01)
endif
set loc_trigger01=null
set loc_unit01=null
return false
endfunction
function GrabTreeAttackEffect takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local trigger loc_trigger02
local integer loc_integer01=GetHandleId(loc_trigger01)
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(2)))
local integer loc_integer02=(LoadInteger(udg_DotaHashtable,(GetHandleId(loc_unit01)),(674)))
call DebugLog(LVL_DEBUG, "GrabTreeAttackEffect")
if GetTriggerEventId()==EVENT_PLAYER_UNIT_ATTACKED and loc_integer02<30 then
// A unit is attacked and the max attack count is not reached yet
if GetAttacker()==loc_unit01 and((LoadInteger(udg_DotaHashtable,(GetHandleId((loc_unit01))),((4297))))==1)==false then
// Attacker is Tiny && SaveUnitInCacheWithDelay is finshed
set loc_trigger02=CreateTrigger()
call TriggerRegisterUnitEvent(loc_trigger02,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
call TriggerRegisterTimerEvent(loc_trigger02,1,false)
call TriggerAddCondition(loc_trigger02,Condition(function GrabTreeCountSuccessfulAttacks))
call SaveUnitHandle(udg_DotaHashtable,(GetHandleId(loc_trigger02)),(2),(loc_unit01))
endif
endif
if loc_integer02>29 then
// The max attack count is about to be reached
call SaveInteger(udg_DotaHashtable,(GetHandleId(GetTriggerUnit())),(674),(0))
call UnitRemoveAbility(loc_unit01,'A06M')
if(LoadInteger(udg_DotaHashtable,(loc_integer01),(34)))==1 then
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DestroyTrigger(loc_trigger01)
endif
endif
if GetTriggerEventId()!=EVENT_PLAYER_UNIT_ATTACKED then
// A unit is attacked
call SaveInteger(udg_DotaHashtable,(loc_integer01),(34),(1))
if loc_integer02>29 then
// The max attack count is about to be reached
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DestroyTrigger(loc_trigger01)
endif
call UnitRemoveAbility(loc_unit01,'A06K')
call SetPlayerTechResearched(GetOwningPlayer(loc_unit01),'R002',0)
//if(Func0367((loc_unit01),integers084[integer355])!=null)then
if (GetHeroLevel(loc_unit01)>=20)then
// Unit carries Tiny's aghanim scepter
call UnitAddPermanentAbility(loc_unit01,'A06L')
endif
call SetPlayerAbilityAvailable(GetOwningPlayer(loc_unit01),'A06L',true)
endif
set loc_trigger01=null
set loc_unit01=null
return false
endfunction
//Dissused
function Func2388 takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(2)))
if GetTriggerEvalCount(loc_trigger01)==1 then
call SetUnitTimeScalePercent(loc_unit01,250)
else
call SetUnitTimeScalePercent(loc_unit01,100)
call SetUnitAnimationByIndex(loc_unit01,12)
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DestroyTrigger(loc_trigger01)
endif
set loc_trigger01=null
return false
endfunction
function GrabTreeEffectRegister takes nothing returns boolean
local trigger loc_trigger01
call DebugLog(LVL_DEBUG, "GrabTreeEffectRegister")
if GetSpellAbilityId()=='A06L' then
// Tiny is casting GrabTree - Current version
call SaveUnitInCacheWithDelay(GetTriggerUnit(),4296,29.9)
call SetPlayerAbilityAvailable(GetOwningPlayer(GetTriggerUnit()),'A06L',false) // Remove dummy grap tree ability
call SetPlayerAbilityAvailable(GetOwningPlayer(GetTriggerUnit()),'A06K',true)
call UnitAddPermanentAbility(GetTriggerUnit(),'A06K') // Add the real grab tree ability
call SetPlayerTechResearched(GetOwningPlayer(GetTriggerUnit()),'R002',1)
call SetPlayerAbilityAvailable(GetOwningPlayer(GetTriggerUnit()),'A06M',false) // Disable to hide the spellbook
call UnitAddPermanentAbility(GetTriggerUnit(),'A06M')
call IssueTargetOrder(GetTriggerUnit(),"grabtree",GetSpellTargetDestructable()) // Cast the real grab tree ability
set loc_trigger01=CreateTrigger()
call TriggerRegisterTimerEvent(loc_trigger01,30,false)
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(loc_trigger01,Condition(function GrabTreeAttackEffect))
call SaveUnitHandle(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(2),(GetTriggerUnit()))
call SaveInteger(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(34),(0))
call SaveInteger(udg_DotaHashtable,(GetHandleId(GetTriggerUnit())),(674),(0))
set loc_trigger01=null
elseif GetSpellAbilityId()=='A06C' then
// Tiny is casting GrabTree - Old version
call RemoveDestructable(GetSpellTargetDestructable())
call ShowUnit(GetTriggerUnit(),false)
call ShowUnit(GetTriggerUnit(),true)
call UnitRemoveAbility(GetTriggerUnit(),'Aloc')
call UnitAddAbility(GetTriggerUnit(),'A06D')
call UnitRemoveAbility(GetTriggerUnit(),'A06D')
call UnitAddAbility(GetTriggerUnit(),'A06I')
call UnitRemoveAbility(GetTriggerUnit(),'A06I')
call AddUnitAnimationProperties(GetTriggerUnit(),"upgrade",false)
endif
return false
endfunction
//Dissused
function Func2390 takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(2)))
//if(Func0367((loc_unit01),integers084[integer355])!=null)then
if(GetHeroLevel(loc_unit01)>=20)then
// Unit carries Tiny's aghanim scepter
if((LoadInteger(udg_DotaHashtable,(GetHandleId((loc_unit01))),((4296))))==1)==false then
if GetUnitAbilityLevel(loc_unit01,'A06L')==0 and GetUnitAbilityLevel(loc_unit01,'A06K')==0 then
call SetPlayerAbilityAvailable(GetOwningPlayer(loc_unit01),'A06L',true)
call UnitAddPermanentAbility(loc_unit01,'A06L')
call SetPlayerTechResearched(GetOwningPlayer(loc_unit01),'R002',0)
endif
endif
else
call UnitRemoveAbility(loc_unit01,'A06L')
call UnitRemoveAbility(loc_unit01,'A06K')
call SetPlayerTechResearched(GetOwningPlayer(loc_unit01),'R002',0)
endif
set loc_trigger01=null
return false
endfunction
// New function
function GrapTreeSkillRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(loc_trigger01,Condition(function GrabTreeEffectRegister))
set loc_trigger01=null
endfunction
function GrowSkillLearnConditions takes nothing returns boolean
return GetLearnedSkill()=='A068' and IsUnitIllusion(GetTriggerUnit())==false
endfunction
function GrowUpdateScaleLoop takes nothing returns nothing
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(GetHandleId(GetTriggeringTrigger())),(298)))
local integer loc_integer01=GetUnitAbilityLevel(loc_unit01,'A068')
if GetUnitState(loc_unit01,UNIT_STATE_LIFE)>1 then
call SetUnitScale(loc_unit01,0.5+0.25*loc_integer01,0.5+0.25*loc_integer01,0.5+0.25*loc_integer01)
endif
endfunction
function GrowUpdateScaleEnterRegion takes nothing returns boolean
local integer loc_integer01
if IsUnitIllusion(GetTriggerUnit())and GetUnitTypeId(GetTriggerUnit())=='U00B' then
set loc_integer01=GetUnitAbilityLevel((LoadUnitHandle(udg_DotaHashtable,(GetHandleId(GetTriggeringTrigger())),(298))),'A068')
call SetUnitScale(GetTriggerUnit(),0.5+0.25*loc_integer01,0.5+0.25*loc_integer01,0.5+0.25*loc_integer01)
endif
return false
endfunction
function GrowSkillLearn takes nothing returns nothing
local trigger loc_trigger01
local unit loc_unit01=GetTriggerUnit()
local integer loc_integer01=GetUnitAbilityLevel(loc_unit01,'A068')
local unit loc_unit03=GetTriggerUnit()
local region loc_region01
call DebugLog(LVL_DEBUG, "GrowSkill")
call SetPlayerTechResearched(GetOwningPlayer(loc_unit01),'R001',loc_integer01)
if loc_integer01==1 then
set loc_trigger01=CreateTrigger()
call TriggerAddAction(loc_trigger01,function GrowUpdateScaleLoop)
call TriggerRegisterTimerEvent(loc_trigger01,2.00,true)
call SaveUnitHandle(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(298),(loc_unit01))
call SetUnitScale(loc_unit01,0.5+0.25*loc_integer01,0.5+0.25*loc_integer01,0.5+0.25*loc_integer01)
set loc_trigger01=CreateTrigger()
call TriggerRegisterEnterRectSimple( loc_trigger01, GetEntireMapRect() )
call TriggerAddCondition(loc_trigger01,Condition(function GrowUpdateScaleEnterRegion))
call SaveUnitHandle(udg_DotaHashtable,(GetHandleId(loc_trigger01)),(298),(loc_unit01))
set loc_trigger01=null
endif
set loc_unit03=null
endfunction
function GrowSkillRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_HERO_SKILL)
call TriggerAddCondition(loc_trigger01,Condition(function GrowSkillLearnConditions))
call TriggerAddAction(loc_trigger01,function GrowSkillLearn)
set loc_trigger01=CreateTrigger()
//call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_EFFECT)
//call TriggerAddCondition(loc_trigger01,Condition(function GrabTreeEffectRegister))
//call SetAllPlayerGrabTreeAvailable()
set loc_trigger01=null
endfunction
function TossDamageUnit takes nothing returns nothing
if IsUnitType(GetEnumUnit(),UNIT_TYPE_STRUCTURE)==true then
call DamageUnit(udg_TempTossCaster,GetEnumUnit(),1,udg_TempTossDamages/3)
else
call DamageUnit(udg_TempTossCaster,GetEnumUnit(),1,udg_TempTossDamages)
endif
endfunction
function TossAreaDamage takes unit loc_unit01,real loc_real01,real loc_real02,real loc_real03,real loc_real04 returns nothing
local group loc_group01=CreateGroup()
set udg_TempTossProjectedUnit=loc_unit01
call GroupEnumUnitsInRange(loc_group01,loc_real01,loc_real02,loc_real03,Condition(function TargetFilterNoAncients))
set udg_TempTossCaster=loc_unit01
set udg_TempTossDamages=loc_real04
call ForGroup(loc_group01,function TossDamageUnit)
call DestroyGroup(loc_group01)
set loc_group01=null
endfunction
function TossFilterProjectableUnits takes nothing returns boolean
if((GetUnitAbilityLevel(GetFilterUnit(),'A069')==0 and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE)==false and GetUnitDefaultMoveSpeed(GetFilterUnit())>0.00 and IsUnitUnknownOrDead(GetFilterUnit())==false)and IsUnitVisible(GetFilterUnit(),GetOwningPlayer(GetTriggerUnit())))and IsCourrierType(GetFilterUnit())==false and(IsUnitType(GetFilterUnit(),UNIT_TYPE_ANCIENT)==false or IsInvalidTargetType(GetFilterUnit()))then
return true
endif
return false
endfunction
function TossSelectProjectUnit takes unit loc_unit01 returns unit
local unit loc_unit02=null
local group loc_group01=CreateGroup()
call GroupEnumUnitsInRange(loc_group01,GetUnitX(loc_unit01),GetUnitY(loc_unit01),275,Condition(function TossFilterProjectableUnits))
call GroupRemoveUnit(loc_group01,loc_unit01)
set loc_unit02=GroupPickRandomUnit(loc_group01)
call DestroyGroup(loc_group01)
set udg_TempTossProjectedUnit=loc_unit02
set loc_unit02=null
set loc_group01=null
return udg_TempTossProjectedUnit
endfunction
function TossProjectedUnitFlightPeriodic takes nothing returns boolean
local trigger loc_trigger01=GetTriggeringTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
local integer loc_integer02=GetTriggerEvalCount(loc_trigger01)
local unit loc_unit01=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(14))) // Caster unit
local unit loc_unit02=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(2))) // Projected unit
//local integer loc_integer03=(LoadInteger(udg_DotaHashtable,(loc_integer01),(30)))
//local unit loc_unit03=Func0022(loc_integer03)
local unit loc_unit03=(LoadUnitHandle(udg_DotaHashtable,(loc_integer01),(30))) // Target unit
local real loc_real01=(LoadReal(udg_DotaHashtable,(loc_integer01),(282))) // Target X
local real loc_real02=(LoadReal(udg_DotaHashtable,(loc_integer01),(283))) // Target Y
local real loc_real03=GetUnitX(loc_unit02)
local real loc_real04=GetUnitY(loc_unit02)
local real loc_real05=GetUnitX(loc_unit03)
local real loc_real06=GetUnitY(loc_unit03)
local real loc_real07
local real loc_real08
local real loc_real09
local real loc_real10
local real loc_real11
local real loc_real12
local location loc_location01
call DebugLog(LVL_DEBUG, "TossProjectedUnitFlightPeriodic")
if DistanceBetweenPointsByCoord(loc_real01,loc_real02,loc_real05,loc_real06)>1000 then
set loc_real05=loc_real01
set loc_real06=loc_real02
endif
set loc_real07=MathsAtan2(loc_real03,loc_real04,loc_real05,loc_real06)
set loc_real08=DistanceBetweenPointsByCoord(loc_real03,loc_real04,loc_real05,loc_real06)
set loc_real09=loc_real08/IMaxBJ((51-loc_integer02),1)
set loc_real10=(loc_integer02-25)*(loc_integer02-25)
set loc_real11=loc_real03+loc_real09*Cos(loc_real07*bj_DEGTORAD)
set loc_real12=loc_real04+loc_real09*Sin(loc_real07*bj_DEGTORAD)
if loc_integer02<51 then
if IsUnitFlying(loc_unit02)==false then
call SetUnitFlyHeight(loc_unit02,775-loc_real10,0)
endif
call SetUnitPosition(loc_unit02,loc_real11,loc_real12)
else
if IsUnitFlying(loc_unit02)==false then
call SetUnitFlyHeight(loc_unit02,GetUnitDefaultFlyHeight(loc_unit02),0)
endif
call PauseUnit(loc_unit02,false)
call SetUnitPathing(loc_unit02,true)
call SetUnitPosition(loc_unit02,loc_real05,loc_real06)
call SaveInteger(udg_DotaHashtable,(GetHandleId((loc_unit02))),((4268)),(2))
set loc_location01=Location(loc_real05,loc_real06)
call TerrainDeformationRippleBJ(0.2,true,loc_location01,1.00,300.00,96.00,1,64.00)
call RemoveLocation(loc_location01)
call DestroyEffect((LoadEffectHandle(udg_DotaHashtable,(loc_integer01),(32)))) // Projection effect handle
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl",GetUnitX(loc_unit02),GetUnitY(loc_unit02)))
if IsUnitAlly(loc_unit02,GetOwningPlayer(loc_unit01))then
else
//if(Func0367((loc_unit01),integers084[integer355])!=null)then
if(GetHeroLevel(loc_unit01)>=20)then
// Unit carries Aghanim scepter
call DamageUnit(loc_unit01,loc_unit02,1,(0.2+0.15*GetUnitAbilityLevel(loc_unit01,'A068')+1)*2000*GetUnitAbilityLevel(loc_unit01,'A06G'))
else
call DamageUnit(loc_unit01,loc_unit02,1,(0.2+0.15*GetUnitAbilityLevel(loc_unit01,'A068'))*2000*GetUnitAbilityLevel(loc_unit01,'A06G'))
endif
endif
call DestroyTreeDestructablesInRegion(loc_real05,loc_real06,300)
call TossAreaDamage(loc_unit01,loc_real05,loc_real06,300,550*GetUnitAbilityLevel(loc_unit01,'A06G'))
//call Func0021(loc_integer03)
call FlushChildHashtable(udg_DotaHashtable,(loc_integer01))
call DisableTrigger(loc_trigger01)
endif
set loc_trigger01=null
set loc_unit01=null
set loc_unit02=null
set loc_unit03=null
set loc_location01=null
return false
endfunction
function TossSourceEffect takes nothing returns nothing
local unit loc_unit01=GetTriggerUnit()
local unit loc_unit02=TossSelectProjectUnit(loc_unit01)
local unit loc_unit03=GetSpellTargetUnit()
local trigger loc_trigger01=CreateTrigger()
local integer loc_integer01=GetHandleId(loc_trigger01)
call DebugLog(LVL_DEBUG, "TossSourceEffect")
//call SetUnitAnimationByIndex(loc_unit01,4)
call SetUnitAnimation(loc_unit01, "spell")
call PauseUnit(loc_unit02,true)
call SetUnitPathing(loc_unit02,false)
if IsUnitFlying(loc_unit02)==false then
call UnitAddAbility(loc_unit02,'Amrf')
call UnitRemoveAbility(loc_unit02,'Amrf')
endif
call SaveInteger(udg_DotaHashtable,(GetHandleId((loc_unit02))),((4268)),(1)) // Is unit projected
call SaveUnitHandle(udg_DotaHashtable,(loc_integer01),(14),(loc_unit01)) // Caster unit
call SaveUnitHandle(udg_DotaHashtable,(loc_integer01),(2),(loc_unit02)) // Projected unit
//call SaveInteger(udg_DotaHashtable,(loc_integer01),(30),(Func0024(loc_unit03))) // Target handle
call SaveUnitHandle(udg_DotaHashtable,(loc_integer01),(30),loc_unit03) // Target unit
call SaveEffectHandle(udg_DotaHashtable,(loc_integer01),(32),(AddSpecialEffectTarget("Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl",loc_unit02,"origin"))) // Projection effect handle
call SaveReal(udg_DotaHashtable,(loc_integer01),(282),((GetUnitX(loc_unit03))*1.0)) // Target X
call SaveReal(udg_DotaHashtable,(loc_integer01),(283),((GetUnitY(loc_unit03))*1.0)) // Target Y
call TriggerRegisterTimerEvent(loc_trigger01,0.02,true)
call TriggerAddCondition(loc_trigger01,Condition(function TossProjectedUnitFlightPeriodic))
set loc_unit01=null
set loc_unit02=null
set loc_unit03=null
set loc_trigger01=null
endfunction
function TossSourceCast takes nothing returns nothing
local unit loc_unit01=GetTriggerUnit()
local unit loc_unit02=TossSelectProjectUnit(loc_unit01)
local unit loc_unit03=GetSpellTargetUnit()
call DebugLog(LVL_DEBUG, "TossSourceCast")
if loc_unit02==null then
call StopUnitSilent(loc_unit01)
call DisplayError(GetOwningPlayer(loc_unit01),"No valid unit to Toss")
elseif GetOwningPlayer(loc_unit03)==GetOwningPlayer(loc_unit01)then
call StopUnitSilent(loc_unit01)
call DisplayError(GetOwningPlayer(loc_unit01),"Cannot Toss to your own units")
endif
set loc_unit01=null
set loc_unit02=null
set loc_unit03=null
endfunction
function TossEffect takes nothing returns boolean
if GetSpellAbilityId()=='A06G' then
call DebugLog(LVL_DEBUG, "TossEffect")
if GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_CAST then
call TossSourceCast()
else
call TossSourceEffect()
endif
endif
return false
endfunction
function TossEffectRegister takes nothing returns nothing
local trigger loc_trigger01=CreateTrigger()
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerRegisterAllPlayersUnitEvent(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(loc_trigger01,Condition(function TossEffect))
set loc_trigger01=null
endfunction
library GameStatus uses optional PlayerUtils
/***************************************************************
*
* v1.0.0 by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Simple API for detecting if the game is online, offline, or a replay.
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map and save it (requires JassHelper *or* JNGP)
* _________________________________________________________________________
* 2. API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* This library provides one function
*
* function GetGameStatus takes nothing returns integer
*
* It returns one of the following constants
*
* - GAME_STATUS_OFFLINE
* - GAME_STATUS_ONLINE
* - GAME_STATUS_REPLAY
*
***************************************************************/
// Configuration:
globals
// The dummy unit is only created once, and removed directly after.
private constant integer DUMMY_UNIT_ID = 'hfoo'
endglobals
// (end)
globals
constant integer GAME_STATUS_OFFLINE = 0
constant integer GAME_STATUS_ONLINE = 1
constant integer GAME_STATUS_REPLAY = 2
private integer status = 0
endglobals
function GetGameStatus takes nothing returns integer
return status
endfunction
private module GameStatusInit
private static method onInit takes nothing returns nothing
local player firstPlayer
local unit u
local boolean selected
// find an actual player
static if not (LIBRARY_PlayerUtils) then
set firstPlayer = Player(0)
loop
exitwhen (GetPlayerController(firstPlayer) == MAP_CONTROL_USER and GetPlayerSlotState(firstPlayer) == PLAYER_SLOT_STATE_PLAYING)
set firstPlayer = Player(GetPlayerId(firstPlayer)+1)
endloop
else
set firstPlayer = User.fromPlaying(0).toPlayer()
endif
// force the player to select a dummy unit
set u = CreateUnit(firstPlayer, DUMMY_UNIT_ID, 0, 0, 0)
call SelectUnit(u, true)
set selected = IsUnitSelected(u, firstPlayer)
call RemoveUnit(u)
set u = null
if (selected) then
// detect if replay or offline game
if (ReloadGameCachesFromDisk()) then
set status = GAME_STATUS_OFFLINE
else
set status = GAME_STATUS_REPLAY
endif
else
// if the unit wasn't selected instantly, the game is online
set status = GAME_STATUS_ONLINE
endif
endmethod
endmodule
private struct GameStatus
implement GameStatusInit
endstruct
endlibrary
library Maths
function Floor takes real r returns integer
local integer i = R2I(r)
if r == i then
return i
endif
if r > 0 then
return i
else // if r < 0 then
return i - 1
endif
endfunction
function Ceil takes real r returns integer
local integer i = R2I(r)
if r == i then
return i
endif
if r > 0 then
return i + 1
else // if r < 0 then
return i
endif
endfunction
function Round takes real r returns integer
if r > 0 then
return R2I(r + 0.5)
else // if r < 0 then
return R2I(r - 0.5)
endif
endfunction
endlibrary
library Logarithm
globals
private constant integer ITERATIONS=20
endglobals
function Log takes real x returns real
local real min=-88.0
local real max= 88.0
local real mid
local integer i=ITERATIONS
loop
set mid=(min+max)/2
exitwhen(i<=0)
set i=i-1
if (Pow(bj_E,mid)>=x) then
set max=mid
else
set min=mid
endif
endloop
return mid
endfunction
function Logarithm takes real base, real x returns real
local real min=-88.0
local real max= 88.0
local real mid
local integer i=ITERATIONS
loop
set mid=(min+max)/2
exitwhen(i<=0)
set i=i-1
if (Pow(base,mid)>=x) then
set max=mid
else
set min=mid
endif
endloop
return mid
endfunction
endlibrary
/*
Armor lib v1.0.1 (28/11/2019) by Ricola3D
API:
### General ###
function ArmorToDamageFactor takes real whichArmor returns real
> Converts armor amount to damage factor.
function DamageFactorToArmor takes real whichDamageFactor returns real
> Converts damage factor to armor amount.
### Unit ###
function ModifyArmor takes unit whichUnit, real armorDiff returns nothing
> Adds/removes the given difference to unit's code armor.
function AdjustArmorToWhite takes unit whichUnit, real desiredWhiteArmor returns nothing
> Modifies unit's code armor to obtain the desired amount of white armor.
function AdjustArmorToWhitePercent takes unit whichUnit, real desiredWhiteArmorPercent returns nothing
> Modifies unit's code armor to obtain the desired percent of current white armor.
function AdjustArmorToTotal takes unit whichUnit, real desiredTotalArmor returns nothing
> Modifies unit's code armor to obtain the desired amount of total armor.
function AdjustArmorToTotalPercent takes unit whichUnit, real desiredTotalArmorPercent returns nothing
> Modifies unit's code armor to obtain the desired percent of current total armor.
function SetCodeArmor takes unit whichUnit, real desiredCodeArmor returns nothing
> Sets unit's code armor to the given value.
function GetWhiteArmor takes unit whichUnit returns real
> Gets white (base + agi + code) armor of the unit.
function GetGreenArmor takes unit whichUnit returns real
> Gets green armor of the unit.
function GetTotalArmor takes unit whichUnit returns real
> Gets total (white + green) armor of the unit.
function GetDamageFactor takes unit whichUnit returns real
> Gets the damage factor corresponding to the total armor of the unit.
function GetAgiArmor takes unit whichUnit, boolean includeBonuses returns real
> Gets agility armor of the unit.
function GetCodeArmor takes unit whichUnit returns real
> Gets code armor of the unit (0 by default, modified by setters).
function GetBaseArmor takes unit whichUnit returns real
> Worthless. Gets base (value from Object Editor) armor of the unit.
*/
native UnitAlive takes unit id returns boolean
library Armor requires Logarithm
globals
// ----------------------------------------------------------------------------
// BASE SETTINGS
// ----------------------------------------------------------------------------
// Values shall be taken from gameplay constants
constant real AGI_DEFENSE_BASE = 5.00 // "Hero Attributes - Defense Base Value (before Agility Bonus)"
constant real AGI_DEFENSE_BONUS = 0.1 // "Hero Attributes - Defense Bonus per Agility Point"
constant real DEFENSE_ARMOR = 0.06 // "Combat - Armor Damage Reduction Multiplier"
// An ability derivated from Devotion Aura that nullifies what Blizzard considers "base" armor.
private constant integer NULLIFY_BASE_ARMOR_ABILITY = 'A05K'
private constant integer NULLIFY_BASE_ARMOR_BUFF = 'B01J'
// System cleaning - Ability to detect unit removal from game
// If you already have a Unit Event system (GUI Unit Event by Bribe, Unit Event by Nestharus, or AutoEvents by grim001) you can reuse the same ability.
private constant integer DETECT_REMOVE_ABILITY = 'A06D'
// ----------------------------------------------------------------------------
// ADVANCED SETTINGS (you may leave them default)
// ----------------------------------------------------------------------------
// Set to true if you want the getter/setters to work for hidden units.
// Notes:
// - Works fine except in one case: during "[ANef] Storm, Earth, And Fire" ability cast.
constant boolean ENABLE_UNHIDE = true
// Set to true to enable last ressort action (if nothing else worked to compute armor values).
// Notes:
// - No known case for the moment, it's just a safe fallback measure.
// - Will temporary remove items, and remove all buffs (only aura/passive buffs will be re-activate after, not active ones)
constant boolean ENABLE_BONUS_REMOVAL = true
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// Internal storage for code armor value
private hashtable unitData
endglobals
// ----------------------------------------------------------------------------
// SaveCode.
// Notes: since there is no native to access internal "code armor" value from Blizzard. This function stores a copy of it.
// ----------------------------------------------------------------------------
private function SaveCode takes unit whichUnit, real codeArmor returns nothing
if ( null != whichUnit ) then
// In case there is no Unit Event system, add the remove detect ability manually.
if ( 0 == GetUnitAbilityLevel(whichUnit, DETECT_REMOVE_ABILITY) ) then
call UnitAddAbility(whichUnit, DETECT_REMOVE_ABILITY)
call UnitMakeAbilityPermanent(whichUnit, true, DETECT_REMOVE_ABILITY)
endif
call SaveReal( unitData, GetHandleId(whichUnit), StringHash("code_armor"), codeArmor )
endif
endfunction
// ----------------------------------------------------------------------------
// ArmorToDamageFactor: get damage modifier corresponding to a armor value.
// Notes:
// - "0.02" means damages are reduced by 98%.
// - "1.25" means damages are amplified by 25%.
// - For the moment Blizzard displays -71% as min reduction
// ----------------------------------------------------------------------------
function ArmorToDamageFactor takes real whichArmor returns real
local real factor = 0.0
if (whichArmor >= 0) then
// Damage reduction - factor is inferior or equal to 1
set factor = 1 - ( whichArmor * DEFENSE_ARMOR ) / ( 1 + whichArmor * DEFENSE_ARMOR )
else
// DamageAmplification - factor is superior to 1
set factor = 2 - Pow( 1 - DEFENSE_ARMOR , -1 * whichArmor )
endif
return factor
endfunction
// ----------------------------------------------------------------------------
// DamageFactorToArmor: computes the armor necessary to reach this damage factor.
// Notes:
// - Does not work for 0 walue (= dodge, nullify damage).
// - Does not work for negative values (=heal).
// ----------------------------------------------------------------------------
function DamageFactorToArmor takes real whichDamageFactor returns real
local real armor = 0.0
if (whichDamageFactor <= 0.0) then
// Negative factor does not work - infinite armor or healing
elseif (whichDamageFactor <= 1.0) then
// Damage reduction - armor is positive or null
set armor = ( 1 - whichDamageFactor ) / ( whichDamageFactor * DEFENSE_ARMOR )
else
// Damage amplification - armor is negative
set armor = -1.0 * Logarithm( 1.0 - DEFENSE_ARMOR, 2.0 - whichDamageFactor )
endif
return armor
endfunction
// ----------------------------------------------------------------------------
// GetAgiArmor: get armor bonus from agility. Returns 0 for non-hero units.
// ----------------------------------------------------------------------------
function GetAgiArmor takes unit whichUnit, boolean includeBonuses returns real
local real agiArmor = 0.0
local integer agi = 0
local boolean isHero = false
if ( null != whichUnit ) then
set isHero = IsUnitIdType(GetUnitTypeId(whichUnit), UNIT_TYPE_HERO)
if (isHero) then
// Unit is hero, illusion of hero, ...
set agi = GetHeroAgi(whichUnit, includeBonuses)
set agiArmor = AGI_DEFENSE_BASE + AGI_DEFENSE_BONUS * I2R(agi)
endif
endif
return agiArmor
endfunction
// ----------------------------------------------------------------------------
// GetCodeArmor: get code armor. This is the only armor you can modify directly (with BlzSetUnitArmor primitive).
// ----------------------------------------------------------------------------
function GetCodeArmor takes unit whichUnit returns real
local real codeArmor = 0.0
if ( null != whichUnit ) then
set codeArmor = LoadReal( unitData, GetHandleId(whichUnit), StringHash("code_armor") )
endif
return codeArmor
endfunction
// ----------------------------------------------------------------------------
// GetBaseArmor: get what Blizzard considers "base" armor.
// If no upgrades, equal to the number in World Editor > Object Editor > Unit > "[def] Combat - Defense base".
// Otherwise also includes upgrades count x "[defUp] Defense Upgrade Bonus"
// Notes:
// - Meaningless in 99% of cases. Equal to white armor ONLY for non-hero units whose armor have not been modified by code...)
// - This is the value taken as base by Devotion Aura with "[DataB1] Data - Percent Bonus" set to true.
// ----------------------------------------------------------------------------
function GetBaseArmor takes unit whichUnit returns real
local real totalArmorBefore = 0.0
local real totalArmorAfter = 0.0
local real baseArmor = 0.0
static if ENABLE_BONUS_REMOVAL then
local integer inventorySize = 0
local integer tempInventorySlot = 0
local item array unitItems
endif
local boolean abilityAdded = false
local boolean buffAdded = false
local boolean isDead = false
static if ENABLE_UNHIDE then
local boolean isHidden = false
endif
if ( null != whichUnit ) then
static if ENABLE_UNHIDE then
set isHidden = IsUnitHidden(whichUnit)
if (isHidden) then
call ShowUnit(whichUnit, true)
endif
endif
// Try to compute base armor using the test ability (that nullifies base armor).
set totalArmorBefore = BlzGetUnitArmor(whichUnit)
call UnitAddAbility(whichUnit, NULLIFY_BASE_ARMOR_ABILITY)
set abilityAdded = ( GetUnitAbilityLevel(whichUnit, NULLIFY_BASE_ARMOR_ABILITY) > 0 )
set buffAdded = ( GetUnitAbilityLevel(whichUnit, NULLIFY_BASE_ARMOR_BUFF) > 0 )
if (abilityAdded and buffAdded) then
// Test worked, base armor has been nullified properly.
set totalArmorAfter = BlzGetUnitArmor(whichUnit)
set baseArmor = totalArmorBefore - totalArmorAfter
else
// Test failed
set isDead = ( not UnitAlive(whichUnit) )
if (isDead) then
// Case A: unit is dead. Thus its green armor is 0, and base = total - agi - code
set baseArmor = BlzGetUnitArmor(whichUnit) - GetAgiArmor(whichUnit, false) - GetCodeArmor(whichUnit)
static if ENABLE_BONUS_REMOVAL then
else
// Case Z: last resort is to remove all armor bonuses
// Temporary remove all items
set inventorySize = UnitInventorySizeBJ(whichUnit)
set tempInventorySlot = 0
loop
set tempInventorySlot = tempInventorySlot + 1
exitwhen tempInventorySlot > inventorySize
set unitItems[tempInventorySlot] = UnitItemInSlotBJ(whichUnit, tempInventorySlot)
if ( null != unitItems[tempInventorySlot] ) then
call UnitRemoveItemFromSlot(whichUnit, tempInventorySlot)
endif
endlop
// Remove all buffs (unfortunately there is no way to restore the active buffs)
call UnitRemoveBuffsEx(whichUnit, true, true, true, true, false, true, true) // Remove all buffs but timed life
set armor = BlzGetUnitArmor(whichUnit) - GetAgiArmor(whichUnit, false) - GetCodeArmor(whichUnit)
// Restore all items
set tempInventorySlot = 0
loop
set tempInventorySlot = tempInventorySlot + 1
exitwhen tempInventorySlot > inventorySize
if ( null != unitItems[tempInventorySlot] ) then
call UnitDropItemSlotBJ( whichUnit, unitItems[tempInventorySlot], tempInventorySlot )
endif
endlop
endif
endif
endif
if (abilityAdded) then
call UnitRemoveAbility(whichUnit, NULLIFY_BASE_ARMOR_ABILITY)
endif
if (buffAdded) then
call UnitRemoveBuffBJ(NULLIFY_BASE_ARMOR_BUFF, whichUnit)
endif
static if ENABLE_UNHIDE then
if (isHidden) then
call ShowUnit(whichUnit, false)
endif
endif
endif
return baseArmor
endfunction
// ----------------------------------------------------------------------------
// GetWhiteArmor: get armor before bonus (= number displayed in white in unit status).
// ----------------------------------------------------------------------------
function GetWhiteArmor takes unit whichUnit returns real
local real whiteArmor = 0.0
local integer baseAgi = 0
if ( null != whichUnit ) then
set whiteArmor = GetBaseArmor(whichUnit) + GetAgiArmor(whichUnit, false) + GetCodeArmor(whichUnit)
endif
return whiteArmor
endfunction
// ----------------------------------------------------------------------------
// GetTotal: get total armor. Same as BlzGetUnitArmor.
// ----------------------------------------------------------------------------
function GetTotalArmor takes unit whichUnit returns real
local real armor = 0.0
if ( null != whichUnit ) then
set armor = BlzGetUnitArmor(whichUnit)
endif
return armor
endfunction
// ----------------------------------------------------------------------------
// GetGreenArmor: get current armor bonus (= number displayed in green in unit status.
// ----------------------------------------------------------------------------
function GetGreenArmor takes unit whichUnit returns real
return ( GetTotalArmor(whichUnit) - GetWhiteArmor(whichUnit) )
endfunction
// ----------------------------------------------------------------------------
// GetDamageFactor: get current damage factor taking into account total armor. Does not consider attack type, damage type and armor type!
// Notes:
// - If factor is <1, then damage reduction
// - If factor >1, then damage amplification
// - If factor ==1, damages unchanged, null armor.
// - If factor ==0, then error.
// ----------------------------------------------------------------------------
function GetDamageFactor takes unit whichUnit returns real
local real damageFactor = 0.0
local real totalArmor = 0.0
if ( null != whichUnit ) then
set totalArmor = GetTotalArmor(whichUnit)
set damageFactor = DamageFactorToArmor(totalArmor)
endif
return damageFactor
endfunction
// ----------------------------------------------------------------------------
// ModifyArmor: apply difference to unit code armor (and thus to white armor). Difference can be positive or negative.
// Also modifies white armor and total armor of the same difference.
// ----------------------------------------------------------------------------
function ModifyArmor takes unit whichUnit, real armorDiff returns nothing
local real currentTotalArmor = 0.0
if ( null != whichUnit ) then
set currentTotalArmor = BlzGetUnitArmor(whichUnit)
call BlzSetUnitArmor(whichUnit, currentTotalArmor + armorDiff )
endif
endfunction
// ----------------------------------------------------------------------------
// SetCode: set unit code armor to desired value.
// ----------------------------------------------------------------------------
function SetCodeArmor takes unit whichUnit, real desiredCodeArmor returns nothing
local real currentCodeArmor = 0.0
local real armorDiff = 0.0
if ( null != whichUnit ) then
set currentCodeArmor = GetCodeArmor(whichUnit)
set armorDiff = desiredCodeArmor - currentCodeArmor
call ModifyArmor(whichUnit, armorDiff)
endif
endfunction
// ----------------------------------------------------------------------------
// AdjustArmorToWhite: set unit base armor such as white armor reaches the desired amount.
// ----------------------------------------------------------------------------
function AdjustArmorToWhite takes unit whichUnit, real desiredWhiteArmor returns nothing
local real currentWhiteArmor = 0.0
local real armorDiff = 0.0
if ( null != whichUnit ) then
set currentWhiteArmor = GetWhiteArmor(whichUnit)
set armorDiff = desiredWhiteArmor - currentWhiteArmor
call ModifyArmor(whichUnit, armorDiff)
endif
endfunction
// ----------------------------------------------------------------------------
// AdjustArmorToWhitePercent: set unit base armor such as white armor changes of the desirated percent.
// Ex: 1.50 will increase white armor of 50%
// ----------------------------------------------------------------------------
function AdjustArmorToWhitePercent takes unit whichUnit, real desiredWhiteArmorPercent returns nothing
local real currentWhiteArmor = 0.0
local real armorDiff = 0.0
if ( null != whichUnit ) then
set currentWhiteArmor = GetWhiteArmor(whichUnit)
set armorDiff = currentWhiteArmor * (desiredWhiteArmorPercent - 1.0)
call ModifyArmor(whichUnit, armorDiff)
endif
endfunction
// ----------------------------------------------------------------------------
// AdjustArmorToTotal: set unit base armor such as total reaches the desired amount.
// Same as BlzSetUnitArmor.
// ----------------------------------------------------------------------------
function AdjustArmorToTotal takes unit whichUnit, real desiredTotalArmor returns nothing
if ( null != whichUnit ) then
call BlzSetUnitArmor(whichUnit, desiredTotalArmor)
endif
endfunction
// ----------------------------------------------------------------------------
// AdjustArmorToTotalPercent: set unit base armor such as total armor changes of the desirated percent.
// Ex: 1.50 will increase total armor of 50%
// ----------------------------------------------------------------------------
function AdjustArmorToTotalPercent takes unit whichUnit, real desiredTotalArmorPercent returns nothing
local real currentTotalArmor = 0.0
if ( null != whichUnit ) then
set currentTotalArmor = BlzGetUnitArmor(whichUnit)
call BlzSetUnitArmor( whichUnit, currentTotalArmor * desiredTotalArmorPercent )
endif
endfunction
// ----------------------------------------------------------------------------
// onBlzSetUnitArmor: called just before everytime code sets unit armor with "BlzSetUnitArmor" native.
// Notes: since there is no native to access internal "code armor" value from Blizzard. This function stores a copy of it.
// ----------------------------------------------------------------------------
private function onBlzSetUnitArmor takes unit whichUnit, real armorAmount returns nothing
local real previousCodeArmor = 0.0
local real nextCodeArmor = 0.0
local real previousArmorAmount = 0.0
local real armorDiff = 0.0
if ( null != whichUnit ) then
// Detect armor difference
set previousArmorAmount = BlzGetUnitArmor(whichUnit)
set armorDiff = armorAmount - previousArmorAmount
// Get previous code armor (0 if not existing), update it, and save-it back
set previousCodeArmor = GetCodeArmor(whichUnit)
set nextCodeArmor = previousCodeArmor + armorDiff
call SaveCode(whichUnit, nextCodeArmor)
endif
endfunction
hook BlzSetUnitArmor onBlzSetUnitArmor
// ----------------------------------------------------------------------------
// onBlzSetUnitRealField: called just before everytime code sets unit armor with "BlzSetUnitRealField" native for UNIT_RF_DEFENSE field.
// Notes: intenally just calls onBlzSetUnitArmor function.
// ----------------------------------------------------------------------------
private function onBlzSetUnitRealField takes unit whichUnit, unitrealfield whichField, real value returns nothing
if ( UNIT_RF_DEFENSE == whichField ) then
call onBlzSetUnitArmor(whichUnit, value)
endif
endfunction
hook BlzSetUnitRealField onBlzSetUnitRealField
// ----------------------------------------------------------------------------
// onUnitRemoved: called just before a unit is removed from the game. Cleans internal storage.
// ----------------------------------------------------------------------------
private function onUnitRemoved takes nothing returns nothing
local unit whichUnit = GetTriggerUnit()
local boolean unitBeingRemoved
// Because unit has DETECT_REMOVE_ABILITY, it will fire a "undefend" event just before being removed from game.
if ( OrderId2StringBJ(GetIssuedOrderIdBJ()) == "undefend" ) then
set unitBeingRemoved = ( 0 == GetUnitAbilityLevel(whichUnit, DETECT_REMOVE_ABILITY) )
if (unitBeingRemoved) then
call FlushChildHashtable( unitData, GetHandleId(whichUnit) )
endif
endif
endfunction
// ----------------------------------------------------------------------------
// onInit: system initializer
// ----------------------------------------------------------------------------
private module M
private static method onInit takes nothing returns nothing
local trigger cleanTrigger = CreateTrigger() // trigger to detect unit removal (and clean hashtable)
call TriggerRegisterAnyUnitEventBJ( cleanTrigger, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerAddAction( cleanTrigger, function onUnitRemoved )
set unitData = InitHashtable() // Init hashtable (avoid adding dependency to an indexer)
endmethod
endmodule
private struct S extends array
implement M
endstruct
endlibrary
library TimeUtils
globals
private constant string FIELDS_DELIMITER = ":"
endglobals
function FormatTime takes real seconds returns string
// Compute seconds, minutes and hours
local real s = ModuloReal( seconds, 60.0 )
local integer m = R2I(ModuloReal( seconds, 3600 ) / 60.0)
local integer h = R2I(seconds / 3600.0)
local string ss
local string ms
local string hs
local string formatedTime
// Format seconds as real with 3 decimals string
set ss = R2SW(s, 2, 3)
// Format minutes as a 2-character number string (3 => 03)
set ms = I2S(m)
if ( 1 == StringLength(ms) ) then
set ms = "0" + ms
endif
// Format hours as a 2-character number string (3 => 03)
set hs = I2S(h)
if ( 1 == StringLength(hs) ) then
set hs = "0" + hs
endif
// Contatenate to obtenate a time under the form: HH:MM:SS.sss
set formatedTime = hs + FIELDS_DELIMITER + ms + FIELDS_DELIMITER + ss
return formatedTime
endfunction
endlibrary
//===========================================================================
function UnitEventDestroyGroup takes integer i returns nothing
if udg_CargoTransportGroup[i] != null then
call DestroyGroup(udg_CargoTransportGroup[i])
set udg_CargoTransportGroup[i] = null
endif
endfunction
function UnitEventCheckAfter takes nothing returns nothing
local integer i = 0
loop
set i = udg_CheckDeathList[i]
exitwhen i == 0
if udg_IsUnitNew[i] then
//The unit was just created.
set udg_IsUnitNew[i] = false
elseif udg_IsUnitTransforming[i] then
//Added 21 July 2017 to fix the iDssue re-adding this ability in the same instant
set udg_UDex = i
set udg_UnitTypeEvent = 0.00
set udg_UnitTypeEvent = 1.00
set udg_UnitTypeOf[i] = GetUnitTypeId(udg_UDexUnits[i]) //Set this afterward to give the user extra reference
set udg_IsUnitTransforming[i] = false
call UnitAddAbility(udg_UDexUnits[i], udg_DetectTransformAbility)
elseif udg_IsUnitAlive[i] then
//The unit has started reincarnating.
set udg_IsUnitReincarnating[i] = true
set udg_IsUnitAlive[i] = false
set udg_UDex = i
set udg_DeathEvent = 0.50
set udg_DeathEvent = 0.00
endif
set udg_CheckDeathInList[i] = false
endloop
//Empty the list
set udg_CheckDeathList[0] = 0
endfunction
function UnitEventCheckAfterProxy takes integer i returns nothing
if udg_CheckDeathList[0] == 0 then
call TimerStart(udg_CheckDeathTimer, 0.00, false, function UnitEventCheckAfter)
endif
if not udg_CheckDeathInList[i] then
set udg_CheckDeathList[i] = udg_CheckDeathList[0]
set udg_CheckDeathList[0] = i
set udg_CheckDeathInList[i] = true
endif
endfunction
function UnitEventOnUnload takes nothing returns nothing
local integer i = udg_UDex
call GroupRemoveUnit(udg_CargoTransportGroup[GetUnitUserData(udg_CargoTransportUnit[i])], udg_UDexUnits[i])
set udg_IsUnitBeingUnloaded[i] = true
set udg_CargoEvent = 0.00
set udg_CargoEvent = 2.00
set udg_CargoEvent = 0.00
set udg_IsUnitBeingUnloaded[i] = false
if not IsUnitLoaded(udg_UDexUnits[i]) or IsUnitType(udg_CargoTransportUnit[i], UNIT_TYPE_DEAD) or GetUnitTypeId(udg_CargoTransportUnit[i]) == 0 then
set udg_CargoTransportUnit[i] = null
endif
endfunction
function UnitEventOnDeath takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_UDex != 0 then
set udg_KillerOfUnit[udg_UDex] = GetKillingUnit() //Added 29 May 2017 for GIMLI_2
set udg_IsUnitAlive[udg_UDex] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
set udg_KillerOfUnit[udg_UDex] = null
if udg_CargoTransportUnit[udg_UDex] != null then
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnOrder takes nothing returns boolean
local integer pdex = udg_UDex
local unit u = GetFilterUnit()
local integer i = GetUnitUserData(u)
if i > 0 then
set udg_UDex = i
if GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
if not udg_IsUnitRemoved[i] then
set udg_IsUnitRemoved[i] = true
set udg_IsUnitAlive[i] = false
set udg_SummonerOfUnit[i] = null
//For backwards-compatibility:
set udg_DeathEvent = 0.00
set udg_DeathEvent = 3.00
set udg_DeathEvent = 0.00
//Fire deindex event for UDex:
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 2.00
set udg_UnitIndexEvent = 0.00
set udg_UDexNext[udg_UDexPrev[i]] = udg_UDexNext[i]
set udg_UDexPrev[udg_UDexNext[i]] = udg_UDexPrev[i]
// Recycle the index for later use
set udg_UDexUnits[i] = null
set udg_UDexPrev[i] = udg_UDexLastRecycled
set udg_UDexLastRecycled = i
call UnitEventDestroyGroup(i)
endif
elseif not udg_IsUnitAlive[i] then
if not IsUnitType(u, UNIT_TYPE_DEAD) then
set udg_IsUnitAlive[i] = true
set udg_DeathEvent = 0.00
set udg_DeathEvent = 2.00
set udg_DeathEvent = 0.00
set udg_IsUnitReincarnating[i] = false
endif
elseif IsUnitType(u, UNIT_TYPE_DEAD) then
if udg_IsUnitNew[i] then
//This unit was created as a corpse.
set udg_IsUnitAlive[i] = false
set udg_DeathEvent = 0.00
set udg_DeathEvent = 1.00
set udg_DeathEvent = 0.00
elseif udg_CargoTransportUnit[i] == null or not IsUnitType(u, UNIT_TYPE_HERO) then
//The unit may have just started reincarnating.
call UnitEventCheckAfterProxy(i)
endif
elseif GetUnitAbilityLevel(u, udg_DetectTransformAbility) == 0 and not udg_IsUnitTransforming[i] then
set udg_IsUnitTransforming[i] = true
call UnitEventCheckAfterProxy(i) //This block has been updated on 21 July 2017
endif
if udg_CargoTransportUnit[i] != null and not udg_IsUnitBeingUnloaded[i] and not IsUnitLoaded(u) or IsUnitType(u, UNIT_TYPE_DEAD) then
call UnitEventOnUnload()
endif
set udg_UDex = pdex
endif
set u = null
return false
endfunction
function UnitEventOnSummon takes nothing returns boolean
local integer pdex = udg_UDex
set udg_UDex = GetUnitUserData(GetTriggerUnit())
if udg_IsUnitNew[udg_UDex] then
set udg_SummonerOfUnit[udg_UDex] = GetSummoningUnit()
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 0.50
set udg_UnitIndexEvent = 0.00
endif
set udg_UDex = pdex
return false
endfunction
function UnitEventOnLoad takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = GetUnitUserData(GetTriggerUnit())
local integer index
if i != 0 then
set udg_UDex = i
if udg_CargoTransportUnit[i] != null then
call UnitEventOnUnload()
endif
//Loaded corpses do not issue an order when unloaded, therefore must
//use the enter-region event method taken from Jesus4Lyf's Transport.
if not udg_IsUnitAlive[i] then
call SetUnitX(udg_UDexUnits[i], udg_WorldMaxX)
call SetUnitY(udg_UDexUnits[i], udg_WorldMaxY)
endif
set udg_CargoTransportUnit[i] = GetTransportUnit()
set index = GetUnitUserData(udg_CargoTransportUnit[i])
if udg_CargoTransportGroup[index] == null then
set udg_CargoTransportGroup[index] = CreateGroup()
endif
call GroupAddUnit(udg_CargoTransportGroup[index], udg_UDexUnits[i])
set udg_CargoEvent = 0.00
set udg_CargoEvent = 1.00
set udg_CargoEvent = 0.00
set udg_UDex = pdex
endif
return false
endfunction
function UnitEventEnter takes nothing returns boolean
local integer pdex = udg_UDex
local integer i = udg_UDexLastRecycled
local unit u = GetFilterUnit()
if udg_UnitIndexerEnabled and GetUnitAbilityLevel(u, udg_DetectRemoveAbility) == 0 then
//Generate a unique integer index for this unit
if i == 0 then
set i = udg_UDexMax + 1
set udg_UDexMax = i
else
set udg_UDexLastRecycled = udg_UDexPrev[i]
endif
//Link index to unit, unit to index
set udg_UDexUnits[i] = u
call SetUnitUserData(u, i)
//For backwards-compatibility, add the unit to a linked list
set udg_UDexNext[i] = udg_UDexNext[0]
set udg_UDexPrev[udg_UDexNext[0]] = i
set udg_UDexNext[0] = i
set udg_UDexPrev[i] = 0
set udg_CheckDeathInList[i] = false
call UnitAddAbility(u, udg_DetectRemoveAbility)
call UnitMakeAbilityPermanent(u, true, udg_DetectRemoveAbility)
call UnitAddAbility(u, udg_DetectTransformAbility)
set udg_UnitTypeOf[i] = GetUnitTypeId(u)
set udg_IsUnitNew[i] = true
set udg_IsUnitAlive[i] = true
set udg_IsUnitRemoved[i] = false
set udg_IsUnitReincarnating[i] = false
set udg_IsUnitPreplaced[i] = udg_IsUnitPreplaced[0] //Added 29 May 2017 for Spellbound
call UnitEventCheckAfterProxy(i)
//Fire index event for UDex
set udg_UDex = i
set udg_UnitIndexEvent = 0.00
set udg_UnitIndexEvent = 1.00
set udg_UnitIndexEvent = 0.00
else
set udg_UDex = GetUnitUserData(u)
if udg_CargoTransportUnit[udg_UDex] != null and not IsUnitLoaded(u) then
//The unit was dead, but has re-entered the map.
call UnitEventOnUnload()
endif
endif
set udg_UDex = pdex
set u = null
return false
endfunction
//===========================================================================
function UnitEventInit takes nothing returns nothing
local integer i = bj_MAX_PLAYER_SLOTS //update to make it work with 1.29
local player p
local trigger t = CreateTrigger()
local trigger load = CreateTrigger()
local trigger death = CreateTrigger()
local trigger summon = CreateTrigger()
local rect r = GetWorldBounds()
local region re = CreateRegion()
local boolexpr enterB = Filter(function UnitEventEnter)
local boolexpr orderB = Filter(function UnitEventOnOrder)
set udg_WorldMaxX = GetRectMaxX(r)
set udg_WorldMaxY = GetRectMaxY(r)
call RegionAddRect(re, r)
call RemoveRect(r)
call UnitEventDestroyGroup(0)
call UnitEventDestroyGroup(1)
set udg_CheckDeathList[0] = 0
set udg_UnitIndexerEnabled = true
call TriggerRegisterEnterRegion(CreateTrigger(), re, enterB)
call TriggerAddCondition(load, Filter(function UnitEventOnLoad))
call TriggerAddCondition(death, Filter(function UnitEventOnDeath))
call TriggerAddCondition(summon, Filter(function UnitEventOnSummon))
loop
set i = i - 1
set p = Player(i)
call SetPlayerAbilityAvailable(p, udg_DetectRemoveAbility, false)
call SetPlayerAbilityAvailable(p, udg_DetectTransformAbility, false)
call TriggerRegisterPlayerUnitEvent(summon, p, EVENT_PLAYER_UNIT_SUMMON, null)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_ISSUED_ORDER, orderB)
call TriggerRegisterPlayerUnitEvent(death, p, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(load, p, EVENT_PLAYER_UNIT_LOADED, null)
call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, enterB)
exitwhen i == 0
endloop
set summon = null
set death = null
set load = null
set re = null
set enterB = null
set orderB = null
set p = null
set r = null
set t = null
endfunction
function InitTrig_Unit_Event takes nothing returns nothing
endfunction
library UnitSelection
globals
private trigger playerSelectUnitTrigger
private trigger playerDeselectUnitTrigger
private trigger unitInactionTrigger
endglobals
function onPlayerSelectUnit takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer pIndex = GetConvertedPlayerId(p)
local unit u = GetTriggerUnit()
local boolean b = IsUnitInGroup(u, udg_PlayerSelections[pIndex])
if (not b) then
call GroupAddUnitSimple(u, udg_PlayerSelections[pIndex])
// Fire a unit selection event
set udg_UnitSelectionPlayerId = pIndex
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionEvent = 1.00
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionPlayerId = 0
endif
set u = null
set p = null
return false
endfunction
function onPlayerDeselectUnit takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer pIndex = GetConvertedPlayerId(p)
local unit u = GetTriggerUnit()
local boolean b = IsUnitInGroup(u, udg_PlayerSelections[pIndex])
if (b) then
call GroupRemoveUnitSimple(u, udg_PlayerSelections[pIndex])
// Fire a unit deselection event
set udg_UnitSelectionPlayerId = pIndex
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionEvent = 2.00
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionPlayerId = 0
endif
set u = null
set p = null
return false
endfunction
function onUnitInaction takes nothing returns boolean
local integer pIndex
local integer pCount = GetPlayers()
local unit u = udg_UDexUnits[udg_UDex]
local boolean b
set pIndex = 1
loop
set b = IsUnitInGroup(u, udg_PlayerSelections[pIndex])
if (b) then
call GroupRemoveUnitSimple(u, udg_PlayerSelections[pIndex])
// Fire a unit deselection event
set udg_UnitSelectionPlayerId = pIndex
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionEvent = 2.00
set udg_UnitSelectionEvent = 0.00
set udg_UnitSelectionPlayerId = 0
endif
set pIndex = pIndex + 1
exitwhen pIndex > pCount
endloop
set u = null
return false
endfunction
// ----------------------------------------------------------------------------
// onInit: system initializer
// ----------------------------------------------------------------------------
private module M
private static method onInit takes nothing returns nothing
local integer index
local integer playerCount = GetPlayers()
set playerSelectUnitTrigger = CreateTrigger()
set playerDeselectUnitTrigger = CreateTrigger()
set unitInactionTrigger = CreateTrigger()
set index = 1
loop
set udg_PlayerSelections[index] = CreateGroup()
call TriggerRegisterPlayerSelectionEventBJ( playerSelectUnitTrigger, ConvertedPlayer(index), true )
call TriggerRegisterPlayerSelectionEventBJ( playerDeselectUnitTrigger, ConvertedPlayer(index), false )
set index = index + 1
exitwhen index > playerCount
endloop
call TriggerRegisterVariableEvent( unitInactionTrigger, "udg_UnitInActionEvent", EQUAL, 2.00 )
call TriggerAddCondition(playerSelectUnitTrigger, Condition(function onPlayerSelectUnit))
call TriggerAddCondition(playerDeselectUnitTrigger, Condition(function onPlayerDeselectUnit))
call TriggerAddCondition(unitInactionTrigger, Condition(function onUnitInaction))
endmethod
endmodule
private struct S extends array
implement M
endstruct
endlibrary
//===========================================================================
//
// Damage Engine 5.7.1.1 - update requires replacing the JASS script.
//
/*
Three GUI Damage systems for the community of The Hive,
Seven vJass Damage systems for the JASS-heads on their pedestals high,
Nine competing Damage systems, doomed to die,
One for Bribe on his dark throne
In the Land of the Hive where the Workshop lies.
One Damage Engine to rule them all, One Damage Engine to find them,
One Damage Engine to bring them all and in cross-compatibility unite them.
*/
//! novjass
JASS API (work in progress - I have a lot of documentation to go through):
struct Damage extends array
readonly static unit source //stores udg_DamageEventSource
readonly static unit target //stores udg_DamageEventTarget
static real amount //stores udg_DamageEventAmount
readonly unit sourceUnit //stores udg_DamageEventSource by index
readonly unit targetUnit //stores udg_DamageEventTarget by index
real damage //stores udg_DamageEventAmount by index
readonly real prevAmt //stores udg_DamageEventPrevAmt by index
attacktype attackType //stores udg_DamageEventAttackT by index
damagetype damageType //stores udg_DamageEventDamageT by index
weapontype weaponType //stores udg_DamageEventWeaponT by index
integer userType //stores udg_DamageEventType by index
readonly integer eFilter //replaces the previous eventFilter variable
readonly boolean isAttack //stores udg_IsDamageAttack by index
readonly boolean isCode //stores udg_IsDamageCode by index
readonly boolean isMelee //stores udg_IsDamageMelee by index
readonly boolean isRanged //stores udg_IsDamageRanged by index
readonly boolean isSpell //stores udg_IsDamageSpell by index
real armorPierced //stores udg_DamageEventArmorPierced by index
integer armorType //stores udg_DamageEventArmorT by index
integer defenseType //stores udg_DamageEventDefenseT by index
static boolean operator enabled
- Set to false to disable the damage event triggers/false to reverse that
static method apply takes unit src, unit tgt, real amt, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt returns Damage
- Same arguments as "UnitDamageTarget" but has the benefit of being performance-friendly during recursive events.
- Will automatically cause the damage to be registered as Code damage.
static method applySpell takes unit src, unit tgt, real amt, damagetype dt returns Damage
- A simplified version of the above function that autofills in the booleans, attack type and weapon type.
static method applyAttack takes unit src, unit tgt, real amt, boolean ranged, attacktype at, weapontype wt returns Damage
- A different variation of the above which autofills the "attack" boolean and sets the damagetype to DAMAGE_TYPE_NORMAL.
struct DamageTrigger extends array
method operator filter= takes integer filter returns nothing
// Apply primary filters such as DamageEngine_FILTER_MELEE/RANGED/SPELL which are based off of limitop handles to enable easier access for GUI folks
// Full filter list:
- global integer DamageEngine_FILTER_ATTACK
- global integer DamageEngine_FILTER_MELEE
- global integer DamageEngine_FILTER_OTHER
- global integer DamageEngine_FILTER_RANGED
- global integer DamageEngine_FILTER_SPELL
- global integer DamageEngine_FILTER_CODE
boolean configured //set to True after configuring any filters listed below.
method configure takes nothing returns nothing
// Apply custom filters after setting any desired udg_DamageFilter variables (for GUI).
// Alternatively, vJass users can set these instead. Just be mindful to set the variable
// "configured" to true after settings these.
unit source
unit target
integer sourceType
integer targetType
integer sourceBuff
integer targetBuff
real damageMin
integer attackType
integer damageType
integer userType
//The string in the aruments below requires the following API:
// "" for standard damage event
// "Modifier(or Mod if you prefer)/After/Lethal/AOE" for the others
static method getIndex takes trigger t, string eventName, real value returns integer
static method registerTrigger takes trigger whichTrig, string var, real weight returns nothing
static method unregister takes trigger t, string eventName, real value, boolean reset returns boolean
static method operator [] takes code c returns trigger
// Converts a code argument to a trigger, while checking if the same code had already been registered before.
//The accepted strings here use the same criteria as DamageTrigger.getIndex/registerTrigger/unregister
function TriggerRegisterDamageEngineEx takes trigger whichTrig, string eventName, real value, integer f returns nothing
function TriggerRegisterDamageEngine takes trigger whichTrig, string eventName, real value returns nothing
function RegisterDamageEngineEx takes code c, string eventName, real value, integer f returns nothing
function RegisterDamageEngine takes code c, string eventName, real value returns nothing
//! endnovjass
//===========================================================================
library DamageEngine
globals
private constant boolean USE_GUI = true //If you don't use any of the GUI events, set to false to slightly improve performance
private constant boolean USE_SCALING = USE_GUI //If you don't need or want to use DamageScalingUser/WC3 then set this to false
private constant boolean USE_EXTRA = true //If you don't use DamageEventLevel or AOEDamageEvent, set this to false
private constant boolean USE_ARMOR_MOD = true //If you do not modify nor detect armor/defense, set this to false
private constant boolean USE_MELEE_RANGE= true //If you do not detect melee nor ranged damage, set this to false
private constant boolean USE_LETHAL = true //If you do not use LethalDamageEvent nor negative damage (explosive) types, set this to false
private constant integer LIMBO = 16 //When manually-enabled recursion is enabled via DamageEngine_recurion, the engine will never go deeper than LIMBO.
public constant integer TYPE_CODE = 1 //Must be the same as udg_DamageTypeCode, or 0 if you prefer to disable the automatic flag.
public constant integer TYPE_PURE = 2 //Must be the same as udg_DamageTypePure
private constant real DEATH_VAL = 0.405 //In case Blizz ever changes this, it'll be a quick fix here.
private timer alarm = CreateTimer()
private boolean alarmSet = false
//Values to track the original pre-spirit Link/defensive damage values
private Damage lastInstance = 0
private boolean canKick = true
private boolean totem = false
private boolean array attacksImmune
private boolean array damagesImmune
//Made global in order to use enable/disable behavior.
private trigger t1 = CreateTrigger()
private trigger t2 = CreateTrigger()
private trigger t3 = CreateTrigger() //Catches, stores recursive events
//These variables coincide with Blizzard's "limitop" type definitions so as to enable users (GUI in particular) with some nice performance perks.
public constant integer FILTER_ATTACK = 0 //LESS_THAN
public constant integer FILTER_MELEE = 1 //LESS_THAN_OR_EQUAL
public constant integer FILTER_OTHER = 2 //EQUAL
public constant integer FILTER_RANGED = 3 //GREATER_THAN_OR_EQUAL
public constant integer FILTER_SPELL = 4 //GREATER_THAN
public constant integer FILTER_CODE = 5 //NOT_EQUAL
public constant integer FILTER_MAX = 6
private integer eventFilter = FILTER_OTHER
public boolean inception = false //When true, it allows your trigger to potentially go recursive up to LIMBO. However it must be set per-trigger throughout the game and not only once per trigger during map initialization.
private boolean dreaming = false
private integer sleepLevel = 0
private group proclusGlobal = CreateGroup() //track sources of recursion
private group fischerMorrow = CreateGroup() //track targets of recursion
private boolean kicking = false
private boolean eventsRun = false
private keyword run
private keyword trigFrozen
private keyword levelsDeep
private keyword inceptionTrig
private boolean hasLethal = false
endglobals
native UnitAlive takes unit u returns boolean
//GUI Vars:
/*
Retained from 3.8 and prior:
----------------------------
unit udg_DamageEventSource
unit udg_DamageEventTarget
unit udg_EnhancedDamageTarget
group udg_DamageEventAOEGroup
integer udg_DamageEventAOE
integer udg_DamageEventLevel
real udg_DamageModifierEvent
real udg_DamageEvent
real udg_AfterDamageEvent
real udg_DamageEventAmount
real udg_DamageEventPrevAmt
real udg_AOEDamageEvent
boolean udg_DamageEventOverride
boolean udg_NextDamageType
boolean udg_DamageEventType
boolean udg_IsDamageSpell
//Added in 5.0:
boolean udg_IsDamageMelee
boolean udg_IsDamageRanged
unit udg_AOEDamageSource
real udg_LethalDamageEvent
real udg_LethalDamageHP
real udg_DamageScalingWC3
integer udg_DamageEventAttackT
integer udg_DamageEventDamageT
integer udg_DamageEventWeaponT
//Added in 5.1:
boolean udg_IsDamageCode
//Added in 5.2:
integer udg_DamageEventArmorT
integer udg_DamageEventDefenseT
//Addded in 5.3:
real DamageEventArmorPierced
real udg_DamageScalingUser
//Added in 5.4.2 to allow GUI users to re-issue the exact same attack and damage type at the attacker.
attacktype array udg_CONVERTED_ATTACK_TYPE
damagetype array udg_CONVERTED_DAMAGE_TYPE
//Added after Reforged introduced the new native BlzGetDamageIsAttack
boolean udg_IsDamageAttack
//Added in 5.6 to give GUI users control over the "IsDamageAttack", "IsDamageRanged" and "DamageEventWeaponT" field
boolean udg_NextDamageIsAttack //The first boolean value in the UnitDamageTarget native
boolean udg_NextDamageIsMelee //Flag the damage classification as melee
boolean udg_NextDamageIsRanged //The second boolean value in the UnitDamageTarget native
integer udg_NextDamageWeaponT //Allows control over damage sound effect
//Added in 5.7 to enable efficient, built-in filtering (see the below "checkConfiguration" method - I recommend commenting-out anything you don't need in your map)
integer udg_DamageFilterAttackT
integer udg_DamageFilterDamageT //filter for a specific attack/damage type
unit udg_DamageFilterSource
unit udg_DamageFilterTarget //filter for a specific source/target
integer udg_DamageFilterSourceT
integer udg_DamageFilterTargetT //unit type of source/target
integer udg_DamageFilterType //which DamageEventType was used
integer udg_DamageFilterSourceB
integer udg_DamageFilterTargetB //if source/target has a buff
real udg_DamageFilterMinAmount //only allow a minimum damage threshold
*/
struct DamageTrigger extends array
//Map-makers should comment-out any booleans they will never need to check for.
method checkConfiguration takes nothing returns boolean
if this.userType != 0 and udg_DamageEventType != this.userType then
elseif this.source != null and this.source != udg_DamageEventSource then
elseif this.target != null and this.target != udg_DamageEventTarget then
elseif this.attackType >= 0 and this.attackType != udg_DamageEventAttackT then
elseif this.damageType >= 0 and this.damageType != udg_DamageEventDamageT then
elseif this.sourceType != 0 and GetUnitTypeId(udg_DamageEventSource) != this.sourceType then
elseif this.targetType != 0 and GetUnitTypeId(udg_DamageEventTarget) != this.targetType then
elseif this.sourceBuff != 0 and GetUnitAbilityLevel(udg_DamageEventSource, this.sourceBuff) == 0 then
elseif this.targetBuff != 0 and GetUnitAbilityLevel(udg_DamageEventTarget, this.targetBuff) == 0 then
elseif udg_DamageEventAmount > this.damageMin then
return true
endif
return false
endmethod
//The below variables are constant
readonly static thistype MOD = 1
readonly static thistype SHIELD = 4
readonly static thistype DAMAGE = 5
readonly static thistype ZERO = 6
readonly static thistype AFTER = 7
readonly static thistype LETHAL = 8
readonly static thistype AOE = 9
private static integer count = 9
static thistype lastRegistered = 0
private static thistype array trigIndexStack
static thistype eventIndex = 0
static boolean array filters
readonly string eventStr
readonly real weight
boolean configured
boolean usingGUI
//The below variables are private
private thistype next
private trigger rootTrig
boolean trigFrozen //Whether the trigger is currently disabled due to recursion
integer levelsDeep //How deep the user recursion currently is.
boolean inceptionTrig //Added in 5.4.2 to simplify the inception variable for very complex DamageEvent trigger.
unit source
unit target
integer sourceType
integer targetType
integer sourceBuff
integer targetBuff
real damageMin
integer attackType
integer damageType
integer userType
method configure takes nothing returns nothing
set this.attackType = udg_DamageFilterAttackT
set this.damageType = udg_DamageFilterDamageT
set this.source = udg_DamageFilterSource
set this.target = udg_DamageFilterTarget
set this.sourceType = udg_DamageFilterSourceT
set this.targetType = udg_DamageFilterTargetT
set this.sourceBuff = udg_DamageFilterSourceB
set this.targetBuff = udg_DamageFilterTargetB
set this.userType = udg_DamageFilterType
set this.damageMin = udg_DamageFilterMinAmount
set udg_DamageFilterAttackT =-1
set udg_DamageFilterDamageT =-1
set udg_DamageFilterSource = null
set udg_DamageFilterTarget = null
set udg_DamageFilterSourceT = 0
set udg_DamageFilterTargetT = 0
set udg_DamageFilterType = 0
set udg_DamageFilterSourceB = 0
set udg_DamageFilterTargetB = 0
set udg_DamageFilterMinAmount=0.00
set this.configured = true
endmethod
static method setGUIFromStruct takes boolean full returns nothing
set udg_DamageEventAmount = Damage.index.damage
set udg_DamageEventAttackT = GetHandleId(Damage.index.attackType)
set udg_DamageEventDamageT = GetHandleId(Damage.index.damageType)
set udg_DamageEventWeaponT = GetHandleId(Damage.index.weaponType)
set udg_DamageEventType = Damage.index.userType
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_DamageEventArmorPierced = Damage.index.armorPierced
set udg_DamageEventArmorT = Damage.index.armorType
set udg_DamageEventDefenseT = Damage.index.defenseType
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if full then
set udg_DamageEventSource = Damage.index.sourceUnit
set udg_DamageEventTarget = Damage.index.targetUnit
set udg_DamageEventPrevAmt = Damage.index.prevAmt
set udg_IsDamageAttack = Damage.index.isAttack
set udg_IsDamageCode = Damage.index.isCode
set udg_IsDamageSpell = Damage.index.isSpell
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_IsDamageMelee = Damage.index.isMelee
set udg_IsDamageRanged = Damage.index.isRanged
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
endmethod
static method setStructFromGUI takes nothing returns nothing
set Damage.index.damage = udg_DamageEventAmount
set Damage.index.attackType = ConvertAttackType(udg_DamageEventAttackT)
set Damage.index.damageType = ConvertDamageType(udg_DamageEventDamageT)
set Damage.index.weaponType = ConvertWeaponType(udg_DamageEventWeaponT)
set Damage.index.userType = udg_DamageEventType
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set Damage.index.armorPierced = udg_DamageEventArmorPierced
set Damage.index.armorType = udg_DamageEventArmorT
set Damage.index.defenseType = udg_DamageEventDefenseT
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endmethod
static method getVerboseStr takes string eventName returns string
if eventName == "Modifier" or eventName == "Mod" then
return "udg_DamageModifierEvent"
endif
return "udg_" + eventName + "DamageEvent"
endmethod
private static method getStrIndex takes string var, real lbs returns thistype
local integer root = R2I(lbs)
if var == "udg_DamageModifierEvent" then
if root >= 4 then
set root= SHIELD //4.00 or higher
else
set root= MOD //Less than 4.00
endif
elseif var == "udg_DamageEvent" then
if root == 2 or root == 0 then
set root= ZERO
else
set root= DAMAGE //Above 0.00 but less than 2.00, generally would just be 1.00
endif
elseif var == "udg_AfterDamageEvent" then
set root = AFTER
elseif var == "udg_LethalDamageEvent" then
set root = LETHAL
elseif var == "udg_AOEDamageEvent" then
set root = AOE
else
set root = 0
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_GDD()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_PDD()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_REG_PLUGIN_05()
endif
return root
endmethod
private method toggleAllFilters takes boolean flag returns nothing
set filters[this + FILTER_ATTACK] = flag
set filters[this + FILTER_MELEE] = flag
set filters[this + FILTER_OTHER] = flag
set filters[this + FILTER_RANGED] = flag
set filters[this + FILTER_SPELL] = flag
set filters[this + FILTER_CODE] = flag
endmethod
method operator filter= takes integer f returns nothing
set this = this*FILTER_MAX
if f == FILTER_OTHER then
call this.toggleAllFilters(true)
else
if f == FILTER_ATTACK then
set filters[this + FILTER_ATTACK] = true
set filters[this + FILTER_MELEE] = true
set filters[this + FILTER_RANGED] = true
else
set filters[this + f] = true
endif
endif
endmethod
static method registerVerbose takes trigger whichTrig, string var, real lbs, boolean GUI, integer filt returns thistype
local thistype index= getStrIndex(var, lbs)
local thistype i = 0
local thistype id = 0
if index == 0 then
return 0
elseif lastRegistered.rootTrig == whichTrig and lastRegistered.usingGUI then
set filters[lastRegistered*FILTER_MAX + filt] = true //allows GUI to register multiple different types of Damage filters to the same trigger
return 0
endif
if not hasLethal and index == LETHAL then
set hasLethal = true
endif
if trigIndexStack[0] == 0 then
set count = count + 1 //List runs from index 10 and up
set id = count
else
set id = trigIndexStack[0]
set trigIndexStack[0] = trigIndexStack[id]
endif
set lastRegistered = id
set id.filter = filt
set id.rootTrig = whichTrig
set id.usingGUI = GUI
set id.weight = lbs
set id.eventStr = var
//Next 2 lines added to fix a bug when using manual vJass configuration,
//discovered and solved by lolreported
set id.attackType = -1
set id.damageType = -1
loop
set i = index.next
exitwhen i == 0 or lbs < i.weight
set index = i
endloop
set index.next = id
set id.next = i
//call BJDebugMsg("Registered " + I2S(id) + " to " + I2S(index) + " and before " + I2S(i))
return lastRegistered
endmethod
static method registerTrigger takes trigger t, string var, real lbs returns thistype
return registerVerbose(t, DamageTrigger.getVerboseStr(var), lbs, false, FILTER_OTHER)
endmethod
private static thistype prev = 0
static method getIndex takes trigger t, string eventName, real lbs returns thistype
local thistype index = getStrIndex(getVerboseStr(eventName), lbs)
loop
set prev = index
set index = index.next
exitwhen index == 0 or index.rootTrig == t
endloop
return index
endmethod
static method unregister takes trigger t, string eventName, real lbs, boolean reset returns boolean
local thistype index = getIndex(t, eventName, lbs)
if index == 0 then
return false
endif
set prev.next = index.next
set trigIndexStack[index] = trigIndexStack[0]
set trigIndexStack[0] = index
if reset then
call index.configure()
set index.configured = false
set index = index*FILTER_MAX
call index.toggleAllFilters(false)
endif
return true
endmethod
method run takes nothing returns nothing
local integer cat = this
local Damage d = Damage.index
static if USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
local boolean structUnset = false
local boolean guiUnset = false
local boolean mod = cat <= DAMAGE
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if dreaming then
return
endif
set dreaming = true
call DisableTrigger(t1)
call DisableTrigger(t2)
call EnableTrigger(t3)
//call BJDebugMsg("Start of event running")
loop
set this = this.next
exitwhen this == 0
exitwhen cat == MOD and (udg_DamageEventOverride or udg_DamageEventType == TYPE_PURE)
exitwhen cat == SHIELD and udg_DamageEventAmount <= 0.00
static if USE_LETHAL then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
exitwhen cat == LETHAL and udg_LethalDamageHP > DEATH_VAL
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set eventIndex = this
if not this.trigFrozen and filters[this*FILTER_MAX + d.eFilter] and IsTriggerEnabled(this.rootTrig) and (not this.configured or this.checkConfiguration()) then
static if USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if mod then
if this.usingGUI then
if guiUnset then
set guiUnset = false
call setGUIFromStruct(false)
endif
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_PDD()
elseif structUnset then
set structUnset = false
call setStructFromGUI()
endif
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_FILTER_PLUGIN_05()
//JASS users who do not use actions can modify the below block to just evaluate.
//It should not make any perceptable difference in terms of performance.
if TriggerEvaluate(this.rootTrig) then
call TriggerExecute(this.rootTrig)
endif
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_05()
static if USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if mod then
if this.usingGUI then
//! runtextmacro optional DAMAGE_EVENT_MOD_PLUGIN_PDD()
if cat != MOD then
set d.damage = udg_DamageEventAmount
else
set structUnset = true
endif
elseif cat != MOD then
set udg_DamageEventAmount = d.damage
else
set guiUnset = true
endif
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
endloop
static if USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if structUnset then
call setStructFromGUI()
endif
if guiUnset then
call setGUIFromStruct(false)
endif
else// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call setGUIFromStruct(false)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
//call BJDebugMsg("End of event running")
call DisableTrigger(t3)
call EnableTrigger(t1)
call EnableTrigger(t2)
set dreaming = false
endmethod
static trigger array autoTriggers
static boolexpr array autoFuncs
static integer autoN = 0
static method operator [] takes code c returns trigger
local integer i = 0
local boolexpr b = Filter(c)
loop
if i == autoN then
set autoTriggers[i] = CreateTrigger()
set autoFuncs[i] = b
call TriggerAddCondition(autoTriggers[i], b)
exitwhen true
endif
set i = i + 1
exitwhen b == autoFuncs[i]
endloop
return autoTriggers[i]
endmethod
endstruct
//! runtextmacro optional DAMAGE_EVENT_USER_STRUCT_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_USER_STRUCT_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_USER_STRUCT_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_USER_STRUCT_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_USER_STRUCT_PLUGIN_05()
struct Damage extends array
readonly unit sourceUnit //stores udg_DamageEventSource
readonly unit targetUnit //stores udg_DamageEventTarget
real damage //stores udg_DamageEventAmount
readonly real prevAmt //stores udg_DamageEventPrevAmt
attacktype attackType //stores udg_DamageEventAttackT
damagetype damageType //stores udg_DamageEventDamageT
weapontype weaponType //stores udg_DamageEventWeaponT
integer userType //stores udg_DamageEventType
readonly boolean isAttack //stores udg_IsDamageAttack
readonly boolean isCode //stores udg_IsDamageCode
readonly boolean isSpell //stores udg_IsDamageSpell
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
readonly boolean isMelee //stores udg_IsDamageMelee
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
readonly boolean isRanged //stores udg_IsDamageRanged
readonly integer eFilter //stores the previous eventFilter variable
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
real armorPierced //stores udg_DamageEventArmorPierced
integer armorType //stores udg_DamageEventArmorT
integer defenseType //stores udg_DamageEventDefenseT
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
readonly static Damage index = 0
private static Damage damageStack = 0
private static Damage prepped = 0
private static integer count = 0 //The number of currently-running queued or sequential damage instances
private Damage stackRef
private DamageTrigger recursiveTrig
private integer prevArmorT
private integer prevDefenseT
static method operator source takes nothing returns unit
return udg_DamageEventSource
endmethod
static method operator target takes nothing returns unit
return udg_DamageEventTarget
endmethod
static method operator amount takes nothing returns real
return Damage.index.damage
endmethod
static method operator amount= takes real r returns nothing
set Damage.index.damage = r
endmethod
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
private static method setArmor takes boolean reset returns nothing
local real pierce
local integer at
local integer dt
if reset then
set pierce = udg_DamageEventArmorPierced
set at = Damage.index.prevArmorT
set dt = Damage.index.prevDefenseT
else
set pierce = -udg_DamageEventArmorPierced
set at = udg_DamageEventArmorT
set dt = udg_DamageEventDefenseT
endif
if pierce != 0.00 then
call BlzSetUnitArmor(udg_DamageEventTarget, BlzGetUnitArmor(udg_DamageEventTarget) + pierce)
endif
if Damage.index.prevArmorT != udg_DamageEventArmorT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_ARMOR_TYPE, at)
endif
if Damage.index.prevDefenseT != udg_DamageEventDefenseT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_DEFENSE_TYPE, dt)
endif
endmethod
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
static if USE_EXTRA then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
private static method onAOEEnd takes nothing returns nothing
if udg_DamageEventAOE > 1 then
call DamageTrigger.AOE.run()
endif
set udg_DamageEventAOE = 0
set udg_DamageEventLevel = 0
set udg_EnhancedDamageTarget = null
set udg_AOEDamageSource = null
call GroupClear(udg_DamageEventAOEGroup)
endmethod
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
private static method afterDamage takes nothing returns nothing
if udg_DamageEventPrevAmt != 0.00 and udg_DamageEventDamageT != 0 then
call DamageTrigger.AFTER.run()
set udg_DamageEventDamageT = 0
set udg_DamageEventPrevAmt = 0.00
endif
endmethod
private method doPreEvents takes boolean natural returns boolean
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set this.armorType = BlzGetUnitIntegerField(this.targetUnit, UNIT_IF_ARMOR_TYPE)
set this.defenseType = BlzGetUnitIntegerField(this.targetUnit, UNIT_IF_DEFENSE_TYPE)
set this.prevArmorT = this.armorType
set this.prevDefenseT = this.defenseType
set this.armorPierced = 0.00
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set Damage.index = this
call DamageTrigger.setGUIFromStruct(true)
call GroupAddUnit(proclusGlobal, udg_DamageEventSource)
call GroupAddUnit(fischerMorrow, udg_DamageEventTarget)
//! runtextmacro optional DAMAGE_EVENT_PRE_VARS_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_PRE_VARS_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_PRE_VARS_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_PRE_VARS_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_PRE_VARS_PLUGIN_05()
if udg_DamageEventAmount != 0.00 then
set udg_DamageEventOverride = udg_DamageEventDamageT == 0
call DamageTrigger.MOD.run()
static if not USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call DamageTrigger.setGUIFromStruct(false)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if natural then
call BlzSetEventAttackType(this.attackType)
call BlzSetEventDamageType(this.damageType)
call BlzSetEventWeaponType(this.weaponType)
call BlzSetEventDamage(udg_DamageEventAmount)
endif
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call setArmor(false)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
return false
endif
return true
endmethod
private static method unfreeze takes nothing returns nothing
local Damage i = damageStack
loop
exitwhen i == 0
set i = i - 1
set i.stackRef.recursiveTrig.trigFrozen = false
set i.stackRef.recursiveTrig.levelsDeep = 0
endloop
call EnableTrigger(t1)
call EnableTrigger(t2)
set kicking = false
set damageStack = 0
set prepped = 0
set dreaming = false
set sleepLevel = 0
call GroupClear(proclusGlobal)
call GroupClear(fischerMorrow)
//call BJDebugMsg("Cleared up the groups")
endmethod
static method finish takes nothing returns nothing
local Damage i = 0
local integer exit
if eventsRun then
set eventsRun = false
call afterDamage()
endif
if canKick and not kicking then
if damageStack != 0 then
set kicking = true
loop
set sleepLevel = sleepLevel + 1
set exit = damageStack
loop
set prepped = i.stackRef
if UnitAlive(prepped.targetUnit) then //Added just in case dead units had issues.
call prepped.doPreEvents(false) //don't evaluate the pre-event
if prepped.damage > 0.00 then
call DisableTrigger(t1) //Force only the after armor event to run.
call EnableTrigger(t2) //in case the user forgot to re-enable this
set totem = true
call UnitDamageTarget(prepped.sourceUnit, prepped.targetUnit, prepped.damage, prepped.isAttack, prepped.isRanged, prepped.attackType, prepped.damageType, prepped.weaponType)
else
//No new events run at all in this case
if udg_DamageEventDamageT != 0 then
call DamageTrigger.DAMAGE.run()
endif
if prepped.damage < 0.00 then
//No need for BlzSetEventDamage here
call SetWidgetLife(prepped.targetUnit, GetWidgetLife(prepped.targetUnit) - prepped.damage)
endif
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call setArmor(true)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
call afterDamage()
endif
set i = i + 1
exitwhen i == exit
endloop
exitwhen i == damageStack
endloop
endif
call unfreeze()
endif
endmethod
private static method failsafeClear takes nothing returns nothing
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call setArmor(true)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set canKick = true
set kicking = false
set totem = false
if udg_DamageEventDamageT != 0 then
call DamageTrigger.DAMAGE.run()
set eventsRun = true
endif
call finish()
endmethod
static method operator enabled= takes boolean b returns nothing
if b then
if dreaming then
call EnableTrigger(t3)
else
call EnableTrigger(t1)
call EnableTrigger(t2)
endif
else
if dreaming then
call DisableTrigger(t3)
else
call DisableTrigger(t1)
call DisableTrigger(t2)
endif
endif
endmethod
static method operator enabled takes nothing returns boolean
return IsTriggerEnabled(t1)
endmethod
private static boolean arisen = false
private static method getOutOfBed takes nothing returns nothing
if totem then
call failsafeClear() //WarCraft 3 didn't run the DAMAGED event despite running the DAMAGING event.
else
set canKick = true
set kicking = false
call finish()
endif
static if USE_EXTRA then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call onAOEEnd()
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set arisen = true
endmethod
private static method wakeUp takes nothing returns nothing
set dreaming = false
set Damage.enabled = true
call ForForce(bj_FORCE_PLAYER[0], function thistype.getOutOfBed) //Moved to a new thread in case of a thread crash
if not arisen then
//call BJDebugMsg("DamageEngine issue: thread crashed!")
call unfreeze()
else
set arisen = false
endif
set Damage.count = 0
set Damage.index = 0
set alarmSet = false
//call BJDebugMsg("Timer wrapped up")
endmethod
private method addRecursive takes nothing returns nothing
if this.damage != 0.00 then
set this.recursiveTrig = DamageTrigger.eventIndex
if not this.isCode then
set this.isCode = true
set this.userType = TYPE_CODE
endif
set inception = inception or DamageTrigger.eventIndex.inceptionTrig
if kicking and IsUnitInGroup(this.sourceUnit, proclusGlobal) and IsUnitInGroup(this.targetUnit, fischerMorrow) then
if not inception then
set DamageTrigger.eventIndex.trigFrozen = true
elseif not DamageTrigger.eventIndex.trigFrozen then
set DamageTrigger.eventIndex.inceptionTrig = true
if DamageTrigger.eventIndex.levelsDeep < sleepLevel then
set DamageTrigger.eventIndex.levelsDeep = DamageTrigger.eventIndex.levelsDeep + 1
if DamageTrigger.eventIndex.levelsDeep >= LIMBO then
set DamageTrigger.eventIndex.trigFrozen = true
endif
endif
endif
endif
set damageStack.stackRef = this
set damageStack = damageStack + 1
//call BJDebugMsg("damageStack: " + I2S(damageStack) + " levelsDeep: " + I2S(DamageTrigger.eventIndex.levelsDeep) + " sleepLevel: " + I2S(sleepLevel))
endif
set inception = false
endmethod
private static method clearNexts takes nothing returns nothing
set udg_NextDamageIsAttack = false
set udg_NextDamageType = 0
set udg_NextDamageWeaponT = 0
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_NextDamageIsMelee = false
set udg_NextDamageIsRanged = false
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endmethod
static method create takes unit src, unit tgt, real amt, boolean a, attacktype at, damagetype dt, weapontype wt returns Damage
local Damage d = Damage.count + 1
set Damage.count = d
set d.sourceUnit = src
set d.targetUnit = tgt
set d.damage = amt
set d.prevAmt = amt
set d.attackType = at
set d.damageType = dt
set d.weaponType = wt
set d.isAttack = udg_NextDamageIsAttack or a
set d.isSpell = d.attackType == null and not d.isAttack
return d
endmethod
private static method createFromEvent takes nothing returns Damage
local Damage d = create(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), BlzGetEventIsAttack(), BlzGetEventAttackType(), BlzGetEventDamageType(), BlzGetEventWeaponType())
set d.isCode = udg_NextDamageType != 0 or udg_NextDamageIsAttack or udg_NextDamageIsRanged or udg_NextDamageIsMelee or d.damageType == DAMAGE_TYPE_MIND or udg_NextDamageWeaponT != 0 or (d.damage != 0.00 and d.damageType == DAMAGE_TYPE_UNKNOWN)
if d.isCode then
if udg_NextDamageType != 0 then
set d.userType = udg_NextDamageType
else
set d.userType = TYPE_CODE
endif
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set d.isMelee = udg_NextDamageIsMelee
set d.isRanged = udg_NextDamageIsRanged
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set d.eFilter = FILTER_CODE
if udg_NextDamageWeaponT != 0 then
set d.weaponType = ConvertWeaponType(udg_NextDamageWeaponT)
set udg_NextDamageWeaponT = 0
endif
else
set d.userType = 0
if d.damageType == DAMAGE_TYPE_NORMAL and d.isAttack then
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set d.isMelee = IsUnitType(d.sourceUnit, UNIT_TYPE_MELEE_ATTACKER)
set d.isRanged = IsUnitType(d.sourceUnit, UNIT_TYPE_RANGED_ATTACKER)
if d.isMelee and d.isRanged then
set d.isMelee = d.weaponType != null // Melee units play a sound when damaging
set d.isRanged = not d.isMelee // In the case where a unit is both ranged and melee, the ranged attack plays no sound.
endif
if d.isMelee then
set d.eFilter = FILTER_MELEE
elseif d.isRanged then
set d.eFilter = FILTER_RANGED
else
set d.eFilter = FILTER_ATTACK
endif
else
set d.eFilter = FILTER_ATTACK
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
else
if d.isSpell then
set d.eFilter = FILTER_SPELL
else
set d.eFilter = FILTER_OTHER
endif
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set d.isMelee = false
set d.isRanged = false
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
endif
call clearNexts()
return d
endmethod
private static method onRecursion takes nothing returns boolean //New in 5.7
local Damage d = Damage.createFromEvent()
call d.addRecursive()
call BlzSetEventDamage(0.00)
return false
endmethod
private static method onDamaging takes nothing returns boolean
local Damage d = Damage.createFromEvent()
//call BJDebugMsg("Pre-damage event running for " + GetUnitName(GetTriggerUnit()))
if alarmSet then
if totem then //WarCraft 3 didn't run the DAMAGED event despite running the DAMAGING event.
if d.damageType == DAMAGE_TYPE_SPIRIT_LINK or d.damageType == DAMAGE_TYPE_DEFENSIVE or d.damageType == DAMAGE_TYPE_PLANT then
set totem = false
set lastInstance= Damage.index
set canKick = false
else
call failsafeClear() //Not an overlapping event - just wrap it up
endif
else
call finish() //wrap up any previous damage index
endif
static if USE_EXTRA then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if d.sourceUnit != udg_AOEDamageSource then
call onAOEEnd()
set udg_AOEDamageSource = d.sourceUnit
elseif d.targetUnit == udg_EnhancedDamageTarget then
set udg_DamageEventLevel= udg_DamageEventLevel + 1
elseif not IsUnitInGroup(d.targetUnit, udg_DamageEventAOEGroup) then
set udg_DamageEventAOE = udg_DamageEventAOE + 1
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
else
call TimerStart(alarm, 0.00, false, function Damage.wakeUp)
set alarmSet = true
static if USE_EXTRA then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_AOEDamageSource = d.sourceUnit
set udg_EnhancedDamageTarget= d.targetUnit
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
static if USE_EXTRA then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call GroupAddUnit(udg_DamageEventAOEGroup, d.targetUnit)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if d.doPreEvents(true) then
call DamageTrigger.ZERO.run()
set canKick = true
call finish()
endif
set totem = lastInstance == 0 or attacksImmune[udg_DamageEventAttackT] or damagesImmune[udg_DamageEventDamageT] or not IsUnitType(udg_DamageEventTarget, UNIT_TYPE_MAGIC_IMMUNE)
return false
endmethod
private static method onDamaged takes nothing returns boolean
local real r = GetEventDamage()
local Damage d = Damage.index
//call BJDebugMsg("Second damage event running for " + GetUnitName(GetTriggerUnit()))
if prepped > 0 then
set prepped = 0
elseif dreaming or d.prevAmt == 0.00 then
return false
elseif totem then
set totem = false
else
//This should only happen for stuff like Spirit Link or Thorns Aura/Carapace
call afterDamage()
set Damage.index = lastInstance
set lastInstance = 0
set d = Damage.index
set canKick = true
call DamageTrigger.setGUIFromStruct(true)
endif
static if USE_ARMOR_MOD then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call setArmor(true)
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
static if USE_SCALING then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if udg_DamageEventAmount != 0.00 and r != 0.00 then
set udg_DamageScalingWC3 = r / udg_DamageEventAmount
elseif udg_DamageEventAmount > 0.00 then
set udg_DamageScalingWC3 = 0.00
else
set udg_DamageScalingWC3 = 1.00
if udg_DamageEventPrevAmt == 0.00 then
set udg_DamageScalingUser = 0.00
else
set udg_DamageScalingUser = udg_DamageEventAmount/udg_DamageEventPrevAmt
endif
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_DamageEventAmount = r
set d.damage = r
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_GDD()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_PDD()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_VARS_PLUGIN_05()
if udg_DamageEventAmount > 0.00 then
call DamageTrigger.SHIELD.run()
static if not USE_GUI then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
set udg_DamageEventAmount = d.damage
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
static if USE_LETHAL then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if hasLethal or udg_DamageEventType < 0 then
set udg_LethalDamageHP = GetWidgetLife(udg_DamageEventTarget) - udg_DamageEventAmount
if udg_LethalDamageHP <= DEATH_VAL then
if hasLethal then
call DamageTrigger.LETHAL.run()
set udg_DamageEventAmount = GetWidgetLife(udg_DamageEventTarget) - udg_LethalDamageHP
set d.damage = udg_DamageEventAmount
endif
if udg_DamageEventType < 0 and udg_LethalDamageHP <= DEATH_VAL then
call SetUnitExploded(udg_DamageEventTarget, true)
endif
endif
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
static if USE_SCALING then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if udg_DamageEventPrevAmt == 0.00 or udg_DamageScalingWC3 == 0.00 then
set udg_DamageScalingUser = 0.00
else
set udg_DamageScalingUser = udg_DamageEventAmount/udg_DamageEventPrevAmt/udg_DamageScalingWC3
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
endif
if udg_DamageEventDamageT != 0 then
call DamageTrigger.DAMAGE.run()
endif
call BlzSetEventDamage(udg_DamageEventAmount)
set eventsRun = true
if udg_DamageEventAmount == 0.00 then
call finish()
endif
return false
endmethod
static method apply takes unit src, unit tgt, real amt, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt returns Damage
local Damage d
if udg_NextDamageType == 0 then
set udg_NextDamageType = TYPE_CODE
endif
if dreaming then
set d = create(src, tgt, amt, a, at, dt, wt)
set d.isCode = true
set d.eFilter = FILTER_CODE
set d.userType = udg_NextDamageType
static if USE_MELEE_RANGE then// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
if not d.isSpell then
set d.isRanged = udg_NextDamageIsRanged or r
set d.isMelee = not d.isRanged
endif
endif// \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
call d.addRecursive()
else
call UnitDamageTarget(src, tgt, amt, a, r, at, dt, wt)
set d = Damage.index
call finish()
endif
call clearNexts()
return d
endmethod
static method applySpell takes unit src, unit tgt, real amt, damagetype dt returns Damage
return apply(src, tgt, amt, false, false, null, dt, null)
endmethod
static method applyAttack takes unit src, unit tgt, real amt, boolean ranged, attacktype at, weapontype wt returns Damage
return apply(src, tgt, amt, true, ranged, at, DAMAGE_TYPE_NORMAL, wt)
endmethod
//===========================================================================
private static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_DAMAGING)
call TriggerAddCondition(t1, Filter(function Damage.onDamaging))
call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DAMAGED)
call TriggerAddCondition(t2, Filter(function Damage.onDamaged))
//For recursion
call TriggerRegisterAnyUnitEventBJ(t3, EVENT_PLAYER_UNIT_DAMAGING)
call TriggerAddCondition(t3, Filter(function Damage.onRecursion))
call DisableTrigger(t3)
//For preventing Thorns/Defensive glitch.
//Data gathered from https://www.hiveworkshop.com/threads/repo-in-progress-mapping-damage-types-to-their-abilities.316271/
set attacksImmune[0] = false //ATTACK_TYPE_NORMAL
set attacksImmune[1] = true //ATTACK_TYPE_MELEE
set attacksImmune[2] = true //ATTACK_TYPE_PIERCE
set attacksImmune[3] = true //ATTACK_TYPE_SIEGE
set attacksImmune[4] = false //ATTACK_TYPE_MAGIC
set attacksImmune[5] = true //ATTACK_TYPE_CHAOS
set attacksImmune[6] = true //ATTACK_TYPE_HERO
set damagesImmune[0] = true //DAMAGE_TYPE_UNKNOWN
set damagesImmune[4] = true //DAMAGE_TYPE_NORMAL
set damagesImmune[5] = true //DAMAGE_TYPE_ENHANCED
set damagesImmune[8] = false //DAMAGE_TYPE_FIRE
set damagesImmune[9] = false //DAMAGE_TYPE_COLD
set damagesImmune[10] = false //DAMAGE_TYPE_LIGHTNING
set damagesImmune[11] = true //DAMAGE_TYPE_POISON
set damagesImmune[12] = true //DAMAGE_TYPE_DISEASE
set damagesImmune[13] = false //DAMAGE_TYPE_DIVINE
set damagesImmune[14] = false //DAMAGE_TYPE_MAGIC
set damagesImmune[15] = false //DAMAGE_TYPE_SONIC
set damagesImmune[16] = true //DAMAGE_TYPE_ACID
set damagesImmune[17] = false //DAMAGE_TYPE_FORCE
set damagesImmune[18] = false //DAMAGE_TYPE_DEATH
set damagesImmune[19] = false //DAMAGE_TYPE_MIND
set damagesImmune[20] = false //DAMAGE_TYPE_PLANT
set damagesImmune[21] = false //DAMAGE_TYPE_DEFENSIVE
set damagesImmune[22] = true //DAMAGE_TYPE_DEMOLITION
set damagesImmune[23] = true //DAMAGE_TYPE_SLOW_POISON
set damagesImmune[24] = false //DAMAGE_TYPE_SPIRIT_LINK
set damagesImmune[25] = false //DAMAGE_TYPE_SHADOW_STRIKE
set damagesImmune[26] = true //DAMAGE_TYPE_UNIVERSAL
endmethod
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_DMGPKG()
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_01()
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_02()
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_03()
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_04()
//! runtextmacro optional DAMAGE_EVENT_STRUCT_PLUGIN_05()
endstruct
public function DebugStr takes nothing returns nothing
local integer i = 0
loop
set udg_CONVERTED_ATTACK_TYPE[i] = ConvertAttackType(i)
exitwhen i == 6
set i = i + 1
endloop
set i = 0
loop
set udg_CONVERTED_DAMAGE_TYPE[i] = ConvertDamageType(i)
exitwhen i == 26
set i = i + 1
endloop
set udg_AttackTypeDebugStr[0] = "SPELLS" //ATTACK_TYPE_NORMAL in JASS
set udg_AttackTypeDebugStr[1] = "NORMAL" //ATTACK_TYPE_MELEE in JASS
set udg_AttackTypeDebugStr[2] = "PIERCE"
set udg_AttackTypeDebugStr[3] = "SIEGE"
set udg_AttackTypeDebugStr[4] = "MAGIC"
set udg_AttackTypeDebugStr[5] = "CHAOS"
set udg_AttackTypeDebugStr[6] = "HERO"
set udg_DamageTypeDebugStr[0] = "UNKNOWN"
set udg_DamageTypeDebugStr[4] = "NORMAL"
set udg_DamageTypeDebugStr[5] = "ENHANCED"
set udg_DamageTypeDebugStr[8] = "FIRE"
set udg_DamageTypeDebugStr[9] = "COLD"
set udg_DamageTypeDebugStr[10] = "LIGHTNING"
set udg_DamageTypeDebugStr[11] = "POISON"
set udg_DamageTypeDebugStr[12] = "DISEASE"
set udg_DamageTypeDebugStr[13] = "DIVINE"
set udg_DamageTypeDebugStr[14] = "MAGIC"
set udg_DamageTypeDebugStr[15] = "SONIC"
set udg_DamageTypeDebugStr[16] = "ACID"
set udg_DamageTypeDebugStr[17] = "FORCE"
set udg_DamageTypeDebugStr[18] = "DEATH"
set udg_DamageTypeDebugStr[19] = "MIND"
set udg_DamageTypeDebugStr[20] = "PLANT"
set udg_DamageTypeDebugStr[21] = "DEFENSIVE"
set udg_DamageTypeDebugStr[22] = "DEMOLITION"
set udg_DamageTypeDebugStr[23] = "SLOW_POISON"
set udg_DamageTypeDebugStr[24] = "SPIRIT_LINK"
set udg_DamageTypeDebugStr[25] = "SHADOW_STRIKE"
set udg_DamageTypeDebugStr[26] = "UNIVERSAL"
set udg_WeaponTypeDebugStr[0] = "NONE" //WEAPON_TYPE_WHOKNOWS in JASS
set udg_WeaponTypeDebugStr[1] = "METAL_LIGHT_CHOP"
set udg_WeaponTypeDebugStr[2] = "METAL_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[3] = "METAL_HEAVY_CHOP"
set udg_WeaponTypeDebugStr[4] = "METAL_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[5] = "METAL_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[6] = "METAL_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[7] = "METAL_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[8] = "METAL_HEAVY_BASH"
set udg_WeaponTypeDebugStr[9] = "METAL_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[10] = "METAL_HEAVY_STAB"
set udg_WeaponTypeDebugStr[11] = "WOOD_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[12] = "WOOD_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[13] = "WOOD_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[14] = "WOOD_LIGHT_BASH"
set udg_WeaponTypeDebugStr[15] = "WOOD_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[16] = "WOOD_HEAVY_BASH"
set udg_WeaponTypeDebugStr[17] = "WOOD_LIGHT_STAB"
set udg_WeaponTypeDebugStr[18] = "WOOD_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[19] = "CLAW_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[20] = "CLAW_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[21] = "CLAW_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[22] = "AXE_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[23] = "ROCK_HEAVY_BASH"
set udg_DefenseTypeDebugStr[0] = "LIGHT"
set udg_DefenseTypeDebugStr[1] = "MEDIUM"
set udg_DefenseTypeDebugStr[2] = "HEAVY"
set udg_DefenseTypeDebugStr[3] = "FORTIFIED"
set udg_DefenseTypeDebugStr[4] = "NORMAL" //Typically deals flat damage to all armor types
set udg_DefenseTypeDebugStr[5] = "HERO"
set udg_DefenseTypeDebugStr[6] = "DIVINE"
set udg_DefenseTypeDebugStr[7] = "UNARMORED"
set udg_ArmorTypeDebugStr[0] = "NONE" //ARMOR_TYPE_WHOKNOWS in JASS, added in 1.31
set udg_ArmorTypeDebugStr[1] = "FLESH"
set udg_ArmorTypeDebugStr[2] = "METAL"
set udg_ArmorTypeDebugStr[3] = "WOOD"
set udg_ArmorTypeDebugStr[4] = "ETHEREAL"
set udg_ArmorTypeDebugStr[5] = "STONE"
endfunction
//===========================================================================
//
// Setup of automatic events from GUI and custom ones from JASS alike
//
//===========================================================================
public function RegisterFromHook takes trigger whichTrig, string var, limitop op, real value returns nothing
call DamageTrigger.registerVerbose(whichTrig, var, value, true, GetHandleId(op))
endfunction
hook TriggerRegisterVariableEvent RegisterFromHook
function TriggerRegisterDamageEngineEx takes trigger whichTrig, string eventName, real value, integer f returns DamageTrigger
return DamageTrigger.registerVerbose(whichTrig, DamageTrigger.getVerboseStr(eventName), value, false, f)
endfunction
function TriggerRegisterDamageEngine takes trigger whichTrig, string eventName, real value returns DamageTrigger
return DamageTrigger.registerTrigger(whichTrig, eventName, value)
endfunction
function RegisterDamageEngineEx takes code c, string eventName, real value, integer f returns DamageTrigger
return TriggerRegisterDamageEngineEx(DamageTrigger[c], eventName, value, f)
endfunction
//Similar to TriggerRegisterDamageEvent, although takes code instead of trigger as the first argument.
function RegisterDamageEngine takes code c, string eventName, real value returns DamageTrigger
return RegisterDamageEngineEx(c, eventName, value, FILTER_OTHER)
endfunction
//For GUI to tap into more powerful vJass event filtering:
//! textmacro DAMAGE_TRIGGER_CONFIG
if not DamageTrigger.eventIndex.configured then
//! endtextmacro
//! textmacro DAMAGE_TRIGGER_CONFIG_END
call DamageTrigger.eventIndex.configure()
if not DamageTrigger.eventIndex.checkConfiguration() then
return
endif
endif
//! endtextmacro
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
//============================================================================
// Easy Item Stack 'n Split v2.7.4
// by Dangerb0y
//============================================================================
//
// FEATURES:
// - Automatically stacks obtained items to a configurable stack limit.
// - Allows stacking items within a unit's inventory.
// - Allows splitting item stacks within a unit's inventory.
// - Allows units to seamlessly pick up items regardless of a full inventory.
// - Copy-paste implementation.
//
// STACKING ITEMS:
// - Obtained items are automatically stacked with same-type items in a unit's inventory.
// - Placing same-type items on top of each other will stack them together.
//
// SPLITTING ITEMS:
// - Double right-clicking or dropping an item stack on itself will split a set amount off the pile. (optional)
// - Consecutively split items will stack together. (optional)
// - If a unit's inventory slots are full when splitting an item stack, the split item will be dropped on the ground in front of the unit. (optional)
//
// ITEM STACKS:
// - The maximum stack size is set by the item's level in the Object Editor (Shift+Double-click allows entering levels greater than 8).
// - Setting an item's level to 0 will give it an unlimited stack size.
// - Items must have charges in order to be stacked; non-charged items will function as Blizzard intended.
//
// RELEASE NOTES:
// - This system can be implemented into any map.
// - This system is completely leak-free.
// - This system is completely lag-free.
// - This system is fully MUI and MPI.
// - This system works with all inventory sizes.
// - This system does NOT use hashtables or gamecache, i.e. it is much faster.
// - This system is available in vJASS and GUI.
//
// IMPLEMENTATION:
// - See trigger comments.
//
// UPDATING? Make sure to first delete old EasyItemStacknSplit triggers and, if you use the GUI version, all the variables with the "EasyItem" prefix.
function InitTrig_Documentation takes nothing returns nothing
call FogEnable( false )
call FogMaskEnable( false )
call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS, 0, "|c0075DD07Easy Item Stack 'n Split|r |c00E6DC28v2.7.4|r\n by Dangerb0y" )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
//=====================================================================================
// Easy Item Stack 'n Split v2.7.4
// by Dangerb0y
//=====================================================================================
library EasyItemStacknSplit initializer onInit
//=====================================================================================
//
// This system adds some much needed item stacking, item splitting, and full inventory
// functionality to Warcraft III.
//
// A couple of useful functions are also included...
//
// - UnitInventoryFull( unit )
// Returns true if all of a unit's inventory slots are occupied, else false.
//
// - UnitStackItem( unit, item )
// Works like UnitAddItem(), but will try to stack items even if inventory is full.
// If excess items from an item stack are dropped, returns the item, else null.
//
//=====================================================================================
// SYSTEM PARAMETERS
//=====================================================================================
globals
// Allow item splitting with double right-click?
private boolean SPLIT = true
// Amount to split from stack... (0 = half)
private integer SPLIT_SIZE = 1
// Allow consecutively split items to stack together?
private boolean SPLIT_STACK = true
private real SPLIT_STACK_DELAY = 2.00
// Allow split items to be dropped if no inventory slots are open?
private boolean SPLIT_DROP = true
// Use item levels to determine stack limit? (false = unlimited stacks)
private boolean USE_ITEM_LEVEL = true
// Full inventory error sound filename... (null = disabled)
private string ERROR_SOUND = "Sound\\Interface\\Error.wav"
private string ERROR_MESSAGE = "Inventory is full."
private integer array DUMMY_ITEM_TYPES
private integer array REAL_ITEM_TYPES
private integer DUMMY_ITEMS_COUNT
endglobals
function InitDummyItemPairs takes nothing returns nothing
// Since BlzSetItemBooleanField does not work, to allow buying items with full inventory we are forced to do this
// For each item with charges, we created a tome-like dummy copy with "use automatically on acquired" = true.
// Such dummy items can be clicked-bought even with full inventory, contrary to other items.
set DUMMY_ITEM_TYPES[0] = 'I00P' // 1st dummy item bought from shop
set REAL_ITEM_TYPES[0] = 'wild' // 1st real item heroes can use
set DUMMY_ITEM_TYPES[1] = 'I00Q'
set REAL_ITEM_TYPES[1] = 'ankh'
set DUMMY_ITEM_TYPES[2] = 'I00O'
set REAL_ITEM_TYPES[2] = 'pams'
set DUMMY_ITEM_TYPES[3] = 'I00W'
set REAL_ITEM_TYPES[3] = 'I002'
set DUMMY_ITEM_TYPES[4] = 'I00S'
set REAL_ITEM_TYPES[4] = 'whwd'
set DUMMY_ITEM_TYPES[5] = 'I00T'
set REAL_ITEM_TYPES[5] = 'pghe'
set DUMMY_ITEM_TYPES[6] = 'I00U'
set REAL_ITEM_TYPES[6] = 'pgma'
set DUMMY_ITEM_TYPES[7] = 'I00V'
set REAL_ITEM_TYPES[7] = 'pnvu'
set DUMMY_ITEM_TYPES[8] = 'I00X'
set REAL_ITEM_TYPES[8] = 'stwp'
set DUMMY_ITEMS_COUNT = 9 // Number of dummy-real item pairs
endfunction
//=====================================================================================
// DO NOT EDIT BELOW THIS LINE
//=====================================================================================
globals
private unit array goPickButFullUnits
private unit array splitStackUnits
private item array goPickButFullItems
private item array splitStackItem1s
private item array splitStackItem2s
private real array splitStackDelays
private integer goPickButFullCount = 0
private integer splitStackCount = 0
private timer t = CreateTimer()
endglobals
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// PUBLIC FUNCTION : UnitInventoryFull( unit )
// Checks if all the inventory slots of a unit are occupied.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
function UnitInventoryFull takes unit u returns boolean
local integer inventorySize = UnitInventorySize( u )
local integer slot = 0
loop
exitwhen slot >= inventorySize
if UnitItemInSlot(u, slot) == null then
return false
endif
set slot = slot + 1
endloop
return true
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// PUBLIC FUNCTION : FireStackChangedEvent( unit, item )
// Fire an event to signal that the stack size on an item carriet has changed.
// The solution decided for the moment is to trigger a "Unit - is issued an order targeting item" to move it in-place event.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
function FireStackChangedEvent takes unit u, item i returns nothing
local integer inventorySize = UnitInventorySize(u)
local integer slot = 0
// Retrieve the item's slot
loop
if ( UnitItemInSlot(u, slot) == i ) then
exitwhen true // item's slot found
endif
set slot = slot + 1
exitwhen slot >= inventorySize
endloop
if ( slot < inventorySize ) then
call DisableTrigger( gg_trg_EasyItemStacknSplit )
call UnitDropItemSlot( u, i, slot )
call EnableTrigger( gg_trg_EasyItemStacknSplit )
endif
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// PUBLIC FUNCTION : UnitStackItem( unit, item )
// Works like UnitAddItem() with full inventory functionality.
// Returns true if excess items are dropped. Otherwise false.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
function UnitStackItem takes unit u, item item1 returns boolean
local integer item1Charges = GetItemCharges( item1 )
local integer inventorySize
local integer item1Level
local integer item1TypeId
local item item2
local integer item2Charges
local integer item2Level
local integer slot
local real posX
local real posY
local real unitAngle
// Make sure the item has charges
if item1Charges <= 0 then
// If not we just give it to the unit
call DisableTrigger( gg_trg_EasyItemStacknSplit )
call UnitAddItem( u, item1 )
call EnableTrigger( gg_trg_EasyItemStacknSplit )
else
// Item has charges
set inventorySize = UnitInventorySize( u )
set item1Level = GetItemLevel( item1 )
set item1TypeId = GetItemTypeId( item1 )
// We can remove the item, we have all the data we need from it
call RemoveItem( item1 )
// Look for items of the same type and try stack onto them
set slot = 0
loop
set item2 = UnitItemInSlot( u, slot )
set item2Charges = GetItemCharges( item2 )
set item2Level = GetItemLevel( item2 )
if item2 != null and (not USE_ITEM_LEVEL or item2Level == 0 or item2Charges < item2Level) and GetItemTypeId(item2) == item1TypeId then
// Found an item with same type and room for some charges
if USE_ITEM_LEVEL and item2Level > 0 and item2Charges + item1Charges > item2Level then
// Not all charges can be stacked onto this item, stack as many as possible and keep the rest
call SetItemCharges( item2, item2Level )
call FireStackChangedEvent(u,item2)
set item1Charges = item2Charges + item1Charges - item2Level
else
// All charges can be stacked onto this item
call SetItemCharges( item2, item2Charges + item1Charges )
call FireStackChangedEvent(u,item2)
set item1Charges = 0
endif
endif
set slot = slot + 1
exitwhen item1Charges <= 0 or slot >= inventorySize
endloop
// If there are any charges left over, look for open slots
if item1Charges > 0 then
// There are charges left
set posX = GetUnitX( u )
set posY = GetUnitY( u )
set slot = 0
loop
// Create as many items as necessary and possible in the unit inventory
set item2 = UnitItemInSlot( u, slot )
if item2 == null then
// There is a free slot: create a new item there for the remaining charges
set item2 = CreateItem( item1TypeId, posX, posY )
if USE_ITEM_LEVEL and item1Level > 0 and item1Charges > item1Level then
// Not all charges can fit in a single item, just put as many as possible
call SetItemCharges( item2, item1Level )
set item1Charges = item1Charges - item1Level
else
// All charges fit in this new item
call SetItemCharges( item2, item1Charges )
set item1Charges = 0
endif
call DisableTrigger( gg_trg_EasyItemStacknSplit )
call UnitAddItem( u, item2 )
call EnableTrigger( gg_trg_EasyItemStacknSplit )
endif
set slot = slot + 1
exitwhen item1Charges <= 0 or slot >= inventorySize
endloop
// If there are still charges left over, drop them on the ground
if item1Charges > 0 then
// There are some charges left that cannot be carried
set unitAngle = GetUnitFacing( u )
set posX = GetUnitX( u ) + 100 * Cos( unitAngle * bj_DEGTORAD )
set posY = GetUnitY( u ) + 100 * Sin( unitAngle * bj_DEGTORAD )
loop
// Create a many items as necessary on the floor
if item1Charges > item1Level then
// Not all charges can find in a single
set item2Charges = item1Level
set item1Charges = item1Charges - item1Level
else
// All charges can fit in a single item
set item2Charges = item1Charges
set item1Charges = 0
endif
set item2 = CreateItem( item1TypeId, posX, posY )
call SetItemCharges( item2, item2Charges )
exitwhen item1Charges <= 0
endloop
return true
endif
endif
endif
// Nothing dropped
return false
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// TEXTMACRO : EasyItemStacknSplit_PLAYITEMSOUND( soundname, unitvar )
// Plays item sound for player if the triggering unit is nearby.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! textmacro EasyItemStacknSplit_PLAYITEMSOUND takes FILENAME
set str = "Sound\\Interface\\$FILENAME$.wav"
set snd = CreateSound( str, false, true, false, 12700, 12700, "" )
call AttachSoundToUnit( snd, u )
call SetSoundVolume( snd, 75 )
call SetSoundDistances( snd, 600.0, 1024.0 )
call SetSoundDistanceCutoff( snd, 1536.0 )
if GetLocalPlayer() != p then
call StartSound( snd )
endif
call KillSoundWhenDone( snd )
//! endtextmacro
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// CONTROLLER : TimerController
// EVENTS : Global Timer (t) expires (periodically, 0.05)
// Runs through full-stack and split-stack queues, and works its magic.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
private function TimerController takes nothing returns nothing
local unit u
local item item1
local item item2
local integer index
local integer orderId
local real deltax
local real deltay
local real delay
local player p
local string str
local sound snd
// Run through the go-pick-but-full actions stack queue
if goPickButFullCount > 0 then
set index = 0
loop
set u = goPickButFullUnits[index]
set item1 = goPickButFullItems[index]
if u != null and item1 != null and not IsItemOwned(item1) and GetWidgetLife(item1) > 0 and GetWidgetLife(u) > 0 then
// Unit and items are still untouched
set orderId = GetUnitCurrentOrder( u )
set deltax = GetItemX( item1 ) - GetUnitX( u )
set deltay = GetItemY( item1 ) - GetUnitY( u )
if deltax * deltax + deltay * deltay <= 22500 or orderId != 851986 then
// Unit has reached the item, or unit is not currently moving
if orderId == 851986 then
// Unit is moving - get the item and try to stack it
set p = GetOwningPlayer( u )
// Play the "Item Get" sound
//! runtextmacro EasyItemStacknSplit_PLAYITEMSOUND( "PickUpItem" )
call IssueImmediateOrder( u, "stop" )
call SetUnitFacing( u, bj_RADTODEG * Atan2(GetItemY(item1) - GetUnitY(u), GetItemX(item1) - GetUnitX(u)) )
if UnitStackItem(u, item1) then
// Couldn't stack all the charges, somes have been left on the floor, play the "Item Drop" sound
//! runtextmacro EasyItemStacknSplit_PLAYITEMSOUND( "HeroDropItem1" )
endif
endif
set goPickButFullCount = goPickButFullCount - 1
if goPickButFullCount > 0 then
// To fill the hole in the queue, move-in the last action
set goPickButFullUnits[index] = goPickButFullUnits[goPickButFullCount]
set goPickButFullItems[index] = goPickButFullItems[goPickButFullCount]
set index = index - 1
endif
endif
elseif u != null or item1 != null then
// The item has been destroyed or picked by someone else
call IssueImmediateOrder( u, "stop" )
set goPickButFullCount = goPickButFullCount - 1
if goPickButFullCount > 0 then
// To fill the hole in the queue, move-in the last action
set goPickButFullUnits[index] = goPickButFullUnits[goPickButFullCount]
set goPickButFullItems[index] = goPickButFullItems[goPickButFullCount]
set index = index - 1
endif
endif
set index = index + 1
exitwhen index >= goPickButFullCount
endloop
endif
// Run through split-stack actions queue
if SPLIT_STACK and splitStackCount > 0 then
set index = 0
loop
set u = splitStackUnits[index]
set item1 = splitStackItem1s[index]
set item2 = splitStackItem2s[index]
set delay = splitStackDelays[index]
if u != null and item1 != null and item2 != null and delay > 0 and UnitHasItem(u, item1) and UnitHasItem(u, item2) then
// Unit still carries both items - split&stack may have not been resolved yet
set splitStackDelays[index] = delay - 0.05
else
// Split-stack has been finished somehow
set splitStackCount = splitStackCount - 1
if splitStackCount > 0 then
// To fill the hole in the queue, move-in the last action
set splitStackUnits[index] = splitStackUnits[splitStackCount]
set splitStackItem1s[index] = splitStackItem1s[splitStackCount]
set splitStackItem2s[index] = splitStackItem2s[splitStackCount]
set splitStackDelays[index] = splitStackDelays[splitStackCount]
set index = index - 1
endif
endif
set index = index + 1
exitwhen index >= splitStackCount
endloop
endif
// Pause timer if not needed
if goPickButFullCount <= 0 and (not SPLIT_STACK or splitStackCount <= 0) then
// If all timed events have been resolved, pause the timer
call PauseTimer( t )
endif
set u = null
set item1 = null
set p = null
set snd = null
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// CONTROLLER : CancelController
// EVENTS : Unit Targets Point
// Flushes trigger-unit and target-item from timer queue.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
private function CancelController takes nothing returns boolean
local integer index = 0
if goPickButFullCount > 0 then
loop
if goPickButFullUnits[index] == GetTriggerUnit() and (GetOrderPointX() != GetItemX(goPickButFullItems[index]) or GetOrderPointY() != GetItemY(goPickButFullItems[index])) then
set goPickButFullCount = goPickButFullCount - 1
if goPickButFullCount > 0 then
set goPickButFullUnits[index] = goPickButFullUnits[goPickButFullCount]
set goPickButFullItems[index] = goPickButFullItems[goPickButFullCount]
set index = index - 1
elseif not SPLIT_STACK or splitStackCount <= 0 then
call PauseTimer( t )
endif
endif
set index = index + 1
exitwhen index >= goPickButFullCount
endloop
endif
return false
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// CONTROLLER : ActionController
// EVENTS : Unit Acquires Item, Unit Targets Object
// Main system controller. Determines unit order and runs actions accordingly.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
private function ActionController takes nothing returns boolean
local eventid eventId = GetTriggerEventId()
local unit u = GetTriggerUnit()
local integer inventorySize = UnitInventorySize(u)
local player p
local integer orderId
local item item1 // Item being manipulated
local integer item1TypeId
local integer item1Charges
local integer item1Level
local item item2 // Either target or newly created item
local integer item2Charges
local integer item2Level
local integer item2Slot
local integer index
local integer splitChargeCount
local location pos
local boolean full
local real unitAngle
local string str
local sound snd
// Only units with not-null inventory are relevant
if (inventorySize == 0) then
return false
endif
// Detect if triggering event is "unit acquires an item" or "unit is issued an order targeting item"
if (eventId == EVENT_PLAYER_UNIT_PICKUP_ITEM) then
// Unit acquired an item
set item1 = GetManipulatedItem()
if (item1 != null) then
// Could it be a dummy item (allow buying items with full inventory)
if ( BlzGetItemBooleanField(item1, ITEM_BF_USE_AUTOMATICALLY_WHEN_ACQUIRED) == true and DUMMY_ITEMS_COUNT > 0 ) then
// Compare to the dummy item list
set index = 0
loop
if (GetItemTypeId(item1) == DUMMY_ITEM_TYPES[index] ) then
// Dummy item found > replace with the real one
call RemoveItem(item1)
set pos = GetUnitLoc(u)
set item1 = CreateItemLoc( REAL_ITEM_TYPES[index], pos )
call RemoveLocation(pos)
exitwhen true
endif
set index = index + 1
exitwhen index >= DUMMY_ITEMS_COUNT
endloop
endif
if ( BlzGetItemBooleanField(item1, ITEM_BF_USE_AUTOMATICALLY_WHEN_ACQUIRED) == true and GetItemCharges(item1) == 1 ) then
// Nothing to add in inventory, all charges will be used on acquisition
else
// The item is being acquired so we stack it
if UnitStackItem(u, item1) then
// Couldnot stack all charges in inventory, some remain on the floor. Play the "Item Drop" sound
set p = GetOwningPlayer( u )
//! runtextmacro EasyItemStacknSplit_PLAYITEMSOUND( "HeroDropItem1.wav" )
endif
endif
endif
elseif (eventId == EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER) then
// Unit is issued an order targeting an object: attack, attack once, move to, right click, moveslot<1-6>
set item1 = GetOrderTargetItem()
if (item1 != null) then
if ( BlzGetItemBooleanField(item1, ITEM_BF_USE_AUTOMATICALLY_WHEN_ACQUIRED) == true and GetItemCharges(item1) == 1 ) then
// Nothing to add in inventory, all charges will be used on acquisition
else
set orderId = GetIssuedOrderId()
if (orderId == 851971) then
// The item is on the floor and left clicked (going to pick it)
if UnitInventoryFull(u) then
// The item is being targeted with a full inventory so we add it to the timer queue
set item1Charges = GetItemCharges( item1 )
set index = 0
if ( item1Charges > 0 ) then
// Item with charges, look up if there is an item available to receive those charges in unit inventory
set item1Level = GetItemLevel( item1 )
set item1TypeId = GetItemTypeId( item1 )
set index = 0
loop
set item2 = UnitItemInSlot( u, index )
set item2Level = GetItemLevel( item2 )
if item2 != item1 and GetItemTypeId(item2) == item1TypeId and (not USE_ITEM_LEVEL or item2Level == 0 or GetItemCharges(item2) < item2Level) then
// Found item with same type
set index = inventorySize + 1
else
set index = index + 1
endif
exitwhen index >= inventorySize
endloop
endif
// Is it possible to pick some charges or not ?
if index > inventorySize then
// Inventory has room to receive the charges
set index = 0
if goPickButFullCount > 0 then
// Check if unit is already moving to pick other charges
loop
if goPickButFullUnits[index] == u then
set goPickButFullItems[index] = item1 // Update the parameters
set index = -1
else
set index = index + 1
endif
exitwhen index >= goPickButFullCount or index == -1
endloop
endif
if index >= 0 then
// No previous go-pick-but-full action, just check if the timer should be started and append this action
if goPickButFullCount == 0 then
call TimerStart( t, 0.05, true, function TimerController )
endif
set goPickButFullUnits[goPickButFullCount] = u
set goPickButFullItems[goPickButFullCount] = item1
set goPickButFullCount = goPickButFullCount + 1
endif
// Order the unit to move to the item position
call IssuePointOrder( u, "move", GetItemX(item1), GetItemY(item1) )
else
// Full inventory error
call IssueImmediateOrder( u, "stop" )
set p = GetOwningPlayer( u )
// Play error sound
if ERROR_SOUND != null and ERROR_SOUND != "" then
set str = ERROR_SOUND
set snd = CreateSound( str, false, false, false, 12700, 12700, "" )
call SetSoundVolume( snd, 127 )
if GetLocalPlayer() != p then
call StartSound( snd )
endif
call KillSoundWhenDone( snd )
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetOwningPlayer(udg_EasyItem_unit),0.50,-1.00,2.00,"|cffffcc00"+ERROR_MESSAGE+"|r")
endif
endif
else
// The item will be picked normally when the unit reaches it (a unit acquire item event will be fired by W3)
endif
elseif (orderId > 852001 and orderId < 852008) then
// The unit is issued a moveslot<1-6> order: an item is being moved to another inventory slot
if UnitHasItem(u, item1) then
// Safety check: item comes from the unit inventory
set item1Charges = GetItemCharges( item1 )
if (item1Charges > 0) then
// The moved item has charges
set item2Slot = orderId - 852002 // target slot index (0 to 5)
set item2 = UnitItemInSlot( u, item2Slot )
if GetItemTypeId(item2) == GetItemTypeId(item1) then
// The moved item and target item have the same type or are identical
if item2 == item1 then
// The item is moved on itself - split charges
if SPLIT then
// Split by double right-click is enabled in settings
set full = UnitInventoryFull( u )
if item1Charges > 1 and (SPLIT_DROP or not full) then
// Split is possible (there is room in inventory or drop is enabled in settings)
if SPLIT_SIZE > 0 then
// Split is set to a fixed size in settings
if SPLIT_SIZE >= item1Charges then
// Not enough charges: splitting total quantity minus 1
set splitChargeCount = item1Charges - 1
else
// Enough charges for full-split
set splitChargeCount = SPLIT_SIZE
endif
else
// Splits in half (bottom-rounded)
set splitChargeCount = item1Charges / 2
endif
call SetItemCharges( item1, item1Charges - splitChargeCount )
call FireStackChangedEvent(u, item1)
if SPLIT_STACK then
// Splitted charged stacked on other items is enabled in settings
set item2 = null
if splitStackCount > 0 then
// Cancel timer is on
set index = 0
loop
if u == splitStackUnits[index] then
// This unit already is in the splitstack/cancel timer input
set item2 = splitStackItem2s[index]
set item2Charges = GetItemCharges( item2 )
set item1Charges = GetItemLevel( item2 )
exitwhen true
endif
set index = index + 1
exitwhen index >= splitStackCount
endloop
endif
endif
if SPLIT_STACK and item2 != null and item2 != item1 and splitStackItem1s[index] == item1 and (not USE_ITEM_LEVEL or item1Charges == 0 or item2Charges < item1Charges) and UnitHasItem(u, item2) and GetItemTypeId(item2) == GetItemTypeId(item1) then
// Merge this split-stack with the other entry in the splitstack/cancel timer input
call SetItemCharges( item2, item2Charges + splitChargeCount )
call FireStackChangedEvent(u, item2)
set splitStackDelays[index] = SPLIT_STACK_DELAY
else
// Create a new item with the splitted charges
set unitAngle = GetUnitFacing( u )
set item2 = CreateItem( GetItemTypeId(item1), GetUnitX(u) + 100 * Cos(unitAngle * bj_DEGTORAD), GetUnitY(u) + 100 * Sin(unitAngle * bj_DEGTORAD) )
call SetItemCharges( item2, splitChargeCount )
if not full then
// There is room, give the new item to the unit
call DisableTrigger( gg_trg_EasyItemStacknSplit )
call UnitAddItem( u, item2 )
call EnableTrigger( gg_trg_EasyItemStacknSplit )
if SPLIT_STACK then
// Splitted charged stacked on other items is enabled in settings
set index = 0
if splitStackCount > 0 then
// Cancel timer is on
loop
if splitStackUnits[index] == u then
// This unit already is in the splitstack/cancel timer input - update the previous parameters
set splitStackItem1s[index] = item1
set splitStackItem2s[index] = item2
set splitStackDelays[index] = SPLIT_STACK_DELAY
set index = -1
else
set index = index + 1
endif
exitwhen index >= splitStackCount or index == -1
endloop
endif
if index >= 0 then
// This unit is not already in the cancel timer input
if splitStackCount == 0 then
// If not started, start the timer
call TimerStart( t, 0.05, true, function TimerController )
endif
// Push back this unit to the splitstack/cancel timer input
set splitStackUnits[splitStackCount] = u
set splitStackItem1s[splitStackCount] = item1
set splitStackItem2s[splitStackCount] = item2
set splitStackDelays[splitStackCount] = SPLIT_STACK_DELAY
set splitStackCount = splitStackCount + 1
endif
endif
else
// There is no room for the new item, leave it on the floor and play the "Item Drop" sound
set p = GetOwningPlayer( u )
//! runtextmacro EasyItemStacknSplit_PLAYITEMSOUND( "HeroDropItem1" )
endif
endif
endif
endif
else
// The item is moved on another item of same type - stack them
set item1Level = GetItemLevel( item1 )
set item2Charges = GetItemCharges( item2 )
if USE_ITEM_LEVEL and item1Level > 0 and item2Charges + item1Charges > item1Level then
// Total charges of destination item is limited and that limit is exceeded
if item1Charges < GetItemLevel(item2) and item2Charges < GetItemLevel(item2) then
// Safety check: both items had less than max charge. Stack a max of charges in the destination item, leave the rest in the source item
call SetItemCharges( item2, item2Charges + item1Charges - item1Level )
call FireStackChangedEvent(u, item2)
call SetItemCharges( item1, item1Level )
call FireStackChangedEvent(u, item1)
endif
else
// All the charges can be stacked, source item disapears
call SetItemCharges( item2, item2Charges + item1Charges )
call FireStackChangedEvent(u, item2)
call RemoveItem( item1 )
endif
endif
endif
endif
endif
else
// Other irrelevant orders targeting an item (attack, ...)
endif
endif
endif
else
// OTHER TYPE OF TRIGGERING EVENT - SHOULD NEVER HAPPEN
endif
set u = null
set p = null
set item1 = null
set item2 = null
set snd = null
return false
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// CONTROLLER : PreloadController
// EVENTS : Game Time Elapsed = 0.00
// Preloads sound files so that they play the first time around.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
private function PreloadController takes nothing returns boolean
local string array str
local sound snd
local integer x = 0
set str[0] = "Sound\\Interface\\PickUpItem.wav"
set str[1] = "Sound\\Interface\\HeroDropItem1.wav"
if ERROR_SOUND != null and ERROR_SOUND != "" then
set str[2] = ERROR_SOUND
endif
loop
exitwhen str[x] == null
set snd = CreateSound( str[x], false, false, false, 12700, 12700, "" )
call SetSoundVolume( snd, 0 )
call StartSound( snd )
call KillSoundWhenDone( snd )
set x = x + 1
endloop
set snd = null
call DestroyTrigger( GetTriggeringTrigger() )
return false
endfunction
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// TRIGGER INITIALIZER
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
private function onInit takes nothing returns nothing
local trigger CancelTrigger = CreateTrigger()
local trigger PreloadTrigger = CreateTrigger()
local integer index = 0
call InitDummyItemPairs()
set gg_trg_EasyItemStacknSplit = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent( gg_trg_EasyItemStacknSplit, Player(index), EVENT_PLAYER_UNIT_PICKUP_ITEM, null )
call TriggerRegisterPlayerUnitEvent( gg_trg_EasyItemStacknSplit, Player(index), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null )
call TriggerRegisterPlayerUnitEvent( CancelTrigger, Player(index), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, null )
set index = index + 1
exitwhen index >= bj_MAX_PLAYER_SLOTS
endloop
call TriggerRegisterTimerEvent( PreloadTrigger, 0.00, false )
call TriggerAddCondition( gg_trg_EasyItemStacknSplit, function ActionController )
call TriggerAddCondition( CancelTrigger, function CancelController )
call TriggerAddCondition( PreloadTrigger, function PreloadController )
endfunction
endlibrary
function RegisterBossUnit takes unit bossUnit returns nothing
call GroupAddUnit(udg_BossUnits, bossUnit)
call EnableTrigger(gg_trg_BossUnregister)
call EnableTrigger(gg_trg_BossRearFlankAttack)
endfunction
function GetAttackAngle takes unit attackerUnit, unit targetUnit returns real
local location attackerLocation = GetUnitLoc(attackerUnit)
local location targetLocation = GetUnitLoc(targetUnit)
local real targetToAttackerAngle = AngleBetweenPoints(targetLocation, attackerLocation)
local real targetFacingAngle = GetUnitFacing(targetUnit)
call RemoveLocation(attackerLocation)
call RemoveLocation(targetLocation)
return (targetFacingAngle - targetToAttackerAngle)
endfunction
function IsFrontAttacking takes unit attackerUnit, unit targetUnit returns boolean
local real attackAngle = GetAttackAngle(attackerUnit, targetUnit)
if ( CosBJ(attackAngle) >= CosBJ(45.0) ) then
return true
endif
return false
endfunction
function IsRearAttacking takes unit attackerUnit, unit targetUnit returns boolean
local real attackAngle = GetAttackAngle(attackerUnit, targetUnit)
if ( CosBJ(attackAngle) <= -CosBJ(45.0) ) then
return true
endif
return false
endfunction
function IsFlankAttacking takes unit attackerUnit, unit targetUnit returns boolean
local real attackAngle = GetAttackAngle(attackerUnit, targetUnit)
// Right
if ( SinBJ(attackAngle) < -SinBJ(45.0) ) then
return true
endif
// Left
if ( SinBJ(attackAngle) > SinBJ(45.0) ) then
return true
endif
return false
endfunction
:+++++++`
..........ymmmmmmm-...............
.NNNNNNNNNN:```````mNNNNNNNNNNNNNNh
+dddddddddh----------` .--------------/ddddddd+
oooooooooooooooooooo+ .oooooooooooooooooooo:
.--hddddddddd/ /ddddddddddddo--`
sNN`````````` ````````````+NN.
sMM` +MM.
-++ss/ sso++`
NMy -:- -:- `MMs
NMy hMm`` ``mMh `MMs
NMy hMMmm+ +mmMMh `MMs
NMy hMMMM+ +MMMMh `MMs
NMy hMMMMy// //yMMMMh `MMs
NMy hMMMMMMM` `MMMMMMMh `MMs
NMy hMMMMMMM` `MMMMMMMh `MMs
NMy hMMMMMMM` `MMMMMMMh `MMs
NMy hMMMMMMM+/: `MMMMMMMh -//yy/
NMy ymmMMMMMMMy .......................` `MMMMMMMh yMN
NMy ``-MMMMMMMy mNNNNNNNNNNNNNNNNNNNNNNo `MMMMMMMh yMN
-:+hh- .MMMMMMMNhhhhhhhhhhMMMMMMMMMMMMMMMMMMMMMMMmhhhhhhhhhdMMMMMMMh yMN
/MM: .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMys+ yMN
/MM: .ddNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNdd. yMN
/MM: ``sMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMs`` yMN
/MM: .----oMMMMMMMs----+MMMMMMMMMMMMMMM+----sMMMMMMMMMN--. yMN
.oooo+ .oooosMMo .oomMMMMMMMMMmoo. oMMsooooooo .ooooo
hMm .MMs-- hMMMMMMMMMh --sMM. :MM/
hNd`` .NNNMM.`` hMMMMMMMMMh ``.MMNNN. ``:NN/
.-:dd/ --yMMmds hMMMMMMMMMh sdmMMy-- hdy--`
.MM+ -++++ossmMMMMMMMMMmssmMN++- mMh
.MM+ :MMMMMMMMMMMMMMMmhh .::yhs
.NNo`` :MMMMMMMMMMMMMMM: ``oNN.
..omm` :MMMMMMMMMMMMMMM: `mmo..
sMM` .//dMMMMMMMMMMMM: `MMs
/hh/:- hMMhhhhhMMMMM: -:/hh/
mmy.. hMN NMMMM: ..ymm
`./mm- hMN NMMMM: -mm/.`
.//sys hMN NMd//` :MM/
hMm hMN/////NMh //+yy-
ymd..... ymNMMMMMNmy `..dmy
``.NNNNN` ``.MMMMM.`` +NN.``
:::::hho ::::: ohhhho::
oso++++/ .++ossss:
:mmmmd......./mm:
`NNNNNNNy
-------.
`-------` `----. `-- `--` ----- --` `-------` .---------` `----- `-------`
/MMMNMMM+ ``/NNMMm sMM``/MM: .MMMNN` `.MMo`` :MMMNMMMo mMMMMMMMMMs `:NNMMN +MMMNMMM/
/MM/.:MM+ dms..dMm sMMmmmMM: .MMs.. smmMMNmm` :MM+.-MMo mMMMMMMMMMs hmy..hMN +MM:./MM/
/MMysyMM+ NMy hMm sMMMMMMM: .MMdss` hMN++hMM` :MMhssMMo mMMMMMMMMMs mMh yMN +MMysyMM/
/MMdhdMM+ NMy hMm sMMMMMMM: .MMmhh` hMN::yMM` :MMmhdMMo mMNhhNMMMMs mMh yMN +MMdhdMM/
/MM- -MM+ NMy dMm sMMMMMMM: .MMo hMMMMMMM` :MM: `MMo mMh yMMMMs mMd yMN +MM. -MM/
/MMNNNMM+ NMMNNMMm sMM.`/MM: .MMNNN` hMN``sMM` :MM: `MMo mMh yMMMMs mMMNNMMN +MM. -MM/
.///////. //////// -// .//` `///// :// -//` .//. //- //: :////- //////// .//` `//.
Import Bone Armor in your map!
Step 1 - Allow creation of unknown variables - (Understand that this is absolutely nessesary)
1A - Under Preferences, make sure you have "Automatically create unknown variables while pasting trigger data" checked
Step 2 - Install Bribe's Damage Engine into your map:
2A - Copy Pasta Bribe's Damage Engine Folder into your trigger editor
Step 3 - Install Bone Armor
4A Copy Pasta the Bone Armor folder into your trigger editor
4B Copy the Bone Armor Ability from Object Editor, and set it to the variable BAmr_SPELL
4C Copy the Bone Armor Buff from Object Editor, and set it to the variable BArmr_BUFF
function castBoneArmorOnAllies takes nothing returns nothing
local unit sourceUnit = GetTriggerUnit()
local unit targetUnit = GetEnumUnit()
local unit dummyUnit
local player sourcePlayer = GetOwningPlayer(sourceUnit)
local location targetLocation
if ( IsUnitAlly(targetUnit, sourcePlayer) == true ) then
set targetLocation = GetUnitLoc(targetUnit)
call CreateNUnitsAtLoc(1, 'n012', sourcePlayer, targetLocation, bj_UNIT_FACING)
set dummyUnit = GetLastCreatedUnit()
call ModifyHeroStat( bj_HEROSTAT_STR, dummyUnit, bj_MODIFYMETHOD_SET, GetHeroStatBJ(bj_HEROSTAT_STR, sourceUnit, true) )
call ModifyHeroStat( bj_HEROSTAT_AGI, dummyUnit, bj_MODIFYMETHOD_SET, GetHeroStatBJ(bj_HEROSTAT_AGI, sourceUnit, true) )
call ModifyHeroStat( bj_HEROSTAT_INT, dummyUnit, bj_MODIFYMETHOD_SET, GetHeroStatBJ(bj_HEROSTAT_INT, sourceUnit, true) )
call UnitAddAbilityBJ( 'A04Z', dummyUnit )
call IssueTargetOrderBJ( dummyUnit, "innerfire", targetUnit )
call RemoveUnit(dummyUnit)
call RemoveLocation(targetLocation)
endif
endfunction
function Trig_BoneArmorAOE_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A00B' ) ) then
return false
endif
return true
endfunction
function Trig_BoneArmorAOE_Actions takes nothing returns nothing
local unit sourceUnit = GetTriggerUnit()
local location sourceLocation = GetUnitLoc(sourceUnit)
local group unitsInRange = GetUnitsInRangeOfLocAll(500.00, sourceLocation)
call ForGroupBJ( unitsInRange, function castBoneArmorOnAllies )
call DestroyGroup(unitsInRange)
endfunction
//===========================================================================
function InitTrig_BoneArmorAOE_JASS takes nothing returns nothing
set gg_trg_BoneArmorAOE_JASS = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_BoneArmorAOE_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_BoneArmorAOE_JASS, Condition( function Trig_BoneArmorAOE_Conditions ) )
call TriggerAddAction( gg_trg_BoneArmorAOE_JASS, function Trig_BoneArmorAOE_Actions )
endfunction
function onBlzEndUnitAbilityCooldown takes unit whichUnit, integer abilCode returns nothing
local integer playerIndex = GetConvertedPlayerId(GetOwningPlayer(whichUnit))
local integer loopIndex = 0
if ( (IsTriggerEnabled(gg_trg_DualHeroChange) == true) and (playerIndex <=8) and (whichUnit == udg_LightHeroes[playerIndex] ) and (udg_LightHeroes[playerIndex+8] != null) ) then
// Only reset cooldown of ability for 2nd hero if it is an item ability
loop
if ( abilCode == udg_ItemAbilities[loopIndex] ) then
call BlzEndUnitAbilityCooldown(udg_LightHeroes[playerIndex+8], abilCode)
exitwhen true
endif
exitwhen loopIndex > udg_ItemAbilityCount
endloop
endif
endfunction
hook BlzEndUnitAbilityCooldown onBlzEndUnitAbilityCooldown
function onBlzSetUnitAbilityCooldown takes unit whichUnit, integer abilId, integer level, real cooldown returns nothing
local integer playerIndex = GetConvertedPlayerId(GetOwningPlayer(whichUnit))
local integer loopIndex = 0
if ( (IsTriggerEnabled(gg_trg_DualHeroChange) == true) and (playerIndex <=8) and (whichUnit == udg_LightHeroes[playerIndex] ) and (udg_LightHeroes[playerIndex+8] != null) ) then
// Only modify cooldown of ability for 2nd hero if it is an item ability
loop
if ( abilId == udg_ItemAbilities[loopIndex] ) then
call BlzSetUnitAbilityCooldown(udg_LightHeroes[playerIndex+8], abilId, level, cooldown)
exitwhen true
endif
exitwhen loopIndex > udg_ItemAbilityCount
endloop
endif
endfunction
hook BlzSetUnitAbilityCooldown onBlzSetUnitAbilityCooldown
function onUnitResetCooldown takes unit whichUnit returns nothing
local integer playerIndex = GetConvertedPlayerId(GetOwningPlayer(whichUnit))
if ( (IsTriggerEnabled(gg_trg_DualHeroChange) == true) and (playerIndex <=8) and (whichUnit == udg_LightHeroes[playerIndex] ) and (udg_LightHeroes[playerIndex+8] != null) ) then
// Also reset all cooldowns of 2nd hero
call UnitResetCooldown(udg_LightHeroes[playerIndex+8])
endif
endfunction
hook UnitResetCooldown onUnitResetCooldown
function Trig_FanOfKnives_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AEfk' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AEfk', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Ewar' ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
return true
endfunction
function Trig_FanOfKnives_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
call TriggerSleepAction( 1.00 )
call SetPlayerAbilityAvailableBJ( false, 'AEfk', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A075', casterPlayer )
call IssueImmediateOrderBJ( casterUnit, "fanofknives" )
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A075', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AEfk', casterPlayer )
endfunction
//===========================================================================
function InitTrig_FanOfKnives_JASS takes nothing returns nothing
set gg_trg_FanOfKnives_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_FanOfKnives_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_FanOfKnives_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_FanOfKnives_JASS, Condition( function Trig_FanOfKnives_Conditions ) )
call TriggerAddAction( gg_trg_FanOfKnives_JASS, function Trig_FanOfKnives_Actions )
endfunction
function Trig_Hex_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A03F' ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Oshd' ) ) then
return false
endif
if ( not ( GetHeroLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
if ( not ( IsUnitPausedBJ(GetSpellTargetUnit()) == false ) ) then
return false
endif
return true
endfunction
function Trig_Hex_Actions takes nothing returns nothing
local unit target = GetSpellTargetUnit()
local location targetLoc = GetUnitLoc(target)
local location tempLoc
local player sourcePlayer = GetOwningPlayer(GetTriggerUnit())
local integer index = 1
loop
exitwhen index > 6
call TriggerSleepAction( 0.10 )
set tempLoc = PolarProjectionBJ(targetLoc, 200.00, ( 60.00 * I2R(index) ))
call CreateNUnitsAtLocFacingLocBJ( 1, 'o000', sourcePlayer, tempLoc, targetLoc )
call RemoveLocation(tempLoc)
call UnitApplyTimedLifeBJ( 8.00, 'Bhwd', GetLastCreatedUnit() )
set index = index + 1
endloop
call RemoveLocation(targetLoc)
set sourcePlayer = null
set tempLoc = null
set targetLoc = null
set target = null
endfunction
//===========================================================================
function InitTrig_Hex_JASS takes nothing returns nothing
set gg_trg_Hex_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_Hex_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Hex_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Hex_JASS, Condition( function Trig_Hex_Conditions ) )
call TriggerAddAction( gg_trg_Hex_JASS, function Trig_Hex_Actions )
endfunction
function Trig_Polymorph_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'A023' ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Ewar' ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
return true
endfunction
function Trig_Polymorph_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
local unit targetUnit = GetSpellTargetUnit()
local location targetLoc = GetUnitLoc(targetUnit)
local location tempLoc
local integer index = 1
local integer indexEnd = 6
call TriggerSleepAction( 0.10 )
call PauseUnitBJ( true, targetUnit )
call DisableTrigger( GetTriggeringTrigger() )
call DisableTrigger( gg_trg_ShadowStrike_JASS )
loop
exitwhen index > indexEnd
call AddSpellEffectTargetById('AEbl', EFFECT_TYPE_AREA_EFFECT, casterUnit, "origin")
set tempLoc = PolarProjectionBJ(targetLoc, 350.00, ( 60.00 * I2R(index) ))
call SetUnitPositionLocFacingLocBJ( casterUnit, tempLoc, targetLoc )
call RemoveLocation(tempLoc)
call SetPlayerAbilityAvailableBJ( false, 'AEsh', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A078', casterPlayer )
call IssueTargetOrderBJ( casterUnit, "shadowstrike", targetUnit )
call TriggerSleepAction( 1.0 )
call SetPlayerAbilityAvailableBJ( false, 'A078', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AEsh', casterPlayer )
set index = index + 1
endloop
call RemoveLocation(targetLoc)
call EnableTrigger( gg_trg_ShadowStrike_JASS )
call EnableTrigger( GetTriggeringTrigger() )
call PauseUnitBJ( false, targetUnit )
set tempLoc = null
set targetLoc = null
set targetUnit = null
set casterPlayer = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_Polymorph_JASS takes nothing returns nothing
set gg_trg_Polymorph_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_Polymorph_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Polymorph_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_Polymorph_JASS, Condition( function Trig_Polymorph_Conditions ) )
call TriggerAddAction( gg_trg_Polymorph_JASS, function Trig_Polymorph_Actions )
endfunction
function ConvertPolarCoordToLocation takes location tL,real TL,real uL returns location
return Location(GetLocationX(tL)+TL*Cos(uL*bj_DEGTORAD),GetLocationY(tL)+TL*Sin(uL*bj_DEGTORAD))
endfunction
function RealmOfSoulPeriodic_Actions takes nothing returns nothing
local trigger realmOfSoulPeriodicTrigger = GetTriggeringTrigger()
local unit dummyUnit = LoadUnitHandle(udg_RosHashtable,GetHandleId(realmOfSoulPeriodicTrigger),StringHashBJ("DummyUnit"))
local location dummyUnitLocation = GetUnitLoc(dummyUnit)
local location targetLocation = ConvertPolarCoordToLocation(dummyUnitLocation,100.,GetRandomReal(0,360))
call DebugLog(LVL_DEBUG, "RealmOfSoulPeriodic_Actions")
call IssuePointOrderLocBJ( dummyUnit, "carrionswarm", targetLocation )
call RemoveLocation(dummyUnitLocation)
call RemoveLocation(targetLocation)
set targetLocation = null
set dummyUnitLocation = null
set dummyUnit = null
set realmOfSoulPeriodicTrigger = null
endfunction
function Trig_RealmOfSoul_Conditions takes nothing returns boolean
return( GetSpellAbilityId()=='A04X' )
endfunction
function Trig_RealmOfSoul_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local real spellDuration = (5.+(I2R(GetUnitAbilityLevelSwapped('A04X', casterUnit))*5.))
local unit dummyUnit
local integer dummyUnitId
local location casterUnitLocation = GetUnitLoc(casterUnit)
local trigger realmOfSoulPeriodicTrigger = CreateTrigger()
call DebugLog(LVL_DEBUG, "RealOfSoul_Actions")
// Create a dummy unit
call CreateNUnitsAtLoc( 1, 'n010', GetOwningPlayer(casterUnit), casterUnitLocation, bj_UNIT_FACING )
set dummyUnit = bj_lastCreatedUnit
set dummyUnitId = GetHandleId(dummyUnit)
call SetUnitAbilityLevelSwapped( 'A04Y', dummyUnit, GetUnitAbilityLevelSwapped('A04X', casterUnit) )
// Save the data required for the periodic and end triggers
call SaveUnitHandle(udg_RosHashtable,GetHandleId(dummyUnit),StringHashBJ("CasterUnit"),casterUnit) // Caster unit
call SaveUnitHandle(udg_RosHashtable,GetHandleId(realmOfSoulPeriodicTrigger),StringHashBJ("DummyUnit"),dummyUnit) // Dummy unit
// Execute the periodic trigger
call TriggerRegisterTimerEvent(realmOfSoulPeriodicTrigger,0.2,true)
call TriggerAddCondition(realmOfSoulPeriodicTrigger,Condition(function RealmOfSoulPeriodic_Actions))
call TriggerEvaluate(realmOfSoulPeriodicTrigger)
// Wait for its end then clean variables
call TriggerSleepAction(spellDuration)
call DisableTrigger(realmOfSoulPeriodicTrigger)
call RemoveSavedHandle(udg_RosHashtable,GetHandleId(dummyUnit),StringHashBJ("CasterUnit"))
call RemoveSavedHandle(udg_RosHashtable,GetHandleId(realmOfSoulPeriodicTrigger),StringHashBJ("DummyUnit"))
call RemoveUnit(dummyUnit)
call DestroyTrigger(realmOfSoulPeriodicTrigger)
call RemoveLocation(casterUnitLocation)
set realmOfSoulPeriodicTrigger = null
set casterUnitLocation = null
set dummyUnit = null
set casterUnit = null
endfunction
function Trig_RealmOfSoulDummyCastFinished_Conditions takes nothing returns boolean
return( GetSpellAbilityId()=='A04Y' )
endfunction
function Trig_RealmOfSoulDummyCastFinished_Actions takes nothing returns nothing
local unit dummyUnit = GetSpellAbilityUnit()
local unit casterUnit = LoadUnitHandle(udg_RosHashtable,GetHandleId(dummyUnit),StringHashBJ("CasterUnit"))
local location casterUnitLocation = GetUnitLoc(casterUnit)
call DebugLog(LVL_DEBUG, "Trig_RealmOfSoulDummyCastFinished_Actions")
call SetUnitPositionLoc(dummyUnit,casterUnitLocation)
call RemoveLocation(casterUnitLocation)
set casterUnitLocation = null
set casterUnit = null
set dummyUnit = null
endfunction
//===========================================================================
function InitTrig_RealmOfSoul takes nothing returns nothing
local trigger Trig_RealmOfSoulDummyCastFinished = CreateTrigger()
set gg_trg_RealmOfSoul = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( gg_trg_RealmOfSoul, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_RealmOfSoul, Condition(function Trig_RealmOfSoul_Conditions) )
call TriggerAddAction( gg_trg_RealmOfSoul, function Trig_RealmOfSoul_Actions )
call TriggerRegisterAnyUnitEventBJ( Trig_RealmOfSoulDummyCastFinished ,EVENT_PLAYER_UNIT_SPELL_FINISH )
call TriggerAddCondition( Trig_RealmOfSoulDummyCastFinished, Condition(function Trig_RealmOfSoulDummyCastFinished_Conditions))
call TriggerAddAction( Trig_RealmOfSoulDummyCastFinished, function Trig_RealmOfSoulDummyCastFinished_Actions )
endfunction
function Trig_ShadowStrike_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AEsh' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AEsh', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Ewar' ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
return true
endfunction
function Trig_ShadowStrike_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local unit targetUnit = GetSpellTargetUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'AEsh', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A078', casterPlayer )
call IssueTargetOrderBJ( casterUnit, "shadowstrike", targetUnit )
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A078', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AEsh', casterPlayer )
set casterPlayer = null
set targetUnit = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_ShadowStrike_JASS takes nothing returns nothing
set gg_trg_ShadowStrike_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_ShadowStrike_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_ShadowStrike_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_ShadowStrike_JASS, Condition( function Trig_ShadowStrike_Conditions ) )
call TriggerAddAction( gg_trg_ShadowStrike_JASS, function Trig_ShadowStrike_Actions )
endfunction
function Trig_ShockWave_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AOsh' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AOsh', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not ( (GetUnitTypeId(GetTriggerUnit()) == 'Otch') or (GetUnitTypeId(GetTriggerUnit()) == 'O008') ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
if ( not ( UnitHasBuffBJ(GetTriggerUnit(), 'B00N') == true ) ) then
return false
endif
return true
endfunction
function Trig_ShockWave_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
local unit targetUnit = GetSpellTargetUnit()
local location targetLocation = GetSpellTargetLoc()
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'AOsh', GetOwningPlayer(GetTriggerUnit()) )
call SetPlayerAbilityAvailableBJ( true, 'A04Q', GetOwningPlayer(GetTriggerUnit()) )
if ( targetUnit != null ) then
call IssueTargetOrderBJ( casterUnit, "carrionswarm", targetUnit)
elseif ( targetLocation != null ) then
call IssuePointOrderLocBJ( casterUnit, "carrionswarm", targetLocation)
endif
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A04Q', GetOwningPlayer(GetTriggerUnit()) )
call SetPlayerAbilityAvailableBJ( true, 'AOsh', GetOwningPlayer(GetTriggerUnit()) )
set targetLocation = null
set targetUnit = null
set casterPlayer = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_ShockWave_JASS takes nothing returns nothing
set gg_trg_ShockWave_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_ShockWave_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_ShockWave_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_ShockWave_JASS, Condition( function Trig_ShockWave_Conditions ) )
call TriggerAddAction( gg_trg_ShockWave_JASS, function Trig_ShockWave_Actions )
endfunction
function Trig_StormBolt_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AHtb' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AHtb', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Hmkg' ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
return true
endfunction
function Trig_StormBolt_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local unit targetUnit = GetSpellTargetUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'AHtb', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A02V', casterPlayer )
call IssueTargetOrderBJ( casterUnit, "creepthunderbolt", targetUnit )
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A02V', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AHtb', casterPlayer )
set casterPlayer = null
set targetUnit = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_StormBolt_JASS takes nothing returns nothing
set gg_trg_StormBolt_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_StormBolt_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_StormBolt_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_StormBolt_JASS, Condition( function Trig_StormBolt_Conditions ) )
call TriggerAddAction( gg_trg_StormBolt_JASS, function Trig_StormBolt_Actions )
endfunction
function Trig_ThunderClap_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AHtc' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AHtc', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Hmkg' ) ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
return true
endfunction
function Trig_ThunderClap_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'AHtc', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A04P', casterPlayer )
call IssueImmediateOrderBJ( casterUnit, "creepthunderclap" )
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A04P', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AHtc', casterPlayer )
set casterPlayer = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_ThunderClap_JASS takes nothing returns nothing
set gg_trg_ThunderClap_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_ThunderClap_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_ThunderClap_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_ThunderClap_JASS, Condition( function Trig_ThunderClap_Conditions ) )
call TriggerAddAction( gg_trg_ThunderClap_JASS, function Trig_ThunderClap_Actions )
endfunction
function Trig_WarStomp_Func009C takes nothing returns boolean
if ( ( GetUnitTypeId(GetTriggerUnit()) == 'Otch' ) ) then
return true
endif
if ( ( GetUnitTypeId(GetTriggerUnit()) == 'O008' ) ) then
return true
endif
return false
endfunction
function Trig_WarStomp_Conditions takes nothing returns boolean
if ( not ( GetSpellAbilityId() == 'AOws' ) ) then
return false
endif
if ( not ( GetUnitAbilityLevelSwapped('AOws', GetTriggerUnit()) == 4 ) ) then
return false
endif
if ( not Trig_WarStomp_Func009C() ) then
return false
endif
if ( not ( GetUnitLevel(GetTriggerUnit()) >= 20 ) ) then
return false
endif
if ( not ( UnitHasBuffBJ(GetTriggerUnit(), 'B00N') == true ) ) then
return false
endif
return true
endfunction
function Trig_WarStomp_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local player casterPlayer = GetOwningPlayer(casterUnit)
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'AOws', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'A01O', casterPlayer )
call IssueImmediateOrderBJ( casterUnit, "creepthunderclap" )
call TriggerSleepAction( 0.10 )
call SetPlayerAbilityAvailableBJ( false, 'A01O', casterPlayer )
call SetPlayerAbilityAvailableBJ( true, 'AOws', casterPlayer )
set casterPlayer = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_WarStomp_JASS takes nothing returns nothing
set gg_trg_WarStomp_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_WarStomp_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_WarStomp_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_WarStomp_JASS, Condition( function Trig_WarStomp_Conditions ) )
call TriggerAddAction( gg_trg_WarStomp_JASS, function Trig_WarStomp_Actions )
endfunction
function Trig_MuradinClap_Conditions takes nothing returns boolean
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Hmbr' ) ) then
return false
endif
if ( not ( GetSpellAbilityId() == 'AHtc' ) ) then
return false
endif
return true
endfunction
function Trig_MuradinClap_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
call PlaySoundOnUnitBJ( gg_snd_MuradinDoubleClap, 100, casterUnit )
call TriggerSleepAction( 0.10 )
call UnitAddAbilityBJ( 'A04P', casterUnit )
call IssueImmediateOrder(casterUnit,"creepthunderclap")
call TriggerSleepAction( 0.50 )
call UnitRemoveAbilityBJ( 'A04P', casterUnit )
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_MuradinClap_JASS takes nothing returns nothing
set gg_trg_MuradinClap_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_MuradinClap_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_MuradinClap_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_MuradinClap_JASS, Condition( function Trig_MuradinClap_Conditions ) )
call TriggerAddAction( gg_trg_MuradinClap_JASS, function Trig_MuradinClap_Actions )
endfunction
function Trig_MuradinBolt_Conditions takes nothing returns boolean
if ( not ( GetUnitTypeId(GetTriggerUnit()) == 'Hmbr' ) ) then
return false
endif
if ( not ( GetSpellAbilityId() == 'AHtb' ) ) then
return false
endif
return true
endfunction
function Trig_MuradinBolt_Actions takes nothing returns nothing
local unit casterUnit = GetTriggerUnit()
local unit targetUnit = GetSpellTargetUnit()
call PlaySoundOnUnitBJ( gg_snd_MuradinDoubleBolt, 100, casterUnit )
call TriggerSleepAction( 0.10 )
call UnitAddAbilityBJ( 'A058', casterUnit )
call IssueTargetOrderBJ(casterUnit,"creepthunderbolt",targetUnit)
call TriggerSleepAction( 0.50 )
call UnitRemoveAbilityBJ( 'A058', casterUnit )
set targetUnit = null
set casterUnit = null
endfunction
//===========================================================================
function InitTrig_MuradinBolt_JASS takes nothing returns nothing
set gg_trg_MuradinBolt_JASS = CreateTrigger( )
call DisableTrigger( gg_trg_MuradinBolt_JASS )
call TriggerRegisterAnyUnitEventBJ( gg_trg_MuradinBolt_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_MuradinBolt_JASS, Condition( function Trig_MuradinBolt_Conditions ) )
call TriggerAddAction( gg_trg_MuradinBolt_JASS, function Trig_MuradinBolt_Actions )
endfunction