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

Spirit Bombs v1.3[Kingz]

Well my very first vJass spell^^
May not be the most original spell or the most efficent spell but i wanted to practice vJass and the best way is to make a spell^^


v1.0 release
v1.1 removed object leaks in the InitSB function
v1.2 fixed things that moderator suggested,indented the code properly,removed paladon's general system from the testmap as it were causing issues with compiling and testing.
v1.3 removed location usage in the triggers actions

Please give feedback.

JASS:
//*******************************************************************************
//                       Spirit Bombs spell by Kingz                            *
//                               Notes:                                         *
//                  My verry first spell made in vJass                          *
//                                                                              *
//                              Requirements:                                   *
//                            A point based spell                               *
//                   dummy.mdx model which is featured in this map              *
//                            The dummy unit                                    *
//                             JassNewGenPack                                   *
//*******************************************************************************
                    
scope SpiritBombs initializer InitSB
//**********************************************
//Settings - All of the spell settings are here*
//**********************************************
globals
 private constant integer SpellID = 'A000' //spell ID
 private constant integer DummyID = 'e000' //dummy unit ID
 private constant string MissileEff = "Abilities\\Spells\\Other\\AcidBomb\\BottleMissile.mdl" //missile art
 private constant string ImpactEff = "Abilities\\Spells\\Undead\\OrbOfDeath\\OrbOfDeathMissile.mdl" //this effects will get created upon missile impact
 private constant string UnitEff = "Abilities\\Spells\\Human\\Feedback\\ArcaneTowerAttack.mdl" //units affected by the spell will get this effect attached to them
 private constant string ImpactEff2 = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl" //upon impact attaches this effect to the missile
 private constant real Mb_base = 20 // base mana burn value
 private constant real Mb_inc = 10 // increasement of mana burn per level
 private constant integer Bn_base = 2 // number of missile bounces
 private constant integer Bn_inc = 1 // increeasment of bounce number per level
 private constant integer Miss_num = 1 // number of missiles thrown
 private constant integer Miss_inc = 1 // number or missiles increased by level
 private constant real Ie_AOE = 250 // range in which the units get affected
 private constant real M_speed = 7 // missile speed
 private constant real M_height = 350 // maximum height which the missile can reach
 private constant real Bonus_mb = 20 // bonus mana burn value; the mana burn gets powered whenever it gathers enough mana
 private constant real Bounce_dist = 275 // distance for each bounce
 private constant real FeedV = 200 // upon reaching this value the mana burn gains in power
 private constant real Angle_dif = 35 // defines the maximum possible spread of the missiles
endglobals
//***************************************************************************************
//Settings end - Do not modify anything below this if you don't know what you are doing!*
//***************************************************************************************
globals
 private boolexpr TF = null
 private player TP = null
 private real MaxX
 private real MaxY 
 private real MinX 
 private real MinY 
 endglobals
 
//parabola function for the missile
private function ParabolaZ takes real h,real d,real cd returns real
    return (4*h / d)*(d - cd)*(cd / d)
