Vestras' Entry for the Spell Olympic Contest at Wc3campaigns.
Contains:
- Overheat (Fire)
- Hailstorm (Frost)
- Summon Abyss (Darkness)
They do all require HAIL and NewGen.
They are all completely MUI.
They are all in vJASS.
Overheat's Code:
Hailstorm's Code:
Summon Abyss' Code:
Enjoy.
Small notice; to those who thinks that Flare's Conflagrate and my Overheat looks very much the same; yes, but the funny thing is, that I started to work on that spell before Flare had submitted his. Period.
Contains:
- Overheat (Fire)
- Hailstorm (Frost)
- Summon Abyss (Darkness)
They do all require HAIL and NewGen.
They are all completely MUI.
They are all in vJASS.
Overheat's Code:
JASS:
scope Overheat
//! runtextmacro HAIL_CreateProperty("Data","integer","private")
// C O N F I G U R A T I O N
globals
private constant integer SPELLID = 039;A000039;
// The spell raw code.
private constant integer DUMMYID = 039;h001039;
// The dummy raw code.
private constant real RANGE = 800
// The range of the spell.
private constant real DMGRANGE = 170
// The range in which units are damaged.
private constant real SPEED = 1600
// The movement speed of the wave. This is divided by the timer interval. The higher speed, the less concentrated is the fx.
private constant real INTERVAL = 0.03
// The timer interval. This is periodic time which the timer is ran.
private constant real MOVESPEED = SPEED * INTERVAL
// The movespeed of the wave. I don't think you should edit that one.
private constant string LAVAFX = "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl"
// The path of the lava fx. (The actual wave missle.)
private constant string EXPLFX = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
// The path of the explosion fx. (The fx that comes when a unit is hit.)
private constant string UBERSPLAT = "DHSB"
// The path of the ubersplat at the end of the wave.
private constant string ATCHPOINT = "chest"
// The attach point of the model.
private constant boolean DOSPLAT = true
// Create the ubersplat or not?
private constant boolean PRELOAD = true
// Allow the trigger to preload? That will cause less lag when using the spell.
private constant damagetype DTYPE = DAMAGE_TYPE_FIRE
// The damage type of the damage.
endglobals
private function DAMAGE takes unit u returns real
// The damage calculate function. You can always add more levels
// by adding elseif lvl==yourlevel then
// return yourdamage
// endif
local integer lvl=GetUnitAbilityLevel(u,SPELLID)
if lvl==1 then
return 65.
elseif lvl==2 then
return 85.
elseif lvl==3 then
return 110.
endif
return 0. // Safety
endfunction
// The neccesary globals;
globals
private player Owner
private unit CastUnit
private boolean done
private group SafeGroup=CreateGroup()
endglobals
// The struct;
private struct OverData
real cx
real cy
real px
real py
real angle
real trange
timer tmr
ubersplat splat
unit caster
unit dummy
private method onDestroy takes nothing returns nothing
call ResetData(.tmr)
call DestroyTimer(.tmr)
set .caster=null
set .tmr=null
set .cx=0
set .cy=0
set .px=0
set .py=0
set .angle=0
set .trange=0
set CastUnit=null
set Owner=null
set done=false
endmethod
endstruct
// End of the struct.
// And finaly, the real code;
private constant function Conditions takes nothing returns boolean
return GetSpellAbilityId()==SPELLID
endfunction
private function FilterActs takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(),Owner)==true
endfunction
private function EndActs takes nothing returns nothing
local OverData d=GetData(GetExpiredTimer())
call FinishUbersplat(d.splat)
call DestroyUbersplat(d.splat)
set d.splat=null
call DestroyTimer(GetExpiredTimer())
endfunction
private function GroupDamage takes nothing returns nothing
local unit s=GetEnumUnit()
local real x=GetUnitX(s)
local real y=GetUnitY(s)
if IsUnitEnemy(s,GetOwningPlayer(CastUnit))==true and GetWidgetLife(s)>.405 and IsUnitType(s,UNIT_TYPE_GROUND)==true then
if IsUnitInGroup(s,SafeGroup) then
else
call UnitDamageTarget(CastUnit,s,DAMAGE(CastUnit),false,true,ATTACK_TYPE_NORMAL,DTYPE,null)
call DestroyEffect(AddSpecialEffect(EXPLFX,x,y))
call GroupAddUnit(SafeGroup,s)
endif
endif
if done==true then
call GroupRemoveUnit(SafeGroup,s)
endif
set s=null
endfunction
private function TimerActs takes nothing returns nothing
local OverData d=GetData(GetExpiredTimer())
local real x
local real y
local real x1=GetUnitX(d.dummy)
local real y1=GetUnitY(d.dummy)
local group grp=CreateGroup()
local unit s
local unit c
local real px=x1+Cos(d.angle)*MOVESPEED
local real py=y1+Sin(d.angle)*MOVESPEED
set d.trange=d.trange+MOVESPEED
set c=CreateUnit(GetOwningPlayer(d.caster),DUMMYID,px,py,d.angle)
call DestroyEffect(AddSpecialEffectTarget(LAVAFX,c,ATCHPOINT))
call UnitApplyTimedLife(c,039;BTLF039;,5)
call SetUnitX(d.dummy,px)
call SetUnitY(d.dummy,py)
call GroupEnumUnitsInRange(grp,px,py,DMGRANGE,Filter(function FilterActs))
call ForGroup(grp,function GroupDamage)
if d.trange>=RANGE then
set done=true
if DOSPLAT==true then
set d.splat=CreateUbersplat(d.px,d.py,UBERSPLAT,255,255,255,PercentTo255(100.0-0),false,false)
call SetUbersplatRenderAlways(d.splat,true)
call ShowUbersplat(d.splat,true)
call TimerStart(CreateTimer(),0.25,false,function EndActs)
endif
call d.destroy()
endif
call DestroyGroup(grp)
set grp=null
set c=null
set s=null
endfunction
private function Actions takes nothing returns nothing
local OverData d=OverData.create()
local location l=GetSpellTargetLoc()
local real x1=GetUnitX(GetTriggerUnit())
local real y1=GetUnitY(GetTriggerUnit())
local real x2=GetLocationX(l)
local real y2=GetLocationY(l)
set d.caster=GetTriggerUnit()
set d.tmr=CreateTimer()
set d.cx=GetUnitX(d.caster)
set d.cy=GetUnitY(d.caster)
set d.angle=Atan2(y2-y1,x2-x1)
set d.px=d.cx+MOVESPEED*Cos(d.angle*bj_DEGTORAD)
set d.py=d.cy+MOVESPEED*Sin(d.angle*bj_DEGTORAD)
set Owner=GetOwningPlayer(d.caster)
set CastUnit=d.caster
set done=false
call GroupClear(SafeGroup)
set d.dummy=CreateUnit(GetOwningPlayer(d.caster),DUMMYID,d.px,d.py,0)
call SetData(d.tmr,d)
call TimerStart(d.tmr,INTERVAL,true,function TimerActs)
call RemoveLocation(l)
set l=null
endfunction
//===========================================================================
function InitTrig_Overheat takes nothing returns nothing
local trigger t=CreateTrigger()
local unit d=null
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Conditions))
call TriggerAddAction(t,function Actions)
if PRELOAD==true then
set d=CreateUnit(Player(0),DUMMYID,0,0,0)
call UnitAddAbility(d,SPELLID)
call UnitRemoveAbility(d,SPELLID)
call RemoveUnit(d)
call Preload(LAVAFX)
call Preload(EXPLFX)
call Preload(UBERSPLAT)
endif
if d!=null then
set d=null
endif
endfunction
endscope
Hailstorm's Code:
JASS:
scope Hailstorm
//! runtextmacro HAIL_CreateProperty("Data","integer","private")
// C O N F I G U R A T I O N
globals
private constant integer SPELLID = 039;A001039;
// The spell raw code.
private constant integer DUMMYID = 039;h000039;
// The dummy raw code.
private constant real AOE = 300
// The AoE in which the hails will appear.
private constant real RANGE = 10
// The range the hails needs to be in before the damage takes place.
private constant real INTERVAL = 0.01
// The timer interval. This is periodic time which the timer is ran.
private real DECREASE = 5
// The fly height which is decreased of the hails.
// This one is not constant, because that if it were, it would be impossible to reset it during onDestroy. If it weren't reset, the speed would increase and increase for each time casted.
private constant real TRGHEIGHT = 300
// The fly height which makes the hails search towards the target.
private constant real TRAVELDIST = 5
// The travel distance when the hails will search towards the target.
private constant string HAILFX = "Abilities\\Weapons\\ZigguratFrostMissile\\ZigguratFrostMissile.mdl"
// The path of the hail model.
private constant string TAILFX = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl"
// The path of the "tail" on the hails.
private constant string IMPACTFX = "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl"
// The path of the fx which comes on impact from the hails.
private constant string ATCHPOINT = "chest"
// The attach point of the model.
private constant damagetype DTYPE = DAMAGE_TYPE_COLD
// The damage type of the damage.
private constant boolean PRELOAD = true
// Allow the trigger to preload? It will cause less lag when casting the spell.
endglobals
private function DAMAGE takes unit u returns real
// The damage calculate function. You can always add more levels
// by adding elseif lvl==yourlevel then
// return yourdamage
// endif
local integer lvl=GetUnitAbilityLevel(u,SPELLID)
if lvl==1 then
return 15.
elseif lvl==2 then
return 20.
elseif lvl==3 then
return 25.
endif
return 0. // Safety
endfunction
private function HAILS takes unit u returns integer
// The number of hails calculate function. You can always add more levels
// by adding elseif lvl==yourlevel then
// return yourhails
// endif
local integer lvl=GetUnitAbilityLevel(u,SPELLID)
if lvl==1 then
return 6
elseif lvl==2 then
return 12
elseif lvl==3 then
return 18
endif
return 0 // Safety
endfunction
// The neccesary globals
globals
private group SafeHails=CreateGroup()
endglobals
// The struct;
private struct HailData
unit caster
unit target
real tx
real ty
group dummies
timer tmr
trigger trg
trigger trg2
boolean done
private method onDestroy takes nothing returns nothing
set DECREASE=DECREASE
call ResetData(.tmr)
call ResetData(.trg)
call ResetData(.trg2)
call DestroyGroup(.dummies)
call DestroyTimer(.tmr)
call DestroyTrigger(.trg)
call DestroyTrigger(.trg2)
set .caster=null
set .target=null
set .dummies=null
set .tmr=null
set .trg=null
set .trg2=null
endmethod
endstruct
// End of the struct
// And finaly, the real code;
private constant function Conditions takes nothing returns boolean
return GetSpellAbilityId()==SPELLID
endfunction
private function SelectActs takes nothing returns boolean
local HailData d=GetData(GetTriggeringTrigger())
if IsUnitInGroup(GetTriggerUnit(),d.dummies)==true then
if GetLocalPlayer()==GetOwningPlayer(GetTriggerUnit()) then
call SelectUnit(GetTriggerUnit(),false)
endif
endif
return false
endfunction
private function InRangeActs takes nothing returns boolean
local HailData d=GetData(GetTriggeringTrigger())
local unit u=GetEnteringUnit()
call UnitDamageTarget(d.caster,d.target,DAMAGE(d.caster),false,true,ATTACK_TYPE_NORMAL,DTYPE,null)
call DestroyEffect(AddSpecialEffect(IMPACTFX,d.tx,d.ty))
call RemoveUnit(u)
set u=null
return false
endfunction
private function RemoveActs takes nothing returns nothing
local real x=GetUnitX(GetEnumUnit())
local real y=GetUnitY(GetEnumUnit())
call DestroyEffect(AddSpecialEffect(IMPACTFX,x,y))
call RemoveUnit(GetEnumUnit())
endfunction
private function SearchActs takes nothing returns nothing
local HailData d=GetData(SafeHails)
local real x1=GetUnitX(GetEnumUnit())
local real y1=GetUnitY(GetEnumUnit())
local real angle
local real x2
local real y2
set d.tx=GetUnitX(d.target)
set d.ty=GetUnitY(d.target)
set angle=bj_RADTODEG*Atan2(d.ty-y1,d.tx-x1)
set x2=x1+TRAVELDIST*Cos(angle*bj_DEGTORAD)
set y2=y1+TRAVELDIST*Sin(angle*bj_DEGTORAD)
if CountUnitsInGroup(d.dummies)<2 and d.done!=true then
call ForGroup(d.dummies,function RemoveActs)
call DestroyTimer(GetExpiredTimer())
set d.done=true
call d.destroy()
return
endif
if GetWidgetLife(d.target)<.405 and d.done!=true then
call ForGroup(d.dummies,function RemoveActs)
call DestroyTimer(GetExpiredTimer())
set d.done=true
call d.destroy()
return
endif
call SetUnitX(GetEnumUnit(),x2)
call SetUnitY(GetEnumUnit(),y2)
endfunction
private function GroupHeight takes nothing returns nothing
local unit s=GetEnumUnit()
local real h=GetUnitFlyHeight(s)-DECREASE
call SetUnitFlyHeight(s,h,0)
if GetUnitFlyHeight(s)<=TRGHEIGHT then
call GroupAddUnit(SafeHails,s)
endif
set s=null
endfunction
private function TimerActs takes nothing returns nothing
local HailData d=GetData(GetExpiredTimer())
call SetData(SafeHails,d)
call ForGroup(d.dummies,function GroupHeight)
call ForGroup(SafeHails,function SearchActs)
endfunction
private function Actions takes nothing returns nothing
local HailData d=HailData.create()
local integer i=1
local unit n=GetSpellTargetUnit()
local real x1=GetUnitX(n)
local real y1=GetUnitY(n)
local rect r=Rect(x1-AOE*0.5,y1-AOE*0.5,x1+AOE*0.5,y1+AOE*0.5)
local real f
local real x2
local real y2
local unit u
set d.caster=GetTriggerUnit()
set d.target=GetSpellTargetUnit()
set d.dummies=CreateGroup()
set d.tmr=CreateTimer()
set d.trg=CreateTrigger()
set d.trg2=CreateTrigger()
set d.tx=GetUnitX(d.target)
set d.ty=GetUnitY(d.target)
set d.done=false
call TriggerRegisterUnitInRange(d.trg,d.target,RANGE,null)
call TriggerAddCondition(d.trg,Condition(function InRangeActs))
call SetData(d.trg,d)
call TriggerRegisterPlayerUnitEvent(d.trg2,GetOwningPlayer(d.caster),EVENT_PLAYER_UNIT_SELECTED,null)
call TriggerAddCondition(d.trg2,Condition(function SelectActs))
call SetData(d.trg2,d)
loop
exitwhen i>HAILS(d.caster)
set f=GetRandomReal(0,360)
set x2=GetRandomReal(GetRectMinX(r),GetRectMaxX(r))
set y2=GetRandomReal(GetRectMinY(r),GetRectMaxY(r))
set u=CreateUnit(GetOwningPlayer(d.caster),DUMMYID,x2,y2,f)
call GroupAddUnit(d.dummies,u)
call SetUnitFlyHeight(u,1000,0)
call AddSpecialEffectTarget(HAILFX,u,ATCHPOINT)
call AddSpecialEffectTarget(TAILFX,u,ATCHPOINT)
set i=i+1
endloop
call TimerStart(d.tmr,INTERVAL,true,function TimerActs)
call SetData(d.tmr,d)
call RemoveRect(r)
set r=null
set n=null
set u=null
endfunction
//===========================================================================
function InitTrig_Hailstorm takes nothing returns nothing
local trigger t=CreateTrigger()
local unit d=null
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Conditions))
call TriggerAddAction(t,function Actions)
call GroupClear(SafeHails)
if PRELOAD==true then
set d=CreateUnit(Player(0),DUMMYID,0,0,0)
call UnitAddAbility(d,SPELLID)
call UnitRemoveAbility(d,SPELLID)
call RemoveUnit(d)
call Preload(HAILFX)
call Preload(TAILFX)
call Preload(IMPACTFX)
endif
if d!=null then
set d=null
endif
endfunction
endscope
Summon Abyss' Code:
JASS:
scope SummonAbyss
//! runtextmacro HAIL_CreateProperty("Data","integer","private")
globals
private constant integer SPELLID = 039;A003039;
// The spell raw code.
private constant integer DUMMYID = 039;h002039;
// The dummy raw code.
private constant integer BANID = 039;A004039;
// The banish raw code.
private constant real RANGE = 150
// The range the opponents needs to be in before the damage and banish takes place.
private constant real INTERVAL = 0.01
// The timer interval. This is periodic time which the timer is ran.
private real TRAVELDIST = 5
// The travel distance which the dragon will move each INTERVAl seconds.
// Yes, it is intended that it isn't constant.
private constant real LIVINGTIME = 1.25
// The seconds the dragon can live.
private constant string DARKFX = "units\\creeps\\NetherDragon\\NetherDragon.mdl"
// The path of the dragon model.
private constant string EXPLFX = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilSpecialArt.mdl"
// The path of the explosion.
private constant string IMPACTFX = "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl"
// The path of the fx which comes on impact from the hails.
private constant string ORDER = "banish"
// The order string. Can be useful if you want the targets to be stunned instead of banished.
private constant string ATCHPOINT = "chest"
// The attach point of the model.
private constant damagetype DTYPE = DAMAGE_TYPE_DEATH
// The damage type of the damage.
private constant boolean PRELOAD = true
// Allow the trigger to preload? It will cause less lag when casting the spell.
endglobals
private function DAMAGE takes unit u returns real
// The damage calculate function. You can always add more levels
// by adding elseif lvl==yourlevel then
// return yourdamage
// endif
local integer lvl=GetUnitAbilityLevel(u,SPELLID)
if lvl==1 then
return 60.
elseif lvl==2 then
return 80.
elseif lvl==3 then
return 100.
endif
return 0. // Safety
endfunction
// The neccesary globals;
globals
endglobals
// The struct;
private struct AbyssData
unit caster
unit dummy
real angle
timer tmr
timer tmr2
trigger trg
private method onDestroy takes nothing returns nothing
set TRAVELDIST=TRAVELDIST
call ResetData(.tmr)
call ResetData(.tmr2)
call ResetData(.trg)
call DestroyTimer(.tmr)
call DestroyTimer(.tmr2)
call DestroyTrigger(.trg)
set .caster=null
set .dummy=null
set .tmr=null
set .tmr2=null
set .trg=null
endmethod
endstruct
// End of the struct.
// And finaly, the real code.
private constant function Conditions takes nothing returns boolean
return GetSpellAbilityId()==SPELLID
endfunction
private function InRangeActs takes nothing returns boolean
local AbyssData d=GetData(GetTriggeringTrigger())
local real dx=GetUnitX(d.dummy)
local real dy=GetUnitY(d.dummy)
local unit u
if IsUnitEnemy(GetTriggerUnit(),GetOwningPlayer(d.caster))==true then
call UnitDamageTarget(d.caster,GetTriggerUnit(),DAMAGE(d.caster),false,true,ATTACK_TYPE_NORMAL,DTYPE,null)
call DestroyEffect(AddSpecialEffectTarget(IMPACTFX,GetTriggerUnit(),"origin"))
set u=CreateUnit(GetOwningPlayer(d.dummy),DUMMYID,dx,dy,0)
call UnitAddAbility(u,BANID)
call IssueTargetOrder(u,ORDER,GetTriggerUnit())
call UnitApplyTimedLife(u,039;BTLF039;,2)
endif
set u=null
return false
endfunction
private function KillActs takes nothing returns nothing
local AbyssData d=GetData(GetExpiredTimer())
local real dx=GetUnitX(d.dummy)
local real dy=GetUnitY(d.dummy)
call DestroyEffect(AddSpecialEffect(EXPLFX,dx,dy))
call RemoveUnit(d.dummy)
call d.destroy()
endfunction
private function TimerActs takes nothing returns nothing
local AbyssData d=GetData(GetExpiredTimer())
local real dx=GetUnitX(d.dummy)
local real dy=GetUnitY(d.dummy)
local real px=dx+TRAVELDIST*Cos(d.angle*bj_DEGTORAD)
local real py=dy+TRAVELDIST*Sin(d.angle*bj_DEGTORAD)
call SetUnitPosition(d.dummy,px,py)
endfunction
private function Actions takes nothing returns nothing
local AbyssData d=AbyssData.create()
local location l=GetSpellTargetLoc()
local real x1
local real y1
local real x2
local real y2
set d.caster=GetTriggerUnit()
set d.tmr=CreateTimer()
set d.trg=CreateTrigger()
set d.tmr2=CreateTimer()
set x1=GetUnitX(d.caster)
set y1=GetUnitY(d.caster)
set x2=GetLocationX(l)
set y2=GetLocationY(l)
set d.angle=bj_RADTODEG*Atan2(y2-y1,x2-x1)
set d.dummy=CreateUnit(GetOwningPlayer(d.caster),DUMMYID,x1,y1,GetUnitFacing(d.caster))
call AddSpecialEffectTarget(DARKFX,d.dummy,ATCHPOINT)
call TimerStart(d.tmr,INTERVAL,true,function TimerActs)
call SetData(d.tmr,d)
call TimerStart(d.tmr2,LIVINGTIME,false,function KillActs)
call SetData(d.tmr2,d)
call TriggerRegisterUnitInRange(d.trg,d.dummy,RANGE,null)
call TriggerAddCondition(d.trg,Condition(function InRangeActs))
call SetData(d.trg,d)
call RemoveLocation(l)
set l=null
endfunction
//===========================================================================
function InitTrig_SummonAbyss takes nothing returns nothing
local trigger t=CreateTrigger()
local unit d=null
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Conditions))
call TriggerAddAction(t,function Actions)
if PRELOAD==true then
set d=CreateUnit(Player(0),DUMMYID,0,0,0)
call UnitAddAbility(d,SPELLID)
call UnitRemoveAbility(d,SPELLID)
call RemoveUnit(d)
call Preload(DARKFX)
call Preload(EXPLFX)
call Preload(IMPACTFX)
endif
if d!=null then
set d=null
endif
endfunction
endscope
Enjoy.
Small notice; to those who thinks that Flare's Conflagrate and my Overheat looks very much the same; yes, but the funny thing is, that I started to work on that spell before Flare had submitted his. Period.