- Joined
- Mar 28, 2005
- Messages
- 160
just figured out how to ignore ability learn orders - but won't have the time to update the spell to make use of "more optimized" END_CAST detection 
how come my spell is not be counted?
But I guess it's your final submission now.in case I don't get around to re-taking a look at this, here is my current WIP
vengeancekael: since my last wip has been re-uploaded, with some changes (a simple buff, str - heal, agi - poison, int - slow) if you dont mind, can you make another one vids for me?
//----------------------------------------------------------------------------------
//Sheep Strike
//Spells and systems contest #20
//Created by : Xiliger
//Uses :
// TimerUtils by Vexorian
// Parabolic movement by Mayoc/Spec
// GroupUtils by Rising_Dusk
//----------------------------------------------------------------------------------
scope SheepStrike initializer Init
globals
private constant integer SPELLID = 'A000'
//This is the abilities id
private constant integer UNITID = 'n000'
//This is the sheep dummy units id
private constant integer MAXCOUNT = 5
//This is the maximum units that gets created
private constant real MAXDISTANCE = 800.00
//This is the distance from the cast point the units will summon
private constant real UNITDISTANCE = 75.00
//This is the distance between units as they are summoned
private constant real MAXHEIGHT = 300.00
//This is the flying height that the units gets spawned
private constant real MAXHEIGHTPARABOLA = 500.00
//This is the maximum height for the parabolic movement
private constant real MOVEDISTANCE = 20.00
//This is the distance a unit is moved by the timer
private constant real DAMAGEAREA = 100.00
//This is the detection area in wich damage will be done
private constant real DAMAGEDONE = 100.00
//This is the damage that is done to units
private constant real RELAPSHIGHT = 400.00
//This is the maximun height for the second bounce
private constant real RELAPSDISTANCE = 7.50
//This is the distance moved in the 3rd phase
private constant string SPELLEFFECT1 = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
//This is the "Fire Effect" added to the sheep
private constant string SPELLEFFECT2 = "Abilities\\Weapons\\SteamTank\\SteamTankImpact.mdl"
endglobals
private function GetDistance takes nothing returns real //Returns a random distance
local real rMin = 0 //This is the min value for the random distance
local real rMax = 300 //This is the max value for the random distance
return GetRandomReal(rMin, rMax)
endfunction
struct Data
unit dUnit = null
unit dCaster = null
real dDistance = 0.00
real dCDistance = 0.00
real dAngle = 0.00
real x = 0.00
real y = 0.00
effect dEffect1 = null
effect dEffect2 = null
boolean dBool1 = false
boolean dBool2 = false
boolean dBool3 = false
boolean dBool4 = false
boolean dBool5 = false
integer dVertex = 0
player dOwner = null
static method create takes unit caster, real x, real y, real a, real d returns Data
local Data dat = Data.allocate()
local timer t = NewTimer()
set dat.dUnit = CreateUnit(GetOwningPlayer(caster), UNITID, x, y, a)
set dat.dCaster = caster
set dat.dDistance = d
set dat.dAngle = a
set dat.dOwner = GetOwningPlayer(caster)
call SetUnitVertexColor(dat.dUnit, 225, 225, 225, 0)
call SetUnitFlyHeight(dat.dUnit, MAXHEIGHT, 0)
call SetTimerData(t, dat)
call TimerStart(t, 0.04, true, function Data.onLoop)
return dat
endmethod
private static method onLoop takes nothing returns nothing
local timer t = GetExpiredTimer()
local Data dat = GetTimerData(t)
local real x = GetUnitX(dat.dUnit) + MOVEDISTANCE * Cos(dat.dAngle * bj_DEGTORAD)
local real y = GetUnitY(dat.dUnit) + MOVEDISTANCE * Sin(dat.dAngle * bj_DEGTORAD)
local real d = 0
local unit n = null
local rect r = bj_mapInitialPlayableArea
local real rX = 0
local real rY = 0
set dat.x = GetUnitX(dat.dUnit)
set dat.y = GetUnitY(dat.dUnit)
if dat.dVertex < 255 then
set dat.dVertex = dat.dVertex + 25
call SetUnitVertexColor(dat.dUnit, 255, 255, 255, dat.dVertex)
endif
//-------------------------------------------------------------------------------------------
//------------------This is the first phase of the spell-------------------------------------
//-------------------------------------------------------------------------------------------
if (dat.dDistance > dat.dCDistance) and (dat.dBool2 == false) then
call SetUnitX(dat.dUnit, x)
call SetUnitY(dat.dUnit, y)
set dat.dCDistance = dat.dCDistance + MOVEDISTANCE
if (dat.dCDistance > (dat.dDistance / 2)) and (dat.dBool1 == false) then
set dat.dEffect1 = AddSpecialEffectTarget(SPELLEFFECT1, dat.dUnit, "origin")
set dat.dBool1 = true
endif
else //The following code switches to the second phase
if dat.dBool2 == false then
set d = GetDistance()
set dat.dBool2 = true
set dat.dBool3 = true
set dat.dAngle = GetRandomReal(0, 359)
set x = GetUnitX(dat.dUnit) + d * Cos(dat.dAngle * bj_DEGTORAD)
set y = GetUnitY(dat.dUnit) + d * Sin(dat.dAngle * bj_DEGTORAD)
set dat.dDistance = SquareRoot((x - GetUnitX(dat.dUnit)) * (x - GetUnitX(dat.dUnit)) + (y - GetUnitY(dat.dUnit)) * (y - GetUnitY(dat.dUnit)))
set dat.dCDistance = 0
endif
endif
//-------------------------------------------------------------------------------------------
//------------------This is the second phase of the spell------------------------------------
//-------------------------------------------------------------------------------------------
if (dat.dDistance > dat.dCDistance) and (dat.dBool2 == true) then
set dat.dCDistance = dat.dCDistance + RELAPSDISTANCE
set x = dat.x + RELAPSDISTANCE * Cos(dat.dAngle * bj_DEGTORAD)
set y = dat.y + RELAPSDISTANCE* Sin(dat.dAngle * bj_DEGTORAD)
call SetUnitX(dat.dUnit, x)
call SetUnitY(dat.dUnit, y)
call SetUnitFacing(dat.dUnit, dat.dAngle)
call SetUnitFlyHeight(dat.dUnit, ParabolaZ2( MAXHEIGHT, 0, MAXHEIGHTPARABOLA, dat.dDistance, dat.dCDistance), 0)
else
if dat.dBool3 == true then
set dat.dBool3 = false
call GroupUnitsInArea(ENUM_GROUP, dat.x, dat.y, DAMAGEAREA)
loop
set n = FirstOfGroup(ENUM_GROUP)
exitwhen n == null
if (IsUnitAlly(n, dat.dOwner) == false) and (GetWidgetLife(n) > 0) then
call UnitDamageTarget(dat.dCaster, n, DAMAGEDONE, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(ENUM_GROUP, n)
call ReleaseGroup(ENUM_GROUP)
endloop
call DestroyEffect(AddSpecialEffectTarget(SPELLEFFECT2, dat.dUnit, "origin"))
set d = GetRandomReal(400, 500)
set dat.dAngle = GetRandomReal(0, 359)
set x = GetUnitX(dat.dUnit) + d * Cos(dat.dAngle * bj_DEGTORAD)
set y = GetUnitY(dat.dUnit) + d * Sin(dat.dAngle * bj_DEGTORAD)
set dat.dDistance = SquareRoot((x - GetUnitX(dat.dUnit)) * (x - GetUnitX(dat.dUnit)) + (y - GetUnitY(dat.dUnit)) * (y - GetUnitY(dat.dUnit)))
set dat.dCDistance = 0
set dat.dBool4 = true
endif
endif
//-------------------------------------------------------------------------------------------
//------------------This is the third phase of the spell-------------------------------------
//-------------------------------------------------------------------------------------------
if (dat.dDistance > dat.dCDistance) and (dat.dBool4 == true) then
set dat.dCDistance = dat.dCDistance + RELAPSDISTANCE
set x = dat.x + RELAPSDISTANCE * Cos(dat.dAngle * bj_DEGTORAD)
set y = dat.y + RELAPSDISTANCE * Sin(dat.dAngle * bj_DEGTORAD)
call SetUnitX(dat.dUnit, x)
call SetUnitY(dat.dUnit, y)
call SetUnitFacing(dat.dUnit, dat.dAngle)
call SetUnitFlyHeight(dat.dUnit, ParabolaZ( RELAPSHIGHT, dat.dDistance, dat.dCDistance), 0)
else
if dat.dBool4 == true then
call ReleaseTimer(t)
call DestroyEffect(AddSpecialEffectTarget(SPELLEFFECT2, dat.dUnit, "origin"))
call dat.destroy()
endif
endif
//This is used as an escape method if the unit is not inside the map bounds
set rX = GetUnitX(dat.dUnit)
set rY = GetUnitY(dat.dUnit)
if (GetRectMinX(r) <= rX) and (rX <= GetRectMaxX(r)) and (GetRectMinY(r) <= rY) and (rY <= GetRectMaxY(r)) == false then
call ReleaseTimer(t)
call dat.destroy()
endif
endmethod
private method destroy takes nothing returns nothing
local unit n = null
call DestroyEffect(.dEffect1)
call KillUnit(.dUnit)
call GroupUnitsInArea(ENUM_GROUP, .x, .y, DAMAGEAREA)
loop
set n = FirstOfGroup(ENUM_GROUP)
exitwhen n == null
if (IsUnitAlly(n, .dOwner) == false) and (GetWidgetLife(n) > 0) then
call UnitDamageTarget(.dCaster, n, DAMAGEDONE, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
call GroupRemoveUnit(ENUM_GROUP, n)
endloop
call ReleaseGroup(ENUM_GROUP)
set n = null
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELLID
endfunction
private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x = GetSpellTargetX()
local real y = GetSpellTargetY()
local real a = bj_RADTODEG * Atan2(y - GetUnitY(u), x - GetUnitX(u))
local integer i = 0
set x = x + MAXDISTANCE * Cos((a - 180) * bj_DEGTORAD)
set y = y + MAXDISTANCE * Sin((a - 180) * bj_DEGTORAD)
loop
call Data.create(u, x, y, a, (MAXDISTANCE + ( i * UNITDISTANCE)))
set i = i + 1
set x = x + UNITDISTANCE * Cos((a - 180) * bj_DEGTORAD)
set y = y + UNITDISTANCE * Sin((a - 180) * bj_DEGTORAD)
exitwhen i == MAXCOUNT
endloop
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( tr, Condition( function Conditions ) )
call TriggerAddAction( tr, function Actions )
endfunction
endscope
scope AerialReaver initializer InitTrig_Initialize
///////////////////////////////////////////////////////////////////////////////////////
//Welcome to the Header //
//u can customize most part of the spell from here //
///////////////////////////////////////////////////////////////////////////////////////
globals
//Insert the raw-code of your Aerial Reaver ability. U can see the raw-code of the spell by pressing Ctrl+D.
private constant integer SpellID = 'A000'
//Insert your dummy unit raw-code. Dummy unit must be able to be attached by an effect.
private constant integer DummyID = 'h000'
//this one for the attachment point of the dummy. most of it use either "chest" or "origin".
private constant string DummyAttach = "chest"
//insert where u want the effect attached to your unit that cast this spell.
private constant string CasterAttach = "chest"
//insert where u want the effect attached to enemy unit that get affected by this spell.
private constant string TargetAttach = "chest"
//to produce a value in this spell that get increased/decreased on different level,
//i use the default and modifier value. for lvl 1 spell, the default value will be applied.
//on each increased lvl, the modifier value will be added to default value, thus effectively
//increase/decrease that value.
//ex: First Explosion's damage default value is 150 dmg and it's modifier value is 50 dmg.
// so, on lvl 1, the damage will be 100. on lvl 2 it's (100+50)=150 dmg,
//on lvl 3 it's (150+50)=200 dmg, and so on
//insert the spell's area of effect here. this will be the default value.
private constant real AoE = 300.
//insert modifier of spell's area of effect here.
private constant real AoEIncr = 50.
//Fitst Explosion Set-up
//insert the damage dealt by the first explosion here. this will be the default value.
private constant real FEDamage = 50.
//insert modifier of first explosion damage here.
private constant real FEDamageIncr = 25.
//insert the animation u want the caster to play when first explosion occur here
private constant string FECasterAnim = "slam"
//insert the max height of the caster's jump here
private constant real FECasterJumpHeight = 200.
//insert how long the first explosion will last. this will be the default value
private constant real FETime = 2.5
//insert modifier of first explosion time here.
private constant real FETimeIncr = 0.5
//insert the max height the tossed unit will reach here
private constant real FETossHeight = 400.
private constant real FETossHeightRatio = 0.5
//First Eplosion Effect
//insert how many line of explosion will be created. this will be the default value
private constant integer FEELineSum = 3
//insert the modifier of line sum here.
private constant integer FEELineSumIncr = 1
//insert how many 'pillar' will be created on each line here. this will be the default value
private constant integer FEECircleSum = 2
//insert the modifier of 'pillar' sum per line here
private constant integer FEECircleSumIncr = 1
//insert how may effect will created for each 'pillar' here
private constant integer FEESum = 10
//insert the height of the pillar here
private constant real FEEHeight = 400.
//insert the interval of each new circle of pillar will be created here
private constant real FEEInterval = 0.5
//insert the time needed for each 'pillar' to fully appear here
private constant real FEEAppearTime = 0.5
//insert the time each pillar will stand still, doing nothing here
private constant real FEEStandTime = 0.5
//insert the time needed for each pillar to fully disappear here
private constant real FEEDisappearTime = 0.5
//Second Explosion Set-up
//insert the damage dealt by the second explosion here. this will be the default value.
private constant real SEDamage = 100.
//insert modifier of second explosion damage here.
private constant real SEDamageIncr = 25.
//insert the animation u want the caster to play when first explosion occur here
private constant string SECasterAnim = "attack"
//insert the max height of the caster's jump here
private constant real SECasterJumpHeight = 200.
//insert the rotation speed of the caster here
private constant real SECasterAngSpeed = 3600.
//insert how long the second explosion will last.
private constant real SETime = 3.
//insert the max height the tossed unit will reach here
private constant real SETossHeight = 400.
//Second Explosion Effect
//insert how many rotating effect that will be created here
private constant integer SEESum = 10
//insert the height of the rotating effect here
private constant real SEEHeight = 200.
//insert the rotating effect distance to caster here
private constant real SEEDistance = 200.
//insert the rotating effect rotating speed here
private constant real SEEAngSpeed = 360.
//insert the interval between the appearance of each rotating effect here
private constant real SEEAppearInterval = 0.1
//insert the interval between the disappearance of each rotating effect here
private constant real SEEDisappearInterval = 0.1
//Effect Set-up
//insert the 'pillar' from first explosion effect model here
private constant string FEEModel = "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
//set the red tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelRed = 255
//set the green tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelGreen = 75
//set the blue tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelBlue = 200
//insert the effect that will be created on caster when the first explosion occur.
//this one destroyed instantly
private constant string FECasterEffect = ""
//insert the effect that will be attached on caster when the first explosion occur.
//this one stay until first explosion end
private constant string FECasterAttachEffect = "Abilities\\Spells\\Items\\HealingSalve\\HealingSalveTarget.mdl"
//insert the effect that will be created on unit when it tossed by the first explosion.
//this one destroyed instantly
private constant string FETargetEffect = ""
//insert the effect that will be attached on unit when it tossed by the first explosion.
//this one stay until the toss end
private constant string FETargetAttachEffect = ""
//insert the rotating effect model here
private constant string SEEModel = "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl"
//set the red tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelRed = 0
//set the green tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelGreen = 0
//set the blue tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelBlue = 0
//set the rotating effect scale
private constant real SEEModelScale = 2.
//insert the effect that will be created on caster when the second explosion occur.
//this one destroyed instantly
private constant string SECasterEffect = "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
//insert the effect that will be attached on caster when the second explosion occur.
//this one stay until second explosion end
private constant string SECasterAttachEffect = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
//insert the effect that will be created on unit when it tossed by the second explosion.
//this one destroyed instantly
private constant string SETargetEffect = ""
//insert the effect that will be attached on unit when it tossed by the second explosion.
//this one stay until the toss end
private constant string SETargetAttachEffect = ""
//set the timer's time out. the lower it is, the more precise the spell will get.
//but, warcraft has it's limit for time out though. don't use value lower than 0.03
//because it will lower the warcraft performance.
//this one usually between 0.05 to 0.03. 0.03 is more common(and efficient too!)
private constant real TimeOut = 0.03
//this one will decide the first explosion attack type
private constant attacktype FEATT = ATTACK_TYPE_NORMAL
//this one will decide the first explosion damage type
private constant damagetype FEDGT = DAMAGE_TYPE_NORMAL
//this one will decide the first explosion weapon type
private constant weapontype FEWPT = WEAPON_TYPE_WHOKNOWS
//this one will decide the second explosion attack type
private constant attacktype SEATT = ATTACK_TYPE_NORMAL
//this one will decide the second explosion damage type
private constant damagetype SEDGT = DAMAGE_TYPE_NORMAL
//this one will decide the second explosion weapon type
private constant weapontype SEWPT = WEAPON_TYPE_WHOKNOWS
//////////////////////////////////////////////////////////////////////
private boolexpr filter
private unit temp
//this line is variable for the spell's mechanism. don't change it.
//it's for the sake of efficiency of the spell..
private unit u2
private group g = CreateGroup()
private real array R
//////////////////////////////////////////////////////////////////////
endglobals
//u can edit the condition the unit neded to be affected by the spell here
private function CanTarget takes unit caster, unit target returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster))/*
*/and not (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))/*
*/and not (IsUnitType(target, UNIT_TYPE_DEAD))/*
*/and IsUnitType(target, UNIT_TYPE_GROUND)/*
*/and IsUnitVisible(target, GetOwningPlayer(caster))
endfunction
///////////////////////////////////////////////////////////////////////////////////////
//This is the end of the header //
//don't edit anything below if u don't know it. //
///////////////////////////////////////////////////////////////////////////////////////
//tossed struct.
private struct Tossed
private unit u
private real vx
private real angle
private real vy
private real acc
private effect sfx
static group Affected = CreateGroup()
private static Tossed array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method Change takes unit u1, real x, real y, real a, real ang, string sfxs, string sfxs2 returns nothing
//change the velocity and the deccelerate of the unit. only called if the unit is tossed when it's already being tossed
local Tossed dat
local integer i = 0
loop
exitwhen i >= Tossed.Total
set dat = Tossed.Index[i]
if dat.u == u1 then
set dat.u = u1
set dat.vx = x
set dat.vy = y
set dat.acc = a
set dat.angle = ang
call DestroyEffect(dat.sfx)
set dat.sfx = AddSpecialEffectTarget(sfxs,u1,TargetAttach)
call DestroyEffect(AddSpecialEffectTarget(sfxs2,u1,TargetAttach))
endif
set i = i + 1
endloop
endmethod
static method Loop takes nothing returns nothing
//the loop. long story short, this one just move the unit according to it's velocity.
//also reduce the velocity by the decceleration.
local Tossed dat
local integer i = 0
loop
exitwhen i >= Tossed.Total
set dat = Tossed.Index[i]
set dat.vy = dat.vy - (dat.acc*TimeOut)
set R[1] = GetUnitX(dat.u) + dat.vx*TimeOut*Cos(dat.angle*bj_DEGTORAD)
set R[2] = GetUnitY(dat.u) + dat.vx*TimeOut*Sin(dat.angle*bj_DEGTORAD)
set R[3] = GetUnitFlyHeight(dat.u) + (dat.vy*TimeOut)
call SetUnitX(dat.u,R[1])
call SetUnitY(dat.u,R[2])
call SetUnitFlyHeight(dat.u,R[3],0.)
if R[3] <= 0 then
call PauseUnit(dat.u,false)
call DestroyEffect(dat.sfx)
call SetUnitFlyHeight(dat.u,GetUnitDefaultFlyHeight(dat.u),0.)
call GroupRemoveUnit(Tossed.Affected,dat.u)
set dat.u = null
set dat.sfx = null
call dat.destroy()
set Tossed.Total = Tossed.Total - 1
set Tossed.Index[i] = Tossed.Index[Tossed.Total]
set i = i - 1
endif
set i = i + 1
endloop
if Tossed.Total == 0 then
call PauseTimer(Tossed.Timer)
endif
endmethod
static method Create takes unit u1, real x, real y, real a, real ang, string sfxs, string sfxs2 returns nothing
//index the unit and save the velocity and decceleration
local Tossed dat = Tossed.allocate()
set dat.u = u1
call UnitAddAbility(u1,'Arav')
call UnitRemoveAbility(u1,'Arav')
set dat.vx = x
set dat.vy = y
set dat.acc = a
set dat.angle = ang
set dat.sfx = AddSpecialEffectTarget(sfxs,u1,TargetAttach)
call PauseUnit(dat.u,true)
call DestroyEffect(AddSpecialEffectTarget(sfxs2,u1,TargetAttach))
call GroupAddUnit(Tossed.Affected,u1)
if Tossed.Total == 0 then
call TimerStart(Tossed.Timer,TimeOut,true,function Tossed.Loop)
endif
set Tossed.Index[Tossed.Total] = dat
set Tossed.Total = Tossed.Total + 1
endmethod
endstruct
//the 'pillar' struct
private struct FEEffect
private group sfxg
private real Time
private integer ActId
private static FEEffect array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method Loop takes nothing returns nothing
//basically doing 1 of 3 stuff.
//1. moving the effect to it's place in 'pillar'
//2. stand still, doing nothing
//3. make pillar dsappear by scale the effect down, then kill it
local FEEffect dat
local integer i = 0
loop
exitwhen i >= FEEffect.Total
set dat = FEEffect.Index[i]
set dat.Time = dat.Time-TimeOut
if dat.ActId == 1 then
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[1] = (FEEHeight/FEESum)*GetUnitUserData(u2)
set R[2] = R[1]*((FEEAppearTime-dat.Time)/FEEAppearTime)
call SetUnitFlyHeight(u2,R[2],0)
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
set dat.Time = FEEStandTime
set dat.ActId = 2
endif
elseif dat.ActId == 2 then
if dat.Time <= 0 then
set dat.Time = FEEDisappearTime
set dat.ActId = 3
endif
elseif dat.ActId == 3 then
if dat.Time <= 0 then
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
set dat.sfxg = null
call dat.destroy()
set FEEffect.Total = FEEffect.Total - 1
set FEEffect.Index[i] = FEEffect.Index[FEEffect.Total]
set i = i -1
else
set R[1] = (dat.Time/FEEDisappearTime)
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
call SetUnitScale(u2,R[1],R[1],R[1])
call GroupRemoveUnit(g,u2)
endloop
endif
endif
set i = i + 1
endloop
if FEEffect.Total == 0 then
call PauseTimer(FEEffect.Timer)
endif
endmethod
static method Create takes real x, real y, player p returns nothing
//initiate and create the effect
local FEEffect dat = FEEffect.allocate()
local integer i = 0
local unit u
set dat.sfxg = CreateGroup()
set dat.Time = FEEAppearTime
set dat.ActId = 1
loop
exitwhen i > FEESum
set u = CreateUnit(p,DummyID,x,y,0.)
call AddSpecialEffectTarget(FEEModel,u,DummyAttach)
call GroupAddUnit(dat.sfxg,u)
call SetUnitUserData(u,i)
call SetUnitVertexColor(u,FEEModelRed,FEEModelGreen,FEEModelBlue,255)
set i = i + 1
endloop
if FEEffect.Total == 0 then
call TimerStart(FEEffect.Timer,TimeOut,true,function FEEffect.Loop)
endif
set FEEffect.Index[FEEffect.Total] = dat
set FEEffect.Total = FEEffect.Total + 1
endmethod
endstruct
//the main struct
private struct Main
private unit Caster
private real x
private real y
private real angle
private integer ActId
private real Area
private real Time
private real Time2
private real v
private real acc
private integer num
private integer num2
private integer level
private group sfxg
private effect sfx
private group affected
private static Main array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method CanTargeted takes nothing returns boolean
//for filter purpose
return CanTarget(temp,GetFilterUnit())
endmethod
static method Loop takes nothing returns nothing
//this basically doing 2 stuff.
//1. doing the first explosion. explained below
//2. doing the second explosion. explained below
//also check if the caster dies. if yes, end the spell immediately
local Main dat
local integer i = 0
local integer l
loop
exitwhen i >= Main.Total
set dat = Main.Index[i]
set dat.Time = dat.Time-TimeOut
set dat.Time2 = dat.Time2-TimeOut
call SetUnitFlyHeight(dat.Caster,GetUnitFlyHeight(dat.Caster)+(dat.v*TimeOut),0.)
set dat.v = dat.v-(dat.acc*TimeOut)
if IsUnitType(dat.Caster,UNIT_TYPE_DEAD) then
call PauseUnit(dat.Caster,false)
call SetUnitFlyHeight(dat.Caster,GetUnitDefaultFlyHeight(dat.Caster),0)
call DestroyEffect(dat.sfx)
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
call DestroyGroup(dat.affected)
set dat.Caster = null
set dat.sfx = null
set dat.sfxg = null
set dat.affected = null
call dat.destroy()
set Main.Total = Main.Total - 1
set Main.Index[i] = Main.Index[Main.Total]
set i = i - 1
elseif dat.ActId == 1 then
//first explosion.
//basically just create each 'pillar' circle by circle on each interval.
//it also toss unit and add it to group so it didn't tossed again
if (dat.Time2 <= 0) and (dat.num<=dat.num2) then
set dat.Time2 = FEEInterval
set l = FEELineSum+(FEELineSumIncr*dat.level)
set R[1] = 360/I2R(l)
set R[2] = (dat.Area/I2R(dat.num2))*I2R(dat.num)
loop
exitwhen l <= 0
set R[3] = dat.angle+(R[1]*I2R(l))
if R[3] > 360 then
set R[3] = R[3] - 360
endif
call FEEffect.Create(dat.x+(R[2]*Cos(R[3]*bj_DEGTORAD)),dat.y+(R[2]*Sin(R[3]*bj_DEGTORAD)),GetOwningPlayer(dat.Caster))
set l = l - 1
endloop
set dat.num = dat.num+1
endif
call GroupAddGroup(dat.affected,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not (CanTarget(dat.Caster,u2)) then
call GroupRemoveUnit(dat.affected,u2)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not IsUnitInGroup(u2,dat.affected) then
set R[4] = (2*FETossHeight*dat.Time)/(FETossHeight+SquareRoot(FETossHeight*FETossHeight*(1-FETossHeightRatio)))
set R[1] = (4*FETossHeight)/(R[4])
set R[3] = (8*FETossHeight)/(R[4]*R[4])
call GroupAddUnit(dat.affected,u2)
set R[0] = FEDamage+(FEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,FEATT,FEDGT,FEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
else
call Tossed.Create(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
endif
endif
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
//change of phase.
//re-initiate the variable, effect, and the group
set dat.angle = GetRandomReal(0.,360.)
set dat.ActId = 2
set dat.Time = SETime
set dat.Time2 = SEEAppearInterval
set dat.v = (4*SECasterJumpHeight)/dat.Time
set dat.acc = (8*SECasterJumpHeight)/(dat.Time*dat.Time)
set dat.num = 1
set dat.num2 = SEESum
call DestroyEffect(dat.sfx)
set dat.sfx = AddSpecialEffectTarget(SECasterAttachEffect,dat.Caster,CasterAttach)
call DestroyEffect(AddSpecialEffectTarget(SECasterEffect,dat.Caster,CasterAttach))
call SetUnitAnimation(dat.Caster,SECasterAnim)
call GroupClear(dat.affected)
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[5] = (2*SETossHeight*dat.Time)/(SETossHeight+SquareRoot(SETossHeight*(SETossHeight-GetUnitFlyHeight(u2))))
set R[1] = (4*SETossHeight)/(R[5])
set R[6] = GetUnitX(u2)-dat.x
set R[7] = GetUnitY(u2)-dat.y
set R[2] = (dat.Area-SquareRoot(R[6]*R[6]+R[7]*R[7]))/dat.Time
set R[3] = (8*FETossHeight)/(R[5]*R[5])
set R[4] = bj_RADTODEG*Atan2(GetUnitY(u2)-dat.y,GetUnitX(u2)-dat.x)
call GroupAddUnit(dat.affected,u2)
set R[0] = SEDamage+(SEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,SEATT,SEDGT,SEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
else
call Tossed.Create(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = null
call DestroyBoolExpr(filter)
endif
elseif dat.ActId == 2 then
//the second explosion
//basically just create each rotating effect one by one, then rotating it individually
//also rotate the caster
set dat.angle = dat.angle+(SEEAngSpeed*TimeOut)
call SetUnitFacing(dat.Caster,GetUnitFacing(dat.Caster)+(SECasterAngSpeed*TimeOut))
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[1] = GetUnitFacing(u2)+(SEEAngSpeed*TimeOut)
call SetUnitX(u2,dat.x+(SEEDistance*Cos(R[1]*bj_DEGTORAD)))
call SetUnitY(u2,dat.y+(SEEDistance*Sin(R[1]*bj_DEGTORAD)))
call SetUnitFacing(u2,R[1])
call GroupRemoveUnit(g,u2)
endloop
if (dat.Time2 <= 0) and (dat.num<=dat.num2) then
set dat.Time2 = SEEAppearInterval
set u2 = CreateUnit(GetOwningPlayer(dat.Caster),DummyID,dat.x+(SEEDistance*Cos(dat.angle*bj_DEGTORAD)),dat.y+(SEEDistance*Sin(dat.angle*bj_DEGTORAD)),dat.angle)
call AddSpecialEffectTarget(SEEModel,u2,DummyAttach)
call SetUnitScale(u2,SEEModelScale,SEEModelScale,SEEModelScale)
call SetUnitFlyHeight(u2,(SEEHeight/I2R(dat.num2))*dat.num,0.)
call SetUnitFacing(u2,dat.angle)
call SetUnitVertexColor(u2,SEEModelRed,SEEModelGreen,SEEModelBlue,255)
set R[1] = ((dat.Time+(dat.Time2*dat.num))/2)+(SEEDisappearInterval*(dat.num-1))
call UnitApplyTimedLife(u2,'BTLF',R[1])
call GroupAddUnit(dat.sfxg,u2)
set dat.angle = dat.angle - (360/I2R(dat.num2))
set dat.num = dat.num+1
endif
call GroupAddGroup(dat.affected,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not (CanTarget(dat.Caster,u2)) then
call GroupRemoveUnit(dat.affected,u2)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not IsUnitInGroup(u2,dat.affected) then
set R[5] = (2*SETossHeight*dat.Time)/(SETossHeight+SquareRoot(SETossHeight*(SETossHeight-GetUnitFlyHeight(u2))))
set R[1] = (4*SETossHeight)/(R[5])
set R[6] = GetUnitX(u2)-dat.x
set R[7] = GetUnitY(u2)-dat.y
set R[2] = (dat.Area-SquareRoot(R[6]*R[6]+R[7]*R[7]))/dat.Time
set R[3] = (8*FETossHeight)/(R[5]*R[5])
set R[4] = bj_RADTODEG*Atan2(GetUnitY(u2)-dat.y,GetUnitX(u2)-dat.x)
call GroupAddUnit(dat.affected,u2)
set R[0] = SEDamage+(SEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,SEATT,SEDGT,SEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
else
call Tossed.Create(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
endif
endif
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
//finish the spell. clearing te index
call PauseUnit(dat.Caster,false)
call SetUnitFlyHeight(dat.Caster,GetUnitDefaultFlyHeight(dat.Caster),0)
call DestroyEffect(dat.sfx)
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
call DestroyGroup(dat.affected)
set dat.Caster = null
set dat.sfx = null
set dat.sfxg = null
set dat.affected = null
call dat.destroy()
set Main.Total = Main.Total - 1
set Main.Index[i] = Main.Index[Main.Total]
set i = i - 1
endif
endif
set i = i +1
endloop
if Main.Total == 0 then
call PauseTimer(Main.Timer)
endif
endmethod
static method Create takes nothing returns nothing
//the creating of the spell.
//create one pillar in the place of caster.
//initiate all variable, create the efect, etc.
local Main dat = Main.allocate()
local unit u = GetTriggerUnit()
call PauseUnit(u,true)
set dat.Caster = u
call PauseUnit(dat.Caster,true)
call UnitAddAbility(u,'Arav')
call UnitRemoveAbility(u,'Arav')
set dat.x = GetUnitX(u)
set dat.y = GetUnitY(u)
set dat.angle = GetRandomReal(0.,360.)
call FEEffect.Create(dat.x,dat.y,GetOwningPlayer(u))
set dat.ActId = 1
set dat.level = GetUnitAbilityLevel(u,SpellID) - 1
set dat.Area = AoE+(AoEIncr*I2R(dat.level))
set dat.Time = FETime+(FETimeIncr*I2R(dat.level))
set dat.Time2 = FEEInterval
set dat.v = (4*FECasterJumpHeight)/dat.Time
set dat.acc = (8*FECasterJumpHeight)/(dat.Time*dat.Time)
set dat.num = 1
set dat.num2 = FEECircleSum+(FEECircleSumIncr*dat.level)
set dat.sfxg = CreateGroup()
set dat.sfx = AddSpecialEffectTarget(FECasterAttachEffect,u,CasterAttach)
call DestroyEffect(AddSpecialEffectTarget(FECasterEffect,u,CasterAttach))
call SetUnitAnimation(u,FECasterAnim)
set dat.affected = CreateGroup()
set temp = u
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[4] = (2*FETossHeight*dat.Time)/(FETossHeight+SquareRoot(FETossHeight*FETossHeight*(1-FETossHeightRatio)))
set R[1] = (4*FETossHeight)/(R[4])
set R[3] = (8*FETossHeight)/(R[4]*R[4])
call GroupAddUnit(dat.affected,u2)
set R[0] = FEDamage+(FEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,FEATT,FEDGT,FEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
else
call Tossed.Create(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = null
call DestroyBoolExpr(filter)
if Main.Total == 0 then
call TimerStart(Main.Timer,TimeOut,true,function Main.Loop)
endif
set Main.Index[Main.Total] = dat
set Main.Total = Main.Total+1
set u = null
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == SpellID then
call Main.Create()
endif
return false
endfunction
private function InitTrig_Initialize takes nothing returns nothing
//create the trigger
local trigger t = CreateTrigger()
//add event
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
//add 'condition'
call TriggerAddCondition(t, Condition(function Conditions))
//preload dummy unit
call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DummyID,0,0,0))
//preload the spell's effect
call Preload(FEEModel)
call Preload(FECasterEffect)
call Preload(FECasterAttachEffect)
call Preload(FETargetEffect)
call Preload(FETargetAttachEffect)
call Preload(SEEModel)
call Preload(SECasterEffect)
call Preload(SECasterAttachEffect)
call Preload(SETargetEffect)
call Preload(SETargetAttachEffect)
endfunction
endscope
yeah, i know. The caster animation is ugly, there's some additional effect i want to add, etc. but darn real life. when i submit this, it's already 1 am here, so i can't use the remaining 7 hour to polish it a bit.You still have some time to work on it. But I guess you're busy.
scope AerialReaver initializer InitTrig_Initialize
///////////////////////////////////////////////////////////////////////////////////////
//Welcome to the Header //
//u can customize most part of the spell from here //
///////////////////////////////////////////////////////////////////////////////////////
globals
//Insert the raw-code of your Aerial Reaver ability. U can see the raw-code of the spell by pressing Ctrl+D.
private constant integer SpellID = 'A000'
//Insert your dummy unit raw-code. Dummy unit must be able to be attached by an effect.
private constant integer DummyID = 'h000'
//this one for the attachment point of the dummy. most of it use either "chest" or "origin".
private constant string DummyAttach = "chest"
//insert where u want the effect attached to your unit that cast this spell.
private constant string CasterAttach = "chest"
//insert where u want the effect attached to enemy unit that get affected by this spell.
private constant string TargetAttach = "chest"
//to produce a value in this spell that get increased/decreased on different level,
//i use the default and modifier value. for lvl 1 spell, the default value will be applied.
//on each increased lvl, the modifier value will be added to default value, thus effectively
//increase/decrease that value.
//ex: First Explosion's damage default value is 150 dmg and it's modifier value is 50 dmg.
// so, on lvl 1, the damage will be 100. on lvl 2 it's (100+50)=150 dmg,
//on lvl 3 it's (150+50)=200 dmg, and so on
//insert the spell's area of effect here. this will be the default value.
private constant real AoE = 300.
//insert modifier of spell's area of effect here.
private constant real AoEIncr = 50.
//Fitst Explosion Set-up
//insert the damage dealt by the first explosion here. this will be the default value.
private constant real FEDamage = 50.
//insert modifier of first explosion damage here.
private constant real FEDamageIncr = 25.
//insert the animation u want the caster to play when first explosion occur here
private constant string FECasterAnim = "slam"
//insert the animation's time here
private constant real FECasterAnimTime = 5.
//insert the max height of the caster's jump here
private constant real FECasterJumpHeight = 200.
//insert how long the first explosion will last. this will be the default value
private constant real FETime = 2.5
//insert modifier of first explosion time here.
private constant real FETimeIncr = 0.5
//insert the max height the tossed unit will reach here
private constant real FETossHeight = 400.
private constant real FETossHeightRatio = 0.5
//First Eplosion Effect
//insert how many line of explosion will be created. this will be the default value
private constant integer FEELineSum = 3
//insert the modifier of line sum here.
private constant integer FEELineSumIncr = 1
//insert how many 'pillar' will be created on each line here. this will be the default value
private constant integer FEECircleSum = 2
//insert the modifier of 'pillar' sum per line here
private constant integer FEECircleSumIncr = 1
//insert how may effect will created for each 'pillar' here
private constant integer FEESum = 5
//insert the height of the pillar here
private constant real FEEHeight = 400.
//insert the interval of each new circle of pillar will be created here
private constant real FEEInterval = 0.5
//insert the time needed for each 'pillar' to fully appear here
private constant real FEEAppearTime = 0.5
//insert the time each pillar will stand still, doing nothing here
private constant real FEEStandTime = 0.5
//insert the time needed for each pillar to fully disappear here
private constant real FEEDisappearTime = 0.5
//Second Explosion Set-up
//insert the damage dealt by the second explosion here. this will be the default value.
private constant real SEDamage = 100.
//insert modifier of second explosion damage here.
private constant real SEDamageIncr = 25.
//insert the animation u want the caster to play when first explosion occur here
private constant string SECasterAnim = "attack"
//insert the animation's time here
private constant real SECasterAnimTime = 0.5
//insert the max height of the caster's jump here
private constant real SECasterJumpHeight = 400.
//insert the rotation speed of the caster here
private constant real SECasterAngSpeed = 3600.
//insert how long the second explosion will last.
private constant real SETime = 3.
//insert the max height the tossed unit will reach here
private constant real SETossHeight = 400.
//Second Explosion Effect
//insert how many rotating effect that will be created here
private constant integer SEESum = 10
//insert the height of the rotating effect here
private constant real SEEHeight = 200.
//insert the rotating effect distance to caster here
private constant real SEEDistance = 200.
//insert the rotating effect rotating speed here
private constant real SEEAngSpeed = 360.
//insert the interval between the appearance of each rotating effect here
private constant real SEEAppearInterval = 0.1
//insert the interval between the disappearance of each rotating effect here
private constant real SEEDisappearInterval = 0.03
//Sound Setup
//sound that played on caster when second explosion occur
private constant string SECasterSound = "Abilities\\Weapons\\PhoenixMissile\\PhoenixAttack.wav"
//the volume percentage of caster's second explosion sound
private constant real SECasterSoundVolume = 200.
//the interval between the play of each sound
private constant real SECasterSoundInterval = 0.2
//Effect Set-up
//insert the 'pillar' from first explosion effect model here
private constant string FEEModel = "Abilities\\Spells\\Undead\\Darksummoning\\DarkSummonTarget.mdl"
//set the red tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelRed = 255
//set the green tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelGreen = 75
//set the blue tinting color of 'pillar' here. It's between 0 to 255.
private constant integer FEEModelBlue = 200
//insert the effect that will be created on caster when the first explosion occur.
//this one destroyed instantly
private constant string FECasterEffect = ""
//insert the effect that will be attached on caster when the first explosion occur.
//this one stay until first explosion end
private constant string FECasterAttachEffect = ""
//insert the effect that will be created on unit when it tossed by the first explosion.
//this one destroyed instantly
private constant string FETargetEffect = ""
//insert the effect that will be attached on unit when it tossed by the first explosion.
//this one stay until the toss end
private constant string FETargetAttachEffect = ""
//insert the rotating effect model here
private constant string SEEModel = "Abilities\\Weapons\\IllidanMissile\\IllidanMissile.mdl"
//set the red tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelRed = 0
//set the green tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelGreen = 255
//set the blue tinting color of rotating effect here. It's between 0 to 255.
private constant integer SEEModelBlue = 0
//set the rotating effect scale
private constant real SEEModelScale = 3.
//insert the effect that will be created on caster when the second explosion occur.
//this one destroyed instantly
private constant string SECasterEffect = "Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl"
//insert the effect that will be attached on caster when the second explosion occur.
//this one stay until second explosion end
private constant string SECasterAttachEffect = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
//insert the effect that will be created on unit when it tossed by the second explosion.
//this one destroyed instantly
private constant string SETargetEffect = ""
//insert the effect that will be attached on unit when it tossed by the second explosion.
//this one stay until the toss end
private constant string SETargetAttachEffect = ""
//set the timer's time out. the lower it is, the more precise the spell will get.
//but, warcraft has it's limit for time out though. don't use value lower than 0.03
//because it will lower the warcraft performance.
//this one usually between 0.05 to 0.03. 0.03 is more common(and efficient too!)
private constant real TimeOut = 0.03
//this one will decide the first explosion attack type
private constant attacktype FEATT = ATTACK_TYPE_NORMAL
//this one will decide the first explosion damage type
private constant damagetype FEDGT = DAMAGE_TYPE_NORMAL
//this one will decide the first explosion weapon type
private constant weapontype FEWPT = WEAPON_TYPE_WHOKNOWS
//this one will decide the second explosion attack type
private constant attacktype SEATT = ATTACK_TYPE_NORMAL
//this one will decide the second explosion damage type
private constant damagetype SEDGT = DAMAGE_TYPE_NORMAL
//this one will decide the second explosion weapon type
private constant weapontype SEWPT = WEAPON_TYPE_WHOKNOWS
//////////////////////////////////////////////////////////////////////
private boolexpr filter
private unit temp
//this line is variable for the spell's mechanism. don't change it.
//it's for the sake of efficiency of the spell..
private unit u2
private group g = CreateGroup()
private real array R
//////////////////////////////////////////////////////////////////////
endglobals
//u can edit the condition the unit neded to be affected by the spell here
private function CanTarget takes unit caster, unit target returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster))/*
*/and not (IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE))/*
*/and not (IsUnitType(target, UNIT_TYPE_DEAD))/*
*/and IsUnitType(target, UNIT_TYPE_GROUND)/*
*/and IsUnitVisible(target, GetOwningPlayer(caster))
endfunction
///////////////////////////////////////////////////////////////////////////////////////
//This is the end of the header //
//don't edit anything below if u don't know it. //
///////////////////////////////////////////////////////////////////////////////////////
//tossed struct.
private struct Tossed
private unit u
private real vx
private real angle
private real vy
private real acc
private effect sfx
static group Affected = CreateGroup()
private static Tossed array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method Change takes unit u1, real x, real y, real a, real ang, string sfxs, string sfxs2 returns nothing
//change the velocity and the deccelerate of the unit. only called if the unit is tossed when it's already being tossed
local Tossed dat
local integer i = 0
loop
exitwhen i >= Tossed.Total
set dat = Tossed.Index[i]
if dat.u == u1 then
set dat.u = u1
set dat.vx = x
set dat.vy = y
set dat.acc = a
set dat.angle = ang
call DestroyEffect(dat.sfx)
set dat.sfx = AddSpecialEffectTarget(sfxs,u1,TargetAttach)
call DestroyEffect(AddSpecialEffectTarget(sfxs2,u1,TargetAttach))
endif
set i = i + 1
endloop
endmethod
static method Loop takes nothing returns nothing
//the loop. long story short, this one just move the unit according to it's velocity.
//also reduce the velocity by the decceleration.
local Tossed dat
local integer i = 0
loop
exitwhen i >= Tossed.Total
set dat = Tossed.Index[i]
set dat.vy = dat.vy - (dat.acc*TimeOut)
set R[1] = GetUnitX(dat.u) + dat.vx*TimeOut*Cos(dat.angle*bj_DEGTORAD)
set R[2] = GetUnitY(dat.u) + dat.vx*TimeOut*Sin(dat.angle*bj_DEGTORAD)
set R[3] = GetUnitFlyHeight(dat.u) + (dat.vy*TimeOut)
call SetUnitX(dat.u,R[1])
call SetUnitY(dat.u,R[2])
call SetUnitFlyHeight(dat.u,R[3],0.)
if R[3] <= 0 then
call PauseUnit(dat.u,false)
call DestroyEffect(dat.sfx)
call SetUnitFlyHeight(dat.u,GetUnitDefaultFlyHeight(dat.u),0.)
call GroupRemoveUnit(Tossed.Affected,dat.u)
set dat.u = null
set dat.sfx = null
call dat.destroy()
set Tossed.Total = Tossed.Total - 1
set Tossed.Index[i] = Tossed.Index[Tossed.Total]
set i = i - 1
endif
set i = i + 1
endloop
if Tossed.Total == 0 then
call PauseTimer(Tossed.Timer)
endif
endmethod
static method Create takes unit u1, real x, real y, real a, real ang, string sfxs, string sfxs2 returns nothing
//index the unit and save the velocity and decceleration
local Tossed dat = Tossed.allocate()
set dat.u = u1
call UnitAddAbility(u1,'Arav')
call UnitRemoveAbility(u1,'Arav')
set dat.vx = x
set dat.vy = y
set dat.acc = a
set dat.angle = ang
set dat.sfx = AddSpecialEffectTarget(sfxs,u1,TargetAttach)
call PauseUnit(dat.u,true)
call DestroyEffect(AddSpecialEffectTarget(sfxs2,u1,TargetAttach))
call GroupAddUnit(Tossed.Affected,u1)
if Tossed.Total == 0 then
call TimerStart(Tossed.Timer,TimeOut,true,function Tossed.Loop)
endif
set Tossed.Index[Tossed.Total] = dat
set Tossed.Total = Tossed.Total + 1
endmethod
endstruct
//the 'pillar' struct
private struct FEEffect
private group sfxg
private real Time
private integer ActId
private static FEEffect array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method Loop takes nothing returns nothing
//basically doing 1 of 3 stuff.
//1. moving the effect to it's place in 'pillar'
//2. stand still, doing nothing
//3. make pillar dsappear by scale the effect down, then kill it
local FEEffect dat
local integer i = 0
loop
exitwhen i >= FEEffect.Total
set dat = FEEffect.Index[i]
set dat.Time = dat.Time-TimeOut
if dat.ActId == 1 then
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[1] = (FEEHeight/FEESum)*GetUnitUserData(u2)
set R[2] = R[1]*((FEEAppearTime-dat.Time)/FEEAppearTime)
call SetUnitFlyHeight(u2,R[2],0)
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
set dat.Time = FEEStandTime
set dat.ActId = 2
endif
elseif dat.ActId == 2 then
if dat.Time <= 0 then
set dat.Time = FEEDisappearTime
set dat.ActId = 3
endif
elseif dat.ActId == 3 then
if dat.Time <= 0 then
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
set dat.sfxg = null
call dat.destroy()
set FEEffect.Total = FEEffect.Total - 1
set FEEffect.Index[i] = FEEffect.Index[FEEffect.Total]
set i = i -1
else
set R[1] = (dat.Time/FEEDisappearTime)
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
call SetUnitScale(u2,R[1],R[1],R[1])
call GroupRemoveUnit(g,u2)
endloop
endif
endif
set i = i + 1
endloop
if FEEffect.Total == 0 then
call PauseTimer(FEEffect.Timer)
endif
endmethod
static method Create takes real x, real y, player p returns nothing
//initiate and create the effect
local FEEffect dat = FEEffect.allocate()
local integer i = 0
local unit u
set dat.sfxg = CreateGroup()
set dat.Time = FEEAppearTime
set dat.ActId = 1
loop
exitwhen i > FEESum
set u = CreateUnit(p,DummyID,x,y,0.)
call AddSpecialEffectTarget(FEEModel,u,DummyAttach)
call GroupAddUnit(dat.sfxg,u)
call SetUnitUserData(u,i)
call SetUnitVertexColor(u,FEEModelRed,FEEModelGreen,FEEModelBlue,255)
set i = i + 1
endloop
if FEEffect.Total == 0 then
call TimerStart(FEEffect.Timer,TimeOut,true,function FEEffect.Loop)
endif
set FEEffect.Index[FEEffect.Total] = dat
set FEEffect.Total = FEEffect.Total + 1
endmethod
endstruct
//the main struct
private struct Main
private unit Caster
private real x
private real y
private real angle
private integer ActId
private real Area
private real Time
private real Time2
private real Time3
private real Time4
private real v
private real acc
private integer num
private integer num2
private integer level
private group sfxg
private effect sfx
private group affected
private static Main array Index
private static integer Total = 0
private static timer Timer = CreateTimer()
static method CanTargeted takes nothing returns boolean
//for filter purpose
return CanTarget(temp,GetFilterUnit())
endmethod
static method Loop takes nothing returns nothing
//this basically doing 2 stuff.
//1. doing the first explosion. explained below
//2. doing the second explosion. explained below
//also check if the caster dies. if yes, end the spell immediately
local Main dat
local integer i = 0
local integer l
local sound snd
loop
exitwhen i >= Main.Total
set dat = Main.Index[i]
set dat.Time = dat.Time-TimeOut
set dat.Time2 = dat.Time2-TimeOut
set dat.Time3 = dat.Time3-TimeOut
call SetUnitFlyHeight(dat.Caster,GetUnitFlyHeight(dat.Caster)+(dat.v*TimeOut),0.)
set dat.v = dat.v-(dat.acc*TimeOut)
if IsUnitType(dat.Caster,UNIT_TYPE_DEAD) then
call PauseUnit(dat.Caster,false)
call SetUnitFlyHeight(dat.Caster,GetUnitDefaultFlyHeight(dat.Caster),0)
call DestroyEffect(dat.sfx)
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
call DestroyGroup(dat.affected)
set dat.Caster = null
set dat.sfx = null
set dat.sfxg = null
set dat.affected = null
call dat.destroy()
set Main.Total = Main.Total - 1
set Main.Index[i] = Main.Index[Main.Total]
set i = i - 1
elseif dat.ActId == 1 then
//first explosion.
//basically just create each 'pillar' circle by circle on each interval.
//it also toss unit and add it to group so it didn't tossed again
if (dat.Time2 <= 0) and (dat.num<=dat.num2) then
set dat.Time2 = FEEInterval
set l = FEELineSum+(FEELineSumIncr*dat.level)
set R[1] = 360/I2R(l)
set R[2] = (dat.Area/I2R(dat.num2))*I2R(dat.num)
loop
exitwhen l <= 0
set R[3] = dat.angle+(R[1]*I2R(l))
if R[3] > 360 then
set R[3] = R[3] - 360
endif
call FEEffect.Create(dat.x+(R[2]*Cos(R[3]*bj_DEGTORAD)),dat.y+(R[2]*Sin(R[3]*bj_DEGTORAD)),GetOwningPlayer(dat.Caster))
set l = l - 1
endloop
set dat.num = dat.num+1
endif
if dat.Time3 <= 0 then
call SetUnitAnimation(dat.Caster,FECasterAnim)
set dat.Time3 = FECasterAnimTime
endif
call GroupAddGroup(dat.affected,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not (CanTarget(dat.Caster,u2)) then
call GroupRemoveUnit(dat.affected,u2)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not IsUnitInGroup(u2,dat.affected) then
set R[4] = (2*FETossHeight*dat.Time)/(FETossHeight+SquareRoot(FETossHeight*FETossHeight*(1-FETossHeightRatio)))
set R[1] = (4*FETossHeight)/(R[4])
set R[3] = (8*FETossHeight)/(R[4]*R[4])
call GroupAddUnit(dat.affected,u2)
set R[0] = FEDamage+(FEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,FEATT,FEDGT,FEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
else
call Tossed.Create(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
endif
endif
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
//change of phase.
//re-initiate the variable, effect, and the group
set dat.angle = GetRandomReal(0.,360.)
set dat.ActId = 2
set dat.Time = SETime
set dat.Time2 = SEEAppearInterval
set dat.Time3 = SECasterAnimTime
set dat.Time4 = SECasterSoundInterval
set snd = CreateSound(SECasterSound, false, true, true, 10, 10, "SpellsEAX")
call SetSoundDuration(snd, GetSoundFileDuration(SECasterSound))
call AttachSoundToUnit(snd, dat.Caster)
call SetSoundVolume(snd, R2I(SECasterSoundVolume*127.*0.01))
call StartSound(snd)
call KillSoundWhenDone(snd)
set dat.v = (4*SECasterJumpHeight)/dat.Time
set dat.acc = (8*SECasterJumpHeight)/(dat.Time*dat.Time)
set dat.num = 1
set dat.num2 = SEESum
call DestroyEffect(dat.sfx)
set dat.sfx = AddSpecialEffectTarget(SECasterAttachEffect,dat.Caster,CasterAttach)
call DestroyEffect(AddSpecialEffectTarget(SECasterEffect,dat.Caster,CasterAttach))
call SetUnitAnimation(dat.Caster,SECasterAnim)
call GroupClear(dat.affected)
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[5] = (2*SETossHeight*dat.Time)/(SETossHeight+SquareRoot(SETossHeight*(SETossHeight-GetUnitFlyHeight(u2))))
set R[1] = (4*SETossHeight)/(R[5])
set R[6] = GetUnitX(u2)-dat.x
set R[7] = GetUnitY(u2)-dat.y
set R[2] = (dat.Area-SquareRoot(R[6]*R[6]+R[7]*R[7]))/dat.Time
set R[3] = (8*FETossHeight)/(R[5]*R[5])
set R[4] = bj_RADTODEG*Atan2(GetUnitY(u2)-dat.y,GetUnitX(u2)-dat.x)
call GroupAddUnit(dat.affected,u2)
set R[0] = SEDamage+(SEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,SEATT,SEDGT,SEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
else
call Tossed.Create(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = null
call DestroyBoolExpr(filter)
endif
elseif dat.ActId == 2 then
//the second explosion
//basically just create each rotating effect one by one, then rotating it individually
//also rotate the caster
set dat.Time4 = dat.Time4-TimeOut
set dat.angle = dat.angle+(SEEAngSpeed*TimeOut)
call SetUnitFacing(dat.Caster,GetUnitFacing(dat.Caster)+(SECasterAngSpeed*TimeOut))
call GroupAddGroup(dat.sfxg,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[1] = GetUnitFacing(u2)+(SEEAngSpeed*TimeOut)
call SetUnitX(u2,dat.x+(SEEDistance*Cos(R[1]*bj_DEGTORAD)))
call SetUnitY(u2,dat.y+(SEEDistance*Sin(R[1]*bj_DEGTORAD)))
call SetUnitFacing(u2,R[1])
call GroupRemoveUnit(g,u2)
endloop
if (dat.Time2 <= 0) and (dat.num<=dat.num2) then
set dat.Time2 = SEEAppearInterval
set u2 = CreateUnit(GetOwningPlayer(dat.Caster),DummyID,dat.x+(SEEDistance*Cos(dat.angle*bj_DEGTORAD)),dat.y+(SEEDistance*Sin(dat.angle*bj_DEGTORAD)),dat.angle)
call AddSpecialEffectTarget(SEEModel,u2,DummyAttach)
call SetUnitScale(u2,SEEModelScale,SEEModelScale,SEEModelScale)
call SetUnitFlyHeight(u2,(SEEHeight/I2R(dat.num2))*dat.num,0.)
call SetUnitFacing(u2,dat.angle)
call SetUnitVertexColor(u2,SEEModelRed,SEEModelGreen,SEEModelBlue,255)
set R[1] = ((dat.Time+(dat.Time2*dat.num))*0.5)+(dat.Time2*(dat.num-1))
call UnitApplyTimedLife(u2,'BTLF',R[1])
call GroupAddUnit(dat.sfxg,u2)
set dat.angle = dat.angle - (360/I2R(dat.num2))
set dat.num = dat.num+1
endif
if dat.Time3 <= 0 then
call SetUnitAnimation(dat.Caster,SECasterAnim)
set dat.Time3 = SECasterAnimTime
endif
if dat.Time4 <= 0 then
set snd = CreateSound(SECasterSound, false, true, true, 10, 10, "SpellsEAX")
call SetSoundDuration(snd, GetSoundFileDuration(SECasterSound))
call AttachSoundToUnit(snd, dat.Caster)
call SetSoundVolume(snd, R2I(SECasterSoundVolume*127.*0.01))
call StartSound(snd)
call KillSoundWhenDone(snd)
set dat.Time4 = SECasterSoundInterval
endif
call GroupAddGroup(dat.affected,g)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not (CanTarget(dat.Caster,u2)) then
call GroupRemoveUnit(dat.affected,u2)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = dat.Caster
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
if not IsUnitInGroup(u2,dat.affected) then
set R[5] = (2*SETossHeight*dat.Time)/(SETossHeight+SquareRoot(SETossHeight*(SETossHeight-GetUnitFlyHeight(u2))))
set R[1] = (4*SETossHeight)/(R[5])
set R[6] = GetUnitX(u2)-dat.x
set R[7] = GetUnitY(u2)-dat.y
set R[2] = (dat.Area-SquareRoot(R[6]*R[6]+R[7]*R[7]))/dat.Time
set R[3] = (8*FETossHeight)/(R[5]*R[5])
set R[4] = bj_RADTODEG*Atan2(GetUnitY(u2)-dat.y,GetUnitX(u2)-dat.x)
call GroupAddUnit(dat.affected,u2)
set R[0] = SEDamage+(SEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,SEATT,SEDGT,SEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
else
call Tossed.Create(u2,R[2],R[1],R[3],R[4],SETargetAttachEffect,SETargetEffect)
endif
endif
call GroupRemoveUnit(g,u2)
endloop
if dat.Time <= 0 then
//finish the spell. clearing te index
call PauseUnit(dat.Caster,false)
call SetUnitFlyHeight(dat.Caster,GetUnitDefaultFlyHeight(dat.Caster),0)
call DestroyEffect(dat.sfx)
loop
set u2 = FirstOfGroup(dat.sfxg)
exitwhen u2 == null
call UnitApplyTimedLife(u2,'BTLF',TimeOut)
call GroupRemoveUnit(dat.sfxg,u2)
endloop
call DestroyGroup(dat.sfxg)
call DestroyGroup(dat.affected)
set dat.Caster = null
set dat.sfx = null
set dat.sfxg = null
set dat.affected = null
call dat.destroy()
set Main.Total = Main.Total - 1
set Main.Index[i] = Main.Index[Main.Total]
set i = i - 1
endif
endif
set i = i +1
endloop
if Main.Total == 0 then
call PauseTimer(Main.Timer)
endif
set snd = null
endmethod
static method Create takes nothing returns nothing
//the creating of the spell.
//create one pillar in the place of caster.
//initiate all variable, create the efect, etc.
local Main dat = Main.allocate()
local unit u = GetTriggerUnit()
call PauseUnit(u,true)
set dat.Caster = u
call PauseUnit(dat.Caster,true)
call UnitAddAbility(u,'Arav')
call UnitRemoveAbility(u,'Arav')
set dat.x = GetUnitX(u)
set dat.y = GetUnitY(u)
set dat.angle = GetRandomReal(0.,360.)
call FEEffect.Create(dat.x,dat.y,GetOwningPlayer(u))
set dat.ActId = 1
set dat.level = GetUnitAbilityLevel(u,SpellID) - 1
set dat.Area = AoE+(AoEIncr*I2R(dat.level))
set dat.Time = FETime+(FETimeIncr*I2R(dat.level))
set dat.Time2 = FEEInterval
set dat.Time3 = FECasterAnimTime
set dat.v = (4*FECasterJumpHeight)/dat.Time
set dat.acc = (8*FECasterJumpHeight)/(dat.Time*dat.Time)
set dat.num = 1
set dat.num2 = FEECircleSum+(FEECircleSumIncr*dat.level)
set dat.sfxg = CreateGroup()
set dat.sfx = AddSpecialEffectTarget(FECasterAttachEffect,u,CasterAttach)
call DestroyEffect(AddSpecialEffectTarget(FECasterEffect,u,CasterAttach))
call SetUnitAnimation(u,FECasterAnim)
set dat.affected = CreateGroup()
set temp = u
set filter = Filter(function Main.CanTargeted)
call GroupEnumUnitsInRange(g,dat.x,dat.y,dat.Area,filter)
loop
set u2 = FirstOfGroup(g)
exitwhen u2 == null
set R[4] = (2*FETossHeight*dat.Time)/(FETossHeight+SquareRoot(FETossHeight*FETossHeight*(1-FETossHeightRatio)))
set R[1] = (4*FETossHeight)/(R[4])
set R[3] = (8*FETossHeight)/(R[4]*R[4])
call GroupAddUnit(dat.affected,u2)
set R[0] = FEDamage+(FEDamageIncr*I2R(dat.level))
call UnitDamageTarget(dat.Caster,u2,R[0],true,false,FEATT,FEDGT,FEWPT)
if IsUnitInGroup(u2,Tossed.Affected) then
call Tossed.Change(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
else
call Tossed.Create(u2,0,R[1],R[3],0.,FETargetAttachEffect,FETargetEffect)
endif
call GroupRemoveUnit(g,u2)
endloop
set temp = null
call DestroyBoolExpr(filter)
if Main.Total == 0 then
call TimerStart(Main.Timer,TimeOut,true,function Main.Loop)
endif
set Main.Index[Main.Total] = dat
set Main.Total = Main.Total+1
set u = null
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == SpellID then
call Main.Create()
endif
return false
endfunction
private function InitTrig_Initialize takes nothing returns nothing
//create the trigger
local trigger t = CreateTrigger()
//add event
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
//add 'condition'
call TriggerAddCondition(t, Condition(function Conditions))
//preload dummy unit
call RemoveUnit(CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DummyID,0,0,0))
//preload the spell's effect
call Preload(SECasterSound)
call Preload(FEEModel)
call Preload(FECasterEffect)
call Preload(FECasterAttachEffect)
call Preload(FETargetEffect)
call Preload(FETargetAttachEffect)
call Preload(SEEModel)
call Preload(SECasterEffect)
call Preload(SECasterAttachEffect)
call Preload(SETargetEffect)
call Preload(SETargetAttachEffect)
endfunction
endscope
Contest is over, I will be reviewing submissions now.
wow, that's really fast. if TRD give the spell, the result will announced immediately? Awesome.What is strict about it? There's a deadline to have the entry in by. I'm also not a robot, despite popular opinion. I do have a sense of flexibility. 3 days is a bit long for me though. I've already reviewed 16/19 of the submissions and that's not counting TRD's meteor spell. Why delay the results?
What is strict about it? There's a deadline to have the entry in by. I'm also not a robot, despite popular opinion. I do have a sense of flexibility. 3 days is a bit long for me though. I've already reviewed 16/19 of the submissions and that's not counting TRD's meteor spell. Why delay the results?
I don't have NewGen to compile it for him
C'mon!!! http://sc2modding.info/warcraft3/wc3-editing-tools/jass-new-generation-pack-(jngp)/I'm eagerly waiting for TRD to publish his map. Garfield1337 also published a bad map (didn't compile the vJass to JASS in the war3map.j file) and I don't have NewGen to compile it for him, so I guess I am waiting for him too.