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

Destructive Slash v1.1

Spell Video
Spell Description

Using the power of the sword in his hand, BladeMaster slashing the ground causing 50/100/150/200 damage to enemies. And those who were hit that would become frightened and unable to use skills and items in 2/2.5/3/3.5 seconds.
Spell code
JASS:
    //***********************************************************************************\\
    //***********************************************************************************\\
    //  This spell is called:                                                            \\
    //                        - D E S T R U T I V E   S L A S H                          \\
    //                    By:                                                            \\
    //                        - Elphis - Nyuu                                            \\
    //               Version:                                                            \\
    //                        - v1.1                                                     \\
    //         How to import:                                                            \\
    //                        - Open this spell and copy Destructive Slash trigger,      \\
    //                          copy Destructive Slash, Destructive Slash                \\
    //                          ability, Destructive Slash buff, Dummy caster            \\
    //                          and change the rawcode                                   \\
    //                          (Ctrl + D to see the rawcode) if needed                  \\
    //                          you may play with spell configuration below and have fun!\\
    //***********************************************************************************\\
    //***********************************************************************************\\
    
library DestructiveSlash
    //                        S P E L L  C O N F I G U R A T I O N                       \\
    globals
        //Spell rawcode, change if needed
        private constant integer SPELL_ID           = 'A000'
        //Dummy spell rawcode, change if needed
        private constant integer DSPELL_ID          = 'A001'
        //Spell buff rawcode, change if needed
        private constant integer BUFF_ID            = 'B000'
        //Dummy rawcode, change if needed
        private constant integer CASTER_DUMMY       = 'e000'
        //Spell periodic, decrease this value = fast ecxecution
        private constant real PERIODIC              = .031250000
        //Caster speed animation, decrease this value = the caster play animation more slower
        private constant real SPEED_ANIMATION       = 1.
        //Default scale of the caster when this spell end
        private constant real DEFAULT_SCALE         = 1.
        //Max scale of the caster when spell running
        private constant real MAX_SCALE             = 4.
        //Min scale of the caster increase per periodic
        private constant real MIN_SCALE             = 0.13
        //Damage radius
        private constant real DAMAGE_RADIUS         = 200.
        //Spell damage base
        private constant real DAMAGE_BASE           = 20.
        //Min distance per loop integer (100. distance = 1 integer = 1 efect, 1000. distance = 10 integer = 10 effect)
        private constant real MIN_DISTANCE          = 100.
        //Effect when the caster fire the ground
        private constant real SWORD_DISTANCE        = 200.
        
        //***************************Damage Weapon Settings***************************
        private constant attacktype AT              = ATTACK_TYPE_HERO
        private constant damagetype DT              = DAMAGE_TYPE_FIRE
        private constant weapontype WT              = WEAPON_TYPE_AXE_MEDIUM_CHOP
        //****************************************************************************
        
        //Animation of the caster play when this spell is actived
        private constant string ANIMATION           = "slam"
        //Effect of the spell when the caster fire the ground
        private constant string EFFECT              = "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl"
        //Order id of the dummy spell
        private constant string ORDER_ID            = "doom"
        
        //                          N O N - C O N F I G U R A T I O N                       \\
        private constant timer TIMER                = CreateTimer()
        private constant group G                    = CreateGroup()
        private          integer M                  = -1
        private          integer array SM
        private          unit Dummy
        //***********************************************************************************
    endglobals
    
    //*******************Damage Settings***********************************
    /**/private constant function Damage takes integer lvl returns real
    /**/    return DAMAGE_BASE*lvl
    /**/endfunction
    //*********************************************************************
    
    //*******************Filter Function***********************************
    /**/function filterFunc takes unit filterUnit,player playe returns boolean
    /**/                                                        //Assure a better death check//
    /**/return not IsUnitType(filterUnit,UNIT_TYPE_DEAD) and /**/GetUnitTypeId(filterUnit) != 0/**/ and IsUnitEnemy(filterUnit,playe)
    /**/endfunction
    //********************************************************************
    
    private struct DestructiveSlash

    unit caster = null
    unit dummy = null
    
    boolean active = false
    
    integer lvl
    
    real scale = DEFAULT_SCALE
    
    real dmg
    
    real tx
    real ty
    
    real dec_scale = MIN_SCALE*2
    
    static method onPeriodic takes nothing returns nothing
        local integer i = 0
        local integer ec
        
        local real md
        local real x
        local real y
        local real cx
        local real cy
        local real a
        local real cos
        local real sin
        
        local integer distance
        
        local unit f = null
        
        local player p = null
        
        local thistype this
        
        loop
            exitwhen i > M
            
            set this = SM[i]
            
            if scale < MAX_SCALE and not active then
                set scale = scale + MIN_SCALE
            else
            
                if not active then
                
                    //Attention!: The code below just run once !
                
                    set active = true
                    
                    set ec = 0
                    
                    set a = Atan2(ty-GetUnitY(caster),tx-GetUnitX(caster))
                    
                    set cos = Cos(a)
                    set sin = Sin(a)
                    
                    set cx = GetUnitX(caster) + SWORD_DISTANCE * cos
                    set cy = GetUnitY(caster) + SWORD_DISTANCE * sin
                    
                    set x = tx - cx
                    set y = ty - cy
                    
                    set distance = R2I(SquareRoot(x*x+y*y))
                    
                    set p = GetOwningPlayer(caster)
                    
                    set md = 0.
                
                    loop
                        exitwhen ec > distance/MIN_DISTANCE
                        
                        set x = cx + md * cos
                        set y = cy + md * sin
                        
                        set md = md + MIN_DISTANCE
                        
                        call DestroyEffect(AddSpecialEffect(EFFECT,x,y))
                        
                        call GroupEnumUnitsInRange(G,x,y,DAMAGE_RADIUS,null)
                        
                        call SetUnitAbilityLevel(Dummy,DSPELL_ID,lvl)
                        
                        loop
                            set f = FirstOfGroup(G)
                            exitwhen f == null
                            
                            if filterFunc(f,p) then
                            
                                call UnitDamageTarget(caster,f,dmg,true,false,AT,DT,WT)
                                
                                if GetUnitAbilityLevel(f,BUFF_ID) == 0 then
                                    call SetUnitX(Dummy,GetUnitX(f))
                                    call SetUnitY(Dummy,GetUnitY(f))
                                    call IssueTargetOrder(Dummy,ORDER_ID,f)
                                endif
                                
                            endif
                            
                            call GroupRemoveUnit(G,f)
                        endloop
                        
                        set ec = ec + 1
                    endloop
                    
                    set p = null
                elseif scale > DEFAULT_SCALE then
                    set scale = scale - dec_scale
                else
                    call SetUnitTimeScale(caster,DEFAULT_SCALE)
                    set caster = null
                
                    set SM[i] = SM[M]
                    set SM[M] = -2
                    set M = M - 1
                    
                    if M == -1 then
                        call PauseTimer(TIMER)
                    endif
                endif
                
            endif
            
            call SetUnitScale(caster,scale,0.,0.)
            
            set i = i + 1
        endloop
    endmethod
    
    static method onCast takes nothing returns boolean
            local thistype this
            
            if GetSpellAbilityId() == SPELL_ID then
                set this = allocate()
                
                set M = M + 1
                set SM[M] = this
                
                set tx = GetSpellTargetX()
                set ty = GetSpellTargetY()
                
                set caster = GetTriggerUnit()
                
                set lvl = GetUnitAbilityLevel(caster,SPELL_ID)
                
                call SetUnitAnimation(caster,ANIMATION)
                call SetUnitTimeScale(caster,SPEED_ANIMATION)
                
                set dmg = Damage(lvl)
                
                if M == 0 then
                    call TimerStart(TIMER,PERIODIC,true,function thistype.onPeriodic)
                endif
            endif
            
            return false
        endmethod
        
        static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            local integer i = 0
            
            loop
                exitwhen i > 15
                
                call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
                
                set i = i + 1
            endloop
            
            call TriggerAddCondition(t,function thistype. onCast)
            
            set Dummy = CreateUnit(Player(15),CASTER_DUMMY,0.,0.,0.)
        endmethod
        
    endstruct
