Spell Earth Shock

vypur85

Hibernate
Reaction score
803
Not sure something similarly to this has been done before or not. If yes please just send this to the grave :p. It's a simple ability. Did it because I was bored at work.

Description:
The Rock Golem hurls massive boulders from the ground into the air, dealing 40/80/120/160 damage to nearby enemy units. As the rocks begin to fall, they are split into random number of smaller rock chunks that deal 20/40/60/80 damage each on impact. Lasts for 5 seconds.

It is MPI
Leak-free
Easy to import
Can be quite laggy if too many cast per instance (quite many dummies created)

Implementation:
Code:
1. Copy and paste the Dummy and Earth Shock ability to your map.
2. Then copy and paste the triggers. Make sure variables are automatically created when copied. This can be set in Preference.
3. Change the damage and AOE values as you wish. That's all.

4. I've created variables for almost everything in 'Map Init for Earth Shock'. Just change the properties of the ability in there will do. Even for the dummy and ability. This is to ease importing task.

Spell by vypur85 (no need credits, just use as you wish)

Triggers:
This is for the setup of the ability. Adjust these to make it suit your map. Also preloads abilities and dummies to reduce lag.
Code:
Map Init for Earth Shock
    Events
        Map initialization
    Conditions
    Actions
        Set Abi_EarthShock = Earth Shock 
        Set UnitType_EShock_Dummy = Dummy
        -------- ============================================================= --------
        -------- ============================================================= --------
        -------- ============================================================= --------
        -------- General --------
        Set Real_ESchock_SpellAoe = 500.00
        Set Real_ESchock_SpellDuration = 5.00
        -------- Large Rock Properties (The damage increases by one time per level) --------
        Set Int_EShock_MaxLargeRocks = 30
        Set Real_EShock_BigRock_AoeDmg = 180.00
        Set Real_EShock_EmergeDmg = 40.00
        -------- Small Rock Properties --------
        Set Int_EShock_MinSmallRocks = 3
        Set Int_EShock_MaxSmallRocks = 8
        Set Real_EShock_SmallRock_AoeDmg = 180.00
        Set Real_ESchock_Damage = 20.00
        Set Real_ESchock_IncreasePerLevel = 20.00
        -------- Flying Properties --------
        Set Real_ESchock_MaxHeight = 800.00
        Set Real_ESchock_MinHeight = 400.00
        -------- ============================================================= --------
        -------- ============================================================= --------
        -------- ============================================================= --------
        -------- Preloading --------
        Set Pt_EShock_DummyPos = (Center of (Playable map area))
        Unit - Create 1 UnitType_EShock_Dummy for Neutral Passive at Pt_EShock_DummyPos facing Default building facing degrees
        Unit - Add Storm Crow Form to (Last created unit)
        Unit - Add Abi_EarthShock to (Last created unit)
        Custom script:   call UnitAddAbilityBJ( 'Aloc', GetLastCreatedUnit() )
        Unit - Remove (Last created unit) from the game
        Custom script:   call RemoveLocation (udg_Pt_EShock_DummyPos)

This creates initial dummies which will die and leads to the spawning of large rocks.
Code:
Earth Shock
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Abi_EarthShock
    Actions
        Set Unit_TriggeringUnit[(Player number of (Owner of (Triggering unit)))] = (Triggering unit)
        Set Pt_EShock_TriggerUnitPos = (Position of (Triggering unit))
        For each (Integer A) from 1 to Int_EShock_MaxLargeRocks, do (Actions)
            Loop - Actions
                Set Pt_EShock_DummyPos = (Pt_EShock_TriggerUnitPos offset by (Random real number between 0.00 and Real_ESchock_SpellAoe) towards (Random angle) degrees)
                Unit - Create 1 UnitType_EShock_Dummy for (Owner of (Triggering unit)) at Pt_EShock_DummyPos facing Default building facing degrees
                -------- This is to make sure that the spell will create AT LEAST 2 dummies at the beginning of the channel and at the end --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Integer A) Greater than or equal to 3
                        (Integer A) Less than or equal to (Int_EShock_MaxLargeRocks - 2)
                    Then - Actions
                        Unit - Add a (Random real number between 0.10 and (Real_ESchock_SpellDuration - 0.20)) second Generic expiration timer to (Last created unit)
                    Else - Actions
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                (Integer A) Greater than (Int_EShock_MaxLargeRocks - 2)
                            Then - Actions
                                Unit - Add a (Real_ESchock_SpellDuration - 0.10) second Generic expiration timer to (Last created unit)
                            Else - Actions
                                Unit - Add a 0.01 second Generic expiration timer to (Last created unit)
                Unit - Make (Last created unit) Invulnerable
                Unit - Add Abi_EarthShock to (Last created unit)
                Unit - Set level of Abi_EarthShock for (Last created unit) to (Level of Abi_EarthShock for (Triggering unit))
                Unit - Set the custom value of (Last created unit) to 1
                Unit - Hide (Last created unit)
                Custom script:   call RemoveLocation (udg_Pt_EShock_DummyPos)
        Custom script:   call RemoveLocation (udg_Pt_EShock_TriggerUnitPos)

