• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Spells & Systems Mini-Contest #20

Status
Not open for further replies.

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,516

Attachments

  • (4)gravityGun009.w3x
    31.3 KB · Views: 106
Level 17
Joined
Jan 21, 2010
Messages
2,111
The real one:
mine:
There, about the description..
E:"Your progress is impressive Kratos, but your skills will not carry youto
your ultimate goal. I offer you the souls of Hades itself, the souls of the dead, set ready to fight by your side. " – Hades
This power is given to Kratos by Lord Hades , after slaying Pandora's Guardian and acquiring the Architect's Son's Head . It allows Kratos to summon the souls of Hades, and make them attack his enemies. A player can also level it up to increase the power and amount of the souls. Kratos uses a variant of this power in God of War II when he defeated the Barbarian King and acquired Barbarian Hammer . Kratos uses a variant of this power in God of War III when he defeated Hadesand acquired The Claws of Hades . - god of war wiki
 
Last edited:
Level 17
Joined
Jan 21, 2010
Messages
2,111
Okay, wait a sec....
Summons 3 powerful Warrior from the depth of Underworld to aid Kratos in his battle, those Ghost is in 3 form:
Fire that deal Str in damage and healing Kratos.
Poison that deal Agi in damage and shoots a Poison attack that deal Dps, and slowing enemy. Frost that deal Int in damage, and slowing enemies.
Level 1
- Fire - deal Str+(0.75*Str) damage.
-Poison - deal Agi+(0.5*Agi) damage.
-Frost - deal Int+(0.25*Int) damage.
Level 2
-Fire - deal Str+(1.5*Str) damage.
-Poison - deal Agi+(1*Agi) damage.
-Frost - deal Int+(0.5*Int) damage.
Level 3
-Fire - deal Str+(2.25*Str) damage.
-Poison - deal Agi+(1.5*Agi) damage.
-Frost - deal Int+(0.75*Int) damage.
Level 4
-Fire - deal Str+(3*Str) damage.
-Poison - deal Agi+(2*Agi) damage.
-Frost - deal Int+(1*Int) damage.

Summons 3 powerful Warrior from the depth of Underworld to aid Kratos in his battle, those Ghost is in 3 form:
Fire that deal Str in damage and healing Kratos in same amount.
Poison that deal Agi in damage and shoots a Poison attack that deal 25 initial damage, and deal 10 Dps, and slowing enemy for 25% of attack speed and 50% of movement speed in 200 AoE.
Frost that deal Int in damage, and slowing enemies for 20% of their movement and attack speed.

