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

Arachnian Queen Spellpack v1.01b

These spells i made for a contest at IDGS forum.

Split Shoot

Ability Type: Active
Target Type: Point
Effect: Multi Directional Damage
Cooldown: 12 seconds
Mana Cost: 75/85/95/105

Description:
Shoots out a number of arrows in a single shoot, splitting into multiple directions, dealing damage to enemy units in their path.

Level 1 - Shoots 3 arrows, deals 30 damage each.
Level 2 - Shoots 4 arrows, deals 40 damage each.
Level 3 - Shoots 5 arrows, deals 50 damage each.
Level 4 - Shoots 6 arrows, deals 60 damage each.

Slows enemy units if the arrows are imbued with poison.
Egg Shack

Ability Type: Active
Target Type: None
Effect: Summon, Decreased Speed
Cooldown: 100 seconds
Mana Cost: 160/260/360

Description:
Creates an egg shack on her back, and carries it around for 15 seconds, slowing her by 10%. Once the shack hatches spawns 3 youngs to scout around and attack enemies. Lasts 30 seconds.

Level 1 - Summons 3 youngs that have normal attack.
Level 2 - Summons 3 youngs that have critical strike.
Level 3 - Summons 3 youngs that have critical strike and bash.

The egg shack drains a small amount hp/s until it hatches.
Web

Ability Type: Active
Target Type: None
Effect: Summon, Increased Attack Speed.
Cooldown: 30/25/20/15 seconds
Mana Cost: 100

Description:
Laying webs to Arachnian Queen location everytime she moves. If an enemy walks through a web, it's slowed for a few second. Web lasts for 10 seconds.

Level 1 - Slowed by 10%
Level 2 - Slowed by 20%.
Level 3 - Slowed by 30%.
Level 4 - Slowed by 40%.

She can pass through unit in this state, her movement speed also increased by 15%. Casting other spells while in this state will break this spell, you should casting the other spells first, then cast this spell in order to use those spells at the same time.

JASS:
library SplitShot initializer init requires xedamage, xecast, xecollider
//******************************************************************************
//*                                                                            *
//*                          Arachnian Queen Spellpack                         *
//*                                  v1.01b                                    *
//*                                                                            *
//*                  By: scorpion182 aka ranzi aka ada_aja                     *
//*                         http://www.jade-wars.com                           *
//*                                                                            *
//******************************************************************************   
//*************************************************************
//* Configuration Constants 
    globals
        private constant integer SPELL_ID='A000' //split shot ability rawcode 
        private constant integer SPELL_ID2='Apo2' //poison sting (orb of venom) rawcode
        private constant integer DUMMY_SPELL_ID='A004' //dummy slow rawcode
        private constant string DUMMY_ORDER="slow" //dummy slow order string
        private constant real SCALE=2.0 //missile scale
        private constant real RADIUS=75. //misssile radius
        private constant real TIME=1.5 //missile expirationTime
        private constant real SPEED=1000. //missile speed
        private constant real START_DISTANCE=50. //arrow distance from the caster
        private constant string NORMAL_FX="Abilities\\Weapons\\MoonPriestessMissile\\MoonPriestessMissile.mdl" //normal arrows
        private constant string POISON_A_FX="Abilities\\Weapons\\PoisonArrow\\PoisonArrowMissile.mdl" //poison arrows
        private constant string HIT_FX1="Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" //normal arrows
        private constant string HIT_FX2="Objects\\Spawnmodels\\Naga\\NagaBlood\\NagaBloodWindserpent.mdl" //poison arrows
    endglobals
    
    private constant function GetArrows takes integer lvl returns integer
        return 2+1*lvl //how many arrows each level
    endfunction
    
    private constant function GetDamage takes integer lvl returns real
        return 20.+10.*lvl// amount damage each missile
    endfunction

    private constant function GetConeAngle takes integer lvl returns real
        return 40. //total cone angle each level
    endfunction
    
    private function DamageOptions takes xedamage spellDamage returns nothing
        set spellDamage.dtype=DAMAGE_TYPE_UNIVERSAL
        set spellDamage.atype=ATTACK_TYPE_NORMAL
        set spellDamage.exception=UNIT_TYPE_STRUCTURE
        set spellDamage.visibleOnly=true
        set spellDamage.damageAllies=false       
    endfunction
//* Configuration End
//*****************************************************************
    globals
        private xedamage xed
        private xecast cast
    endglobals
    
    private function SetDummy takes xecast DummySpell returns nothing 
        set DummySpell.abilityid=DUMMY_SPELL_ID
        set DummySpell.orderstring=DUMMY_ORDER  
    endfunction
    
    private function IsEven takes real r returns boolean
        local integer i = R2I(r)
        set i = i/2
        set i= i+i
        return i == r
    endfunction
    
    //distance between X cord
    private function PolarProjectionX takes real x, real distance, real angle returns real
        return x+distance*Cos(angle * bj_DEGTORAD)
    endfunction
    //distance between Y cord
    private function PolarProjectionY takes real y, real distance, real angle returns real
        return y+distance*Sin(angle * bj_DEGTORAD)
    endfunction
    
    private struct missile extends xecollider
        unit caster
        integer lvl
        
        method onUnitHit takes unit target returns nothing
            
            
            if (this.caster != target) then
                call xed.damageTarget(this.caster,target, GetDamage(this.lvl))
                if (GetUnitAbilityLevel(this.caster,SPELL_ID2)==0) then
                    call DestroyEffect(AddSpecialEffectTarget(HIT_FX1,target,"origin"))
                else
                    call DestroyEffect(AddSpecialEffectTarget(HIT_FX2,target,"origin"))
                    
                    set cast.owningplayer = GetOwningPlayer(this.caster)
                    call cast.castOnTarget(target)
                endif
            endif
        endmethod
    endstruct
    
    private function SpellEffect takes nothing returns nothing
        local missile d
        local unit u
        local integer i=0
        local integer j=0
        local integer lvl
        local real x
        local real y
        local integer count
        local real angle
        local real facing=0.
        
        if GetSpellAbilityId() == SPELL_ID then
            set u=GetSpellAbilityUnit()
            set lvl=GetUnitAbilityLevel(u,SPELL_ID)
            set x=PolarProjectionX(GetUnitX(u),START_DISTANCE,GetUnitFacing(u))
            set y=PolarProjectionY(GetUnitY(u),START_DISTANCE,GetUnitFacing(u))
            set count=GetArrows(lvl)
            set angle=Atan2(GetSpellTargetY() - y, GetSpellTargetX() - x)
            
            if not IsEven(count) then
                set d=missile.create(x,y,angle+facing*bj_DEGTORAD)
                set d.scale=SCALE
                set d.collisionSize=RADIUS
                set d.direction=angle+facing*bj_DEGTORAD
                set d.expirationTime = TIME
                set d.speed = SPEED
                set d.caster=u
                set d.lvl=lvl
                
                if (GetUnitAbilityLevel(d.caster,SPELL_ID2)==0) then
                    set d.fxpath=NORMAL_FX
                else
                    set d.fxpath=POISON_A_FX
                endif
                    
                set i=i+1
                set facing=GetConeAngle(lvl)/count
                
                loop
                exitwhen j==count/2
                    set d=missile.create(x,y,angle+facing*bj_DEGTORAD)
                    set d.scale=SCALE
                    set d.collisionSize=RADIUS
                    set d.direction=angle+facing*bj_DEGTORAD
                    set d.expirationTime = TIME
                    set d.speed = SPEED
                    set d.caster=u
                    set d.lvl=lvl
                    
                    if (GetUnitAbilityLevel(d.caster,SPELL_ID2)==0) then
                        set d.fxpath=NORMAL_FX
                    else
                        set d.fxpath=POISON_A_FX
                    endif
                    
                    set facing=facing/2.
                    set i=i+1
                    set j=j+1
                endloop
                
                set j=1
                set facing=GetConeAngle(lvl)/count
                set facing=facing*-1
                loop
                exitwhen j>count/2
                    set d=missile.create(x,y,angle+facing*bj_DEGTORAD)
                    set d.scale=SCALE
                    set d.collisionSize=RADIUS
                    set d.direction=angle+facing*bj_DEGTORAD
                    set d.expirationTime = TIME
                    set d.speed = SPEED
                    set d.caster=u
                    set d.lvl=lvl
                    
                    if (GetUnitAbilityLevel(d.caster,SPELL_ID2)==0) then
                        set d.fxpath=NORMAL_FX
                    else
                        set d.fxpath=POISON_A_FX
                    endif
                    
                    set facing=facing/2.
                    set j=j+1
                    set i=i+1
                endloop
            else
                set facing=GetConeAngle(lvl)/count
                
                loop
                exitwhen j==count/2
                    set d=missile.create(x,y,angle+facing*bj_DEGTORAD)
                    set d.scale=SCALE
                    set d.collisionSize=RADIUS
                    set d.direction=angle+facing*bj_DEGTORAD
                    set d.expirationTime = TIME
                    set d.speed = SPEED
                    set d.caster=u
                    set d.lvl=lvl
                    
                    if (GetUnitAbilityLevel(d.caster,SPELL_ID2)==0) then
                        set d.fxpath=NORMAL_FX
                    else
                        set d.fxpath=POISON_A_FX
                    endif
                    
                    set facing=facing/2.
                    set i=i+1
                    set j=j+1
                endloop
                
                set j=1
                set facing=GetConeAngle(lvl)/count
                set facing=facing*-1
                loop
                exitwhen j>count/2
                    set d=missile.create(x,y,angle+facing*bj_DEGTORAD)
                    set d.scale=SCALE
                    set d.collisionSize=RADIUS
                    set d.direction=angle+facing*bj_DEGTORAD
                    set d.expirationTime = TIME
                    set d.speed = SPEED
                    set d.caster=u
                    set d.lvl=lvl
                    
                    if (GetUnitAbilityLevel(d.caster,SPELL_ID2)==0) then
                        set d.fxpath=NORMAL_FX
                    else
                        set d.fxpath=POISON_A_FX
                    endif
                    
                    set facing=facing/2.
                    set j=j+1
                    set i=i+1
                endloop                
            endif
                
                
        endif
        
        set u=null
    endfunction

    private function init takes nothing returns nothing
        //init spellcast trigger 
        local trigger t=CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction(t,function SpellEffect)
        
        //init xedamage
        set xed=xedamage.create()
        call DamageOptions(xed)
        
        //init xecast
        set cast = xecast.create()  
        call SetDummy(cast)
        
        //preload dummy ability
        call XE_PreloadAbility(DUMMY_SPELL_ID)
    endfunction

endlibrary



JASS:
//******************************************************************************
//*                                                                            *
//*                          Arachnian Queen Spellpack                         *
//*                                  v1.01b                                    *
//*                                                                            *
//*                  By: scorpion182 aka ranzi aka ada_aja                     *
//*                         http://www.jade-wars.com                           *
//*                                                                            *
//******************************************************************************
library Web initializer init requires xecollider, xecast, TimerUtils
//*************************************************************
//* Configuration Constants
    globals
        private constant integer SPELL_ID='A005' //web ability rawcode
        private constant integer BUFF_ID='B002' //web buff rawcode
        private constant integer SLOW_BUFF='Bslo' //slow buff rawcode
        private constant integer DUMMY_SPELL_ID='A001' //dummy slow rawcode
        private constant string DUMMY_ORDER="slow" //dummy slow order string
        private constant real RADIUS=150. //web collosion size radius
        private constant real HEIGHT=100. //web height
        private constant string FX="Abilities\\Weapons\\ChimaeraAcidMissile\\ChimaeraAcidMissile.mdl" //caster fx
        private constant string WEB_FX="Abilities\\Spells\\Undead\\Web\\WebTarget.mdl" //web fx
        private constant real SCALE=1.0 //web scale
        private constant string ATT_POINT="origin" //caster fx attachment point
        private constant real WEB_DURATION=10. //web duration
        private constant real MIN_DIST=100. //minimum distance between webs
        private constant real WEB_INTERVAL=0.35 //web create interval
    endglobals
//* Configuration End
//*****************************************************************
    globals
        private xecast cast
    endglobals

    private struct data
        unit caster
        timer t
        real x1=0
        real x2=0
        real y1=0
        real y2=0
        
        static method create takes unit u, timer t returns data
            local data d=data.allocate()
            
            set d.caster=u
            set d.t=t
            
            return d
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct
    
    private function SetDummy takes xecast DummySpell returns nothing 
        set DummySpell.abilityid=DUMMY_SPELL_ID
        set DummySpell.orderstring=DUMMY_ORDER  
    endfunction
    
    private function IsSlowed takes unit u returns boolean
        return GetUnitAbilityLevel(u,SLOW_BUFF)>0
    endfunction
    
    private struct web extends xecollider
        unit caster
        
        method onUnitHit takes unit target returns nothing
            local xecast xc
            
            if (this.caster != target and IsSlowed(target)==false) then
                set xc=xecast.createA()
                set cast.owningplayer = GetOwningPlayer(this.caster)
                call cast.castOnTarget(target)
            endif
        endmethod
    endstruct

    private function Check takes nothing returns nothing
        local timer t=GetExpiredTimer()
        local data d=data(GetTimerData(t))
        local real dx = d.x2 - d.x1
        local real dy = d.y2 - d.y1
        local real dis= SquareRoot(dx * dx + dy * dy) 
        local web xc
        
        if (GetUnitAbilityLevel(d.caster,BUFF_ID)>0) then
        
            set d.x1=d.x2
            set d.y1=d.y2
            
            if (dis>MIN_DIST) then
                set xc=web.create(GetUnitX(d.caster),GetUnitY(d.caster),GetUnitFacing(d.caster))
                set xc.scale=SCALE
                set xc.collisionSize=RADIUS
                set xc.expirationTime=WEB_DURATION
                set xc.fxpath=WEB_FX
                set xc.z=HEIGHT
                set xc.caster=d.caster
            endif
            
            set d.x2=GetUnitX(d.caster)
            set d.y2=GetUnitY(d.caster)
            
            call DestroyEffect(AddSpecialEffectTarget(FX,d.caster,ATT_POINT))
        else
            call d.destroy()
        endif
    endfunction
    
    private function Actions takes nothing returns nothing
        local unit u
        local timer t
        local data d
        
        if GetSpellAbilityId() == SPELL_ID then
            set u=GetSpellAbilityUnit()
            set t=NewTimer()
            set d=data.create(u,t)
            call SetTimerData(t,integer(d))
            call TimerStart(t,WEB_INTERVAL,true,function Check)
        endif
        
        set u=null
    endfunction

    private function init takes nothing returns nothing
        //init spellcast trigger 
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddAction(t, function Actions )
        
        //init xecast
        set cast = xecast.create()  
        call SetDummy(cast)
        
        //preload dummy ability
        call XE_PreloadAbility(DUMMY_SPELL_ID)
    endfunction

endlibrary



JASS:
//******************************************************************************
//*                                                                            *
//*                          Arachnian Queen Spellpack                         *
//*                                  v1.01b                                    *
//*                                                                            *
//*                  By: scorpion182 aka ranzi aka ada_aja                     *
//*                         http://www.jade-wars.com                           *
//*                                                                            *
//******************************************************************************
library Eggshack initializer init requires xefx, TimerUtils
//*************************************************************
//* Configuration Constants
    globals 
        private constant integer SPELL_ID='A006' //eggshack ability rawcode
        private constant integer BUFF_ID='B004' //eggshack buff
        private constant integer BEETLE='ucs1' //beetle unit rawcode
        private constant integer DUMMY_ID='e000' //dummy unit rawcode
        private constant string FX="Doodads\\Dungeon\\Terrain\\EggSack\\EggSack1.mdl" //eggshack fx
        private constant integer NUM=3 //how many beetle spawns
        private constant real EGG_DISTANCE=-35.0 //egg distance from caster
        private constant real EGG_HEIGHT=100. //egg height
        private constant real PATROL_RADIUS=500. //beetle spawns patrol radius
        private integer array B_ABILITY[3]
    endglobals
    
    //beetle spawn abilities
    private function InitBSpells takes nothing returns nothing
        //set B_ABILITY[0]='ACct'
        set B_ABILITY[1]='ACct' //critical strike
        set B_ABILITY[2]='ACbh' //bash
        //...and so on
    endfunction
    
    private constant function Duration takes integer lvl returns real
        return 30.+0.*lvl //beetle spawns duration
    endfunction
    
    private constant function LifeCost takes integer lvl returns real
        return 5.*lvl //life cost per second
    endfunction
//* Configuration End
//*****************************************************************
    private struct data
        unit caster
        timer t
        unit Egg
        unit array Beetle[NUM]
        boolean patrol=false
        real counter=0.
        real hpcost=0.
        integer lvl
        xefx fx
        
        static method create takes unit c, timer t returns data
            local data d=data.allocate()
            local integer lvl=GetUnitAbilityLevel(c,SPELL_ID)
            
            set d.caster=c
            set d.t=t
            set d.counter=Duration(lvl)
            set d.hpcost=LifeCost(lvl)
            set d.lvl=lvl
            set d.fx=xefx.create(GetUnitX(c),GetUnitY(c),GetUnitFacing(c))
            set d.fx.z=EGG_HEIGHT
            set d.fx.fxpath=FX
            
            return d
        endmethod
        
        private method onDestroy takes nothing returns nothing
            call ReleaseTimer(.t)
        endmethod
    endstruct

    //distance between X cord
    private function PolarProjectionX takes real x, real distance, real angle returns real
        return x+distance*Cos(angle * bj_DEGTORAD)
    endfunction
    //distance between Y cord
    private function PolarProjectionY takes real y, real distance, real angle returns real
        return y+distance*Sin(angle * bj_DEGTORAD)
    endfunction

    private function Check takes nothing returns nothing
        local timer t=GetExpiredTimer()
        local data d=data(GetTimerData(t))
        local real x=PolarProjectionX(GetUnitX(d.caster),EGG_DISTANCE,GetUnitFacing(d.caster))
        local real y=PolarProjectionY(GetUnitY(d.caster),EGG_DISTANCE,GetUnitFacing(d.caster))
        local rect r
        local integer i=0
        
        if (GetUnitAbilityLevel(d.caster,BUFF_ID)>0) then
            set d.fx.x=x
            set d.fx.y=y
            set d.fx.z=EGG_HEIGHT+GetUnitFlyHeight(d.caster)
            call SetUnitState(d.caster,UNIT_STATE_LIFE,GetUnitState(d.caster,UNIT_STATE_LIFE)-d.hpcost*.035)
            call TimerStart(t,XE_ANIMATION_PERIOD,false,function Check)
        elseif (d.patrol==false) then
            call d.fx.destroy()
            set d.patrol=true
            loop
            exitwhen i>NUM-1
                set d.Beetle[i]=CreateUnit(GetOwningPlayer(d.caster),BEETLE,GetUnitX(d.caster),GetUnitY(d.caster),0)
                call UnitApplyTimedLife(d.Beetle[i],'BTLF',d.counter)
                //--add ability--
                if (d.lvl==2) then
                    call UnitAddAbility(d.Beetle[i],B_ABILITY[1])
                elseif (d.lvl==3) then
                    call UnitAddAbility(d.Beetle[i],B_ABILITY[1])
                    call UnitAddAbility(d.Beetle[i],B_ABILITY[2])
                endif
                //--------------
                set i=i+1
            endloop
            call TimerStart(t,XE_ANIMATION_PERIOD,false,function Check)
        elseif (d.patrol==true and GetWidgetLife(d.caster)>0.405) then 
            set r = Rect(GetUnitX(d.caster)-PATROL_RADIUS, GetUnitY(d.caster)-PATROL_RADIUS, GetUnitX(d.caster)+PATROL_RADIUS, GetUnitY(d.caster)+PATROL_RADIUS)
        
            set i=0
            loop
            exitwhen i>NUM-1
            
                set x=GetRandomReal(GetRectMinX(r), GetRectMaxX(r))
                set y=GetRandomReal(GetRectMinY(r), GetRectMaxY(r))
            
                call IssuePointOrder(d.Beetle[i],"patrol",x,y)
            
                set i=i+1
            
            endloop
        
            if (d.counter>0.) then
                call TimerStart(t,1.0,false,function Check)
                set d.counter=d.counter-1.0
            else 
                call d.destroy()
            endif
        
            call RemoveRect(r)
        elseif (GetWidgetLife(d.caster)<=0.405) then
            call d.destroy()
        endif
        
        set r=null
    endfunction
    
    private function Actions takes nothing returns nothing
        local timer t
        local unit u
        local data d
        
        if GetSpellAbilityId() == SPELL_ID then
            set t=NewTimer()
            set u=GetSpellAbilityUnit()
            set d=data.create(u,t)
            call SetTimerData(t,integer(d))
            call TimerStart(t,XE_ANIMATION_PERIOD,false,function Check)
        endif
        
        set u=null
    endfunction

    private function init takes nothing returns nothing
        local trigger t = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddAction(t, function Actions )
        call InitBSpells()
    endfunction

endlibrary


Requires:
- TimerUtils by Vexorian
- xe by Vexorian
- PUI (for map testing purpose only: creep revival things, not required by the spells) by Cohadar

History
[x] v1.01b Updated 1 - Remove unnecessary codes.
[x] v1.01b - Remove Poison Tip, icon and model from the spellpack.
[x] v1.01 - Fixed what Deaod said (Poison Tip still PUI, I don´t really know how to make it fully MUI), remove the GroupUtils from the requirement, the spells use xe now.
[x] v1.00 - Initial Release

Keywords:
nerubian, queen, arachnian, spider, egg, hatch, arrow, arrows, multiple, combo, combination, hero, spellpack
Contents

Arachnian Queen v1.01b (Map)

Reviews
12:00, 29th Dec 2009 TriggerHappy: You should probably not use PUI, and use something like AutoIndex. IIRC, PUI was depreciated at wc3c. Overall the spells were good.

Moderator

M

Moderator

12:00, 29th Dec 2009
TriggerHappy:

You should probably not use PUI, and use something like AutoIndex. IIRC, PUI was depreciated at wc3c.

Overall the spells were good.
 
Level 10
Joined
Sep 21, 2007
Messages
517
Good spells man, i like the oldschool programming ;P its pretty good code, and not too simple and not too hard spells. They seem pretty well coordinated; hmm the only thing im unsure of is if im supposed to give it a 4 or a 5, i mean its pretty good, but not astounding... i would rather give a 4.5 or so ;P but hey, round up the 4.5 and u get a 5 ey? >_>

things to fix:

make sure the arrows dont start at the origin of the unit, just a distance farther so it doesnt look like the arrows are coming out of the spiders belly from the ground :p and increase the arrows heights a bit

overall i like the sfx, not too much, but just in the middle ^^

care to tell me what CopyGroup() function does? never really experimented with it >_>
 
Level 16
Joined
Jun 9, 2008
Messages
734
Good spells man, i like the oldschool programming ;P its pretty good code, and not too simple and not too hard spells. They seem pretty well coordinated; hmm the only thing im unsure of is if im supposed to give it a 4 or a 5, i mean its pretty good, but not astounding... i would rather give a 4.5 or so ;P but hey, round up the 4.5 and u get a 5 ey? >_>

things to fix:

make sure the arrows dont start at the origin of the unit, just a distance farther so it doesnt look like the arrows are coming out of the spiders belly from the ground :p and increase the arrows heights a bit

overall i like the sfx, not too much, but just in the middle ^^

care to tell me what CopyGroup() function does? never really experimented with it >_>

That function receives a group as a parameter. Then it uses a bj global variable called bj_groupAddGroupDest which will become a group. This group will then receive all units the group passed as an argument has due the ForGroup.
 
Level 14
Joined
Nov 18, 2007
Messages
816
Split Shot:
  • Some hardcoded values here and there
  • Very trivial spell using xefx/xecast/xecollider.
  • Make use of the global ENUM_GROUP GroupUtils provides.
  • Use boolexprs to perform actions on multiple units.

Poison Tip:
  • High OE dependencies. Is there any way to avoid these?
  • Only one instance per player allowed. Ill try to explain why: You disable the ability for a player, even though another instance of this spell might still be running.
  • You couldve outsourced the preloading to xe (this applies to multiple spells, but is only noted here).
  • You could have used libraries instead of scopes for improved error reporting. It also wouldve saved you from mentioning the dependencies of the individual spells, which you failed to do, btw. Again, this applies to all of these spells.

Web:
  • High OE dependencies, again. Are any of those avoidable?
  • You couldve saved a SquareRoot call by squaring both sides of the equation: if (dis>MIN_DIST) then
  • You dont have to null local timers when using TimerUtils. Still, its not like doing so is bad style or anything. Just a general note for you.

Egg Shack:
  • Using HP to decide if a unit is alive or not is bad practice. It can break if you increase the health of a unit after it has died.
  • Again, im seeing some hardcoded values.
 
Level 16
Joined
Jun 9, 2008
Messages
734
Split Shot:
  • Some hardcoded values here and there
  • Very trivial spell using xefx/xecast/xecollider.
  • Make use of the global ENUM_GROUP GroupUtils provides.
  • Use boolexprs to perform actions on multiple units.

Poison Tip:
  • High OE dependencies. Is there any way to avoid these?
  • Only one instance per player allowed. Ill try to explain why: You disable the ability for a player, even though another instance of this spell might still be running.
  • You couldve outsourced the preloading to xe (this applies to multiple spells, but is only noted here).
  • You could have used libraries instead of scopes for improved error reporting. It also wouldve saved you from mentioning the dependencies of the individual spells, which you failed to do, btw. Again, this applies to all of these spells.

Web:
  • High OE dependencies, again. Are any of those avoidable?
  • You couldve saved a SquareRoot call by squaring both sides of the equation: if (dis>MIN_DIST) then
  • You dont have to null local timers when using TimerUtils. Still, its not like doing so is bad style or anything. Just a general note for you.

Egg Shack:
  • Using HP to decide if a unit is alive or not is bad practice. It can break if you increase the health of a unit after it has died.
  • Again, im seeing some hardcoded values.

thanks for the feedbacks and review my codes, i gonna fix it later :grin:. And what's OE :confused:?
 
Top