Spell Meteor Shower

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Meteor Shower

MUI/MPI? - Yes
Leakless? - Yes
Lagless? - Not if cast 20+ times ...
Requires? - NewGen Editor and ABCT v2.0 (or higher)


Causes meteors to fall at random locations around the Hero, leaving circles of fire as they hit the ground. Units that stay in the circles will be damaged.
Level 1 - 3 meteors
Level 2 - 6 meteors
Level 3 - 9 meteors

It's just eyecandy and it's very easy to edit. Meteors are special effects and the fire is Flame Strike. Enjoy :)

Code:
JASS:

scope MeteorShower

//Created by cr4xzZz (azwraith_ftL)
//Credits to Cohadar for ABCT.

//  CONFIGURATION MENU !!!
globals 
//Ability raw code
    private constant integer ABILITY_RAW = 'A002'
//Dummy raw code (I use an edited Footman as a dummy, you can copy him
// and put him in your map or if you already have a dummy unit you can skip 
// the copying part and replace this raw code with your dummy raw code)
    private constant integer DUMMY = 'hfoo' 
//Dummy unit ability raw
    private constant integer DUMMY_ABILITY = 'A003'
//Special effect string (Meteor effect)
    private constant string EFFECT = "Units\\Demon\\Infernal\\InfernalBirth.mdl"
//The maximum distance where a meteor can fall, or simply put - AoE
    private constant real DISTANCE = 600.00 
//The degrees where a meteor falls. It's recommended to be 360, so it can fall everywhere (full circle)
    private constant real DEGREES = 360.00
//The time between meteors fall
    private constant real TIME = 0.45
endglobals
//Number of meteors
    private constant function NUMBER_OF_METEORS takes integer level returns integer
        return level * 3
    endfunction

//  END OF CONFIGURATION MENU !!!

private struct Spell
    unit hero
    integer ticks
endstruct

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


private function Callback takes nothing returns boolean
    local Spell data = ABCT_GetData()
    local real deg_real = GetRandomReal(1, DEGREES)
    local real dis_real = GetRandomReal(1, DISTANCE)
    local real x = GetUnitX(data.hero) + dis_real * Cos(deg_real * bj_DEGTORAD)
    local real y = GetUnitY(data.hero) + dis_real * Sin(deg_real * bj_DEGTORAD)
    local location loc = Location(x, y)
    //Create the dummy unit and make it cast Flame Strike
    local unit d = CreateUnitAtLoc(GetOwningPlayer(data.hero), DUMMY, loc, 0.)
    call UnitAddAbility(d, DUMMY_ABILITY)
    call SetUnitAbilityLevel(d, DUMMY_ABILITY, GetUnitAbilityLevel(data.hero, ABILITY_RAW))
    call IssuePointOrderLoc(d, "flamestrike", loc)
    call UnitApplyTimedLife(d, 'BTLF', 3.00)
    //Meteor special effect
    call DestroyEffect(AddSpecialEffectLoc(EFFECT, loc))
    //If ticks is 0 then destroy the timer and stop the loop process
    set data.ticks = data.ticks - 1
    if data.ticks <= 0 then
        call data.destroy()
        return true
    endif
    call RemoveLocation(loc)
    set loc = null
    set d = null
    return false
endfunction
    

private function Actions takes nothing returns nothing
    //Create the struct
    local Spell data = Spell.create()
    
    local unit c = GetTriggerUnit()
    local timer t = CreateTimer()
    local integer level = GetUnitAbilityLevel(c, ABILITY_RAW) 
    
    //Add the struct components
    set data.hero = c
    set data.ticks = NUMBER_OF_METEORS(level)
    call ABCT_Start(function Callback, data, TIME)
    
    set c = null
    set t = null
endfunction

function InitTrig_MeteorShower takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
endfunction
    
endscope

Screenshot: (looks better in-game)
meteorshoweroy0.jpg

EDIT: Fixed code leaks and bugs, added more stuff to the configuration menu
EDIT2: Removed a BJ. Simplified a bit.
 

Attachments

  • [Spell]Meteor Shower.w3x
    77.5 KB · Views: 589

darkRae

Ueki Fan (Ueki is watching you)
Reaction score
173
Then use
tags and/or resize it.
600x450 or 500x375 is a good size.

EDIT:
> local location omg = PolarProjectionBJ(data.loc, GetRandomReal(1,600), (GetUnitFacing(data.cast) + GetRandomReal(1,360)))

lol

Why do you have to add a random real value to the facing angle of unit?
Random Real is random enough.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> Why do you have to add a random real value to the facing angle of unit?
Random Real is random enough.

Ops, I was experimenting some stuff and forgot about that... It's not that critical, right? But if you insist I will update the map
 

darkRae

Ueki Fan (Ueki is watching you)
Reaction score
173
Well, insisting is not what I do, I was just wondering :p
The result is also random anyway.

EDIT:
On second thought, I insist you to resize your screenshot :rolleyes:
And GaLs, you too, remove that picture or do something about it because it's streeetching the page.
 

Cohadar

master of fugue
Reaction score
209
You know when I first saw the picture I thought this could be made without triggers.
You don't get much points for originality but it is coded well and looks decent in game.

PS: make struct private.
 
Reaction score
456
Null the local trigger in the InitTrig function. And instead of the location, you could use reals x and y.

JASS:
    set data.ticks = GetUnitAbilityLevel(c, ABI_RAW) * 3

Those ticks should be a constant function. Also, the distance in the handler actions should be a constant function or a constant real.

When people use your spell, they probably don't want to look through the code to see how to modify the ticks and the distance.
 

Tom Jones

N/A
Reaction score
437
Null the local trigger in the InitTrig function.
Doesn't matter since the trigger will keep it's handle id until the end of the game. However you should pause your timer before destroying it. Destroying a running timer can seriously mess a map up.
 
Reaction score
456
>Doesn't matter since the trigger will keep it's handle id until the end of the game.
Doesn't matter to null it either :).

>Destroying a running timer can seriously mess a map up.
I wonder who actually said that first, because I've never had problem with destroying a running timer.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
> Also, the distance in the handler actions should be a constant function or a constant real.
I tried that. But when I cast the spell the ability picks a random real once and uses it for every meteor (meteors fall only on one location). Or I messed something?
 

darkRae

Ueki Fan (Ueki is watching you)
Reaction score
173
I said 'resize' not 'crop' :p
Well, whatever.
It's neat and very versatile spell anyway.
(it's just a Flame Strike + an SFX)

By versatile I mean you can easily change the whole spell to something new, just same base.
(random Flame Strike -> random Frost Nova -> random Inferno -> random anything)

Very versatile, like my Splitbolts I made a long time ago...
 
Reaction score
456
>Or I messed something?
You could just make a constant function for maximum distance. The constant function would look like this:
JASS:
private constant function MaximumArea takes integer level returns real
    return 600.00 //Can be modified by level, for an example 400.00 + (level * 200.00)
endfunction
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Well, I never used functions that take something... So I'll need a little help here :p

JASS:
private constant function ABI_TICKS takes integer level returns integer
    return level * 3
endfunction

function act takes nothing returns nothing
    ...
    local integer level = GetUnitAbilityLevel(c, ABI_RAW)
    ...
    set data.ticks = ABI_TICKS () //not enough arguments
    ...
endfunction


And it says "not enough arguments passed to function"
 
Reaction score
456
Move the struct below Configuration Menu. Doesn't matter much, but makes it more user-friendly.
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
Thanks a lot for your help too bad I can't +rep you right now.
The interval between meteor falls now can be customized
 

Cohadar

master of fugue
Reaction score
209
>Doesn't matter since the trigger will keep it's handle id until the end of the game.
Doesn't matter to null it either :).
It matters.

>Destroying a running timer can seriously mess a map up.
I wonder who actually said that first, because I've never had problem with destroying a running timer.

That is because you never tried that in a big map.
 
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