Level 1
-Fire - deal Str+(0.75*Str) damage.
-Poison - deal Agi+(0.5*Agi) damage.
-Frost - deal Int+(0.25*Int) damage.

  • Hades Army Start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to (==) Hades Army
    • Actions
      • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HA_Skip Equal to (==) 0
        • Then - Actions
          • Trigger - Turn on Hades Army Loop <gen>
        • Else - Actions
      • -------- - --------
      • Set HA_Times = (HA_Times + 1)
      • Set HA_Skip = (HA_Skip + 1)
      • -------- - --------
      • Set HA_Off[HA_Times] = True
      • -------- - --------
      • Set HA_Caster[HA_Times] = (Triggering unit)
      • Set HA_Dur[HA_Times] = 0.00
      • Set HA_Order[HA_Times] = 0.75
      • Set HA_Sound[HA_Times] = HadesArmy <gen>
      • Set HA_DamageStr[HA_Times] = ((Strength of HA_Caster[HA_Times] (Include bonuses)) + (((Integer(0.75)) x (Level of Hades Army for HA_Caster[HA_Times])) x (Strength of HA_Caster[HA_Times] (Include bonuses))))
      • Set HA_DamageAgi[HA_Times] = ((Agility of HA_Caster[HA_Times] (Include bonuses)) + (((Integer(0.50)) x (Level of Hades Army for HA_Caster[HA_Times])) x (Agility of HA_Caster[HA_Times] (Include bonuses))))
      • Set HA_DamageInt[HA_Times] = ((Intelligence of HA_Caster[HA_Times] (Include bonuses)) + (((Integer(0.25)) x (Level of Hades Army for HA_Caster[HA_Times])) x (Intelligence of HA_Caster[HA_Times] (Include bonuses))))
      • Set GlobalPoint[0] = (Position of HA_Caster[HA_Times])
      • Unit - Create 1 Ghost for (Owner of HA_Caster[HA_Times]) at GlobalPoint[0] facing Default building facing (270.0) degrees
      • Set HA_GhostStr[HA_Times] = (Last created unit)
      • Unit - Create 1 Ghost for (Owner of HA_Caster[HA_Times]) at GlobalPoint[0] facing Default building facing (270.0) degrees
      • Set HA_GhostAgi[HA_Times] = (Last created unit)
      • Unit - Create 1 Ghost for (Owner of HA_Caster[HA_Times]) at GlobalPoint[0] facing Default building facing (270.0) degrees
      • Set HA_GhostInt[HA_Times] = (Last created unit)
      • Unit - Add HA_Agi_additionalSkill to HA_GhostAgi[HA_Times]
      • Unit - Add HA_Int_AdditonalSkill to HA_GhostInt[HA_Times]
      • Unit - Set level of HA_Agi_additionalSkill for HA_GhostAgi[HA_Times] to (Level of Hades Army for HA_Caster[HA_Times])
      • Unit - Set level of HA_Int_AdditonalSkill for HA_GhostInt[HA_Times] to (Level of Hades Army for HA_Caster[HA_Times])
      • Special Effect - Create a special effect attached to the chest of HA_GhostStr[HA_Times] using Abilities\Weapons\PhoenixMissile\Phoenix_Missile_mini.mdl
      • Special Effect - Create a special effect attached to the chest of HA_GhostAgi[HA_Times] using Abilities\Weapons\IllidanMissile\IllidanMissile.mdl
      • Special Effect - Create a special effect attached to the chest of HA_GhostInt[HA_Times] using Abilities\Weapons\ZigguratFrostMissile\ZigguratFrostMissile.mdl
      • Custom script: call RemoveLocation(udg_GlobalPoint[0])
      • Sound - Play HA_Sound[HA_Times] at 100.00% volume, attached to HA_Caster[HA_Times]
  • Hades Army Loop
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Do Multiple ActionsFor each (Integer HA) from 1 to HA_Times, do (Actions)
        • Loop - Actions
          • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • HA_Off[HA] Equal to (==) True
            • Then - Actions
              • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • HA_Dur[HA] Equal to (==) 15.00
                • Then - Actions
                  • Set HA_Skip = (HA_Skip - 1)
                  • Set HA_Off[HA] = False
                  • Unit - Kill HA_GhostStr[HA]
                  • Unit - Kill HA_GhostAgi[HA]
                  • Unit - Kill HA_GhostInt[HA]
                  • Sound - Stop HA_Sound[HA] After fading
                    • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • HA_Skip Equal to (==) 0
                      • Then - Actions
                        • Set HA_Times = 0
                        • Trigger - Turn off Hades Army Loop <gen>
                      • Else - Actions
                • Else - Actions
                  • Set HA_Dur[HA] = (HA_Dur[HA] + 0.05)
                    • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                      • If - Conditions
                        • HA_Order[HA] Equal to (==) 0.75
                      • Then - Actions
                        • Set HA_Order[HA] = 0.00
                        • Animation - Change HA_GhostAgi[HA] flying height to (Random real number between 1.00 and 500.00) at 650.00
                        • Animation - Change HA_GhostInt[HA] flying height to (Random real number between 1.00 and 500.00) at 650.00
                        • Animation - Change HA_GhostStr[HA] flying height to (Random real number between 1.00 and 500.00) at 650.00
                        • Set GlobalPoint[1] = (Position of HA_GhostStr[HA])
                        • Set GlobalPoint[2] = (Position of HA_GhostAgi[HA])
                        • Set GlobalPoint[3] = (Position of HA_GhostInt[HA])
                        • Set GlobalPoint[4] = (Position of HA_Caster[HA])
                        • Set GlobalPoint[5] = (Random point in (Region centered at GlobalPoint[4] with size (1200.00, 1200.00)))
                        • Set GlobalPoint[6] = (Random point in (Region centered at GlobalPoint[4] with size (1200.00, 1200.00)))
                        • Set GlobalPoint[7] = (Random point in (Region centered at GlobalPoint[4] with size (1200.00, 1200.00)))
                        • Unit - Order HA_GhostStr[HA] to Attack-Move To GlobalPoint[5]
                        • Unit - Order HA_GhostAgi[HA] to Attack-Move To GlobalPoint[6]
                        • Unit - Order HA_GhostInt[HA] to Attack-Move To GlobalPoint[7]
                        • Set GlobalGroup[0] = (Units within 100.00 of GlobalPoint[1] matching ((((Matching unit) is A structure) Equal to (==) False) and ((((Matching unit) is alive) Equal to (==) True) and ((((Matching unit) belongs to an ally of (Owner of HA_Caster[HA])) Equal to (==) False) and (((Mat
                        • Unit Group - Pick every unit in GlobalGroup[0] and do (Actions)
                          • Loop - Actions
                            • Unit - Cause HA_GhostStr[HA] to damage (Picked unit), dealing (Real(HA_DamageStr[HA])) damage of attack type Hero and damage type Universal
                            • Unit - Set life of HA_Caster[HA] to ((Life of HA_Caster[HA]) + (Real(HA_DamageStr[HA])))
                        • Set GlobalGroup[1] = (Units within 100.00 of GlobalPoint[2] matching ((((Matching unit) is A structure) Equal to (==) False) and ((((Matching unit) is alive) Equal to (==) True) and ((((Matching unit) belongs to an ally of (Owner of HA_Caster[HA])) Equal to (==) False) and (((Mat
                        • Unit Group - Pick every unit in GlobalGroup[1] and do (Actions)
                          • Loop - Actions
                            • Multiple FunctionsIf (All Conditions are True) then do (Then Actions) else do (Else Actions)
                              • If - Conditions
                                • ((Picked unit) has buff Poisoned 123 ) Equal to (==) False
                              • Then - Actions
                                • Unit - Order HA_GhostAgi[HA] to Night Elf Warden - Shadow Strike (Picked unit)
                              • Else - Actions
                                • Unit - Cause HA_GhostAgi[HA] to damage (Picked unit), dealing (Real(HA_DamageAgi[HA])) damage of attack type Hero and damage type Universal
                        • Set GlobalGroup[2] = (Units within 100.00 of GlobalPoint[3] matching ((((Matching unit) is A structure) Equal to (==) False) and ((((Matching unit) is alive) Equal to (==) True) and ((((Matching unit) belongs to an ally of (Owner of HA_Caster[HA])) Equal to (==) False) and (((Mat
                        • Unit Group - Pick every unit in GlobalGroup[2] and do (Actions)
                          • Loop - Actions
                            • Unit - Cause HA_GhostInt[HA] to damage (Picked unit), dealing (Real(HA_DamageInt[HA])) damage of attack type Hero and damage type Universal
                        • Custom script: call DestroyGroup(udg_GlobalGroup[0])
                        • Custom script: call DestroyGroup(udg_GlobalGroup[1])
                        • Custom script: call DestroyGroup(udg_GlobalGroup[2])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[1])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[2])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[3])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[4])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[5])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[6])
                        • Custom script: call RemoveLocation(udg_GlobalPoint[7])
                      • Else - Actions
                        • Set HA_Order[HA] = (HA_Order[HA] + 0.05)
            • Else - Actions
  • Removal of unit
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to (==) Ghost
    • Actions
      • Set GlobalPoint[8] = (Position of (Triggering unit))
      • Unit - Hide (Triggering unit)
      • Special Effect - Create a special effect at GlobalPoint[8] using Abilities\Spells\Human\MarkOfChaos\MarkOfChaosDone.mdl
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call RemoveLocation(udg_GlobalPoint[8])
 
Last edited:
Last edited:
Level 22
Joined
Dec 31, 2006
Messages
2,216
Derp derp, finishing the spell now. Had to play some FFX :D

Just to be sure, the spell must've been submitted before 08:00 GMT on Saturday (18th of June), right?

Edit: Btw, Bribe, be prepared for spaghetti code from my side :D
 
Level 22
Joined
Dec 31, 2006
Messages
2,216
Okeh.

Btw, my spell got an unintentional feature :D
When it's burning in one place (the ground begins to burn after a meteor has hit it) and another meteor strikes very close, then the fire (burning soil) is tossed away just like the units. This way the fire is spreading. I'm too lazy to make the fire damage units though, and it would kinda be overkill if it did, imo. Suddenly the fire is tossed into a forest and it begins to burn, lol. I might add it as an option when I release this in the spells section though.

Edit: Btw, Deo, I chose another sound. U mad?
 
Last edited:
Level 17
Joined
Jun 28, 2008
Messages
776
Here is my final submission, so far :

Worms Sheep Strike

Code
JASS:
//----------------------------------------------------------------------------------
//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
 

Attachments

  • Xiliger Entry - Sheep Strike.w3x
    59.4 KB · Views: 47
Level 10
Joined
Jun 1, 2008
Messages
485
fuh... it's still 7 hour before the deadline, right?

Finally, the first and final submission:
Final Submission here

Legend of Mana's Aerial Reaver

here's the video, it start from 2.26 to 2.32. Can't find any other video, so i hope this will do

JASS:
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

honestly, this is the most un-polished and rushed spell I've ever done. If only I still have time... darn exam, killing 90% of my time.

v1.0
Uploaded
 

Attachments

  • Aerial Reaver v1.0 [MG].w3x
    139.5 KB · Views: 44
Last edited:
Level 10
Joined
Jun 1, 2008
Messages
485
You still have some time to work on it. But I guess you're busy.
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.

So, now it's already finished, right?
anyone have the list of all submission?
EDIT:
DARN!
still have four hours left! gonna update it

EDIT2:
since I'm not allowed to double post, I'll just make the proper submission here


Contestant Name: Mage_Goo
Entry Name: Aerial Reaver v1.1

Aerial Reaver
icon.jpg
A secret technique of throwin enemies up into the air and carving into them as they fall.

Level 1 - Deal a total of 150 damage in an area of 300.
Level 2 - Deal a total of 200 damage in an area of 350.
Level 3 - Deal a total of 250 damage in an area of 400.
Target ground unit only.

Some screeny
attachment.php

The real Aerial Reaver. It start from 2.26 to 2.32. Can't find other video, so I hope this will do.
another long code...
JASS:
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
v1.0
Submit the spell

v1.1
Improve Caster Animation
Add Additional Sound
Other small stuff that I forgot
 

Attachments

  • Aerial Reaver v1.1 [MG].w3x
    140.4 KB · Views: 63
  • Aerial Reaver Screen.jpg
    Aerial Reaver Screen.jpg
    62.2 KB · Views: 191
Last edited:
Level 48
Joined
Apr 18, 2008
Messages
8,416
Contest is over, I will be reviewing submissions now.

I know I'm not participating, but may I please ask... Can someone still submit an entry, even if it's a few hours late?
Because last time I saw TRD in chat, he said that all the spell lacks is a tooltip, and then disconnected. That was yesterday. I haven't seen him since then. I assume that he's done with the spell, and he simply didn't have the chance to submit it.
 
Level 10
Joined
Jun 1, 2008
Messages
485
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?
wow, that's really fast. if TRD give the spell, the result will announced immediately? Awesome.

grr... just realized that one of my parabolic formula is a bit wrong. hope it won't reduce my point too much...
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Still no sign of TRD :-/

Funny thing is I did have NewGen installed, Moyack's version, somewhere on my hard drive. I was just too lazy to put it in the right folder ;)

Attached is Garfield's map if anyone wants to try it out. However, testing it reveals some pretty cool effects but does not damage enemies like it says in the tooltip.

Edit: Looks like it was a WIP spell, the whole section on damaging units was commented out from one of the "execute" methods. This mystery has been solved.
 

Attachments

  • Infernal Wrath.w3x
    29 KB · Views: 23

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
I can delete my review of it from the resulting list, but if you want here's what I put down for it:


Overall Aspect: 3/5 -> Unfinished product - the tooltip suggests it deals damage but what results is just eyecandy with no functionality.
Visual Effects: 10/10 -> Beautiful effects
Sound Effects: 5/5
Triggering: 6/10 -> (Unfinished) Why did you comment out the mechanics of the spell? Some things you over-programmed, you don't need to ".execute()" periodic functions because it would be easier and less stressful on the computer to simply call them.
Total: 24/30
 
Status
Not open for further replies.
Top