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

Aeromancer Spells v1.4

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Some simple air themed spells i made.
Spells don't follow JESP standard but i tried to add some decent comments.

Forked Chain Lightning (GUI)
-The combination of chan lightning and forked lightning.
  • Forked Chain
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Forked Chain Lightning
    • Actions
      • Set tempUnit = (Target unit of ability being cast)
      • Set tempPoint2 = (Position of tempUnit)
      • Set tempPoint = (Position of (Triggering unit))
      • Set tempInt = 0
      • -------- - --------
      • -------- Cast Chain Lightning on target --------
      • Unit - Create 1 caster for (Owner of (Triggering unit)) at tempPoint facing Default building facing degrees
      • Unit - Add dummy Forked Chain Lightning to (Last created unit)
      • Unit - Set level of dummy Forked Chain Lightning for (Last created unit) to (Level of Forked Chain Lightning for (Triggering unit))
      • Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning tempUnit
      • -------- - --------
      • -------- Cast Chain Lightning on random targets around target --------
      • Set tempGroup = (Units within 400.00 of tempPoint2 matching ((Owner of (Matching unit)) Equal to (Owner of tempUnit)))
      • Unit Group - Pick every unit in tempGroup and do (Actions)
        • Loop - Actions
          • If (tempInt Equal to 0) then do (Unit Group - Remove tempUnit from (Last created unit group)) else do (Do nothing)
          • Set tempInt = (tempInt + 1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (((Level of Forked Chain Lightning for (Triggering unit)) x 3) - ((Level of Forked Chain Lightning for (Triggering unit)) - 1)) Greater than or equal to tempInt
            • Then - Actions
              • Unit - Create 1 caster for (Owner of (Triggering unit)) at tempPoint facing Default building facing degrees
              • Unit - Add dummy Forked Chain Lightning to (Last created unit)
              • Unit - Set level of dummy Forked Chain Lightning for (Last created unit) to (Level of Forked Chain Lightning for (Triggering unit))
              • Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning (Picked unit)
            • Else - Actions
      • Custom script: call DestroyGroup (udg_tempGroup)
      • Custom script: call RemoveLocation (udg_tempPoint)
      • Custom script: call RemoveLocation (udg_tempPoint2)
Static Charge (JASS)
-Charge an enemy for x seconds, then all units around the target get shocked.
-My first jass spell i made, i find the idea not bad but the code is horrible, if there is request for a better vJASS version then i will make one.
JASS:
//==========================================================
// Static Charge
// Made by Darkwatcher
//
// My first jass spell i made: idea is good (IMO), code sucks very hard
//
// To use: copy the Static Charge, Static Charge (dummy) and the static charge buff into you map.
// Copy this trigger into you map
// Check all rawcodes matching the abilities and buff.
//
//==========================================================
function Trig_Static_Charge_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction

//Cast the forked lightning
function Cast_Forked takes unit caster, unit target returns nothing
    local unit dummy = CreateUnitAtLoc( GetOwningPlayer(caster), 'h001', GetUnitLoc(target), 270 )
    call UnitAddAbility( dummy, 'A001')
    call SetUnitAbilityLevel( dummy, 'A001', GetUnitAbilityLevel( caster, 'A000') )
    call IssueImmediateOrder( dummy, "fanofknives")
    set dummy = null
endfunction    

//Run Cast_Forked when buff is gone from target
function End_Channeling takes unit caster, unit target returns nothing     
    local timer t = CreateTimer()
    local real timeRemaining
    call TimerStart(t, 5.00-GetUnitAbilityLevel(caster, 'A000'), false, null)
    call PolledWait( 0.10 )
    loop
        exitwhen ( (GetUnitAbilityLevel(target, 'B000') > 0) == false )
        call PolledWait(0.10)
    endloop
    if( TimerGetRemaining(t) <= 0 ) then
        call Cast_Forked(caster, target)
    endif
    call DestroyTimer(t)
    set t = null
endfunction

//Check target having the charged buff.
function Already_Buff takes nothing returns nothing
    local unit target = GetSpellTargetUnit()
    if ( GetUnitAbilityLevel(target, 'B000') > 0) then
        // Target already getting charged, immediatly release this charge
        call Cast_Forked(GetTriggerUnit(), target)
        call TriggerSleepAction( 0.10 )
        call IssueImmediateOrder( GetTriggerUnit(), "stop" )
    else
        call End_Channeling(GetTriggerUnit(), target) 
    endif   
endfunction

//===========================================================================
function InitTrig_Static_Charge takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Trig_Static_Charge_Conditions ) )
    call TriggerAddAction( t, function Already_Buff )
