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

Rain of Cold Arrows v1.04

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Description:


Archer jumps back into air shooting arrows at target point. Enemy hitted by arrows are slowed by 50% for 3 seconds.​


Video:




Requires:

[self=https://github.com/nestharus/JASS/tree/master/jass/Systems/ConstantTimerLoop32]CTL[/self]​
[self=https://github.com/nestharus/JASS/tree/master/jass/Systemswor]World Bounds[/self]​
[self=http://www.hiveworkshop.com/forums/jass-resources-412/snippet-isdestructabletree-248054/]IsDestructableTree[/self]​
[self=http://www.hiveworkshop.com/forums/jass-resources-412/snippet-spelleffectevent-187193/]SpellEffectEvent[/self]​
[self=http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/]RegisterPlayerUnitEvent[/self]​


Code:

JASS:
scope RainOfArrow //version 1.04
/*---------------------------------------------------------------------------------------------------------
*
*       Requires:
*
*-----------------------------------------------------------------------------------------------------------
*
*   - CTL                       [By Nestharus]
*   - WorldBounds               [By Nestharus]
*   - IsDestructableTree        [By PitzerMike]
*   - SpellEffectEvent          [By Bribe]
*   - RegisterPlayerUnitEvent   [By Magtheridon9]
*
*-----------------------------------------------------------------------------------------------------------
*
*       How to import:
*
*-----------------------------------------------------------------------------------------------------------
*
*   - Copy Rain of Cold Arrows Ability from object editor ---> Abilities
*   - Copy Rain of Cold Arrows (slow) Ability from objest editor ---> Abilities
*   - Copy Rain of Cold Arrows (slow) Buff from object editor ---> Buffs/Effects
*   - Copy Rain of Cold Arrows - Dummy 1 from objedt editor ---> Units
*   - Copy Rain of Cold Arrows - Dummy 2 from object editor ---> Units
*   - Copy Rain of Cold Arrows Trigger from Trigger editor
*   - Copy Libraries folder from Trigger editor
*
*-----------------------------------------------------------------------------------------------------------
*
*       Changelog:
*
*-----------------------------------------------------------------------------------------------------------
*
*       v1.0 
*       - First release.
*       v1.01
*       - Moved Fire struct over Jump struct.
*       - Removed onCast functions and inlined in to onRun function changing it's name to onCast.
*       - Speed[this] now have value of global varaiable SPEED not 10 like it was before.
*       - Removed unused libraries.
*       v1.02
*       - Added Z damage range dor now arrows can hit flying units.
*       - Added dummy death effect.
*       - Added SlowFilter function.
*       - Now you can spawn more than arrows at once.
*       - Removed GroupUtils and now using one group for damage
*       - Privatized Fire struct
*       v1.03
*       - Removed some leaks
*       - Now using one dummy to apply slow
*       - Renamed some globals
*       - Remove unused dummy
*       v1.04
*       - Changed some globals named
*       - Now using global dmmy to apply debuffs
*       
*-----------------------------------------------------------------------------------------------------------*/

/**************************************************************************************
*                                                                                     *
*                                   CONFIGURATION                                     *
*                                                                                     *                                               
**************************************************************************************/

    globals
        /*Main ability rawcode*/
        private constant integer        SPELL_CODE      =   'A000'
        /*Slow ability rawcode*/
        private constant integer        SLOW_CODE       =   'A001'
        /*/Dummy - 1 rawcode*/
        private constant integer        DUMMY_CODE      =   'h000'
        /*Dummy - 2 rawcode*/
        private constant integer        DUMMY_CODE2     =   'h003'
        /*Storm crow ability rawcode*/
        private constant integer        CROW_CODE       =   'Arav'
        
        /*Max jump height*/
        private constant real           MAX_HEIGHT      =   225
        /*Jump total distance traveled*/
        private constant real           DISTANCE        =   250
        /*Jump move speed*/
        private constant real           SPEED           =   10
        
        /*Arrows spawn in signle shot*/
        private constant integer        S_AMMOUT        =   2
        /*Distance at which archer will start shooting arrows*/
        private constant real           S_DISTANCE      =   70            
        /*Jump move speed when only shooting*/                           
        private constant real           S_SPEED         =   1.00
        /*Shoting dummy height. It's caster's height + this value
        to make arrows appear from bow not from feet*/
        private constant real           S_HEIGHT        =   80
        /*Arrows size 1 = 100%, 0.5 = 50%*/
        private constant real           S_SCALE         =   1.10
        /*Arrows will not spawn on caster*/
        /*It will spawn on caster's location + this value*/
        private constant real           S_CREATE_OFF    =   20
        
        /*Caster's animation while shooting*/
        private constant string         S_ANIM          =   "attack"
        /*Every X timer ticks (0.031250) player caster's animation*/
        private constant integer        S_ANIM_CD       =   6
        /*Every X timer ticks (0.031250) spawn arrow*/
        private constant integer        S_SPAWN_CD      =   5
        
        /*Arrows move speed*/
        private constant real           F_SPEED         =   25
        /*Arrows death animation when it land on the ground*/
        private constant string         F_ANIM          =   "death"
        /*Arrows death effect size*/
        private constant real           F_D_SCALE       =   1
        /*Arrows death effect expiration time*/
        private constant real           F_D_LT          =   1.2
        /*Arrows death effect animation*/
        private constant string         F_D_ANIM        =   "death"
        
        /*Arrows damage range*/
        private constant real           DAMAGE_RANGE    =   50
        /*Arrows Z damage range*/
        private constant real           Z_DAMAGE_RANGE  =   25
        /*Damage and attack type*/
        private constant attacktype     ATTACK_TYPE     =   ATTACK_TYPE_MAGIC
        private constant damagetype     DAMAGE_TYPE     =   DAMAGE_TYPE_DEATH
        
        /*Should arrows kill trees?*/
        private constant boolean        DESTROY_TREE    =   true
        /*Should arrows slow enemy targets?*/
        private constant boolean        SLOW            =   true
        
    endglobals
    
/**************************************************************************************
*                                                                                     *
*                                FUNCTIONS CONFIGURATION                              *
*                                                                                     *                                               
**************************************************************************************/
    
    /*Damage dealt per arrow in DAMAGE_RANGE*/
    private function GetDamage takes integer level returns real
        return level * 15.00
    endfunction
    
    /*Arena of effect. Arrows will move from caster's location*/
    /*to random point in target location based on this value*/
    private function GetAoE takes integer level returns real
        return level * 25.00 + 75.00
    endfunction
    
    /*Total ammout of arrows spawned*/
    private function GetArrows takes integer level returns integer
        return level * 5 + 15
    endfunction
    
    /*Damage filter function, you can set which units should not be damaged by spell*/
    private function TargetFilter takes unit u, player p returns boolean
        return IsUnitEnemy(u, p) and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)
    endfunction
    
    private function SlowFilter takes unit u, player p returns boolean
        return IsUnitEnemy(u, p) and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL)
    endfunction
    
/**************************************************************************************
*                                                                                     *
*                                 CONFIGURATION END                                   *
*                                                                                     *                                               
**************************************************************************************/
    
    private function ParabolaZ2 takes real y0, real y1, real h, real d, real x returns real
        local real A = (2*(y0+y1)-4*h)/(d*d)
        local real B = (y1-y0-A*d*d)/d
        return A*x*x + B*x + y0
    endfunction
    
    private function GetDist takes real x1, real y1, real x2, real y2 returns real
        return SquareRoot(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)))
    endfunction
    
    private function Tree_Kill takes nothing returns boolean
        local destructable dummy = GetFilterDestructable()
        if IsDestructableTree(dummy) then
            call KillDestructable(dummy)
        endif
        set dummy = null
        return false
    endfunction
    
/**************************************************************************************
*                                                                                     *
*                                   ARROWS MOVEMENT                                   *
*                                                                                     *                                               
**************************************************************************************/
    
    private struct Fire
    
        private static unit array dummy         /*Dummy*/
        private static unit array sDummy        /*Slow dummy*/
        private static player array owner       /*Dummy owner*/
        
        private static real array targetx       /*Spell Target X*/
        private static real array targety       /*Spell Target Y*/
        
        private static real array distance      /*Arrows Distance traveled*/
        private static real array angle         /*Arrows Move angle*/
        private static real array speed         /*Arrows Move speed*/
        
        private static real array height        /*Arrows height*/    
        private static real array heightDec     /*Arrows height decrease*/
        
        private static real array damage        /*Arrows damage*/
        
        private static rect array treeRect      /*Rect for tree kill*/
        private static group array damageGroup  /*Group to pick units for damage*/
    
        implement CTL
        
            local unit t            /*Damaged unit*/
            local unit de           /*Death effect dummy*/
            local real tx           /*Damaged unit X*/
            local real ty           /*Damaged unit Y*/
            local real dx           /*Arrow location X*/
            local real dy           /*Arrow location Y*/
            local real mx           /*Arrow move location X*/
            local real my           /*Arrow move location Y*/
            local real th           /*Target height*/
        
        implement CTLExpire
        
            /*Arrows move*/
        
            set dx = GetUnitX(dummy[this])
            set dy = GetUnitY(dummy[this])
            
            set mx = dx + speed[this] * Cos(angle[this])
            set my = dy + speed[this] * Sin(angle[this])
            
            /*World bound check*/
            
            if (mx < WorldBounds.maxX and mx > WorldBounds.minX and my < WorldBounds.maxY and my > WorldBounds.minY) then
            
                call SetUnitX(dummy[this], mx)
                call SetUnitY(dummy[this], my)
                
            else
            
                set distance[this] = 0
            
            endif
            
            /*Arrows height*/
            
            set height[this] = height[this] - heightDec[this]
            
            call SetUnitFlyHeight(dummy[this], height[this], 0)
            
            set distance[this] = distance[this] - speed[this]
            
            /*Damage*/
        
            call GroupEnumUnitsInRange(damageGroup[this], mx, my, DAMAGE_RANGE, null) 
        
            loop
                set t = FirstOfGroup(damageGroup[this])
                exitwhen t == null
                
                set th = GetUnitFlyHeight(t)
            
                if TargetFilter(t, owner[this]) and height[this] > th  - Z_DAMAGE_RANGE and height[this] < th + Z_DAMAGE_RANGE then
            
                    call UnitDamageTarget(dummy[this], t, damage[this], false, true, ATTACK_TYPE, DAMAGE_TYPE, null)
                    
                    /*Slowing damaged units*/
                    
                    static if SLOW then
                        
                        if SlowFilter(t, owner[this]) then
                            
                            call IssueTargetOrder(sDummy[this], "slow", t)
                            
                        endif  
                        
                    endif
                    
                    /*Ending arrow move*/
                    
                    set distance[this] = 0
                
                endif
            
                call GroupRemoveUnit(damageGroup[this], t)
            
            endloop
            
            /*Tree Kill*/
            
            static if DESTROY_TREE then
                call SetRect(treeRect[this], mx - DAMAGE_RANGE, my - DAMAGE_RANGE, mx + DAMAGE_RANGE, my + DAMAGE_RANGE)
                call EnumDestructablesInRect(treeRect[this],function Tree_Kill,null)
            endif
            
            /*Arrow move end*/
            
            if distance[this] <= 0 then
            
                call SetUnitAnimation(dummy[this], F_ANIM)
                call UnitApplyTimedLife(dummy[this], 'BTLF', 0.75)
                
                /*Arrows death effect*/
                
                set de = CreateUnit(owner[this], DUMMY_CODE2, mx, my, angle[this] * bj_RADTODEG)
                
                call SetUnitAnimation(de, F_D_ANIM)
                call SetUnitScale(de, F_D_SCALE, 0, 0)
                call UnitApplyTimedLife(de, 'BTLF', F_D_LT)
                call SetUnitFlyHeight(de, height[this], 0) 
                
                call DestroyGroup(damageGroup[this])
                
                call KillUnit(sDummy[this])
                
                set de = null
                set sDummy[this] = null
                set dummy[this] = null
                set owner[this] = null
                set damageGroup[this] = null
                
                call destroy()
            
            endif
        
        implement CTLNull
        implement CTLEnd
    
        static method onFire takes unit d, player p, integer lvl, real tx, real ty, real dHeight returns nothing
        
            local thistype this = create()
            
            local real AoE = GetAoE(lvl)
            local real dx = GetUnitX(d)
            local real dy = GetUnitY(d)
            local real RT
            
            set dummy[this] = d
            set owner[this] = p
            
            /*Arrow destination location*/
            
            set targetx[this] = tx + AoE * Cos(GetRandomReal(0, 360))
            set targety[this] = ty + AoE * Sin(GetRandomReal(0, 360))
            
            set angle[this] = Atan2(targety[this] - dy, targetx[this] - dx)
            set distance[this] = GetDist(dx, dy, targetx[this], targety[this])
            
            set speed[this] = F_SPEED
            
            set damage[this] = GetDamage(lvl)
            set damageGroup[this] = CreateGroup()
            
            /*Calcultaing time needed for arrows reach target location*/
            
            set RT = distance[this] / speed[this]
            set RT = RT * 0.031250
            
            /*Calculating height decrease based on arrows time needed to reach target location*/
            
            set height[this] = dHeight
            set heightDec[this] = height[this] / (RT / 0.031250)
            
            /*Tree kill rect*/
            
            static if DESTROY_TREE then
                set treeRect[this] = Rect(0, 0, 0, 0)
            endif
            
            /*Slow apply dummy*/
            
            set sDummy[this] = CreateUnit(owner[this], DUMMY_CODE, dx, dy, 0)
            
            call ShowUnit(sDummy[this], false)
            call UnitAddAbility(sDummy[this], SLOW_CODE)
            call SetUnitAbilityLevel(sDummy[this], SLOW_CODE, lvl)
        
        endmethod
    
    endstruct
    
/**************************************************************************************
*                                                                                     *
*                             ARCHER JUMP + ARROW SPAWN                               *
*                                                                                     *                                               
**************************************************************************************/
    
    private struct Jump extends array
    
        private static unit array caster        /*caster*/
        private static player array owner       /*caster's owner*/
        
        private static real array cDistance     /*Current distance for parabola function*/
        private static real array mDistance     /*Maximum distance for parabola funcrion*/          
        private static real array speed         /*Caster move speed*/
        private static real array angle         /*Caster move angle*/
        
        private static real array targetx       /*Spell Target X*/
        private static real array targety       /*Spell Target Y*/
        
        private static integer array spawnCD    /*Arrows spawn cooldown*/
        private static integer array spawnCCD   /*Arrows spawn cooldown*/
        private static integer array ammout     /*Arrows total ammout*/
        private static integer array count      /*Arrows current ammout*/
        
        private static integer array animCD     /*Caster animation cooldown*/
        private static integer array animCCD    /*Caster animation cooldown*/
        private static integer array level      /*Caster ability level*/
    
        implement CTL
        
            local unit d            /*Arrow dummy*/
            local real cx           /*Caster location X*/
            local real cy           /*Caster location Y*/
            local real mx           /*Caster move X*/
            local real my           /*Caster move Y*/
            local real crx          /*Arrow create X*/
            local real cry          /*Arrow create Y*/
            local real height       /*Caster height*/
            local integer index = 0 /*For arrows spawn loop*/
        
        implement CTLExpire
        
            /*Caster movement*/
        
            set cx = GetUnitX(caster[this])
            set cy = GetUnitY(caster[this])
            
            set mx = cx - speed[this] * Cos(angle[this])
            set my = cy - speed[this] * Sin(angle[this])
            
            /*World bound check*/
            
            if (mx < WorldBounds.maxX and mx > WorldBounds.minX and my < WorldBounds.maxY and my > WorldBounds.minY) then
            
                call SetUnitX(caster[this], mx)
                call SetUnitY(caster[this], my)
                
            endif
            
            /*Caster height*/
            
            set height = ParabolaZ2(0, 0, MAX_HEIGHT, mDistance[this], cDistance[this])
            
            call SetUnitFlyHeight(caster[this], height, 0)
            
            /*Distance traveled*/
            
            set cDistance[this] = cDistance[this] + speed[this]
            
            /*Shooting arrows*/
            
            if cDistance[this] > S_DISTANCE and count[this] < ammout[this] then
            
                /*Reducing move speed*/
            
                set speed[this] = S_SPEED 
                
                set spawnCCD[this] = spawnCCD[this] + 1
                set animCCD[this] = animCCD[this] + 1
                
                /*Caster's animation*/
                
                if animCCD[this] == animCD[this] then
                
                    call SetUnitAnimation(caster[this], S_ANIM)
                    set animCCD[this] = animCCD[this] - animCD[this]
                
                endif
                
                /*Arrows spawn*/
                
                if spawnCCD[this] == spawnCD[this] then
                
                    loop
                
                        set crx = cx + S_CREATE_OFF * Cos(angle[this])
                        set cry = cy + S_CREATE_OFF * Sin(angle[this])
                
                        set d = CreateUnit(owner[this], DUMMY_CODE, crx, cry, angle[this] * bj_RADTODEG)
                    
                        /*Arrow move struct call*/
                        call Fire.onFire(d, owner[this], level[this], targetx[this], targety[this], height + S_HEIGHT)
                    
                        call SetUnitFlyHeight(d, height + S_HEIGHT, 0)
                        call SetUnitScale(d, S_SCALE, 0, 0)
                    
                        /*Calculating ammout of arrows shooted*/
                        set count[this] = count[this] + 1
                        
                        set index = index + 1
                        
                        exitwhen index == S_AMMOUT or count[this] == ammout[this]
                        
                        set d = null
                    
                    endloop
                    
                    set spawnCCD[this] = 0
                
                endif
                
            else
            
                /*Changing speed to norma*/
            
                set speed[this] = SPEED
            
            endif
            
            /*Jump end*/
            
            if cDistance[this] >= mDistance[this] then
            
                call SetUnitFlyHeight(caster[this], 0, 0)
                call PauseUnit(caster[this], false)
            
                set caster[this] = null
                set owner[this] = null
                
                call destroy()
            
            endif
        
        implement CTLNull
        implement CTLEnd
        
        private static method onCast takes nothing returns nothing
        
            local thistype this = create()
            
            local real cx
            local real cy
            
            set caster[this] = GetTriggerUnit()
            set owner[this] = GetTriggerPlayer()
            set level[this] = GetUnitAbilityLevel(caster[this], SPELL_CODE)
            
            set cx = GetUnitX(caster[this])
            set cy = GetUnitY(caster[this])
            
            set targetx[this] = GetSpellTargetX()
            set targety[this] = GetSpellTargetY()
            
            set mDistance[this] = DISTANCE
            set cDistance[this] = 0
            
            set speed[this] = SPEED
            
            set count[this] = 0
            set ammout[this] = GetArrows(level[this])
            
            set animCD[this] = S_ANIM_CD
            set animCCD[this] = 0
            
            set spawnCD[this] = S_SPAWN_CD
            set spawnCCD[this] = 0
            
            set angle[this] = Atan2(targety[this] - cy, targetx[this] - cx)
            
            /*Crow ability for caster's fly*/
            
            if UnitAddAbility(caster[this], CROW_CODE) then
                call UnitRemoveAbility(caster[this], CROW_CODE)
            endif
            
            /*Caster pause - rly need it*/
            
            call PauseUnit(caster[this], true)
            
        endmethod
        
        /*Init method*/
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(SPELL_CODE,function thistype.onCast)
        endmethod
    endstruct
endscope


v1.04
- Changed some globals named
- Now using global dmmy to apply debuffs
v1.03
- Removed some leaks
- Now using one dummy to apply slow
- Renamed some globals
- Remove unused dummy
v1.02
- Added Z damage range so now arrows can hit flying units.
- Added dummy death effect.
- Added SlowFilter function.
- Now you can spawn more than arrows at once.
- Removed GroupUtils and now using one group for damage
- Privatized Fire struct
v1.01
- Moved Fire struct over Jump struct
- Removed onCast functions and inlined in to onRun function changing it's name to onCast
- Speed[this] now have value of global varaiable SPEED not 10 like it was before
- Removed unused libraries
v1.0
- First release


Keywords:
Archer, Ranger, Arrow
Contents

Rain of Cold Arrows (Map)

Reviews
Rain of Cold Arrows v1.04 | Reviewed by BPower | 15.06.2015 Concept[/COLOR]] The caster is jumping backwards in the air, while shooting a salve of cold arrows on a target area. Optionally slows all damaged targets. Optionally destroys...

Moderator

M

Moderator


Rain of Cold Arrows v1.04 | Reviewed by BPower | 15.06.2015

[COLOR="gray"

[COLOR="gray"

[COLOR="gray"

[COLOR="gray"

[COLOR="gray"

[COLOR="gray"

Concept[/COLOR]]
126248-albums6177-picture66521.png
The caster is jumping backwards in the air, while shooting a
salve of cold arrows on a target area.

Optionally slows all damaged targets.
Optionally destroys nearby trees.
Code[/COLOR]]
126248-albums6177-picture66521.png
  • The spell is MUI and working. Currently one unit leak exists.
  • There are some things, which could have been done better:
126248-albums6177-picture66523.png
  • You leak a unit handle in CTlExpire ( d )
  • What happens if the caster dies? Fix this!
  • private struct Fire --> private struct Fire extend array
  • In order to enumerate trees a static rect is enough, currently you use an array.
  • Same applies for unit enumeration --> Use just one static unit group.
  • The angle of creation of each missile does not match the fly angle. This can look fishy.
  • If you create a secondary death effect for each arrow, then use RemoveUnit() and not KillUnit() for the main arrow.
  • PauseUnit() comes along with unwanted side effects.
    Can't you use a combination of UnitPropWindow and TurnSpeed?
    I'm not against PauseUnit() in all cases, but it should be avoided for public resources.
  • PauseUnit() freezes the units animation,
    aslong as no new command is given to that unit
  • What is the meaning of prefix "F" and "S" in the globals i.e F_SPEED?
    Please use complete variable names, so users understand directly their purpose.
  • Ammout is written with 1 "m"
Objects[/COLOR]]
126248-albums6177-picture66523.png
  • Object data is ok.
  • There are 4 files in the import manager,
    which are not related to the spell.
Effects[/COLOR]]
126248-albums6177-picture66521.png
  • Effects sometimes looks fishy, as the facing of each arrow
    does not match with it's fly angle.
Rating[/COLOR]]
CONCEPTCODEOBJECTSEFFECTSRATINGSTATUS
3/5
3/5
4/5
2/5
3/5
NEED FIX
Links[/COLOR]]
126248-albums6177-picture66524.png
  • Missile allows to easily create projectile like spells.
    It's more a hint, than a real recommendation from my side.

[COLOR="gray"

[/TD]
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
Provide links to required libraries(its not so easy to find them)

Jump.onCast is completly useless function and can(and should) be inlined into onRun, where you just define the arguments as local variables.

You call Fire.onFire inside Jump in the CTL module method, so you most likely generate trigger evaluations -> move struct Fire above struct Jump(Fire struct does not depend on Jump in any way, shape or form)

Im too tired for algorithm checking, but I assume it works fine
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Shit. It's another one of those "explains every single line in the code" spells.
I agree that spacing and comments here and there are very nice and help read-ability in many cases!

First of all IsDestructableTree is not written by Bribe! :p

struct Fire should be private.

GroupUtils doesn't seem important to me for your spell. You could also use one static group handle instead.

Gonna check the demo map.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I gave you a detailed review for your spell. You might want to defend the usage
of PauseUnit() here in the comments as we normally don't allow it in public spells.

If you have any questions, fell free to ask. :)

Please do not update your submission until you changed, what I pointed out.
Not like in your last spell submission.

EDIT:
You can either create each arrow dummy unit in struct Fire instead of in struct Jump.
Just pass in desired x/y coordinates and use the angle you calculate in onFire for the dummy unit.

Another not so good solution would be to adjust the angle after creation, by using SetUnitFacing()

I know why you are using PauseUnit(). Let's see what IcemanBoo says to this.
 
Last edited:
Level 5
Joined
Sep 16, 2008
Messages
47
Ok so. Still don't know what about
JASS:
PauseUnit()

"Effects sometimes looks fishy, as the facing of each arrow
does not match with it's fly angle."

This is real problem. I was trying to calculate angle in Fire struct but effect is the same arrows spawn like this:

*
*
*
*

JASS:
static method onFire takes player p, integer lvl, real tx, real ty, real dHeight, real crx, real cry returns nothing
        
            local thistype this = create()
            
            local real AoE = GetAoE(lvl)
            local real RT
            
            set owner[this] = p
            
            /*Arrow destination location*/
            
            set targetx[this] = tx + AoE * Cos(GetRandomReal(0, 360))
            set targety[this] = ty + AoE * Sin(GetRandomReal(0, 360))
            
            set angle[this] = Atan2(targety[this] - cry, targetx[this] - crx)
            
            set dummy[this] = CreateUnit(owner[this], DUMMY_CODE, crx, cry, angle[this] * bj_RADTODEG)
            
            /*Arrows distance traveled*/
            
            set distance[this] = GetDist(crx, cry, targetx[this], targety[this])
            
            set speed[this] = FIRE_SPEED
            
            set damage[this] = GetDamage(lvl)
            set damageGroup = CreateGroup()
            
            /*Calcultaing time needed for arrows reach target location*/
            
            set RT = distance[this] / speed[this]
            set RT = RT * 0.031250
            
            /*Calculating height decrease based on arrows time needed to reach target location*/
            
            set height[this] = dHeight
            set heightDec[this] = height[this] / (RT / 0.031250)
            
            /*Tree kill rect*/
            
            static if DESTROY_TREE then
                set treeRect = Rect(0, 0, 0, 0)
            endif
            
            /*Slow apply dummy*/
            
            call UnitAddAbility(SLOW_DUMMY, SLOW_CODE)
            call SetUnitAbilityLevel(SLOW_DUMMY, SLOW_CODE, lvl)
        
        endmethod
 
Top