This is the main trigger of this ability. It detects the death of dummies thus spawning other dummies accordingly.
Code:
Dummy Dies
    Events
        Unit - A unit Dies
    Conditions
        (Unit-type of (Triggering unit)) Equal to UnitType_EShock_Dummy
    Actions
        -------- This creates the big rocks if the hidden dummies die --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (Custom value of (Triggering unit)) Equal to 1
            Then - Actions
                Set Pt_EShock_DeadDummyPos = (Position of (Triggering unit))
                Special Effect - Create a special effect at Pt_EShock_DeadDummyPos using Objects\Spawnmodels\Undead\ImpaleTargetDust\ImpaleTargetDust.mdl
                Special Effect - Destroy (Last created special effect)
                Set Real_EShock_RandomTimedLife = (Random real number between 0.50 and 1.00)
                Set Real_ESchock_RandomFlyHeight = (Random real number between Real_ESchock_MinHeight and Real_ESchock_MaxHeight)
                Unit - Create 1 UnitType_EShock_Dummy for (Owner of (Triggering unit)) at Pt_EShock_DeadDummyPos facing Default building facing degrees
                Animation - Change (Last created unit)'s size to (200.00%, 200.00%, 200.00%) of its original size
                Unit - Add a Real_EShock_RandomTimedLife second Generic expiration timer to (Last created unit)
                Custom script:   call UnitAddAbilityBJ( 'Aloc', GetLastCreatedUnit() )
                Unit - Make (Last created unit) Invulnerable
                Unit - Add Abi_EarthShock to (Last created unit)
                Unit - Set level of Abi_EarthShock for (Last created unit) to (Level of Abi_EarthShock for (Triggering unit))
                Unit - Set the custom value of (Last created unit) to 2
                Unit - Add Storm Crow Form to (Last created unit)
                Unit - Remove Storm Crow Form from (Last created unit)
                Animation - Change (Last created unit) flying height to Real_ESchock_RandomFlyHeight at (Real_ESchock_RandomFlyHeight / Real_EShock_RandomTimedLife)
                Set Unitgp_EShock_AoeDmg = (Units within Real_EShock_BigRock_AoeDmg of Pt_EShock_DeadDummyPos matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True) and ((((Matching unit) is alive) Equal to
                Unit Group - Pick every unit in Unitgp_EShock_AoeDmg and do (Actions)
                    Loop - Actions
                        Unit - Cause (Triggering unit) to damage (Picked unit), dealing (Real_EShock_EmergeDmg x (Real((Level of Abi_EarthShock for (Triggering unit))))) damage of attack type Spells and damage type Magic
                Custom script:   call DestroyGroup (udg_Unitgp_EShock_AoeDmg)
                Custom script:   call RemoveLocation (udg_Pt_EShock_DeadDummyPos)
            Else - Actions
        -------- This creates the random small cluster rocks if the large rock dies --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (Custom value of (Triggering unit)) Equal to 2
            Then - Actions
                Set Pt_EShock_DeadDummyPos = (Position of (Triggering unit))
                Set Int_ESchock_RandomSmallRock = (Random integer number between Int_EShock_MinSmallRocks and Int_EShock_MaxSmallRocks)
                For each (Integer A) from 1 to Int_ESchock_RandomSmallRock, do (Actions)
                    Loop - Actions
                        Set Pt_EShock_MoveToPos = (Pt_EShock_DeadDummyPos offset by 250.00 towards ((Real((Integer A))) x (360.00 / (Real(Int_ESchock_RandomSmallRock)))) degrees)
                        Unit - Create 1 UnitType_EShock_Dummy for (Owner of (Triggering unit)) at Pt_EShock_DeadDummyPos facing Default building facing degrees
                        Animation - Change (Last created unit)'s size to (60.00%, 60.00%, 60.00%) of its original size
                        Unit - Add Storm Crow Form to (Last created unit)
                        Unit - Remove Storm Crow Form from (Last created unit)
                        Animation - Change (Last created unit) flying height to (Current flying height of (Triggering unit)) at 0.00
                        Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                        Custom script:   call UnitAddAbilityBJ( 'Aloc', GetLastCreatedUnit() )
                        Unit - Make (Last created unit) Invulnerable
                        Unit - Add Abi_EarthShock to (Last created unit)
                        Unit - Set level of Abi_EarthShock for (Last created unit) to (Level of Abi_EarthShock for (Triggering unit))
                        Unit - Set the custom value of (Last created unit) to 3
                        Unit - Set (Last created unit) movement speed to 250.00
                        Unit - Order (Last created unit) to Move To Pt_EShock_MoveToPos
                        Animation - Change (Last created unit) flying height to 0.00 at ((Current flying height of (Triggering unit)) / 1.00)
                        Custom script:   call RemoveLocation (udg_Pt_EShock_MoveToPos)
                Custom script:   call RemoveLocation (udg_Pt_EShock_DeadDummyPos)
            Else - Actions
        -------- This deals the damage if the small clusters die --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                (Custom value of (Triggering unit)) Equal to 3
            Then - Actions
                Set Pt_EShock_DeadDummyPos = (Position of (Triggering unit))
                Set Unitgp_EShock_AoeDmg = (Units within Real_EShock_SmallRock_AoeDmg of Pt_EShock_DeadDummyPos matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True) and ((((Matching unit) is alive) Equal 
                Unit Group - Pick every unit in Unitgp_EShock_AoeDmg and do (Actions)
                    Loop - Actions
                        Unit - Cause (Triggering unit) to damage (Picked unit), dealing (Real_ESchock_Damage + (Real_ESchock_IncreasePerLevel x (Real((Level of Abi_EarthShock for (Triggering unit)))))) damage of attack type Spells and damage type Magic
                Special Effect - Create a special effect at Pt_EShock_DeadDummyPos using Abilities\Spells\Other\Volcano\VolcanoMissile.mdl
                Special Effect - Destroy (Last created special effect)
                Custom script:   call DestroyGroup (udg_Unitgp_EShock_AoeDmg)
                Custom script:   call RemoveLocation (udg_Pt_EShock_DeadDummyPos)
            Else - Actions

This is to make the spell a channeling spell. You can even make it non-channeling by removing this trigger. Set the Follow Through Time of the ability to zero. If this is done, the ability can be considered MUI instead of MPI (but I prefer channeling, suits better).
Code:
Remove Dummy If Ability Stops
    Events
        Unit - A unit Stops casting an ability
    Conditions
        (Ability being cast) Equal to Abi_EarthShock
    Actions
        For each (Integer A) from 1 to 16, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Owner of (Triggering unit)) Equal to (Player((Integer A)))
                    Then - Actions
                        Set Unitgp_EShock_Dummy = (Units of type UnitType_EShock_Dummy)
                        Unit Group - Pick every unit in Unitgp_EShock_Dummy and do (Actions)
                            Loop - Actions
                                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                    If - Conditions
                                        (Owner of (Picked unit)) Equal to (Player((Integer A)))
                                        ((Picked unit) is alive) Equal to True
                                        (Custom value of (Picked unit)) Equal to 1
                                    Then - Actions
                                        Unit - Remove (Picked unit) from the game
                                    Else - Actions
                        Custom script:   call DestroyGroup (udg_Unitgp_EShock_Dummy)
                    Else - Actions

The spell basically plays around with 'A Unit is Dead' event. I hope it is understandable :). There are a lot of variables. Just change those in the 'Map Init for Earth Shock' trigger. Try not to change the others as there are some mathematical calculations involved (for the fly rate and land rate).

Do comment. Hope you like this simple spell :).

Please give me some time for s/shots (Done).

Update:
The spell is updated. :) Added this and that to ease implementation even more.

