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

[JASS] Explosive shoot & Five Sword

  • Like
Reactions: Losam
First: Five Sword absolute not new by me, just previous version was made with trigger sleep, in this version i fixed few thing like: i use timer, swords are in same height, i use dummy unit for illustrate the hp leech

Second: Maybe you see many attachments but acctually u can try it, i think its a bit pump up the spell effect

Third - Importing:
- If u want use them u must export the imported files from this demo map
- copy /paste the JumpParabola function from map header, the 3 dummy unit, 2 ability and 3 triggers (2 spell trigger and unit indexer if u dont have it yet)
- variables: p = point variable, Spell_Table = hashtable

Four: i choosed spell pack type because i dont know what could be the better option for 2 spell :/

Code:

(Five) Magical Sword

JASS:
function Magical_Sword_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer i
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local unit ut = LoadUnitHandle(udg_Spell_Table, id, 2)
    local unit dummy
    local real x1
    local real y1
    local real x2
    local real y2
    local real z
    local real hp
    local real spd
    local lightning l
    local real c = LoadReal(udg_Spell_Table, id, 6)

    if c < 18 and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(ut, UNIT_TYPE_DEAD) then
        if c == 0 then
            call SaveReal(udg_Spell_Table, id, 9, 0.05)
            set z = LoadReal(udg_Spell_Table, id, 4)
            set i = 0
            loop
                exitwhen i > 4
                set dummy = LoadUnitHandle(udg_Spell_Table, id, i + 10)
                set x1 = GetUnitX(dummy)
                set y1 = GetUnitY(dummy)
                if i == 4 then
                    set dummy = LoadUnitHandle(udg_Spell_Table, id, 10)

                else
                    set dummy = LoadUnitHandle(udg_Spell_Table, id, i + 11)
                endif
                set x2 = GetUnitX(dummy)
                set y2 = GetUnitY(dummy)
                set l = AddLightningEx("DRAL", true, x1, y1, z, GetUnitX(ut), GetUnitY(ut), z)
                call SaveLightningHandle(udg_Spell_Table, id, 20 + i, l)
                call SetLightningColor(l, 1, 0, 0, 1)
                set l = AddLightningEx("LEAS", true, x1, y1, z, x2, y2, z)
                call SaveLightningHandle(udg_Spell_Table, id, 30 + i, l)
                call SetLightningColor(l, 0, 0, 1, 1)
                set dummy = CreateUnit (Player(15), 'ewsp', GetUnitX(ut), GetUnitY(ut), 0)
                call UnitAddAbility(dummy, 'Aloc' )
                call SetUnitPathing(dummy, false)
                call SetUnitScale(dummy, 0.5, 0.5, 0.5)
                call UnitAddAbility(dummy, 'Amrf' )
                call UnitRemoveAbility(dummy, 'Amrf' )
                call UnitRemoveAbility( dummy, 'Amov' )
                call SaveUnitHandle(udg_Spell_Table, id, i + 15, dummy)
                set i = i + 1
            endloop
            set l = null
            set dummy = null
        elseif c > 0 and c < 16 then

            if c == R2I(c + 1) then
                set hp = LoadReal(udg_Spell_Table, id, 7)
                call SetWidgetLife(u, GetWidgetLife(u) + hp)
                call SetWidgetLife(ut, GetWidgetLife(ut) - hp)
            endif
            set i = 0
            loop
                exitwhen i > 4
                set hp = c - R2I(c)
                set x1 = GetUnitX(ut)
                set y1 = GetUnitY(ut)
                set x2 = x1 + (hp * 300) * Cos(bj_DEGTORAD * 72 * i)
                set y2 = y1 + (hp * 300) * Sin(bj_DEGTORAD * 72 * i)
                call MoveLocation(udg_p, x2, y2)
                set z = LoadReal(udg_Spell_Table, id, 4) - GetLocationZ(udg_p)
                set dummy = LoadUnitHandle(udg_Spell_Table, id, i + 15)
                call SetUnitFlyHeight( dummy, z - 25, 0 )
                call SetUnitPosition( dummy, x2, y2)

                set i = i + 1
            endloop
        elseif c == 16 or c == 16.05 then
            call SaveReal(udg_Spell_Table, id, 9, 1)
            call SaveReal(udg_Spell_Table, id, 6, 16)
            set c = 16
            set i = 0
            set spd = LoadReal(udg_Spell_Table, id, 8)
            loop
                exitwhen i > 4
                call SetUnitFlyHeight( LoadUnitHandle(udg_Spell_Table, id, i + 10), 1500, spd * 4 )
                call DestroyLightning(LoadLightningHandle(udg_Spell_Table, id, 20 + i))
                call DestroyLightning(LoadLightningHandle(udg_Spell_Table, id, 30 + i))
                call RemoveUnit (LoadUnitHandle(udg_Spell_Table, id, i + 15))

                set i = i + 1
            endloop
            call UnitAddAbility( ut, 'Amrf' )
            call UnitRemoveAbility( ut, 'Amrf' )
            call SetUnitFlyHeight( ut, 0, spd )

        elseif c == 17 then
            call PauseUnit( ut, false )
            call SetUnitInvulnerable( ut, false )
            call DestroyEffect(LoadEffectHandle(udg_Spell_Table, id, 5))


        endif

        call SaveReal(udg_Spell_Table, id, 6, c + LoadReal(udg_Spell_Table, id, 9))
        call TimerStart(t, LoadReal(udg_Spell_Table, id, 9), false, function Magical_Sword_Timer)
    else
        set i = 0
        loop
            exitwhen i > 4
            call UnitApplyTimedLife( LoadUnitHandle(udg_Spell_Table, id, i + 10), 'BUan', 1 )
            set i = i + 1
        endloop
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
    endif
    set t = null
    set u = null
    set ut = null