endlibrary
Screenshot
Why did you not see the video ?, the video truthful than picture :p
Changelog
v1.0: First release version !
v1.0b: Remove dummy on Init
v1.0c: Put If then else filter on the top of the spell.
v1.1: Minor improvement.
Keywords:
destructive,slash
Contents

Just another Warcraft III map (Map)

Reviews
10:17, 15th Feb 2014 BPower: Approved. Here is your full review: http://www.hiveworkshop.com/forums/spells-569/destructive-slash-v1-0c-248148/index2.html#post2487071

Moderator

M

Moderator

10:17, 15th Feb 2014
BPower:
Approved.
Here is your full review:
http://www.hiveworkshop.com/forums/spells-569/destructive-slash-v1-0c-248148/index2.html#post2487071
 
Why aren't you using self explanatory variables it's easier to understand the code even for someone who doesn't like jass (like me :p)
The trigger(s) look clear but i don't like that it is in one trigger (maybe :D)
It should be all shorter, can't be SquareRoot also written as Sqrt? or those little things.
PS: People, why? what are you doing everyone with those Blademasters? Everyone is making spells with the Blademaster (Blood mage too), why? is he so popular or what?
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
do you understand what you are commenting at?

well, mostly they are just don't have idea what hero should they use, but this one, maybe she selected blademaster because the spell fits with it..

poff, vJass looks so much sexier than Jass..

my review/suggestion:
- I think disable ability side effect doesn't fit well, maybe got some dps or burned or get stunned is better.
- add some delays for each explosion..
- your dummy unit has foodcost, not really a problem for player 16
- weapon and damage type doesn't affect anything until the apocalypse, isn't it better you just remove it?
-
JASS:
    private constant function Damage takes unit u,integer lvl returns real
        return DAMAGE_BASE*lvl
    endfunction
takes unit for what?
- using this
JASS:
call TriggerRegisterPlayerUnitEvent
looks little bit better, bcause can reduce fc for 1 time :p

That's it, I may be wrong there :)
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
Why aren't you using self explanatory variables it's easier to understand the code even for someone who doesn't like jass (like me :p)
Some people outline their code with comments, which can be very awesome.
The trigger(s) look clear but i don't like that it is in one trigger (maybe :D)
That's basically nonesense. Could you explain in detail what you mean.
It should be all shorter, can't be SquareRoot also written as Sqrt? or those little things.
You have completly wrong information. The SquareRoot function is a blizzard native and the only thing you could do is writing a wrapper and label it Sqrt which has zero advantages. However it is true that vJass and JASS are verbose scripting languages.

People, why? what are you doing everyone with those Blademasters?
I think that's not true. Nowadays many different hero models have their own fitting custom spells. Certainly the blademaster is a badass character and very popular among players and coders:grin:.
damage type doesn't affect anything
Damage type can be very important for example in Nestharus DDS you can find this feature (archetype == Archetype.SPELL) checking if dealt damage is Damagetype magic.

I wouldn't make it optional to create a DummyCaster onInit.
You could use an optional requirement and create your own dummy if that Dummy Caster library is not part of the map.
The code looks ok. I haven't checked the map nor the spell concept, yet.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
damage type doesn't affect anything
Damage type can be very important for example in Nestharus DDS you can find this feature (archetype == Archetype.SPELL) checking if dealt damage is Damagetype magic.
damn right! I just saw somewhere, random people said dat damage type is not important...
 
- using this
Jass:
call TriggerRegisterPlayerUnitEvent
looks little bit better, bcause can reduce fc for 1 time :p

It's perfectly fine to use call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT) :) since i always use call TriggerRegisterPlayerUnitEvent ( Lazy you know ^^! )

JASS:
private constant function Damage takes unit u,integer lvl returns real
        return DAMAGE_BASE*lvl
    endfunction

your dummy unit has foodcost, not really a problem for player 16

Oops forgot >.<, fixed..

add some delays for each explosion..

No, i like it instantly explosion :)

I think disable ability side effect doesn't fit well, maybe got some dps or burned or get stunned is better.

"And those who were hit that would become frightened and unable to use skills and items in 2/2.5/3/3.5 seconds."

Panic, people will be confused and will not know what to do
 
Level 18
Joined
Sep 14, 2012
Messages
3,413
JASS:
unit caster = null
    unit dummy = null
Still asking why initializing struct members to null ?
Why don't you set them to null in a destroy method ?

JASS:
local unit f = null
        
        local player p = null
No need to declare them to null ;)

exitwhen ec > R2I(distance/MIN_DISTANCE)
R2I(distance/MIN_DISTANCE) should be store in a var :p

if IsUnitEnemy(f,p) and not IsUnitType(f,UNIT_TYPE_DEAD) then put this in a filter function in the configurable block.
I suggest to use UnitAlive -> faster and now correctly handled :p

For now that's all (sorry can't test atm XD) !
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
FilterFunction requires some optional changes
  • Pass in a player variable (local player p). I guess you forgot that one because p is currently not used.
  • According to JPAG filterFunction should be FilterFuntion.
  • Change the argument order. What is evaluated first comes first. (first unit then player)
  • Because it is part of the user configuration use variables names like target, etc ... and not u.
  • Could use UnitAlive, because it is clearly superior.
JASS:
    private constant function FilterFunction takes unit target, player who returns boolean
        return not IsUnitType(target, UNIT_TYPE_DEAD) and IsUnitEnemy(target, who)
    endfunction

Once each cast you pass in a null argument into this function call SetUnitScale(caster,scale,0.,0.), maybe you could put it somewhere else.

I suggest you use only 1 dummy caster for the whole game, as you did in the previous version.
There is no benefit in creating multiple dummy casters, just a lot of cons
(Fires Index/Deindex Event and associated functions, small unit leak, (negligible) performance loss, ...)

You don't have to initialize variables with null.
Inside the loop GetUnitX/Y could be stored into local variables. Use x and y, as they are not needed until then.
set distance = SquareRoot(x*x+y*y) could be set distance = R2I(SquareRoot(x*x+y*y)/IN_DISTANCE)) distance will be of type integer.

Object Editor settings are fair enough.

The effects leave room for improvement. The fire could spread from the caster towards the target or the unit scaling could be variable related to the distance between caster and the spell target coordinates.
 
Level 2
Joined
Apr 29, 2014
Messages
6
Nice but maybe making him not big is good but how about making him jump high and slash down to the ground. just change the animation :)) :thumbs_up::thumbs_up::thumbs_up:
 
Top