Note:
Code:
Set Int_EShock_MaxSmallRocks = 8
Setting this number to a high value (eg. 20 or 30) makes the spell looks like a firework display >.<. Lol... But it lags... So, give yourself a limit, please....

The Screen Shot enlarged:
attachment.php
 

Attachments

  • Earth Shock.jpg
    Earth Shock.jpg
    87.3 KB · Views: 2,235
  • Earth Shock.w3x
    28.3 KB · Views: 610

gref

New Member
Reaction score
33
Apart from the lag its a pretty neat spell.
It would be good if you could target the rocks more too.
 

Cohadar

master of fugue
Reaction score
209
Why don't you people simply lean jass?
If you are good at GUI you will be good at jass in no time.
and your spells will not lag...
and will be mui...
and be easier to import...
 

gref

New Member
Reaction score
33
I think this spell is cool so I'm making it Jass.
I won't post it here unless he wants me to.


Cleaned in Jass. PM me if anyone wants it.
 

hell_knight

Playing WoW
Reaction score
126
Its nice intresting spell ,
@cohadar
um some people just have trouble learning it>?
I've read countless JASS tuts I don't get them at all god I dont evne know what a function is. Copy n pasting wall of text / folder is almost just as hard o_O .
 

Flare

Stops copies me!
Reaction score
662
cool spell vypur, lots of fiery-rock-goodness :). might wanna add a little bit of text over each trigger's spoiler tag to show what specific part of the code its dealing with

@hell_knight: JASS is relatively simple (looking) once you get past the stuff like InitTrig and all that (imo anyways, that was probably the worst part of trying to learn JASS for me :S). and as far as i kno, a function is like a 'block' of GUI code (all the events for a trigger, the conditions and so on). look for vex's tut if u havent alredy, i found that to be the easiest to understand
 

Tinki3

Special Member
Reaction score
418
> I've read countless JASS tuts I don't get them at all god I dont even know what a function is

You don't?
Then perhaps JASS is not for you.

Just kidding.
JASS is for everyone.

The best way to start, IMO, would be to convert simple GUI triggers into
JASS, look at what each line changes into, and simply just remember the
important ones at first. That's how I learnt, btw.

And, if you are unsure of the JASS version of a GUI action, don't panic,
you can simply find the action in the GUI, convert that to JASS, and
add that to your script/code(s). Don't give up right away, like some would.

It's not impossible, at all. Most people say they don't "get this", or they
don't "get that", or even "I've read every JASS tut and none of them help
me in the least", but, most of the time, it's probably because they are too
lazy to actually stick their heads in the dirt and really start to get using JASS, and learn it, properly.

Reading tutorials on JASS don't help at all if you've never actually
written or attempted to write your own code in JASS, becuase if
you aren't slightly familiar with it, tutorials aren't of much use.
 

