1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  4. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  5. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  6. The results are out! Check them out.
    Dismiss Notice
  7. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  8. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  9. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Snippet] GetLastCastAbility

Discussion in 'JASS Resources' started by edo494, Aug 7, 2012.

  1. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    Hope this will be more useful then my first submission

    Code (vJASS):
    library GetLastCastAbility uses Table, RegisterPlayerUnitEvent, UnitIndexer
    /*   by edo494 version 1.8d
    *
    *============================================================================
    *
    * Requires:
    *
    * Table by Bribe - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
    *
    * RegisterPlayerUnitEvent by Magtheridon96 - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
    *
    * UnitIndexer by Nestharus - http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
    *
    *============================================================================
    *  
    *   This library includes:
    *
    *       - Allows you to retrieve last cast spells ID(returns integer)
    *       - Allows you to retrieve last cast spells target
    *       - Allows you to retrieve last cast spells caster
    *       - Allows you to retrieve last cast spells X and Y coordiantions
    *       - Allows you to retrieve last cast spells ID by specific unit
    *       - Allows you to retrieve target of cast spell by specific unit
    *       - Allows you to retrieve X and Y coordinates of last cast spell by specific unit
    *       - Additionally this allows you to pass unit's index and returns the unit's last cast ability
    *
    *   This also features "BAN/UNBAN" SPELL which you can add spells into it
    *   If units cast those spells it will not get registered.
    *
    *       This feature can be used for things like Spell Steal for either
    *       not registering the spell steal(because you dont want to steal that dont you?)
    *       or for spells that you dont want to be spell stealed.
    *
    *   Also if you want to catch only heros spells, there is texted if in MainBody function which
    *   you can use.
    *
    *============================================================================
    *
    *   Issues:
    *       You cant register passives for instance Bash because they
    *       technically never fire the event Unit - a Unit starts the effect of an ability.
    *
    *       Also if you cast spell with no target the GetLastCastAbilityX, Y and
    *       GetLastCastSpellTarget will return 0, 0, null
    *
    *============================================================================
    *  
    *   The API is:
    *  
    *       function GetLastCastAbility takes nothing returns integer
    *       function GetLastCastAbilityTarget takes nothing returns unit
    *       function GetLastCastAbilityUnit takes nothing returns unit
    *       function GetLastCastAbilityX takes nothing returns real
    *       function GetLastCastAbilityY takes nothing returns real
    *
    *   Based on Unit:
    *      
    *       function GetUnitLastCastAbility takes unit returns integer
    *       function GetUnitLastCastAbilityTarget takes unit returns unit
    *       function GetUnitLastCastAbilityX takes unit returns real
    *       function GetUnitLastCastAbilityX takes unit returns real
    *
    *   Based on Unit's index:
    *
    *       function GetUnitLastCastAbilityById takes integer returns integer
    *       function GetUnitLastCastAbilityTargetById takes integer returns unit
    *       function GetUnitLastCastAbilityXById takes integer returns real
    *       function GetUnitLastCastAbilityXById takes integer returns real
    *
    *   Ban API:
    *
    *       function LastAbilityAddFilter takes integer returns nothing
    *       function LastAbilityRemoveFilter takes integer returns nothing
    *
    *============================================================================
    *
    *   Change Log:
    *
    *       1.0    - Intial Release
    *
    *       1.1    - Added BanAbility
    *              - Added UnbanAbility
    *              - Added Get(Unit)LastCastAbilityX and Y
    *              - Changed GetLastCast***what***ByUnit to GetUnitLastCast***what***
    *
    *       1.2    - Added TempBanAbility function
    *              - Removed Get(Unit)LastCastAbility and Get(Unit)LastCastAbilityLoc
    *
    *       1.3    - Changed AbilityId to Ability
    *              - Added support for Table
    *
    *       1.4    - Changed Size of myTab from 0x1000000(lol this wont work anyways) to 0x200
    *
    *       1.5    - Resized the Table from 0x200 to 5
    *              - Removed TempBan function
    *
    *       1.6    - Changed Ban/Unban Ability to LastAbilityAddFilter/LastAbilityRemoveFilter
    *              - Implemented support for RegisterPlayerUnitEvent Library
    *              - changed Scope Initializer to Module Initializer
    *
    *       1.7    - Added "Deinxeding" when unit dies
    *
    *       1.7a   - Improved speed a very little bit
    *
    *       1.8    - Remade the idea of GetUnitLastCastAbility
    *
    *       1.8a   - Removed Useless stuff
    *              - Changed the way how the nulling variables works(Special thanks to Bribe)
    *
    *       1.8b   - TableArray -> Table (special thanks to Yixx)
    *
    *       1.8b.1 - Changed how GetLastCast***what*** works(thanks to Magtheridon96)
    *              - Removed local unit u from Deindex function
    *
    *       1.8b.2 - unit lastCastAbilityUnit -> integer lastCastAbilityCaster
    *
    *       1.8c   - Reorganized the structure of the header
    *              - Added GetUnitLastCast ability taking unit's index instead of actual unit
    *              - Changed names of textmacroes(added GetLastCastAbility_ to their name)
    *
    *       1.8d   - removed local integer from mainbody function
    *
    *============================================================================
    */


    globals
        private integer lastCastAbilityCaster = 0
       
        /*
        *   table for Filter/UnFilter
        */

       
        private Table myTab
       
        /*
        *   variables for GetUnitLastCast
        */

       
        private integer array lastCastUnitAbility
        private unit array lastCastUnitTarget
        private real array lastCastUnitX
        private real array lastCastUnitY
    endglobals


        //! textmacro GetLastCastAbility_GETLAST takes Name, RSName, RName
            function GetLastCast$Name$ takes nothing returns $RSName$
                return $RName$
            endfunction
        //! endtextmacro
       
        //! runtextmacro GetLastCastAbility_GETLAST("Ability", "integer", "lastCastUnitAbility[lastCastAbilityCaster]")
        //! runtextmacro GetLastCastAbility_GETLAST("AbilityUnit", "unit", "GetUnitById(lastCastAbilityCaster)")
        //! runtextmacro GetLastCastAbility_GETLAST("AbilityTarget", "unit", "lastCastUnitTarget[lastCastAbilityCaster]")
        //! runtextmacro GetLastCastAbility_GETLAST("AbilityX", "real", "lastCastUnitY[lastCastAbilityCaster]")
        //! runtextmacro GetLastCastAbility_GETLAST("AbilityY", "real", "lastCastUnitY[lastCastAbilityCaster]")
       
       
        //! textmacro GetLastCastAbility_GETUNITLAST takes name, return, what
            function GetUnitLastCast$name$ takes unit u returns $return$
                return lastCastUnit$what$[GetUnitUserData(u)]
            endfunction
        //! endtextmacro
       
        //! runtextmacro GetLastCastAbility_GETUNITLAST("Ability", "integer", "Ability")
        //! runtextmacro GetLastCastAbility_GETUNITLAST("X", "real", "X")
        //! runtextmacro GetLastCastAbility_GETUNITLAST("Y", "real", "Y")
        //! runtextmacro GetLastCastAbility_GETUNITLAST("Target", "unit", "Target")
       
       
        //! textmacro GetLastCastAbility_GETUNITLASTBYID takes name, return, what
            function GetUnitLastCast$name$ById takes integer index returns $return$
                return lastCastUnit$what$[index]
            endfunction
        //! endtextmacro
       
        //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Ability", "integer", "Ability")
        //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("X", "real", "X")
        //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Y", "real", "Y")
        //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Target", "unit", "Target")


            function LastAbilityAddFilter takes integer abilcode returns nothing
                set myTab[abilcode] = 1
            endfunction
           
           
            function LastAbilityRemoveFilter takes integer abilcode returns nothing
                set myTab[abilcode] = 0
            endfunction

           
            private function MainBody takes nothing returns nothing
                //if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
                    if myTab[GetSpellAbilityId()] != 1 then
                        set lastCastAbilityCaster = GetUnitId(GetTriggerUnit())
                        set lastCastUnitAbility[lastCastAbilityCaster] = GetSpellAbilityId()
                        set lastCastUnitTarget[lastCastAbilityCaster] = GetSpellTargetUnit()
                        set lastCastUnitX[lastCastAbilityCaster] = GetSpellTargetX()
                        set lastCastUnitY[lastCastAbilityCaster] = GetSpellTargetY()
                    endif
                //endif
            endfunction

        private module GetLastAbility
            private static method onInit takes nothing returns nothing            
                /*
                *   for ban list
                */

               
                set myTab = Table.create()
               
                /*
                *   Registering the starts the effect of an ability to the function
                */

               
                call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function MainBody)
            endmethod
        endmodule
       
        private struct GetLast
            implement GetLastAbility
        endstruct
       
    //***************************************************************
    //***************************************************************

        //When unit dies, null the numbers
       
        private function DiesFunc takes nothing returns boolean
            local integer i = GetIndexedUnitId()
            set lastCastUnitAbility[i] = 0
            set lastCastUnitTarget[i] = null
            set lastCastUnitX[i] = 0
            set lastCastUnitY[i] = 0
            return false
        endfunction

    //***************************************************************
       
        private module DiesInit
            private static method onInit takes nothing returns nothing
                call RegisterUnitIndexEvent(Condition(function DiesFunc), UnitIndexer.DEINDEX)
            endmethod
        endmodule

        private struct DIES
            implement DiesInit
        endstruct
    endlibrary
     


    ZINC version:
    Code (vJASS):
    //! zinc
    library GetLastCastAbility requires Table, RegisterPlayerUnitEvent, UnitIndexer

    /*   by edo494 version 1.0.a.z
    *
    *============================================================================
    *
    * Requires:
    *
    * Table by Bribe - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
    *
    * RegisterPlayerUnitEvent by Magtheridon96 - http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
    *
    * UnitIndexer by Nestharus - http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
    *
    *============================================================================
    *  
    *   This library includes:
    *
    *       - Allows you to retrieve last cast spells ID(returns integer)
    *       - Allows you to retrieve last cast spells target
    *       - Allows you to retrieve last cast spells caster
    *       - Allows you to retrieve last cast spells X and Y coordiantions
    *       - Allows you to retrieve last cast spells ID by specific unit
    *       - Allows you to retrieve target of cast spell by specific unit
    *       - Allows you to retrieve X and Y coordinates of last cast spell by specific unit
    *       - Additionally this allows you to pass unit's index and returns the unit's last cast ability
    *
    *   This also features "BAN/UNBAN" SPELL which you can add spells into it
    *   If units cast those spells it will not get registered.
    *
    *       This feature can be used for things like Spell Steal for either
    *       not registering the spell steal(because you dont want to steal that dont you?)
    *       or for spells that you dont want to be spell stealed.
    *
    *   Also if you want to catch only heros spells, there is texted if in MainBody function which
    *   you can use.
    *
    *============================================================================
    *
    *   Issues:
    *       You cant register passives for instance Bash because they
    *       technically never fire the event Unit - a Unit starts the effect of an ability.
    *
    *       Also if you cast spell with no target the GetLastCastAbilityX, Y and
    *       GetLastCastSpellTarget will return 0, 0, null
    *
    *============================================================================
    *  
    *   The API is:
    *  
    *       function GetLastCastAbility takes nothing returns integer
    *       function GetLastCastAbilityTarget takes nothing returns unit
    *       function GetLastCastAbilityUnit takes nothing returns unit
    *       function GetLastCastAbilityX takes nothing returns real
    *       function GetLastCastAbilityY takes nothing returns real
    *
    *   Based on Unit:
    *      
    *       function GetUnitLastCastAbility takes unit returns integer
    *       function GetUnitLastCastAbilityTarget takes unit returns unit
    *       function GetUnitLastCastAbilityX takes unit returns real
    *       function GetUnitLastCastAbilityX takes unit returns real
    *
    *   Based on Unit's index:
    *
    *       function GetUnitLastCastAbilityById takes integer returns integer
    *       function GetUnitLastCastAbilityTargetById takes integer returns unit
    *       function GetUnitLastCastAbilityXById takes integer returns real
    *       function GetUnitLastCastAbilityXById takes integer returns real
    *
    *   Ban API:
    *
    *       function LastAbilityAddFilter takes integer returns nothing
    *       function LastAbilityRemoveFilter takes integer returns nothing
    *
    *============================================================================
    *
    *   Change Log:
    *
    *       1.0.z    - Intial Release
    *
    *       1.0.a.z  - removed the local integer from mainbody function
    *
    *============================================================================
    */

    {
            private integer lastCastAbilityCaster = 0;
            private Table myTab;
            private integer lastCastUnitAbility[8192];
            private unit lastCastUnitTarget[8192];
            private real lastCastUnitX[8192];
            private real lastCastUnitY[8192];
           
            //! textmacro GETLAST_GetLast takes Name, RSName, RName
                public function GetLastCast$Name$() -> $RSName$ { return $RName$; }
            //! endtextmacro
           
            //! runtextmacro GETLAST_GetLast("Ability", "integer", "lastCastUnitAbility[lastCastAbilityCaster]")
            //! runtextmacro GETLAST_GetLast("AbilityUnit", "unit", "GetUnitById(lastCastAbilityCaster)")
            //! runtextmacro GETLAST_GetLast("AbilityTarget", "unit", "lastCastUnitTarget[lastCastAbilityCaster]")
            //! runtextmacro GETLAST_GetLast("AbilityX", "real", "lastCastUnitY[lastCastAbilityCaster]")
            //! runtextmacro GETLAST_GetLast("AbilityY", "real", "lastCastUnitY[lastCastAbilityCaster]")
           
            //! textmacro GETCAST_LAST_UNIT takes Name, Return, what
                public function GetUnitLastCast$Name$(unit u) -> $Return$ { return lastCastUnit$what$[GetUnitUserData(u)]; }
            //! endtextmacro
           
            //! runtextmacro GETCAST_LAST_UNIT("Ability", "integer", "Ability")
            //! runtextmacro GETCAST_LAST_UNIT("X", "real", "X")
            //! runtextmacro GETCAST_LAST_UNIT("Y", "real", "Y")
            //! runtextmacro GETCAST_LAST_UNIT("Target", "unit", "Target")
       
            //! textmacro GetLastCastAbility_GETUNITLASTBYID takes name, return, what
                public function GetUnitLastCast$name$ById(integer index) -> $return$ { return lastCastUnit$what$[index]; }
            //! endtextmacro

            //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Ability", "integer", "Ability")
            //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("X", "real", "X")
            //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Y", "real", "Y")
            //! runtextmacro GetLastCastAbility_GETUNITLASTBYID("Target", "unit", "Target")
           
           
            public function LastAbilityAddFilter(integer abilcode) { myTab[abilcode] = 1; }
           
            public function LastAbilityRemoveFilter(integer abilcode) { myTab[abilcode] = 0; }
           
            function MainBody()
            {
                if (myTab[GetSpellAbilityId()] != 1)
                {
                    lastCastAbilityCaster = GetUnitId(GetTriggerUnit());
                    lastCastUnitAbility[lastCastAbilityCaster] = GetSpellAbilityId();
                    lastCastUnitTarget[lastCastAbilityCaster] = GetSpellTargetUnit();
                    lastCastUnitX[lastCastAbilityCaster] = GetSpellTargetX();
                    lastCastUnitY[lastCastAbilityCaster] = GetSpellTargetY();
                }
            }
           
            function DiesFunc() -> boolean
            {
                integer i = GetIndexedUnitId();
                lastCastUnitAbility[i] = 0;
                lastCastUnitTarget[i] = null;
                lastCastUnitX[i] = 0;
                lastCastUnitY[i] = 0;
                return false;
            }
           
            function onInit()
            {
                myTab = Table.create();
                RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function MainBody);
                RegisterUnitIndexEvent(Condition(function DiesFunc), UnitIndexer.DEINDEX);
            }
        }

    //! endzinc
     
     
    Last edited: Dec 31, 2012
  2. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Would be cool is this used SpellEffectEvent by Bribe and coordinates rather than locations.

    You may argue that less requirements = good, but we don't believe that here in the JASS Realm >:D

    Also, instead of relying on the user setting up an array of 'banned' abilities, you could have a function that stores a boolean in a hashtable to indicate that a certain ability is banned.

    The user would call the function from any other trigger:

    Code (vJASS):
    struct SetupAbilitiesCast extends array

        private static method onInit takes nothing returns nothing
            call GetLastCastAbility_Ban('A000')
            call GetLastCastAbility_Ban('A004')
            // etc...
        endmethod

    endstruct


    The ban function would just be something that stores a 'true' boolean into your own hashtable.

    This method is better than having an array of abilities because the algorithm has a complexity of O(1) as opposed to the O(n) that your method has.

    When an ability is cast, just load the boolean to determine whether you should skip this instance or not.

    ACTUALLY, on second thought, it would be much better to have users register abilities that they want this system to run for.
    Yes, it's more work for the users, but it makes more sense.

    And why are you putting your API functions inside that scope?

    Functions inside a scope are private by default :C

    By the way, I'd recommend using Table by Bribe too.
    It's really awesome and more beautiful than those shitty Hashtable natives c:
     
  3. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    Well, I didnt even know there is something like that :D Ill look into that one

    Nope :D

    Thats actually a damn good idea :D

    Im still newb and Ive saw you and others talking about O(1), O(n)... but well, I dont know what that mean :D Explanation would be great

    Im not working with vJass long enough to know such a things, so could you give me some veeery basic example?

    Sure?
    jass long

    Code (vJASS):
    //library GetLastCastAbility:



    a
    // scope GetLastCastAbility_GetLastCastSpell begins
       
    //textmacro instance: GETLAST("Ability", "ability", "lastCastAbility")
            function GetLastCastAbility takes nothing returns ability
                return lastCastAbility
            endfunction
    //end of: GETLAST("Ability", "ability", "lastCastAbility")
    //textmacro instance: GETLAST("AbilityId", "integer", "lastCastAbilityId")
            function GetLastCastAbilityId takes nothing returns integer
                return lastCastAbilityId
            endfunction
    //end of: GETLAST("AbilityId", "integer", "lastCastAbilityId")
    //textmacro instance: GETLAST("AbilityUnit", "unit", "lastCastAbilityUnit")
            function GetLastCastAbilityUnit takes nothing returns unit
                return lastCastAbilityUnit
            endfunction
    //end of: GETLAST("AbilityUnit", "unit", "lastCastAbilityUnit")
    //textmacro instance: GETLAST("AbilityTarget", "unit", "lastCastAbilityTarget")
            function GetLastCastAbilityTarget takes nothing returns unit
                return lastCastAbilityTarget
            endfunction
    //end of: GETLAST("AbilityTarget", "unit", "lastCastAbilityTarget")
    //textmacro instance: GETLAST("AbilityTargetLoc", "location", "lastCastAbilityLoc")
            function GetLastCastAbilityTargetLoc takes nothing returns location
                return lastCastAbilityLoc
            endfunction
    //end of: GETLAST("AbilityTargetLoc", "location", "lastCastAbilityLoc")
       
       
    //textmacro instance: BYID("Ability", "ability", "AbilityHandle", "97612")
            function GetLastCastAbilityByUnit takes unit u returns ability
                return LoadAbilityHandle(lastcast, GetHandleId(u), 97612)
            endfunction
    //end of: BYID("Ability", "ability", "AbilityHandle", "97612")
    //textmacro instance: BYID("AbilityTarget", "unit", "UnitHandle", "97666")
            function GetLastCastAbilityTargetByUnit takes unit u returns unit
                return LoadUnitHandle(lastcast, GetHandleId(u), 97666)
            endfunction
    //end of: BYID("AbilityTarget", "unit", "UnitHandle", "97666")
    //textmacro instance: BYID("AbilityId", "integer", "Integer", "97548")
            function GetLastCastAbilityIdByUnit takes unit u returns integer
                return LoadInteger(lastcast, GetHandleId(u), 97548)
            endfunction
    //end of: BYID("AbilityId", "integer", "Integer", "97548")
    //textmacro instance: BYID("AbilityTargetLoc", "location", "LocationHandle", "97652")    
            function GetLastCastAbilityTargetLocByUnit takes unit u returns location
                return LoadLocationHandle(lastcast, GetHandleId(u), 97652)
            endfunction
    //end of: BYID("AbilityTargetLoc", "location", "LocationHandle", "97652")    

           
            function GetLastCastAbility_GetLastCastSpell__MainBody takes nothing returns nothing
                local integer looper= 0
              //if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
                loop
                    if GetSpellAbilityId() == banned[looper] then
                        return
                    endif
                    exitwhen looper == bannedmax
                    set looper=looper + 1
                endloop
                call FlushChildHashtable(lastcast, GetHandleId(lastCastAbilityUnit))
                call MoveLocation(lastCastAbilityLoc, GetSpellTargetX(), GetSpellTargetY())
                set lastCastAbility=GetSpellAbility()
                set lastCastAbilityId=GetSpellAbilityId()
                set lastCastAbilityUnit=GetTriggerUnit()
                set lastCastAbilityTarget=GetSpellTargetUnit()
                call SaveAbilityHandle(lastcast, GetHandleId(lastCastAbilityUnit), 97612, lastCastAbility)
                call SaveInteger(lastcast, GetHandleId(lastCastAbilityUnit), 97548, lastCastAbilityId)
                call SaveUnitHandle(lastcast, GetHandleId(lastCastAbilityUnit), 97666, lastCastAbilityTarget)
                call SaveLocationHandle(lastcast, GetHandleId(lastCastAbilityUnit), 97652, lastCastAbilityLoc)
              //endif
            endfunction

            function OnInit takes nothing returns nothing
                local trigger t= CreateTrigger()
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
                call TriggerAddAction(t, function GetLastCastAbility_GetLastCastSpell__MainBody)
                set t=null
                set banned[1]='A000'
            endfunction
           
    // scope GetLastCastAbility_GetLastCastSpell ends
       

    //library GetLastCastAbility ends

    took from jasshleper compiler when I made the misstake
    The function MainBody is private on purpose, I dont want users to call it anywhere they want.
    I've actually tested it and it works fine as it is(I mean the private/public thingy)

    Anyways, thx for great suggestions. Ill update it as soon as possible
     
  4. mckill2009

    mckill2009

    Joined:
    Mar 10, 2009
    Messages:
    4,696
    Resources:
    34
    Maps:
    5
    Spells:
    27
    JASS:
    2
    Resources:
    34
    - why are you putting a scope inside the library?
    - make the function onInit and variables private
    - the banned[1] could be;
    Code (vJASS):

    function AbilityBan takes integer abilityID returns nothing
       if AbilCount==bannedmax then
          call BJDebugMsg("ERRORRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR")
       else
          set banned[AbilCount] = abilityID
          set AbilCount = AbilCount + 1
       endif            
    endfunction
     

    no Mags is not sure, he maybe talking about structs :)...
     
    Last edited: Aug 8, 2012
  5. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
    You don't need to store it in a hashtable, just use the method Bribe's SpellEffectEvent uses, that's possibly the fastest way.

    And yea, I agree with the custom "BanSpell" function (and possibly an "UnbanSpell" one as well, might come in handy), it's definitely easier and much more user-friendly than having to write a huge list of banned spells, things tend to get lost quite easily that way. Just keep it simple, 1 trigger per 1 spell, and you can ban the necessary dummy spells from each spell trigger using that function, that can also be made inline-friendly, so you won't lose any speed.
     
  6. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Well, I don't use scopes, so I forgot how they work xD
    I only use structs for map-specific things and certain modules, and libraries for major systems and data repositories.

    @Luorax:
    It would stilll be using hashtables :p

    Imo, the fastest model for this resource is this:

    Code (vJASS):
    /*****************************************
    *
    *   API:
    *   ----
    *
    *       struct LastCastAbility extends array
    *
    *           static thistype last
    *               - The instance of the last ability cast.
    *
    *           integer abilityId
    *           unit caster
    *           unit target
    *           real targetX
    *           real targetY
    *               - Data for last-cast instances.
    *
    *           static method operator [] takes unit whichUnit returns thistype
    *               - Returns the instance of the unit.
    *
    *           static method register takes integer abilityId returns nothing
    *               - Registers an ability for the system.
    *
    *       function GetLastCastAbilityId takes nothing returns integer
    *       function GetLastCastAbilityUnit takes nothing returns unit
    *       function GetLastCastAbilityTarget takes nothing returns unit
    *       function GetLastCastAbilityTargetX takes nothing returns real
    *       function GetLastCastAbilityTargetY takes nothing returns real
    *           - Retrieval of data for the last cast ability.
    *
    *       public function Register takes integer abilityId returns nothing
    *           - Alternate function for registering a spell to the system.
    *
    *****************************************/

    library LastCastAbility requires UnitIndexer, SpellEffectEvent
       
        struct LastCastAbility extends array
           
            static thistype last = 0
           
            integer abilityId
            unit caster
            unit target
            real targetX
            real targetY
           
            /*
            *   I am only using this function to
            *   save a bit of memory in case any of
            *   the referenced handles is removed.
            */

            private static method deindex takes nothing returns nothing
                set thistype(GetIndexedUnitId()).caster = null
                set thistype(GetIndexedUnitId()).target = null
            endmethod
           
            implement UnitIndexStruct
           
            private static method run takes nothing returns nothing
                local thistype this = GetUnitUserData(GetTriggerUnit())
               
                set this.abilityId = GetSpellAbilityId()
                set this.caster = GetUnitById(this)
                set this.target = GetSpellTargetUnit()
                set this.targetX = GetSpellTargetX()
                set this.targetY = GetSpellTargetY()
               
                set last = this
            endmethod
           
            static method register takes integer abilityId returns nothing
                call RegisterSpellEffectEvent(abilityId, function thistype.run)
            endmethod
        endstruct
       
        function GetLastCastAbilityId takes nothing returns integer
            return LastCastAbility.last.abilityId
        endfunction
       
        function GetLastCastAbilityUnit takes nothing returns unit
            return LastCastAbility.last.caster
        endfunction
       
        function GetLastCastAbilityTarget takes nothing returns unit
            return LastCastAbility.last.target
        endfunction
       
        function GetLastCastAbilityTargetX takes nothing returns real
            return LastCastAbility.last.targetX
        endfunction
       
        function GetLastCastAbilityTargetY takes nothing returns real
            return LastCastAbility.last.targetY
        endfunction
       
        public function Register takes integer abilityId returns nothing
            call LastCastAbility.register(abilityId)
        endfunction
    endlibrary


    It's also incredibly clean, sweet and short ^_^

    edit
    Fixed. xD
     
  7. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I know, but it'd make banning/unbanning spells faster. Just because you're using hashtables, you don't have to use any everytime you can :)
     
  8. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    And why are you including bannning/unbanning spells? That should be a separate resource.

    This is called last cast ability or w/e, so it should return the last ability that a unit used.

    edit
    Mag hit it perfectly with what he thinks you should revise your resource to be.

    Focus only on what the resource should do, don't add in extra crap no matter how much you want it in there. That's the best advice I can give to you =).
     
  9. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
    How is banning/unbanning spells from this snippet a different resource? It is essential to have a banning function, you want to return the last ability used, which shouldn't be a dummy spell.
     
  10. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    I have updated it slightly btw.

    I dont think its really needed to use structs, Im not amongst those who abuse the powers of structures at every oppoturnity.
    It does what I made it for to do.

    Also I dont say its not fact but how can be table faster then normal hashtable function call?
    Also how can structs be faster then normal function calls?
     
  11. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,426
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Nice job.

    Table isn't faster than a normal hashtable call, it is just more "efficient" memory-wise to use since it uses only 1 hashtable for everything. So if you have like 10 systems or spells which each use their own hashtable, you end up using 10 hashtables. But if you switch them all to use table, you use only 1. It isn't a big deal, but it is a pretty nice thing for mapmaking. You don't have to swap completely to it, however. You can just abuse static ifs and make table an optional requirement. :)

    As for structs, Mag used it because he used UnitIndexer instead of a hashtable. By doing so, he was able to save everything to the unit id rather than their handle id.

    However, your version is perfectly fine. The speed difference is negligible and the API is the same so it doesn't really matter. (actually, Mag's doesn't have the unit-specific functions)

    -----

    As for the system itself, you don't need to use SaveAbilityHandle. The type
    ability
    is not used in JASS (or GUI, for that matter).

    You can also just save the X/Y of the spell individually and scrap saving the location, since locations are scarcely used in JASS anyway.

    Also make the globals all private so that they won't be modified outside the scope.

    Otherwise, it looks good. :)
     
  12. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,149
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Dummy Spells are cast by Dummy Units :\

    If you're going to do that, rename it to FilterSpell or w/e so that it's not misleading. Also, you should never be able to unfilter a spell, that's pointless. After all, these are dummy spells we are talking about, so permanently filtering them is fine.


    The reason mag wants you to use Table is because you are using an entire hashtable for one tiny resource. You do realize that a map can only have 255 hashtables in it right? Why does your resource get to have its own hashtable?

    Use Table, your resource doesn't necessitate the need for its own hashtable.
     
  13. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Simply using structs is not exactly faster, but it allows you to make things faster.
    For example, instead of hashtables, I'm using a UnitIndexer and hence, only arrays, of course, your version using a hashtable is fine.

    It would be better if it used Table, but that's not exactly the most important change.

    Right now, what's important is getting rid of the 'ability' caching and the 'location' caching, because they are pretty useless. The location is only useful if you want to get the Z of the target location.
     
  14. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
    In the most cases, but not always. Some of my heroes also have dummy spells, to cancel spells, or to display cooldowns - for me though it's simple to filter them, as all the hero spells are registered to my Ability struct, and I'm not using other pitiful dummy abilities to place bonuses, heals, dots, or other kind of things.

    Unfiltering them was just an idea, I don't see a reason why it shouldn't be included - one might find it useful. An example: an ultimate spell, with only one level, where the second, invisible level is a dummy one to decrease its cooldown to 0.5 seconds. It's based on Berserk, so it doesn't interrupt movement. The hero's passive makes their normal spells able to crit, and whenever they do so, the ultimate's cooldown is reduced to 0.5 seconds - it's readded, set to level 2 and the hero is ordered to cast it.

    In that case, you don't want it to be the last spell cast on the list, because it wasn't cast, so you have to temporarily add it to the list of banned spells (of course you can also make a dummy spell, but in this scenario it's unnecessary). Just because you can't find use for something, others may do, and you're making resources for others, not only for yourself.
     
  15. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    A totally different resource called AbilityList would be cool.
    There could be a ton of other resources that could work off of that list, so having it as an entire resource is a good idea.

    It's not a requirement though.

    I think having the ability to register abilities is better than having the ability to ban them.

    This way, you would have 1 call per 1 spell trigger on map init.
     
  16. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    it would be nice, but I cant have banability and allowability at same time
    Also think about it:
    Yes its 1 call per 1 spell trigger but, if we want basic abilities all to be registered, we need to call this function 778 times :D + the custom ones.
    You wont ban 778 functions, I personally dont know any map that has 700 custom abilities.
    Btw update incomming(not today tho.)
     
    Last edited: Aug 11, 2012
  17. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
  18. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    huh, you got me :D
    But still IceFrog most definitely is not going to come here to copy something that he already has in his map :D (I assume this is DotA)
    But you proved "Never say Never" :D
     
  19. Luorax

    Luorax

    Joined:
    Aug 7, 2009
    Messages:
    1,301
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Look at my signature, then look at the map that's in the editor (IID.w3x). Anyways, I doubt DotA is any close to be as ordered as the map is on the picture.
     
  20. edo494

    edo494

    Joined:
    Apr 16, 2012
    Messages:
    3,852
    Resources:
    5
    Spells:
    1
    JASS:
    4
    Resources:
    5
    oh nice map you have, I though its dota because the minimap preview or w/e its called looks a little bit similar. Sorry for that :ogre_hurrhurr: