wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Resources > Code Resources > vJass Spells
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 06-08-2009, 07:11 AM   #1
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default Boomerang!

Throw a deadly boomerang at your enemies.

This uses vJass (JassHelper 0.9.H.0 and up), GroupUtils, xefx, DestructableLib and IsTerrainWalkable.

In-Game-Commands

- "-reset": spawns some footmen
- "-level <level>": Set the heros level to the level you specified. Note that you cannot decrease it that way.
- "-handleid": creates a location, displays its handlid-0x100001, and then destroys it.
- "-credits": displays credits
- "-commands": displays this list
- "-clear": removes all messages ingame



Changelog

06/03/2009 - Version 1.0.0
- initial release

06/04/2009 - Version 1.1.0
- stopped the spell from triggering when using unrelated abilities
- added a minimum range
- added support for trees
- added damage reduction when hitting multiple targets
- added a hit sound
- switched from direct dummy unit usage to xe

06/05/2009 - Version 1.2.0
- fixed two bugs reported by -JonNny
- enabled damaging units more than once

06/08/2009 - Version 1.2.1
- some optimizations and the final touches (i hope this really is the final version)

06/15/2009 - Version 1.3.0
- added an option to launch a boomerang to the left side, either additionally or exclusively
- made the boomerang collide with unwalkable terrain (after checking for trees)

07/12/2009 - Version 1.3.1
- more and better comments
- made configuring valid targets easier
- boomerangs colliding with unwalkable terrain is now optional
- made an additional version where the calibration section uses formulae (for those who cant/dont want to configure arrays)

08/07/2009 - Version 1.3.3
- Compatibility with 1.24
- 1.3.2 was a private build for a request

06/10/2011 - Version 1.3.4
- fixed a few double frees

07/11/2011 - Version 1.4.0
- you can now change the width of the path of the boomerang (BOOMERANG_FOCUS)
- you can now configure the spell to simply ignore trees.
- a few optimizations in the background (mainly using static ifs) and a bit of cleanup

01/28/2012 - Version 1.4.1
- boomerangs now follow unit targets
- each boomerang now has its own group of units it has already hit
- cleaned up the code with more meaningful names

01/07/2015 - Version 1.4.2
- rewrote the entire spell, no functionality was changed
- fixed a bug involving bad logic which excluded all units from being dealt damage



Expand Code (Array version) + Credits:

Expand Code (Formula version) + Credits:
Attached Images
File Type: gif Boomerang_01.GIF (106.1 KB, 623 views)
Attached Files
File Type: w3x Boomerang_1.4.2.w3x (58.4 KB, 18 views)
__________________

Last edited by Deaod : 01-07-2015 at 05:30 AM. Reason: Updated to 1.4.2
Deaod is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 06-08-2009, 09:12 AM   #2
wraithseeker
User
 
Join Date: Feb 2009
Posts: 406

wraithseeker is on a distinguished road (17)

Default

I heard somewhere that doing GroupClear before a ENUM_GROUP is safer, is that true?

The way you name your struct members make it really hard to understand, couldn't you just name them properly?

Like s.d and etc
wraithseeker is offline   Reply With Quote
Old 06-08-2009, 11:07 AM   #3
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default

calling GroupEnums clears the groups.

And i didnt add comments to the declaration of the members for nothing. Read them. The members are properly named (d for distance, a for angle, ...).
__________________
Deaod is offline   Reply With Quote
Old 06-08-2009, 12:53 PM   #4
Sunwarrior25
I say!
 
Sunwarrior25's Avatar
 
Join Date: Jul 2007
Posts: 366

Submissions (3)

Sunwarrior25 will become famous soon enough (30)Sunwarrior25 will become famous soon enough (30)

Send a message via Yahoo to Sunwarrior25
Question Three questions:

  • Can this work with items? (thinking Legend of Zelda)
  • Can you move about while a boomerang is in the air?
  • Can we limit the number of boomerangs a given hero/item can have flying in the air at a time?
__________________
Table:
Currently:
- Fooling around with various things.
- Staying up WAY too late.
- Fooling around with various things.
Other places to find me:
YouTube
deviantART
Twitter
uStream
Sunwarrior25 is offline   Reply With Quote
Old 06-08-2009, 01:32 PM   #5
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default

  1. yes, i think you can add abilities to items which in turn can trigger off this ability.
  2. yes, you can (blinking will cause some visual glitches, but nothing screws up when blinking).
  3. yes, use unit indexing and assign each index a number of currently active boomerangs. You will have to add code for that yourself though.
__________________
Deaod is offline   Reply With Quote
Old 06-15-2009, 05:45 PM   #6
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default

Version 1.3.0

Someone asked for a few additional features.
__________________
Deaod is offline   Reply With Quote
Old 07-01-2009, 03:05 PM   #7
Rising_Dusk
Obscurity, the Art


Projects Director
Project Leader: OD
 
Join Date: Feb 2006
Posts: 9,729

Submissions (27)

Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)

Hero Contest #3 - 1st PlaceApproved Map: Desert of ExileApproved Map: Advent of the ZenithHero Contest #2 - 1st PlaceHero Contest - Third place>

Send a message via AIM to Rising_Dusk Send a message via MSN to Rising_Dusk
Default

Critiques...
  • Collapse JASS:
        private function SetUpDAMAGE takes nothing returns nothing
            set DAMAGE[1]=200. // initially deals 200 damage
            set DAMAGE[2]=275.
            set DAMAGE[3]=350.
        endfunction
        
        private function Damage takes integer level returns real // PROXY
            return DAMAGE[level]
        endfunction
    I think that should be replaced with the following, which gets rid of the unnecessary call at Init. I like formulas more anyways.
    Collapse JASS:
        private constant function Damage takes integer level returns real
            return 125.+75.*level
        endfunction
  • Similar as above for Damage Absorption.
  • Similar as above for Minimum Range.
  • The rest looks okay, but it's entirely possible I missed something due to it being tough to read and follow in a lot of places. You should comment the bulk of your code more in the future, it would really help in navigating the trickier parts.
__________________

Last edited by Rising_Dusk : 07-01-2009 at 04:18 PM.
Rising_Dusk is offline   Reply With Quote
Old 07-01-2009, 03:15 PM   #8
akolyt0r
In Flames
 
akolyt0r's Avatar
 
Join Date: Jan 2006
Posts: 1,153

Submissions (3)

akolyt0r has a spectacular aura about (120)

Default

if you alread critisize deaods config function(s), you should tell him to use constant functions aswell (+3% speed 0.o)
__________________
akolyt0r is offline   Reply With Quote
Old 07-01-2009, 04:04 PM   #9
busterkomo
User
 
Join Date: Aug 2007
Posts: 68

Submissions (1)

busterkomo is on a distinguished road (10)

Default

Quote:
Originally Posted by Rising_Dusk
Critiques...
  • Collapse JASS:
        private function SetUpDAMAGE takes nothing returns nothing
            set DAMAGE[1]=200. // initially deals 200 damage
            set DAMAGE[2]=275.
            set DAMAGE[3]=350.
        endfunction
        
        private function Damage takes integer level returns real // PROXY
            return DAMAGE[level]
        endfunction
    I think that should be replaced with the following, which gets rid of the unnecessary call at Init. I like formulas more anyways.
    Collapse JASS:
        private function Damage takes integer level returns real
            return 125.+75.*level
        endfunction
  • Similar as above for Damage Absorption.
  • Similar as above for Minimum Range.
  • The rest looks okay, but it's entirely possible I missed something due to it being tough to read and follow in a lot of places. You should comment the bulk of your code more in the future, it would really help in navigating the trickier parts.
Well, formulas are good because they're a lot cleaner than arrays. On the other hand, you might not want the increments to be linear.

Quote:
if you alread critisize deaods config function(s), you should tell him to use constant functions aswell (+3% speed 0.o)
A 3% speed boost is extremely negligible.
busterkomo is offline   Reply With Quote
Old 07-01-2009, 04:20 PM   #10
Rising_Dusk
Obscurity, the Art


Projects Director
Project Leader: OD
 
Join Date: Feb 2006
Posts: 9,729

Submissions (27)

Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)

Hero Contest #3 - 1st PlaceApproved Map: Desert of ExileApproved Map: Advent of the ZenithHero Contest #2 - 1st PlaceHero Contest - Third place>

Send a message via AIM to Rising_Dusk Send a message via MSN to Rising_Dusk
Default

Quote:
Originally Posted by busterkomo
Well, formulas are good because they're a lot cleaner than arrays. On the other hand, you might not want the increments to be linear.
You can always generate a function fitting N points in a curve. It's very easy with only 3 levels, and still easy even with 5. After that it gets a bit ugly, yeah, so I can see the value of an array. Also, accessing array values is negligibly faster than doing the arithmetic.
__________________
Rising_Dusk is offline   Reply With Quote
Old 07-01-2009, 04:30 PM   #11
akolyt0r
In Flames
 
akolyt0r's Avatar
 
Join Date: Jan 2006
Posts: 1,153

Submissions (3)

akolyt0r has a spectacular aura about (120)

Default

if its no problem to get bonus speed, it should be done no matter how negligible the speed bonus is !
__________________

Last edited by akolyt0r : 07-01-2009 at 04:31 PM.
akolyt0r is offline   Reply With Quote
Old 07-02-2009, 01:20 PM   #12
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default

Dusk, linear is still okay...quadratic is a bit tricky and cubic even more so. But i wont spend half an hour finding a formula fitting my spell values. I will instead use the array method. Easier (for more complex formulae (quadratic and up (nested parentheses ftw))), faster (accessing an array is faster) and still provides you with the possibility to use formulae. Also, IIRC all config functions should get inlined (either by JH or by Vex's Optimizer).

What were the tough parts for you?
__________________

Last edited by Deaod : 07-02-2009 at 01:25 PM.
Deaod is offline   Reply With Quote
Old 07-02-2009, 03:49 PM   #13
Rising_Dusk
Obscurity, the Art


Projects Director
Project Leader: OD
 
Join Date: Feb 2006
Posts: 9,729

Submissions (27)

Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)

Hero Contest #3 - 1st PlaceApproved Map: Desert of ExileApproved Map: Advent of the ZenithHero Contest #2 - 1st PlaceHero Contest - Third place>

Send a message via AIM to Rising_Dusk Send a message via MSN to Rising_Dusk
Default

Quote:
Originally Posted by Deaod
Dusk, linear is still okay...quadratic is a bit tricky and cubic even more so. But i wont spend half an hour finding a formula fitting my spell values. I will instead use the array method. Easier (for more complex formulae (quadratic and up (nested parentheses ftw))), faster (accessing an array is faster) and still provides you with the possibility to use formulae. Also, IIRC all config functions should get inlined (either by JH or by Vex's Optimizer).
Speed as an argument is lame. When you are down to comparing basic arithmetic to array accessing in a spell then you need to shoot yourself. I care more about code readability and user safety. It is much easier for a user to screw up that array thing by changing the index to something unusable or renaming the array thinking that he is allowed to do that than it is for him to screw up a formula that will return a passable value for a given level no matter what.

And if it takes someone half an hour to generate a formula to hit several known points, I dare venture that someone is an idiot.
Quote:
Originally Posted by Deaod
What were the tough parts for you?
Hidden information:
Most of the uncommented functions with numerous nested conditionals that aren't explained, so I can't easily check their veracity. Variable names come into play for those boolean vars here.
Collapse JASS:
        private static method DamageFilterFunc takes nothing returns boolean
        local unit u=GetFilterUnit()
            if IsUnitType(u, UNIT_TYPE_DEAD)==false and IsUnitType(u, UNIT_TYPE_STRUCTURE)==false and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)==false and (not IsUnitInGroup(u, tmps.g)) and IsUnitEnemy(u, GetOwningPlayer(tmps.c)) then
                if tmpd==1 then
                    if UnitDamageTarget(tmps.c, u, tmps.dam1, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE) then
                        call DestroyEffect(AddSpecialEffectTarget(HIT_FX, u, HIT_FX_ATTPT))
                        call GroupAddUnit(tmps.g, u)
                        if DAMAGE_ABSORPTION_RELATIVE then
                            set tmps.dam1=tmps.dam1*(1-Damage_Absorption(tmps.level))
                        else
                            set tmps.dam1=tmps.dam1-Damage_Absorption(tmps.level)
                        endif
                        if tmps.dam1<=DAMAGE_BOUNDARY then
                            call tmps.dum1.destroy()
                            set tmps.d1a=false
                            if not tmps.d2a then
                                call tmps.destroy()
                            endif
                        endif
                    endif
                elseif tmpd==2 then
                    if UnitDamageTarget(tmps.c, u, tmps.dam2, false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE) then
                        call DestroyEffect(AddSpecialEffectTarget(HIT_FX, u, HIT_FX_ATTPT))
                        call GroupAddUnit(tmps.g, u)
                        if DAMAGE_ABSORPTION_RELATIVE then
                            set tmps.dam2=tmps.dam2*(1-Damage_Absorption(tmps.level))
                        else
                            set tmps.dam2=tmps.dam2-Damage_Absorption(tmps.level)
                        endif
                        if tmps.dam2<=DAMAGE_BOUNDARY then
                            call tmps.dum2.destroy()
                            set tmps.d2a=false
                            if not tmps.d1a then
                                call tmps.destroy()
                            endif
                        endif
                    endif
                endif
            endif
            set u=null
            return false
        endmethod
        
        private static method TreeFilterFunc takes nothing returns boolean
        local destructable d=GetFilterDestructable()
        local real x
        local real y
        local real bx
        local real by
            if (not IsDestructableDead(d)) and IsDestructableTree(d) then
                set x=GetWidgetX(d)
                set y=GetWidgetY(d)
                if tmpd==1 then
                    set bx=tmps.dum1.x
                    set by=tmps.dum1.y
                    if (((x-bx)*(x-bx))+((y-by)*(y-by)))<=BOOMERANG_COLLSIZE*BOOMERANG_COLLSIZE then
                        if KILL_TREES then
                            call KillDestructable(d)
                            if DAMAGE_ABSORPTION_RELATIVE then
                                set tmps.dam1=tmps.dam1*(1-Damage_Absorption(tmps.level))
                            else
                                set tmps.dam1=tmps.dam1-Damage_Absorption(tmps.level)
                            endif
                            if tmps.dam1<=DAMAGE_BOUNDARY then
                                call tmps.dum1.destroy()
                                set tmps.d1a=false
                                if not tmps.d2a then
                                    call tmps.destroy()
                                endif
                            endif
                        else
                            call tmps.dum1.destroy()
                            set tmps.d1a=false
                            if not tmps.d2a then
                                call tmps.destroy()
                            endif
                        endif
                    endif
                elseif tmpd==2 then
                    set bx=tmps.dum2.x
                    set by=tmps.dum2.y
                    if (((x-bx)*(x-bx))+((y-by)*(y-by)))<=BOOMERANG_COLLSIZE*BOOMERANG_COLLSIZE then
                        if KILL_TREES then
                            call KillDestructable(d)
                            if DAMAGE_ABSORPTION_RELATIVE then
                                set tmps.dam2=tmps.dam2*(1-Damage_Absorption(tmps.level))
                            else
                                set tmps.dam2=tmps.dam2-Damage_Absorption(tmps.level)
                            endif
                            if tmps.dam2<=DAMAGE_BOUNDARY then
                                call tmps.dum2.destroy()
                                set tmps.d2a=false
                                if not tmps.d1a then
                                    call tmps.destroy()
                                endif
                            endif
                        else
                            call tmps.dum2.destroy()
                            set tmps.d2a=false
                            if not tmps.d1a then
                                call tmps.destroy()
                            endif
                        endif
                    endif
                endif
            endif
            set d=null
            return false
        endmethod
