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

[v]JASS - Spinning Shards v0.4


BTNFrostBolt.gif

Spinning Shards
Spell Description

Summons a barrier of circulating shards damaging trough any foe in a radius of 300. After some time the swords shoot into the current facing direction of the caster dealing heavy damage to anyone who touches them.
The amount of Swords, the damage, the duration and the shoot distance increase per level. Recasting increases the duration.


Stackable !

Level Info

Level: 1
Level: 2Level: 3

Shard Amount: 3
Shard Amount: 5Shard Amount: 7

Spin Damage: 50
Spin Damage: 90Spin Damage: 130

Shoot Damage: 35
Shoot Damage: 35Shoot Damage: 75

Duration: 9
Duration: 14Duration: 19

Shoot Distance: 900
Shoot Distance: 1150Shoot Distance: 1450
Requirements:You will need Jass New Gen to edit the vJass version. Get Adic Helper or JNGPS if you want to use the cJass version.

Version:
Changes:

v0.1
  • Initial Release
  • Credits to Dark_Dragon for helping me
  • Credits to shamonyouranus for the sword model and Deuterium for his opinion.
v0.2
  • Removed the the bug with the count down timer
  • Removed the facing bug
  • Removed a bug that the swords can leave the map
  • The user can decide now if the swords should spread out or fly in the casters direction. (Aspards Idea)
  • When the spell is being cast the user can decide if the swords should spin around a bit more or if the swords should immediatly fly away. This also solved the count down timer bug. (Deuteriums idea)
  • The JNGP link was added to this description
v0.3
  • Renamed the Spell form Summoned Swords into Spinning Shards
  • Changed the Spell Theme (Dummy model)
  • Removed the imported stuff.
  • Removed the bug which made the spell unuseable.
v0.4
  • Removed the repicking bug
  • Added the TIME_STACK option
  • Added the DAMAGE_STACK option
  • Added a cJass version to the tesmap. The vJass version is enabled by default.
  • Slight efficiency improvements
JASS:
scope SpinningShards initializer Init

    //User constants, feel free to experiment
    globals
        private constant integer SID = 'spsw'
        //Place the spell Rawcode here

        private constant integer DID = 'spsd'
        //Place the Dummy´s Rawcode here

        private constant integer LID ='lnch'
        //Rawcode for the launcher ability

        private constant integer TAG_RED = 255
        //How Red should the textag be ? NOTE: The value must be between 0 and 255

        private constant integer TAG_BLUE = 255
        //How Blue should the textag be ? NOTE: The value must be between 0 and 255

        private constant integer TAG_GREEN = 255
        //How Green should the textag be ? NOTE: The value must be between 0 and 255

        private constant integer TAG_OPA = 0
        //How transparent should the textag be ? NOTE: The value must be between 0 and 255

        private constant boolean TIME_STACK = true
        //true = The caster will keep his shards when the spell is recasted and the duration increases
        //false = The caster shoots his shards away and creates new ones
        
        private constant boolean DAMAGE_STACK = false
        //true = The spells deals more AoE damage during the spinning phase when recasted
        //false = The spell won´t deal more AoE damage when recasting
        
        private constant boolean REMOVE_BY_HIT = false
        //true = The shards will disappear when they hit an enemy
        //false = The shards can travel trough enemies (deals more damage)

        private constant boolean SPREAD_OUT = false
        //true = Shoots every missile in its current facing direction
        //false = Shoots all missiles int the facing directon of the caster

        private constant boolean WANT_TEXT_TAG = true
        //true = Creates a time indicating floating text above the caster
        //false = No floating text is created

        private constant string IMPACT_SFX = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
        //The special effect being displayed when an enemy gets hit during the spinning phase

        private constant string SPAWN_SFX = "Abilities\\Spells\\Undead\\OrbOfDeath\\OrbOfDeathMissile.mdl"
        //The special effect being displayed when the shards are created

        private constant string DEATH_SFX = SPAWN_SFX
        //The special effect being displayed when the shards disappear

        private constant string IMPACT_ATTATCH = "head"
        //Where should the IMPACT_SFX be attatched on a target ?

        private constant real DIAMETER = 200
        //The diameter of the circle of the shards

        private constant real SPIN_INTER = 0.02
        //How fast should the shards spin ?

        private constant real ANGLE_ALTER = 13
        //How many degrees should the shards move per interval ?

        private constant real SHOOT_INTER = 0.03
        //How fast should the shards move when they shoot away ?

        private constant real SHOOT_DIST = 45
        //Which distance should a shard being moved per interval ?

        private constant real SHOOT_IMPACT_RANGE = 120
        //The range in which a shard can damae an enemy when it´s moving

        private constant real DAMAGE_INTER = 0.1
        //How long is the interval for damageing enemys when spinning around the caster ?

        private constant real SPIN_IMPACT_RANGE = 300
        //The AoE radius for dealing damage while the shards are spinning

        private constant real TAG_SIZE = 0.03
        //How large should a textag be (the values are some kinda weird)

        private constant real TAG_HEIGHT = 13
        //How far should the textag float above the caster ?


        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        //The spell privates. PLEASE DO NOT TOUCH !
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        private constant group TEMP_GROUP = CreateGroup()
        private constant timer SPIN_TIM = CreateTimer()
        private constant timer SHOOT_TIM = CreateTimer()
        private integer TEMP_STRUCT
        private filterfunc SPIN_DAMAGE_FILTER
        private filterfunc SHOOT_DAMAGE_FILTER
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-

    endglobals

    //Howmany shards should spawn related to the level ?
    private constant function GetSwordAmount takes integer level returns integer
        return level * 2 + 1
    endfunction

    //Howmuch damage shall the enemies recieve per second when the sworeds are spinning
    private constant function GetSpinDamage takes integer level returns integer
        return level * 40 + 10
    endfunction

    //How much damage should a singe shard deal upon impact when they are launched ?
    private constant function GetImpactDamage takes integer level returns integer
        return level * 20 + 15
    endfunction

    //How long should the shards spin around the caster ?
    private constant function GetDuration takes integer level returns integer
        return level * 5 + 4
    endfunction

    //How far should the shards travel when they are launched ?
    private constant function GetShootDistance takes integer level returns integer
        return level * 250 + 650
    endfunction

    //The struct that hodls the data when the shards are spinning
    private struct SpinData

        static thistype array Index
        static integer Total = 0
        //Static fields needed for struct indexing method

        unit caster
        group swords
        texttag tag
        real spin_damage
        real damage_inter
        real dur

        method onDestroy takes nothing returns nothing

            //Clean up some leaks
            call UnitRemoveAbility(.caster,LID)
            call DestroyGroup(.swords)
            call DestroyTextTag(.tag)
            set .caster = null

        endmethod

        //The creator mehod
        static method create takes unit u returns thistype

            local thistype this = thistype.allocate()
            local integer lv = GetUnitAbilityLevel(u,SID)
            local integer i = GetSwordAmount(lv)
            local real a
            local real x
            local real y

            //General setup
            set .caster = u
            set .spin_damage = GetSpinDamage(lv) * SPIN_INTER
            set .dur = GetDuration(lv)
            set .swords = CreateGroup()
            set .damage_inter = 0
            call UnitAddAbility(u,LID)

            //TextTag Setup
            if WANT_TEXT_TAG then
                set .tag = CreateTextTag()
                call SetTextTagText(.tag,I2S(R2I(.dur)),TAG_SIZE)
                call SetTextTagColor(.tag,TAG_RED,TAG_GREEN,TAG_BLUE,255 - TAG_OPA)
                call SetTextTagPermanent(.tag,false)
                call SetTextTagVisibility(.tag,true)
                call SetTextTagLifespan(.tag,.dur)
                call SetTextTagFadepoint(.tag,.dur - 1)
                call SetTextTagPosUnit(.tag,.caster,TAG_HEIGHT)
            endif

            //Preparing the shards and placing them in a circle
            loop
                exitwhen i == 0
                set a = (360/GetSwordAmount(lv)) * i * bj_DEGTORAD
                set x = GetUnitX(.caster) + DIAMETER * Cos(a)
                set y = GetUnitY(.caster) + DIAMETER * Sin(a)
                set u = CreateUnit(GetOwningPlayer(.caster),DID,x,y,a * bj_RADTODEG)
                call PauseUnit(u,true)
                call SetUnitPathing(u,false)
                call SetUnitUseFood(u,false)
                call GroupAddUnit(.swords,u)
                call UnitAddAbility(u,'Aloc')
                call DestroyEffect(AddSpecialEffect(SPAWN_SFX,x,y))
                set i = i - 1
            endloop

            //Update the index
            set thistype.Index[thistype.Total] = this
            set thistype.Total = thistype.Total + 1

            return this

        endmethod

    endstruct

    //This struct hodls the data for shooting the shards
    private struct ShootData

        static thistype array Index
        static integer Total = 0
        //Static fields needed for struct indexing method

        static real MAX_X
        static real MAX_Y
        static real MIN_X
        static real MIN_Y
        //since this struct behaves like a knockback the units could escape the map but we don´t want that

        unit missile
        real dist
        real cos
        real sin
        real dmg
        real dmg_inter

        static method Move takes nothing returns nothing

            local thistype this
            local integer inst = 0

            //Loop for all structs
            loop
                exitwhen inst == thistype.Total
                set this = thistype.Index[inst]

                //Moving a shard
                set .dist = .dist - SHOOT_DIST
                set .dmg_inter = .dmg_inter + SHOOT_INTER
                call SetUnitPosition(.missile,GetUnitX(.missile) + .cos,GetUnitY(.missile) + .sin)

                //Ready for dealing damage ?
                if .dmg_inter > DAMAGE_INTER then
                    call GroupEnumUnitsInRange(TEMP_GROUP,GetUnitX(.missile),GetUnitY(.missile),SHOOT_IMPACT_RANGE,SHOOT_DAMAGE_FILTER)
                    set .dmg_inter = 0
                endif

               //Destrying structs and recycle the index
               if .dist <= 0 or GetUnitX(.missile) >= ShootData.MAX_X or GetUnitX(.missile) <= ShootData.MIN_X or GetUnitY(.missile) >= ShootData.MAX_Y or GetUnitY(.missile) <= ShootData.MIN_Y or (FirstOfGroup(TEMP_GROUP) != null and REMOVE_BY_HIT) then
                    call DestroyEffect(AddSpecialEffect(DEATH_SFX,GetUnitX(.missile),GetUnitY(.missile)))
                    call RemoveUnit(.missile)
                    call this.destroy()
                    set thistype.Total = thistype.Total - 1
                    set thistype.Index[inst] = thistype.Index[thistype.Total]
                    set inst = inst - 1
                endif

                call GroupClear(TEMP_GROUP)
                set inst = inst + 1
            endloop

            //No struct running, no timer needed
            if thistype.Total == 0 then
                call PauseTimer(SHOOT_TIM)
            endif

        endmethod

        static method create takes unit m, unit c returns thistype

            local thistype this = thistype.allocate()
            local integer lv = GetUnitAbilityLevel(c,SID)
            local real a = GetUnitFacing(c) * bj_DEGTORAD

            //General Setup
            set .missile = m
            set .dist = GetShootDistance(lv)
            set .dmg = GetImpactDamage(lv)

            if SPREAD_OUT then
                set a = GetUnitFacing(m) * bj_DEGTORAD
                set .cos = SHOOT_DIST * Cos(a)
                set .sin = SHOOT_DIST * Sin(a)

            else

                call SetUnitFacing(m,a * bj_RADTODEG)
                set .cos = SHOOT_DIST * Cos(a)
                set .sin = SHOOT_DIST * Sin(a)
            endif

            //Is the timer running ?
            if thistype.Total == 0 then
                call TimerStart(SHOOT_TIM,SHOOT_INTER,true,function thistype.Move)
            endif

            //Update the index
            set thistype.Index[thistype.Total] = this
            set thistype.Total = thistype.Total + 1

            return this

        endmethod

    endstruct

    //Makes the shards circulate
    private function Shift takes nothing returns nothing

        local SpinData this = TEMP_STRUCT
        local unit u = GetEnumUnit()
        local real a = (GetUnitFacing(u) + ANGLE_ALTER) * bj_DEGTORAD
        
        call SetUnitPosition(u,GetUnitX(this.caster) + DIAMETER * Cos(a),GetUnitY(this.caster) + DIAMETER * Sin(a))
        call SetUnitFacing(u,a * bj_RADTODEG)

        set u = null

    endfunction

    //Launching the shards....
    private function Launch takes nothing returns nothing

       local SpinData this = TEMP_STRUCT

        call ShootData.create(GetEnumUnit(),this.caster)

    endfunction

    //Deals damage during the spin phase, this "Filter" adds no units to any group
    private function SpinDamage takes nothing returns boolean

        local SpinData this = TEMP_STRUCT
        local unit u = GetFilterUnit()

        if IsUnitEnemy(u,GetOwningPlayer(this.caster)) and GetWidgetLife(u) > 0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) !=true and IsUnitType(u, UNIT_TYPE_MECHANICAL) != true and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) != true and IsUnitType(u, UNIT_TYPE_ANCIENT) != true then
            call UnitDamageTarget(this.caster,u,this.spin_damage,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffectTarget(IMPACT_SFX,u,IMPACT_ATTATCH))
            set u = null
            return true
        endif

        set u = null
        return false

    endfunction

    //Deals damage during the shoot phase, this is a real Filter which adds units under certain circumstances
    private function ShootDamage takes nothing returns boolean

        local ShootData this = TEMP_STRUCT
        local unit u = GetFilterUnit()

        if IsUnitEnemy(u,GetOwningPlayer(this.missile)) and GetWidgetLife(u) > 0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) !=true and IsUnitType(u, UNIT_TYPE_MECHANICAL) != true and IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) != true and IsUnitType(u, UNIT_TYPE_ANCIENT) != true then
            call UnitDamageTarget(this.missile,u,this.dmg,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_UNKNOWN,WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffectTarget(IMPACT_SFX,u,IMPACT_ATTATCH))
            set u = null
            return true
        endif

        set u = null
        return false

    endfunction

    //Main function that moves the shards in a circle
    private function Spin takes nothing returns nothing

        local SpinData this
        local integer inst = 0

        //Looping trough all structs
        loop
            exitwhen inst == SpinData.Total
            set this = SpinData.Index[inst]

            if this.dur > 0 then

                set this.dur = this.dur - SPIN_INTER
                set this.damage_inter = this.damage_inter + SPIN_INTER

                //Moving the Shards
                set TEMP_STRUCT = this
                call ForGroup(this.swords,function Shift)

               //Moving the texttag (if you want)
               if WANT_TEXT_TAG then
                    call SetTextTagText(this.tag,I2S(R2I(this.dur)),TAG_SIZE)
                    call SetTextTagPosUnit(this.tag,this.caster,TAG_HEIGHT)
                endif

               //Deals the damage...Not every sword deals damage, only the caster
               if this.damage_inter > DAMAGE_INTER then
                    set TEMP_STRUCT = this
                    call GroupEnumUnitsInRange(TEMP_GROUP,GetUnitX(this.caster),GetUnitY(this.caster),SPIN_IMPACT_RANGE,SPIN_DAMAGE_FILTER)
                    set this.damage_inter = 0
                endif

            else

                //Launching the shards
                set TEMP_STRUCT = this
                call ForGroup(this.swords,function Launch)

                //Destroying the struct and recycle the index
                call this.destroy()
                set SpinData.Total = SpinData.Total - 1
                set SpinData.Index[inst] = SpinData.Index[SpinData.Total]
                set inst = inst - 1
            endif

            set inst = inst + 1
        endloop

        //No struct running no timer needed
        if SpinData.Total == 0 then
            call PauseTimer(SPIN_TIM)
        endif

    endfunction

    //The remains of GUI
    private function InitSpin takes nothing returns nothing

        local SpinData this
        local unit u = GetTriggerUnit()
        local integer i = 0
        
        loop
            exitwhen i == SpinData.Total
            set this = SpinData.Index[i]
            
            if u == this.caster then
                
                if TIME_STACK then
                    set this.dur = this.dur + GetDuration(GetUnitAbilityLevel(u,SID))
                    call SetTextTagAge(this.tag,0)
                    call SetTextTagLifespan(this.tag,this.dur)
                    call SetTextTagFadepoint(this.tag,this.dur-1)
                    set u = null
                    return
                endif
                
                if DAMAGE_STACK then
                    set this.spin_damage = this.spin_damage + GetSpinDamage(GetUnitAbilityLevel(u,SID))
                    set u = null
                    return
                endif
                
                return
                
            endif
            
            set i = i + 1
            
        endloop

        //Starting the spell and exchanging the abilities
        call SpinData.create(u)
        set u = null

        if SpinData.Total - 1 == 0 then
            call TimerStart(SPIN_TIM,SPIN_INTER,true,function Spin)
        endif

    endfunction

    //When the launcher ability is being cast the shards move instantly away
    private function InstantLaunch takes nothing returns nothing

        local SpinData this
        local integer inst = 0
        local unit u = GetTriggerUnit()

        //Looping thourgh all active instances to find out the caster
        loop
            exitwhen inst == SpinData.Total
            set this = SpinData.Index[inst]

            //When we found our caster we end the spell
            if u == this.caster then

                set this.dur = -1
                set u = null

                return
            endif

            set inst = inst + 1

        endloop

        set u = null

    endfunction


    //Checking the spell rawcode
    private function CheckSID takes nothing returns boolean
        return GetSpellAbilityId() == SID
    endfunction

    //Checking the rawcode for the instant launch ability
    private function CheckLID takes nothing returns boolean
        return GetSpellAbilityId() == LID
    endfunction

    //I don´t want to leak upon trigger creation
    private constant function AntiLeak takes nothing returns boolean
        return true
    endfunction

    //The initializer....
    private function Init takes nothing returns nothing

        local trigger t = CreateTrigger()
        local trigger t2 = CreateTrigger()
        local filterfunc f = Filter(function AntiLeak)
        local integer i = 0

        //Initializing some globals
        set SPIN_DAMAGE_FILTER = Filter(function SpinDamage)
        set SHOOT_DAMAGE_FILTER = Filter(function ShootDamage)
        set ShootData.MAX_X = GetRectMaxX(bj_mapInitialPlayableArea) - 100
        set ShootData.MAX_Y = GetRectMaxY(bj_mapInitialPlayableArea) - 100
        set ShootData.MIN_X = GetRectMinX(bj_mapInitialPlayableArea) + 100
        set ShootData.MIN_Y = GetRectMinY(bj_mapInitialPlayableArea) + 100

        //Registrating the Trigger
        loop
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
            call TriggerRegisterPlayerUnitEvent(t2,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,f)
            exitwhen i == 15
            set i = i + 1
        endloop

        //Preloading the SFX´s
        call Preload(SPAWN_SFX)
        call Preload(IMPACT_SFX)
        call Preload(DEATH_SFX)
        call PreloadStart()

        //Triger Registraion Part 2
        call TriggerAddCondition(t,Condition(function CheckSID))
        call TriggerAddCondition(t2,Condition(function CheckLID))
        call TriggerAddAction(t,function InitSpin)
        call TriggerAddAction(t2,function InstantLaunch)
        call DestroyFilter(f)
        set t = null
        set t2 = null
        set f = null

    endfunction

endscope


I have only recoded the globals and the config header so that the constants get inlined directly. This may reduce the loading times.
JASS:
scope SpinningShards initializer Init

    //User constants, feel free to experiment
    define private SID = 'spsw'
    //Place the spell Rawcode here

    define private DID = 'spsd'
    //Place the Dummy´s Rawcode here

    define private LID ='lnch'
    //Rawcode for the launcher ability

    define private TAG_RED = 255
    //How Red should the textag be ? NOTE: The value must be between 0 and 255

    define private TAG_BLUE = 255
    //How Blue should the textag be ? NOTE: The value must be between 0 and 255

    define private TAG_GREEN = 255
    //How Green should the textag be ? NOTE: The value must be between 0 and 255

    define private TAG_OPA = 0
    //How transparent should the textag be ? NOTE: The value must be between 0 and 255

    define private TIME_STACK = true
    //true = The caster will keep his shards when the spell is recasted and the duration increases
    //false = The caster shoots his shards away and creates new ones
    
    define private DAMAGE_STACK = false
    //true = The spells deals more AoE damage during the spinning phase when recasted
    //false = The spell won´t deal more AoE damage when recasting
    
    define private REMOVE_BY_HIT = false
    //true = The shards will disappear when they hit an enemy
    //false = The shards can travel trough enemies (deals more damage)

    define private SPREAD_OUT = false
    //true = Shoots every missile in its current facing direction
    //false = Shoots all missiles int the facing directon of the caster

    define private WANT_TEXT_TAG = true
    //true = Creates a time indicating floating text above the caster
    //false = No floating text is created

    define private IMPACT_SFX = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl"
    //The special effect being displayed when an enemy gets hit during the spinning phase

    define private SPAWN_SFX = "Abilities\\Spells\\Undead\\OrbOfDeath\\OrbOfDeathMissile.mdl"
    //The special effect being displayed when the shards are created

    define private DEATH_SFX = SPAWN_SFX
    //The special effect being displayed when the shards disappear

    define private IMPACT_ATTATCH = "head"
    //Where should the IMPACT_SFX be attatched on a target ?

    define private DIAMETER = 200
    //The diameter of the circle of the shards

    define private SPIN_INTER = 0.02
    //How fast should the shards spin ?

    define private ANGLE_ALTER = 13
    //How many degrees should the shards move per interval ?

    define private SHOOT_INTER = 0.03
    //How fast should the shards move when they shoot away ?

    define private SHOOT_DIST = 45
    //Which distance should a shard being moved per interval ?

    define private SHOOT_IMPACT_RANGE = 120
    //The range in which a shard can damae an enemy when it´s moving

    define private DAMAGE_INTER = 0.1
    //How long is the interval for damageing enemys when spinning around the caster ?

    define private SPIN_IMPACT_RANGE = 300
    //The AoE radius for dealing damage while the shards are spinning

    define private TAG_SIZE = 0.03
    //How large should a textag be (the values are some kinda weird)

    define private TAG_HEIGHT = 13
    //How far should the textag float above the caster ?
    
    define private GetSwordAmount (level) = lv * 2 + 1
    //Howmany shards should spawn related to the level ?
    
    define private GetImpactDamage (level) = level * 20 + 15
    //How much damage should a singe shard deal upon impact when they are launched ?
    
    define private GetShootDistance (level) = level * 250 + 650
    //How far should the shards travel when they are launched ?

    globals
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        //The spell privates. PLEASE DO NOT TOUCH !
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        private constant group TEMP_GROUP = CreateGroup()
        private constant timer SPIN_TIM = CreateTimer()
        private constant timer SHOOT_TIM = CreateTimer()
        private integer TEMP_STRUCT
        private filterfunc SPIN_DAMAGE_FILTER
        private filterfunc SHOOT_DAMAGE_FILTER
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-
        //_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-

    endglobals
    
    //Howmuch damage shall the enemies recieve per second when the sworeds are spinning
    private function GetSpinDamage takes integer level returns integer
        return level * 40 + 10
    endfunction

    //How long should the shards spin around the caster ?
    private function GetDuration takes integer level returns integer
        return level * 5 + 4
    endfunction

//_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-//
//_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-//
             //Beyond this line the code is the same as in the vJass version//
//_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-//
//_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-_-=-//


Keywords:
Summoned, Sword, Circle, Summon, AoE, DoT, shield, melee
Contents

Noch eine WARCRAFT-III-Karte (Map)

Reviews
20:26, 24th Jul 2009 Dr Super Good: Pretty impressive spells. Function and mechanics wise it is flawless. It also is structured pretty well for the code and people can easilly modify it. I also noticed no lag when using it multiple times at once...

Moderator

M

Moderator

20:26, 24th Jul 2009
Dr Super Good:
Evaluation

Pretty impressive spells. Function and mechanics wise it is flawless. It also is structured pretty well for the code and people can easilly modify it. I also noticed no lag when using it multiple times at once hitting multiple units at the same time. Only problem I noticed was the countdown timer messed up if it was cast multiple times at the same time on the same unit. It also does use custom models which are not toally nescescary, however as the rest of the spell looks prety good to me, ill overlook this fact. I however can recommend its use for almost any general standard WC3 hero map.

Suggestions . . .
- Fix the countdown / stack system. I think it should not stack more than once on a unit (recasting resets duration or adds damage) or else only one coutdown timer is displayed (the oldest displays). Currently if the spell is cast multiple at once on the same unit the countdown becomes unreadable and unusable.
- Try and remove the imported model, I do not think it is completly vital.

Advice: If you do not understand why this spell was given the rating it received or if you would like to ask questions about how to improve this spell. Feel free to send a private message to spell moderator Dr Super Good.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
Deut's Brief Spell Review:

[+]

1. Well-done efficient script


2. Bugless


3. MUI


4. Leakless


5. Very original and creative idea


6. Documented


7. Lagless


8. Nice special effects


9. User friendly and adjustable



[*]

Well not much to say other than this is a perfectly done spell which I'd advice people to use.

I skimmed through the script and it seems all ok to me.

Good job Thanathos! I like this spell the most among your spells, and it is one of the best I've seen around!
 
Last edited:
Level 9
Joined
Aug 2, 2008
Messages
219
@Deut thank you for the nice review^^

@DD well we´ve already talked about this, don´t what to add:wink:

@DSG this was quite a very fast review (rep+). I´ll fix the thing with the floating text ( adding more duration is a nice idea ) , but i think i won´t remove the custom model. I´ll make a alternative version of it which will use a default model.
 
Level 11
Joined
Jul 2, 2008
Messages
601
Am I the one, who think, that swords should fly in the direction, THEY face? In different directions. This would look more realistic, but maybe useless for WarCraft... Maybe not, dunno. But this will be eye-candy :)

And, ftw, Fear_The_Night is right! The swords fly in the facing direction of the last casting unit! oO

To Deuterium,
:p
 
Level 9
Joined
Aug 2, 2008
Messages
219
uhm about that facing stuff.....i´ve already fixed it, i just forgot to set the tempstruct...
i will update this tomorrow since i have to do some tests and minor improvements ,etcetera, etcetera

btw it´s really fun to play with the dummy model...i used some acolytes...it looked so weird, i think i´ll attatch some pics of model variations, instead of making an alternative to the swords.
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
TNT this is an idea that went through my mind yesterday as I was reviewing, but I forgot to mention it:

You'll need a second instant root ability. Basically, it's an ability attached to Summoned Swords.
When the swords are turning, you use that second ability to just skip the timer and throw the swords.

Get my point eh? What's the point of it? Let's say someone is escaping from the hero during the game, you start the Swords, and if you find out your too slow to get the kill, just throw the swords ;)
 
Level 9
Joined
Aug 2, 2008
Messages
219
Update v0.2

Deuterium said:
You'll need a second instant root ability. Basically, it's an ability attached to Summoned Swords.
When the swords are turning, you use that second ability to just skip the timer and throw the swords.
Excelent idea ! And this had also solved the timer bug and your review should be correct now too^^. I think i´ve extinct all bugs for now, but we can never now.

Aspard said:
Am I the one, who think, that swords should fly in the direction, THEY face? In different directions. This would look more realistic, but maybe useless for WarCraft... Maybe not, dunno. But this will be eye-candy :)
Nice idea and also applied. User can use a constant boolean for that now.

DSG said:
Well, you really should not use any imported models except if they are vital for the spell mechanics like the dummy model. Also make sure you credit the models as well, I did not check if you did so but it occured to me that you should.
Ofc your right i´ll try to use default models as soon i got some new ideas for the name and so on, but as you said the custom model is not vial for the mechianics but i think it´s vial for the idea of the spell. Changing the model wouldn´t affect the script but it would completely change the whole spell idea. Anyway i played a bit with the models in here is the result:

The vote has expired. Variation A has been chosen




Variation A (my favourite)
154238-albums1879-picture15313.png

Variation B
154238-albums1879-picture15314.png

Variation C
154238-albums1879-picture15315.png

Everyone is welcome to tell me (via VM or PM) what he/she likes best or may show me your own variotion (using default models).

Raziel br said:
Vergil from devil may cry have this spell...
some1 found out my real inspiration ^^
 
Last edited:
Level 17
Joined
Mar 17, 2009
Messages
1,349
VARIATION A! Don't even bothering waiting for opinions, go for A! =P

Well although Aspard mentioned that throwing swords in different directions makes more sense, i prefer keeping it as it is... that way it could be used as a "psychic spell" (ie mind controlling) .. ;)
 
Level 1
Joined
Jun 24, 2009
Messages
5
Wow!!! That's an awsome spell ;D. Still i think theres 1 bug. If u w8 until the timers at 0 and dont have shooted the swords away... U cant make em spinning again. Plz fix it... othervise AWSOME spell 100/100,0000000000000000000000000000001. gj
 
Level 9
Joined
Aug 2, 2008
Messages
219
Argh dammit i thoght i fixed that already....wasn´t shure if uploaded the right version but indeed it was the wrong one.... that bugfix will come along with the dummy model....And since Deut was the only one who voted for one of the variations i will wait a bit longer

[Edit]
Lulz the code i posted in the description does not have the bug boob_cake mentioned...Indeed i uploaded the wrong map. So that bug is fixed now with easy c´n´p. Well i still keep on waiting. Let´s say i use a new model in about 4 days.
 
Last edited:
Level 11
Joined
Jul 2, 2008
Messages
601
Are we still voting here? :D I like the third one - it seems really protecting, so if the units comes - he'll get damaged. ;) But what effect would it play, if launched? I can't even get the model of the specil effect.

So, the first one is nice. :)
 
Level 2
Joined
Apr 10, 2008
Messages
8
Hey, excellent spell, just found a small bug when testing on a different map. If the hero thats leveling this spell has other spells, and can learn a spell, while this spell is active, you can re-learn this spell (i think because you remove and re-add the ability to get the launch spell to work).

Either way, great spell ^_^
 
Level 4
Joined
Jun 1, 2009
Messages
87
Hey, excellent spell, just found a small bug when testing on a different map. If the hero thats leveling this spell has other spells, and can learn a spell, while this spell is active, you can re-learn this spell (i think because you remove and re-add the ability to get the launch spell to work).

Either way, great spell ^_^

yep i jsut found that bug when i tested the spell as well,
when the shards is spinning you can actually open "learn skill menu" and the spell is there to be learnt, however it will be level 1.

so if someone have this skills as level 3, they can learn it again and it be level 1.
 
Level 11
Joined
Oct 13, 2008
Messages
560
Can you import your spell on my map?

my map are in portuguease, sory about it, but i love your spell!!
If you can, can you change the sword model to seen more the summoned swords from vergil?
(don't laught from my map, he are not compleate, I'm working on dante and vergil, some thinks are bugged)

:grin:
 

Attachments

  • Animes vs Games (BR).w3x
    6.4 MB · Views: 54
Top