endfunction

 private struct SB
    unit c
    unit m
    integer l
    real mh
    real a
    real d
    real cd = 0
    integer bn
    real mb
    real f
    player p
    effect e
 
    static SB array ind
    static integer sca = 0
    static timer counter = CreateTimer()

    // moving the dummy unit as well as the mana burn effect is located below
    static method Motion takes nothing returns nothing
        local SB v
        local real x
        local real y
        local real bx
        local real by
        local real ang
        local real ang2
        local real h
        local integer i = 0
        local group tg = CreateGroup()
        local unit tu
        local real mlb
        loop
            exitwhen i >= SB.sca
            set v = SB.ind[i]
            if GetUnitX(v.m) > MaxX or GetUnitX(v.m) < MinX or GetUnitY(v.m) > MaxY or GetUnitX(v.m) < MinY then
                set v.cd = v.d
            endif
        if v.cd < v.d then
            set x = GetUnitX(v.m) + M_speed * Cos(v.a)
            set y = GetUnitY(v.m) + M_speed * Sin(v.a)
            set v.cd = v.cd + M_speed
            call SetUnitX(v.m,x)
            call SetUnitY(v.m,y)
            set h = ParabolaZ(M_height,v.d,v.cd)
            call SetUnitFlyHeight(v.m,h,0)
        else
            call DestroyEffect(AddSpecialEffectTarget(ImpactEff2,v.m,"chest"))
            call DestroyEffect(AddSpecialEffect(ImpactEff,GetUnitX(v.m),GetUnitY(v.m)))
            set TP = v.p
            call GroupEnumUnitsInRange(tg,GetUnitX(v.m),GetUnitY(v.m),Ie_AOE,TF)
            loop
                set tu = FirstOfGroup(tg)
                exitwhen tu == null
                if GetUnitState(tu,UNIT_STATE_MANA) > 0 then
                    if GetUnitState(tu,UNIT_STATE_MANA) > v.mb then
                        call SetUnitState(tu,UNIT_STATE_MANA,GetUnitState(tu,UNIT_STATE_MANA) - v.mb)
                        call UnitDamageTarget(v.c,tu,v.mb,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
                        set v.f = v.f + v.mb
                    else
                        set mlb = GetUnitState(tu,UNIT_STATE_MANA)
                        call SetUnitState(tu,UNIT_STATE_MANA,GetUnitState(tu,UNIT_STATE_MANA) - mlb)
                        call UnitDamageTarget(v.c,tu,mlb,true,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_MAGIC,null)
                        set v.f = v.f + mlb
                    endif
                call DestroyEffect(AddSpecialEffectTarget(UnitEff,tu,"chest"))
                endif 
                if v.f >= FeedV then
                    set v.f = v.f - FeedV
                    set v.mb = v.mb + Bonus_mb
                endif 
                call GroupRemoveUnit(tg,tu)
                set tu = null
            endloop
            if v.bn > 0 then
                set ang = (v.a * bj_PI)
                set bx = GetUnitX(v.m) + Bounce_dist * Cos(ang)
                set by = GetUnitY(v.m) + Bounce_dist * Sin(ang)
                set ang2 = GetRandomReal(0,2)*bj_PI
                set x = bx + Bounce_dist * Cos(ang2)
                set y = by + Bounce_dist * Cos(ang2)
                set v.a = Atan2(y - GetUnitY(v.m),x - GetUnitX(v.m))
                set v.cd = 0.00
                set v.bn = v.bn - 1
            else
                call DestroyEffect(v.e)
                call RemoveUnit(v.m)
                set v.e = null
                set v.c = null
                set v.m = null    
                call v.destroy()
                set SB.sca = SB.sca - 1
                set SB.ind[i] = v.ind[SB.sca]                        
                set i  = i - 1  
            endif
        endif
        set i = i + 1
        set TP = null
        endloop
        call DestroyGroup(tg)
        set tg = null
        if SB.sca == 0 then
            call PauseTimer(SB.counter)
        endif
  endmethod
 
  static method GetVal takes unit c,unit m,real a,real d,integer lvl,real mb,integer bn,player p,effect e returns nothing
    local SB v = SB.allocate()
    set v.c = c
    set v.m = m
    set v.a = a
    set v.d = d
    set v.l = lvl
    set v.mb = mb
    set v.bn = bn
    set v.p = p
    set v.e = e
    set v.f = 0
    set v.cd = 0.00
    if SB.sca == 0 then
        call TimerStart(SB.counter,0.02,true,function SB.Motion)
    endif
    set SB.ind[SB.sca] = v
    set SB.sca = SB.sca + 1
  endmethod

 endstruct
 
 //unit filter 
private function filter takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit()) > 0 and IsUnitEnemy(GetFilterUnit(),TP) and IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING) == false and IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) == false 
endfunction

private function dummyFilter takes nothing returns boolean
    return true
endfunction

//trigger condition
private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == SpellID
endfunction