duyen

New Member
Reaction score
214
> I've read countless JASS tuts I don't get them at all god I dont even know what a function is

You don't?
Then perhaps JASS is not for you.

Just kidding.
JASS is for everyone.

The best way to start, IMO, would be to convert simple GUI triggers into
JASS, look at what each line changes into, and simply just remember the
important ones at first. That's how I learnt, btw.

And, if you are unsure of the JASS version of a GUI action, don't panic,
you can simply find the action in the GUI, convert that to JASS, and
add that to your script/code(s). Don't give up right away, like some would.

It's not impossible, at all. Most people say they don't "get this", or they
don't "get that", or even "I've read every JASS tut and none of them help
me in the least", but, most of the time, it's probably because they are too
lazy to actually stick their heads in the dirt and really start to get using JASS, and learn it, properly.

Reading tutorials on JASS don't help at all if you've never actually
written or attempted to write your own code in JASS, becuase if
you aren't slightly familiar with it, tutorials aren't of much use.

Cohadar says converting GUI is probably the worst way to learn JASS, and no offense but I think Cohadar is probably the best coder on TH. I personally have no knowledge of JASS so I can't really give you input.
 

Cohadar

master of fugue
Reaction score
209
Tinki3 said simple triggers, that is perfectly fine in the beginning to see how stuff work.

The worst thing is to try to convert a whole big GUI spell.

But once you learn how to set up your basic jass trigger:
JASS:
scope Template

globals
    private constant integer AID_SPELL = &#039;XXXX&#039;
endglobals

//===========================================================================
private function Actions takes nothing returns nothing
    // add spell code here
endfunction

//===========================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == AID_SPELL
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( trig, Condition( function Conditions ) )
    call TriggerAddAction( trig, function Actions )
endfunction

endscope


It is pointless to use GUI after that.
Especially because TESH has autocompletion.
 

Matemeo

New Member
Reaction score
20
And if someone wishes to learn Jass, theres a perfectly good forum, that they can spam questions in. (Seriously, do it, its slow in there)

Even after reading tuts if you don't understand something, ask about it.

Srsly.

I'm serial.

Totally, cereal.

:D
 

vypur85

Hibernate
Reaction score
803
Thanks for all the comments.

>gref
You can do anything you like with the spell. It's free for all. Credits are not an issue. Just do whatever you think is necessary (you can give credits if you want to :p). Of course converting it into JASS is a great thing to do. Inform me when you are done with it, I'd like to see it :).

>For the learning JASS issue - Hell, Tinki and Cohadar
Yeah. Hell got it correctly. I do have problems learning JASS (as of now). I have no programming experience before (You'd never guess what profession I have, as it's rare,I think, for people of my background to do WE :p). Have tried to learn once, but I kind of understand the basics a little bit. Just not sure how to make it to practice. Maybe more time of experimenting will help :). I just began learning GUI like around Aug last year, so I need some more time to play with GUI.

As for the spell, I think it lags because of the enormous amount of units produced (so I think even if it was to be converted into JASS, it would lag considerably too). For this spell, I've loop 30 rounds to produce 30 rocks. I made the loop adjustable to reduce its lag. The channeling time is 5 seconds - cannot be adjusted. I'll try to make it adjustable if necessary. To Flare, I'll try to make some brief notes on important areas. But give me some time ya, not quite bored now :p.

By the way, implementation of this spell is quite simple as I've made most important values into variables so that it is import-friendly and easy-to-adjust.

Additional comments will be welcomed :). What do I lack to get this approved?
 

gref

New Member
Reaction score
33
I had to do it because I just thought the eyecandy and idea was awesome.
It would lag less if you had these actions in your initialization trigger:
Code:
Custom Script: call Preload("Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl")
Custom Script: call Preload("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl")
and place your dummy on the map at the start, then remove it.
ie Unit - Remove Dummy 0000 <gen> from the game.
Also you give all of the units invulnerability and locust, when you could just give them locust in the editor, and you pass the level of the spell with Add Ability to Unit, Set Unit Ability Level etc. so that slows down performance as well. (I understand you just do that because its a simple way to keep passing the variable in GUI)

