function IsGrounded takes unit u returns boolean
return (not IsUnitType(u, UNIT_TYPE_FLYING) or GetUnitAbilityLevel(u, 'B00O') > 0 or GetUnitAbilityLevel(u, 'Bwea') > 0 or GetUnitAbilityLevel(u, 'Bena') > 0)
endfunction
function IsHuman takes unit u returns boolean
local integer ut = GetUnitTypeId(u)
//return (GetPlayerRace(GetOwningPlayer(u)) == RACE_HUMAN and ut != 'hrif' and ut != 'hmtm' and ut != 'hgyr' and ut != 'hgry' and ut != 'hmpr' and ut != 'hsor' and ut != 'hspt' and ut != 'hdhw')
return ut == 'Hpal' or ut == 'Hamg' or ut == 'hpea' or ut == 'hmil' or ut == 'hfoo' or ut == 'hkni' or ut == 'h004' or ut == 'h003' or ut == 'h00B' or ut == 'h00J' or ut == 'h00E' or ut == 'o001' or ut == 'o004' or ut == 'o005' or ut == 'o000' or ut == 'H001' or ut == 'H002' or ut == 'H007' or ut == 'h00K'
endfunction
function IsTower takes unit u returns boolean
local integer it = GetUnitTypeId(u)
return it == 'hgtw' or it == 'hctw' or it == 'hatw' or it == 'owtw' or it == 'uzg1' or it == 'uzg2' or it == 'etrp'
endfunction
function DSpellFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and not IsPlayerAlly(GetOwningPlayer(udg_TempUnit), p2)
endfunction
function SSpellFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and IsGrounded(udg_TempUnit) and not IsPlayerAlly(GetOwningPlayer(udg_TempUnit), p2)
endfunction
function USpellFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(udg_TempUnit, UNIT_TYPE_STRUCTURE) and not IsPlayerAlly(GetOwningPlayer(udg_TempUnit), p2)
endfunction
function OrganicFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(udg_TempUnit, UNIT_TYPE_MECHANICAL) and not IsUnitType(udg_TempUnit, UNIT_TYPE_STRUCTURE) and not IsPlayerAlly(GetOwningPlayer(udg_TempUnit), p2)
endfunction
function BOrganicFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(udg_TempUnit, UNIT_TYPE_MECHANICAL) and not IsUnitType(udg_TempUnit, UNIT_TYPE_STRUCTURE)
endfunction
function GSpellFilter takes player p2 returns boolean
return GetUnitAbilityLevel(udg_TempUnit, 'Avul') == 0 and GetUnitState(udg_TempUnit, UNIT_STATE_LIFE) > 0 and not IsUnitType(udg_TempUnit, UNIT_TYPE_MAGIC_IMMUNE) and IsGrounded(udg_TempUnit) and not IsUnitType(udg_TempUnit, UNIT_TYPE_STRUCTURE) and not IsPlayerAlly(GetOwningPlayer(udg_TempUnit), p2)
endfunction
function MAreaODamage takes unit fker, real amount, real exe, real range, string targfx, real nx, real ny, attacktype at returns nothing
local group g = CreateGroup()
local unit vic
local real total
local player p1 = GetOwningPlayer(fker)
local integer id1 = GetPlayerId(p1) + 1
call GroupEnumUnitsInRange(g, nx, ny, range + udg_MaxColl, null)
loop
set vic = FirstOfGroup(g)
call GroupRemoveUnit(g, vic)
exitwhen vic == null
if IsUnitInRangeXY(vic, nx, ny, range) then
set udg_TempUnit = vic
if BOrganicFilter(p1) then
set total = amount
if GetUnitLifePercent(vic) < 40. then
set total = total * exe
endif
//set udg_NextDamageType = 2
call UnitDamageTarget( fker, vic, total, false, false, at, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget( targfx, vic, "chest" ))
endif
endif
endloop
call DestroyGroup(g)
set g = null
set p1 = null
set vic = null
endfunction
function MAreaDamage takes unit fker, real amount, real exe, real range, string targfx, real nx, real ny, attacktype at returns nothing
local group g = CreateGroup()
local unit vic
local real total
local player p1 = GetOwningPlayer(fker)
local integer id1 = GetPlayerId(p1) + 1
call GroupEnumUnitsInRange(g, nx, ny, range + udg_MaxColl, null)
loop
set vic = FirstOfGroup(g)
call GroupRemoveUnit(g, vic)
exitwhen vic == null
if IsUnitInRangeXY(vic, nx, ny, range) then
set udg_TempUnit = vic
if GSpellFilter(p1) then
set total = amount
if GetUnitLifePercent(vic) < 40. then
set total = total * exe
endif
//set udg_NextDamageType = 2
call UnitDamageTarget( fker, vic, total, false, false, at, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget( targfx, vic, "chest" ))
endif
endif
endloop
call DestroyGroup(g)
set g = null
set p1 = null
set vic = null
endfunction
function MAreaDamageS takes unit fker, real amount, real exe, real range, string targfx, real nx, real ny, attacktype at returns nothing
local group g = CreateGroup()
local unit vic
local real total
local player p1 = GetOwningPlayer(fker)
local integer id1 = GetPlayerId(p1) + 1
call GroupEnumUnitsInRange(g, nx, ny, range + udg_MaxColl, null)
loop
set vic = FirstOfGroup(g)
call GroupRemoveUnit(g, vic)
exitwhen vic == null
if IsUnitInRangeXY(vic, nx, ny, range) then
set udg_TempUnit = vic
if SSpellFilter(p1) then
set total = amount
if GetUnitLifePercent(vic) < 40. then
set total = total * exe
endif
//set udg_NextDamageType = 2
call UnitDamageTarget( fker, vic, total, false, false, at, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget( targfx, vic, "chest" ))
endif
endif
endloop
call DestroyGroup(g)
set g = null
set p1 = null
set vic = null
endfunction
function Distance takes real x1, real y1, real x2, real y2 returns real
return SquareRoot(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
endfunction
Name | Type | is_array | initial_value |
A | integervar | No | |
A_Index | integer | No | |
AfterDamageEvent | real | No | |
AI_Difficulty | integer | Yes | |
AMSAmount | real | Yes | |
AOEDamageEvent | real | No | |
B | integer | No | |
C | integervar | No | |
ClearDamageEvent | trigger | No | |
CP_HiddenItems | item | Yes | |
CP_HiddenItemsIndex | integer | No | |
CP_Item | item | No | |
CP_PointIsWalkable | boolean | No | |
CP_Rect | rect | No | |
Crit_Total | real | Yes | |
CritDid | real | Yes | |
DAMAGE_FACTOR_BRACERS | real | No | |
DAMAGE_FACTOR_ELUNES | real | No | |
DAMAGE_FACTOR_ETHEREAL | real | No | |
DamageAdd | real | No | |
DamageBlockingAbility | abilcode | No | |
DamageEvent | real | No | |
DamageEventAmount | real | No | |
DamageEventAOE | integer | No | |
DamageEventAOEGroup | group | No | |
DamageEventLevel | integer | No | |
DamageEventOverride | boolean | No | |
DamageEventPrevAmt | real | No | |
DamageEventSource | unit | No | |
DamageEventsWasted | integer | No | |
DamageEventTarget | unit | No | |
DamageEventTrigger | trigger | No | |
DamageEventType | integer | No | |
DamageMod | real | No | |
DamageModifierEvent | real | No | |
DamageTypeBlocked | integer | No | |
DamageTypeCriticalStrike | integer | No | |
DamageTypeExplosive | integer | No | |
DamageTypeHeal | integer | No | |
DamageTypeReduced | integer | No | |
DebugOn | boolean | No | |
DmgEvBracers | itemcode | No | |
DmgEvMana | real | No | |
DmgEvManaMult | real | No | |
DmgEvMSlvl | integer | No | |
DmgEvRecursionN | integer | No | |
DmgEvRunning | boolean | No | |
DmgEvStarted | boolean | No | |
DmgEvTimer | timer | No | |
DmgEvTrig | trigger | No | |
EnhancedDamageTarget | unit | No | |
FuckOff | boolean | Yes | |
GarithosBitches | force | No | |
GarithosFirsts | boolean | Yes | |
Gary_F | unit | Yes | |
Gary_PnP | unit | Yes | |
GaryTs_C | integer | Yes | |
GBats | integer | Yes | |
GFacts | integer | Yes | |
GFats | integer | Yes | |
GForges | integer | Yes | |
GForts | integer | Yes | |
GGars | integer | Yes | |
GIRs | integer | Yes | |
GJavs | integer | Yes | |
GTechs | integer | Yes | |
GTechs01 | integer | Yes | |
GTGs | integer | Yes | |
GWorkers | integer | Yes | |
HideDamageFrom | boolean | Yes | |
IsDamageSpell | boolean | No | |
KB3D_Accel | real | No | |
KB3D_AllowOutSiding | boolean | No | |
KB3D_Angle | real | No | |
KB3D_AoE | real | No | |
KB3D_AoEDamage | real | No | |
KB3D_AoEEndDamage | real | No | |
KB3D_AoEEndFx | string | No | |
KB3D_AoEKB | boolean | No | |
KB3D_AoEKB_Power | real | No | |
KB3D_Arc | real | No | |
KB3D_Attach | string | No | |
KB3D_AttackType | attacktype | No | |
KB3D_B | boolean | No | |
KB3D_Bounce_Fx | string | No | |
KB3D_Bounce_Power | real | No | |
KB3D_Bounce_Target | boolean | No | |
KB3D_Bounce_Unit | boolean | No | |
KB3D_Counter | integer | No | |
KB3D_D_ALLY | boolean | No | |
KB3D_D_ENEMY | boolean | No | |
KB3D_D_FLYING | boolean | No | |
KB3D_D_MAGIC_IMMINUE | boolean | No | |
KB3D_D_MECHANICAL | boolean | No | |
KB3D_D_RESISTANT | boolean | No | |
KB3D_D_STRUCTURE | boolean | No | |
KB3D_Damager | unit | No | |
KB3D_DamageType | damagetype | No | |
KB3D_DestroyDestructables | boolean | No | |
KB3D_DestroyTree | boolean | No | |
KB3D_DisableUnit | boolean | No | |
KB3D_EndFx | string | No | |
KB3D_EndisNormal | boolean | No | |
KB3D_EndisUnit | boolean | No | |
KB3D_EndisUnpathable | boolean | No | |
KB3D_EndOnObstacle | boolean | No | |
KB3D_EndOnTargetBounce | boolean | No | |
KB3D_EndTrigger | trigger | No | |
KB3D_EndUnit | unit | No | |
KB3D_EndwhenDead | boolean | No | |
KB3D_EndWhenHit | boolean | No | |
KB3D_FaceAngle | boolean | No | |
KB3D_Flyover | boolean | No | |
KB3D_Flyover_Duration | real | No | |
KB3D_Fx | string | No | |
KB3D_Fx_Attach | string | No | |
KB3D_g | group | No | |
KB3D_GroundDamage | boolean | No | |
KB3D_HA | hashtable | No | |
KB3D_Harvester | unit | No | |
KB3D_HomingMissile | boolean | No | |
KB3D_iKB | boolean | No | |
KB3D_ImpactDamage | real | No | |
KB3D_Instances | integer | No | |
KB3D_JumpOverCliff | boolean | No | |
KB3D_KBTarget | boolean | No | |
KB3D_KillatEnd | boolean | No | |
KB3D_KillatTime | real | No | |
KB3D_KillifOutSider | boolean | No | |
KB3D_KillWhenHit | boolean | No | |
KB3D_Line_Fx | string | No | |
KB3D_LineDamage | real | No | |
KB3D_LoopDamage | real | No | |
KB3D_Paused | boolean | No | |
KB3D_PausedReg | boolean | No | |
KB3D_PauseID | integer | No | |
KB3D_Range | real | No | |
KB3D_Reals | real | Yes | |
KB3D_Registration | trigger | No | |
KB3D_RemoveUnit | unit | No | |
KB3D_Speed | real | No | |
KB3D_Speed_Changer | boolean | No | |
KB3D_StopTime | real | No | |
KB3D_TargetDamage | real | No | |
KB3D_Targeted_Unit | unit | No | |
KB3D_Time | real | No | |
KB3D_Timer | timer | No | |
KB3D_TrailFx | string | No | |
KB3D_Unit | unit | No | |
KB3D_UnpathableStop | boolean | No | |
KB3D_Zoffset | real | No | |
LastDamageHP | real | No | |
LastDmgPrevAmount | real | Yes | |
LastDmgPrevType | integer | Yes | |
LastDmgSource | unit | Yes | |
LastDmgTarget | unit | Yes | |
LastDmgValue | real | Yes | |
LastDmgWasSpell | boolean | Yes | |
MaxColl | real | No | 256.00 |
MCamo_I | integer | No | |
MCamo_U | unit | Yes | |
MChal_I | integer | No | |
MChal_T | real | Yes | |
MChal_U1 | unit | Yes | |
MChal_U2 | unit | Yes | |
MDelB_A | real | Yes | |
MDelB_C | unit | Yes | |
MDelB_FXA | string | Yes | |
MDelB_FXB | string | Yes | |
MDelB_FXS | real | Yes | |
MDelB_I | integer | No | |
MDelB_ID | integer | Yes | |
MDelB_R | real | Yes | |
MDelB_T | real | Yes | |
MDelB_X | real | Yes | |
MDelB_Y | real | Yes | |
MLB_C | unit | Yes | |
MLB_I | integer | No | |
MLB_T | real | Yes | |
MLB_U | unit | Yes | |
MLite_Dur | real | Yes | |
MLite_FadeIn | real | Yes | |
MLite_FadeOut | real | Yes | |
MLite_I | integer | No | |
MLite_L | lightning | Yes | |
MLite_U1 | unit | Yes | |
MLite_U2 | unit | Yes | |
MMC_C | unit | Yes | |
MMC_G | group | Yes | |
MMC_I | integer | No | |
MMM2_C | unit | Yes | |
MMM2_D | real | Yes | |
MMM2_I | integer | No | |
MMM3_Sounds | sound | Yes | |
MMM_C | unit | Yes | |
MMM_I | integer | No | |
MouseX | real | Yes | |
MouseY | real | Yes | |
MRecon_I | integer | No | |
MRecon_S | unit | Yes | |
MRecon_U | unit | Yes | |
MVan_C | unit | Yes | |
MVan_I | integer | No | |
MVan_R | real | Yes | |
MVan_Str | real | Yes | |
MVan_T | real | Yes | |
NamePool | string | Yes | |
NamePoolInt | integer | No | |
NextDamageOverride | boolean | No | |
NextDamageType | integer | No | |
Player_IsAI | boolean | Yes | |
PlayerAllies | force | Yes | |
PlayerGPM | integer | Yes | |
PlayerGRat | real | Yes | |
PlayerName | string | Yes | |
Set_Distance | real | No | |
SpellDamageAbility | abilcode | No | |
SpinS | real | Yes | |
SW_AbStr | string | No | |
SW_AffectAir | boolean | Yes | |
SW_AffectAlly | boolean | Yes | |
SW_AffectEnemy | boolean | Yes | |
SW_AffectGround | boolean | Yes | |
SW_AffectStructure | boolean | Yes | |
SW_Angle | real | No | |
SW_AreaCurrent | real | Yes | |
SW_AreaFinal | real | Yes | |
SW_AreaGrowth | real | Yes | |
SW_AreaInitial | real | Yes | |
SW_Attachment | string | No | |
SW_AttackType | attacktype | Yes | |
SW_Caster | unit | Yes | |
SW_Damage | real | Yes | |
SW_DamageType | damagetype | Yes | |
SW_DamageX | real | Yes | |
SW_Distance | real | Yes | |
SW_DistanceX | real | Yes | |
SW_Dummy | unit | Yes | |
SW_ExtraEffect | trigger | Yes | |
SW_ExtraEffectCheck | boolean | Yes | |
SW_ExtraEffectTarget | trigger | Yes | |
SW_ExtraEffectTargetCheck | boolean | Yes | |
SW_Group | group | No | |
SW_GroupDone | group | Yes | |
SW_Height | real | No | |
SW_Loop | integervar | No | |
SW_LoopingSfx | boolean | Yes | |
SW_Lvl | integer | Yes | |
SW_Max | integer | No | |
SW_NextPoint | location | Yes | |
SW_OneInstance | boolean | Yes | |
SW_Point | location | Yes | |
SW_Size | real | No | |
SW_Speed | real | Yes | |
SW_SpeedX | real | Yes | |
SW_Wave | effect | Yes | |
SW_WaveEffect | modelfile | Yes | |
SW_WaveEffectEnd | modelfile | Yes | |
SW_WaveEffectLoop | modelfile | Yes | |
TempFX | effect | No | |
TempGroup | group | No | |
TempPlayer | player | No | |
TempPlayers | player | Yes | |
TempPoint | location | No | |
TempPoints | location | Yes | |
TempReal | real | No | |
TempReals | real | Yes | |
TempString | string | No | |
TempText | texttag | No | |
TempUnit | unit | No | |
TempUnits | unit | Yes | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
UDummies | unit | Yes | |
UnitDamageRegistered | boolean | Yes | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No | |
UnitSpeedX | real | Yes | |
X | integer | No | |
Z | integer | No |
function Trig_Names_Actions takes nothing returns nothing
local integer c = 0
//set udg_Spell_Dmg_Constant = 0.03
// Names
set udg_NamePool[1] = "My Little War Criminal"
set udg_NamePool[2] = "Angela Mur'gul"
set udg_NamePool[3] = "Hausfrau"
set udg_NamePool[4] = "Bad or $ick Guy"
set udg_NamePool[5] = "Savage Bedfellow"
set udg_NamePool[6] = "My Regards"
set udg_NamePool[7] = "Wholesome Degenerate"
set udg_NamePool[8] = "Scarlet Bitch"
set udg_NamePool[9] = "Random Sellout"
set udg_NamePool[10] = "Citizen Shill"
set udg_NamePool[11] = "Red New Deal"
set udg_NamePool[12] = "Green New Pill"
set udg_NamePool[13] = "Hormonal_Misha"
set udg_NamePool[14] = "Manufactured Crisis"
set udg_NamePool[15] = "Winter Captain"
set udg_NamePool[16] = "wakanda4ever"
set udg_NamePool[17] = "You Have Been Slain"
set udg_NamePool[18] = "bolshevik69"
set udg_NamePool[19] = "Little Mao"
set udg_NamePool[20] = "My Effeminate Doctor"
set udg_NamePool[21] = "my moms bf"
set udg_NamePool[22] = "Good Hombre"
set udg_NamePool[23] = "Tony Dabs"
set udg_NamePool[24] = "deporter in chief"
set udg_NamePool[25] = "gib oil"
set udg_NamePool[26] = "CNN"
set udg_NamePool[27] = "Moonwalker"
set udg_NamePool[28] = "Captain Deadpool"
set udg_NamePool[29] = "Murdered by PROXY"
set udg_NamePool[30] = "Obomba"
set udg_NamePool[31] = "Stacy"
set udg_NamePool[32] = "Gageaux"
set udg_NamePool[33] = "SAD!"
set udg_NamePool[34] = "dont tread on muh feelings"
set udg_NamePool[35] = "Living Wage"
set udg_NamePool[36] = "Climate Change"
set udg_NamePool[37] = "Al Bore"
set udg_NamePool[38] = "so diverse!"
set udg_NamePool[39] = "Andres Me"
set udg_NamePool[40] = "Death/Amor"
set udg_NamePool[41] = "#feelthebern"
set udg_NamePool[42] = "Do You Wanna Build A Strawman?"
set udg_NamePool[43] = "Surprise.Buttseks"
set udg_NamePool[44] = "Russian Asset"
set udg_NamePool[45] = "American Puppy"
set udg_NamePool[46] = "BigWilly"
set udg_NamePool[47] = "DaddyRostov"
set udg_NamePool[48] = "EarlyBirdFucksTheWorm"
set udg_NamePool[49] = "Mickey Pence"
set udg_NamePool[50] = "Winter is Cumming"
set udg_NamePool[51] = "Fuck.Molly"
set udg_NamePool[52] = "oh nu"
set udg_NamePool[53] = "Kekwolf"
set udg_NamePool[54] = "Morgoth"
set udg_NamePool[55] = "Professional Pervert"
set udg_NamePool[56] = "Will Smith"
set udg_NamePool[57] = "Chunky Yogurt"
set udg_NamePool[58] = "Lord of the Memes"
set udg_NamePool[59] = "b4rbie$ucks"
set udg_NamePool[60] = "PUKE"
set udg_NamePool[61] = "The Professional Fanboy"
set udg_NamePool[62] = "Defender of Justice"
set udg_NamePool[63] = "Dividend Conquer"
set udg_NamePool[64] = "Freedom Dividend"
set udg_NamePool[65] = "The Establishment"
set udg_NamePool[66] = "Enemy of the People"
set udg_NamePool[67] = "Michael Bubble"
set udg_NamePool[68] = "Migrant Caravan"
set udg_NamePool[69] = "b0rderz"
set udg_NamePool[70] = "virginland"
set udg_NamePool[71] = "socialist_skills"
set udg_NamePool[72] = "$$ Democracy $$"
set udg_NamePool[73] = "There's a Planet B"
set udg_NamePool[74] = "J.R.R. Token"
set udg_NamePool[75] = "Okanisms"
set udg_NamePool[76] = "Fox News"
set udg_NamePool[77] = "MSNBC"
set udg_NamePool[78] = "MSM"
set udg_NamePool[79] = "Shen_Bapiro"
set udg_NamePool[80] = "Global Warming"
set udg_NamePool[81] = "Trigger Warning"
set udg_NamePool[82] = "-taliban-"
set udg_NamePool[83] = "Muscle-Worship"
set udg_NamePool[84] = "Lugenpresse"
set udg_NamePool[85] = "Fake News Media"
set c = 86
loop
exitwhen c > 96
set udg_NamePool[c] = "Storm Kards"
set c = c + 1
endloop
set c = 97
loop
exitwhen c > 103
set udg_NamePool[c] = "Selena345"
set c = c + 1
endloop
set udg_NamePoolInt = 103
endfunction
//===========================================================================
function InitTrig_Names takes nothing returns nothing
set gg_trg_Names = CreateTrigger( )
call TriggerAddAction( gg_trg_Names, function Trig_Names_Actions )
endfunction
function Trig_I_Actions takes nothing returns nothing
set udg_UDummies[0] = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'h000', 0, 0, 0)
endfunction
//===========================================================================
function InitTrig_I takes nothing returns nothing
set gg_trg_I = CreateTrigger( )
call TriggerAddAction( gg_trg_I, function Trig_I_Actions )
endfunction
function Trig_Tips_Actions takes nothing returns nothing
local player p
local integer c
local unit d
local group g
// Player Loop
set c = 0
loop
exitwhen c > 23
set p = Player(c)
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g, p, null)
// Building Loop
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
// Homestead
if GetUnitTypeId(d) == 'h008' then
call ForceAddPlayer(udg_GarithosBitches, p)
call DisplayTextToPlayer(p, 0, 0, "|cff88ddffType '|r|cff00c4eb-fuckoff|r|cff99ddff' to turn off info. Enjoy! :)|r")
call TriggerRegisterPlayerChatEvent( gg_trg_Fuckoff, p, "-fuckoff", true )
call TriggerRegisterPlayerChatEvent( gg_trg_Fuckon, p, "-fuckon", true )
// Javelin Throwers
call SetPlayerTechMaxAllowed(p, 'o004', 0) // II
call SetPlayerTechMaxAllowed(p, 'o005', 0) // III
// Iron Rider
call SetPlayerTechMaxAllowed(p, 'h00J', 0)
// Garrison
call SetPlayerAbilityAvailable(p, 'A019', false) // Attrition
call SetPlayerAbilityAvailable(p, 'A001', false) // Hail of Thorns
// Talents
call SetPlayerTechMaxAllowed(p, 'H00L', 1)
call SetPlayerTechMaxAllowed(p, 'H00M', 1)
call SetPlayerAbilityAvailable(p, 'A007', false) // Fortitude
call SetPlayerAbilityAvailable(p, 'A00B', false) // Pride & Prejudice
endif
endloop
call DestroyGroup(g)
set c = c + 1
endloop
set d = null
set g = null
set p = null
endfunction
//===========================================================================
function InitTrig_Tips takes nothing returns nothing
set gg_trg_Tips = CreateTrigger( )
call TriggerRegisterTimerEventSingle( gg_trg_Tips, 0.00 )
call TriggerAddAction( gg_trg_Tips, function Trig_Tips_Actions )
endfunction
function Trig_Cannibalize_Func004A takes nothing returns nothing
call SetUnitOwner( GetEnumUnit(), udg_TempPlayers[0], true )
endfunction
function Trig_Cannibalize_Actions takes nothing returns nothing
set udg_TempPlayers[0] = GetTriggerPlayer()
set udg_TempPlayer = GetOwningPlayer(GroupPickRandomUnit(GetUnitsSelectedAll(udg_TempPlayers[0])))
call ForGroupBJ( GetUnitsOfPlayerAll(udg_TempPlayer), function Trig_Cannibalize_Func004A )
endfunction
//===========================================================================
function InitTrig_Cannibalize takes nothing returns nothing
set gg_trg_Cannibalize = CreateTrigger( )
call TriggerAddAction( gg_trg_Cannibalize, function Trig_Cannibalize_Actions )
endfunction
function Trig_Teams_Of_Actions takes nothing returns nothing
local string s = SubString(GetEventPlayerChatString(), 3, 5)
// Main Looper
local integer x = 0
// Lower Range
local integer c = 0
// Range Update Counter
local integer y = 0
// Second Looper
local integer z
// Substring
local integer v = S2I(s) - 1
local player p1
local player p2
loop
set z = 0
loop
set p1 = Player(x)
set p2 = Player(z)
if z >= c and z < c + v then
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, true)
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, false)
endif
set z = z + 1
exitwhen z > 23
endloop
set y = y + 1
if y > v then
set y = 0
set c = x
endif
set x = x + 1
exitwhen x > 23
endloop
set p1 = null
set p2 = null
set s = null
endfunction
//===========================================================================
function InitTrig_Teams_Of takes nothing returns nothing
set gg_trg_Teams_Of = CreateTrigger( )
call TriggerAddAction( gg_trg_Teams_Of, function Trig_Teams_Of_Actions )
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
library NeutralHeroes initializer Init
function RestrictHeroToOne takes integer heroid returns nothing
local integer i = 0
loop
call SetPlayerTechMaxAllowed(Player(i),heroid,1)
set i = i+1
exitwhen i == bj_MAX_PLAYERS
endloop
endfunction
private function Init takes nothing returns nothing
// Neutral Heroes
call RestrictHeroToOne('Hlgr') // Dark Knight
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library HumanSetup initializer Init requires CustomRaceSystem
private function Init takes nothing returns nothing
local CustomRace c = CustomRace.create("Human",RACE_HUMAN,1.0)
call c.setTownHall('htow') // Town Hall
call c.addWorkerType('hpea',c.NEAR_MINE,5) // Peasant
call c.addHeroType('Hpal') // Paladin
call c.addHeroType('Hamg') // Archmage
call c.addHeroType('Hmkg') // Mountain King
call c.addHeroType('Hblm') // Blood Mage
call c.setAIScript("human.ai")
set c = CustomRace.create("Human",RACE_HUMAN,0.9)
call c.setTownHall('h008') // Altstad
call c.addWorkerType('h004',c.NEAR_MINE,5) // Worker
call c.addHeroType('H001') // Dark Knight
call c.setAIScript("human.ai")
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library OrcSetup initializer Init requires CustomRaceSystem
private function Init takes nothing returns nothing
local CustomRace c = CustomRace.create("Orc",RACE_ORC,1.0)
call c.setTownHall('ogre') // Great Hall
call c.addWorkerType('opeo',c.NEAR_MINE,5) // Peon
call c.addHeroType('Obla') // Blademaster
call c.addHeroType('Ofar') // Far Seer
call c.addHeroType('Otch') // Tauren Chieftain
call c.addHeroType('Oshd') // Shadow Hunter
call c.setAIScript("orc.ai")
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UndeadSetup initializer Init requires CustomRaceSystem
private function WorkerHideToggle takes nothing returns nothing
call ShowUnit(GetEnumUnit(),IsUnitHidden(GetEnumUnit()))
endfunction
private function HauntGoldMine takes player play, group workers, unit goldmine, unit townhall, unit randhero returns nothing
call ForGroup(workers,function WorkerHideToggle)
call BlightGoldMineForPlayerBJ(goldmine,play)
call ForGroup(workers,function WorkerHideToggle)
call DestroyGroup(workers)
endfunction
private function Init takes nothing returns nothing
local CustomRace c = CustomRace.create("Undead",RACE_UNDEAD,1.0)
call c.setTownHall('unpl') // Necropolis
call c.addWorkerType('uaco',c.NEAR_MINE,3) // Acolyte
call c.addWorkerType('ugho',c.NEAR_HALL,1) // Ghoul
call c.addHeroType('Udea') // Death Knight
call c.addHeroType('Ulic') // Lich
call c.addHeroType('Udre') // Dreadlord
call c.addHeroType('Ucrl') // Crypt Lord
call c.setCallback(CustomRaceCall.HauntGoldMine)
call c.setAIScript("undead.ai")
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library NightElfSetup initializer Init requires CustomRaceSystem
private function EntangleGoldMine takes player play, group workers, unit goldmine, unit townhall, unit randhero returns nothing
call SetUnitPosition(townhall,GetUnitX(goldmine),GetUnitY(goldmine))
call IssueTargetOrder(townhall, "entangleinstant", goldmine)
call DestroyGroup(workers)
endfunction
private function Init takes nothing returns nothing
local CustomRace c = CustomRace.create("Night Elf",RACE_NIGHTELF,1.0)
call c.setTownHall('etol') // Tree of Life
call c.addWorkerType('ewsp',c.NEAR_MINE,5) // Wisp
call c.addHeroType('Ekee') // Keeper of the Grove
call c.addHeroType('Emoo') // Priestess of the Moon
call c.addHeroType('Edem') // Demon Hunter
call c.addHeroType('Ewar') // Warden
call c.setCallback(CustomRaceCall.EntangleGoldMine)
call c.setAIScript("elf.ai")
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library NagaSetup initializer Init requires CustomRaceSystem
private function Init takes nothing returns nothing
local CustomRace c = CustomRace.create("Naga",RACE_NIGHTELF,0.9)
call c.setTownHall('nntt') // Temple of Tides
call c.addWorkerType('nmpe',c.NEAR_MINE,5) // Murgul Slave
call c.addHeroType('Hvsh') // Lady Vashj
call c.setAIScript("naga.ai")
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//==============================================================================
// Custom Race System by Archmage Owenalacaster
//==============================================================================
//
// Purpose:
// - Creates the starting units for custom races and replaces the standard
// Melee Initialization trigger. Custom races are selected by race and
// handicap.
//
// Usage:
// - Register a new custom race with CustomRace.create(name, RACE, handicap)
// Handicaps: Valid handicap values are 1.0, 0.9, 0.8, 0.7, 0.6 and 0.5.
// - Register a new custom race for all handicaps of a single race with
// CustomRace.createAll(name, RACE)
// - Extend the registration of a race with c.register(RACE, handicap)
// - Set the townhall type with c.setTownHall(unitid)
// - Add a new worker type with c.addWorkerType(unitid, priority, qty)
// Priorities: c.NEAR_MINE spawns workers near the mine, where workers
// typically spawn.
// c.NEAR_HALL spawns workers near the town hall, where
// Ghouls spawn.
// - Add a random hero type with c.addHeroType(unitid)
// - Set the ai script used by computer players with c.setAIScript(stringpath)
// - Set a callback function with c.setCallback(CustomRaceCall.function)
// Callbacks: The callback is executed after all the starting units for a
// player are created, and its purpose is to provide enhanced
// initial behaviour for a race. A good example of this with the
// standard races would be the Undead Goldmine Haunting and
// Night Elves Goldmine Entangling.
// The callback function passes as arguments all the units
// generated in addition to the nearest goldmine detected.
// Please note that if a random hero is not created, the last
// argument will have a null value, so always do a check.
// - Get a player's custom race name string with GetPlayerCustomRaceName(player)
//
// Notes:
// - Supports a maximum of 24 custom races.
// - Maximum for worker and hero types are configurable.
//
// Requirements:
// - JassHelper version 0.9.E.0 or newer (older versions may still work).
//
// Installation:
// - Create a new trigger called CustomRaceSystem.
// - Convert it to custom text and replace all the code with this code.
//
// Special Thanks:
// - Alevice: He practically co-wrote the code.
// - cosmicat: His formula for circular unit formation.
// Co-developing the single-array registry.
//
//==============================================================================
library CustomRaceSystem initializer Init
//===========================================================================
// CONFIGURATION SECTION
//===========================================================================
globals
// Unit Type Constants
private constant integer MAX_WORKERTYPES = 4
private constant integer MAX_HEROTYPES = 4
endglobals
//===========================================================================
// END CONFIGURATION SECTION
//===========================================================================
function interface CustomRaceCall takes player play, group workers, unit goldmine, unit townhall, unit randhero returns nothing
private function r2S takes race r returns string
if r == RACE_HUMAN then
return "Human"
elseif r == RACE_ORC then
return "Orc"
elseif r == RACE_UNDEAD then
return "Undead"
elseif r == RACE_NIGHTELF then
return "Night Elf"
endif
return "Unknown"
endfunction
private function r2I takes race r returns integer
if r == RACE_HUMAN then
return 1
elseif r == RACE_ORC then
return 2
elseif r == RACE_UNDEAD then
return 3
elseif r == RACE_NIGHTELF then
return 4
endif
return 5
endfunction
globals
// Victory Defeat Variables
private string array KEY_STRUCTURE
private integer KEY_STRUCTURE_COUNT = 0
endglobals
//===========================================================================
// STRUCT DATA
//===========================================================================
private keyword createStartingUnits
struct CustomRace
string name
// Town Hall Variable
integer townhallType = 0
//string townhallName
// Town Hall name is not currently supported.
// Worker Variables
integer totalWorkerTypes = 0
integer array workerType[MAX_WORKERTYPES]
integer array workerPriority[MAX_WORKERTYPES]
integer array workerQty[MAX_WORKERTYPES]
// Random Hero Variables
integer totalHeroTypes = 0
integer array heroType[MAX_HEROTYPES]
// AI Script Directory String Variable
string aiscript = ""
// Callback Variable
private CustomRaceCall c
// Registry Variable
static integer array REGISTRY
// Spawn Priority Variables
static integer NEAR_MINE = 0
static integer NEAR_HALL = 1
static method get takes race r, real h returns CustomRace
return CustomRace(.REGISTRY[((r2I(r)-1)*6)+(10-R2I(h*10.))])
endmethod
method register takes race r, real h returns boolean
local CustomRace c = CustomRace.get(r,h)
if c != 0 then
debug call BJDebugMsg("|cffff0000Registration of "+.name+" failed due to conflict with "+c.name+" registered for "+r2S(r)+" race Handicap "+R2S(h))
return false
endif
set .REGISTRY[((r2I(r)-1)*6)+(10-R2I(h*10.))] = integer(this)
return true
endmethod
static method create takes string name, race r, real h returns CustomRace
local CustomRace c = CustomRace.allocate()
set c.name = name
if not c.register(r,h) then
call c.destroy()
return 0
endif
return c
endmethod
static method createAll takes string name, race r returns CustomRace
local CustomRace c = CustomRace.allocate()
set c.name = name
if not c.register(r,1.0) and not c.register(r,0.9) and not c.register(r,0.8) and not c.register(r,0.7) and not c.register(r,0.6) and not c.register(r,0.5) then
call c.destroy()
return 0
endif
return c
endmethod
method setTownHall takes integer hallid returns nothing
set .townhallType = hallid
set KEY_STRUCTURE[KEY_STRUCTURE_COUNT] = UnitId2String(hallid)
set KEY_STRUCTURE_COUNT = KEY_STRUCTURE_COUNT+1
endmethod
method addWorkerType takes integer workerid, integer priority, integer quantity returns nothing
set .workerType[.totalWorkerTypes] = workerid
set .workerPriority[.totalWorkerTypes] = priority
set .workerQty[.totalWorkerTypes] = quantity
set .totalWorkerTypes = .totalWorkerTypes+1
endmethod
method addHeroType takes integer heroid returns nothing
local integer i = 0
set .heroType[.totalHeroTypes] = heroid
set .totalHeroTypes = .totalHeroTypes+1
loop
call SetPlayerTechMaxAllowed(Player(i),heroid,1)
set i = i+1
exitwhen i == bj_MAX_PLAYERS
endloop
endmethod
private method getRandomHeroType takes nothing returns integer
local integer randomindex = GetRandomInt(0,.totalHeroTypes-1)
return .heroType[randomindex]
endmethod
method setAIScript takes string s returns nothing
set .aiscript = s
endmethod
method setCallback takes CustomRaceCall callb returns nothing
set .c = callb
endmethod
private method createRandomHero takes player p, location loc returns unit
local unit h = CreateUnitAtLoc(p, .getRandomHeroType(), loc, bj_UNIT_FACING)
if bj_meleeGrantHeroItems then
call MeleeGrantItemsToHero(h)
endif
return h
endmethod
method createStartingUnits takes player p returns nothing
local location startLoc = GetPlayerStartLocationLoc(p)
local location nearMineLoc = startLoc
local location nearTownLoc = startLoc
local location spawnLoc = startLoc
local location heroLoc = startLoc
local unit nearestMine = MeleeFindNearestMine(startLoc, bj_MELEE_MINE_SEARCH_RADIUS)
local unit myTownhall = null
local unit myRandHero = null
local group workerGroup = CreateGroup()
local integer workertypeindex = 0
local integer workerqty = 0
local integer spawnPriority = 0
if nearestMine != null then
set nearMineLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine),startLoc,320,0)
set nearTownLoc = MeleeGetProjectedLoc(startLoc,GetUnitLoc(nearestMine),288,0)
set heroLoc = MeleeGetProjectedLoc(GetUnitLoc(nearestMine),startLoc,384,45)
endif
set myTownhall = CreateUnitAtLoc(p,.townhallType,startLoc,bj_UNIT_FACING)
loop
exitwhen workertypeindex == .totalWorkerTypes
set spawnPriority = .workerPriority[workertypeindex]
if (spawnPriority==.NEAR_HALL) then
set spawnLoc = nearTownLoc
elseif(spawnPriority==.NEAR_MINE) then
set spawnLoc = nearMineLoc
endif
loop
call GroupAddUnit(workerGroup, CreateUnitAtLoc(p,.workerType[workertypeindex],PolarProjectionBJ(spawnLoc,65,(I2R(workerqty)*(360.00 / I2R(.workerQty[workertypeindex]))) + 90),bj_UNIT_FACING))
set workerqty = workerqty + 1
exitwhen workerqty >= .workerQty[workertypeindex]
endloop
call RemoveLocation(spawnLoc)
set workerqty = 0
set workertypeindex = workertypeindex+1
endloop
if (IsMapFlagSet(MAP_RANDOM_HERO) and .totalHeroTypes>0 ) then
set myRandHero = .createRandomHero(p,heroLoc)
else
call SetPlayerState(p,PLAYER_STATE_RESOURCE_HERO_TOKENS,bj_MELEE_STARTING_HERO_TOKENS)
endif
if(.c!=0) then
call .c.evaluate(p,workerGroup,nearestMine,myTownhall,myRandHero)
else
call DestroyGroup(workerGroup)
endif
if nearMineLoc != startLoc then
call RemoveLocation(nearMineLoc)
call RemoveLocation(nearTownLoc)
call RemoveLocation(heroLoc)
endif
call RemoveLocation(startLoc)
set startLoc = null
set nearMineLoc = null
set nearTownLoc = null
set spawnLoc = null
set heroLoc = null
set nearestMine = null
set myTownhall = null
set myRandHero = null
set workerGroup = null
endmethod
endstruct
globals
private string array PLAYER_RACE
endglobals
function GetPlayerCustomRaceName takes player p returns string
return PLAYER_RACE[GetPlayerId(p)]
endfunction
//===========================================================================
// UNIT CREATION SECTION
//===========================================================================
private function CreateStartingUnitsForAllPlayers takes nothing returns nothing
local integer index = 0
local player indexPlayer
local race playerRace
local CustomRace c
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set playerRace = GetPlayerRace(indexPlayer)
set c = CustomRace.get(playerRace,GetPlayerHandicap(indexPlayer)+0.01)
if (GetPlayerController(indexPlayer) == MAP_CONTROL_USER or (GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER and c.aiscript != "" )) and c != 0 then
set PLAYER_RACE[index] = c.name
call c.createStartingUnits(indexPlayer)
elseif playerRace == RACE_HUMAN then
call MeleeStartingUnitsHuman(indexPlayer,GetStartLocationLoc(GetPlayerStartLocation(indexPlayer)),true,true,true)
elseif playerRace == RACE_ORC then
call MeleeStartingUnitsOrc(indexPlayer,GetStartLocationLoc(GetPlayerStartLocation(indexPlayer)),true,true,true)
elseif playerRace == RACE_NIGHTELF then
call MeleeStartingUnitsNightElf(indexPlayer,GetStartLocationLoc(GetPlayerStartLocation(indexPlayer)),true,true,true)
elseif playerRace == RACE_UNDEAD then
call MeleeStartingUnitsUndead(indexPlayer,GetStartLocationLoc(GetPlayerStartLocation(indexPlayer)),true,true,true)
else
call MeleeStartingUnitsUnknownRace(indexPlayer,GetStartLocationLoc(GetPlayerStartLocation(indexPlayer)),true,true,true)
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
endfunction
//===========================================================================
// CUSTOM MELEE AI SECTION
//===========================================================================
private function CustomMeleeStartingAI takes nothing returns nothing
local integer index = 0
local player indexPlayer
local race indexRace
local CustomRace c
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set indexRace = GetPlayerRace(indexPlayer)
set c = CustomRace.get(indexRace,GetPlayerHandicap(indexPlayer)+0.01)
call SetPlayerHandicap(indexPlayer,1.0)
if (GetPlayerController(indexPlayer) == MAP_CONTROL_COMPUTER) then
// Run a race-specific melee AI script.
if c != 0 and c.aiscript != "" then
call StartMeleeAI(indexPlayer, c.aiscript)
elseif (indexRace == RACE_HUMAN) then
call PickMeleeAI(indexPlayer, "human.ai", null, null)
elseif (indexRace == RACE_ORC) then
call PickMeleeAI(indexPlayer, "orc.ai", null, null)
elseif (indexRace == RACE_UNDEAD) then
call PickMeleeAI(indexPlayer, "undead.ai", null, null)
call RecycleGuardPosition(bj_ghoul[index])
elseif (indexRace == RACE_NIGHTELF) then
call PickMeleeAI(indexPlayer, "elf.ai", null, null)
else
// Unrecognized race.
endif
call ShareEverythingWithTeamAI(indexPlayer)
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
endfunction
//===========================================================================
// VICTORY DEFEAT SECTION
//===========================================================================
private function CustomGetAllyKeyStructureCount takes player whichPlayer returns integer
local integer i = 0
local integer keyStructs = 0
local integer playerIndex = 0
local player indexPlayer
loop
set indexPlayer = Player(playerIndex)
if (PlayersAreCoAllied(whichPlayer, indexPlayer)) then
set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "townhall", true, true)
set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "greathall", true, true)
set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "necropolis", true, true)
set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, "treeoflife", true, true)
loop
set keyStructs = keyStructs + GetPlayerTypedUnitCount(indexPlayer, KEY_STRUCTURE[i], true, true)
set i = i+1
exitwhen i == KEY_STRUCTURE_COUNT
endloop
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
return keyStructs
endfunction
private function CustomPlayerIsCrippled takes player whichPlayer returns boolean
local integer allyStructures = MeleeGetAllyStructureCount(whichPlayer)
local integer allyKeyStructures = CustomGetAllyKeyStructureCount(whichPlayer)
return (allyStructures > 0) and (allyKeyStructures <= 0)
endfunction
private function CustomCheckForCrippledPlayers takes nothing returns nothing
local integer playerIndex
local player indexPlayer
local boolean isNowCrippled
call MeleeCheckForLosersAndVictors()
if bj_finishSoonAllExposed then
return
endif
set playerIndex = 0
loop
set indexPlayer = Player(playerIndex)
set isNowCrippled = CustomPlayerIsCrippled(indexPlayer)
if (not bj_playerIsCrippled[playerIndex] and isNowCrippled) then
set bj_playerIsCrippled[playerIndex] = true
call TimerStart(bj_crippledTimer[playerIndex], bj_MELEE_CRIPPLE_TIMEOUT, false, function MeleeCrippledPlayerTimeout)
if (GetLocalPlayer() == indexPlayer) then
call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], true)
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_WARNING_HUMAN"))
endif
elseif (bj_playerIsCrippled[playerIndex] and not isNowCrippled) then
set bj_playerIsCrippled[playerIndex] = false
call PauseTimer(bj_crippledTimer[playerIndex])
if (GetLocalPlayer() == indexPlayer) then
call TimerDialogDisplay(bj_crippledTimerWindows[playerIndex], false)
if (MeleeGetAllyStructureCount(indexPlayer) > 0) then
if (bj_playerIsExposed[playerIndex]) then
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNREVEALED"))
else
call DisplayTimedTextToPlayer(indexPlayer, 0, 0, bj_MELEE_CRIPPLE_MSG_DURATION, GetLocalizedString("CRIPPLE_UNCRIPPLED"))
endif
endif
endif
call MeleeExposePlayer(indexPlayer, false)
endif
set playerIndex = playerIndex + 1
exitwhen playerIndex == bj_MAX_PLAYERS
endloop
endfunction
private function CustomInitVictoryDefeat takes nothing returns nothing
local trigger checker = CreateTrigger()
local trigger trig
local integer index
local player indexPlayer
set bj_finishSoonTimerDialog = CreateTimerDialog(null)
call TriggerAddAction(checker, function CustomCheckForCrippledPlayers)
set trig = CreateTrigger()
call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_SOON)
call TriggerAddAction(trig, function MeleeTriggerTournamentFinishSoon)
set trig = CreateTrigger()
call TriggerRegisterGameEvent(trig, EVENT_GAME_TOURNAMENT_FINISH_NOW)
call TriggerAddAction(trig, function MeleeTriggerTournamentFinishNow)
set index = 0
loop
set indexPlayer = Player(index)
if (GetPlayerSlotState(indexPlayer) == PLAYER_SLOT_STATE_PLAYING) then
set bj_meleeDefeated[index] = false
set bj_meleeVictoried[index] = false
set bj_playerIsCrippled[index] = false
set bj_playerIsExposed[index] = false
set bj_crippledTimer[index] = CreateTimer()
set bj_crippledTimerWindows[index] = CreateTimerDialog(bj_crippledTimer[index])
call TimerDialogSetTitle(bj_crippledTimerWindows[index], MeleeGetCrippledTimerMessage(indexPlayer))
call TriggerRegisterPlayerUnitEvent(checker, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_CANCEL, null)
call TriggerRegisterPlayerUnitEvent(checker, indexPlayer, EVENT_PLAYER_UNIT_DEATH, null)
call TriggerRegisterPlayerUnitEvent(checker, indexPlayer, EVENT_PLAYER_UNIT_CONSTRUCT_START, null)
call TriggerRegisterPlayerAllianceChange(checker, indexPlayer, ALLIANCE_PASSIVE)
call TriggerRegisterPlayerStateEvent(checker, indexPlayer, PLAYER_STATE_ALLIED_VICTORY, EQUAL, 1)
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_DEFEAT)
call TriggerAddAction(trig, function MeleeTriggerActionPlayerDefeated)
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
call TriggerAddAction(trig, function MeleeTriggerActionPlayerLeft)
else
set bj_meleeDefeated[index] = true
set bj_meleeVictoried[index] = false
if (IsPlayerObserver(indexPlayer)) then
set trig = CreateTrigger()
call TriggerRegisterPlayerEvent(trig, indexPlayer, EVENT_PLAYER_LEAVE)
call TriggerAddAction(trig, function MeleeTriggerActionPlayerLeft)
endif
endif
set index = index + 1
exitwhen index == bj_MAX_PLAYERS
endloop
call TimerStart(CreateTimer(), 2.0, false, function CustomCheckForCrippledPlayers)
endfunction
private function TimerAction takes nothing returns nothing
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, bj_MELEE_STARTING_TOD)
call MeleeStartingHeroLimit()
call MeleeGrantHeroItems()
call MeleeStartingResources()
call MeleeClearExcessUnits()
call CreateStartingUnitsForAllPlayers()
call CustomMeleeStartingAI()
call CustomInitVictoryDefeat()
call DestroyTimer(GetExpiredTimer())
endfunction
private function Init takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function TimerAction)
endfunction
endlibrary
function Trig_Attack_Actions takes nothing returns nothing
local unit u1 = GetAttacker()
local unit u2 = GetTriggerUnit()
local player p1 = GetOwningPlayer(u1)
local player p2 = GetOwningPlayer(u2)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local real tx = GetUnitX(u2)
local real ty = GetUnitY(u2)
local integer id1 = GetPlayerId(p1)
local integer ut1 = GetUnitTypeId(u1)
local integer c = 0
local group g
local unit d
local real hp2 = GetUnitState(u2, UNIT_STATE_LIFE)
local real r
local real a = Atan2 (ty - cy, tx - cx)
// Garrison
if ut1 == 'h00F' then
set c = 1
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g, p1, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if IsUnitInTransport(d, u1) then
set c = c + 1
endif
endloop
call SetUnitAbilityLevel(u1, 'A00Z', c)
call DestroyGroup(g)
endif
// Iron Will Swing
if udg_Gary_F[id1] != null and GetUnitAbilityLevel(u1, 'A007') > 0 and GetRandomInt(0, 100) < (BlzGetUnitArmor(u1) + 15) and not IsUnitType(u2, UNIT_TYPE_STRUCTURE) then
call SetUnitAnimation(u1, "attack slam")
set udg_CritDid[id1] = 1.
endif
// Orb of Judgement Swing
if not IsHuman(u2) and GetInventoryIndexOfItemTypeBJ(u1, 'I007') > 0 and not IsUnitType(u2, UNIT_TYPE_MECHANICAL) and not IsUnitType(u2, UNIT_TYPE_STRUCTURE) and hp2 - (BlzGetUnitBaseDamage(u1, 1) * (1 + udg_CritDid[id1] + (0.35 * GetUnitAbilityLevel(u1, 'B00J')))) <= (GetUnitState(u2, UNIT_STATE_MAX_LIFE) * 0.18) then
call SetUnitAnimation(u1, "spell slam fifth")
endif
set d = null
set g = null
set u1 = null
set u2 = null
set p1 = null
set p2 = null
endfunction
//===========================================================================
function InitTrig_Attack takes nothing returns nothing
set gg_trg_Attack = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Attack, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddAction( gg_trg_Attack, function Trig_Attack_Actions )
endfunction
function Trig_Mythicast_Actions takes nothing returns nothing
local unit u1 = GetTriggerUnit()
local unit u2 = GetSpellTargetUnit()
local player p1 = GetOwningPlayer(u1)
local player p2 = GetOwningPlayer(u2)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local real tx = GetUnitX(u2)
local real ty = GetUnitY(u2)
local unit d
local group g
local integer rand
local real a = Atan2 (ty - cy, tx - cx)
local integer abil = GetSpellAbilityId()
local integer int = GetUnitAbilityLevel(u1, abil)
// Vanguard
if abil == 'A00K' then
if udg_MVan_I == 0 then
call EnableTrigger(gg_trg_Vanguard)
endif
set udg_MVan_I = udg_MVan_I + 1
set udg_MVan_C[udg_MVan_I] = u1
set udg_MVan_R[udg_MVan_I] = 0.1 + (int * 0.1)
set udg_MVan_Str[udg_MVan_I] = 50. + (70 * int)
set udg_MVan_T[udg_MVan_I] = 8
//call IssueTargetOrder(udg_UDummies[0], "innerfire", u1)
call UnitAddAbility(udg_MVan_C[udg_MVan_I], 'A00O')
call UnitMakeAbilityPermanent(udg_MVan_C[udg_MVan_I], true, 'A00O')
call BlzUnitHideAbility(udg_MVan_C[udg_MVan_I], 'A00O', true)
endif
// Blazing Arms
if abil == 'A00G' then
call UnitAddAbility(udg_UDummies[0], 'A00E')
call SetUnitAbilityLevel(udg_UDummies[0], 'A00E', int)
set g = CreateGroup()
call GroupEnumUnitsInRange(g, cx, cy, 666. + udg_MaxColl, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if IsUnitInRangeXY(d, cx, cy, 666.) and GetUnitState(d, UNIT_STATE_LIFE) > 0.41 and IsUnitAlly(d, p1) then
call IssueTargetOrder(udg_UDummies[0], "bloodlust", d)
endif
endloop
call DestroyGroup(g)
call UnitRemoveAbility(udg_UDummies[0], 'A00E')
endif
// Marshal's Might
if abil == 'A015' then
set g = CreateGroup()
call GroupEnumUnitsInRange(g, cx, cy, 600. + udg_MaxColl, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if IsUnitInRangeXY(d, cx, cy, 600.) and GetUnitState(d, UNIT_STATE_LIFE) > 0.41 and IsUnitEnemy(d, p1) then
call IssueTargetOrder(d, "attack", u1)
endif
endloop
call UnitAddAbility(u1, 'A01D')
call UnitMakeAbilityPermanent(u1, true, 'A01D')
call BlzUnitHideAbility(u1, 'A01D', true)
set udg_MMM2_I = udg_MMM2_I + 1
set udg_MMM2_C[udg_MMM2_I] = u1
set udg_MMM2_D[udg_MMM2_I] = 3.
if udg_MMM2_I == 1 then
call EnableTrigger(gg_trg_Marshals_Might_2)
endif
call DestroyGroup(g)
endif
set u1 = null
set u2 = null
set p1 = null
set p2 = null
set d = null
set g = null
endfunction
//===========================================================================
function InitTrig_Cast takes nothing returns nothing
set gg_trg_Cast = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Cast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( gg_trg_Cast, function Trig_Mythicast_Actions )
endfunction
function Trig_Construct_Actions takes nothing returns nothing
local unit u1 = GetConstructedStructure()
local player p1 = GetOwningPlayer(u1)
local integer id1 = GetPlayerId(p1)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local integer ut = GetUnitTypeId(u1)
// Fort
if ut == 'h00F' then
//call UnitAddAbility(u1, 'A00T') // Refuge
call UnitAddAbility(u1, 'S000') // Load
call UnitAddAbility(u1, 'A019') // Attrition
endif
// Windmill
if ut == 'h006' then
call UnitAddAbility(u1, 'A00R') // Windspeed
endif
// TIPS!!
if not udg_FuckOff[id1] then
// Training Ground
if ut == 'h00C' then
if udg_GTGs[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "In tune with the faction's minimalist design, its combatants are made to scale late into the game.")
endif
set udg_GTGs[id1] = udg_GTGs[id1] + 1
endif
// Forge
if ut == 'h005' then
if udg_GForges[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffForges|r enable the Garrison expansion/T2 Hall.")
endif
set udg_GForges[id1] = udg_GForges[id1] + 1
endif
// Garrison
if ut == 'h00F' then
if udg_GGars[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffGarrisons|r are multi-purpose structures, valuable in defense but easily countered by enemy spells.")
endif
set udg_GGars[id1] = udg_GGars[id1] + 1
endif
// Factory
if ut == 'h00A' then
if udg_GFacts[id1] == 0 then
//call DisplayTextToPlayer(p1, 0., 0., "Stock up on lumber for those |cff88ddffSiege Weapons|r. They don't come cheap. :)")
endif
set udg_GFacts[id1] = udg_GFacts[id1] + 1
endif
endif
set u1 = null
set p1 = null
endfunction
//===========================================================================
function InitTrig_Construct takes nothing returns nothing
set gg_trg_Construct = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Construct, EVENT_PLAYER_UNIT_CONSTRUCT_FINISH )
call TriggerAddAction( gg_trg_Construct, function Trig_Construct_Actions )
endfunction
function Trig_Death_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit k = GetKillingUnit()
local player p1 = GetOwningPlayer(u)
local player p2 = GetOwningPlayer(k)
local group g
local real cx = GetUnitX(k)
local real cy = GetUnitY(k)
local real tx = GetUnitX(u)
local real ty = GetUnitY(u)
local unit d
local integer ut1 = GetUnitTypeId(u)
local integer c
local real r1
//local real h = GetUnitState()
// Garrison
if ut1 == 'h00F' then
set c = 0
loop
set c = c + 1
exitwhen c > udg_MRecon_I
if udg_MRecon_U[c] == u then
call KillUnit(udg_MRecon_S[c])
set udg_MRecon_U[c] = udg_MRecon_U[udg_MRecon_I]
set udg_MRecon_S[c] = udg_MRecon_S[udg_MRecon_I]
set udg_MRecon_I = udg_MRecon_I - 1
endif
endloop
endif
// Vanquisher Aura
if not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL) then
set g = CreateGroup()
call GroupEnumUnitsInRange(g, tx, ty, 900. + udg_MaxColl, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if IsUnitInRangeXY(d, tx, ty, 900.) and GetUnitState(d, UNIT_STATE_LIFE) > 0.41 and (GetUnitAbilityLevel(d, 'B004') > 0 or GetUnitAbilityLevel(d, 'B006') > 0) and IsUnitEnemy(d, p1) and IsUnitAlly(d, p2) and not IsUnitType(d, UNIT_TYPE_MECHANICAL) then
call SetUnitState(d, UNIT_STATE_LIFE, (GetUnitState(d, UNIT_STATE_LIFE) + (10.)))
call DestroyEffect(AddSpecialEffectTarget("war3mapImported\\VanquisherTarget3.mdl", d, "origin"))
endif
endloop
call DestroyGroup(g)
endif
set u = null
set k = null
set p1 = null
set p2 = null
set g = null
set d = null
endfunction
//===========================================================================
function InitTrig_Death takes nothing returns nothing
set gg_trg_Death = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Death, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction( gg_trg_Death, function Trig_Death_Actions )
endfunction
function Trig_Enter_Actions takes nothing returns nothing
local unit u1 = GetEnteringUnit()
local player p1 = GetOwningPlayer(u1)
local integer id1 = GetPlayerId(p1)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local integer ut = GetUnitTypeId(u1)
// Knight
if ut == 'h00B' or ut == 'h00J' then
//call UnitAddAbility(u1, 'A012') Brothers in Arms
call BlzUnitHideAbility(u1, 'A012', true)
endif
// Camouflage
if GetUnitAbilityLevel(u1, 'A01T') > 0 then
if udg_MCamo_I == 0 then
call EnableTrigger(gg_trg_Camouflage)
endif
set udg_MCamo_I = udg_MCamo_I + 1
set udg_MCamo_U[udg_MCamo_I] = u1
endif
// Garitwos
if ut == 'H00L' or ut == 'H00M' then
set udg_GaryTs_C[id1] = udg_GaryTs_C[id1] + 1
call SuspendHeroXP(u1, true)
call PauseUnit(u1, true)
call ShowUnit(u1, false)
if udg_GaryTs_C[id1] == 1 then
call SetPlayerTechResearched(p1, 'R00H', 1)
elseif udg_GaryTs_C[id1] == 2 then
call SetPlayerTechResearched(p1, 'R00L', 1)
endif
if ut == 'H00L' then // F
set udg_Gary_F[id1] = u1
call SetPlayerAbilityAvailable(p1, 'A007', true)
elseif ut == 'H00M' then // PnP
set udg_Gary_PnP[id1] = u1
call SetPlayerAbilityAvailable(p1, 'A00B', true)
endif
endif
// Recon
if GetUnitAbilityLevel(u1, 'A017') > 0 and GetPlayerTechCount(p1, 'R00K', true) > 0 then
if udg_MRecon_I == 0 then
call EnableTrigger(gg_trg_Reconnaissance)
endif
set udg_MRecon_I = udg_MRecon_I + 1
set udg_MRecon_U[udg_MRecon_I] = u1
set udg_MRecon_S[udg_MRecon_I] = CreateUnit(p1, 'h00H', cx, cy, 0.)
call SetUnitPathing(udg_MRecon_S[udg_MRecon_I], false)
endif
// TIPS!!
if not udg_FuckOff[id1] then
// Workers
if ut == 'h004' then
if udg_GWorkers[id1] == 6 then
//call DisplayTextToPlayer(p1, 0., 0., "The faction can be reliant on lumber, so don't disregard it.")
endif
set udg_GWorkers[id1] = udg_GWorkers[id1] + 1
endif
// Javelin Throwers
if ut == 'o001' then
if udg_GJavs[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffJavelin Throwers|r rely on allies to keep their targets at bay. Their innate passive and low health makes them heavily dependent on positioning.")
endif
if udg_GJavs[id1] == 2 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffJavelin Throwers|r may sting, but most of their damage disappears in close quarters. They are also weak against mechanicals.")
endif
set udg_GJavs[id1] = udg_GJavs[id1] + 1
endif
// Iron Riders
if ut == 'h00B' then
if udg_GIRs[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffIron Riders|r start with abysmal damage, but make for a valuable line of defense.")
endif
if udg_GIRs[id1] == 2 then
//call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffJavelin Throwers|r may sting, but half their damage disappears in close quarters. They are also weak against mechanicals.")
endif
set udg_GIRs[id1] = udg_GIRs[id1] + 1
endif
// Batteries
if ut == 'o000' then
if udg_GBats[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffBatteries|r trade expense, a shorter range, and Medium armor for superior damage and mobility.")
endif
set udg_GBats[id1] = udg_GBats[id1] + 1
endif
// Fatimahs
if ut == 'h00E' then
if udg_GFats[id1] == 0 then
call DisplayTextToPlayer(p1, 0., 0., "|cff88ddffCitybreakers|r are support siege units, sporting minimal damage but shredding the enemy's armor and hindering their movement.")
endif
set udg_GFats[id1] = udg_GFats[id1] + 1
endif
endif
set u1 = null
set p1 = null
endfunction
//===========================================================================
function InitTrig_Enter takes nothing returns nothing
set gg_trg_Enter = CreateTrigger( )
call TriggerRegisterEnterRectSimple( gg_trg_Enter, GetEntireMapRect() )
call TriggerAddAction( gg_trg_Enter, function Trig_Enter_Actions )
endfunction
function Trig_Fuckoff_Actions takes nothing returns nothing
local player p = GetTriggerPlayer()
local integer id = GetPlayerId(p)
if not udg_FuckOff[id] then
set udg_FuckOff[id] = true
call DisplayTextToPlayer(p, 0, 0, "Info will now fuck off. Type '-fuckon' if you want it back.")
endif
set p = null
endfunction
//===========================================================================
function InitTrig_Fuckoff takes nothing returns nothing
set gg_trg_Fuckoff = CreateTrigger( )
call TriggerAddAction( gg_trg_Fuckoff, function Trig_Fuckoff_Actions )
endfunction
function Trig_Fuckon_Actions takes nothing returns nothing
local player p = GetTriggerPlayer()
local integer id = GetPlayerId(p)
if udg_FuckOff[id] then
set udg_FuckOff[id] = false
call DisplayTextToPlayer(p, 0, 0, "Info's back!")
endif
set p = null
endfunction
//===========================================================================
function InitTrig_Fuckon takes nothing returns nothing
set gg_trg_Fuckon = CreateTrigger( )
call TriggerAddAction( gg_trg_Fuckon, function Trig_Fuckon_Actions )
endfunction
function LearnAct takes nothing returns nothing
local unit u1 = GetTriggerUnit()
local player p1 = GetOwningPlayer(u1)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local integer abil = GetLearnedSkill()
// Marshal's Might
if abil == 'A015' then
call UnitAddAbility(u1, 'A00Q')
call BlzUnitHideAbility(u1, 'A00Q', true)
if udg_MMM_I == 0. then
call EnableTrigger(gg_trg_Marshals_Might)
endif
set udg_MMM_I = udg_MMM_I + 1
set udg_MMM_C[udg_MMM_I] = u1
endif
set u1 = null
set p1 = null
endfunction
//===========================================================================
function InitTrig_Learn takes nothing returns nothing
set gg_trg_Learn = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Learn, EVENT_PLAYER_HERO_SKILL )
call TriggerAddAction( gg_trg_Learn, function LearnAct )
endfunction
function Trig_Level_Actions takes nothing returns nothing
local unit u = GetEnteringUnit()
local player p = GetOwningPlayer(u)
local integer id = GetPlayerId(p)
local real cx = GetUnitX(u)
local real cy = GetUnitY(u)
local integer ut = GetUnitTypeId(u)
// AI
if GetPlayerController(p) == MAP_CONTROL_COMPUTER then
// Human
// Archmage
if ut == 'Hamg' then
call SelectHeroSkill(u, 'AHmt')
call SelectHeroSkill(u, 'AHbz')
call SelectHeroSkill(u, 'AHab')
call SelectHeroSkill(u, 'AHwe')
endif
// MK
if ut == 'Hmkg' then
call SelectHeroSkill(u, 'AHav')
call SelectHeroSkill(u, 'AHtc')
call SelectHeroSkill(u, 'AHtb')
call SelectHeroSkill(u, 'AHbh')
endif
// P
if ut == 'Hpal' then
call SelectHeroSkill(u, 'AHre')
call SelectHeroSkill(u, 'AHhb')
call SelectHeroSkill(u, 'AHad')
call SelectHeroSkill(u, 'AHds')
endif
// BM
if ut == 'Hblm' then
call SelectHeroSkill(u, 'AHpx')
call SelectHeroSkill(u, 'AHfs')
call SelectHeroSkill(u, 'AHdr')
call SelectHeroSkill(u, 'AHbn')
endif
// Orc
// Far Seer
if ut == 'Ofar' then
call SelectHeroSkill(u, 'AOeq')
call SelectHeroSkill(u, 'AOcl')
call SelectHeroSkill(u, 'AOsf')
call SelectHeroSkill(u, 'AOfs')
endif
// BM
if ut == 'Obla' then
call SelectHeroSkill(u, 'AOww')
call SelectHeroSkill(u, 'AOwk')
call SelectHeroSkill(u, 'AOcr')
call SelectHeroSkill(u, 'AOmi')
endif
// TC
if ut == 'Otch' then
call SelectHeroSkill(u, 'AOre')
call SelectHeroSkill(u, 'AOae')
call SelectHeroSkill(u, 'AOws')
call SelectHeroSkill(u, 'AOsh')
endif
// SH
if ut == 'Oshd' then
call SelectHeroSkill(u, 'AOvd')
call SelectHeroSkill(u, 'AOhw')
call SelectHeroSkill(u, 'AOsw')
call SelectHeroSkill(u, 'AOhx')
endif
endif
set u = null
set p = null
endfunction
//===========================================================================
function InitTrig_Level takes nothing returns nothing
set gg_trg_Level = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Level, EVENT_PLAYER_HERO_LEVEL )
call TriggerAddAction( gg_trg_Level, function Trig_Level_Actions )
endfunction
function Trig_Research_Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
local integer id = GetPlayerId(p)
local integer ut
local real cx = GetUnitX(u)
local real cy = GetUnitY(u)
local group g
local unit d
local integer tech = GetResearched()
local integer lvl = GetPlayerTechCount(p, tech, true)
// Javelins
if tech == 'R005' then
if lvl == 2 then
call SetPlayerTechMaxAllowed(p, 'o001', 0) // I
call SetPlayerTechMaxAllowed(p, 'o004', -1) // II
endif
if lvl == 3 then
call SetPlayerTechMaxAllowed(p, 'o004', 0) // II
call SetPlayerTechMaxAllowed(p, 'o005', -1) // III
endif
endif
// Iron Riders
if tech == 'R009' then
if lvl == 3 then
call SetPlayerTechMaxAllowed(p, 'h00B', 0) // II
call SetPlayerTechMaxAllowed(p, 'h00J', -1) // III
endif
endif
// Attrition
if tech == 'R00O' then
call SetPlayerAbilityAvailable(p, 'A019', true)
endif
// Hail of Thorns
if tech == 'R00G' then
call SetPlayerAbilityAvailable(p, 'A001', true)
endif
// Reconnaissance
if tech == 'R00K' then
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g, p, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if GetUnitTypeId(d) == 'h00K' then
if udg_MRecon_I == 0 then
call EnableTrigger(gg_trg_Reconnaissance)
endif
set udg_MRecon_I = udg_MRecon_I + 1
set udg_MRecon_U[udg_MRecon_I] = d
set udg_MRecon_S[udg_MRecon_I] = CreateUnit(p, 'h00H', GetUnitX(d), GetUnitY(d), 0.)
call SetUnitPathing(udg_MRecon_S[udg_MRecon_I], false)
endif
endloop
endif
// INFO!!
if not udg_FuckOff[id] then
if udg_GTechs01[id] == 0 and (tech == 'R005' or tech == 'R009' or tech == 'R00J' or tech == 'R002' or tech == 'R00C' or tech == 'R00M') and GetPlayerTechCount(p, tech, true) == 2 and not udg_FuckOff[id] then
call DisplayTextToPlayer(p, 0., 0., "Certain |cff88ddffTier 3 Techs|r are more expensive, but are much more rewarding - making up for standard factions having to construct advanced structures to access higher tier units.")
set udg_GTechs01[id] = udg_GTechs01[id] + 1
endif
// Iron Chains
if tech == 'R00E' then
//call DisplayTextToPlayer(p, 0., 0., "|cff88ddffIron Chains|r turns Citybreakers into potent air counters.")
endif
// Reconnaissance
if tech == 'R00K' then
call DisplayTextToPlayer(p, 0., 0., "|cff88ddffReconnaissance|r makes up for the faction's lack of air scouts.")
endif
// Valiant Charge
if tech == 'R00B' then
call DisplayTextToPlayer(p, 0., 0., "|cff88ddffValiant Charge|r hurts as much as Pulverize, but it's narrower and less likely.")
endif
// Pyro
if tech == 'R004' and lvl == 1 then
call DisplayTextToPlayer(p, 0., 0., "Unlike other caster upgrades, |cff88ddffPyromancer Training|r does not increase health.")
endif
endif
set u = null
set d = null
set p = null
set g = null
endfunction
//===========================================================================
function InitTrig_Research takes nothing returns nothing
set gg_trg_Research = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Research, EVENT_PLAYER_UNIT_RESEARCH_FINISH )
call TriggerAddAction( gg_trg_Research, function Trig_Research_Actions )
endfunction
function MCamouflage takes nothing returns nothing
local integer c = 0
local real hp
local integer n
local group g
local unit d
local player p1
local real cx
local real cy
loop
set c = c + 1
exitwhen c > udg_MCamo_I
set hp = GetUnitState(udg_MCamo_U[c], UNIT_STATE_LIFE)
if hp > 0.41 then
set n = 0
set cx = GetUnitX(udg_MCamo_U[c])
set cy = GetUnitY(udg_MCamo_U[c])
set p1 = GetOwningPlayer(udg_MCamo_U[c])
set g = CreateGroup()
call GroupEnumUnitsInRange(g, cx, cy, 200. + udg_MaxColl, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if IsUnitInRangeXY(d, cx, cy, 200.) and GetUnitState(d, UNIT_STATE_LIFE) > 0.41 and IsUnitEnemy(d, p1) and not IsUnitType(d, UNIT_TYPE_STRUCTURE) and not IsUnitType(d, UNIT_TYPE_PEON) then
set n = n + 1
endif
endloop
if n > 0 then
call UnitRemoveAbility(udg_MCamo_U[c], 'A01S')
else
call UnitAddAbility(udg_MCamo_U[c], 'A01S')
endif
else
set udg_MCamo_U[c] = udg_MCamo_U[udg_MCamo_I]
set udg_MCamo_U[udg_MCamo_I] = null
if udg_MCamo_I == 0 then
call DisableTrigger(gg_trg_Camouflage)
endif
endif
endloop
set g = null
set d = null
endfunction
//===========================================================================
function InitTrig_Camouflage takes nothing returns nothing
set gg_trg_Camouflage = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Camouflage, 0.1 )
call DisableTrigger(gg_trg_Camouflage )
call TriggerAddAction( gg_trg_Camouflage, function MCamouflage )
endfunction
function Trig_IR_Challenger_Actions takes nothing returns nothing
local integer c = 0
loop
set c = c + 1
exitwhen c > udg_MChal_I
if udg_MChal_T[c] > 0. and GetUnitState(udg_MChal_U1[c], UNIT_STATE_LIFE) > 0.41 and GetUnitState(udg_MChal_U2[c], UNIT_STATE_LIFE) > .41 and GetUnitAbilityLevel(udg_MChal_U2[c], 'B00M') > 0 then
set udg_MChal_T[c] = udg_MChal_T[c] - 0.1
call IssueTargetOrder(udg_MChal_U2[c], "attack", udg_MChal_U1[c])
else
call UnitRemoveAbility(udg_MChal_U2[c], 'B00M')
set udg_MChal_T[c] = udg_MChal_T[udg_MChal_I]
set udg_MChal_U1[c] = udg_MChal_U1[udg_MChal_I]
set udg_MChal_U2[c] = udg_MChal_U2[udg_MChal_I]
set udg_MChal_I = udg_MChal_I - 1
set c = c - 1
if udg_MChal_I == 0 then
call DisableTrigger(gg_trg_IR_Challenger)
endif
endif
endloop
endfunction
//===========================================================================
function InitTrig_IR_Challenger takes nothing returns nothing
set gg_trg_IR_Challenger = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_IR_Challenger, 0.1 )
call DisableTrigger(gg_trg_IR_Challenger )
call TriggerAddAction( gg_trg_IR_Challenger, function Trig_IR_Challenger_Actions )
endfunction
function Trig_Vanguard_Actions takes nothing returns nothing
local integer c = 0
loop
set c = c + 1
exitwhen c > udg_MVan_I
if udg_MVan_Str[c] > 0. and udg_MVan_T[c] > 0. and GetUnitAbilityLevel(udg_MVan_C[c], 'A00O') > 0 then
set udg_MVan_T[c] = udg_MVan_T[c] - 0.1
else
// Explode if depleted
if udg_MVan_Str[c] <= 0. and udg_MVan_C[c] != null then
call MAreaDamage(udg_MVan_C[c], 15. + (55 * (GetUnitAbilityLevel(udg_MVan_C[c], 'A00K'))), 1., 270., "Abilities\\Weapons\\LavaSpawnMissile\\LavaSpawnMissile.mdl", GetUnitX(udg_MVan_C[c]), GetUnitY(udg_MVan_C[c]), ATTACK_TYPE_MAGIC)
call DestroyEffect(AddSpecialEffect("war3mapImported\\Vanguard Explosion.mdl", GetUnitX(udg_MVan_C[c]), GetUnitY(udg_MVan_C[c])))
endif
call UnitRemoveAbility(udg_MVan_C[c], 'A00O')
call UnitRemoveAbility(udg_MVan_C[c], 'B009')
set udg_MVan_C[c] = udg_MVan_C[udg_MVan_I]
set udg_MVan_R[c] = udg_MVan_R[udg_MVan_I]
set udg_MVan_Str[c] = udg_MVan_Str[udg_MVan_I]
set udg_MVan_T[c] = udg_MVan_T[udg_MVan_I]
set udg_MVan_C[udg_MVan_I] = null
set udg_MVan_I = udg_MVan_I - 1
set c = c - 1
if udg_MVan_I == 0 then
call DisableTrigger(gg_trg_Vanguard)
endif
endif
endloop
endfunction
//===========================================================================
function InitTrig_Vanguard takes nothing returns nothing
set gg_trg_Vanguard = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Vanguard, 0.1 )
call DisableTrigger(gg_trg_Vanguard )
call TriggerAddAction( gg_trg_Vanguard, function Trig_Vanguard_Actions )
endfunction
function Trig_LightningM_Actions takes nothing returns nothing
local integer c = 0
local real r
local real r2
loop
set c = c + 1
exitwhen c > udg_MLite_I
if udg_MLite_Dur[c] > 0. and GetUnitState(udg_MLite_U1[c], UNIT_STATE_LIFE) > 0.41 and GetUnitState(udg_MLite_U2[c], UNIT_STATE_LIFE) > .41 then
set udg_MLite_Dur[c] = udg_MLite_Dur[c] - 0.03
call MoveLightningEx(udg_MLite_L[c], true, GetUnitX(udg_MLite_U1[c]), GetUnitY(udg_MLite_U1[c]), 15 + GetUnitFlyHeight(udg_MLite_U1[c]) + BlzGetUnitZ(udg_MLite_U1[c]), GetUnitX(udg_MLite_U2[c]), GetUnitY(udg_MLite_U2[c]), 15 + GetUnitFlyHeight(udg_MLite_U2[c]) + BlzGetUnitZ(udg_MLite_U2[c]))
else
// End
call DestroyLightning(udg_MLite_L[c])
set udg_MLite_Dur[c] = udg_MLite_Dur[udg_MLite_I]
set udg_MLite_FadeIn[c] = udg_MLite_FadeIn[udg_MLite_I]
set udg_MLite_FadeOut[c] = udg_MLite_FadeOut[udg_MLite_I]
set udg_MLite_L[c] = udg_MLite_L[udg_MLite_I]
set udg_MLite_U1[c] = udg_MLite_U1[udg_MLite_I]
set udg_MLite_U2[c] = udg_MLite_U2[udg_MLite_I]
set udg_MLite_I = udg_MLite_I - 1
set c = c - 1
if udg_MLite_I == 0 then
call DisableTrigger(gg_trg_Lightning_M)
endif
endif
endloop
endfunction
//===========================================================================
function InitTrig_Lightning_M takes nothing returns nothing
set gg_trg_Lightning_M = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Lightning_M, 0.03 )
call DisableTrigger(gg_trg_Lightning_M )
call TriggerAddAction( gg_trg_Lightning_M, function Trig_LightningM_Actions )
endfunction
function Trig_MarshalsMight_Actions takes nothing returns nothing
local integer c = 0
local real hp
local real r
local group g
local unit d
local player p1
local real cx
local real cy
loop
set c = c + 1
exitwhen c > udg_MMM_I
set hp = GetUnitState(udg_MMM_C[c], UNIT_STATE_LIFE)
if hp > 0.41 then
if GetUnitAbilityLevel(udg_MMM_C[c], 'A01D') > 0 then
set r = 0.007
set cx = GetUnitX(udg_MMM_C[c])
set cy = GetUnitY(udg_MMM_C[c])
set p1 = GetOwningPlayer(udg_MMM_C[c])
set g = CreateGroup()
call GroupEnumUnitsInRange(g, cx, cy, 600. + udg_MaxColl, null)
loop
set d = FirstOfGroup(g)
call GroupRemoveUnit(g, d)
exitwhen d == null
if GetUnitAbilityLevel(d, 'B00M') == 0 and IsUnitInRangeXY(d, cx, cy, 600.) and GetUnitState(d, UNIT_STATE_LIFE) > 0.41 and IsUnitEnemy(d, p1) then
call IssueTargetOrder(d, "attack", udg_MMM_C[c])
endif
endloop
else
set r = 0.001
endif
call SetUnitState(udg_MMM_C[c], UNIT_STATE_LIFE, (hp + (GetUnitState(udg_MMM_C[c], UNIT_STATE_MAX_LIFE) * r)))
endif
endloop
set g = null
set d = null
endfunction
//===========================================================================
function InitTrig_Marshals_Might takes nothing returns nothing
set gg_trg_Marshals_Might = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Marshals_Might, 0.1 )
call DisableTrigger(gg_trg_Marshals_Might )
call TriggerAddAction( gg_trg_Marshals_Might, function Trig_MarshalsMight_Actions )
endfunction
function Trig_MarshalsMight2_Actions takes nothing returns nothing
local integer c = 0
loop
set c = c + 1
exitwhen c > udg_MMM2_I
if udg_MMM2_D[c] > 0. then
set udg_MMM2_D[c] = udg_MMM2_D[c] - 0.5
if GetUnitAbilityLevel(udg_MMM2_C[c], 'A01D') == 0 then
call UnitAddAbility(udg_MMM2_C[c], 'A01D')
call UnitMakeAbilityPermanent(udg_MMM2_C[c], true, 'A01D')
call BlzUnitHideAbility(udg_MMM2_C[c], 'A01D', true)
endif
else
call UnitRemoveAbility(udg_MMM2_C[c], 'A01D')
call UnitRemoveAbility(udg_MMM2_C[c], 'B00H')
set udg_MMM2_C[c] = udg_MMM2_C[udg_MMM2_I]
set udg_MMM2_D[c] = udg_MMM2_D[udg_MMM2_I]
set udg_MMM2_I = udg_MMM2_I - 1
set c = c - 1
if udg_MMM2_I == 0 then
call DisableTrigger(gg_trg_Marshals_Might_2)
endif
endif
endloop
endfunction
//===========================================================================
function InitTrig_Marshals_Might_2 takes nothing returns nothing
set gg_trg_Marshals_Might_2 = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Marshals_Might_2, 0.5 )
call DisableTrigger(gg_trg_Marshals_Might_2 )
call TriggerAddAction( gg_trg_Marshals_Might_2, function Trig_MarshalsMight2_Actions )
endfunction
function Reconnaissance_Mover takes nothing returns nothing
local integer c = 0
loop
set c = c + 1
exitwhen c > udg_MRecon_I
if udg_MRecon_U[c] != null and GetUnitState(udg_MRecon_U[c], UNIT_STATE_LIFE) > 0.41 then
call SetUnitX(udg_MRecon_S[c], GetUnitX(udg_MRecon_U[c]))
call SetUnitY(udg_MRecon_S[c], GetUnitY(udg_MRecon_U[c]))
else
call RemoveUnit(udg_MRecon_S[c])
set udg_MRecon_S[c] = udg_MRecon_S[udg_MRecon_I]
set udg_MRecon_U[c] = udg_MRecon_U[udg_MRecon_I]
set udg_MRecon_I = udg_MRecon_I - 1
set c = c - 1
if udg_MRecon_I == 0 then
call DisableTrigger(gg_trg_Reconnaissance)
endif
endif
endloop
endfunction
//===========================================================================
function InitTrig_Reconnaissance takes nothing returns nothing
set gg_trg_Reconnaissance = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Reconnaissance, 0.2 )
call DisableTrigger(gg_trg_Reconnaissance )
call TriggerAddAction( gg_trg_Reconnaissance, function Reconnaissance_Mover )
endfunction
//TESH.scrollpos=175
//TESH.alwaysfold=0
library MoveSpeedXGUI /* v1.1.0.0
*************************************************************************************
*
* This library allows you to set unit movement speeds beyond 522 without bugs.
* This is an extension of the library MoveSpeedX, but is formatted for GUI use.
* Credits to Jesus4Lyf for the original system.
*
************************************************************************************
*
* SETTINGS
*/
globals
private constant real PERIOD = 0.01
// This is the period on which all units will be run.
// If you lower this value, movement bonuses will be smoother,
// but will require more processing power (lag more).
// Also, the lower this is, the higher the move speed can be
// before it starts bugging on waypoints. The lowest valid
// period is 0.00125. A period of 0.00625 is very robust.
private constant real MARGIN = 0.01
// This is the margin of approximation when comparing reals.
// You will most likely not need to change this.
endglobals
/*
************************************************************************************
*
* Functions
*
* function GetUnitMoveSpeedX takes unit whichUnit returns real
* - Returns a unit movement speed. The GUI function will
* - not return the correct value. This function will always
* - return the correct value regardless of whether the unit
* - has a movement speed beyond 522.
*
************************************************************************************
*
* REQUIREMENTS
*
* 1. JassNewGen Pack v5d
* 2. JassHelper 0.A.2.B
* 3. Any unit indexer
*
* HOW TO IMPLEMENT
*
* 1. Copy the 'folder' MoveSpeedX.
* 2. Paste it into your map.
* 3. Open "Advanced -> Gameplay Constants".
* 4. Checkmark "Use Custom Gameplay Constants".
* 5. Find the field, "Movement - Unit Speed - Maximum", change
* that to 522.
* 6. Find the field, "Movement - Unit Speed - Minimum", hold
* shift and click, and change it to 0.
* 7. Read HOW TO USE.
*
************************************************************************************
*
* HOW TO USE
*
* This system will automatically work by itself. You can use the
* normal GUI function for modifying unit movement speeds. Simply
* use "Unit - Set Movement Speed", input whatever value you want,
* and you are good to go! It will handle values beyond 522 by itself.
*
* HOWEVER, the GUI function will not return correct values if a unit
* has a movement speed greater than 522. To fix this, use the function
* GetUnitMoveSpeedX to return the correct value. A sample is given in
* the trigger "Speed Change" in the test map.
*
************************************************************************************
*
* NOTES
*
* Units that were issued orders as groups might not *always* end up in the proper
* "order". (they might not end up in an organized formation) They do sometimes though.
* This is only for units with speeds above 522.
*
* This also will not factor in bonuses and probably not slows either.
*
* Units may waddle around the point for a little bit. Reduce PERIOD to fix
* it a little bit. I recommend about 0.02 if you have really high speeds.
*
************************************************************************************/
private function ApproxEqual takes real A, real B returns boolean
return (A >= (B - MARGIN)) and (A <= (B + MARGIN))
endfunction
private module M
private static trigger issued = CreateTrigger()
thistype next
thistype prev
boolean enabled
unit curr
real speed
real x
real y
real ox
real oy
method destroy takes nothing returns nothing
set this.next.prev = this.prev
set this.prev.next = this.next
set this.enabled = false
endmethod
private static method periodic takes nothing returns nothing
local thistype this = thistype(0).next // first instance in list
local real nx // the x-coordinate after tick
local real ny // the y-coordinate after tick
local real dx // distance between new-x and old-x
local real dy // distance between new-y and old-y
local real d // distance between new point and old point
local integer order // the unit's current order
local unit u // unit being affected
loop
exitwhen this == 0
set u = .curr
set nx = GetUnitX(u)
set ny = GetUnitY(u)
if IsUnitType(u, UNIT_TYPE_DEAD) then
call this.destroy()
elseif not ApproxEqual(nx, .x) or not ApproxEqual(ny, .y) then
if (not IsUnitPaused(u)) and GetUnitAbilityLevel(u, 'BSTN') == 0 and GetUnitAbilityLevel(u, 'BPSE') == 0 then
set order = GetUnitCurrentOrder(u)
set dx = nx - .x
set dy = ny - .y
set d = SquareRoot(dx * dx + dy * dy)
set dx = dx / d * .speed // move the unit offset-x by this
set dy = dy / d * .speed // move the unit offset-y by this
if (order == 851986 or order == 851971) and /*
*/ (this.ox - nx)*(this.ox - nx) < (dx*dx) and /*
*/ (this.oy - ny)*(this.oy - ny) < (dy*dy) then
// if the unit is issued a move or smart order and they are near their destination
// then move them there instantly (removes a bit of glitchyness towards the end)
call SetUnitX(u, .ox)
call SetUnitY(u, .oy)
set .x = .ox
set .y = .oy
call IssueImmediateOrderById(u, 851972) // order them to stop
else
set .x = nx + dx
set .y = ny + dy
call SetUnitX(u, .x)
call SetUnitY(u, .y)
endif
endif
endif
set this = this.next
endloop
set u = null
endmethod
static method create takes unit whichUnit, real newSpeed returns thistype
local thistype this = GetUnitUserData(whichUnit)
set this.next = thistype(0).next
set thistype(0).next.prev = this
set thistype(0).next = this
set this.prev = 0
set this.curr = whichUnit
set this.speed = (newSpeed - 522) * PERIOD
set this.x = GetUnitX(whichUnit)
set this.y = GetUnitY(whichUnit)
set this.enabled = true
return this
endmethod
static method update takes unit whichUnit, real newSpeed returns nothing
local thistype this = GetUnitUserData(whichUnit)
if this.enabled then
if newSpeed > 522 then
set this.speed = (newSpeed - 522) * PERIOD
else
call this.destroy()
endif
elseif newSpeed > 522 then
call thistype.create(whichUnit, newSpeed)
endif
endmethod
private static method storeOrderPoint takes nothing returns boolean
local thistype this = GetUnitUserData(GetTriggerUnit())
set this.ox = GetOrderPointX()
set this.oy = GetOrderPointY()
return false
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), PERIOD, true, function thistype.periodic)
call TriggerRegisterAnyUnitEventBJ(issued, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(issued, Condition(function thistype.storeOrderPoint))
endmethod
endmodule
private struct MoveSpeedStruct extends array
implement M
endstruct
function GetUnitMoveSpeedX takes unit whichUnit returns real
if MoveSpeedStruct(GetUnitUserData(whichUnit)).enabled then
return udg_UnitSpeedX[GetUnitUserData(whichUnit)]
endif
return GetUnitMoveSpeed(whichUnit)
endfunction
function SetUnitMoveSpeedX takes unit whichUnit, real newSpeed returns nothing
call MoveSpeedStruct.update(whichUnit, newSpeed)
set udg_UnitSpeedX[GetUnitUserData(whichUnit)] = newSpeed
endfunction
hook SetUnitMoveSpeed SetUnitMoveSpeedX
endlibrary
//===========================================================================
// Damage Engine lets you detect, amplify, block or nullify damage. It even
// lets you detect if the damage was physical or from a spell. Just reference
// DamageEventAmount/Source/Target or the boolean IsDamageSpell, to get the
// necessary damage event data.
//
// - Detect damage: use the event "DamageEvent Equal to 1.00"
// - To change damage before it's dealt: use the event "DamageModifierEvent Equal to 1.00"
// - Detect damage after it was applied, use the event "AfterDamageEvent Equal to 1.00"
// - Detect spell damage: use the condition "IsDamageSpell Equal to True"
// - Detect zero-damage: use the event "DamageEvent Equal to 2.00" (an AfterDamageEvent will not fire for this)
//
// You can specify the DamageEventType before dealing triggered damage. To prevent an already-improbable error, I recommend running the trigger "ClearDamageEvent (Checking Conditions)" after dealing triggered damage from within a damage event:
// - Set NextDamageType = DamageTypeWhatever
// - Unit - Cause...
// - Trigger - Run ClearDamageEvent (Checking Conditions)
//
// You can modify the DamageEventAmount and the DamageEventType from a "DamageModifierEvent Equal to 1.00" trigger.
// - If the amount is modified to negative, it will count as a heal.
// - If the amount is set to 0, no damage will be dealt.
//
// If you need to reference the original in-game damage, use the variable "DamageEventPrevAmt".
//
//===========================================================================
// Programming note about "integer i" and "udg_DmgEvRecursionN": integer i
// ranges from -1 upwards. "udg_DmgEvRecursionN" ranges from 0 upwards.
// "integer i" is always 1 less than "udg_DmgEvRecursionN"
//
function DmgEvResetVars takes nothing returns nothing
local integer i = udg_DmgEvRecursionN - 2
set udg_DmgEvRecursionN = i + 1
if i >= 0 then
set udg_DamageEventPrevAmt = udg_LastDmgPrevAmount[i]
set udg_DamageEventAmount = udg_LastDmgValue[i]
set udg_DamageEventSource = udg_LastDmgSource[i]
set udg_DamageEventTarget = udg_LastDmgTarget[i]
set udg_IsDamageSpell = udg_LastDmgWasSpell[i]
set udg_DamageEventType = udg_LastDmgPrevType[i]
endif
endfunction
function CheckDamagedLifeEvent takes boolean clear returns nothing
if clear then
set udg_NextDamageOverride = false
set udg_NextDamageType = 0
endif
if udg_DmgEvTrig != null then
call DestroyTrigger(udg_DmgEvTrig)
set udg_DmgEvTrig = null
if udg_IsDamageSpell then
call SetWidgetLife(udg_DamageEventTarget, RMaxBJ(udg_LastDamageHP, 0.41))
if udg_LastDamageHP <= 0.405 then
if udg_DamageEventType < 0 then
call SetUnitExploded(udg_DamageEventTarget, true)
endif
//Kill the unit
call DisableTrigger(udg_DamageEventTrigger)
call UnitDamageTarget(udg_DamageEventSource, udg_DamageEventTarget, -999, false, false, null, DAMAGE_TYPE_UNIVERSAL, null)
call EnableTrigger(udg_DamageEventTrigger)
endif
elseif GetUnitAbilityLevel(udg_DamageEventTarget, udg_DamageBlockingAbility) > 0 then
call UnitRemoveAbility(udg_DamageEventTarget, udg_DamageBlockingAbility)
call SetWidgetLife(udg_DamageEventTarget, udg_LastDamageHP)
endif
if udg_DamageEventAmount != 0.00 and not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_AfterDamageEvent = 0.00
set udg_AfterDamageEvent = 1.00
set udg_AfterDamageEvent = 0.00
endif
call DmgEvResetVars()
endif
endfunction
function DmgEvOnAOEEnd takes nothing returns nothing
if udg_DamageEventAOE > 1 then
set udg_AOEDamageEvent = 0.00
set udg_AOEDamageEvent = 1.00
set udg_AOEDamageEvent = 0.00
set udg_DamageEventAOE = 1
endif
set udg_DamageEventLevel = 1
set udg_EnhancedDamageTarget = null
call GroupClear(udg_DamageEventAOEGroup)
endfunction
function DmgEvOnExpire takes nothing returns nothing
set udg_DmgEvStarted = false
call CheckDamagedLifeEvent(true)
//Reset things so they don't perpetuate for AoE/Level target detection
call DmgEvOnAOEEnd()
set udg_DamageEventTarget = null
set udg_DamageEventSource = null
endfunction
function PreCheckDamagedLifeEvent takes nothing returns boolean
call CheckDamagedLifeEvent(true)
return false
endfunction
function OnUnitDamage takes nothing returns boolean
local boolean override = udg_DamageEventOverride
local integer i
local integer e = udg_DamageEventLevel
local integer a = udg_DamageEventAOE
local string s
local real prevAmount
local real life
local real prevLife
local unit u
local unit f
call CheckDamagedLifeEvent(false) //in case the unit state event failed and the 0.00 second timer hasn't yet expired
set i = udg_DmgEvRecursionN - 1 //Had to be moved here due to false recursion tracking
if i < 0 then
//Added 25 July 2017 to detect AOE damage or multiple single-target damage
set u = udg_DamageEventTarget
set f = udg_DamageEventSource
elseif i < 16 then
set udg_LastDmgPrevAmount[i]= udg_DamageEventPrevAmt
set udg_LastDmgValue[i] = udg_DamageEventAmount
set udg_LastDmgSource[i] = udg_DamageEventSource
set udg_LastDmgTarget[i] = udg_DamageEventTarget
set udg_LastDmgWasSpell[i] = udg_IsDamageSpell
set udg_LastDmgPrevType[i] = udg_DamageEventType
else
set s = "WARNING: Recursion error when dealing damage! Make sure when you deal damage from within a DamageEvent trigger, do it like this:\n\n"
set s = s + "Trigger - Turn off (This Trigger)\n"
set s = s + "Unit - Cause...\n"
set s = s + "Trigger - Turn on (This Trigger)"
//Delete the next couple of lines to disable the in-game recursion crash warnings
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 999.00, s)
return false
endif
set udg_DmgEvRecursionN = i + 2
set prevAmount = GetEventDamage()
set udg_DamageEventTarget = GetTriggerUnit()
set udg_DamageEventSource = GetEventDamageSource()
set udg_DamageEventAmount = prevAmount
set udg_DamageEventType = udg_NextDamageType
set udg_NextDamageType = 0
set udg_DamageEventOverride = udg_NextDamageOverride
set udg_NextDamageOverride = false
if i < 0 then
//Added 25 July 2017 to detect AOE damage or multiple single-target damage
if udg_DamageEventType == 0 then
if f == udg_DamageEventSource then
//Source has damaged more than once
if IsUnitInGroup(udg_DamageEventTarget, udg_DamageEventAOEGroup) then
//Added 5 August 2017 to improve tracking of enhanced damage against, say, Pulverize
set udg_DamageEventLevel = udg_DamageEventLevel + 1
set udg_EnhancedDamageTarget = udg_DamageEventTarget
else
//Multiple targets hit by this source - flag as AOE
set udg_DamageEventAOE = udg_DamageEventAOE + 1
endif
else
//New damage source - unflag everything
set u = udg_DamageEventSource
set udg_DamageEventSource = f
call DmgEvOnAOEEnd()
set udg_DamageEventSource = u
endif
call GroupAddUnit(udg_DamageEventAOEGroup, udg_DamageEventTarget)
endif
if not udg_DmgEvStarted then
set udg_DmgEvStarted = true
call TimerStart(udg_DmgEvTimer, 0.00, false, function DmgEvOnExpire)
endif
endif
if prevAmount == 0.00 then
if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_DamageEventPrevAmt = 0.00
set udg_DamageEvent = 0.00
set udg_DamageEvent = 2.00
set udg_DamageEvent = 0.00
endif
call DmgEvResetVars()
else
set u = udg_DamageEventTarget
set udg_IsDamageSpell = prevAmount < 0.00
if udg_IsDamageSpell then
set prevAmount = -udg_DamageEventAmount
set life = 1.00
if IsUnitType(u, UNIT_TYPE_ETHEREAL) and not IsUnitType(u, UNIT_TYPE_HERO) then
set life = life*udg_DAMAGE_FACTOR_ETHEREAL //1.67
endif
if GetUnitAbilityLevel(u, 'Aegr') > 0 then
set life = life*udg_DAMAGE_FACTOR_ELUNES //0.80
endif
if udg_DmgEvBracers != 0 and IsUnitType(u, UNIT_TYPE_HERO) then
//Inline of UnitHasItemOfTypeBJ without the potential handle ID leak.
set i = 6
loop
set i = i - 1
if GetItemTypeId(UnitItemInSlot(u, i)) == udg_DmgEvBracers then
set life = life*udg_DAMAGE_FACTOR_BRACERS //0.67
exitwhen true
endif
exitwhen i == 0
endloop
endif
set udg_DamageEventAmount = prevAmount*life
endif
set udg_DamageEventPrevAmt = prevAmount
set udg_DamageModifierEvent = 0.00
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 1.00
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 2.00
set udg_DamageModifierEvent = 3.00
endif
endif
set udg_DamageEventOverride = override
if udg_DamageEventAmount > 0.00 then
set udg_DamageModifierEvent = 4.00
endif
set udg_DamageModifierEvent = 0.00
if not udg_HideDamageFrom[GetUnitUserData(udg_DamageEventSource)] then
set udg_DamageEvent = 0.00
set udg_DamageEvent = 1.00
set udg_DamageEvent = 0.00
endif
call CheckDamagedLifeEvent(true) //in case the unit state event failed from a recursive damage event
//All events have run and the damage amount is finalized.
set life = GetWidgetLife(u)
set udg_DmgEvTrig = CreateTrigger()
call TriggerAddCondition(udg_DmgEvTrig, Filter(function PreCheckDamagedLifeEvent))
if not udg_IsDamageSpell then
if udg_DamageEventAmount != prevAmount then
set life = life + prevAmount - udg_DamageEventAmount
if GetUnitState(u, UNIT_STATE_MAX_LIFE) < life then
set udg_LastDamageHP = life - prevAmount
call UnitAddAbility(u, udg_DamageBlockingAbility)
endif
call SetWidgetLife(u, RMaxBJ(life, 0.42))
endif
call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, LESS_THAN, RMaxBJ(0.41, life - prevAmount/2.00))
else
set udg_LastDamageHP = GetUnitState(u, UNIT_STATE_MAX_LIFE)
set prevLife = life
if life + prevAmount*0.75 > udg_LastDamageHP then
set life = RMaxBJ(udg_LastDamageHP - prevAmount/2.00, 1.00)
call SetWidgetLife(u, life)
set life = (life + udg_LastDamageHP)/2.00
else
set life = life + prevAmount*0.50
endif
set udg_LastDamageHP = prevLife - (prevAmount - (prevAmount - udg_DamageEventAmount))
call TriggerRegisterUnitStateEvent(udg_DmgEvTrig, u, UNIT_STATE_LIFE, GREATER_THAN, life)
endif
endif
set u = null
set f = null
return false
endfunction
function CreateDmgEvTrg takes nothing returns nothing
set udg_DamageEventTrigger = CreateTrigger()
call TriggerAddCondition(udg_DamageEventTrigger, Filter(function OnUnitDamage))
endfunction
function SetupDmgEv takes nothing returns boolean
local integer i = udg_UDex
local unit u
if udg_UnitIndexEvent == 1.00 then
set u = udg_UDexUnits[i]
if GetUnitAbilityLevel(u, 'Aloc') == 0 and TriggerEvaluate(gg_trg_Damage_Engine_Config) then
set udg_UnitDamageRegistered[i] = true
call TriggerRegisterUnitEvent(udg_DamageEventTrigger, u, EVENT_UNIT_DAMAGED)
call UnitAddAbility(u, udg_SpellDamageAbility)
call UnitMakeAbilityPermanent(u, true, udg_SpellDamageAbility)
endif
set u = null
else
set udg_HideDamageFrom[i] = false
if udg_UnitDamageRegistered[i] then
set udg_UnitDamageRegistered[i] = false
set udg_DamageEventsWasted = udg_DamageEventsWasted + 1
if udg_DamageEventsWasted == 32 then //After 32 registered units have been removed...
set udg_DamageEventsWasted = 0
//Rebuild the mass EVENT_UNIT_DAMAGED trigger:
call DestroyTrigger(udg_DamageEventTrigger)
call CreateDmgEvTrg()
set i = udg_UDexNext[0]
loop
exitwhen i == 0
if udg_UnitDamageRegistered[i] then
call TriggerRegisterUnitEvent(udg_DamageEventTrigger, udg_UDexUnits[i], EVENT_UNIT_DAMAGED)
endif
set i = udg_UDexNext[i]
endloop
endif
endif
endif
return false
endfunction
//===========================================================================
function InitTrig_Damage_Engine takes nothing returns nothing
local unit u = CreateUnit(Player(bj_PLAYER_NEUTRAL_EXTRA), 'uloc', 0, 0, 0)
local integer i = bj_MAX_PLAYERS //Fixed in 3.8
//Create this trigger with UnitIndexEvents in order add and remove units
//as they are created or removed.
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 2.00)
call TriggerAddCondition(t, Filter(function SetupDmgEv))
set t = null
//Run the configuration trigger to set all configurables:
if gg_trg_Damage_Engine_Config == null then
//It's possible this InitTrig_ function ran first, in which case use ExecuteFunc.
call ExecuteFunc("Trig_Damage_Engine_Config_Actions")
else
call TriggerExecute(gg_trg_Damage_Engine_Config)
endif
//Create trigger for storing all EVENT_UNIT_DAMAGED events.
call CreateDmgEvTrg()
//Create GUI-friendly trigger for cleaning up after UnitDamageTarget.
set udg_ClearDamageEvent = CreateTrigger()
call TriggerAddCondition(udg_ClearDamageEvent, Filter(function PreCheckDamagedLifeEvent))
//Disable SpellDamageAbility for every player.
loop
set i = i - 1
call SetPlayerAbilityAvailable(Player(i), udg_SpellDamageAbility, false)
exitwhen i == 0
endloop
//Preload abilities.
call UnitAddAbility(u, udg_DamageBlockingAbility)
call UnitAddAbility(u, udg_SpellDamageAbility)
call RemoveUnit(u)
set u = null
endfunction
function Trig_OnDamage_Actions takes nothing returns nothing
local unit u1 = udg_DamageEventSource
local unit u2 = udg_DamageEventTarget
local player p1 = GetOwningPlayer(u1)
local player p2 = GetOwningPlayer(u2)
local integer id1 = GetPlayerId(p1)
local integer id2 = GetPlayerId(p2)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local real tx = GetUnitX(u2)
local real ty = GetUnitY(u2)
local real x3
local real y3
local real a = Atan2 (ty - cy, tx - cx)
local integer c
local real r
local real r2
local unit d
local unit u3
local effect fx
local real hp1 = GetUnitState(u1, UNIT_STATE_LIFE)
local real hp2 = GetUnitState(u2, UNIT_STATE_LIFE)
local group g
set udg_DamageMod = 1.
set udg_DamageAdd = 0
// Blazing Arms
if udg_IsDamageSpell and GetUnitAbilityLevel(u2, 'B005') > 0 then
set udg_DamageMod = udg_DamageMod + 0.15
endif
// Ironclad
if GetUnitAbilityLevel(u2, 'A00L') > 0 and GetPlayerTechCount(p1, 'R00D', true) > 0 and (IsUnitType(u1, UNIT_TYPE_MECHANICAL) or IsUnitType(u1, UNIT_TYPE_STRUCTURE)) then
set udg_DamageMod = udg_DamageMod - 0.25
endif
// Vanguard
if GetUnitAbilityLevel(u2, 'B009') > 0 then
set c = 0
loop
set c = c + 1
exitwhen c > udg_MVan_I
if u2 == udg_MVan_C[c] and udg_MVan_Str[c] > 0 then
set r = udg_DamageEventAmount
set udg_DamageEventAmount = RMaxBJ(udg_DamageEventAmount - udg_MVan_Str[c], 0.)
set udg_MVan_Str[c] = udg_MVan_Str[c] - r
endif
endloop
endif
// Pyromancer
// Burning Man
if udg_IsDamageSpell and GetUnitAbilityLevel(u1, 'B00J') > 0 then
set udg_DamageMod = udg_DamageMod + 0.35
endif
// Living Bomb
if GetUnitAbilityLevel(u2, 'B00D') > 0 then
set udg_DamageMod = udg_DamageMod + 0.3
endif
// Physical Damage
if not udg_IsDamageSpell then
// Challenger
if GetUnitAbilityLevel(u1, 'A01H') > 0 and GetUnitAbilityLevel(u1, 'B00L') == 0 and GetUnitAbilityLevel(u2, 'B00L') == 0 and not IsUnitType(u2, UNIT_TYPE_HERO) and IsUnitEnemy(u2, p1) then
call IssueTargetOrder(u2, "attack", u1)
set fx = AddSpecialEffectTarget("war3mapImported\\DefendCaster2.mdx", u1, "origin")
call BlzSetSpecialEffectHeight(fx, 40)
call BlzSetSpecialEffectOrientation(fx, 0, 0, a)
call DestroyEffect(fx)
// Challenged
call UnitAddAbility(udg_UDummies[0], 'A01I')
call IssueTargetOrder(udg_UDummies[0], "bloodlust", u2)
call UnitRemoveAbility(udg_UDummies[0], 'A01I')
// Duel
call UnitAddAbility(udg_UDummies[0], 'A01L')
call IssueTargetOrder(udg_UDummies[0], "slow", u2)
call UnitRemoveAbility(udg_UDummies[0], 'A01L')
if udg_MChal_I == 0 then
call EnableTrigger(gg_trg_IR_Challenger)
endif
set udg_MChal_I = udg_MChal_I + 1
set udg_MChal_T[udg_MChal_I] = 2
set udg_MChal_U1[udg_MChal_I] = u1
set udg_MChal_U2[udg_MChal_I] = u2
endif
// Relentless Aim
if GetUnitAbilityLevel(u1, 'A016') > 0 and ((Distance(cx, cy, tx, ty) + GetUnitFlyHeight(u2)) > 420. or GetUnitAbilityLevel(u2, 'B00K') > 0) and not IsUnitType(u2, UNIT_TYPE_MECHANICAL) and not IsUnitType(u2, UNIT_TYPE_STRUCTURE) then
set r = (3 + (9 * I2R(GetUnitAbilityLevel(u1, 'A016'))))
if GetUnitAbilityLevel(u2, 'B00K') > 0 then
set r = r + r
endif
set udg_DamageAdd = udg_DamageAdd + r
set fx = AddSpecialEffectTarget("Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl", u2, "chest")
call BlzSetSpecialEffectScale(fx, 1.4)
call DestroyEffect(fx)
endif
// Valiant Charge
if GetUnitAbilityLevel(u1, 'A00C') > 0 and GetPlayerTechCount(p1, 'R00B', true) > 0 and (GetRandomInt(0, 100) < 21 or GetUnitAbilityLevel(u2, 'B00K') > 0) and IsUnitEnemy(u1, p2) then
if not IsUnitType(u2, UNIT_TYPE_STRUCTURE) then
set fx = AddSpecialEffect("war3mapImported\\Valiant Rush.mdx", cx, cy)
call BlzSetSpecialEffectHeight(fx, 90.)
call BlzSetSpecialEffectOrientation(fx, 0, 0, a)
call DestroyEffect(fx)
set udg_KB3D_Unit = u1
set udg_KB3D_Range = 180.00
set udg_KB3D_Speed = ( GetUnitMoveSpeed(u1) * 1.50 )
set udg_KB3D_Angle = bj_RADTODEG * a
set udg_KB3D_Bounce_Power = 1.0
set udg_KB3D_Bounce_Target = true
set udg_KB3D_EndFx = ""
set udg_KB3D_AoEKB = true
set udg_KB3D_AoEKB_Power = 1.00
set udg_KB3D_EndwhenDead = false
set udg_KB3D_KBTarget = false
set udg_KB3D_StopTime = 0.00
//set udg_KB3D_EndOnTargetBounce = true
set udg_KB3D_KillatEnd = false
set udg_KB3D_AllowOutSiding = false
set udg_KB3D_AoE = 160.00
set udg_KB3D_DisableUnit = true
set udg_KB3D_D_MECHANICAL = true
set udg_KB3D_D_RESISTANT = false
set udg_KB3D_EndWhenHit = false
set udg_KB3D_FaceAngle = true
set udg_KB3D_Fx = ""
//set udg_KB3D_Fx_Attach = "origin"
set udg_KB3D_iKB = true
//set udg_KB3D_TrailFx = "Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl"//"war3mapImported\\Valiant Charge.mdx"
set udg_KB3D_UnpathableStop = true
set udg_SW_Max = ( udg_SW_Max + 1 )
set udg_SW_Caster[udg_SW_Max] = u1
set udg_SW_Point[0] = GetUnitLoc(u1)
set udg_SW_Point[1] = GetUnitLoc(u2)
set udg_SW_Lvl[udg_SW_Max] = 1
set udg_SW_WaveEffect[udg_SW_Max] = ""
set udg_SW_WaveEffectEnd[udg_SW_Max] = " "
set udg_SW_LoopingSfx[udg_SW_Max] = false
set udg_SW_ExtraEffectTargetCheck[udg_SW_Max] = false
set udg_SW_AffectAlly[udg_SW_Max] = false
set udg_SW_AffectEnemy[udg_SW_Max] = true
set udg_SW_AffectAir[udg_SW_Max] = false
set udg_SW_AffectGround[udg_SW_Max] = true
set udg_SW_AffectStructure[udg_SW_Max] = false
set udg_SW_OneInstance[udg_SW_Max] = true
set udg_SW_AttackType[udg_SW_Max] = ATTACK_TYPE_NORMAL
set udg_SW_DamageType[udg_SW_Max] = DAMAGE_TYPE_MAGIC
set udg_SW_Attachment = "origin"
set udg_SW_Damage[1] = 60.00
set udg_SW_AreaInitial[1] = 180.00
set udg_SW_AreaFinal[1] = 180.00
set udg_SW_Speed[1] = udg_KB3D_Speed
set udg_SW_Distance[1] = 240.00
call TriggerExecute( gg_trg_Shockwave_Cast )
call ExecuteFunc( "KB3D_Registration" )
call SetUnitX(udg_UDummies[0], tx)
call SetUnitY(udg_UDummies[0], ty)
call UnitAddAbility(udg_UDummies[0], 'A01C')
call IssueTargetOrder(udg_UDummies[0], "creepthunderbolt", u2)
call UnitRemoveAbility(udg_UDummies[0], 'A01C')
else
//call UnitDamageTarget( u1, u2, 90., false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS )
endif
endif
// Iron Will
if GetUnitAbilityLevel(u1, 'A007') > 0 and udg_CritDid[id1] > 0 then
set udg_DamageMod = udg_DamageMod + 1
set udg_TempText = CreateTextTagUnitBJ( ( I2S( R2I(250)) + "%!" ), u2, 0, 11.00, 100, 0.00, 0.00, 0 )
call SetTextTagVelocityBJ( udg_TempText, 112.00, 90 )
call SetTextTagPermanentBJ( udg_TempText, false )
call SetTextTagLifespanBJ( udg_TempText, 1.00 )
call RemoveLocation(udg_TempPoint)
set udg_TempText = null
set fx = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl", u2, "origin")
call BlzSetSpecialEffectHeight(fx, 50.)
call BlzSetSpecialEffectScale(fx, 1.5)
call DestroyEffect(fx)
endif
// Pride & Prejudice
if GetUnitAbilityLevel(u2, 'A00B') > 0 and udg_Gary_PnP[id2] != null then
call SetUnitState(u2, UNIT_STATE_MANA, (GetUnitState(u2, UNIT_STATE_MANA) + 5))
endif
set udg_CritDid[id1] = 0.
endif
//End
set udg_DamageEventAmount = udg_DamageEventAmount + udg_DamageAdd
set udg_DamageEventAmount = udg_DamageEventAmount * udg_DamageMod
// Post-Mod
// Demolition
if not udg_IsDamageSpell and GetUnitAbilityLevel(u1, 'A01B') > 0 and GetPlayerTechCount(p1, 'R00P', true) > 0 and IsUnitType(u2, UNIT_TYPE_STRUCTURE) and hp2 - udg_DamageEventAmount <= (GetUnitState(u2, UNIT_STATE_MAX_LIFE) * 0.15) then
call SetUnitState(u2, UNIT_STATE_LIFE, 1)
set fx = AddSpecialEffectTarget("war3mapImported\\Tank Shell Silver.mdx", u2, "origin")
call BlzSetSpecialEffectScale(fx, 1 + (BlzGetUnitCollisionSize(u2) * 0.025))
call BlzSetSpecialEffectHeight(fx, 120.)
call DestroyEffect(fx)
endif
// Mark of Chaos
if GetUnitAbilityLevel(u2, 'B00K') > 0 and hp2 - udg_DamageEventAmount <= 0.41 then
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl", tx, ty))
if udg_MDelB_I == 0 then
call EnableTrigger(gg_trg_Delayed_Blast)
endif
set udg_MDelB_I = udg_MDelB_I + 1
set udg_MDelB_A[udg_MDelB_I] = 180
set udg_MDelB_C[udg_MDelB_I] = u1
set udg_MDelB_FXA[udg_MDelB_I] = "war3mapImported\\Living Bomb.mdx"
set udg_MDelB_FXB[udg_MDelB_I] = ""
set udg_MDelB_FXS[udg_MDelB_I] = 1
set udg_MDelB_ID[udg_MDelB_I] = 2
set udg_MDelB_R[udg_MDelB_I] = 250
set udg_MDelB_T[udg_MDelB_I] = 0.4
set udg_MDelB_X[udg_MDelB_I] = tx
set udg_MDelB_Y[udg_MDelB_I] = ty
endif
// Orb of Judgement
if not IsHuman(u2) and GetInventoryIndexOfItemTypeBJ(u1, 'I007') > 0 and not IsUnitType(u2, UNIT_TYPE_MECHANICAL) and not IsUnitType(u2, UNIT_TYPE_STRUCTURE) and hp2 - udg_DamageEventAmount <= (GetUnitState(u2, UNIT_STATE_MAX_LIFE) * 0.18) then
call SetUnitState(u2, UNIT_STATE_LIFE, 1)
set fx = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl", u2, "origin")
call BlzSetSpecialEffectHeight(fx, 50.)
call DestroyEffect(fx)
set fx = AddSpecialEffectTarget("Abilities\\Weapons\\HydraliskImpact\\HydraliskImpact.mdl", u2, "origin")
call BlzSetSpecialEffectHeight(fx, 50.)
call DestroyEffect(fx)
set fx = AddSpecialEffectTarget("Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl", u2, "origin")
call BlzSetSpecialEffectHeight(fx, 50.)
call BlzSetSpecialEffectScale(fx, 1.5)
call DestroyEffect(fx)
set fx = AddSpecialEffectTarget("war3mapImported\\Alpha Strike 07.mdl", u2, "origin")
call BlzSetSpecialEffectHeight(fx, 50.)
call DestroyEffect(fx)
endif
set u1 = null
set u2 = null
set u3 = null
set d = null
set p1 = null
set p2 = null
set fx = null
set g = null
endfunction
//===========================================================================
function InitTrig_OnDamage takes nothing returns nothing
set gg_trg_OnDamage = CreateTrigger( )
call TriggerRegisterVariableEvent( gg_trg_OnDamage, "udg_DamageModifierEvent", EQUAL, 1.00 )
call TriggerAddAction( gg_trg_OnDamage, function Trig_OnDamage_Actions )
endfunction
function AfterDamage01 takes nothing returns nothing
local unit u1 = udg_DamageEventSource
local unit u2 = udg_DamageEventTarget
local player p1 = GetOwningPlayer(u1)
local player p2 = GetOwningPlayer(u2)
local real cx = GetUnitX(u1)
local real cy = GetUnitY(u1)
local real tx = GetUnitX(u2)
local real ty = GetUnitY(u2)
local real x3
local real y3
local real a = Atan2 (ty - cy, tx - cx)
local integer c
local real r1
local real r2
local unit d
local unit u3
local effect fx
local real hp1 = GetUnitState(u1, UNIT_STATE_LIFE)
local real hp2 = GetUnitState(u2, UNIT_STATE_LIFE)
local group g
// Road to Ruin
if IsUnitType(u2, UNIT_TYPE_STRUCTURE) and GetPlayerTechCount(p1, 'R006', true) > 0 /*
*/and not udg_IsDamageSpell and GetUnitAbilityLevel(u1, 'A009') > 0 and hp2 <= 0.41 then
set r1 = BlzGetUnitCollisionSize(u2)
if r1 < 80 then
set r1 = 80
endif
// Delayed Blast
if udg_MDelB_I == 0 then
call EnableTrigger(gg_trg_Delayed_Blast)
endif
set udg_MDelB_I = udg_MDelB_I + 1
set udg_MDelB_A[udg_MDelB_I] = 100
set udg_MDelB_C[udg_MDelB_I] = u1
set udg_MDelB_FXA[udg_MDelB_I] = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
set udg_MDelB_FXB[udg_MDelB_I] = ""
set udg_MDelB_FXS[udg_MDelB_I] = 1 + (r1 * 0.01)
set udg_MDelB_ID[udg_MDelB_I] = 1
set udg_MDelB_R[udg_MDelB_I] = 240 + r1
set udg_MDelB_T[udg_MDelB_I] = 0.6
set udg_MDelB_X[udg_MDelB_I] = GetUnitX(u2)
set udg_MDelB_Y[udg_MDelB_I] = GetUnitY(u2)
endif
set u1 = null
set u2 = null
set u3 = null
set d = null
set p1 = null
set p2 = null
set fx = null
set g = null
endfunction
//===========================================================================
function InitTrig_AfterDamage takes nothing returns nothing
set gg_trg_AfterDamage = CreateTrigger( )
call TriggerRegisterVariableEvent( gg_trg_AfterDamage, "udg_AfterDamageEvent", EQUAL, 1.00 )
call TriggerAddAction( gg_trg_AfterDamage, function AfterDamage01 )
endfunction
function MDelBMain takes nothing returns nothing
local effect f
local integer i = 0
loop
set i = i + 1
exitwhen i > udg_MDelB_I
set udg_MDelB_T[i] = udg_MDelB_T[i] - 0.2
if udg_MDelB_T[i] <= 0. then
if udg_MDelB_ID[i] == 1 then
call DisableTrigger(gg_trg_AfterDamage)
call MAreaDamageS(udg_MDelB_C[i], udg_MDelB_A[i], 1., udg_MDelB_R[i], udg_MDelB_FXB[i], udg_MDelB_X[i], udg_MDelB_Y[i], ATTACK_TYPE_SIEGE)
call EnableTrigger(gg_trg_AfterDamage)
elseif udg_MDelB_ID[i] == 2 then
call MAreaDamage(udg_MDelB_C[i], udg_MDelB_A[i], 1., udg_MDelB_R[i], udg_MDelB_FXB[i], udg_MDelB_X[i], udg_MDelB_Y[i], ATTACK_TYPE_NORMAL)
elseif udg_MDelB_ID[i] == 3 then
call MAreaODamage(udg_MDelB_C[i], udg_MDelB_A[i], 1., udg_MDelB_R[i], udg_MDelB_FXB[i], udg_MDelB_X[i], udg_MDelB_Y[i], ATTACK_TYPE_NORMAL)
endif
set f = AddSpecialEffect(udg_MDelB_FXA[i], udg_MDelB_X[i], udg_MDelB_Y[i])
call BlzSetSpecialEffectScale(f, udg_MDelB_FXS[i])
call DestroyEffect(f)
set udg_MDelB_A[i] = udg_MDelB_A[udg_MDelB_I]
set udg_MDelB_C[i] = udg_MDelB_C[udg_MDelB_I]
set udg_MDelB_FXA[i] = udg_MDelB_FXA[udg_MDelB_I]
set udg_MDelB_FXB[i] = udg_MDelB_FXB[udg_MDelB_I]
set udg_MDelB_FXS[i] = udg_MDelB_FXS[udg_MDelB_I]
set udg_MDelB_ID[i] = udg_MDelB_ID[udg_MDelB_I]
set udg_MDelB_R[i] = udg_MDelB_R[udg_MDelB_I]
set udg_MDelB_T[i] = udg_MDelB_T[udg_MDelB_I]
//set udg_MDelB_TC[i] = udg_MDelB_TC[udg_MDelB_I]
set udg_MDelB_X[i] = udg_MDelB_X[udg_MDelB_I]
set udg_MDelB_Y[i] = udg_MDelB_Y[udg_MDelB_I]
set udg_MDelB_ID[udg_MDelB_I] = 0
set udg_MDelB_I = udg_MDelB_I - 1
set i = i - 1
if udg_MDelB_I == 0 then
call DisableTrigger(GetTriggeringTrigger())
endif
endif
endloop
set f = null
endfunction
//===========================================================================
function InitTrig_Delayed_Blast takes nothing returns nothing
set gg_trg_Delayed_Blast = CreateTrigger( )
call TriggerRegisterTimerEventPeriodic( gg_trg_Delayed_Blast, .2 )
call TriggerAddAction( gg_trg_Delayed_Blast, function MDelBMain )
call DisableTrigger(gg_trg_Delayed_Blast)
endfunction
//TESH.scrollpos=12
//TESH.alwaysfold=0
constant function GetAMSBuffId takes nothing returns integer
return 'Bams'
endfunction
constant function GetAMSAbilId takes nothing returns integer
return 'A002'
endfunction
constant function GetAMSShieldVal takes nothing returns real
return 300.00
endfunction
function Trig_Anti_Magic_Shield_Fix_Actions takes nothing returns nothing
local integer id = GetUnitUserData(udg_DamageEventTarget)
local real shield = udg_AMSAmount[id]- udg_DamageEventAmount
if shield <= 0.00 then
set udg_DamageEventAmount = -shield
set shield = 0.00
call UnitRemoveAbility(udg_DamageEventTarget, GetAMSBuffId())
else
set udg_DamageEventAmount = 0.00
if udg_DamageEventType == 0 then
set udg_DamageEventType = udg_DamageTypeBlocked
endif
endif
set udg_AMSAmount[id] = shield
endfunction
function Trig_Anti_Magic_Shield_Fix_Conditions takes nothing returns boolean
if udg_IsDamageSpell then
if GetUnitAbilityLevel(udg_DamageEventTarget, GetAMSBuffId()) > 0 then
call Trig_Anti_Magic_Shield_Fix_Actions()
else
set udg_AMSAmount[GetUnitUserData(udg_DamageEventTarget)] = 0.00
endif
endif
return false
endfunction
function AMS_Refresh_Conditions takes nothing returns boolean
if GetSpellAbilityId() == GetAMSAbilId() then
set udg_AMSAmount[GetUnitUserData(GetSpellTargetUnit())] = GetAMSShieldVal()
endif
return false
endfunction
function InitTrig_Anti_Magic_Shield_Fix takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "udg_DamageModifierEvent", EQUAL, 4.00)
call TriggerAddCondition(t, Condition(function Trig_Anti_Magic_Shield_Fix_Conditions))
set t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Filter(function AMS_Refresh_Conditions))
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
function KB3D_Features_JASS takes nothing returns nothing
// Those Values are Required for the KB
// ------------------------------------------------
// ------------------------
// Knock-Backed Unit, the Knock-Backed Unit who all actions orbit around
set udg_KB3D_Unit = null
// Requires: NONE
// ------------------------
// Max Range, Maximum Range possible of the Knock-Back
set udg_KB3D_Range = 0.00
// Requires: NONE
// ------------------------
// Base KB Speed, Base Speed when starting the Knock-Back
set udg_KB3D_Speed = 0.00
// Requires: NONE
// ------------------------
// Angle, The KB's line angle, this will be useless if KB3D_Targeted_Unit is not null
set udg_KB3D_Angle = 0.00
// Requires: NONE
// ------------------------
// ------------------------------------------------
// Those Values are Optional for the KB
// NOTE: some values may depend on other to function, like LineDamage that needs "Damager, AttackType, DamageType, AoE" to function
// ------------------------------------------------
// ------------------------
// Targets Allowed
// ------------------------
// Filter Damages and AoEKB with those values, if true, each one will allow filtering of Structures, Mechanicals, Magic Imminues, Allies
// ------------------------
set udg_KB3D_D_MAGIC_IMMINUE = false
set udg_KB3D_D_ALLY = false
set udg_KB3D_D_MECHANICAL = false
set udg_KB3D_D_STRUCTURE = false
set udg_KB3D_D_ENEMY = true
set udg_KB3D_D_FLYING = false
set udg_KB3D_D_RESISTANT = false
// Requires: AoEKB, or, Damagers, or, BounceTarget
// ------------------------
// Speed Changer, makes the unit move forward with a bonus speed equal to the KB speed, negative speed also works
set udg_KB3D_Speed_Changer = false
// Requires: NONE, Disables Angle
// ------------------------
// Homing Missile, automatically sets needed features of KB3D for a homing missile
set udg_KB3D_HomingMissile = true
// Requires: NONE, Disables Angle
// ------------------------
// Bounce Unit, Makes the KBed unit bounce on unpathable areas and units
set udg_KB3D_Bounce_Unit = false
// Requires: NONE
// ------------------------
// Bounce Targets, Bounces units that encounter the KBed unit
set udg_KB3D_Bounce_Target = false
// Requires: AoE
// ------------------------
// End on Target Bounce, when hits a unit, ends the KB
set udg_KB3D_EndOnTargetBounce = false
// Requires: Bounce_Target
// ------------------------
// Bounce Power, intensity of the Bounce
set udg_KB3D_Bounce_Power = 1.00
// Requires: Bounce
// ------------------------
// Bounce Effect, Effect created on units that get Bounced
set udg_KB3D_Bounce_Fx = ""
// Requires: Bounce
// ------------------------
// Destroy Destructibles, Destroys any destructibles on the path of the KB, does not destroy platforms, bridges, elevators
set udg_KB3D_DestroyDestructables = false
// Requires: Line Damage
// ------------------------
// Line Effect, Effect created on units damaged by Line Damage
set udg_KB3D_Line_Fx = ""
// Requires: Line Damage
// ------------------------
// End Trigger, This trigger will be excecuted at the end of the KB, you can use KB3D_Unit and KB3D_Targeted_Unit variables in the trigger
set udg_KB3D_EndTrigger = udg_KB3D_EndTrigger
// Requires: NONE
// ------------------------
// End on Obstacle, Immediatly Ends the KB if the KBed unit encounters an unpathable area
set udg_KB3D_EndOnObstacle = false
// Requires: NONE
// ------------------------
// Arc, Arc of the Angle of the KB, does not work with homing KB
set udg_KB3D_Arc = 0.00
// Requires: Angle
// ------------------------
// Ending Effect, an Effect created at the End of the KB on the KBed Unit
set udg_KB3D_EndFx = ""
// Requires: AoE
// ------------------------
// AoE End Damage, Damage dealt to enemy units in the AoE at the End of the KB
set udg_KB3D_AoEEndDamage = 0.00
// Requires: AoE, Damager, AType, DType
// ------------------------
// AoE KB, if true, KBs Enemy units within the AoE, Range, Speed, Angle, are automatic
set udg_KB3D_AoEKB = false
// Requires: AoE
// ------------------------
// AoE KB Power, The Power of the AoE KB, default value is 1.00 (normal), Min value: 0.01, Max value: 3.00
set udg_KB3D_AoEKB_Power = 0.00
// Requires: AoEKB
// ------------------------
// End when Dead, if true, the KB will end if the KBed unit is dead, TRUE by default
set udg_KB3D_EndwhenDead = true
// Requires: NONE
// ------------------------
// Ground Damage, Damages the Unit When it hits the Ground, Damage dealt is KB3D_ImpactDamage
set udg_KB3D_GroundDamage = false
// Requires: Damager, ImpactDamage, AType, DType
// ------------------------
// KB the Target, When the Targeted Unit is hit, it will be KBed depending on the speed of the original KB
set udg_KB3D_KBTarget = false
// Requires: Targeted_Unit
// ------------------------
// Stop Time, Maximum Time the KB will last, Note that if the KBed unit is flying at this time, it will be stuck
set udg_KB3D_StopTime = 0.00
// Requires: NONE
// ------------------------
// Kill at End, Kills the KBed Unit at the End of the KB
set udg_KB3D_KillatEnd = false
// Requires: NONE
// ------------------------
// Kill at Time, When this time is reached, the KBed unit will be killed, if this number is higher than KB3D_StopTime, EndWhenDead will be automatically turned on no matter what
set udg_KB3D_KillatTime = 0.00
// Requires: NONE
// ------------------------
// Acceleration, Speed Added/s to the KB speed
set udg_KB3D_Accel = 0.00
// Requires: NONE
// ------------------------
// Allow going outside playable bounds, Allows the KBed unit to go out of the Playable Bounds, SAFETY notice: this will not crash the game
set udg_KB3D_AllowOutSiding = false
// Requires: NONE
// ------------------------
// Area of Effect, Range where the Line Damage is applied to units
set udg_KB3D_AoE = 0.00
// Requires: NONE
// ------------------------
// Area of Effect Damage, Makes the KB3D_Damager, damage enemy units within KB3D_AoE by this value as a DPS
set udg_KB3D_AoEDamage = 0.00
// Requires: AoE, Damager, DType, AType
// ------------------------
// Attack Type, Attack type of ALL damagings in the Instance
set udg_KB3D_AttackType = ATTACK_TYPE_MELEE
// Requires: NONE
// ------------------------
// Damage Type, Damage type of ALL damagings in the Instance
set udg_KB3D_DamageType = DAMAGE_TYPE_MAGIC
// Requires: NONE
// ------------------------
// Damager, Source of ALL damagings in the Instance
set udg_KB3D_Damager = null
// Requires: NONE
// ------------------------
// Destroy Trees?, Destroy Trees around the KBed unit while he is KBed?
set udg_KB3D_DestroyTree = true
// Requires: NONE
// ------------------------
// Disable Unit?, Disable the KBed Unit's Movement and Turning?
set udg_KB3D_DisableUnit = false
// Requires: NONE
// ------------------------
// End When Hit?, Ends the KB if the KBed Unit hits the Targeted Unit
set udg_KB3D_EndWhenHit = false
// Requires: Targeted_Unit
// ------------------------
// Face KB Anlge, makes the KBed Unit Face the Anlge of the KB during the KB
set udg_KB3D_FaceAngle = false
// Requires: NONE
// ------------------------
// Effect, Effect created on the Unit's Location if he is not flying, and applied on the Unit if he is flying on the Attach Point
set udg_KB3D_Fx = ""
// Requires: Attach
// ------------------------
// Attachment Point, location on the KBed unit where Effects are attached
set udg_KB3D_Attach = ""
// Requires: NONE
// ------------------------
// AoE End Effect, Effect Created on target units in the AoE at the End of the KB
set udg_KB3D_AoEEndFx = ""
// Requires: AoE, Attach
// ------------------------
// Impact Damage, Damaged dealt to the KBed Unit if he hits an obstacle
set udg_KB3D_ImpactDamage = 0.00
// Requires: Damager
// ------------------------
// intelligent KB, Enables the intelligent features of KB3D, see Main Code Comments for more info
set udg_KB3D_iKB = true
// Requires: NONE
// ------------------------
// Kill When Hit?, Kills the KBed Unit if he hits the Targeted Unit, Automatically set EndWhenHit to true
set udg_KB3D_KillWhenHit = false
// Requires: Targeted_Unit
// ------------------------
// Kill if Out of Playable Bounds, Kills the KBed Unit if he gets out of Playable Bounds, this automatically sets KB3D_AllowOutSiding to TRUE
set udg_KB3D_KillifOutSider = false
// Requires: AllowOutSiding
// ------------------------
// Line Damage, Damage dealt to enemy units in the AoE around the KBed Unit
set udg_KB3D_LineDamage = 0.00
// Requires: Damager, AoE
// ------------------------
// Loop Damage, DPS dealt to the KBed Unit
set udg_KB3D_LoopDamage = 0.00
// Requires: Damager, AoE
// ------------------------
// Jump over Cliff, Allows the KBed unit to go over cliffs if he has more than 150 fly height and IF there is a possible location where he can land in a pathable point, not recommended with >0 Acceleration
set udg_KB3D_JumpOverCliff = false
// Requires: NONE
// ------------------------
// Target Damage, Damage dealt to the Targeted Unit when both KBed Unit and Targeted Unit hit each other, only happens once
set udg_KB3D_TargetDamage = 0.00
// Requires: Targeted_Unit, Damager
// ------------------------
// Targeted Unit, if not null, makes the KBed Unit act like a homing missile targeting this unit, it also used for other functions
set udg_KB3D_Targeted_Unit = null
// Requires: NONE
// ------------------------
// Trail Effect, Effect Attached on the KBed Unit all along the Knock-Back and Destroyed at the end of the KB
set udg_KB3D_TrailFx = ""
// Requires: Attach
// ------------------------
// Stop at Unpathable, Makes it impossible for the KBed Unit to path throught Unpathable Terrain
set udg_KB3D_UnpathableStop = true
// Requires: NONE
// ------------------------
// Z Offset, Max Flying Height reached while Knockbacking
set udg_KB3D_Zoffset = 0.00
// Requires: NONE
// ------------------------
// ------------------------------------------------
// Registed All of the Settings
call ExecuteFunc( "KB3D_Registration" )
// You can use the following to know how much the knock-back will last -- this can vary if the KB is homed on a moving unit
set udg_KB3D_Time = udg_KB3D_Time
endfunction
//===========================================================================
function InitTrig_KB3D_Features_JASS takes nothing returns nothing
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
/////////////////////////////////////////////////////////////////////////////
// //
// Knock-Back 3D [JASS - GUI] V. 3.2.1 //
// Multi-Movement System 3D //
// by Jad aka DotCa and T.D.W. //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// System's Hidden Features: //
// //
// 1. To know if a unit is being KBed by the System, Use: //
// - LoadBoolean(udg_KB3D_HA, GetHandleId(Unit), GetHandleId(Unit)) //
// True means that the unit is being KBed, also works in GUI //
// 2. Use udg_KB3D_Time variable after registring the KB to actually //
// know how much the KB will last, NOTE that this the time may //
// varry if you have a Homing KB (using KB3D_Targeted_Unit) //
// 3. Some Variables in the System has default values, but useful; //
// in Example, "udg_KB3D_Attach" is "origin" even without setting //
// it, so you won't need to change it before Registering a KB //
// 4. You can get the ID of a Knockback after registrating it by //
// using the value of KB3D_Counter //
// 5. You can remove any KB on a specific unit by setting KB3D_Remove //
// KB3D_RemoveUnit to this Unit, and then calling the function: //
// "KB3D_RemoveUnit() //
// 6. You can know what caused the end of a KB in the EndTrigger by //
// checking those variables: KB3D_EndisUnit / KB3D_EndisUnpathable //
// KB3D_EndisNormal //
// 7. You can use the following Pause/Resume functions on a specific //
// KB instance or on all the system //
// - KB3D_Pause( ID ) Applies on a single KB //
// - KB3D_Resume( ID ) Applies on a single KB //
// - KB3D_PauseAll() Applies on a All KB Instances //
// - KB3D_ResumeAll() Applies on a All KB Instances //
// - KB3D_PauseRegistration() Applies on a All KB Instances //
// - KB3D_ResumeRegistration() Applies on a All KB Instances //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// System Informations: //
// //
// The System is a well performing, ultra-purpose knockback (see uses //
// below ) Coded in JASS making it possible for all users to take //
// advantage of it, and GUI friendly to use, see Examples in the triggers //
// above //
// Configurations that have default values: //
// //
// - KB3D_EndWhenDead ==> TRUE by default //
// - KB3D_UnpathableStop ==> TRUE by default //
// - KB3D_iKB ==> TRUE by default //
// - KB3D_D_ENEMY ==> TRUE by default //
// - KB3D_DestroyTree ==> TRUE by default //
// - KB3D_AttackType ==> ATTACK_TYPE_NORMAL by default //
// - KB3D_DamageType ==> DAMAGE_TYPE_MAGIC by default //
// - KB3D_AoEKB_Power ==> 1.00 by default //
// - KB3D_Attach ==> "origin" by default //
// - Other Booleans ==> FALSE by default //
// //
// The System also uses Always positive values for some configurations //
// to not make the knockback go wrong, those configurations are: //
// //
// "KB3D_Range" - "KB3D_Speed" - "KB3D_ZOffset" - "KB3D_AoE" //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// HomingMissile, Accessibility feature //
// //
// When true, there will be no need to set the range and some other //
// features, since they will be automatically set to fit a homing //
// missile: //
// - KB3D_Zoffset - KB3D_Range - KB3D_KillatEnd - KB3D_EndWhenHit - //
// - KB3D_FaceAngle - KB3D_UnpathableStop - KB3D_KillWhenHit - //
// //
// This feature allows to skip the configurations of some features //
// needed for a homing missile, Note that Targeted_Unit needs to be set //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// iKB, intelligent KB informations: //
// //
// iKB, makes some features in KB3D act intelligently, those features: //
// //
// -Range: usually always positive, it will be available in negative //
// values, it will, if negative, flip the Angle (+180 d) //
// -Speed: usually always positive, it will be available in negative //
// values, it will act normally, just the KBed unit will //
// move backward if the current speed is negative //
// -Height: usually always positive, it will be available in negative//
// values, it will, if negative, make the unit go down //
// instead of up //
// -Damages: //
// AoEEndDamage, AoEDamage, LineDamage, ImpactDamage, TargetDamage //
// //
// All those values ^ will turn intelligent, by this, it means //
// that if the Target of the Damage is not in approximated //
// height (Z) of the KBed Unit, the damage won't occur //
// -AoEKB, usually KBs all units in the AoE, it will choose only //
// Units that are close to it by the height, Z offset //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// System Requirements: Basic WE - (NONE) //
// //
// The System uses implemented CheckWalkability System by PurgeandFire //
// You "can" remove the initialization trigger of PnF's System since //
// it is directly implemented in the System, all will work fine with or //
// without removing your Initializer trigger //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// Credits: //
// //
// *WEHZ & TS Helpers Group for helping in Script Fixes //
// *Barry the Moose for helping in main codes and fixes //
// *PurgeandFire for his CheckWalkability System //
// *Vexorian / Nestharus for the GetCollision function //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// How to Import? //
// //
// 1. Check that Create Unknown Variables is ticked in your WE Settings //
// 2. Copy the Paste the Knock-Back 3D Folder //
// 3. Delete the Variable Creator Trigger and learn how to use the System //
// by reading the documentation in the 2 Features Triggers (GUI - JASS)//
// Congratulations, the System is now implemented in your map //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// How to Use? //
// //
// 1. There are many Examples of use in the KB3D Example Folder //
// 2. Documentations are there in the Features Triggers to help you //
// 3. The KB3D System is an Ultra-Purpose System where you can use it for://
// -Projectiles, the system supports homing so a projectile is easy //
// -Jump, the System's smoothness in the fly is useful for a jump spell//
// -And of course, a 2D Knock-Back //
// -And More depending on your imagination //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// Bug Reports - Feedbacks //
// //
// * We count on you to report bugs in the system, also telling the source//
// * Feedbacks about the system are much appreciated //
// * We mostly hope suggestions about enhancements for the System //
// //
/////////////////////////////////////////////////////////////////////////////
function KB3D_AlwaysNeg takes real R returns real
if R > 0 then
return -R
endif
return R
endfunction
function KB3D_InBetween takes real Min, real R, real Max returns real
return RMaxBJ(RMinBJ(R, Max), Min)
endfunction
function KB3D_IsInBetween takes real Min, real R, real Max returns boolean
return R > Min and R < Max
endfunction
function KB3D_CW_Loop takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = GetEnumItem()
call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], false)
set udg_CP_HiddenItemsIndex = ( udg_CP_HiddenItemsIndex + 1 )
endif
endfunction
function KB3D_CW takes real x, real y returns boolean
local real x2 = 0
local real y2 = 0
//---------------------------
call MoveRectTo(udg_CP_Rect, x, y)
call EnumItemsInRect(udg_CP_Rect, null, function KB3D_CW_Loop )
call SetItemPosition(udg_CP_Item, x, y)
set x2 = GetItemX(udg_CP_Item)
set y2 = GetItemY(udg_CP_Item)
call SetItemVisible(udg_CP_Item, false)
//---------------------------
loop
exitwhen udg_CP_HiddenItemsIndex == 0
set udg_CP_HiddenItemsIndex = udg_CP_HiddenItemsIndex - 1
call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], true)
set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = null
endloop
//---------------------------
return (((x2-x)*(x2-x) + (y2-y)*(y2-y) <= 75) and (not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)))
endfunction
function KB3D_GetCoordinatesZ takes real x, real y returns real
local location L = Location(x,y)
local real r = 0
local integer I = 0
local integer t = 12
local boolean B = true
loop
exitwhen I == 12
if GetPlayerSlotState(Player(I)) != ConvertPlayerSlotState(1) then
set t = t - 1
else
if IsLocationFoggedToPlayer( L , Player(I)) then
set B = false
set t = t - 1
endif
endif
set I = I + 1
endloop
if B or t == 0 then
set r = GetLocationZ(L)
endif
call RemoveLocation(L)
set L = null
return r
endfunction
function KB3D_Approx takes unit U, unit U2, integer Loop returns boolean
local real r = KB3D_InBetween(50, LoadReal(udg_KB3D_HA, 29, Loop) / 2, 1000)
local real r1 = GetUnitFlyHeight(U2)
//---------------------------
return KB3D_IsInBetween(r1-r, GetUnitFlyHeight(U), r1+r)
endfunction
function KB3D_Filter takes unit U, unit U1, integer Loop returns boolean
if not IsUnitType(U, UNIT_TYPE_DEAD) then
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 48, Loop)) and ( IsUnitType(U, UNIT_TYPE_STRUCTURE)) then
return false
elseif not((LoadBoolean(udg_KB3D_HA, 48, Loop)) and ( IsUnitType(U, UNIT_TYPE_STRUCTURE))) then
if not(LoadBoolean(udg_KB3D_HA, 49, Loop)) and ( IsUnitType(U, UNIT_TYPE_MECHANICAL)) then
return false
endif
endif
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 50, Loop)) and ( IsUnitType(U, UNIT_TYPE_MAGIC_IMMUNE)) then
return false
endif
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 51, Loop)) and ( IsUnitAlly(U, GetOwningPlayer(U1))) then
return false
endif
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 63, Loop)) and ( IsUnitEnemy(U, GetOwningPlayer(U1))) then
return false
endif
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 64, Loop)) and ( IsUnitType(U, UNIT_TYPE_RESISTANT)) then
return false
endif
//---------------------------
if not(LoadBoolean(udg_KB3D_HA, 65, Loop)) and ( IsUnitType(U, UNIT_TYPE_FLYING)) then
return false
endif
//---------------------------
return true
endif
//---------------------------
return false
endfunction
function KB3D_RegisterUnitCollision takes unit u, real x, real y, integer i returns real
local real l = 0
local real h = 300
local real m = 150
local real nm
//---------------------------
loop
if (IsUnitInRangeXY(u, x+m, y, 0)) then
set l = m
else
set h = m
endif
set nm = (l+h)/2
exitwhen nm+.001 > m and nm-.001 < m
set m = nm
endloop
//---------------------------
set m = R2I(m*10)/10.
call SaveReal( udg_KB3D_HA, 16, GetUnitTypeId(u), m )
//---------------------------
return m
endfunction
function KB3D_GetUnitCollision takes unit u returns real
local integer i = GetUnitTypeId(u)
//---------------------------
if HaveSavedReal( udg_KB3D_HA, 16, i) then
return LoadReal(udg_KB3D_HA, 16, i)
endif
//---------------------------
return KB3D_RegisterUnitCollision(u, GetUnitX(u), GetUnitY(u), i)
endfunction
function KB3D_Tree_Check takes destructable D returns boolean
return IssueTargetOrderById( udg_KB3D_Harvester, 852018, D ) and IssueImmediateOrderById(udg_KB3D_Harvester, 851972)
endfunction
function KB3D_KillEnumDest takes nothing returns nothing
local destructable D = GetEnumDestructable()
//---------------------------
if GetDestructableLife(D)>0 and ( KB3D_Tree_Check(D) ) and (GetUnitFlyHeight(LoadUnitHandle(udg_KB3D_HA, 0, R2I(udg_KB3D_Reals[0]))) < GetDestructableOccluderHeight(D)) and LoadBoolean(udg_KB3D_HA, 8, R2I(udg_KB3D_Reals[0])) then
call KillDestructable(D)
elseif /*not(KB3D_CW(GetDestructableX(D),GetDestructableY(D))) and*/ GetDestructableLife(D)>0 and not(KB3D_Tree_Check(D)) and LoadBoolean(udg_KB3D_HA, 56, R2I(udg_KB3D_Reals[0])) then
call KillDestructable(D)
endif
set D = null
endfunction
function KB3D_CircleTreeKill takes real radius, real x, real y returns nothing
local rect r = Rect(x-radius, y-radius, x+radius, y+radius)
//---------------------------
call EnumDestructablesInRect(r, null, function KB3D_KillEnumDest)
//---------------------------
call RemoveRect(r)
set r = null
endfunction
function KB3D_BounceOnUnit takes unit u, unit U, integer Loop returns nothing
set udg_KB3D_Angle = (Atan2(GetUnitY(u) - GetUnitY(U), GetUnitX(u) - GetUnitX(U)) *57.29578) + GetRandomReal(-15,15)
set udg_KB3D_Speed = LoadReal(udg_KB3D_HA, 2, Loop) / .03125 * .25 * LoadReal(udg_KB3D_HA, 59, Loop)
set udg_KB3D_DestroyTree = LoadBoolean(udg_KB3D_HA, 8, Loop)
set udg_KB3D_Fx = LoadStr(udg_KB3D_HA, 9, Loop)
set udg_KB3D_Attach = LoadStr(udg_KB3D_HA, 10, Loop)
set udg_KB3D_Range = 1.5*udg_KB3D_Speed*udg_KB3D_Bounce_Power
set udg_KB3D_Unit = u
set udg_KB3D_Bounce_Fx = LoadStr(udg_KB3D_HA, 62, Loop)
set udg_KB3D_Accel = -udg_KB3D_Speed*.6
set udg_KB3D_Bounce_Unit = true
call TriggerEvaluate(udg_KB3D_Registration)
call SaveEffectHandle(udg_KB3D_HA, 14, udg_KB3D_Counter, LoadEffectHandle(udg_KB3D_HA, 14, Loop))
endfunction
function KB3D_Bounce_Filter takes nothing returns boolean
local boolean b = not(IsUnitInGroup(GetFilterUnit(), LoadGroupHandle(udg_KB3D_HA, 68, R2I(udg_KB3D_Reals[0])))) or KB3D_Filter(LoadUnitHandle(udg_KB3D_HA, 0, R2I(udg_KB3D_Reals[0])),LoadUnitHandle(udg_KB3D_HA, 0, R2I(udg_KB3D_Reals[0])),R2I(udg_KB3D_Reals[0]))
if b then
call GroupAddUnit(LoadGroupHandle(udg_KB3D_HA, 68, R2I(udg_KB3D_Reals[0])), GetFilterUnit())
endif
return b
endfunction
function KB3D_FilterGrp takes nothing returns boolean
return KB3D_Filter(GetFilterUnit(), LoadUnitHandle(udg_KB3D_HA, 0, R2I(udg_KB3D_Reals[0])),R2I(udg_KB3D_Reals[0]))
endfunction
function KB3D_ClearInstance takes integer i returns nothing
local integer x = 0
//---------------------------
call DestroyGroup(LoadGroupHandle(udg_KB3D_HA, 27, i))
call DestroyGroup(LoadGroupHandle(udg_KB3D_HA, 67, i))
//---------------------------
loop
exitwhen x > 100
call RemoveSavedHandle(udg_KB3D_HA, x, i)
call SaveReal(udg_KB3D_HA, x, i, 0)
set x = x +1
endloop
endfunction
function KB3D_isPossiblePathability takes real x, real y, real RADangle, real MaxDist returns boolean
local real X = x
local real Y = y
local real max = RAbsBJ(MaxDist)
local real dist = max
//---------------------------
loop
exitwhen (dist <= 0)
set dist = dist - max/300
set X = x + ( dist * Cos(RADangle) )
set Y = y + ( dist * Sin(RADangle) )
if KB3D_CW(X,Y) then
return true
endif
endloop
//---------------------------
return false
endfunction
function MoveUnit_3D takes unit U, real x, real y, real z, real MaxZ, boolean P, boolean OS, boolean KiOS, real Angle, real S, real time, integer Loop returns boolean
local boolean B = false
local boolean b = true
local real tz
// CREEPY FUNCTION ALERT
if LoadBoolean(udg_KB3D_HA, 57, Loop) then
if LoadBoolean(udg_KB3D_HA, 44, Loop) then
set tz = KB3D_GetCoordinatesZ(x,y) - LoadReal(udg_KB3D_HA, 68, Loop)
set z = z - tz
call SaveReal(udg_KB3D_HA, 68, Loop, KB3D_GetCoordinatesZ(x,y))
if LoadReal(udg_KB3D_HA, 3, Loop)<0 and GetUnitDefaultFlyHeight(U)<z then
call SetUnitFlyHeight(U, KB3D_InBetween(-999,z,GetUnitDefaultFlyHeight(U)), 0)
else
call SetUnitFlyHeight(U, z, 0)
endif
else
call SetUnitFlyHeight(U, KB3D_InBetween(GetUnitDefaultFlyHeight(U), z, 9999), 0)
endif
endif
//---------------------------
if ( not(P) or ( KB3D_CW(x, y) ) ) then
set B = true
if (OS) then
call SetUnitX(U, KB3D_InBetween(udg_KB3D_Reals[6], x, udg_KB3D_Reals[5]))
call SetUnitY(U, KB3D_InBetween(udg_KB3D_Reals[8], y, udg_KB3D_Reals[7]))
set b = false
if (KiOS) and (not(KB3D_IsInBetween(udg_KB3D_Reals[2], x, udg_KB3D_Reals[1])) or not(KB3D_IsInBetween(udg_KB3D_Reals[4], x, udg_KB3D_Reals[3]))) then
call KillUnit(U)
endif
else
call SetUnitX(U, KB3D_InBetween(udg_KB3D_Reals[2], x, udg_KB3D_Reals[1]))
call SetUnitY(U, KB3D_InBetween(udg_KB3D_Reals[4], y, udg_KB3D_Reals[3]))
set b = false
endif
elseif LoadBoolean(udg_KB3D_HA, 52, Loop) and P and not(KB3D_CW(x, y)) then
if GetUnitFlyHeight(U) != 0 then
if KB3D_isPossiblePathability(GetUnitX(U),GetUnitY(U), Angle, S*time/0.03125) and LoadBoolean(udg_KB3D_HA, 44, Loop) then
set B = true
//call SaveBoolean(udg_KB3D_HA, 53, Loop, true)
if (OS) then
call SetUnitX(U, KB3D_InBetween(udg_KB3D_Reals[6], x, udg_KB3D_Reals[5]))
call SetUnitY(U, KB3D_InBetween(udg_KB3D_Reals[8], y, udg_KB3D_Reals[7]))
set b = false
if (KiOS) and (not(KB3D_IsInBetween(udg_KB3D_Reals[2], x, udg_KB3D_Reals[1])) or not(KB3D_IsInBetween(udg_KB3D_Reals[4], x, udg_KB3D_Reals[3]))) then
call KillUnit(U)
endif
else
call SetUnitX(U, KB3D_InBetween(udg_KB3D_Reals[2], x, udg_KB3D_Reals[1]))
call SetUnitY(U, KB3D_InBetween(udg_KB3D_Reals[4], y, udg_KB3D_Reals[3]))
set b = false
endif
else
call SaveBoolean(udg_KB3D_HA, 52, Loop, false)
endif
else
endif
endif
if b then
set udg_KB3D_B = true
if LoadBoolean(udg_KB3D_HA, 66, Loop) then
set udg_KB3D_EndisUnpathable = true
set udg_KB3D_EndisNormal = false
return true
endif
endif
return false
endfunction
function KB3D_LineDamageLoop takes unit U, group g returns nothing
local integer Loop = R2I(udg_KB3D_Reals[0])
local unit Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
local attacktype AType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
local damagetype DType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
local real LineD = LoadReal(udg_KB3D_HA, 28, Loop)
local unit U1 = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
local group G = LoadGroupHandle(udg_KB3D_HA, 27, Loop)
//---------------------------
if KB3D_Filter(U, U1, Loop) and not ( IsUnitInGroup(U, G) ) then
call GroupAddUnit(G, U)
if not(LoadBoolean(udg_KB3D_HA, 44, Loop)) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, LineD, true, false, AType, DType, null)
call DestroyEffect(AddSpecialEffectTarget(LoadStr(udg_KB3D_HA, 58, Loop), U, LoadStr(udg_KB3D_HA, 10, Loop)))
elseif KB3D_Approx(U, U1, Loop) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, LineD, true, false, AType, DType, null)
call DestroyEffect(AddSpecialEffectTarget(LoadStr(udg_KB3D_HA, 58, Loop), U, LoadStr(udg_KB3D_HA, 10, Loop)))
endif
endif
//---------------------------
set G = null
set U1 = null
set Damager = null
set AType = null
set DType = null
endfunction
function KB3D_AoEDamageLoop takes unit U, group g returns nothing
local integer Loop = R2I(udg_KB3D_Reals[0])
local unit Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
local attacktype AType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
local damagetype DType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
local real AoED = LoadReal(udg_KB3D_HA, 32, Loop)
local unit U1 = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
//---------------------------
if KB3D_Filter(U, U1, Loop) then
if not(LoadBoolean(udg_KB3D_HA, 44, Loop)) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, AoED * 0.031250000, true, false, AType, DType, null)
elseif KB3D_Approx(U, U1, Loop) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, AoED * 0.031250000, true, false, AType, DType, null)
endif
endif
//---------------------------
set U1 = null
set Damager = null
set AType = null
set DType = null
endfunction
function KB3D_AoEEndDamage takes unit U, group g returns nothing
local integer Loop = R2I(udg_KB3D_Reals[0])
local unit Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
local attacktype AType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
local damagetype DType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
local real D = LoadReal(udg_KB3D_HA, 38, Loop)
local unit U1 = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
//---------------------------
if KB3D_Filter(U, U1, Loop) then
if not(LoadBoolean(udg_KB3D_HA, 44, Loop)) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, D, true, false, AType, DType, null)
elseif KB3D_Approx(U, U1, Loop) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, D, true, false, AType, DType, null)
endif
endif
//---------------------------
call GroupRemoveUnit(g, U)
//---------------------------
set U1 = null
set Damager = null
set AType = null
set DType = null
endfunction
function KB3D_GiveKBto takes unit U1, unit U2, integer Loop returns nothing
set udg_KB3D_AoEEndDamage = LoadReal(udg_KB3D_HA, 38, Loop)
set udg_KB3D_EndwhenDead = LoadBoolean(udg_KB3D_HA, 35, Loop)
set udg_KB3D_Speed = LoadReal(udg_KB3D_HA, 2, Loop)/0.031250000*.5
set udg_KB3D_Accel = -udg_KB3D_Speed
set udg_KB3D_AllowOutSiding = LoadBoolean(udg_KB3D_HA, 34, Loop)
set udg_KB3D_Angle = (LoadReal(udg_KB3D_HA, 5, Loop)*180/3.14159)
set udg_KB3D_AoE = LoadReal(udg_KB3D_HA, 29, Loop)
set udg_KB3D_AoEDamage = LoadReal(udg_KB3D_HA, 32, Loop)
set udg_KB3D_AttackType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
set udg_KB3D_DamageType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
set udg_KB3D_Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
set udg_KB3D_DestroyTree = LoadBoolean(udg_KB3D_HA, 8, Loop)
set udg_KB3D_DisableUnit = LoadBoolean(udg_KB3D_HA, 6, Loop)
set udg_KB3D_FaceAngle = LoadBoolean(udg_KB3D_HA, 31, Loop)
set udg_KB3D_Fx = LoadStr(udg_KB3D_HA, 9, Loop)
set udg_KB3D_Attach = LoadStr(udg_KB3D_HA, 10, Loop)
set udg_KB3D_ImpactDamage = LoadReal(udg_KB3D_HA, 17, Loop)
set udg_KB3D_LineDamage = LoadReal(udg_KB3D_HA, 28, Loop)
set udg_KB3D_LoopDamage = LoadReal(udg_KB3D_HA, 18, Loop)/0.031250000
set udg_KB3D_Range = 99999
set udg_KB3D_Unit = U1
if LoadBoolean(udg_KB3D_HA, 57, Loop) then
set udg_KB3D_Zoffset = LoadReal(udg_KB3D_HA, 3, Loop)/1.85 - GetUnitDefaultFlyHeight(U2)
endif
//---------------------------
call TriggerEvaluate( udg_KB3D_Registration )
endfunction
function KB3D_AoEGiveKBto takes unit U1, unit U2, integer Loop returns nothing
local real x1 = GetUnitX(U1)
local real y1 = GetUnitY(U1)
local real x2 = GetUnitX(U2)
local real y2 = GetUnitY(U2)
local real P = LoadReal(udg_KB3D_HA, 43, Loop)
//---------------------------
set udg_KB3D_AoE = LoadReal(udg_KB3D_HA, 29, Loop)
set udg_KB3D_EndwhenDead = LoadBoolean(udg_KB3D_HA, 35, Loop)
set udg_KB3D_Accel = -550*P
set udg_KB3D_AllowOutSiding = LoadBoolean(udg_KB3D_HA, 34, Loop)
set udg_KB3D_Angle = Atan2(y1 - y2, x1 - x2)*180/3.14159
set udg_KB3D_AoEDamage = LoadReal(udg_KB3D_HA, 32, Loop)
set udg_KB3D_AttackType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
set udg_KB3D_DamageType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
set udg_KB3D_Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
set udg_KB3D_DestroyTree = LoadBoolean(udg_KB3D_HA, 8, Loop)
set udg_KB3D_DisableUnit = LoadBoolean(udg_KB3D_HA, 6, Loop)
set udg_KB3D_FaceAngle = LoadBoolean(udg_KB3D_HA, 31, Loop)
set udg_KB3D_Fx = LoadStr(udg_KB3D_HA, 9, Loop)
set udg_KB3D_Attach = LoadStr(udg_KB3D_HA, 10, Loop)
set udg_KB3D_ImpactDamage = LoadReal(udg_KB3D_HA, 17, Loop)
set udg_KB3D_LineDamage = LoadReal(udg_KB3D_HA, 28, Loop)
set udg_KB3D_LoopDamage = LoadReal(udg_KB3D_HA, 18, Loop)/0.031250000
set udg_KB3D_Speed = udg_KB3D_AoE*2*P
set udg_KB3D_Range = udg_KB3D_Speed*2
set udg_KB3D_Unit = U1
if LoadBoolean(udg_KB3D_HA, 57, Loop) then
set udg_KB3D_Zoffset = (udg_KB3D_AoE - SquareRoot(x2 * x1 + y2 * y1)*3.14159/180)*P
endif
//---------------------------
call TriggerEvaluate( udg_KB3D_Registration )
endfunction
function KB3D_AoEKB takes unit U, group g returns nothing
local integer Loop = R2I(udg_KB3D_Reals[0])
local unit U1 = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
local real r
//---------------------------
if KB3D_Filter(U, U1, Loop) then
if not(LoadBoolean(udg_KB3D_HA, 44, Loop)) then
call KB3D_AoEGiveKBto(U, U1, Loop)
elseif KB3D_Approx(U, U1, Loop) then
call KB3D_AoEGiveKBto(U, U1, Loop)
endif
endif
//---------------------------
call GroupRemoveUnit(g, U)
//---------------------------
set U1 = null
endfunction
function KB3D_AoEEndFx takes unit U, string A, string F, group g returns nothing
local integer Loop = R2I(udg_KB3D_Reals[0])
local unit U1 = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
local real x
local real y
//---------------------------
if KB3D_Filter(U, U1, Loop) and (U != null) then
if not(LoadBoolean(udg_KB3D_HA, 44, Loop)) then
if ( GetUnitFlyHeight(U) > 20 ) then
call DestroyEffect(AddSpecialEffectTarget(F, U, A))
else
set x = GetUnitX(U)
set y = GetUnitY(U)
call DestroyEffect(AddSpecialEffect(F, x, y))
endif
elseif KB3D_Approx(U, U1, Loop) then
if ( GetUnitFlyHeight(U) > 20 ) then
call DestroyEffect(AddSpecialEffectTarget(F, U, A))
else
set x = GetUnitX(U)
set y = GetUnitY(U)
call DestroyEffect(AddSpecialEffect(F, x, y))
endif
endif
endif
//---------------------------
call GroupRemoveUnit(g, U)
//---------------------------
set U1 = null
endfunction
function KB3D_Grpto takes nothing returns nothing
call GroupAddUnit(udg_KB3D_g, GetEnumUnit())
endfunction
function KB3D_PointBounce takes real BAngle, real x, real y returns real
local real BAngle1 //bounce angle 1
local real BAngle2 //bounce angle 2
local real q //quadrant
set BAngle = BAngle*0.01745329251994329576923690768489
if 0<BAngle and BAngle<90 then
set q = 1
elseif 90<BAngle and BAngle<180 then
set q = 2
elseif 180<BAngle and BAngle<270 then
set q = 3
elseif 270<BAngle and BAngle<360 then
set q = 4
else
set q = BAngle/90 + 2
endif
set BAngle1 = q*90 - BAngle
set BAngle2 = - q*90 + BAngle + 90
if KB3D_isPossiblePathability(x, y, (BAngle - 2*BAngle2), 40) then
set BAngle = BAngle - 2*BAngle2
elseif KB3D_isPossiblePathability(x, y, (BAngle + 2*BAngle1), 40) then
set BAngle = BAngle + 2*BAngle1
endif
return BAngle
endfunction
function KB3D_Flyover takes real Zi, real Zf, real Yi, real Yf, real Xi, real Xf, real Speed, real dur, integer Loop returns nothing
local location Li = Location(Xi, Yi)
local location Lf = Location(Xf, Yf)
local real Xmax = Speed/0.03125*dur
local real Ymax = (GetLocationZ(Lf) - GetLocationZ(Li))*GetLocationZ(Lf)/Speed*Xmax ////BEWARE LOCATIONZ
if (GetLocationZ(Lf) - GetLocationZ(Li)) > 0.5 then
call SaveReal( udg_KB3D_HA, 74, Loop, GetLocationZ(Li) )
call BJDebugMsg("Sup")
elseif (GetLocationZ(Lf) - GetLocationZ(Li)) < -0.5 then
set Ymax = -(GetLocationZ(Lf) - LoadReal( udg_KB3D_HA, 74, Loop))*GetLocationZ(Lf)/Speed*Xmax
call SaveBoolean( udg_KB3D_HA, 75, Loop, false)
call BJDebugMsg(R2S(Ymax))
endif
endfunction
function KB3D_Loop takes integer Loop returns nothing
//Create all the nessesary locals
local unit U = LoadUnitHandle(udg_KB3D_HA, 0, Loop)
local real X = GetUnitX(U)
local real Y = GetUnitY(U)
local real Z = GetUnitFlyHeight(U)
local real x = X
local real y = Y
local real z = Z
local real Range = LoadReal(udg_KB3D_HA, 1, Loop)
local real Speed = LoadReal(udg_KB3D_HA, 2, Loop)
local real Zoffset = LoadReal(udg_KB3D_HA, 3, Loop)
local real Accel = LoadReal(udg_KB3D_HA, 4, Loop)
local real Angle
local real ZSpeed = LoadReal(udg_KB3D_HA, 12, Loop)
local real ZAccel = LoadReal(udg_KB3D_HA, 13, Loop)
local real ImpactD = LoadReal(udg_KB3D_HA, 17, Loop)
local real LoopD = LoadReal(udg_KB3D_HA, 18, Loop)
local real TargetD = LoadReal(udg_KB3D_HA, 19, Loop)
local real LineD = LoadReal(udg_KB3D_HA, 28, Loop)
local real AoE = LoadReal(udg_KB3D_HA, 29, Loop)
local real ZT = LoadReal(udg_KB3D_HA, 26, Loop)
local real AoED = LoadReal(udg_KB3D_HA, 32, Loop)
local real Time = LoadReal(udg_KB3D_HA, 41, Loop) + 0.031250000
local real KillatTime = LoadReal(udg_KB3D_HA, 36, Loop)
local real StopTime = LoadReal(udg_KB3D_HA, 37, Loop)
local real AoEEndDamage = LoadReal(udg_KB3D_HA, 38, Loop)
local real Flyover_dur = LoadReal(udg_KB3D_HA, 73, Loop)
local unit Target = LoadUnitHandle(udg_KB3D_HA, 5, Loop)
local unit Damager = LoadUnitHandle(udg_KB3D_HA, 22, Loop)
local unit u
local boolean DisableUnit = LoadBoolean(udg_KB3D_HA, 6, Loop)
local boolean UnpathableStop = LoadBoolean(udg_KB3D_HA, 7, Loop)
local boolean DestroyTree = LoadBoolean(udg_KB3D_HA, 8, Loop)
local boolean KillWhenHit = LoadBoolean(udg_KB3D_HA, 24, Loop)
local boolean EndWhenHit = LoadBoolean(udg_KB3D_HA, 25, Loop)
local boolean KiOS = LoadBoolean(udg_KB3D_HA, 33, Loop)
local boolean OS = LoadBoolean(udg_KB3D_HA, 34, Loop)
local boolean b = true
local boolean EndwhenDead = LoadBoolean(udg_KB3D_HA, 35, Loop)
local boolean KBTarget = LoadBoolean(udg_KB3D_HA, 39, Loop)
local boolean AoEKB = LoadBoolean(udg_KB3D_HA, 40, Loop)
local boolean KillatEnd = LoadBoolean(udg_KB3D_HA, 46, Loop)
local boolean GroundDamage = LoadBoolean(udg_KB3D_HA, 47, Loop)
local boolean EndB = false
local boolean EndOnObstacle = false
local boolean Flyover = LoadBoolean(udg_KB3D_HA, 72, Loop)
local string Fx = LoadStr(udg_KB3D_HA, 9, Loop)
local string Attach = LoadStr(udg_KB3D_HA, 10, Loop)
local string EndFx = LoadStr(udg_KB3D_HA, 42, Loop)
local string AoEEndFx = LoadStr(udg_KB3D_HA, 54, Loop)
local attacktype AType = ConvertAttackType(LoadInteger(udg_KB3D_HA, 20, Loop))
local damagetype DType = ConvertDamageType(LoadInteger(udg_KB3D_HA, 21, Loop))
local trigger EndT = LoadTriggerHandle(udg_KB3D_HA, 55, Loop)
//end of locals
//Loop Damage Execution
if LoopD != 0 and Damager != null then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, LoopD, true, false, AType, DType, null)
endif
//Calculate the Angle
if ( Target == null ) then
set Angle = LoadReal(udg_KB3D_HA, 5, Loop) + LoadReal(udg_KB3D_HA, 30, Loop)//if there is no unit target
else
set Angle = Atan2(GetUnitY(Target) - Y, GetUnitX(Target) - X)//if there is a unit target
endif
//
if LoadBoolean(udg_KB3D_HA, 16, Loop) then
set Angle = GetUnitFacing(U)*0.0174533
if LoadBoolean(udg_KB3D_HA, 44, Loop) then
if GetUnitCurrentOrder(U) != 851986 and GetUnitCurrentOrder(U) != 851971 then
set b = false
endif
else
set b = false
endif
endif
//Make Unit Face Angle
if LoadBoolean(udg_KB3D_HA, 31, Loop) then
call SetUnitFacing(U, Angle * 3.141592)
endif
//Calculate 3D coordinates
if b then
set Speed = Speed + ( Accel )//Increase the KB speed depending on the Acceleration
set Range = Range - ( RAbsBJ(Speed) )//Decrease distance traveled
set x = X + ( Speed * Cos(Angle) )//new X location of the KBed unit
set y = Y + ( Speed * Sin(Angle) )//new Y location of the KBed unit
set ZSpeed = ZSpeed + ( ZAccel )//change the fly changing rate //Acceleration is for smoothness
set z = Z + ( ZSpeed * 0.031250000 )//new Z Offset of the KBed unit
set ZT = ZT + ( ZSpeed * 0.031250000 )//Total Height Changings
endif
set b = false
if z >= Zoffset then
call SaveReal(udg_KB3D_HA, 12, Loop, -ZSpeed)
endif
//Flyover Feature
//if Flyover then
// if LoadBoolean(udg_KB3D_HA, 75, Loop) then
// if z-LoadReal(udg_KB3D_HA, 71, Loop) <= 0 and (Speed/0.03125*Flyover_dur) <= Range then
// call KB3D_Flyover(Z, z, Y, y, X, x, Speed, Flyover_dur, Loop)
// endif
// endif
//endif
//Destroy Trees around the Unit depending on the unit's Collision Size
if (DestroyTree) or (LoadBoolean(udg_KB3D_HA, 56, Loop)) then
set udg_KB3D_Reals[0] = I2R(Loop)
call KB3D_CircleTreeKill( KB3D_InBetween(2*Speed, 5 * KB3D_GetUnitCollision(U), Speed*4), x, y )
endif
//Move the unit according to the X, Y, Z
set EndOnObstacle = MoveUnit_3D(U, x, y, z, Zoffset, UnpathableStop, OS, KiOS, Angle, Speed, LoadReal(udg_KB3D_HA, 11, Loop)-Time, Loop)
//Bounce on Point
if udg_KB3D_B and LoadBoolean(udg_KB3D_HA, 60, Loop) then
set udg_KB3D_B = false
set Speed=Speed*.85
set Angle = KB3D_PointBounce(Angle,x,y)
if LoadReal(udg_KB3D_HA, 76, Loop) <= 0 then
call DestroyEffect(AddSpecialEffect(LoadStr(udg_KB3D_HA, 62, Loop), GetUnitX(U), GetUnitY(U)))
call SaveReal(udg_KB3D_HA, 76, Loop, 10)
endif
endif
//Create the Effect on the unit
if (Fx != "") then
if ( z > 20 ) then
if (Attach != "") then
call DestroyEffect(AddSpecialEffectTarget(Fx, U, Attach))//attach the effect on the unit if he is flying
endif
else
call DestroyEffect(AddSpecialEffect(Fx, x, y))//create the effect on his location if he is not flying
endif
endif
//Initiate Impact Damage
if ( (UnpathableStop) and not ( KB3D_CW(x, y) ) ) and ( (ImpactD != 0) and (Damager != null ) ) then//if the terrain is unpathable or if unpathable stop is disabled then..
if ( KB3D_CW(x, y) ) then
call SaveBoolean(udg_KB3D_HA, 23, Loop, true)
endif
if ( LoadBoolean(udg_KB3D_HA, 23, Loop) ) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, ImpactD, true, false, AType, DType, null)//Apply Impact Damage to the unit
call SaveBoolean(udg_KB3D_HA, 23, Loop, false)
endif
endif
//Create AoE Grp
if (AoE != 0) and ((LineD != 0) or (AoED != 0) or LoadBoolean(udg_KB3D_HA, 61, Loop) or LoadBoolean(udg_KB3D_HA, 60, Loop)) then
set udg_KB3D_g = CreateGroup()
set udg_KB3D_Reals[0] = I2R(Loop)
call GroupEnumUnitsInRange(udg_KB3D_g, x, y, RAbsBJ(AoE), Filter(function KB3D_FilterGrp))
//----------------------------------
loop
set u = FirstOfGroup(udg_KB3D_g)
exitwhen (u == null)
if (Damager != null) then
if (LineD != 0) then
call KB3D_LineDamageLoop(u, udg_KB3D_g)
endif
if (AoED != 0) then
call KB3D_AoEDamageLoop(u, udg_KB3D_g)
endif
endif
if not IsUnitInGroup(u, LoadGroupHandle(udg_KB3D_HA, 67, Loop)) and RAbsBJ(AoE)>SquareRoot((GetUnitX(u) - GetUnitX(U)) * (GetUnitX(u) - GetUnitX(U)) + (GetUnitY(u) - GetUnitY(U)) * (GetUnitY(u) - GetUnitY(U))) then
if LoadBoolean(udg_KB3D_HA, 61, Loop) then
call KB3D_BounceOnUnit(u, U, Loop)
call GroupAddUnit(LoadGroupHandle(udg_KB3D_HA, 67, Loop),u)
call DestroyEffect(AddSpecialEffect(LoadStr(udg_KB3D_HA, 62, Loop), GetUnitX(u), GetUnitY(u)))
if LoadBoolean(udg_KB3D_HA, 70, Loop) then
set b = true
set udg_KB3D_EndisUnit = true
set udg_KB3D_EndisNormal = false
set udg_KB3D_EndUnit = u
endif
endif
if LoadBoolean(udg_KB3D_HA, 60, Loop) then
set Angle = (Atan2(GetUnitY(u) - GetUnitY(U), GetUnitX(u) - GetUnitX(U))) + Deg2Rad(GetRandomReal(-15,15) + 180)
set Speed = Speed*.85
call DestroyEffect(AddSpecialEffect(LoadStr(udg_KB3D_HA, 62, Loop), GetUnitX(U), GetUnitY(U)))
endif
endif
call GroupRemoveUnit(udg_KB3D_g,u)
endloop
//----------------------------------
call DestroyGroup(udg_KB3D_g)
set udg_KB3D_g = null
endif
//Disable the unit partially
if ( DisableUnit ) then
call SetUnitPropWindow(U, 0)
call SetUnitTurnSpeed(U, 0)
endif
//Initiate Target-Related Actions
if (Target != null) then
if (SquareRoot ( ( GetUnitX(Target) - x ) * ( GetUnitX(Target) - x ) + ( GetUnitY(Target) - y ) * ( GetUnitY(Target) - y ) ) < Speed+2) then//when the target and the unit are close
if not (TargetD == 0) and not(Damager == null) then//Damage the Target
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, Target, TargetD, true, false, AType, DType, null)
call SaveReal(udg_KB3D_HA, 19, Loop, 0)
endif
if KBTarget then//KB the Target
call KB3D_GiveKBto(Target, U, Loop)
call SaveBoolean( udg_KB3D_HA, 39, udg_KB3D_Counter, false )
endif
if (KillWhenHit) then//Kill the Unit
call KillUnit(U)
endif
if (EndWhenHit) then//End the KB
call SaveReal(udg_KB3D_HA, 4, Loop, KB3D_AlwaysNeg(Speed))
call SaveReal(udg_KB3D_HA, 3, Loop, GetUnitFlyHeight(U) - ZT)
endif
set udg_KB3D_EndisUnit = true
set udg_KB3D_EndisNormal = false
endif
endif
//Kill the Unit at the time
if (KillatTime != 0) and ( Time > KillatTime ) then
call KillUnit(U)
endif
//Save Changes in the Hashtable
call SaveReal(udg_KB3D_HA, 1, Loop, Range)
call SaveReal(udg_KB3D_HA, 2, Loop, Speed)
call SaveReal(udg_KB3D_HA, 5, Loop, Angle)
call SaveReal(udg_KB3D_HA, 12, Loop, ZSpeed)
call SaveReal(udg_KB3D_HA, 26, Loop, ZT)
call SaveReal(udg_KB3D_HA, 41, Loop, Time)
call SaveReal(udg_KB3D_HA, 76, Loop, LoadReal(udg_KB3D_HA, 76, Loop)-1)
//Inititate End of the KB
if ( b or (LoadBoolean(udg_KB3D_HA, 45, Loop) and (Speed <= 2.34)) or ( Range <= 0 ) or ( (StopTime != 0) and ( Time > StopTime ) ) or EndOnObstacle ) then
call SaveBoolean(udg_KB3D_HA, 100, Loop, false)
set udg_KB3D_Instances = udg_KB3D_Instances - 1
if IsUnitType(U, UNIT_TYPE_DEAD) then
call SetUnitFlyHeight(U, GetUnitDefaultFlyHeight(U), 750 )
endif
call SetUnitPropWindow(U, LoadReal(udg_KB3D_HA, 15, Loop)*3.14159/180)
call SetUnitTurnSpeed(U, GetUnitDefaultTurnSpeed(U))
if HaveSavedHandle(udg_KB3D_HA, 14, Loop) and not EndB then
call DestroyEffect(LoadEffectHandle(udg_KB3D_HA, 14, Loop))
endif
set b = true
elseif IsUnitType(U, UNIT_TYPE_DEAD) and (EndwhenDead) then
call SaveBoolean(udg_KB3D_HA, 100, Loop, false)
set udg_KB3D_Instances = udg_KB3D_Instances - 1
if IsUnitType(U, UNIT_TYPE_DEAD) then
call SetUnitFlyHeight(U, GetUnitDefaultFlyHeight(U), 750 )
endif
call SetUnitPropWindow(U, LoadReal(udg_KB3D_HA, 15, Loop)*3.14159/180)
call SetUnitTurnSpeed(U, GetUnitDefaultTurnSpeed(U))
if HaveSavedHandle(udg_KB3D_HA, 14, Loop) and not EndB then
call DestroyEffect(LoadEffectHandle(udg_KB3D_HA, 14, Loop))
endif
set b = true
endif
//variable b refers to if the KB has ended
if b then
call SetUnitFlyHeight(U, GetUnitFlyHeight(U)-KB3D_InBetween(0,ZT-LoadReal(udg_KB3D_HA, 71, Loop),999), 500)
if LoadBoolean(udg_KB3D_HA, 44, Loop) then
call SetUnitFlyHeight(U, GetUnitFlyHeight(U)-KB3D_InBetween(0,(LoadReal(udg_KB3D_HA, 69, Loop)-KB3D_GetCoordinatesZ(x,y)),9999), RAbsBJ(ZSpeed))
endif
//----------
call SaveInteger(udg_KB3D_HA, -5, GetHandleId(U), LoadInteger(udg_KB3D_HA, -5, GetHandleId(U))-1)
if LoadInteger(udg_KB3D_HA, -5, GetHandleId(udg_KB3D_Unit)) == 0 then
call SaveBoolean(udg_KB3D_HA, GetHandleId(U), GetHandleId(U), false)
endif
//----------
if (AoEEndDamage != 0) and (Damager != null) and (AoE != 0) then
set udg_KB3D_g = CreateGroup()
set udg_KB3D_Reals[0] = I2R(Loop)
call GroupEnumUnitsInRange(udg_KB3D_g, x, y, RAbsBJ(AoE), null)
loop
set u = FirstOfGroup(udg_KB3D_g)
call KB3D_AoEEndDamage(u, udg_KB3D_g)
exitwhen (u == null)
endloop
call DestroyGroup(udg_KB3D_g)
set udg_KB3D_g = null
endif
//----------
if (AoEKB) and (AoE != 0) then
set udg_KB3D_g = CreateGroup()
set udg_KB3D_Reals[0] = I2R(Loop)
call GroupEnumUnitsInRange(udg_KB3D_g, x, y, RAbsBJ(AoE), null)
loop
set u = FirstOfGroup(udg_KB3D_g)
call KB3D_AoEKB(u, udg_KB3D_g)
exitwhen (u == null)
endloop
call DestroyGroup(udg_KB3D_g)
set udg_KB3D_g = null
endif
//----------
if (EndFx != "") then
if ( z > 20 ) and (Attach != "") then
call DestroyEffect(AddSpecialEffectTarget(EndFx, U, Attach))//attach the effect on the unit if he is flying
else
call DestroyEffect(AddSpecialEffect(EndFx, x, y))//create the effect on his location if he is not flying
endif
endif
//----------
if (AoEEndFx != "") and (Attach != "") and (AoE > 0) then
set udg_KB3D_g = CreateGroup()
set udg_KB3D_Reals[0] = I2R(Loop)
call GroupEnumUnitsInRange(udg_KB3D_g, x, y, RAbsBJ(AoE), null)
loop
set u = FirstOfGroup(udg_KB3D_g)
call KB3D_AoEEndFx(u, Attach, AoEEndFx, udg_KB3D_g)
exitwhen (u == null)
endloop
call DestroyGroup(udg_KB3D_g)
set udg_KB3D_g = null
endif
//----------
if (AoEEndFx != "") and (Attach != "") and (AoE > 0) then
set udg_KB3D_g = CreateGroup()
set udg_KB3D_Reals[0] = I2R(Loop)
call GroupEnumUnitsInRange(udg_KB3D_g, x, y, RAbsBJ(AoE), null)
loop
set u = FirstOfGroup(udg_KB3D_g)
call KB3D_AoEEndFx(u, Attach, AoEEndFx, udg_KB3D_g)
exitwhen (u == null)
endloop
call DestroyGroup(udg_KB3D_g)
set udg_KB3D_g = null
endif
//----------
if GroundDamage and (ImpactD != 0) and z < 75 and (Damager != null) then
set udg_NextDamageType = 2
call UnitDamageTarget(Damager, U, ImpactD, true, false, AType, DType, null)
endif
//----------
if (KillatEnd) and not EndB then
call KillUnit(U)
endif
//----------
if (EndT != null) then
set udg_KB3D_Unit = U
set udg_KB3D_Targeted_Unit = Target
call ConditionalTriggerExecute(EndT)
set udg_KB3D_Unit = null
set udg_KB3D_Targeted_Unit = null
set udg_KB3D_EndUnit = null
set udg_KB3D_EndisUnpathable = false
set udg_KB3D_EndisUnit = false
set udg_KB3D_EndisNormal = true
endif
endif
//Function to know if the unit is being KBed by the system
call SaveInteger(udg_KB3D_HA, -2, GetHandleId(udg_KB3D_Unit), LoadInteger(udg_KB3D_HA, -2, GetHandleId(udg_KB3D_Unit))-1)
call SaveBoolean(udg_KB3D_HA, -1, GetHandleId(udg_KB3D_Unit), LoadInteger(udg_KB3D_HA, -2, GetHandleId(udg_KB3D_Unit))!=0)
//Clear Instance
if b then
call KB3D_ClearInstance(Loop)
endif
//Clear locals
set udg_KB3D_B = false
set U = null
set Target = null
set Damager = null
endfunction
function KB3D_Loop_Actions takes nothing returns nothing
local integer x = 0
if udg_KB3D_Paused then
else
loop
exitwhen x >= udg_KB3D_Counter
set x = x + 1
if ( LoadBoolean(udg_KB3D_HA, 100, x) and not(LoadBoolean(udg_KB3D_HA, 77, x))) then
call KB3D_Loop(x)
endif
endloop
if ( udg_KB3D_Instances == 0 ) then
set udg_KB3D_Counter = 0
call PauseTimer(udg_KB3D_Timer)
endif
endif
endfunction
function KB3D_ClearVar takes nothing returns nothing
set udg_KB3D_HomingMissile = false
set udg_KB3D_EndOnTargetBounce = false
set udg_KB3D_Speed_Changer = false
set udg_KB3D_AoEEndFx = ""
set udg_KB3D_D_STRUCTURE = false
set udg_KB3D_D_MECHANICAL = false
set udg_KB3D_D_ALLY = false
set udg_KB3D_D_MAGIC_IMMINUE = false
set udg_KB3D_D_ENEMY = true
set udg_KB3D_D_RESISTANT = false
set udg_KB3D_D_FLYING = false
set udg_KB3D_Accel = 0.00
set udg_KB3D_AllowOutSiding = false
set udg_KB3D_Flyover = false
set udg_KB3D_Flyover_Duration = 0.00
set udg_KB3D_Angle = 0.00
set udg_KB3D_AoE = 0.00
set udg_KB3D_Arc = 0.00
set udg_KB3D_AoEDamage = 0.00
set udg_KB3D_AttackType = ATTACK_TYPE_NORMAL
set udg_KB3D_DamageType = DAMAGE_TYPE_MAGIC
set udg_KB3D_Damager = null
set udg_KB3D_DestroyTree = true
set udg_KB3D_DisableUnit = false
set udg_KB3D_EndWhenHit = false
set udg_KB3D_Fx = ""
set udg_KB3D_Fx_Attach = ""
set udg_KB3D_EndFx = ""
set udg_KB3D_Attach = "origin"
set udg_KB3D_ImpactDamage = 0.00
set udg_KB3D_KillWhenHit = false
set udg_KB3D_FaceAngle = false
set udg_KB3D_KillifOutSider = false
set udg_KB3D_LineDamage = 0.00
set udg_KB3D_LoopDamage = 0.00
set udg_KB3D_Range = 0.00
set udg_KB3D_Speed = 0.00
set udg_KB3D_TargetDamage = 0.00
set udg_KB3D_Targeted_Unit = null
set udg_KB3D_TrailFx = ""
set udg_KB3D_Unit = null
set udg_KB3D_UnpathableStop = true
set udg_KB3D_Zoffset = 0.00
set udg_KB3D_AoEEndDamage = 0.00
set udg_KB3D_AoEKB = false
set udg_KB3D_EndwhenDead = true
set udg_KB3D_KBTarget = false
set udg_KB3D_StopTime = 0.00
set udg_KB3D_KillatTime = 0.00
set udg_KB3D_AoEKB_Power = 1.00
set udg_KB3D_iKB = true
set udg_KB3D_KillatEnd = false
set udg_KB3D_GroundDamage = false
set udg_KB3D_EndTrigger = null
set udg_KB3D_JumpOverCliff = false
set udg_KB3D_DestroyDestructables = false
set udg_KB3D_Line_Fx = ""
set udg_KB3D_Bounce_Target = false
set udg_KB3D_Bounce_Unit = false
set udg_KB3D_Bounce_Power = 1.00
set udg_KB3D_Bounce_Fx = ""
set udg_KB3D_EndOnObstacle = false
set udg_KB3D_EndUnit = null
set udg_KB3D_RemoveUnit = null
set udg_KB3D_EndisUnpathable = false
set udg_KB3D_EndisUnit = false
set udg_KB3D_EndisNormal = true
endfunction
function KB3D_Registration takes nothing returns boolean
local real Time
local real R
local real R1
local real dx
local real dy
if udg_KB3D_PausedReg then
return false
endif
//------------------------
if udg_KB3D_Unit == null then
return false
endif
//------------------------
if udg_KB3D_Fx_Attach != "" then
set udg_KB3D_Fx = udg_KB3D_Fx_Attach
endif
//------------------------
if udg_KB3D_HomingMissile and udg_KB3D_Targeted_Unit != null then
set udg_KB3D_Zoffset = GetUnitFlyHeight(udg_KB3D_Targeted_Unit)
set dx = GetUnitX(udg_KB3D_Unit)-GetUnitX(udg_KB3D_Targeted_Unit)
set dy = GetUnitY(udg_KB3D_Unit)-GetUnitY(udg_KB3D_Targeted_Unit)
if udg_KB3D_Zoffset == 0 then
set udg_KB3D_Zoffset = 100
set udg_KB3D_Range = SquareRoot( dx * dx + dy * dy)*1.25
else
set udg_KB3D_Range = SquareRoot( dx * dx + dy * dy)*2
endif
set udg_KB3D_KillatEnd = true
set udg_KB3D_KillWhenHit = true
set udg_KB3D_EndWhenHit = true
set udg_KB3D_FaceAngle = true
set udg_KB3D_UnpathableStop = false
endif
//------------------------
set udg_KB3D_Arc = KB3D_InBetween(-10, udg_KB3D_Arc, 10)
set udg_KB3D_AoEKB_Power = KB3D_InBetween(0.01, udg_KB3D_AoEKB_Power, 3)
//------------------------
if IsUnitType(udg_KB3D_Unit, UNIT_TYPE_FLYING) then
set udg_KB3D_UnpathableStop = false
endif
//------------------------
if (udg_KB3D_iKB) and udg_KB3D_Range < 0 then
if ( udg_KB3D_Targeted_Unit == null ) then
set udg_KB3D_Angle = udg_KB3D_Angle + 180
else
set udg_KB3D_Speed = -1*(udg_KB3D_Speed)
endif
endif
//------------------------
set udg_KB3D_Range = KB3D_InBetween(0.0000001, RAbsBJ(udg_KB3D_Range), RAbsBJ(udg_KB3D_Range))
//------------------------
if (udg_KB3D_iKB) and udg_KB3D_Speed < 0 then
set udg_KB3D_Speed = KB3D_InBetween(udg_KB3D_Speed, udg_KB3D_Speed, 0)
else
set udg_KB3D_Speed = KB3D_InBetween(0.0, RAbsBJ(udg_KB3D_Speed), RAbsBJ(udg_KB3D_Speed))
endif
//------------------------
set udg_KB3D_Counter = udg_KB3D_Counter + 1
set udg_KB3D_Instances = udg_KB3D_Instances + 1
call SaveBoolean(udg_KB3D_HA, -1, GetHandleId(udg_KB3D_Unit), true)
call SaveBoolean(udg_KB3D_HA, 57, udg_KB3D_Counter, (udg_KB3D_Zoffset != 0))
//------------------------
if not udg_KB3D_iKB then
set udg_KB3D_Zoffset = RAbsBJ(udg_KB3D_Zoffset)
elseif GetUnitFlyHeight(udg_KB3D_Unit)+udg_KB3D_Zoffset < 0 then
set udg_KB3D_Zoffset = -GetUnitFlyHeight(udg_KB3D_Unit)
endif
//------------------------
set udg_KB3D_StopTime = RAbsBJ(udg_KB3D_StopTime)
set udg_KB3D_KillatTime = RAbsBJ(udg_KB3D_KillatTime)
set udg_KB3D_AoE = RAbsBJ(udg_KB3D_AoE)
//------------------------
//------------------------
call SaveUnitHandle( udg_KB3D_HA, 0, udg_KB3D_Counter, udg_KB3D_Unit )
call SaveReal( udg_KB3D_HA, 1, udg_KB3D_Counter, udg_KB3D_Range )
call SaveReal( udg_KB3D_HA, 2, udg_KB3D_Counter, udg_KB3D_Speed * 0.031250000 )
call SaveReal( udg_KB3D_HA, 4, udg_KB3D_Counter, udg_KB3D_Accel * 0.031250000 * 0.031250000 )
//------------------------
if ( udg_KB3D_Targeted_Unit == null ) then
call SaveReal( udg_KB3D_HA, 5, udg_KB3D_Counter, udg_KB3D_Angle * 3.14159 / 180 )
else
call SaveUnitHandle( udg_KB3D_HA, 5, udg_KB3D_Counter, udg_KB3D_Targeted_Unit )
set udg_KB3D_JumpOverCliff = false
endif
//------------------------
call SaveBoolean( udg_KB3D_HA, 6, udg_KB3D_Counter, udg_KB3D_DisableUnit )
call SaveBoolean( udg_KB3D_HA, 7, udg_KB3D_Counter, udg_KB3D_UnpathableStop )
call SaveBoolean( udg_KB3D_HA, 8, udg_KB3D_Counter, udg_KB3D_DestroyTree )
call SaveStr( udg_KB3D_HA, 9, udg_KB3D_Counter, udg_KB3D_Fx )
call SaveStr( udg_KB3D_HA, 10, udg_KB3D_Counter, udg_KB3D_Attach )
call SaveBoolean( udg_KB3D_HA, 45, udg_KB3D_Counter, udg_KB3D_Speed>0 )
//------------------------
//------------------------
set udg_KB3D_Speed = KB3D_InBetween(0.01, RAbsBJ(udg_KB3D_Speed), RAbsBJ(udg_KB3D_Speed))
//------------------------
if ( udg_KB3D_Accel == 0.00 ) then
set Time = udg_KB3D_Range / (udg_KB3D_Speed)//calculating time for the knockback if Acceleration = 0
else
if ( udg_KB3D_Accel > 0 ) then
set Time = (-udg_KB3D_Speed-SquareRoot(udg_KB3D_Speed*udg_KB3D_Speed + 2*udg_KB3D_Accel*udg_KB3D_Range))/-udg_KB3D_Accel//calculating time for the knockback if Acceleration > 0*/
endif
if ( udg_KB3D_Accel < 0 ) then
set Time = (-udg_KB3D_Speed+SquareRoot(udg_KB3D_Speed*udg_KB3D_Speed + 2*udg_KB3D_Accel*udg_KB3D_Range))/udg_KB3D_Accel
endif
endif
//------------------------
call SaveReal( udg_KB3D_HA, 11, udg_KB3D_Counter, Time )
call SaveBoolean( udg_KB3D_HA, 100, udg_KB3D_Counter, true )
//------------------------
if UnitAddAbility(udg_KB3D_Unit, 'Amrf') then
call UnitRemoveAbility(udg_KB3D_Unit, 'Amrf')
endif
//------------------------
call SaveReal( udg_KB3D_HA, 3, udg_KB3D_Counter, udg_KB3D_Zoffset )
call SaveReal( udg_KB3D_HA, 12, udg_KB3D_Counter, (2*udg_KB3D_Zoffset / ( Time / 2)) )
call SaveReal( udg_KB3D_HA, 13, udg_KB3D_Counter, ( -2 * udg_KB3D_Zoffset / ( Time / 2) ) / ( Time / 2) * 0.031250000 )
//------------------------
if not (udg_KB3D_TrailFx == "") and not (udg_KB3D_Attach == "") then
call SaveEffectHandle(udg_KB3D_HA, 14, udg_KB3D_Counter, AddSpecialEffectTarget(udg_KB3D_TrailFx, udg_KB3D_Unit, udg_KB3D_Attach))
endif
//------------------------
call SaveReal( udg_KB3D_HA, 15, udg_KB3D_Counter, GetUnitDefaultPropWindow(udg_KB3D_Unit) )
call SaveBoolean(udg_KB3D_HA, 16, udg_KB3D_Counter, udg_KB3D_Speed_Changer)
call SaveReal( udg_KB3D_HA, 17, udg_KB3D_Counter, udg_KB3D_ImpactDamage )
call SaveReal( udg_KB3D_HA, 18, udg_KB3D_Counter, udg_KB3D_LoopDamage * 0.031250000 )
call SaveReal( udg_KB3D_HA, 19, udg_KB3D_Counter, udg_KB3D_TargetDamage )
call SaveInteger( udg_KB3D_HA, 20, udg_KB3D_Counter, GetHandleId(udg_KB3D_AttackType))
call SaveInteger( udg_KB3D_HA, 21, udg_KB3D_Counter, GetHandleId(udg_KB3D_DamageType))
call SaveUnitHandle( udg_KB3D_HA, 22, udg_KB3D_Counter, udg_KB3D_Damager )
call SaveBoolean( udg_KB3D_HA, 23, udg_KB3D_Counter, true )
call SaveBoolean( udg_KB3D_HA, 24, udg_KB3D_Counter, udg_KB3D_KillWhenHit )
call SaveBoolean( udg_KB3D_HA, 25, udg_KB3D_Counter, udg_KB3D_EndWhenHit )
// 26 used
call SaveGroupHandle(udg_KB3D_HA, 27, udg_KB3D_Counter, CreateGroup() )
call SaveReal( udg_KB3D_HA, 28, udg_KB3D_Counter, udg_KB3D_LineDamage )
call SaveReal( udg_KB3D_HA, 29, udg_KB3D_Counter, RAbsBJ(udg_KB3D_AoE) )
call SaveReal( udg_KB3D_HA, 30, udg_KB3D_Counter, udg_KB3D_Arc * (3.14159/180) )
call SaveBoolean( udg_KB3D_HA, 31, udg_KB3D_Counter, udg_KB3D_FaceAngle )
call SaveReal( udg_KB3D_HA, 32, udg_KB3D_Counter, udg_KB3D_AoEDamage )
call SaveBoolean( udg_KB3D_HA, 33, udg_KB3D_Counter, udg_KB3D_KillifOutSider )
//------------------------
set udg_KB3D_AllowOutSiding = udg_KB3D_KillifOutSider
//------------------------
call SaveBoolean( udg_KB3D_HA, 34, udg_KB3D_Counter, udg_KB3D_AllowOutSiding )
//------------------------
if not udg_KB3D_EndwhenDead then
set udg_KB3D_EndwhenDead = udg_KB3D_KillatTime > udg_KB3D_StopTime
endif
//------------------------
call SaveBoolean( udg_KB3D_HA, 35, udg_KB3D_Counter, udg_KB3D_EndwhenDead )
call SaveReal( udg_KB3D_HA, 36, udg_KB3D_Counter, udg_KB3D_KillatTime )
call SaveReal( udg_KB3D_HA, 37, udg_KB3D_Counter, udg_KB3D_StopTime )
call SaveReal( udg_KB3D_HA, 38, udg_KB3D_Counter, udg_KB3D_AoEEndDamage )
call SaveBoolean( udg_KB3D_HA, 39, udg_KB3D_Counter, udg_KB3D_KBTarget )
call SaveBoolean( udg_KB3D_HA, 40, udg_KB3D_Counter, udg_KB3D_AoEKB )
//41 used
call SaveStr(udg_KB3D_HA, 42, udg_KB3D_Counter, udg_KB3D_EndFx )
call SaveReal( udg_KB3D_HA, 43, udg_KB3D_Counter, udg_KB3D_AoEKB_Power )
call SaveBoolean( udg_KB3D_HA, 44, udg_KB3D_Counter, udg_KB3D_iKB )
call SaveBoolean( udg_KB3D_HA, 46, udg_KB3D_Counter, udg_KB3D_KillatEnd )
call SaveBoolean( udg_KB3D_HA, 47, udg_KB3D_Counter, udg_KB3D_GroundDamage )
call SaveBoolean( udg_KB3D_HA, 48, udg_KB3D_Counter, udg_KB3D_D_STRUCTURE )
call SaveBoolean( udg_KB3D_HA, 49, udg_KB3D_Counter, udg_KB3D_D_MECHANICAL )
call SaveBoolean( udg_KB3D_HA, 50, udg_KB3D_Counter, udg_KB3D_D_MAGIC_IMMINUE )
call SaveBoolean( udg_KB3D_HA, 51, udg_KB3D_Counter, udg_KB3D_D_ALLY )
call SaveBoolean( udg_KB3D_HA, 52, udg_KB3D_Counter, udg_KB3D_JumpOverCliff )
//call SaveBoolean( udg_KB3D_HA, 53, udg_KB3D_Counter, false )
call SaveStr( udg_KB3D_HA, 54, udg_KB3D_Counter, udg_KB3D_AoEEndFx )
call SaveTriggerHandle( udg_KB3D_HA, 55, udg_KB3D_Counter, udg_KB3D_EndTrigger )
call SaveBoolean( udg_KB3D_HA, 56, udg_KB3D_Counter, udg_KB3D_DestroyDestructables )
//57 used
call SaveStr( udg_KB3D_HA, 58, udg_KB3D_Counter, udg_KB3D_Line_Fx )
call SaveReal( udg_KB3D_HA, 59, udg_KB3D_Counter, udg_KB3D_Bounce_Power )
call SaveBoolean( udg_KB3D_HA, 60, udg_KB3D_Counter, udg_KB3D_Bounce_Unit )
call SaveBoolean( udg_KB3D_HA, 61, udg_KB3D_Counter, udg_KB3D_Bounce_Target )
call SaveStr( udg_KB3D_HA, 62, udg_KB3D_Counter, udg_KB3D_Bounce_Fx )
call SaveBoolean( udg_KB3D_HA, 63, udg_KB3D_Counter, udg_KB3D_D_ENEMY )
call SaveBoolean( udg_KB3D_HA, 64, udg_KB3D_Counter, udg_KB3D_D_RESISTANT )
call SaveBoolean( udg_KB3D_HA, 65, udg_KB3D_Counter, udg_KB3D_D_FLYING )
call SaveBoolean( udg_KB3D_HA, 66, udg_KB3D_Counter, udg_KB3D_EndOnObstacle )
//------------------------
if udg_KB3D_Bounce_Target then
call SaveGroupHandle(udg_KB3D_HA, 67, udg_KB3D_Counter, CreateGroup())
endif
//------------------------
call SaveReal( udg_KB3D_HA, 68, udg_KB3D_Counter, KB3D_GetCoordinatesZ(GetUnitX(udg_KB3D_Unit), GetUnitY(udg_KB3D_Unit)) )
call SaveReal( udg_KB3D_HA, 69, udg_KB3D_Counter, KB3D_GetCoordinatesZ(GetUnitX(udg_KB3D_Unit), GetUnitY(udg_KB3D_Unit)) )
call SaveBoolean( udg_KB3D_HA, 70, udg_KB3D_Counter, udg_KB3D_EndOnTargetBounce )
call SaveReal(udg_KB3D_HA, 71, udg_KB3D_Counter, GetUnitFlyHeight(udg_KB3D_Unit))
call SaveBoolean(udg_KB3D_HA, 72, udg_KB3D_Counter, udg_KB3D_Flyover)
call SaveReal(udg_KB3D_HA, 73, udg_KB3D_Counter, udg_KB3D_Flyover_Duration)
//74 used
call SaveBoolean(udg_KB3D_HA, 75, udg_KB3D_Counter, udg_KB3D_Flyover)
call SaveReal(udg_KB3D_HA, 76, udg_KB3D_Counter, 0)
call SaveBoolean(udg_KB3D_HA, 77, udg_KB3D_Counter, false)
//------------------------
if ( udg_KB3D_Counter == 1 ) then
call TimerStart(udg_KB3D_Timer, 0.031250000, true, function KB3D_Loop_Actions )
endif
//------------------------
set udg_KB3D_Time = Time
//------------------------
//------------------------
call SaveInteger(udg_KB3D_HA, -5, GetHandleId(udg_KB3D_Unit), LoadInteger(udg_KB3D_HA, -5, GetHandleId(udg_KB3D_Unit))+1)
call SaveBoolean(udg_KB3D_HA, GetHandleId(udg_KB3D_Unit), GetHandleId(udg_KB3D_Unit), true)
//------------------------
//------------------------
//------------------------
call KB3D_ClearVar()
return false
endfunction
function KB3D_RemoveUnit takes nothing returns nothing
local integer x = 1
loop
exitwhen x > udg_KB3D_Counter
if LoadUnitHandle(udg_KB3D_HA, 0, x) == udg_KB3D_RemoveUnit then
call SaveReal(udg_KB3D_HA, 1, x, 0)
endif
set x = x + 1
endloop
endfunction
function KB3D_Pause takes nothing returns nothing
call SaveBoolean(udg_KB3D_HA, 77, udg_KB3D_PauseID, true)
set udg_KB3D_PauseID = -1
endfunction
function KB3D_Resume takes nothing returns nothing
call SaveBoolean(udg_KB3D_HA, 77, udg_KB3D_PauseID, false)
set udg_KB3D_PauseID = -1
endfunction
function KB3D_PauseAll takes nothing returns nothing
set udg_KB3D_Paused = true
endfunction
function KB3D_ResumeAll takes nothing returns nothing
set udg_KB3D_Paused = false
endfunction
function KB3D_PauseRegistration takes nothing returns nothing
set udg_KB3D_PausedReg = true
endfunction
function KB3D_ResumeRegistration takes nothing returns nothing
set udg_KB3D_PausedReg = false
endfunction
//===========================================================================
function InitTrig_KB3D takes nothing returns nothing
////////REGISTRATION
set udg_KB3D_Registration = CreateTrigger( )
call TriggerAddCondition( udg_KB3D_Registration, Condition(function KB3D_Registration) )
set udg_KB3D_Harvester = CreateUnit(Player(15), 'hpea', 0, 0, 0)
call ShowUnit(udg_KB3D_Harvester, false)
call UnitAddAbility(udg_KB3D_Harvester, 'Aloc')
call UnitAddAbility(udg_KB3D_Harvester, 'Ahar')
call UnitRemoveAbility(udg_KB3D_Harvester, 'Amov')
set udg_KB3D_HA = InitHashtable()
////////Check Walkability System by PnF
set udg_CP_Rect = Rect(0, 0, 128.00, 128.00)
set udg_CP_Item = CreateItem('wtlg', 0, 0)
call SetItemVisible( udg_CP_Item, false )
////////InitReals
set udg_KB3D_Reals[1] = GetRectMaxX(bj_mapInitialPlayableArea)
set udg_KB3D_Reals[2] = GetRectMinX(bj_mapInitialPlayableArea)
set udg_KB3D_Reals[3] = GetRectMaxY(bj_mapInitialPlayableArea)
set udg_KB3D_Reals[4] = GetRectMinY(bj_mapInitialPlayableArea)
set udg_KB3D_Reals[5] = GetRectMaxX(GetWorldBounds())
set udg_KB3D_Reals[6] = GetRectMinX(GetWorldBounds())
set udg_KB3D_Reals[7] = GetRectMaxY(GetWorldBounds())
set udg_KB3D_Reals[8] = GetRectMinY(GetWorldBounds())
//Initiate Default Values
call KB3D_ClearVar()
endfunction