Tom_Kazansky
--- wraith it ! ---
- Reaction score
- 157
Arctic Blast
Aided by the will of the North Winds, the Cold Reaver conjures up a chilling torrent of frost
that incapacitates all caught within the frozen blast.
Aided by the will of the North Winds, the Cold Reaver conjures up a chilling torrent of frost
that incapacitates all caught within the frozen blast.
Method: vJass (requires NewGen)
MUI: Yes
MPI: Yes
Lagless: Yes but I know I still have leak somewhere
Well-made tooltips: Yes
The hero will channel for 5 seconds but the hero can recast the spell to continue channeling and change direction. Mana cost for casting is 0 (free) but mana will be drained over time(default is 10x12.5 mana per second)
Screen shot:
v1.1
JASS:
scope ArcticBlast initializer Init
globals
private integer ArcticBlastID = 039;A001039; //RawId of the Arctic Blast ability
private integer ArcticBoltID = 039;n002039; //RawId of the Arctic Bolt dummy
private real ArcticBlastSpeed = 800 //speed for the Arctic Blast bolts
private integer IceSlowID = 039;A000039; //this ability is used for slow, modify this for the slow duration
private string IceSlowOrder = "frostnova" //this is order string of the ice slow ability, if you use a different ability (not Frost Nova), you should change this
private real ArcticBoltCollides = 125. //the range that the Arctic Blast bolts will hit enemy unit.
private integer BoltInterval = 2 //This is the amount of time between the fire of two bolts
//inteval = BoltInterval * 0.05 = 0.1. So every 0.1s a bolt will be fired
private real DamageInterval = BoltInterval * 0.05 // = 0.1
endglobals
//==========================================
private function TJSetUnitHeight takes unit c, real h returns nothing
call UnitAddAbility(c,039;Amrf039;)
call UnitRemoveAbility(c,039;Amrf039;)
call SetUnitFlyHeight(c,h,0)
endfunction
private function TJGetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function TJGetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
//===========================================
private function GetManaCost takes integer lvl returns real
return 10. //this is the mana cost per DamageInterval second
endfunction
private function GetMinDamage takes integer lvl returns real
return lvl * 5. //this is the minimum damage per DamageInterval second
endfunction
private function GetMaxDamage takes integer lvl returns real
return lvl * 10. //this is the maximum damage per DamageInterval second
endfunction
private function GetDistance takes integer lvl returns real
return 400.+100.*lvl
endfunction
//===========================================
private struct data
unit caster = null
trigger hit = null
triggeraction hitact = null
timer move = null
group blast = null
real cx = 0.0
real cy = 0.0
real cost = 0.0
real min = 0.0
real max = 0.0
real dis = 0.0
integer interval = 0
integer lvl = 0
method onDestroy takes nothing returns nothing
if .hit != null then
call TriggerRemoveAction(.hit, .hitact)
call DestroyTrigger(.hit)
endif
if .move != null then
call ReleaseTimer(.move)
endif
if .blast != null then
call ReleaseGroup(.blast)
endif
endmethod
endstruct
private function ArcticBlastH takes nothing returns nothing
local trigger t = GetTriggeringTrigger()
local data d = GetCSData(t)
local unit a = GetTriggerUnit()
if GetWidgetLife(a) == 0 or not IsUnitEnemy(a,GetOwningPlayer(d.caster)) then
return
endif
//when a is alive and a is an enemy, a takes damage (Still need more conditions)
call UnitDamageTarget(d.caster,a,GetRandomReal(d.min,d.max),false,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
call CasterCastAbilityEx( Player(15), GetUnitX(a), GetUnitY(a), 0., IceSlowID, d.lvl, IceSlowOrder, a, 1. )
set a = null
endfunction
private function ArcticBlastGM takes nothing returns nothing
local unit d = GetEnumUnit()
if GetWidgetLife(d) > 0 then
call SetUnitPosition(d, TJGetPPX(GetUnitX(d),ArcticBlastSpeed/25,GetUnitFacing(d)), TJGetPPY(GetUnitY(d),ArcticBlastSpeed/25,GetUnitFacing(d)) )
endif
set d = null
endfunction
private function ArcticBlastE takes nothing returns nothing
local timer t = GetExpiredTimer()
local data d = GetCSData(t)
local boolean b = true
local string o
local unit db
if GetUnitState(d.caster,UNIT_STATE_MANA)<d.cost then
call IssueImmediateOrder(d.caster,"stop")
endif
set o = OrderId2String(GetUnitCurrentOrder(d.caster))
if o != "blizzard" or d.cx != GetUnitX(d.caster) or d.cy != GetUnitY(d.caster) then
set b = false
call SetCSData(d.caster,0)
endif
if b then
if d.interval == 0 and b then
set db = CreateUnit(GetOwningPlayer(d.caster),ArcticBoltID,TJGetPPX(GetUnitX(d.caster),50,GetUnitFacing(d.caster)), TJGetPPY(GetUnitY(d.caster),50,GetUnitFacing(d.caster)),GetUnitFacing(d.caster))
call SetUnitPathing(db,false)
call SetUnitExploded(db,true)
call TJSetUnitHeight(db,75)
call UnitApplyTimedLife(db,039;BTLF039;,d.dis/ArcticBlastSpeed)
call GroupAddUnit(d.blast,db)
call TriggerRegisterUnitInRange(d.hit,db,ArcticBoltCollides,null)
set db = null
set d.interval = BoltInterval
call SetUnitState(d.caster,UNIT_STATE_MANA,GetUnitState(d.caster,UNIT_STATE_MANA)-d.cost)
endif
set d.interval = d.interval - 1
endif
if IsUnitGroupDeadBJ(d.blast) then
call SetCSData(d.caster,0)
call data.destroy(d)
else
call ForGroup(d.blast,function ArcticBlastGM)
endif
endfunction
private function ArcticBlast takes unit c, real min, real max, real dis, integer lvl,real cost returns nothing
local data d = GetCSData(c)
if d == 0 then
set d = data.create()
set d.hit = CreateTrigger()
set d.hitact = TriggerAddAction(d.hit,function ArcticBlastH )
set d.move = NewTimer()
call TimerStart(d.move,0.05,true, function ArcticBlastE)
set d.blast = NewGroup()
call SetCSData(d.move,d)
call SetCSData(d.hit,d)
call SetCSData(c,d)
endif
set d.cx = GetUnitX(c)
set d.cy = GetUnitY(c)
set d.caster = c
set d.cost = cost
set d.min = min
set d.max = max
set d.lvl = lvl
set d.dis = dis
endfunction
private function ArcticBlastC takes nothing returns boolean
return GetSpellAbilityId() == ArcticBlastID
endfunction
private function ArcticBlastA takes nothing returns nothing
local unit c = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(c,ArcticBlastID)
call ArcticBlast(c,GetMinDamage( lvl ) , GetMaxDamage( lvl ) , GetDistance( lvl ) , lvl , GetManaCost( lvl ) )
set c = null
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function ArcticBlastC ) )
call TriggerAddAction( t, function ArcticBlastA )
set t = null
endfunction
endscope
v1.1
JASS:
//=====================================================================================================
//| Artic Blast
//| ¯¯¯¯¯¯¯¯¯¯¯¯¯
//|
//| Requires:
//| ¯¯¯¯¯¯¯¯
//| JASS NewGen
//| ABC and PUI of Cohadar
//|
//| How to implement in your map:
//| ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//| Make sure you have JASS Newgen, it can be found on wc3campaigns
//| Copy the ABC trigger to your map unless you already have it
//| Copy the PUI trigger to your map
//| Copy the ArcticBlast trigger to your map
//| Copy the unit Dummy and Dummy Arctic Bolt
//| Copy the ability Arctic Blast and Arctic Blast Slow
//| In the ArcticBlast trigger, change the RAW IDs of the dummy units and ability ID
//| to match the ones you have (ctrl + D in object editor to view RAW IDs)
//|
//| Credit:
//| ¯¯¯¯¯¯¯
//| If you like this spell and decide to use it in your map, I would be happy to be mentioned
//| somewhere, but it is not required <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
//|
//| Modification:
//| ¯¯¯¯¯¯¯¯¯¯¯¯
//| You can change any of the values in the globals section of ArcticBlast trigger to your liking
//| Only change the core functions if you're experienced in JASS
//|
//=====================================================================================================
scope ArcticBlast initializer Init
globals
private integer ArcticBlastID = 039;A001039; //RawId of the Arctic Blast ability
private integer ArcticBoltID = 039;n002039; //RawId of the Arctic Bolt dummy
private real ArcticBlastSpeed = 800 //speed for the Arctic Blast bolts
private integer IceSlowID = 039;A000039; //this ability is used for slow, modify this for the slow duration
private string IceSlowOrder = "frostnova" //this is order string of the ice slow ability, if you use a different ability (not Frost Nova), you should change this
private real ArcticBoltCollides = 125. //the range that the Arctic Blast bolts will hit enemy unit.
private integer BoltInterval = 2 //This is the amount of time between the fire of two bolts
private integer DummyId = 039;e000039; //dummy unit's Id
//inteval = BoltInterval * 0.05 = 0.1. So every 0.1s a bolt will be fired
private real DamageInterval = BoltInterval * 0.05 // = 0.1
endglobals
//==========================================
private function SetUnitZ takes unit c, real h returns nothing
call UnitAddAbility(c,039;Amrf039;)
call UnitRemoveAbility(c,039;Amrf039;)
call SetUnitFlyHeight(c,h,0)
endfunction
private function GetPPX takes real x, real dist, real angle returns real
return x + dist * Cos(angle * bj_DEGTORAD)
endfunction
private function GetPPY takes real y, real dist, real angle returns real
return y + dist * Sin(angle * bj_DEGTORAD)
endfunction
//===========================================
globals
private unit SLOWCASTER
private integer TEMPINT
endglobals
private function GetManaCost takes integer lvl returns real
return 10. //this is the mana cost per DamageInterval second
endfunction
private function GetMinDamage takes integer lvl returns real
return lvl * 5. //this is the minimum damage per DamageInterval second
endfunction
private function GetMaxDamage takes integer lvl returns real
return lvl * 10. //this is the maximum damage per DamageInterval second
endfunction
private function GetDistance takes integer lvl returns real
return 400.+100.*lvl
endfunction
//===========================================
private struct data
//! runtextmacro PUI()
unit caster = null
trigger hit = null
triggeraction hitact = null
timer move = null
group blast = null
integer blastc = 0
real cx = 0.0
real cy = 0.0
real cost = 0.0
real min = 0.0
real max = 0.0
real dis = 0.0
integer interval = 0
integer lvl = 0
boolean stop = false
sound snd
method onDestroy takes nothing returns nothing
if .hit != null then
call ClearTriggerStructA(.hit)
call DisableTrigger(.hit)
call TriggerRemoveAction(.hit, .hitact)
call DestroyTrigger(.hit)
endif
if .move != null then
call ClearTimerStructA(.move)
call DestroyTimer(.move)
endif
if .blast != null then
call DestroyGroup(.blast)
endif
endmethod
endstruct
private function ArcticBlastH takes nothing returns nothing
local data d = GetTriggerStructA(GetTriggeringTrigger())
local unit a = GetTriggerUnit()
if GetWidgetLife(a) == 0 or not IsUnitEnemy(a,GetOwningPlayer(d.caster)) then
set a = null
return
endif
//when a is alive and a is an enemy, a takes damage (Still need more conditions)
call UnitDamageTarget(d.caster,a,GetRandomReal(d.min,d.max),false,true,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,WEAPON_TYPE_WHOKNOWS)
call IssueImmediateOrder(SLOWCASTER,"stop")
call SetUnitAbilityLevel(SLOWCASTER,IceSlowID,d.lvl)
call IssueTargetOrder(SLOWCASTER,IceSlowOrder,a)
set a = null
endfunction
private function ArcticBlastGM takes nothing returns nothing
local data d = TEMPINT
local unit e = GetEnumUnit()
if IsUnitType(e,UNIT_TYPE_DEAD) then
call GroupRemoveUnit(d.blast,e)
set d.blastc = d.blastc - 1
else
call SetUnitPosition(e, GetPPX(GetUnitX(e),ArcticBlastSpeed/25.,GetUnitFacing(e)), GetPPY(GetUnitY(e),ArcticBlastSpeed/25.,GetUnitFacing(e)) )
endif
set e = null
endfunction
private function ArcticBlastE takes nothing returns nothing
local data d = GetTimerStructA( GetExpiredTimer() )
local boolean b = true
local string o
local unit db
if not d.stop then
if GetUnitState(d.caster,UNIT_STATE_MANA)<d.cost then
call IssueImmediateOrder(d.caster,"stop")
endif
set o = OrderId2String(GetUnitCurrentOrder(d.caster))
if o != "blizzard" or d.cx != GetUnitX(d.caster) or d.cy != GetUnitY(d.caster) then
set d.stop = true
call StopSound(d.snd,true,true)
endif
if d.interval == 0 and b then
set db = CreateUnit(GetOwningPlayer(d.caster),ArcticBoltID,GetPPX(GetUnitX(d.caster),50,GetUnitFacing(d.caster)), GetPPY(GetUnitY(d.caster),50,GetUnitFacing(d.caster)),GetUnitFacing(d.caster))
call SetUnitPathing(db,false)
call SetUnitExploded(db,true)
call SetUnitZ(db,40.)
call UnitApplyTimedLife(db,039;BTLF039;,d.dis/ArcticBlastSpeed)
call GroupAddUnit(d.blast,db)
call TriggerRegisterUnitInRange(d.hit,db,ArcticBoltCollides,null)
call SetUnitTimeScale(db,0.)
set db = null
set d.interval = BoltInterval
call SetUnitState(d.caster,UNIT_STATE_MANA,GetUnitState(d.caster,UNIT_STATE_MANA)-d.cost)
set d.blastc = d.blastc - 1
endif
set d.interval = d.interval - 1
endif
if d.blastc == 0 then
set data[d.caster] = 0
else
set TEMPINT = d
call ForGroup(d.blast,function ArcticBlastGM)
endif
endfunction
private function ArcticBlast takes unit c, real min, real max, real dis, integer lvl,real cost returns nothing
local data d = data[c]
if d == 0 then
set d = data.create()
set d.hit = CreateTrigger()
set d.hitact = TriggerAddAction(d.hit,function ArcticBlastH )
set d.move = CreateTimer()
call TimerStart(d.move,0.05,true, function ArcticBlastE)
set d.blast = CreateGroup()
call SetTimerStructA(d.move,d)
call SetTriggerStructA(d.hit,d)
//set d.snd = CreateSound("Units\\Undead\\FrostWyrm\\FrostwyrmAttack1.wav",true,true,true, 10 , 10 , "" )
set d.snd = CreateSound("Abilities\\Spells\\Other\\BreathOfFrost\\BreathOfFrost1.wav" ,true,true,true, 10 , 10 , "" )
call SetSoundVolume(d.snd,127)
call StartSound(d.snd)
set data[c] = d
endif
set d.cx = GetUnitX(c)
set d.cy = GetUnitY(c)
call SetSoundPosition(d.snd,d.cx,d.cy,0.)
set d.caster = c
set d.cost = cost
set d.min = min
set d.max = max
set d.lvl = lvl
set d.dis = dis
set d.stop = false
endfunction
private function ArcticBlastC takes nothing returns boolean
return GetSpellAbilityId() == ArcticBlastID
endfunction
private function ArcticBlastA takes nothing returns nothing
local unit c = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(c,ArcticBlastID)
call ArcticBlast(c,GetMinDamage( lvl ) , GetMaxDamage( lvl ) , GetDistance( lvl ) , lvl , GetManaCost( lvl ) )
set c = null
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function ArcticBlastC ) )
call TriggerAddAction( t, function ArcticBlastA )
set t = null
set SLOWCASTER = CreateUnit( Player(15), DummyId, 0.,0.,0. )
call UnitAddAbility( SLOWCASTER, IceSlowID )
endfunction
endscope
version 1.2 is compatible with patch 1.24b
Credit:
- Thanks Tinki3 for the test map template
- Thanks Vexorian for the CasterSystem
(v1.1)
- Thanks Tinki3 for the test map template
- Thanks Vexorian for CSData
- Thanks Cohadar for PUI and ABC