//basicaly this function is the triggers actions 
private function SetValues takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local unit m
    local player p = GetOwningPlayer(c)
    local location loc = GetSpellTargetLoc()
    local integer lvl = GetUnitAbilityLevel(c,SpellID)
    local integer bn = (Bn_base + Bn_inc*(lvl-1)) 
    local integer i = 0
    local real a = Atan2(GetLocationY(loc) - GetUnitY(c),GetLocationX(loc) - GetUnitX(c))
    local real d = Bounce_dist
    local real mb = (Mb_base + Mb_inc*(I2R(lvl-1)))
    local effect e
        loop
            exitwhen i > (Miss_num + (Miss_inc * (lvl - 1)))
            set a = ((a * bj_RADTODEG) + GetRandomReal(-Angle_dif,Angle_dif)) * bj_DEGTORAD
            set m = CreateUnit(p,DummyID,GetUnitX(c),GetUnitY(c),a)
            set e = AddSpecialEffectTarget(MissileEff,m,"chest")
            call SetUnitPathing(m,false)
            call UnitAddAbility(m,'Arav')
            call UnitRemoveAbility(m,'Arav')
            call SB.GetVal(c,m,a,d,lvl,mb,bn,p,e)
            set m = null
            set e = null
            set i = i + 1
        endloop
    call RemoveLocation(loc)
    set c = null
    set p = null
    set loc = null
endfunction


private function InitSB takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    loop
        exitwhen i >= bj_MAX_PLAYER_SLOTS
        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,Filter(function dummyFilter))
        set i = i + 1
    endloop
    set TF = Filter(function filter)
    set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)
    set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)
    set MinX = GetRectMinX(bj_mapInitialPlayableArea)
    set MinY = GetRectMinY(bj_mapInitialPlayableArea)
    call TriggerAddCondition(t,Condition(function Cond))
    call TriggerAddAction(t,function SetValues)
    call Preload(MissileEff)
    call Preload(ImpactEff)
    call Preload(UnitEff)
    call Preload(ImpactEff2)
    call PreloadStart()
endfunction
endscope


Special credits go to PurplePoot.

Keywords:
spirit, bomb, feedback, bottle, diffusal, mana, burn, vJass
Contents

Spirit Bombs (Map)

Reviews
19:35, 8th Dec 2009 TriggerHappy: Review for Spirit Bombs The indentation is horrific. Please use the tab key to indent. The BJ event is completely fine. null filters don't leak anymore so no need for Filter(function filter) I...

Moderator

M

Moderator

19:35, 8th Dec 2009
TriggerHappy:

Review for Spirit Bombs

The indentation is horrific. Please use the
tab key to indent.
  • The BJ event is completely fine.
  • null filters don't leak anymore so no need for Filter(function filter)
  • I strongly suggest using UnitAlive. It's more accurate and safter
    than checking the units life.

Status

Approved
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Kingz working with vJass now!! :D

Well, it's a nice original idea. Icon is worth begin used...

I can't comment on triggering since I know some vJass but not much.


However, there's something I noticed:

In the two images below, you'll see how I target the ability at a point, but all the bottles fall at a certain point close to the caster where they bump the first time instead of falling at that target point...

Maybe you'd like to shorten the Cast Range or adjust something else... or maybe it's supposed to be that way.

