--Thanatos--
New Member
- Reaction score
- 33
Spell:
Dragons' Horde
Dragons' Horde
- Description:
Summons dragons which will follow the hero.
The dragons will burst a cone of freezing breath
periodically to enemies around the hero, dealing damage,
as well as slowing it.
Active Spell
- JASS (JESP)
- MUI
- Spell's Code:
JASS:
scope DragonsHorde
//*****************************************************************************************
//*****************************************************************************************
//** //**
//** Name : Dragons' Horde //**
//** //**
//** Author : --Thanatos-- //**
//** //**
//*****************************************************************************************
//*****************************************************************************************
//** //**
//** Credits: PandaMine's HSAS //**
//** //**
//*****************************************************************************************
//*****************************************************************************************
//#########################################################################################
//#####################################configurations######################################
//## //##
//## Change the part "= ****" with your configuration. //##
//## //##
globals //##
//## //##
private constant integer Rawcode = 039;A000039; //##
//## Spell's Rawcode. Base it on Vampiric Potion ('AIpv'). Change duration here. //##
//## //##
private constant integer BuffRawcode = 039;B000039; //##
//## The Immolation's Buff's Rawcode. //##
//## //##
private constant integer BreathRawcode = 039;A007039; //##
//## A Breath ability. Base it on Carrion Swarm ('ACca'). //##
//## //##
private constant integer FrostArmorRawcode = 039;A002039; //##
//## The base of slowing frost. Base it on Frost Armor ('ACfa'). Change slow duration //##
//## here. //##
//## //##
private constant integer DragonRawcode = 039;h004039; //##
//## The unit used as the dragons. Should act like dummies, have Movement Speed of 1, //##
//## or more, Movement type of flying, ability Locust ('Aloc'), and Invulnerable //##
//## ('Avul'). (Should act like a dummy) //##
//## //##
private constant real radius = 700. //##
//## Radius of enemies from the dragons that shall be breathed by the dragons. //##
//## //##
private constant real drgnSpd = 600. //##
//## Movement Speed of the dragons. This may pass the Movement Speed limit. //##
//## //##
private constant real drgnSpdDist = 300. //##
//## Distance between Minimum and Maximum Movement Speed with it's default. //##
//## //##
private constant real drgnSpdSpd = 600. //##
//## Movement Speed change per second. //##
//## //##
private constant real drgnRad = 300. //##
//## How far the dragons should be from the caster. //##
//## //##
private constant real drgnRadDist = 150. //##
//## Distance between Minimum and Maximum Range of the dragons to the caster with it's //##
//## default. //##
//## //##
private constant real drgnRadSpd = 150. //##
//## Range change between dragons to caster per second. //##
//## //##
private constant real drgnHgt = 150. //##
//## Flying height of the dragons. //##
//## //##
private constant real drgnHgtDist = 50. //##
//## Distance between Minimum and Maximum Flying Height with it's default. //##
//## //##
private constant real drgnHgtSpd = 25. //##
//## Flying Height change per second. //##
//## //##
private constant real timerPeriod = .02 //##
//## Period of the main timer. The best should range between .01 - .05. //##
//## The less it is, the laggier it is. However, the less it is, the better the //##
//## resolution is. //##
//## //##
private constant real dmgPoint = .75 //##
//## Damage point of the dragons' animation. //##
//## //##
private constant integer Dragons = 1 // base //##
private constant integer DragonsInc = 1 // base + level * this //##
//## Quantity of the dragons at each level. //##
//## CURRENT MAXIMUM AMOUNT OF DRAGON IS 4; USING NUMBER ABOVE THREE WILL CAUSE ERRORS //##
//## UNLESS: //##
//## - Search for three "ADD HERE"s in the whole script, //##
//## - It has some //! runtextmacro DragonsHorde_<A FUNCTION NAME> ("<A NUMBER>"). //##
//## - Copy Paste a line of it, and change the number to the next number of it. //##
//## - Keep doing that until you reach the amount of max dragon you want. //##
//## //##
private constant real Damage = 20. // base //##
private constant real DamageInc = 20. // base + level * this //##
//## Damage of each dragon at each level. //##
//## //##
private constant real Cooldown = 1.5 // base //##
private constant real CooldownInc = 0. // base + level * this //##
//## Cooldown of the dragons at each level. //##
//## //##
private constant string casterEffect = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"//##
//## Special Effect that should appear when activated. //##
//## //##
private constant string dragonEffect = "Abilities\\Spells\\NightElf\\Blink\\BlinkCaster.mdl"//##
//## Special Effect that should appear when the dragons come. //##
//## //##
endglobals //##
//## //##
//#########################################################################################
//#########################################################################################
//***************************************conditions****************************************
//* //*
private function ActiveConditions takes nothing returns boolean //*
//*
return GetSpellAbilityId () == Rawcode //*
//*
endfunction //*
//* //*
//*****************************************************************************************
//*************************************spell's script*************************************
//! textmacro DragonsHorde_Unlimit takes DRAGON
unit dragon$DRAGON$
//! endtextmacro
//! textmacro DragonsHorde_GetDragon takes DRAGON
if lDragon == $DRAGON$ then
set eDragon = DhData.dragon$DRAGON$
endif
//! endtextmacro
//! textmacro DragonsHorde_SetDragon takes DRAGON
if lDragon == $DRAGON$ then
set DhData.dragon$DRAGON$ = eDragon
endif
//! endtextmacro
private struct Data
unit caster
integer level
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//! runtextmacro DragonsHorde_Unlimit ("1")
//! runtextmacro DragonsHorde_Unlimit ("2")
//! runtextmacro DragonsHorde_Unlimit ("3")
//! runtextmacro DragonsHorde_Unlimit ("4")
//ADD HERE
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
endstruct
private struct Dragon
real spin
real dist
real fly
boolean revSpin
boolean revDist
boolean revFly
real angle
real cooldown
boolean done
real targX
real targY
endstruct
private struct Slowset
unit caster
unit dummy
integer level
endstruct
private struct Endslow
trigger endtrig
triggercondition endcond
endstruct
private function TargetFilter takes nothing returns boolean
local Data DhData = GetAttachedStruct (GetExpiredTimer())
local player owner = GetOwningPlayer (DhData.caster)
local unit target = GetFilterUnit ()
local boolean returnVal = false
if GetUnitAbilityLevel (target,Dummy_Ability_Rawcode) <= 0 then
if IsUnitHidden (target) == false then
if GetWidgetLife (target) > .405 then
if IsUnitEnemy (target,owner) then
if IsUnitVisible (target,owner) then
if IsUnitType (target,UNIT_TYPE_STRUCTURE) == false then
if IsUnitType (target,UNIT_TYPE_MAGIC_IMMUNE) == false then
set returnVal = true
endif
endif
endif
endif
endif
endif
endif
set owner = null
set target = null
return returnVal
endfunction
private function FrostEnd takes nothing returns nothing
local timer dhTimer = GetExpiredTimer ()
local Endslow dHData = GetAttachedStruct (dhTimer)
local trigger DhTrig = dHData.endtrig
local triggercondition endcond = dHData.endcond
local Slowset DHData = GetAttachedStruct (DhTrig)
call TriggerRemoveCondition (DhTrig,endcond)
call Endslow.destroy (dHData )
call Slowset.destroy (DHData )
call PauseTimer (dhTimer)
call DestroyTimer (dhTimer)
call DestroyTrigger (DhTrig )
set dhTimer = null
set DhTrig = null
set endcond = null
endfunction
private function Frost takes nothing returns boolean
local trigger DhTrig = GetTriggeringTrigger ()
local Slowset DHData = GetAttachedStruct (DhTrig)
local unit caster = DHData.caster
local unit dummy = DHData.dummy
local integer level = DHData.level
local unit source = GetEventDamageSource ()
local unit target = GetTriggerUnit ()
local real drgnX = GetWidgetX (dummy)
local real drgnY = GetWidgetY (dummy)
local unit frost
local real damage = Damage + level * DamageInc
if source == dummy then
set frost = CreateUnit (GetOwningPlayer(caster),Dummy_Target_Rawcode,drgnX,drgnY,0.)
call UnitApplyTimedLife (frost,039;BTLF039;,.00001)
call UnitAddAbility (frost,FrostArmorRawcode)
call SetUnitX (frost,drgnX)
call SetUnitY (frost,drgnY)
call IssueTargetOrderById (frost,852225,frost)
call UnitDamageTarget (target,frost ,0. ,true ,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null)
call UnitDamageTarget (caster,target,damage,false,true ,ATTACK_TYPE_CHAOS ,DAMAGE_TYPE_MAGIC ,null)
endif
set DhTrig = null
set caster = null
set dummy = null
set frost = null
set source = null
set target = null
return false
endfunction
private function Effect takes nothing returns nothing
local timer DhTimer = GetExpiredTimer ()
local timer dhTimer
local trigger DhTrig
local triggercondition endcond
local Data DhData = GetAttachedStruct (DhTimer)
local Dragon dhData
local Slowset DHData
local Endslow dHData
local unit caster = DhData.caster
local integer level = DhData.level
local boolean buffed = GetUnitAbilityLevel (caster,BuffRawcode) > 0
local integer dragons = Dragons + level * DragonsInc
local real cooldown = Cooldown + level * CooldownInc
local player owner = GetOwningPlayer (caster)
local real castX = GetWidgetX (caster)
local real castY = GetWidgetY (caster)
local real drgnX
local real drgnY
local real lastX
local real lastY
local real targX
local real targY
local real diffX
local real diffY
local real nextX
local real nextY
local real angle
local real Angle
local real random
local real attack
local real spin
local real dist
local real height
local boolean Spin
local boolean Dist
local boolean Height
local boolean breath
local boolean Attack
local boolean invert
local real diff
local group targets
local unit target
local unit enum
local integer Enum
local unit dummy
local unit eDragon
local integer lDragon = 0
local real multiplier = timerPeriod
loop
set lDragon = lDragon + 1
exitwhen lDragon > dragons
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//! runtextmacro DragonsHorde_GetDragon ("1")
//! runtextmacro DragonsHorde_GetDragon ("2")
//! runtextmacro DragonsHorde_GetDragon ("3")
//! runtextmacro DragonsHorde_GetDragon ("4")
//ADD HERE
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
if buffed then
if GetWidgetLife (eDragon) <= .405 then
set spin = GetRandomReal (drgnSpd - drgnSpdDist,drgnSpd + drgnSpdDist)
set dist = GetRandomReal (drgnRad - drgnRadDist,drgnRad + drgnRadDist)
set height = GetRandomReal (drgnHgt - drgnHgtDist,drgnHgt + drgnHgtDist)
set Spin = GetRandomInt (1,2) == 1
set Dist = GetRandomInt (1,2) == 1
set Height = GetRandomInt (1,2) == 1
set angle = GetRandomReal (0.,360.)
set attack = 0.
set breath = false
set drgnX = castX + dist * Cos (angle * (3.14159 / 180.))
set drgnY = castY + dist * Sin (angle * (3.14159 / 180.))
set lastX = drgnX
set lastY = drgnY
set targX = 0.
set targY = 0.
set eDragon = CreateUnit (owner,DragonRawcode,drgnX,drgnY,angle + 90.)
set dhData = Dragon.create ()
call AttachStruct (eDragon,dhData)
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//! runtextmacro DragonsHorde_SetDragon ("1")
//! runtextmacro DragonsHorde_SetDragon ("2")
//! runtextmacro DragonsHorde_SetDragon ("3")
//! runtextmacro DragonsHorde_SetDragon ("4")
//ADD HERE
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------
call DestroyEffect (AddSpecialEffectTarget(dragonEffect,eDragon,"chest"))
call SetUnitAnimationByIndex (eDragon,0)
call SetUnitX (eDragon,drgnX)
call SetUnitY (eDragon,drgnY)
call SetUnitFlyHeight (eDragon,height,0.)
set dhData.spin = spin
set dhData.dist = dist
set dhData.fly = height
set dhData.revSpin = Spin
set dhData.revDist = Dist
set dhData.revFly = Height
set dhData.angle = angle
set dhData.cooldown = attack
set dhData.done = breath
set dhData.targX = targX
set dhData.targY = targY
else
set dhData = GetAttachedStruct (eDragon)
set spin = dhData.spin
set dist = dhData.dist
set height = dhData.fly
set Spin = dhData.revSpin
set Dist = dhData.revDist
set Height = dhData.revFly
set angle = dhData.angle
set attack = dhData.cooldown
set breath = dhData.done
set targX = dhData.targX
set targY = dhData.targY
endif
set drgnX = GetWidgetX (eDragon)
set drgnY = GetWidgetY (eDragon)
set diffX = drgnX - castX
set diffY = drgnY - castY
set diff = SquareRoot (diffX * diffX + diffY * diffY)
if attack > 0. and attack < dmgPoint then
set Attack = true
set multiplier = 0.
else
set Attack = false
endif
if not Attack then
set invert = diff > drgnRad + drgnRadDist
else
set invert = false
endif
set random = drgnSpdSpd * multiplier
if Spin then
set spin = spin + random
if spin >= drgnSpd + drgnSpdDist then
set Spin = false
endif
elseif not Spin then
set spin = spin - random
if spin <= drgnSpd - drgnSpdDist then
set Spin = true
endif
endif
if invert or Attack then
set angle = Atan2 (diffY,diffX) * (180. / 3.14159)
elseif not Attack then
set angle = angle + spin / (2. * 3.14159 * dist / 360.) * multiplier
endif
if invert then
set dist = diff - spin * multiplier
elseif not Attack then
set random = drgnRadSpd * multiplier
if Dist then
set dist = dist + random
if dist >= drgnRad + drgnRadDist then
set Dist = false
endif
elseif not Dist then
set dist = dist - random
if dist <= drgnRad - drgnRadDist then
set Dist = true
endif
endif
elseif Attack then
set dist = diff
endif
set random = drgnHgtSpd * multiplier
if Height then
set height = height + random
if height >= drgnHgt + drgnHgtDist then
set Height = false
endif
elseif not Height then
set height = height - random
if height <= drgnHgt - drgnHgtDist then
set Height = true
endif
endif
if not Attack then
set nextX = castX + dist * Cos (angle * (3.14159 / 180.))
set nextY = castY + dist * Sin (angle * (3.14159 / 180.))
set drgnX = nextX
set drgnY = nextY
call SetUnitX (eDragon,drgnX)
call SetUnitY (eDragon,drgnY)
call SetUnitFlyHeight (eDragon,height,0.)
endif
set dhData.spin = spin
set dhData.dist = dist
set dhData.fly = height
set dhData.revSpin = Spin
set dhData.revDist = Dist
set dhData.revFly = Height
set dhData.angle = angle
if Attack then
set Angle = Atan2 (targY - drgnY,targX - drgnX) * (180. / 3.14159)
elseif invert then
set Angle = angle + 180.
else
set Angle = angle + 90.
endif
call SetUnitFacing (eDragon,Angle)
if attack >= cooldown then
set attack = 0.
set breath = false
set dhData.cooldown = attack
set dhData.done = breath
elseif attack > 0. then
if attack >= dmgPoint and (breath == false) then
set breath = true
set dhData.done = breath
set dummy = CreateUnit (owner,Dummy_Visibility_Rawcode,drgnX,drgnY,0.)
call UnitApplyTimedLife (dummy,039;BTLF039;,2.5)
call UnitAddAbility (dummy,BreathRawcode)
call SetUnitX (dummy,drgnX)
call SetUnitY (dummy,drgnY)
call SetUnitAnimationByIndex (eDragon,0)
set dhTimer = CreateTimer ()
set dHData = Endslow.create ()
set DhTrig = CreateTrigger ()
set DHData = Slowset.create ()
set targets = CreateGroup ()
call GroupEnumUnitsInRange (targets,drgnX,drgnY,9999999.,Filter(function GetTrue))
loop
set target = FirstOfGroup (targets)
exitwhen target == null
call GroupRemoveUnit (targets,target)
call TriggerRegisterUnitEvent (DhTrig,target,EVENT_UNIT_DAMAGED)
endloop
call DestroyGroup (targets)
set endcond = TriggerAddCondition (DhTrig,Condition(function Frost))
set dHData.endtrig = DhTrig
set dHData.endcond = endcond
set DHData.caster = caster
set DHData.dummy = dummy
set DHData.level = level
call AttachStruct (dhTimer,dHData)
call AttachStruct (DhTrig ,DHData)
call TimerStart (dhTimer,2.5,true,function FrostEnd)
call IssuePointOrderById (dummy,852218,targX,targY)
endif
set attack = attack + timerPeriod
set dhData.cooldown = attack
elseif attack == 0. then
set targets = CreateGroup ()
call GroupEnumUnitsInRange (targets,drgnX,drgnY,radius,Filter(function TargetFilter))
if FirstOfGroup (targets) != null then
set Enum = 0
loop
set enum = FirstOfGroup (targets)
exitwhen enum == null
call GroupRemoveUnit (targets,enum)
set Enum = Enum + 1
if GetRandomInt (1,Enum) == 1 then
set target = enum
endif
endloop
set targX = GetWidgetX (target)
set targY = GetWidgetY (target)
set dhData.targX = targX
set dhData.targY = targY
call SetUnitFacing (eDragon,Atan2(targY - drgnY,targX - drgnX) * (180. / 3.14159))
call SetUnitAnimationByIndex (eDragon,1)
set attack = attack + timerPeriod
set dhData.cooldown = attack
endif
call DestroyGroup (targets)
endif
set multiplier = timerPeriod
else
set dhData = GetAttachedStruct (eDragon)
call Dragon.destroy (dhData)
call UnitApplyTimedLife (eDragon,039;BTLF039;,.00001)
endif
endloop
if not buffed then
call Data.destroy (DhData)
call PauseTimer (DhTimer)
call DestroyTimer (DhTimer)
endif
set DhTimer = null
set DhTrig = null
set endcond = null
set caster = null
set eDragon = null
set owner = null
set targets = null
set target = null
set enum = null
set dummy = null
set eDragon = null
endfunction
private function Active takes nothing returns nothing
local timer DhTimer
local Data DhData
local unit caster = GetTriggerUnit ()
local integer level = GetUnitAbilityLevel (caster,Rawcode)
local boolean buffed = GetUnitAbilityLevel (caster,BuffRawcode) > 0
call DestroyEffect (AddSpecialEffectTarget(casterEffect,caster,"origin"))
if not buffed then
set DhTimer = CreateTimer ()
set DhData = Data.create ()
set DhData.caster = caster
set DhData.level = level
call AttachStruct (DhTimer,DhData)
call TimerStart (DhTimer,timerPeriod,true,function Effect)
endif
set DhTimer = null
set caster = null
endfunction
//****************************************************************************************
//****************************************preloads*********************************************
//* //*
private function SpellPreload takes nothing returns nothing //*
//*
local player neutral = Player (PLAYER_NEUTRAL_PASSIVE) //*
local unit tempUnit = CreateUnit (neutral,Dummy_Unit_Rawcode,0.,0.,0.) //*
call DestroyEffect (AddSpecialEffectTarget(casterEffect,tempUnit,"origin"))//*
call DestroyEffect (AddSpecialEffectTarget(dragonEffect,tempUnit,"origin"))//*
call UnitAddAbility (tempUnit,Rawcode) //*
call UnitAddAbility (tempUnit,BreathRawcode) //*
call UnitAddAbility (tempUnit,FrostArmorRawcode) //*
call RemoveUnit (tempUnit) //*
call RemoveUnit (CreateUnit(neutral,DragonRawcode,0.,0.,0.)) //*
call RemoveUnit (CreateUnit(neutral,Dummy_Visibility_Rawcode,0.,0.,0.))//*
call RemoveUnit (CreateUnit(neutral,Dummy_Target_Rawcode,0.,0.,0.)) //*
set neutral = null //*
set tempUnit = null //*
//*
endfunction //*
//* //*
//*********************************************************************************************
//===========================================================================
function InitTrig_DragonsHorde takes nothing returns nothing
local integer index = 0
call SpellPreload ()
set gg_trg_DragonsHorde = CreateTrigger ()
loop
call TriggerRegisterPlayerUnitEvent (gg_trg_DragonsHorde,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,Condition(function GetTrue))
set index = index + 1
exitwhen index == 16
endloop
call TriggerAddCondition (gg_trg_DragonsHorde,Condition(function ActiveConditions))
call TriggerAddAction (gg_trg_DragonsHorde,function Active)
endfunction
endscope
Updates:
- vJass version of the Dragons' Horde.
- The Default Icon DO looks better than the imported one -.-.
- Uppercase beginning for structs. -.-