• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Need help to code the damage of this spell

Status
Not open for further replies.
Level 13
Joined
Aug 19, 2014
Messages
1,111
Hello guys I'm making simple triggered spells and I've run out of ideas, so what I did is that I looked some spells in the spell section. I found this :fp: http://www.hiveworkshop.com/forums/spells-569/rain-arrows-v1-01-a-158598/ and I kinda liked it :ogre_haosis: However I wanted its damaged to be liked 50 + 30% of the hero's agility, I'm just currently learning to create MUI spells so basically I find vjass very complicated. I hoped someone could help me to recode this spells damage and from that maybe I might learn something :vw_wtf:
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
All spells in my map must be powered by hero's stats. Strength, agility and intelligence each stats give bonus damage or effect on hero's spells. So modifying this Rain of Arrows will mean a lot to me, as I can take it from their and see if I can modify some vjass spells myself.
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
In the damage line you can add + GetHeroAgi(this.caster, true)*5

Thanks for the reply dude, here's the script of the spell and I did put what you said. It cause an error :goblin_cry:


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 + GetHeroAgi(this.caster, true)*5
        {
            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
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Not like this. You're not doing any calculations by putting it up there xP The actual math is done in the return line.

JASS:
  function GetDamage(integer lvl)->real + GetHeroAgi(this.caster, true)*5
        {
            return 25. * lvl; /*deals damage each arrow*/
        }

Like THIS.
JASS:
  function GetDamage(integer lvl, unit caster)->real 
        {
            return 25. *lvl + GetHeroAgi(this.caster, true) * whatever you want to multiply it by; /*deals damage each arrow*/
        }
 
Last edited:
Level 13
Joined
Aug 19, 2014
Messages
1,111
I did what you said guys

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 + GetHeroAgi(this.caster, true) * 0.30; /*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

However it gives this error :fp: Pic. 1.jpg
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
I did what you said but still errors :vw_sad:

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(this.lvl, this.caster)
        {
            return 400. + lvl * 0; /*spell aoe, must match the object editor field*/
        }
    
        function GetDamage(this.lvl, this.caster)
        {
            return 25. *lvl + GetHeroAgi(this.caster, true) * 0.30; /*deals damage each arrow*/
        }
        
        function GetCollisionSize(this.lvl, this.caster)
        {
            return 125. + lvl * 0; /*collision size each arrow*/
        }
    
        function GetArrowCount(this.lvl, this.caster)
        {
            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

Pic. 1.jpg
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
I did what you said but still errors :vw_sad:

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(this.lvl, this.caster)
        {
            return 400. + lvl * 0; /*spell aoe, must match the object editor field*/
        }
    
        function GetDamage(this.lvl, this.caster)
        {
            return 25. *lvl + GetHeroAgi(this.caster, true) * 0.30; /*deals damage each arrow*/
        }
        
        function GetCollisionSize(this.lvl, this.caster)
        {
            return 125. + lvl * 0; /*collision size each arrow*/
        }
    
        function GetArrowCount(this.lvl, this.caster)
        {
            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

View attachment 147742

Why does the function call in GetAoE, GetCollisionSize, and GetArrowCount have this.caster? Do you plan on changing that to hero stats as well? o:
 
Level 13
Joined
Aug 19, 2014
Messages
1,111
Okay what is the right thing to do then? Here's the newly script that I changed. I only changed the function GetDamage(integer lvl)->real and the

method onDestroy()
{
xed.damageAOE(this.caster,this.fx.x, this.fx.y, GetCollisionSize(this.lvl), GetDamage(this.lvl, this.caster));


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 + GetHeroAgi(this.caster, true) * 0.30; /*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.caster));
                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

and still it errors :ogre_hurrhurr: :fp: Pic. 1.jpg
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Okay what is the right thing to do then? Here's the newly script that I changed. I only changed the function GetDamage(integer lvl)->real and the

method onDestroy()
{
xed.damageAOE(this.caster,this.fx.x, this.fx.y, GetCollisionSize(this.lvl), GetDamage(this.lvl, this.caster));


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 + GetHeroAgi(this.caster, true) * 0.30; /*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.caster));
                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

and still it errors :ogre_hurrhurr: :fp: View attachment 147743

Your method onDestroy is fine now, but you removed the unit caster from function GetDamage... it needs to be like this.

JASS:
function GetDamage(integer lvl, unit caster)->real
        {
            return 25. * lvl + GetHeroAgi(caster, true); /*deals damage each arrow*/
        }
 
Status
Not open for further replies.
Top