• 🏆 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!

Armageddon v 1.0

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This spell is calls effects and after a specific time it deals damage at the effectpoint
so for example every 0.1 seconds it calls a blizzard effect at x-y and after 1 second it deals damage at x-y, so very simple, but you can do various spells with it

JASS:
scope Armageddon initializer Init

    globals
        private constant integer    ABILITY_ID     = 'A003'
        private constant real       AREA_OF_EFFECT = 600
        private constant attacktype ATTACK_TYPE    = ATTACK_TYPE_NORMAL
        private constant real       DAMAGE         = 30
        private constant damagetype DAMAGE_TYPE    = DAMAGE_TYPE_FIRE
        private constant integer    DUMMY_ID       = 'h001'
        private constant real       DURATION       = 8
        private constant string     EFFECT         = "Abilities\\Spells\\Demon\\RainOfFire\\RainOfFireTarget.mdl"
        private constant real       IMPACT_DELAY   = 1
        private constant real       RADIUS         = 80
        private constant real       TIMEOUT        = 0.15
        private constant weapontype WEAPON_TYPE    = WEAPON_TYPE_WHOKNOWS
    endglobals

    globals
        private player    ENUM_PLAYER
        private boolexpr  FILTER
        private group     GROUP
        private hashtable TABLE
    endglobals
    
    private function Targets_Allowed takes nothing returns boolean
        local unit filterUnit = GetFilterUnit(  )
        if GetUnitState( filterUnit, UNIT_STATE_LIFE ) > 0.405 and IsUnitEnemy( filterUnit, ENUM_PLAYER ) and not IsUnitType( filterUnit, UNIT_TYPE_FLYING ) then
            set filterUnit = null
            return true
        endif
        set filterUnit = null
        return false
    endfunction

    private function Damage_Loop takes nothing returns nothing
        local timer t = GetExpiredTimer(  )
        local integer parentKey = GetHandleId(t)
        local unit target
        set ENUM_PLAYER = LoadPlayerHandle( TABLE, parentKey, StringHash( "id" ) )
        set bj_lastCreatedUnit = CreateUnit( ENUM_PLAYER, DUMMY_ID, 0, -256, 0 )
        call GroupEnumUnitsInRange( GROUP, LoadReal( TABLE, parentKey, StringHash( "x" ) ), LoadReal( TABLE, parentKey, StringHash( "y" ) ), RADIUS, FILTER )
        loop
            set target = FirstOfGroup( GROUP )
            exitwhen target == null
            call UnitDamageTarget( bj_lastCreatedUnit, target, DAMAGE, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE )
            call GroupRemoveUnit( GROUP, target )
        endloop
        call DestroyTimer( t )
        set t = null
        set target = null
        call RemoveUnit( bj_lastCreatedUnit )
        call FlushChildHashtable( TABLE, parentKey )
    endfunction

    private function Damage takes unit caster returns nothing
        local timer t = CreateTimer(  )
        local integer parentKey = GetHandleId( t )
        local real offset = GetRandomReal( 100, AREA_OF_EFFECT )
        local real angle = GetRandomReal( 0, 360 ) * bj_PI / 180
        local real x = GetUnitX( caster ) + offset * Cos( angle )
        local real y = GetUnitY( caster ) + offset * Sin( angle )
        call DestroyEffect( AddSpecialEffect( EFFECT, x, y ) )
        call SavePlayerHandle( TABLE, parentKey, StringHash( "id" ), GetOwningPlayer( caster ) )
        call SaveReal( TABLE, parentKey, StringHash( "x" ), x )
        call SaveReal( TABLE, parentKey, StringHash( "y" ), y )
        call TimerStart( t, IMPACT_DELAY, false, function Damage_Loop )
        set t = null
    endfunction

    private function Loop takes nothing returns nothing
        local timer t = GetExpiredTimer(  )
        local integer parentKey = GetHandleId( t )
        local unit caster = LoadUnitHandle( TABLE, parentKey, StringHash( "caster" ) )
        local real duration = LoadReal( TABLE, parentKey, StringHash( "duration" ) ) - TIMEOUT
        if GetWidgetLife( caster ) > 0.405 and duration > 0 then
            call Damage( caster )
            call SaveReal( TABLE, parentKey, StringHash( "duration" ), duration )
        else
            call PauseTimer( t )
            call DestroyTimer( t )
            call FlushChildHashtable( TABLE, parentKey )
        endif
        set t = null
        set caster = null
    endfunction

    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == ABILITY_ID and DURATION > 0
    endfunction

    private function Actions takes nothing returns nothing
        local timer t = CreateTimer(  )
        local integer parentKey = GetHandleId( t )
        local unit caster = GetTriggerUnit(  )
        call SaveUnitHandle( TABLE, parentKey, StringHash( "caster" ), caster )
        call SavePlayerHandle( TABLE, parentKey, StringHash( "id" ), GetOwningPlayer( caster ) )
        call SaveReal( TABLE, parentKey, StringHash( "duration" ), DURATION )
        call TimerStart( t, TIMEOUT, true, function Loop )
        set t = null
        set caster = null
    endfunction

    private constant function True takes nothing returns boolean
        return true
    endfunction

    private function Init takes nothing returns nothing
        local trigger trg = CreateTrigger(  )
        local boolexpr filter = Filter( function True )
        set bj_forLoopAIndex = 0
        loop
            call TriggerRegisterPlayerUnitEvent( trg, Player( bj_forLoopAIndex ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
            set bj_forLoopAIndex = bj_forLoopAIndex + 1
            exitwhen bj_forLoopAIndex == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition( trg, Condition( function Conditions ) )
        call TriggerAddAction( trg, function Actions )

        // globals
        set FILTER = Condition( function Targets_Allowed )
        set GROUP = CreateGroup(  )
        set TABLE = InitHashtable(  )
        // endglobals

        // preload
        call Preload( EFFECT )
        call PreloadStart(  )
        // endpreload

        set trg = null
        call DestroyBoolExpr( filter )
        set filter = null
    endfunction

endscope

Keywords:
armageddon, fire, explosion
Contents

Harry Potter Wizard War (Map)

Reviews
7 November 2015 Bribe: Rejecting due to the status of this resource being "needs fix" for years. 17:52, 17th Jan 2010 TriggerHappy: This idea has been done over and over again, and it looks just like an extremely overdone effect. Even with...

Moderator

M

Moderator

7 November 2015
Bribe: Rejecting due to the status of this resource being "needs fix" for years.

17:52, 17th Jan 2010
TriggerHappy:

This idea has been done over and over again, and it looks just like an extremely overdone effect. Even with the code being perfect (which it's not) I can not approve this based on the originality factor, since this has almost none of it.

PM me if you feel different.
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
See isn't the usage of private variables and scope/libraries better than those ugly name vars?

Anyway 1 extremely helpfull tip:

When you write your functions please put spaces between them:
JASS:
// white space here please
private function bla takes nothing returns nothing
...
endfunction
// white space here please
private function bla2 takes nothing returns nothing
...
endfunction
// white space here please

EDIT:

[Please use TimerUtils so you recycle timers, other than that it seems fine on the first look.

JASS:
call TriggerRegisterPlayerUnitEvent

Just replace it by AnyUnitEventBJ, no need to inline it.

Also may be my opinion only but people tend to hate BJ loop integers since a GUI spell can use them and cause problems, it is a global integer it can screw up your spell.

The timer counter is too low, put it on 0.02
 
Level 5
Joined
Dec 8, 2008
Messages
102
thanks for comments, but pls

@ kingz, i did spaces between functions, didnt i? (i looked at the code)
and i inlined it only for the reason cause else i would leak 16x null boolexpr
yeah, even a predefined boolexpr leaks :D

and yeah, implement timerutils next version if u want...

and this forloopA thingy, it will never cause errors if used correct...
the only bug you mean is with waits in a gui loop or in a loop in which loads of groups are created
 
Top