endfunction

Storm,earth and fire (vJASS)
-A spell with 4 second casting time, when casting you hear the shaman ready sound., then a flame pillar, an eathquake and a lightning storm are created at the location
JASS:
scope SEF initializer Init
//*==============================================================
//*  Storm, earth and fire
//*  Made by DarkWatcher
//*  
//*  Requirements: None (except JNGP ofc)
//*
//*  Only works for patch 1.23b+
//*  
//*  How to use:
//*  1)Copy this trigger into you map
//*  2)Copy the Storm,earth and fire, monsoon(dummy) and EarthQuake(dummy) abilities into your map
//*  3)Check spell rawcodes matching ones below
//*  4)Set the DUMMY field to your dummy rawcode
//*==============================================================
    globals
        private constant integer DUMMY = 'h001'
        private constant integer SPELLID = 'A004'
        private constant integer MONSOONID = 'A007'
        private constant integer EQID = 'A005'
    endglobals   
    
    //==========================================================
    
    globals
        private hashtable hT
    endglobals
    
    private struct Spell
        real X
        real Y
        player id
        
        static method create takes real x, real y, player id returns Spell
            local Spell spell = Spell.allocate()
            set spell.X = x
            set spell.Y = y
            set spell.id = id
            return spell
        endmethod
    endstruct      
    
    private function Cond takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction
    
    private function Actions takes nothing returns nothing
        local Spell spell = Spell.create( GetSpellTargetX(), GetSpellTargetY(), GetOwningPlayer(GetTriggerUnit()))
        
        //Play storm,earth and fire
        local sound s = CreateSound("Units\\Orc\\Shaman\\ShamanReady1.wav", false, false, true, 10, 10, "")
        call SetSoundPosition(s, GetSpellTargetX(), GetSpellTargetY(), 0)
        call SetSoundVolume(s, 127)
        call StartSound(s)
        call KillSoundWhenDone(s)
        set s = null
        
        call SaveInteger(hT, 0, GetHandleId(GetTriggerUnit()), spell)
    endfunction
    
    private function Actions2 takes nothing returns nothing
        local Spell spell = LoadInteger(hT, 0, GetHandleId(GetTriggerUnit()))
        
        local unit dummy = CreateUnit( spell.id, DUMMY, spell.X, spell.Y, 270 )
        call UnitAddAbility(dummy, MONSOONID)
        call IssuePointOrder( dummy, "monsoon", spell.X, spell.Y)
        
        set dummy = CreateUnit( spell.id, DUMMY, spell.X, spell.Y, 270 )
        call UnitAddAbility( dummy, EQID)
        call IssuePointOrder( dummy, "earthquake", spell.X, spell.Y)
        
        set dummy = null
    endfunction
    
    private function Actions3 takes nothing returns nothing
        local Spell spell = LoadInteger(hT, 0, GetHandleId(GetTriggerUnit()))
        call TriggerSleepAction(0.10)
        call spell.destroy()
    endfunction

    function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( t, Condition( function Cond ) )
        call TriggerAddAction( t, function Actions )
               
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_FINISH )
        call TriggerAddCondition( t, Condition( function Cond ) )
        call TriggerAddAction( t, function Actions2 )
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
        call TriggerAddCondition( t, Condition( function Cond ) )
        call TriggerAddAction( t, function Actions3 )
        
        set hT = InitHashtable()
    endfunction
endscope