endfunction

function Trig_Magical_Sword_Actions takes nothing returns nothing
    local timer t
    local integer id
    local unit u
    local unit ut
    local unit dummy
    local real x
    local real y
    local real nx
    local real ny
    local real spd
    local real hpdrain
    local player p
    local real z
    local real z2
    local real h1
    local real h2
    local integer i
    local integer c
    local real interval

    if GetSpellAbilityId() == 'A000' then
        set t = CreateTimer()
        set id = GetHandleId(t)
        set u = GetTriggerUnit()
        set ut = GetSpellTargetUnit()
        set x = GetUnitX(ut)
        set y = GetUnitY(ut)
        set spd = 100
        set hpdrain = GetWidgetLife(ut) / 100.00 * GetUnitAbilityLevel(u, GetSpellAbilityId())
        set p = GetTriggerPlayer()
        set h1 = 330
        set h2 = 320
        set i = 0
        set c = 0
        set interval = 1
  
        call MoveLocation(udg_p, x, y)
        set z = GetLocationZ(udg_p)

        call SaveUnitHandle(udg_Spell_Table, id, 1, u)
        call SaveUnitHandle(udg_Spell_Table, id, 2, ut)
        call SaveReal(udg_Spell_Table, id, 3, h1)
        call SaveReal(udg_Spell_Table, id, 4, h2 + z)
        call SaveEffectHandle(udg_Spell_Table, id, 5, AddSpecialEffectTarget("Abilities\\Spells\\Human\\DivineShield\\DivineShieldTarget.mdl", ut, "origin"))
        call SaveReal(udg_Spell_Table, id, 6, c)
        call SaveReal(udg_Spell_Table, id, 7, hpdrain)
        call SaveReal(udg_Spell_Table, id, 8, spd)
        call SaveReal(udg_Spell_Table, id, 9, interval)
 
        call SetUnitInvulnerable( ut, true )
        call PauseUnit( ut, true )
        loop
            exitwhen i > 4
            set nx = x + 300 * Cos(bj_DEGTORAD * i * 72)
            set ny = y + 300 * Sin(bj_DEGTORAD * i * 72)
            set dummy = CreateUnit (p, 'h003', nx , ny, 0)
            call UnitAddAbility(dummy, 'Amrf' )
            call UnitRemoveAbility(dummy, 'Amrf' )
            call MoveLocation(udg_p, nx, ny)
            set z2 = GetLocationZ(udg_p)
            call SetUnitFlyHeight( dummy, h1 + z - z2, spd * 4 )
            call SaveUnitHandle(udg_Spell_Table, id, i + 10, dummy)
            set i = i + 1
        endloop

        call UnitAddAbility(ut, 'Amrf' )
        call UnitRemoveAbility(ut, 'Amrf' )
        call SetUnitFlyHeight( ut, h2, spd )

        call TimerStart(t, 3.5, false, function Magical_Sword_Timer)

        set u = null
        set ut = null
        set dummy = null
        set p = null
    endif