Code:
JASS:
scope EarthShock
    globals
        private constant integer AbilCode = &#039;A000&#039; //Earth Shock Ability
        private constant integer MaxLargeRockNumber = 30 //Maximum first rocks
        private constant integer DummyType = &#039;h000&#039; //Dummy unit
        private constant real MaxHeight = 800.0 //Maximum Height a rock will reach
        private constant real MinHeight = 400.0 //Minimum Height a rock will reach
        private constant real BigRockAOE = 180 // Range that you will be damaged in by a Big rock.
        private constant real SmallRockAOE = 180 //Range that you will be damaged in by a small rock
        private constant real BigRockDamage = 40.0 //Damage per level of big rock
        private constant real BaseDamage = 20.0 //Base damage of small rock
        private constant real DamageFactor = 20.0 //Damage per level of small rock
    endglobals
    
    struct RockStruct
        real level
        integer stage
                
        static method create takes real level, integer stage returns RockStruct
            local RockStruct r = RockStruct.allocate()
            
            set r.level = level
            set r.stage = stage
            
            return r
        endmethod    
    endstruct    
    
    private function StopFilter takes nothing returns boolean
        return (GetUnitTypeId(GetFilterUnit()) == DummyType)      
    endfunction
    
    private function EarthShockStop_Actions takes nothing returns nothing
        local group g = CreateGroup()
        local unit u
        local RockStruct r
        
        call GroupEnumUnitsOfPlayer(g, GetOwningPlayer(GetTriggerUnit()), Condition( function StopFilter))
        
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            
            set r = GetAttachedInt(u, &quot;RockStruct&quot;)
            if (r.stage == 1) then
                call RockStruct.destroy(r)
                call CleanAttachedVars(u)
                call RemoveUnit(u)
            endif
            
            call GroupRemoveUnit(g, u)
        endloop
        
        call DestroyGroup(g)
        set g = null
        set u = null    
    endfunction
    
    
    private function DummyDies_Conditions takes nothing returns boolean
        if (  GetUnitTypeId(GetTriggerUnit()) == DummyType  ) then
            return true
        endif
        return false
    endfunction

    private function DamageFilter takes nothing returns boolean
        return not(IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE))and(GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE)&gt;0)    
    endfunction

    private function DummyDies_Actions takes nothing returns nothing 
        local unit u = GetTriggerUnit()
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real timedlife
        local real flyheight
        local unit d
        local group g = CreateGroup()
        local unit l
        local integer smallrocknumber
        local integer i
        local real dx
        local real dy
        local RockStruct r = GetAttachedInt(u, &quot;RockStruct&quot;)
        local RockStruct r2
        
                                                                             
    // This creates the big rocks
        if ( r.stage == 1 ) then //Big rock damage.
        //call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;1&quot;)
        
            call DestroyEffect( AddSpecialEffect( &quot;Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl&quot;, x, y ))
        
            set timedlife = GetRandomReal(0.50, 1.00)
            set flyheight = GetRandomReal(MinHeight, MaxHeight)
            set d =  CreateUnit( GetOwningPlayer(u), DummyType, x, y, bj_UNIT_FACING )
            call SetUnitScale( d, 2.0, 2.0, 2.0 )
            call UnitApplyTimedLife(d, &#039;BTLF&#039;, timedlife )
            
            set r2 = RockStruct.create(r.level, 2)
            call AttachInt(d, &quot;RockStruct&quot;, r2)
            
            call UnitAddAbility(d, &#039;Arav&#039; )
            call UnitRemoveAbility(d, &#039;Arav&#039; )
            call SetUnitFlyHeight( d, flyheight, ( flyheight/timedlife ) )
        
            call GroupEnumUnitsInRange(g, x, y, BigRockAOE, Condition(function DamageFilter))
            loop
                set l = FirstOfGroup(g)
                exitwhen l == null
            
                if(IsUnitEnemy(l, GetOwningPlayer(u))) then            
                    call UnitDamageTarget(u, l, BigRockDamage*r.level, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
                endif
            
                call GroupRemoveUnit(g, l)
            endloop
        elseif ( r.stage == 2 ) then //Big rock has died, spawns small rocks
        
            set smallrocknumber = GetRandomInt(3, 8) 
        //call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;2&quot;)
        
            set i = 0
            loop
                exitwhen i == smallrocknumber       
                set d = CreateUnit(GetOwningPlayer(u), DummyType, x, y, 0)
                call SetUnitScale( d, .60, .60, .60 )
                call UnitAddAbility(d, &#039;Arav&#039;)
                call UnitRemoveAbility(d, &#039;Arav&#039;)
            
                call SetUnitFlyHeight( d, GetUnitFlyHeight(u), 0.00 )
            
                call UnitApplyTimedLife(d, &#039;BTLF&#039;, 1.00)
                
                call SetUnitMoveSpeed( d, 250.00 )
            
                set dx = x + 250*Cos(I2R(i)*(6.28318/I2R(smallrocknumber))) 
                set dy = y + 250*Sin(I2R(i)*(6.28318/I2R(smallrocknumber)))
            
                call IssuePointOrder( d, &quot;move&quot;, dx, dy )
                call SetUnitFlyHeight( d, 0.00, ( GetUnitFlyHeight(u) / 1.00 ) ) 
                
                set r2 = RockStruct.create(r.level, 3)
                call AttachInt(d, &quot;RockStruct&quot;, r2)
                
                set i = i + 1
            endloop
        
        elseif ( r.stage == 3 ) then //Small rocks have died, now do damge. 
        
            call GroupEnumUnitsInRange(g, x, y, SmallRockAOE, Condition(function DamageFilter))
            loop
                set l = FirstOfGroup(g)
                exitwhen l == null
            
                if(IsUnitEnemy(l, GetOwningPlayer(u))) then            
                    call UnitDamageTarget(u, l, BaseDamage+DamageFactor*r.level, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
                endif
            
                call GroupRemoveUnit(g, l)
            endloop   
        
        
            call DestroyEffect(AddSpecialEffect( &quot;Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl&quot;, x, y ))
        endif
        
        call CleanAttachedVars(u)
        call RockStruct.destroy(r)
        
        call DestroyGroup(g)
        set g = null
        set l = null
        set u = null
        set d = null
    endfunction

    private function EarthShockCast_Conditions takes nothing returns boolean
        if ( GetSpellAbilityId() == AbilCode ) then
            return true
        endif
        return false
    endfunction

    private function EarthShockCast_Actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
    
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
    
        local real dx
        local real dy
    
        local integer i = 0
        local unit d
        local real distance
        local real angle
        
        local real level = I2R(GetUnitAbilityLevel(u, AbilCode))
        
        local RockStruct r
        
    
        loop
            exitwhen i == MaxLargeRockNumber
        
            set distance = GetRandomReal(0,500) 
            set angle = GetRandomReal(0, 6.28318)
            set dx = x + distance*Cos(angle)
            set dy = y + distance*Sin(angle)
        
            set d = CreateUnit(GetOwningPlayer(u), DummyType, dx, dy, 0)
            set r = RockStruct.create(level, 1)
            call AttachInt(d, &quot;RockStruct&quot;, r)
        
            if ( i &gt; 2)and(i &lt; (MaxLargeRockNumber-1) ) then
                call UnitApplyTimedLife( d, &#039;BTLF&#039;, GetRandomReal(0.10, 4.80) )
            elseif ( i &gt; (MaxLargeRockNumber - 2) ) then
                call UnitApplyTimedLife( d, &#039;BTLF&#039;, 4.90 )
            else
                call UnitApplyTimedLife( d, &#039;BTLF&#039;, 0.01 )
            endif
            
            call ShowUnit(d, false)
            
            set i = i + 1
        endloop
    
        set u = null
        set d = null
    endfunction 

    function InitTrig_Earth_Shock takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH )
        call TriggerAddCondition(t, Condition(function DummyDies_Conditions))
        call TriggerAddAction(t, function DummyDies_Actions)
        
        set t = CreateTrigger()        
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t, Condition( function EarthShockCast_Conditions ) )
        call TriggerAddAction( t, function EarthShockCast_Actions )
        
         
        set t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
        call TriggerAddCondition( t, Condition( function EarthShockCast_Conditions ) )
        call TriggerAddAction( t, function EarthShockStop_Actions )
        
        call Preload(&quot;Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl&quot;)
        call Preload(&quot;Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl&quot;)
        

        set t = null
    endfunction

endscope
It's here on my webpage because I ran out of attachment room:
http://shnurple.com/home/dl/Earth%20Shock.w3x

@ Tinkie: that's that same way I learned. That and watching people get schooled for having leaks.
 

Tinki3

Special Member
Reaction score
418
I simply love this spell, now that I've tested it.
Good job, and well done, vypur85 :).

Though, a small suggestion, if I may:
I noticed when the rocks "exploded" into smaller ones,
there was no eyecandy during this event.

Here is a fantastic model that you can use to spice up the explosions.
I highly recommend it.

Now to the code:

In the "Earth Shock" trigger, you create a unit at a leaky location:
Code:
Unit - Create 1 UnitType_EShock_Dummy for (Owner of (Triggering unit)) at [COLOR="Red"](Pt_EShock_TriggerUnitPos offset by (Random real number between 0.00 and 500.00) towards (Random angle) degrees)[/COLOR] facing Default building facing degrees
The offset location also needs to be stored inside a point variable,
and that content needs to be referenced via that variable to prevent leaks.

In the "Dummy Dies" trigger, there is also a similar leak:
Code:
Unit - Order (Last created unit) to Move To [COLOR="Red"](Pt_EShock_DummyPos offset by 250.00 towards ((Real((Integer A))) x (360.00 / (Real(Int_ESchock_RandomSmallRock)))) degrees)[/COLOR]

All else seems fine.
If you are unsure of how to clean leaks properly, you should check out the Tutorial Repository.

***** spell rating.
 

vypur85

Hibernate
Reaction score
803
Updated the spell. Added quite a number of stuff to make implementation even more easier (but this has created quite a number of variables - just for one spell). Fixed the leaks. Wow, I've never knew that those were considered as leaks. Damn it... Need to fix my map that I've been working with.

>Tinki
Actually... To be honest... I don't know how to import models and icons yet :p. Haven't really took the time to learn all those. (Because my intention is to finish my map then learn all those import stuff :p). By the way, I don't think effects can be attached to units with missile model. Not sure. I've tried with other default effects but they just don't show up. Maybe need to create a dummy with the effect (but that'll lag the ability even more, so I've decided to skip that effect thing :)).

>gref
Saw your JASS. Tested the map. But.. Wow... I don't understand anything = =. I really can't read JASS. +R for your effort :). (Not sure whether I've repped you before or not).

Thanks for the comments :). Appreciate them.
 

gref

New Member
Reaction score
33
Seriously though...
As we were saying earlier. The concept for that was awesome. So learn Jass so everything else can be awesome too. --
 

Quauhtli

I have the right to remain silent.
Reaction score
62
Reading the tooltip, would this be an ulti or is the damage good enough for being a normal spell?
 

vypur85

Hibernate
Reaction score
803
Hmmm... It is up to you. Reduce the damage and aoe if you want it to be normal. But it seems that it is more to an ultimate spell. (Similarly to Crystal Maiden of DotA). The rock spawn (large or small) is rather random, so it's balanced in a way.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top