• 🏆 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 Arrows v1.01

Rain of Arrows

Fires a fire arrow into the sky which explodes and scatters at the center of the point target, showering the target area. Deals amount of damage each.
JASS:
//! zinc
    /*
    -------------------------------------------------------------------------------------------
        Rain of Arrows v1.01 by scorpion182
        requires:
        
        [-X-] TimerUtils, SimError, BoundSentinel, xe by vexorian
        [-X-] ParabolicMovement by Moyack & Spec
    -------------------------------------------------------------------------------------------
    */
    library RainofArrows requires TimerUtils, ParabolicMovement, SimError, xefx, xedamage, optional BoundSentinel
    {
    /*
    -------------------------------------------------------------------------------------------
        CALIBRATION SECTION
    -------------------------------------------------------------------------------------------
    */
        constant integer SPELL_ID    = 'A000'; /*spell id*/
        constant string  ARROW_PATH  = "Abilities\\Weapons\\SearingArrow\\SearingArrowMissile.mdl"; /*the arrow effect path*/
        constant string  FLASH_PATH  = "Abilities\\Weapons\\FragDriller\\FragDriller.mdl"; /*the arrow flash effect path*/
        constant string  DAMAGE_FX   = "Abilities\\Weapons\\Rifle\\RifleImpact.mdl"; /*on-damage effect*/
        constant string  DAMAGE_ATCH = "origin"; /*on-damage effect attachment point*/
        constant integer ARROW_SCALE = 1; /*arrow scale*/
        constant real    MAX_H       = 500.; /*maximum parabola height*/
        constant real    SPEED       = 800. * XE_ANIMATION_PERIOD; /*missile speed*/
        constant real    MIN_DIST    = 300.; /*minimum casting distance, the parabolic movement looks weird if the distance is too short*/
        constant real    MIN_H       = 80.; /*minimum distance for the rain arrows, must higher than 80., otherwise it won't work*/
        constant string  ERROR_MSG   = "Inside Minimum Range." ; /*display error message*/
        constant boolean PRELOAD_FX  = true; /*preload effect?*/
        
        function GetAoE(integer lvl)->real
        {
            return 400. + lvl * 0; /*spell aoe, must match the object editor field*/
        }
    
        function GetDamage(integer lvl)->real
        {
            return 25. * lvl; /*deals damage each arrow*/
        }
        
        function GetCollisionSize(integer lvl)->real
        {
            return 125. + lvl * 0; /*collision size each arrow*/
        }
    
        function GetArrowCount(integer lvl)->integer 
        {
            return 12 + lvl * 0; /*how many arrows*/
        }
        
        /* damage filter */
        function DamageOptions(xedamage spellDamage)
        {
            spellDamage.dtype = DAMAGE_TYPE_UNIVERSAL;
            spellDamage.atype = ATTACK_TYPE_NORMAL;
            spellDamage.exception=UNIT_TYPE_STRUCTURE; /*doesn't damage building*/
            spellDamage.visibleOnly = true;
            spellDamage.damageAllies = false; /* damage allies if true */
            spellDamage.damageTrees = true; /* damage destructables? */
            spellDamage.useSpecialEffect(DAMAGE_FX, DAMAGE_ATCH);
        }
        
    /*
    -------------------------------------------------------------------------------------------
        END OF CALIBRATION SECTION
    -------------------------------------------------------------------------------------------
    */
        constant real A = 2 * bj_PI;
        location l = Location(0, 0);
        xedamage xed;
        
        function GetPointZ(real x, real y)->real
        {
            MoveLocation(l, x, y);
            return GetLocationZ(l);
        }
        
        /*rain of arrows*/
        struct rain
        {
            unit caster; /*the caster*/
            timer t; 
            real tx; /*spell target x*/
            real ty; /*spell target y*/
            xefx fx;
            integer lvl; /*ability level*/
            real zpoint; /*spell target z*/
            
            static method create(unit c, real x, real y, real tx, real ty, integer lvl)->thistype
            {
                thistype this = thistype.allocate();
                real dx = tx - x;
                real dy = ty - y;
                real angle = Atan2(dy, dx);
                
                this.caster = c;
                this.t = NewTimer();
                this.tx = tx;
                this.ty = ty;
                this.lvl = lvl;
                this.fx = xefx.create(x, y, angle);
                this.fx.fxpath = ARROW_PATH;
                this.fx.scale = ARROW_SCALE;
                this.fx.z = MAX_H;
                this.zpoint = GetPointZ(tx, ty);
                SetTimerData(this.t, this);
                TimerStart(this.t, XE_ANIMATION_PERIOD, true, function thistype.onMove);
                
                return this;
            }
            
            static method onMove()
            {
                thistype this = thistype(GetTimerData(GetExpiredTimer()));
                real x = this.tx - this.fx.x;
                real y = this.ty - this.fx.y;
                real z = -this.fx.z + SPEED;
                real distance = SquareRoot(x*x + y*y + z*z);
                real angle1 = Atan2(y, x);
                real angle2 = Acos(z / distance);
                real angle3 = Atan2(z, SquareRoot(x*x + y*y));
                
                if (distance > MIN_H && this.fx.z + this.zpoint > this.zpoint + MIN_H)
                {
                    this.fx.xyangle = angle1;
                    this.fx.x += SPEED * Cos(angle1) * Sin(angle2);
                    this.fx.y += SPEED * Sin(angle1) * Sin(angle2);
                    this.fx.z += SPEED * Cos(angle2);
                    this.fx.zangle = angle3;
                }
                else
                {
                    this.destroy();
                }
                
                
            }
            
            
            method onDestroy()
            {
                xed.damageAOE(this.caster,this.fx.x, this.fx.y, GetCollisionSize(this.lvl), GetDamage(this.lvl));
                this.fx.flash(FLASH_PATH); 
                ReleaseTimer(this.t);
                this.fx.destroy();
            }
            
        }
        
        constant real factor = 2.;
        
        /*parabolic arrow*/
        struct data
        {
            unit caster; /*the caster*/
            timer t;
            real pos; /*current pos*/
            real dist; /*total distance*/
            integer lvl; /*ability level*/
            xefx fx;
            real tx; /*spell target x*/
            real ty; /*spell target y*/
            
            static method create(unit c, real tx, real ty)->thistype
            {
                thistype this = thistype.allocate();
                real x = GetUnitX(c);
                real y = GetUnitY(c);
                real dx = tx - x;
                real dy = ty - y;
                real angle = Atan2(dy, dx);
                
                this.caster = c;
                this.t = NewTimer();
                this.lvl = GetUnitAbilityLevel(c, SPELL_ID);
                this.tx = tx;
                this.ty = ty;
                this.pos = SquareRoot(dx * dx + dy * dy)*factor;
                this.dist = this.pos;
                this.fx = xefx.create(x, y, angle);
                this.fx.fxpath = ARROW_PATH;
                this.fx.scale = ARROW_SCALE;
                
                
                return this;
            }
            
            method onDestroy()
            {
                integer i = 0;
                real x = this.fx.x;
                real y = this.fx.y;
                real angle;
                real dis; 
                real tx; 
                real ty;
                rain s;
            
                this.fx.flash(FLASH_PATH); 
                ReleaseTimer(this.t);
                this.fx.destroy();
                /*create rain arrows*/
                for(i = 0; i<GetArrowCount(this.lvl); i += 1)
                {
                    angle = GetRandomReal(0, A);
                    dis = GetRandomReal(1, GetAoE(this.lvl));
                    tx = x + dis * Cos (angle);
                    ty = y + dis * Sin (angle);
                    s = s.create(this.caster, x, y, tx, ty, this.lvl);
                }
                
            }
            
            /*move the parabolic arrow*/
            static method onLoop()
            {
                thistype this = thistype (GetTimerData(GetExpiredTimer()));
                real x = this.fx.x;
                real y = this.fx.y;
                real z = this.fx.z;
                real dx;
                real dy;
                real dz;
                
                if (this.pos>this.dist/factor)
                {
                    this.fx.x += SPEED * Cos(this.fx.xyangle);
                    this.fx.y += SPEED * Sin(this.fx.xyangle);
                    this.fx.z = ParabolaZ(MAX_H, this.dist, this.pos);
                    dx = this.fx.x - x;
                    dy = this.fx.y - y;
                    dz = this.fx.z - z;
                    this.fx.zangle = Atan(dz * dz / (dx * dx + dy * dy) );
                    this.pos -= SPEED;
                }
                else
                {
                    this.destroy();
                }
                
            }
            
            static method SpellEffect()->boolean
            {
                thistype this;
                
                if (GetSpellAbilityId() == SPELL_ID)
                {
                    this = thistype.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY());
                    SetTimerData(this.t, this);
                    TimerStart(this.t, XE_ANIMATION_PERIOD, true, function thistype.onLoop);
                }
                return false;
            }
            
            /*check minimum casting distance*/
            static method CheckMinDistance()->boolean
            {
                unit u = GetTriggerUnit();
                real x = GetUnitX(u);
                real y = GetUnitY(u);
                real dx = x - GetSpellTargetX();
                real dy = y - GetSpellTargetY();
            
                if (GetSpellAbilityId() == SPELL_ID && dx * dx + dy * dy<MIN_DIST * MIN_DIST)
                {
                    SimError(GetOwningPlayer(u), ERROR_MSG);
                    PauseUnit(u, true);
                    IssueImmediateOrder(u, "stop");
                    PauseUnit(u, false);
                }
            
                u = null;
                return false;
            }
            
            static method onInit()
            {
                trigger t = CreateTrigger();
                TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT);
                TriggerAddCondition(t, Condition(function thistype.SpellEffect));
                
                t = CreateTrigger();
                TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CHANNEL);
                TriggerAddCondition(t, Condition(function thistype.CheckMinDistance));
                
                /* init xedamage */
                xed = xedamage.create();
                DamageOptions(xed);
                
                /*preload effect*/
                static if (PRELOAD)
                {
                    Preload(ARROW_PATH);
                    Preload(FLASH_PATH);
                    Preload(DAMAGE_FX);
                }
            }
            
        }
    }

//! endzinc

Requires:
- TimerUtils by Vexorian
- xe by Vexorian
- BoundSentinel by Vexorian
- Parabolic Function by moyack
- SimError by Vexorian

History:
~ v1.00 First Release.
~ v1.01 Fixed minor bugs, added on-damage effect.



Keywords:
zinc, rain, of, arrow, arrows, parabola, area, damage, target, many, scatter, shard, whatever, archer, fire, mui
Contents

Rain of Arrows v1.01 (Map)

Reviews
20:31, 2nd Mar 2010 The_Reborn_Devil: The coding looks good and I couldn't find any leaks. Status: Approved Rating: Recommended

Moderator

M

Moderator

20:31, 2nd Mar 2010
The_Reborn_Devil:

The coding looks good and I couldn't find any leaks.


Status: Approved
Rating: Recommended
 
Level 13
Joined
Mar 16, 2008
Messages
941
Zinc was added quite late, people got used to vJass and the site doesn't want zinc. If Vex adds another 10 languages, do you want them all to be accepted? Would be quite a mess and I can understand the rules, see it as some standard. I'd vote for accepting Zinc too, and I think there are mods that do so, but I'm not quite sure.

Compatibility
Currently, spells are allowed in Vanilla GUI (No third party GUI modifications), JASS, or vJASS. All spells must be 1.24 compatible.
 
Level 16
Joined
Jun 9, 2008
Messages
734
Zinc was added quite late, people got used to vJass and the site doesn't want zinc. If Vex adds another 10 languages, do you want them all to be accepted? Would be quite a mess and I can understand the rules, see it as some standard. I'd vote for accepting Zinc too, and I think there are mods that do so, but I'm not quite sure.

as i already said that zinc is a part of the jasshelper, it doesn't need an additional tool to compile except the jasshelper itself.

this spell was approved, and coded in zinc
http://www.hiveworkshop.com/forums/...-9-9-5-a-148321/?prev=search=zinc&d=list&r=20

and this

http://www.hiveworkshop.com/forums/spells-569/beacon-149221/?prev=search=zinc&d=list&r=20

http://www.hiveworkshop.com/forums/site-discussion-97/zinc-resources-acceptable-146328/

Zinc is accepted, but certain moderators don't like reviewing it...
 
Level 10
Joined
May 19, 2008
Messages
176
Two things:

1. Don't create the explosion sfx of the splitters on them. Because the effects has then the angle of the missile, which looks a bit bad.

2. Add the possibility to set a start z. ( looks bad when the missile starts out of the ground )

But anyway, nice spell.

cedi
 
Top