endfunction

//===========================================================================
function InitTrig_Magical_sword takes nothing returns nothing
    set gg_trg_Magical_sword = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Magical_sword, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Magical_sword, function Trig_Magical_Sword_Actions )
endfunction

Explosive Shoot

JASS:
function ExplosiveMissileTimer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer id = GetHandleId(t)
    local integer cv
    local unit u = LoadUnitHandle(udg_Spell_Table, id, 1)
    local unit arrow = LoadUnitHandle(udg_Spell_Table, id, 7)
    local unit pu
    local integer part = LoadInteger(udg_Spell_Table, id, 10)
    local real x = GetUnitX(arrow)
    local real y = GetUnitY(arrow)
    local real ang = LoadReal(udg_Spell_Table, id, 2)
    local real nx = x + 10 * Cos(ang)
    local real ny = y + 10 * Sin(ang)
    local real distance = LoadReal(udg_Spell_Table, id, 3) + 10
    local real maxdistance = LoadReal(udg_Spell_Table, id, 4)
    local real dmg
    local player p
    if distance < maxdistance then
        call SaveReal(udg_Spell_Table, id, 3, distance)
        call SetUnitPosition (arrow, nx , ny)
        call SetUnitFlyHeight(arrow, JumpParabola(distance, maxdistance, LoadReal(udg_Spell_Table, id, 8)), 0 )
        if part == 0 then
            call SaveInteger(udg_Spell_Table, id, 11, LoadInteger(udg_Spell_Table, id, 11) + 1)
            call SetUnitFacing(arrow, bj_RADTODEG * 20 * LoadInteger(udg_Spell_Table, id, 11))
        endif
        call TimerStart(t, 0.03, false, function ExplosiveMissileTimer)

    elseif part == 0 then
        call SaveInteger(udg_Spell_Table, id, 10, 1)
        call DestroyEffect(AddSpecialEffect ("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", nx , ny))
        call DestroyEffect(AddSpecialEffect ("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", nx , ny))
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        set ang = Atan2(ny - y, nx - x)
        set distance = SquareRoot((nx - x) * (nx - x) + (ny - y) * (ny - y))
        call RemoveUnit(arrow)
        call SaveReal(udg_Spell_Table, id, 2, ang)
        call SaveReal(udg_Spell_Table, id, 3, 0)
        call SaveReal(udg_Spell_Table, id, 4, distance)
        call SaveReal(udg_Spell_Table, id, 5, x)
        call SaveReal(udg_Spell_Table, id, 6, y)
        set arrow = CreateUnit(GetOwningPlayer(u), 'h001', x, y, bj_RADTODEG * ang)
        call UnitAddAbility(arrow, 'Amrf' )
        call UnitRemoveAbility(arrow, 'Amrf' )
        call SaveUnitHandle(udg_Spell_Table, id, 7, arrow)
        call SetUnitFacing(u, bj_RADTODEG * ang)
        call SetUnitAnimation( u, "attack" )
        call SaveReal(udg_Spell_Table, id, 8, 1)
        call SaveDestructableHandle(udg_Spell_Table, id, 9, CreateDestructable ('LTex', nx, ny, 0, 1, 1))
        call TimerStart(t, 0.5, false, function ExplosiveMissileTimer)

    elseif part == 1 then
        call PauseUnit(u, false)
        call DestroyEffect(AddSpecialEffect ("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", nx , ny))
        call DestroyEffect(AddSpecialEffect ("ShrapnelShards.mdl", nx , ny))
        call GroupEnumUnitsInRange(udg_UG, nx, ny, 250, null)
        set p = GetOwningPlayer(u)
        set dmg = LoadReal(udg_Spell_Table, id, 9)
        if dmg > 0 then
            loop
                set pu = FirstOfGroup(udg_UG)
                exitwhen (pu==null)
                if IsUnitEnemy(pu, p) then
                    call UnitDamageTarget(u, pu, dmg, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
                endif
                call GroupRemoveUnit(udg_UG, pu)
            endloop
        endif
        call RemoveDestructable (LoadDestructableHandle(udg_Spell_Table, id, 9))
        call KillUnit(arrow)
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_Spell_Table, id)
    endif

    set t = null
    set u = null
    set pu = null