__________________

Last edited by Rising_Dusk : 07-02-2009 at 03:51 PM.
Rising_Dusk is offline   Reply With Quote
Old 07-02-2009, 05:00 PM   #14
Deaod
User
 
Join Date: Jan 2007
Posts: 542

Submissions (11)

Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)Deaod is a jewel in the rough (192)

Send a message via ICQ to Deaod Send a message via MSN to Deaod
Default

Lets say you have a spell with 5 or more levels. Lets further assume those values are in no particular easy order (linear, exponential). Maximum complexity would be of 4th degree (ax^4+bx^3+cx^2+dx+e) or of (level-1)th degree. Inserting the values and deducing the formula would be kind of tiresome (not that its impossible, its just tiresome and youre prone to make errors somewhere in that whole mess). Oh, and speed is FAR worse (for any function of a higher degree than 2, but as you mentioned, it doesnt really matter that much for a spell).

Also, arrays saves you the recalculation of the function every time you want to adjust the balance of the spell.

Expand Commented Code:

Maybe we could ask Vex to fix jass tags in hidden tags to not strech the whole thing to infinity.
__________________
Deaod is offline   Reply With Quote
Old 07-02-2009, 06:11 PM   #15
Rising_Dusk
Obscurity, the Art


Projects Director
Project Leader: OD
 
Join Date: Feb 2006
Posts: 9,729

Submissions (27)

Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)Rising_Dusk has a reputation beyond repute (1192)

Hero Contest #3 - 1st PlaceApproved Map: Desert of ExileApproved Map: Advent of the ZenithHero Contest #2 - 1st PlaceHero Contest - Third place>

Send a message via AIM to Rising_Dusk Send a message via MSN to Rising_Dusk
Default

Quote:
Originally Posted by Deaod
Lets say you have a spell with 5 or more levels. Lets further assume those values are in no particular easy order (linear, exponential). Maximum complexity would be of 4th degree (ax^4+bx^3+cx^2+dx+e) or of (level-1)th degree. Inserting the values and deducing the formula would be kind of tiresome (not that its impossible, its just tiresome and youre prone to make errors somewhere in that whole mess)
Dude... You can do up to 10th order polynomial regression by the least squares method online. Generating a 99% accurate formula for 10 levels of any spell is good enough for me - and I found that website in ten seconds of a google search.

Let's also consider the fact that most sensible spell design has linear growth, so this is a non-issue in the first place.
Quote:
Originally Posted by Deaod
Maybe we could ask Vex to fix jass tags in hidden tags to not strech the whole thing to infinity.
Yes, this would be a good idea.

Your commented code looks good now that I know what those booleans mean. Perhaps you should actually comment the spell, instead of just having that excerpt in a separate post?
__________________
Rising_Dusk is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 05:56 AM.


Affiliates
The Hubb The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2017, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services