(I don't know if the images are obvious...)


Keep up the good work!!
 

Attachments

  • New Picture (4) copy.jpg
    New Picture (4) copy.jpg
    250 KB · Views: 182
  • New Picture (5) copy.jpg
    New Picture (5) copy.jpg
    254 KB · Views: 189

Rmx

Rmx

Level 19
Joined
Aug 27, 2007
Messages
1,164
Sad but True, we have lost another GUI'er, Could i ask u Kingz just Why ?

Don't go to JASS and vJASS stay with GUI.

GUI is harder to make spells with it and requires more Brain Scratching, Could u make one in GUI.

I'll will not rate it coz i don't know vJass nor Jass either.
 
Level 15
Joined
Jul 19, 2007
Messages
618
i checked it out its good for first vjass spell.
idea is good icon matches well so 4/5!

you still leaks 16 objects boolexprs in inti function see how Paladon fixed that in his PGSystem.

coding speed is slow coz of using loop instead of ForGroup, but as long as it does not lag hard its fine.

so onec again for first vjass spell this is awesome!
+rep

Greets!
~Dark Dragon
 
Level 10
Joined
Jan 14, 2006
Messages
160
Sad but True, we have lost another GUI'er, Could i ask u Kingz just Why ?

Don't go to JASS and vJASS stay with GUI.

GUI is harder to make spells with it and requires more Brain Scratching, Could u make one in GUI.

I'll will not rate it coz i don't know vJass nor Jass either.



I'm a GUI Spellmaker because I just don't understand Jass, but I understand why people use it, it's much clearer what happens since everything is written in the code and u have a lot more functions than in gui. If I would understand it, I would always prefer jass over gui.
 
Last edited:
Level 11
Joined
May 16, 2007
Messages
288
Kingz, nice that you decided to learn jass, it really makes things easier :D

I didn't have time to test it yet (stuck with some weird problems with another code), but looking at the code, there are parts where you could have optimized it, for example:

Instead of:

JASS:
private constant real Mb_base = 20 // base mana burn value 
private constant real Mb_inc = 10 // increasement of mana burn per level

You could have done:
JASS:
private function ManaBurn takes integer level returns real
return level * 10. + 20.
endfunction

Anyway, it's looking nice, I'll test it as soon as possible.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO you foooool !!! :'(

/cry

well nice as always, will use this one for sure in a map!! 5/5 +rep

also Kingz you remembered from the marines don't ya,

"Never leave a man behind" don't ya remember that one?!

So now you have to teach me vJass ;)
 
Level 11
Joined
May 16, 2007
Messages
288
@Kingz

Well, maybe it is, I prefer the function way, though :)

PS: You spelled my name wrong, lol.

@baassee

Most of the times you learn Jass by trial and error (at least that's how I learned most of it), if you already know the basics of Jass, these 2 tutorials are very good and probably what you're looking for:

http://www.hiveworkshop.com/forums/f280/making-spell-vjass-practice-session-1-a-114519/#9

Spell Making Course: Part 1: Making a simple stomp spell. - Wc3campaigns

Edit: Post number 100, yay!
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
@Kingz

Well, maybe it is, I prefer the function way, though :)

PS: You spelled my name wrong, lol.

@baassee

Most of the times you learn Jass by trial and error (at least that's how I learned most of it), if you already know the basics of Jass, these 2 tutorials are very good and probably what you're looking for:

http://www.hiveworkshop.com/forums/f280/making-spell-vjass-practice-session-1-a-114519/#9

Spell Making Course: Part 1: Making a simple stomp spell. - Wc3campaigns

Edit: Post number 100, yay!

Thank you very much for those :) yeah I know alrdy a little but that's a little! ^^

@Kingz
yaya we'll see in the future :)
 
Level 9
Joined
Aug 2, 2008
Messages
219
Ok i have just been able to take a look at the code for now because i cant load or compile the map even with JASS NEW GEN. I know i have to save the map manually before testing it so that it is fully compiled but it still doesent work. The code looks fine to me but im still learning vJASS and kingz is probably better than me.
 

Attachments

  • bug.jpg
    bug.jpg
    274.7 KB · Views: 68
Level 9
Joined
Aug 2, 2008
Messages
219
I got the chance to test the spell but the error occurs now every second time i save the map…but at least i worked for once. The Spell is pretty nice, good job:thumbs_up: but sometimes the bottles jump in an other directoion as they should. And i also think i can learn something from this spell.:grin:
 

N.O

N.O

Level 6
Joined
Feb 20, 2009
Messages
200
Why can't this spell be tested in game?
I thought there was a rule against 1.23 or below spells?
If it is 1.24b compatible then something is strangely wrong...
 
Level 25
Joined
Jun 5, 2008
Messages
2,572
o_O?

I tested it yesterday, with my patch 1.24c, worked fine, what is your problem?

EDIT:

I downloaded it myself, opened in WE, saved the map, clicked test and it launched :p

I really dunno what is the problem(only thing coming to my mind is that you are using 1.24b Warcraft 3 and that is somehow interrupting you from testing this).
 

N.O

N.O

Level 6
Joined
Feb 20, 2009
Messages
200
Interesting... I have 1.24c too, i'll figure something out,thanks for letting me know Kingz and sorry for thinking you got it wrong.
 
Top