endfunction

function Trig_ExplosiveMissile_Actions takes nothing returns nothing
    local unit u
    local timer t
    local integer id
    local integer aid
    local real x1
    local real y1
    local real x2
    local real y2
    local real ang
    local real distance
    local real curve
    local integer alv
    local real dmg

    if GetSpellAbilityId() == 'A001' then
        set u = GetTriggerUnit()
        set t = CreateTimer()
        set id = GetHandleId(t)
        set aid = GetSpellAbilityId()
        set x1 = GetUnitX(u)
        set y1 = GetUnitY(u)
        set x2 = GetSpellTargetX()
        set y2 = GetSpellTargetY()
        set ang = Atan2(y2 - y1, x2 - x1)
        set distance = SquareRoot((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
        set curve = 2
        set alv = GetUnitAbilityLevel(u , GetSpellAbilityId())
        set dmg = 100 * alv + alv * GetHeroAgi(u, true)

        if distance > 150 then

            call SaveUnitHandle(udg_Spell_Table, id, 1, u)
            call SaveReal(udg_Spell_Table, id, 2, ang)
            call SaveReal(udg_Spell_Table, id, 3, 0)
            call SaveReal(udg_Spell_Table, id, 4, distance)
            call SaveReal(udg_Spell_Table, id, 5, x1)
            call SaveReal(udg_Spell_Table, id, 6, y1)
            set u = CreateUnit(GetTriggerPlayer(), 'h000', x1, y1, bj_RADTODEG * ang)
            call UnitAddAbility(u, 'Amrf' )
            call UnitRemoveAbility(u, 'Amrf' )
            call SaveUnitHandle(udg_Spell_Table, id, 7, u)
            call SaveReal(udg_Spell_Table, id, 8, curve)
            call SaveReal(udg_Spell_Table, id, 9, dmg)
            call SaveInteger(udg_Spell_Table, id, 10, 0)
            call SaveInteger(udg_Spell_Table, id, 11, 0)
            call IssueImmediateOrder( GetTriggerUnit(), "stop" )
            call PauseUnit(GetTriggerUnit(), true)
            call TimerStart(t, 0.1, false, function ExplosiveMissileTimer)
        else
            call UnitRemoveAbility(u, aid )
            call UnitAddAbility(u, aid )
            call DisplayTextToPlayer( GetTriggerPlayer(), 0, 0, "Target is |cffffff00too close|r, need atleast 250 range!" )
        endif
        set u = null
        set t = null
    endif
endfunction

//===========================================================================
function InitTrig_Explosive_shoot takes nothing returns nothing
    set gg_trg_Explosive_shoot = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Explosive_shoot, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Explosive_shoot, function Trig_ExplosiveMissile_Actions )
endfunction
Screenshoots
http://shadowvzs87.uw.hu/1.jpg
http://shadowvzs87.uw.hu/2.jpg

credit & thanks:
pWn3d - sunfire missile model
WILL THE ALMIGHTY - shard explosion model
sPy - Exploding Barrel model
M0rbid - Exploding Barrel icon
stefanstan95 - Frostmourne icon
shamanyouranus - Frostmourne sword model
Bribe - Unit indexer

Keywords:
explosive, effect, barrel, missile, archer, five, sword, lightnings, life, drain
Contents

Just another Warcraft III map (Map)

Reviews
6 April 2012 Bribe: Looks pretty good for plain JASS. I recommend using "local trigger t" instead of these global triggers. I recommend making importing instructions. Yes it is pretty simple but things like making sure the hashtable is there are...

Moderator

M

Moderator

6 April 2012
Bribe: Looks pretty good for plain JASS. I recommend using "local trigger t" instead of these global triggers.

I recommend making importing instructions. Yes it is pretty simple but things like making sure the hashtable is there are very important.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Totally un-configurable. Make it MUCH more configurable. the only thing thats configurable is the ability to trigger! Ex.

1) Distance (based on hero level)
2) Damage (based on hero level)
3) Projectiles
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
Totally un-configurable. Make it MUCH more configurable. the only thing thats configurable is the ability to trigger! Ex.

1) Distance (based on hero level)
2) Damage (based on hero level)
3) Projectiles

1. its configurable in object editor the casting range but make it hero level depend is useless, sorry but really no point in that
2. it is based on agility, agility increased by items/levels -> more configurable than hero level
(also i make every damage based on unit level on my map, so no point in make ability damage to level depend, stat depency is better)
3. u can change projectile model in object editor

Seriously i agree if u say "more configurable special effect", "curve" ....
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
1. its configurable in object editor the casting range but make it hero level depend is useless, sorry but really no point in that
2. it is based on agility, agility increased by items/levels -> more configurable than hero level
(also i make every damage based on unit level on my map, so no point in make ability damage to level depend, stat depency is better)
3. u can change projectile model in object editor

Seriously i agree if u say "more configurable special effect", "curve" ....

1) Whatever...... Stretching to unit is ugly
2) This is the only UnitDamageTarget in the entire code

call UnitDamageTarget(u, pu, 100.00, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif

and that deals 100damage. All other damage is object editor, and is ugly. And if you say that agility is more configurable than hero level, its not at all. Make a function that gets called when your about to deal damage and use the unit caster as a parameter. Than its 100% confiurable
 
Level 10
Joined
Aug 21, 2010
Messages
316
I do not understand how the damage here is based on agility

Here you set the damage and it's ok
JASS:
local real dmg = 100 * alv + alv * GetHeroAgi(u,true)

but then you put here only the value of 100
JASS:
call UnitDamageTarget(u, pu, 100.00, true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)

seems you missed something here
perhaps this
JASS:
call SaveReal(udg_Spell_Table, id, some value, dmg)
JASS:
local real dmg=LoadReal(udg_Spell_Table, id, some value)
JASS:
call UnitDamageTarget(u, pu, [dmg], true, false, ATTACK_TYPE_HERO, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
that right, i have no ideea how i missed that :D
And if you say that agility is more configurable than hero level, its not at all.

sorry but i dont agree with this, example in my map (like in alot rpg map) i use stating, and could be funny when a lv100 archer deal same damage with abilities even he stated to HP, than other archer who also lv 100 but he put all point to agility...

damage is fixed here, whatever i think setting damage in 1st trigger enough because then every configurable thing could be place there.

Stretching to unit is ugly
i dont got what u mean with this, it isnt streched
 

Attachments

  • 1_explosiveArrow.w3x
    83.8 KB · Views: 84
sorry but i dont agree with this, example in my map (like in alot rpg map) i use stating, and could be funny when a lv100 archer deal same damage with abilities even he stated to HP, than other archer who also lv 100 but he put all point to agility...

That's besided the point. Configurability means that I can easily adjust the spell to the needs of my map, where I for example want it to be depending on the ability level and with blue effects. If I have to go through the code, searching for the point where the damage is dealt and where effects are attached is annoying and difficult if the code is not well written. If I can, on the other hand, easily see all relevant data in the gloabals block and be sure that I only have to write what I want there to change what the spell does, then it is easily configurable.
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
That's besided the point. Configurability means that I can easily adjust the spell to the needs of my map, where I for example want it to be depending on the ability level and with blue effects. If I have to go through the code, searching for the point where the damage is dealt and where effects are attached is annoying and difficult if the code is not well written. If I can, on the other hand, easily see all relevant data in the gloabals block and be sure that I only have to write what I want there to change what the spell does, then it is easily configurable.

ok but this isnt vjass where u can use globals, exclude the ugly gui variables (udg_ things), also all thing allways configurable in action part, everything is in action fuction local parts
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
you dont need vjass to initialize globals... just do a function sorta like this

function ObtainData takes integer index returns real
if index = 0 then
return 500.00 (range)
endif
if index = 1 then
return 50 x GetHeroLevel(TriggeringUnit) // damage
endif
endfunction
 
Level 17
Joined
Nov 13, 2006
Messages
1,814
@update
- fixed the leak at sword
- removed condition function, i use action only
- used vjass lang. aligner

you dont need vjass to initialize globals... just do a function sorta like this

function ObtainData takes integer index returns real
if index = 0 then
return 500.00 (range)
endif
if index = 1 then
return 50 x GetHeroLevel(TriggeringUnit) // damage
endif
endfunction

1. its point target spell, so dont have a fixed distance for it
2. why i already mentioned the i dont like the hero level part also i dont got why need for this a function call when condition was also a useless function call?
 
Last edited:
Top