Force Punch (vJASS)
-A single targeted knockback that uses Rising Dusk's knockback system
-Targets further away take less damage and are less knockbacked than close targets.
JASS:
scope ForcePunch initializer Init
//*==================================================================
//*  ForcePunch
//*  Made by DarkWatcher
//*
//*  Requires:
//*      -KnockBack(RisingDusk)
//*         -TerrainPathability
//*         -UnitIndexingUtils
//*         -LastOrder
//*         -GroupUtils
//*
//*  How to use:
//*  1)Copy this trigger into you map
//*  2)Copy the Force Punch ability into your map
//*  3)Check spell rawcode matching the one below
//*  4)Copy the libraries in the libraries Category
//*
//*==================================================================
    globals
        private constant integer SPELLID = 'A003'
        //This must be same as range in object editor
        private constant real RANGE = 700
        //Knockback time in seconds
        private constant real TIME = 1.00
    endglobals
    
    //The maximum damage of the spell, when target is next to the caster
    private constant function MAXDAMAGE takes integer level returns real
        return 100.00*level
    endfunction
    
    //The maximum knockback distance of the spell, when target is next to the caster
    private constant function MAXPUSH takes integer level returns real
        return 300.00 + 400.00*level
    endfunction
    
    //==============================================================
    
    public function distanceBetweenUnits takes unit u1, unit u2 returns real
        return SquareRoot((GetUnitX(u1) - GetUnitX(u2))*(GetUnitX(u1) - GetUnitX(u2)) + (GetUnitY(u1) - GetUnitY(u2))*(GetUnitY(u1) - GetUnitY(u2)))
    endfunction
    
    public function angleBetweenUnits takes unit u1, unit u2 returns real
        return bj_RADTODEG * Atan2((GetUnitY(u2) - GetUnitY(u1)), (GetUnitX(u2) - GetUnitX(u1)))
    endfunction
        
    private function Actions takes nothing returns nothing
        local real distance = distanceBetweenUnits(GetTriggerUnit(), GetSpellTargetUnit())
        local real angle = angleBetweenUnits(GetTriggerUnit(), GetSpellTargetUnit())
        local real damage = 0.5*MAXDAMAGE(GetUnitAbilityLevel(GetTriggerUnit(), SPELLID))*(2 - distance/RANGE)
        local real kbDistance = 0.5*MAXPUSH(GetUnitAbilityLevel(GetTriggerUnit(), SPELLID))*(2 - distance/RANGE)
        //Ally units don't get damaged
        if IsUnitEnemy(GetSpellTargetUnit(), GetOwningPlayer(GetTriggerUnit())) then
            call UnitDamageTarget(GetTriggerUnit(), GetSpellTargetUnit() , damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
        endif
        call KnockbackTarget(GetTriggerUnit(), GetSpellTargetUnit(), angle, kbDistance, TIME*kbDistance, true, true, true)
    endfunction

    private function Cond takes nothing returns boolean
        return GetSpellAbilityId() == SPELLID
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Condition(function Cond))
        call TriggerAddAction(t, function Actions)
    endfunction
endscope


V1.4
-The struct instance in the SEF trigger doesn't leak anymore when spell is not finished.

V1.3
-The struct instance in the SEF trigger is now destroyed after spell is cast

V1.2
-esc now really resets mana and cd's
-The SEF sound is now MUI

V1.1
-Removed pointer leak in Static Charge
-Forked Chain Lightning: Changed (casting unit) into (triggering unit)
-Forked Chain Lightning: Removed 2 point leaks and a group leak.
-You cooldowns and mana are reseted when you press esc.

V1.0
-Initial release




Keywords:
Aeromancer, air spells, lightning, elemental, element
Contents

Aeromancer Spells v1.4 (Map)

Reviews
21:46, 28th Dec 2009 TriggerHappy: Remove or heavily optimize the Static Charge spell, the coding is a complete mess. I don't even know where to start. Furthermore, it looks to simple. The rest are decent from a quick glance, however I will not...

Moderator

M

Moderator

21:46, 28th Dec 2009
TriggerHappy:

Remove or heavily optimize the Static Charge spell, the coding is a complete mess. I don't even know where to start. Furthermore, it looks to simple. The rest are decent from a quick glance, however I will not review them until I know that the author of this spell is still active and is willing to update/remove Static Charge.
 
Level 15
Joined
Jul 6, 2009
Messages
889
Forked Chain Lightning is not really original.
local unit dummy = null
Why not just put local unit dummy = CreateUnit blahblah.

Well, your sound is not MUI, it will only play one at a time...... so if its already playing.... use CreateSound()...

Your testmap is irittating, when your spells have cooldown, people have to wait. Remove it or add an ESC restore command.
 
Last edited:
Top