DrinkSlurm
Eat Bachelor Chow!
- Reaction score
- 50
Typo in title: mod please change to [Spellpack] Arcane Sorcerer
last updated: January 24, 2008
version 1.00: original submission
Shadow Banish
Spell type: unit target, ground/air/organic/non-immune targets
Description: Turns a non-mechanical unit ethereal and slows its movement speed for a short duration. Ethereal creatures cannot attack, but they can cast spells and certain spells cast upon them will have a greater effect. Shadow Banished units also attract the attention of dark energies in the vicinity. Nearby shadows from all organic units within 500 range will periodically form into hostile entities that attack the targeted unit. [100 mana cost; 15 second cooldown]
Level 1 - 30% slow for 5 seconds; shadows deal 5 damage each (8 damage if they strike while the target is ethereal).
Level 2 - 45% slow for 7 seconds; shadows deal 6 damage each (9 damage if they strike while the target is ethereal).
Level 3 - 60% slow for 9 seconds; shadows deal 7 damage each (11 damage if they strike while the target is ethereal).
Note: In order to see the shadows produced by this spell, the player must have Unit Shadows turned on in their WC3 video settings.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
Screenshot:
Backlash
Spell type: unit target, chain-type, hero/non-immune targets only
Description: A chain spell that bounces among multiple enemy Heroes and punishes them according to their own Strength, Agility, and Intelligence stats. [75 mana cost; 12 second cooldown]
Level 1 - deals damage equal to [target's Strength x 1.00]; destroys mana equal to [target's Intelligence x 1.00]; slows by 20% for duration equal to [target's Agility / 10] seconds. Strikes up to 3 Heroes.
Level 2 - deals damage equal to target's [Strength x 1.50]; destroys mana equal to [target's Intelligence x 1.50]; slows by 30% for duration equal to [target's Agility / 10] seconds. Strikes up to 4 Heroes.
Level 3 - deals damage equal to target's [Strength x 2.00]; destroys mana equal to [target's Intelligence x 2.00]; slows by 40% for duration equal to [target's Agility / 10] seconds. Strikes up to 5 Heroes.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
Screenshot:
Multi Life Grip
Spell type: channelling, instant cast, ground/organic/non-immune targets only
Description: A quick channeling spell that drains life from several nearby enemy organic ground units within 600 range. The targets are lifted up into the air and are helpless for the duration of the spell. Life that is drained is given to the Hero. (This spell does NOT allow the health to exceed maximum.) [150 mana cost; 60 second cooldown]
Level 1 - drains up to 10 life per second from up to 6 units for 6 seconds.
Level 2 - drains up to 11 life per second from up to 7 units for 7 seconds.
Level 3 - drains up to 12 life per second from up to 8 units for 8 seconds.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
Screenshot:
last updated: January 24, 2008
version 1.00: original submission
Shadow Banish
Spell type: unit target, ground/air/organic/non-immune targets
Description: Turns a non-mechanical unit ethereal and slows its movement speed for a short duration. Ethereal creatures cannot attack, but they can cast spells and certain spells cast upon them will have a greater effect. Shadow Banished units also attract the attention of dark energies in the vicinity. Nearby shadows from all organic units within 500 range will periodically form into hostile entities that attack the targeted unit. [100 mana cost; 15 second cooldown]
Level 1 - 30% slow for 5 seconds; shadows deal 5 damage each (8 damage if they strike while the target is ethereal).
Level 2 - 45% slow for 7 seconds; shadows deal 6 damage each (9 damage if they strike while the target is ethereal).
Level 3 - 60% slow for 9 seconds; shadows deal 7 damage each (11 damage if they strike while the target is ethereal).
Note: In order to see the shadows produced by this spell, the player must have Unit Shadows turned on in their WC3 video settings.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
JASS:
//===========================================================================
//========================== Shadow Banish v1.00 ============================
//============================== Instructions ===============================
//===========================================================================
// MUI; requires vJASS
//===========================================================================
// IMPORTANT NOTE: In order to see the shadows produced by this spell, the
// player must have Unit Shadows turned on in their WC3 video settings.
//===========================================================================
// 1. Go to the Object Editor, and copy + paste the following:
// Units
// * Shadow Dummy
// Abilities
// * Shadow Banish: Add this ability to the Hero; make sure the custom
// "Shadow Banish" buff is properly referenced.
// * Shadow Flood (for Shadow Dummy): This is the spell that does damage
// everytime a Shadow approaches the target unit; make sure the custom
// "Shadow Flood" buff is properly referenced.
// Buffs
// * Shadow Banish: Make sure this buff is properly referenced in the
// "Shadow Banish" ability.
// * Shadow Flood: Make sure this buff is properly referenced in the
// "Shadow Flood (for Shadow Dummy) ability.
// 2. Copy the following triggers:
// * this trigger: "ShadowBanish"
// 3. To adjust the balance of the skill, you can change some of the following
// values in the Object Editor:
// Abilities
// * Shadow Banish: cooldown, mana cost, speed reduction, cast range
// * Shadow Flood (for Shadow Dummy): Damage per shadow
// 4. Make sure that the rawcodes specified below reference the to proper units,
// abilities, or buffs.
scope ShadowBanish
globals
private constant integer SHBANISH = 039;A007039; //Ability ID of "Shadow Banish"
private constant integer SHDUMMY = 039;h001039; //Unit ID of "Shadow Dummy"
private constant integer SHFLOOD = 039;A008039; //Ability ID of "Shadow Flood (for Shadow Dummy)"
private constant integer SBBUFF = 039;B000039; //Buff ID of "Shadow Banish"
// 5. More Configuration Options
private constant real INTERVAL = 0.50 //timer interval, how often shadows are spawned; default 0.50
private constant real MOVEMIN = 150.00 //random min move speed of shadows; default 150.00
private constant real MOVEMAX = 400.00 //random max move speed of shadows; default 400.00
private constant real RADIUS = 500.00 //range in which affected targets will attract shadows; default 500.00
private constant real DURADDEND = 3.00 //this and DURFACTOR determine the duration of the spell; default 3.00
private constant real DURFACTOR = 2.00 //this and DURADDEND determine the druation of the spell; default 2.00
endglobals
//=========================== End of Instructions ===========================
//===========================================================================
private struct SB
integer p //keeps track of player # of casting hero
integer lvl //keeps track of the level of Shadow Banish that was cast
unit targ //target unit
integer ticks //iteration count
endstruct
globals
private SB array ALLDATA
private timer ALLTIMER = CreateTimer()
private integer TOTAL = 0
private boolexpr FILTER
private unit TARG
private integer P
private integer LVL
endglobals
//===========================================================================
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == SHFLOOD or GetSpellAbilityId() == SHBANISH
endfunction
//===========================================================================
private function RemoveShadows takes nothing returns nothing
if GetUnitCurrentOrder(GetEnumUnit()) != OrderId("acidbomb") then
call UnitApplyTimedLife(GetEnumUnit(), 039;BTLF039;, 0.50)
endif
endfunction
private function GroupFilter takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) > 0.406 and GetFilterUnit() != TARG and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false
endfunction
private function GroupActions takes nothing returns nothing
local real x = GetUnitX(GetEnumUnit())
local real y = GetUnitY(GetEnumUnit())
local unit u = CreateUnit(Player(P), SHDUMMY, x, y, 0)
call SetUnitMoveSpeed(u, GetRandomReal(MOVEMIN, MOVEMAX))
call UnitAddAbility(u, SHFLOOD)
call SetUnitAbilityLevel(u, SHFLOOD, LVL)
call IssueTargetOrder(u, "acidbomb", TARG)
set u = null
endfunction
private function TimerActions takes nothing returns nothing
local SB data
local group g = CreateGroup()
local real x
local real y
local integer i = 1
loop
exitwhen i > TOTAL
set data = ALLDATA<i>
set x = GetUnitX(data.targ)
set y = GetUnitY(data.targ)
set P = data.p
set LVL = data.lvl
set TARG = data.targ
call GroupEnumUnitsInRange(g, x, y, RADIUS, FILTER)
call ForGroup(g, function GroupActions)
call GroupClear(g)
if GetWidgetLife(TARG) < 0.406 then
set data.ticks = 0
endif
set data.ticks = data.ticks -1
if data.ticks <= 0 then
call UnitRemoveAbility(TARG, SBBUFF)
set bj_groupEnumTypeId = SHDUMMY
call GroupEnumUnitsOfPlayer(g, Player(P), filterGetUnitsOfTypeIdAll)
call ForGroup(g, function RemoveShadows)
call data.destroy()
set ALLDATA<i> = ALLDATA[TOTAL]
set TOTAL = TOTAL - 1
set i = i - 1
if TOTAL == 0 then
call PauseTimer(ALLTIMER)
endif
endif
set i = i + 1
endloop
call DestroyGroup(g)
set g = null
endfunction
private function SBCast takes nothing returns nothing
local SB data = SB.create()
if GetSpellAbilityId() == SHBANISH then
set data.p = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set data.lvl = GetUnitAbilityLevel(GetTriggerUnit(), SHBANISH)
set data.targ = GetSpellTargetUnit()
set data.ticks = R2I((DURFACTOR * data.lvl + DURADDEND) / INTERVAL)
set TOTAL = TOTAL + 1
set ALLDATA[TOTAL] = data
if TOTAL == 1 then
call TimerStart(ALLTIMER, INTERVAL, true, function TimerActions)
endif
endif
endfunction
//===========================================================================
private function SFCast takes nothing returns nothing
if GetSpellAbilityId() == SHFLOOD then
call UnitApplyTimedLife(GetTriggerUnit(), 039;BTLF039;, 0.50)
endif
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
local unit u = CreateUnit(Player(0), SHDUMMY, 0, 0, 0)
call UnitAddAbility(u, SHFLOOD)
call RemoveUnit(u)
set gg_trg_ShadowBanish = CreateTrigger()
set FILTER = Condition(function GroupFilter)
call TriggerRegisterAnyUnitEventBJ(gg_trg_ShadowBanish, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_ShadowBanish, Condition(function Cond))
call TriggerAddAction(gg_trg_ShadowBanish, function SBCast)
call TriggerAddAction(gg_trg_ShadowBanish, function SFCast)
set u = null
endfunction
endscope</i></i>
Screenshot:
Backlash
Spell type: unit target, chain-type, hero/non-immune targets only
Description: A chain spell that bounces among multiple enemy Heroes and punishes them according to their own Strength, Agility, and Intelligence stats. [75 mana cost; 12 second cooldown]
Level 1 - deals damage equal to [target's Strength x 1.00]; destroys mana equal to [target's Intelligence x 1.00]; slows by 20% for duration equal to [target's Agility / 10] seconds. Strikes up to 3 Heroes.
Level 2 - deals damage equal to target's [Strength x 1.50]; destroys mana equal to [target's Intelligence x 1.50]; slows by 30% for duration equal to [target's Agility / 10] seconds. Strikes up to 4 Heroes.
Level 3 - deals damage equal to target's [Strength x 2.00]; destroys mana equal to [target's Intelligence x 2.00]; slows by 40% for duration equal to [target's Agility / 10] seconds. Strikes up to 5 Heroes.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
JASS:
//===========================================================================
//============================= Backlash v1.00 ==============================
//============================== Instructions ===============================
//===========================================================================
// MUI; requires vJASS
//===========================================================================
// 1. Go to the Object Editor, and copy + paste the following:
// Units
// * Dummy Caster
// Abilities
// * Backlash: Add this ability to the Hero
// * Chain Lightning (for Dummy)
// * Slow 1 (for Dummy)
// * Slow 2 (for Dummy)
// * Slow 3 (for Dummy)
// 2. Copy the following triggers:
// Triggers
// * this trigger: "Backlash"
// 3. To adjust the balance of the skill, you can change some of the following
// values in the Object Editor:
// Abilities
// * Backlash: Cooldown, Mana Cost. Cast Range
// * Slow 1/2/3: Amount and duration of slow; increase the levels of these
// abilities if necessary (if your map has Heroes with more than 200
// Agility); if you want Backlash to have more than 3 levels, create more
// slow abilities and make sure they are properly referenced (including below
// in the InitTrig function).
// 4. Make sure that the rawcodes specified below reference the to proper units,
// abilities, or buffs.
scope Backlash
globals
private constant integer BACKLASH = 039;A00A039; //Ability ID of "Backlash"
private constant integer DUMMY = 039;h000039; //Unit ID of "Dummy Caster"
private constant integer CHAINLIT = 039;A003039; //Ability ID of "Chain Lightning (for Dummy)"
private constant integer SLOW1 = 039;A004039; //Ability ID of "Slow 1 (for Dummy)"
private constant integer SLOW2 = 039;A005039; //Ability ID of "Slow 2 (for Dummy)"
private constant integer SLOW3 = 039;A006039; //Ability ID of "Slow 3 (for Dummy)"
// 5. More Configuration Options
private constant integer JUMPADDEND = 2 //this and JUMPFACTOR determine total max number of chain targets; default 2
private constant integer JUMPFACTOR = 1 //this and JUMPADDEND determine total max number of chain targets; default 1
private constant real INTERVAL = 0.15 //timer interval how fast next chain target is hit; default 0.15
private constant real RADIUS = 600.00 //range in which next chain target is chosen; default 600.00
private constant real STRADDEND = 1.00 //this and STRDIVISOR help determine the damage to target's HP; default 1.00
private constant real STRDIVISOR = 2.00 //this and STRADDEND help determine the damage to target's HP; default 2.00
private constant real INTADDEND = 1.00 //this and INTDIVISOR help determine the amount of target's Mana loss; default 1.00
private constant real INTDIVISOR = 2.00 //this and INTADDEND help determine the amount of target's Mana loss; default 2.00
private constant real AGIFACTOR = 0.10 //multiplier for Agility that determines the level (duration) of slow; default 0.10
endglobals
//=========================== End of Instructions ===========================
//===========================================================================
private struct BL
group g = CreateGroup() //keeps track of units already struck
unit targ //current target unit
unit hero //casting Hero
integer ticks //# of bounce targets remaining
endstruct
globals
private BL array ALLDATA
private timer ALLTIMER = CreateTimer()
private integer TOTAL = 0
private boolexpr FILTER
private group TEMPGROUP = CreateGroup()
private unit TEMPHERO
private integer array SLOW
endglobals
//===========================================================================
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == BACKLASH
endfunction
//===========================================================================
private function GroupFilter takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) > 0.406 and IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO) == true and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(TEMPHERO)) == true and IsUnitInGroup(GetFilterUnit(), TEMPGROUP) == false
endfunction
private function TimerActions takes nothing returns nothing
local BL data
local integer lvl
local real r
local integer int
local group g = CreateGroup()
local real x
local real y
local unit u
local texttag tt = CreateTextTag()
local integer i = 1
loop
exitwhen i > TOTAL
set data = ALLDATA<i>
set lvl = GetUnitAbilityLevel(data.hero, BACKLASH)
set int = R2I(GetHeroAgi(data.targ, true) * AGIFACTOR + 0.50)
set x = GetUnitX(data.targ)
set y = GetUnitY(data.targ)
//damage per strength
set r = GetHeroStr(data.targ, true) * (lvl + STRADDEND) / STRDIVISOR
call UnitDamageTarget(data.hero, data.targ, r, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
call SetTextTagText(tt, "-" + I2S(R2I(r)), 0.023)
call SetTextTagPosUnit(tt, data.targ, 0)
call SetTextTagColor(tt, 255, 0, 0, 255)
call SetTextTagPermanent(tt, false)
call SetTextTagFadepoint(tt, 2.00)
call SetTextTagVelocity(tt, -0.0251, 0.0251)
call SetTextTagLifespan(tt, 3.00)
//mana loss per intelligence
set r = GetHeroInt(data.targ, true) * (lvl + INTADDEND) / INTDIVISOR
call SetUnitState(data.targ, UNIT_STATE_MANA, RMaxBJ(0, GetUnitState(data.targ, UNIT_STATE_MANA) - r))
set tt = CreateTextTag()
call SetTextTagText(tt, "-" + I2S(R2I(r)), 0.023)
call SetTextTagPosUnit(tt, data.targ, 0)
call SetTextTagColor(tt, 0, 0, 255, 255)
call SetTextTagPermanent(tt, false)
call SetTextTagFadepoint(tt, 2.00)
call SetTextTagVelocity(tt, 0.0251, 0.0251)
call SetTextTagLifespan(tt, 3.00)
//slow per agility
set u = CreateUnit(GetOwningPlayer(data.hero), DUMMY, x, y, 0)
call UnitApplyTimedLife(u, 039;BTLF039;, 1.00)
call UnitAddAbility(u, SLOW[lvl])
call SetUnitAbilityLevel(u, SLOW[lvl], int)
call IssueTargetOrder(u, "slow", data.targ)
//chain to next target
set TEMPHERO = data.hero
call GroupAddGroup(data.g, TEMPGROUP)
call GroupEnumUnitsInRange(g, x, y, RADIUS, FILTER)
set data.targ = GroupPickRandomUnit(g)
if data.targ == null then
set data.ticks = 0
else
set u = CreateUnit(GetOwningPlayer(data.hero), DUMMY, x, y, 0)
call UnitApplyTimedLife(u, 039;BTLF039;, 1.00)
call UnitAddAbility(u, CHAINLIT)
call IssueTargetOrder(u, "chainlightning", data.targ)
call GroupAddUnit(data.g, data.targ)
endif
set data.ticks = data.ticks - 1
if data.ticks <= 0 then
call data.destroy()
set ALLDATA<i> = ALLDATA[TOTAL]
set TOTAL = TOTAL - 1
set i = i - 1
if TOTAL == 0 then
call PauseTimer(ALLTIMER)
endif
endif
set i = i + 1
call GroupClear(TEMPGROUP)
endloop
call DestroyGroup(g)
set u = null
set g = null
set tt = null
endfunction
private function Actions takes nothing returns nothing
local BL data = BL.create()
set data.hero = GetTriggerUnit()
set data.targ = GetSpellTargetUnit()
set data.ticks = GetUnitAbilityLevel(GetTriggerUnit(), BACKLASH) * JUMPFACTOR + JUMPADDEND
call GroupAddUnit(data.g, data.targ)
set TOTAL = TOTAL + 1
set ALLDATA[TOTAL] = data
if TOTAL == 1 then
call TimerStart(ALLTIMER, INTERVAL, true, function TimerActions)
endif
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
local unit u = CreateUnit(Player(0), DUMMY, 0, 0, 0)
call UnitAddAbility(u, CHAINLIT)
call UnitAddAbility(u, SLOW1)
call UnitAddAbility(u, SLOW2)
call UnitAddAbility(u, SLOW3)
call RemoveUnit(u)
set gg_trg_Backlash = CreateTrigger()
set FILTER = Condition(function GroupFilter)
set SLOW[1] = SLOW1
set SLOW[2] = SLOW2
set SLOW[3] = SLOW3
call TriggerRegisterAnyUnitEventBJ(gg_trg_Backlash, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_Backlash, Condition(function Cond))
call TriggerAddAction(gg_trg_Backlash, function Actions)
set u = null
endfunction
endscope</i></i>
Screenshot:
Multi Life Grip
Spell type: channelling, instant cast, ground/organic/non-immune targets only
Description: A quick channeling spell that drains life from several nearby enemy organic ground units within 600 range. The targets are lifted up into the air and are helpless for the duration of the spell. Life that is drained is given to the Hero. (This spell does NOT allow the health to exceed maximum.) [150 mana cost; 60 second cooldown]
Level 1 - drains up to 10 life per second from up to 6 units for 6 seconds.
Level 2 - drains up to 11 life per second from up to 7 units for 7 seconds.
Level 3 - drains up to 12 life per second from up to 8 units for 8 seconds.
Coding: JASS; requires vJASS
Leaks: Leakless
Multi Instanceability: MUI
Lag-susceptibility: none
Import Difficulty: easy (instructions included)
Trigger:
JASS:
//===========================================================================
//========================= Multi Life Grip v1.00 ===========================
//============================== Instructions ===============================
//===========================================================================
// MUI; requires vJASS
//===========================================================================
// 1. Go to the Object Editor, and copy + paste the following:
// Units
// * Dummy Caster: Note that for this spell the dummy caster must have no life
// regeneration. When the dummy is created, the life set to 1.00 by the
// trigger, and life that it drains is periodically given to the Hero caster.
// Abilities
// * Multi Life Grip: Add this ability to the Hero. Make sure the Base Order ID
// does not conflict with any other spell on the Hero.
// * Life Drain (for Dummy)
// 2. Copy the following trigger and variables:
// Triggers
// * this trigger: "MultiLifeGrip"
// Variables
// * udg_SimError: global sound variable used in Vexorian's SimError snippet
// 3. To adjust the balance of the skill, you can change some of the following
// values in the Object Editor:
// Abilities
// * Multi Life Grip: duration, mana cost, cooldown
// * Life Drain (for Dummy): hit points drained, drain interval
// 4. Make sure that the rawcodes specified below reference the to proper units,
// abilities, or buffs.
scope MultiLifeGrip
globals
private constant integer MLGRIP = 039;A000039; //Ability ID of "Multi Life Grip"
private constant integer DUMMY = 039;h000039; //Unit ID of "Dummy Caster"
private constant integer LFDRAIN = 039;A001039; //Ability ID of "Life Drain (for Dummy)"
// 5. More Configuration Options
private constant real RADIUS = 600.00 //range in which targets will be affected; default 600.00
private constant real INTERVAL = 0.25 //timer interval, how often targets are spun and life is drained; default 0.25
private constant real DURADDEND = 5.00 //this and DURFACTOR help to determine the duration of the spell; default 5.00
private constant real DURFACTOR = 1.00 //this and DURADDEND help to determine the duration of the spell; default 1.00
private constant integer MTADDEND = 5 //this and MTFACTOR help to determine the max number of targets; default 5
private constant integer MTFACTOR = 1 //this and MTADDEND help to determine the max number of targets; default 1
private constant real FLYHTFACTOR = 37.50 //this and FLYHTBASE determine the max flying height of targets; default 37.50
private constant real FLYHTBASE = 187.50 //this and FLYHTFACTOR determine the max flying height of targets; default 187.50
private constant string ORDER = "absorb" //this must match the Base Order ID for the "Multi Life Grip" ability; change this only if necessary
endglobals
//=========================== End of Instructions ===========================
//===========================================================================
//###########################################################################
//####################### SimError system by Vexorian #######################
function SimError takes player ForPlayer, string msg returns nothing
if udg_SimError==null then
set udg_SimError = CreateSoundFromLabel("InterfaceError", false, false, false, 10, 10)
endif
if GetLocalPlayer() == ForPlayer then
call ClearTextMessages()
call DisplayTimedTextToPlayer(ForPlayer, 0.52, -1.00, 2.00, "|c00FFCC00" + msg + "|r")
call StartSound(udg_SimError)
endif
endfunction
//########################### end of the SimError ###########################
//###########################################################################
private struct MLG
unit hero //triggering unit
group tg = CreateGroup() //target group
group dg = CreateGroup() //dummy group
real rate //fly height change rate
integer ticks //iteration count
integer ticks2 //iteration half-count
endstruct
globals
private MLG array ALLDATA
private timer ALLTIMER = CreateTimer()
private integer TOTAL = 0
private boolexpr FILTER
private unit TEMPHERO
private real RATE
private group TEMPGROUP = CreateGroup()
endglobals
//===========================================================================
private function Cond takes nothing returns boolean
return GetSpellAbilityId() == MLGRIP
endfunction
//===========================================================================
private function GroupFilter takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true and GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false and GetUnitAbilityLevel(GetFilterUnit(), 039;Bdtl039;) == 0
endfunction
private function TGStopActions takes nothing returns nothing
call PauseUnit(GetEnumUnit(), false)
call SetUnitTimeScale(GetEnumUnit(), 1.00)
call SetUnitFlyHeight(GetEnumUnit(), 0.00, RATE)
endfunction
private function DGStopActions takes nothing returns nothing
call RemoveUnit(GetEnumUnit())
endfunction
private function TGDownActions takes nothing returns nothing
call SetUnitFlyHeight(GetEnumUnit(), 0.00, RATE)
endfunction
private function TGActions takes nothing returns nothing
call SetUnitFacingTimed(GetEnumUnit(), GetUnitFacing(GetEnumUnit()) + 90.00, 0.66)
if GetWidgetLife(GetEnumUnit()) < 0.406 then
call GroupRemoveUnit(TEMPGROUP, GetEnumUnit())
call PauseUnit(GetEnumUnit(), false)
call SetUnitTimeScale(GetEnumUnit(), 1.00)
call SetUnitFlyHeight(GetEnumUnit(), 0.00, RATE)
endif
endfunction
private function DGActions takes nothing returns nothing
local real r = GetWidgetLife(GetEnumUnit()) - 1
call SetWidgetLife(GetEnumUnit(), 1.00)
call SetWidgetLife(TEMPHERO, GetWidgetLife(TEMPHERO) + r)
endfunction
private function TimerActions takes nothing returns nothing
local MLG data
local integer i = 1
loop
exitwhen i > TOTAL
set data = ALLDATA<i>
set TEMPHERO = data.hero
set RATE = data.rate
call GroupAddGroup(data.tg, TEMPGROUP)
call ForGroup(TEMPGROUP, function TGActions)
set data.ticks2 = data.ticks2 - 1
if data.ticks2 == 0 then
call ForGroup(TEMPGROUP, function TGDownActions)
endif
call GroupClear(data.tg)
call GroupAddGroup(TEMPGROUP, data.tg)
call ForGroup(data.dg, function DGActions)
if CountUnitsInGroup(data.tg) == 0 or GetUnitCurrentOrder(data.hero) != OrderId(ORDER) then
set data.ticks = 0
endif
set data.ticks = data.ticks - 1
if data.ticks <= 0 then
call IssueImmediateOrder(TEMPHERO, "stop")
call ForGroup(data.dg, function DGStopActions)
call GroupClear(data.dg)
call ForGroup(TEMPGROUP, function TGStopActions)
call GroupClear(TEMPGROUP)
call data.destroy()
set ALLDATA<i> = ALLDATA[TOTAL]
set TOTAL = TOTAL - 1
set i = i - 1
if TOTAL == 0 then
call PauseTimer(ALLTIMER)
endif
endif
set i = i + 1
endloop
call GroupClear(TEMPGROUP)
endfunction
private function Cast takes nothing returns nothing
local MLG data = MLG.create()
local integer lvl = GetUnitAbilityLevel(GetTriggerUnit(), MLGRIP)
local real dur = lvl * DURFACTOR + DURADDEND
local integer mt = lvl * MTFACTOR + MTADDEND
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
local group g = CreateGroup()
local unit targ
local unit u
local real height = lvl * FLYHTFACTOR + FLYHTBASE
set data.hero = GetTriggerUnit()
set data.ticks = R2I(dur / INTERVAL)
set data.ticks2 = data.ticks / 2
set data.rate = height * 2 / dur
call GroupEnumUnitsInRange(data.tg, x, y, RADIUS, FILTER)
if CountUnitsInGroup(data.tg) > mt then
loop
exitwhen CountUnitsInGroup(data.tg) == mt
call GroupRemoveUnit(data.tg, GroupPickRandomUnit(data.tg))
endloop
endif
if CountUnitsInGroup(data.tg) > 0 then
call GroupAddGroup(data.tg, g)
loop
set targ = FirstOfGroup(g)
exitwhen targ == null
set u = CreateUnit(GetOwningPlayer(data.hero), DUMMY, x, y, 0)
call UnitApplyTimedLife(u, 039;BTLF039;, dur + 1)
call SetWidgetLife(u, 1.00)
call UnitAddAbility(u, LFDRAIN)
call SetUnitAbilityLevel(u, LFDRAIN, lvl)
call IssueTargetOrder(u, "drain", targ)
call GroupAddUnit(data.dg, u)
call PauseUnit(targ, true)
call UnitAddAbility(targ, 039;Amrf039;)
call UnitRemoveAbility(targ, 039;Amrf039;)
call SetUnitTimeScale(targ, 0.00)
call SetUnitFlyHeight(targ, height, data.rate)
call GroupRemoveUnit(g, targ)
endloop
set TOTAL = TOTAL + 1
set ALLDATA[TOTAL] = data
if TOTAL == 1 then
call TimerStart(ALLTIMER, INTERVAL, true, function TimerActions)
endif
else
call TriggerSleepAction(0.00)
call IssueImmediateOrder(GetTriggerUnit(), "stop")
call SimError(GetOwningPlayer(GetTriggerUnit()), "No valid targets within range.")
endif
call DestroyGroup(g)
set g = null
set targ = null
set u = null
endfunction
//===========================================================================
public function InitTrig takes nothing returns nothing
local unit u = CreateUnit(Player(0), DUMMY, 0, 0, 0)
call UnitAddAbility(u, LFDRAIN)
call RemoveUnit(u)
set gg_trg_MultiLifeGrip = CreateTrigger()
set FILTER = Condition(function GroupFilter)
call TriggerRegisterAnyUnitEventBJ(gg_trg_MultiLifeGrip, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
call TriggerAddCondition(gg_trg_MultiLifeGrip, Condition(function Cond))
call TriggerAddAction(gg_trg_MultiLifeGrip, function Cast)
set u = null
endfunction
endscope</i></i>
Screenshot: