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

I request a skill please

Status
Not open for further replies.
Level 7
Joined
Jul 17, 2018
Messages
185
Hi, I don't know if this could be done, but if it can be done, I would like the skill to be a GUI with 3 levels instead of JASS because it is very confusing for me, I think it is very difficult to create it. But I would really appreciate it.

Rain of Arrows v1.01
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I'm assuming you're having trouble importing it into your map. If you'd like, I could import the spell into your map for you and modify it to work how you'd like. It's a fairly time consuming project to recreate the spell.
 
Level 7
Joined
Jul 17, 2018
Messages
185
I'm assuming you're having trouble importing it into your map. If you'd like, I could import the spell into your map for you and modify it to work how you'd like. It's a fairly time consuming project to recreate the spell.

Hello, it's okay, I'll pass it to you :)
 
Level 7
Joined
Jul 17, 2018
Messages
185
@Uncle Here is the map. It is mainly in Spanish and still needs a lot of correction, xd
 

Attachments

  • (8)Frio y Sangre.w3x
    30.5 MB · Views: 21

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Alright, I fixed it. I put a test Priestess of the Moon on the map, feel free to edit and delete her.

And the issue was that you're using multiple custom spells that use different libraries that conflict with one another. One spell is from 10+ years ago while the other is newer, etc... Very old and outdated stuff.

You'll continue to run into these problems for imported spells that say things like: Requires TimerUtils, etc...
 

Attachments

  • (8)Frio y Sangre Rain of Arrows Fix.w3x
    30.5 MB · Views: 14
Level 7
Joined
Jul 17, 2018
Messages
185
Alright, I fixed it. I put a test Priestess of the Moon on the map, feel free to edit and delete her.

And the issue was that you're using multiple custom spells that use different libraries that conflict with one another. One spell is from 10+ years ago while the other is newer, etc... Very old and outdated stuff.

You'll continue to run into these problems for imported spells that say things like: Requires TimerUtils, etc...

Thanks bro, I don't know when I will upload this map, but I will give you credits (I still need a lot) xd
 
Level 7
Joined
Jul 17, 2018
Messages
185
@Uncle there was a problem, when I open the map I get: "there was a level error or data was missing", my version of the game, I have it in 1.31
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Ah, I'm on the latest patch. Well, here's what you do:

Copy and paste all of the Rain of Arrows triggers into your map. Put them all in the same folder to make it easy. (Don't copy the test triggers)

Then follow the instructions inside:
Delete the code inside the "TimerUtils" trigger and paste this:
Code:
//TESH.scrollpos=24
//TESH.alwaysfold=0
library_once TimerUtils initializer init
//*********************************************************************
//* TimerUtils (Blue flavor for 1.23b or later)
//* ----------
//*
//*  To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//*  To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass)   More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//*  * Attaching
//*  * Recycling (with double-free protection)
//*
//* set t=NewTimer()      : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t)       : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2)     : Attach value 2 to timer
//* GetTimerData(t)       : Get the timer's value.
//*                         You can assume a timer's value is 0
//*                         after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//*             limit, which means that if more than 408000 handle ids
//*             are used in your map, TimerUtils might fail, this
//*             value is quite big and it is much bigger than the
//*             timer limit in Red flavor.
//*
//********************************************************************

    //==================================================================================================
    globals
        private hashtable hasht //I <3 blizz
    endglobals

    //It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
    function SetTimerData2 takes timer t, integer value returns nothing
        call SaveInteger(hasht,0, GetHandleId(t), value)
    endfunction

    function GetTimerData2 takes timer t returns integer
        return LoadInteger(hasht, 0, GetHandleId(t))
    endfunction

    //==========================================================================================
    globals
        private timer array tT
        private integer tN = 0
        private constant integer HELD=0x28829022
        //use a totally random number here, the more improbable someone uses it, the better.
    endglobals

    //==========================================================================================
    function NewTimer2 takes nothing returns timer
        if (tN==0) then
            set tT[0]=CreateTimer()
        else
            set tN=tN-1
        endif
        call SetTimerData2(tT[tN],0)
     return tT[tN]
    endfunction

    //==========================================================================================
    function ReleaseTimer2 takes timer t returns nothing
        if(t==null) then
            debug call BJDebugMsg("Warning: attempt to release a null timer")
            return
        endif
        if (tN==8191) then
            debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")

            //stack is full, the map already has much more troubles than the chance of bug
            call DestroyTimer(t)
        else
            call PauseTimer(t)
            if(GetTimerData2(t)==HELD) then
                debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
                return
            endif
            call SetTimerData2(t,HELD)
            set tT[tN]=t
            set tN=tN+1
        endif
    endfunction

    private function init takes nothing returns nothing
        set hasht = InitHashtable()
    endfunction

endlibrary

Then delete the code inside the "xebasic" trigger and paste this:
Code:
//TESH.scrollpos=21
//TESH.alwaysfold=0
library xebasic
//**************************************************************************
//
// xebasic 0.4
// =======
// XE_DUMMY_UNITID : Rawcode of the dummy unit in your map. It should
//                   use the dummy.mdx model, so remember to import it as
//                   well, just use copy&paste to copy the dummy from the
//                   xe map to yours, then change the rawcode.
//
// XE_HEIGHT_ENABLER: Medivh's raven form ability, you may need to change
//                    this rawcode to another spell that morphs into a flier
//                    in case you modified medivh's spell in your map.
//
// XE_TREE_RECOGNITION: The ancients' Eat tree ability, same as with medivh
//                      raven form, you might have to change it.
//
// XE_ANIMATION_PERIOD: The global period of animation used by whatever
//                      timer that depends on it, if you put a low value
//                      the movement will look good but it may hurt your
//                      performance, if instead you use a high value it
//                      will not lag but will be fast.
//
// XE_MAX_COLLISION_SIZE: The maximum unit collision size in your map, if
//                        you got a unit bigger than 197.0 it would be
//                        a good idea to update this constant, since some
//                        enums will not find it. Likewise, if none of
//                        your units can go bellow X and X is much smaller
//                        than 197.0, it would be a good idea to update
//                        as well, since it will improve the performance
//                        those enums.
//
// Notice you probably don't have to update this library, unless I specify
// there are new constants which would be unlikely.
//
//**************************************************************************

//===========================================================================
globals
   constant integer XE_DUMMY_UNITID       = 'e002'
   constant integer XE_HEIGHT_ENABLER     = 'Amrf'
   constant integer XE_TREE_RECOGNITION   = 'Aeat'
   constant real    XE_ANIMATION_PERIOD   =  0.025
   constant real    XE_MAX_COLLISION_SIZE =  197.0
endglobals

endlibrary
Then delete the code inside the "Rain of Arrows" trigger and paste this:
Code:
//TESH.scrollpos=274
//TESH.alwaysfold=0
//! 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    = 'A01L'; /*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 = NewTimer2();
                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);
                SetTimerData2(this.t, this);
                TimerStart(this.t, XE_ANIMATION_PERIOD, true, function thistype.onMove);
              
                return this;
            }
          
            static method onMove()
            {
                thistype this = thistype(GetTimerData2(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);
                ReleaseTimer2(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 = NewTimer2();
                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);
                ReleaseTimer2(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 (GetTimerData2(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());
                    SetTimerData2(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

Then look for "xe unit" in the Object Editor. It's a Unit. You'll see it has the Ghost (Visible) ability. Remove that and give it the "Locust" ability.

That should be it.
 
Last edited:
Status
Not open for further replies.
Top