System Item Ability System

Tukki

is Skeleton Pirate.
Reaction score
29
Ability System

ABILITY SYSTEM
Version: 2.1​

This system has been revamped! Now it's using structs instead.
Check the readme for more info. The old version will still be available.


Requirements:

Features:
  • MUI/MPI;
  • Supports: Ability Requirements, Attribute/Level Requirements, Level Factor and Instant Use;
  • Capable of adding spells into spell books, but also the regular way;
  • Units are able to unlearn specific spells, but also all of them. (note: the spells must have been added by the system for this to work)

Purpose: Making a cool way of adding spells to units! Adds spells to units depending on items.

CODE
JASS:
 //===========================================================================
// Ability System v 2.1 - by Tukki
//===========================================================================
//*
//* Example of use:
//*     local spellData d = spellData.create('I000', 'A000', 3) - add the spell with 
//*                                                               3 levels.
//*         
//*         set d.instant = true                                - make it instantly 
//*                                                               try to give the unit 
//*                                                               this spell.
//*         
//*         call d.addStatReq(0, 0, 0, 2, 1)                    - make it require 
//*                                                               2*ABILITY_LEVEL in level 
//*                                                               to learn the spell.
//*
//*         set d.addSpellBook = 'A001'                         - add the spell into a
//*                                                               spell book when learned.
//*                                                               'A001' is the rawcode of 
//*                                                               the dummy spell book.
//***************************************************************************
//* Now when a unit picks up a item of 'I000' type it will check if he meets
//* the requirements. In this case it requires that he is in level 2/4/6 +.
//*
//* Stuff you may read, but not set:
//*
//* itemId    - the rawcode of the item                 (integer)
//* maxLevel  - the max level of the spell              (integer)
//* spellId   - the rawcode of the ability              (integer)
//* spellBook - rawcode of the dummy spell book         (integer)
//* agiReq    - agility requirement                     (integer)
//* strReq    - strength requirement                    (integer)
//* intReq    - intelligence requirement                (integer)
//* lvlReq    - the hero-level requirement              (integer)
//* factor    - level factor of the requirements        (real)
//* useReq    - whether it has requirements or not      (boolean)
//* spellReq  - the rawcode of the required spell       (integer)
//* spellLvl  - the required level of above spell       (integer)
//*
//* Stuff you may read and set:
//*
//* instant   - if the spell will be instantly learned  (boolean)
//===========================================================================
library AbilitySystem initializer InitTrig requires Table

    globals
        //===========================================================================
        //                        START OF CONFIGURATION
        //===========================================================================
        private constant integer MAXIMUM_ABILITIES = 5    // Max abilities a unit may learn.
        private constant integer MAXIMUM_INSTANCES = 8100 // MAXIMUM_INSTANCES/MAXIMUM_ABILITIES is the maximum number of units who can use this system.
        
        // NOTE: Only if RETAIN_ON_FAIL and the user fails to learn the spell he will get his
        // resources back.
        private constant integer GOLD_COST         = 0    // The gold cost of the item.
        private constant integer LUMBER_COST       = 0    // The lumber cost of the item.
        
        private constant boolean RETAIN_ON_FAIL    = false // Give a new item to a failing unit.
        private constant boolean COUNT_BONUSES     = false // Count attribute bonuses (in green)
        private constant boolean INSTANT_LEARN     = false // Instantly learn the item's spell.
        private constant boolean USE_CHARGES       = false // Do you use charged items?

        private constant string DIALOG_MENU        = "Choose ability to unlearn" // Menu text.
        
        //----------------
        // Error message when a unit tries to learn/unlearn spells.
        private constant string ERROR_DIALOG       = "No abilities to unlearn!" // no abilities?
        private constant string ERROR_MAX_LEARNED  = "Maximum amount of spells learned!" // maximum spells learned!!
        private constant string ERROR_MAX_LEVELD   = "You have mastered this spell!" // When the unit has maxed the spell.
        
        // Error messages for different requirements, should be rather clear.
        private constant string ERROR_COLOR        = "|CFFFFCC00" // Color of the error text.
        private constant string ERROR_FAIL_REQ     = "You must have following in order to learn the spell:"
        
        // Different Strength/Agility/Intelligence/Level and ability requirements fail-texts.
        private constant string ERROR_STRENGTH     = "Strength: " 
        private constant string ERROR_AGILITY      = "Agility: "  
        private constant string ERROR_INTELLIGENCE = "Intelligence" 
        private constant string ERROR_LEVEL        = "Hero level: "
        private constant string ERROR_ABILITY_REQ  = "The spell: "
        
        private constant string EFFECT_PATH        = ""       // The effect path.
        private constant string ATTACHMENT_POS     = "origin" // Attachment point on the unit.
        //===========================================================================
        //                          END OF CONFIGURATION
        //===========================================================================
    endglobals
    
    //===========================================================================
    globals
        private HandleTable unitTable
        private Table       itemTable
        private HandleTable dialogTable
    endglobals
    
    //===========================================================================
    struct spellData
        readonly integer itemId = 0
        readonly integer maxLevel = 1
        readonly integer spellId
        readonly integer spellBook = 0
        
        readonly integer agiReq = 0
        readonly integer strReq = 0
        readonly integer intReq = 0
        readonly integer lvlReq = 0
        readonly real    factor = 0
        readonly boolean useReq = false
        
        readonly integer spellReq = 0
        readonly integer spellLvl = 0
        boolean instant
        
        //---------------------------------------------------------------------------
        static method create takes integer iid, integer sid, integer max returns spellData
         local spellData this = spellData.allocate()
         
            set .spellId = sid
            set .maxLevel = max
            set .itemId = iid
            set .instant = INSTANT_LEARN
            
            set itemTable[iid] = this
            return this
        endmethod
        
        //---------------------------------------------------------------------------
        method operator addSpellBook= takes integer sbid returns nothing
         local integer i = 0
            set .spellBook = sbid    
            loop
                exitwhen i > 11
                call SetPlayerAbilityAvailable(Player(i), sbid, false)
                set i = i + 1
            endloop
        endmethod
        
        //---------------------------------------------------------------------------
        method addStatReq takes integer str, integer agi, integer int, integer lvl, real f returns nothing
            set .strReq = str
            set .agiReq = agi
            set .intReq = int
            set .lvlReq = lvl
            set .factor = f
            set .useReq = true
        endmethod
        
        //---------------------------------------------------------------------------
        method addAbilReq takes integer reqId, integer reqLevel returns nothing
            set .spellReq = reqId
            set .spellLvl = reqLevel
        endmethod
        
        //---------------------------------------------------------------------------
        private method onDestroy takes nothing returns nothing
            call itemTable.flush(.itemId)
        endmethod
    endstruct
    
    //===========================================================================
    private struct unitData[MAXIMUM_INSTANCES]
        unit u
        integer array spells[MAXIMUM_ABILITIES]
        integer counter = 0
        
        //---------------------------------------------------------------------------
        method add takes integer id returns nothing
            call UnitAddAbility(.u, id)
            set .spells[.counter] = id
            set .counter = .counter + 1
        endmethod
        
        //---------------------------------------------------------------------------
        private method onDestroy takes nothing returns nothing
            call unitTable.flush(.u)
        endmethod
    endstruct
    
    //===========================================================================
    private struct dialogData
        unit u
        dialog d
        
        integer array buttonId[32]
        button array buttons[32]
        integer counter = 0
        
        //---------------------------------------------------------------------------
        private method onDestroy takes nothing returns nothing
            call dialogTable.flush(.d)
        endmethod
    endstruct
    
    //===========================================================================
    private function ErrorMessage takes player p, string message returns boolean
        call DisplayTextToPlayer(p, 0, 0, message)
        return false
    endfunction
    
    //===========================================================================
    private function ReturnItem takes spellData d, unit to returns nothing
       if (RETAIN_ON_FAIL) then
           if (d.instant) then
                call CreateItem(d.itemId, GetUnitX(to), GetUnitY(to))
                return
            endif
            call UnitAddItemById(to, d.itemId)
        else
            call SetPlayerState(GetOwningPlayer(to), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(to), PLAYER_STATE_RESOURCE_GOLD)+GOLD_COST)
            call SetPlayerState(GetOwningPlayer(to), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(GetOwningPlayer(to), PLAYER_STATE_RESOURCE_LUMBER)+GOLD_COST)
        endif
    endfunction
    
    //===========================================================================
    private function CheckStats takes spellData d, unit u returns boolean
     local real f      = 1
     local integer agi = d.agiReq
     local integer str = d.strReq
     local integer int = d.intReq
     local integer lvl = d.lvlReq
     local string s = ERROR_COLOR + ERROR_FAIL_REQ
     local integer i = 0
     
        if (d.factor > 0) then
            set f = d.factor * (GetUnitAbilityLevel(u, d.spellId)+1)
            set agi = R2I(agi * f)
            set str = R2I(str * f)
            set int = R2I(int * f)
            set lvl = R2I(lvl * f)
        endif
        
        if (GetHeroAgi(u, COUNT_BONUSES) < agi) then
            set s = s + "\n"+ERROR_COLOR + ERROR_AGILITY + "|CFFFF0000" + I2S(agi) + "|r"
            set i = 1
        endif
        
        if (GetHeroStr(u, COUNT_BONUSES) < str) then
            set s = s + "\n"+ERROR_COLOR + ERROR_STRENGTH + "|CFFFF0000" + I2S(str) + "|r"
            set i = 1
        endif
        
        if (GetHeroInt(u, COUNT_BONUSES) < int) then
            set s = s + "\n"+ERROR_COLOR + ERROR_INTELLIGENCE + "|CFFFF0000" + I2S(int) + "|r"
            set i = 1
        endif
     
        if (GetHeroLevel(u) < lvl) then
            set s = s + "\n"+ERROR_COLOR + ERROR_LEVEL + "|CFFFF0000" + I2S(lvl) + "|r"
            set i = 1
        endif
        
        if (i == 1) then
            return ErrorMessage(GetOwningPlayer(u), s)
        endif
        return true
    endfunction
    
    //===========================================================================
    private function CheckSpell takes spellData d, unit u returns boolean
     local string s = ERROR_COLOR + ERROR_FAIL_REQ
     
        if not (GetUnitAbilityLevel(u, d.spellReq) >= d.spellLvl) then
            set s = s + "\n"+ERROR_COLOR + ERROR_ABILITY_REQ + GetObjectName(d.spellReq) + ERROR_COLOR + " at level " + "|CFFFF0000" + I2S(d.spellLvl) + "|r"
            return ErrorMessage(GetOwningPlayer(u), s)
        endif
        return true
    endfunction
    
    //===========================================================================
    // MAIN - checks requirements and adds the spell to the unit if he passes
    //===========================================================================
    private function AddAbilityMain takes unit to, spellData d returns boolean
     local unitData a = unitTable[to]
     local integer c = d.spellId
     
        if (GetUnitAbilityLevel(to, c) >= d.maxLevel) then
            call ReturnItem(d, to)
            return ErrorMessage(GetOwningPlayer(to), ERROR_MAX_LEVELD)
        endif

        if (d.useReq) then
            if not (CheckStats(d, to)) then
                call ReturnItem(d, to)
                return false
            endif
        endif

        if (d.spellReq != 0) then
            if not (CheckSpell(d, to)) then
                call ReturnItem(d, to)
                return false
            endif
        endif

        if (a.counter >= MAXIMUM_ABILITIES) then
            if (GetUnitAbilityLevel(to, c) <= 0) then
                call ReturnItem(d, to)
                return ErrorMessage(GetOwningPlayer(to), ERROR_MAX_LEARNED)
            endif
        endif

        if (GetUnitAbilityLevel(to, c) <= 0) then
            if (d.spellBook != 0) then
                set c = d.spellBook
            endif
            call a.add(c)
        else
            call IncUnitAbilityLevel(to, c)
        endif
        call DestroyEffect(AddSpecialEffectTarget(EFFECT_PATH, to, ATTACHMENT_POS))
        
        return true
    endfunction
    
    //===========================================================================
    private function RemoveAbilities takes nothing returns nothing
     local dialog di = GetClickedDialog()
     local dialogData d = dialogTable[di]
     local button clicked = GetClickedButton()
     local integer i = d.counter-2
     local unitData a = unitTable[d.u]
     
        if (clicked == d.buttons[d.counter-1]) then
            set i = a.counter-1
            loop
                exitwhen i < 0
                call UnitRemoveAbility(a.u, a.spells<i>)
                set a.spells<i> = 0
                set i = i - 1
            endloop
            call a.destroy()
        endif

        loop
            exitwhen i &lt; 0
            if (clicked == d.buttons<i>) then
                call UnitRemoveAbility(a.u, a.spells<i>)
                set a.spells<i> = 0
                set a.counter = a.counter - 1
                if (a.counter &lt; 0) then
                    set a.counter = 0
                else
                    set a.spells<i> = a.spells[a.counter]
                endif
            endif
            set i = i - 1
        endloop
        
        call d.destroy()
        call DialogClear(di)
        call DialogDestroy(di)
        call DestroyTrigger(GetTriggeringTrigger())
        set di = null
    endfunction
    
    //===========================================================================
    private function BeginUnlearn takes unit who returns nothing
     local dialog di = DialogCreate()
     local trigger t = CreateTrigger()
     local integer i = 0
     local dialogData d = dialogData.create()
     local unitData a = unitTable[who]
     
     
        set dialogTable[di] = d
        set d.u = who
        set d.d = di
        call DialogSetMessage(di, DIALOG_MENU)
        loop
            exitwhen i &gt;= a.counter
            set d.buttons<i> = DialogAddButton(di, GetObjectName(a.spells<i>), 0)
            set d.buttonId<i> = a.spells<i>
            set i = i + 1
        endloop
        
        set d.buttons<i> = DialogAddButton(di, &quot;Unlearn All&quot;, 0)
        set d.buttons[i+1] = DialogAddButton(di, &quot;Cancel&quot;, 0)
        set d.counter = i+1
        
        call TriggerRegisterDialogEvent(t, di)
        call TriggerAddAction(t, function RemoveAbilities)
        call DialogDisplay(GetOwningPlayer(who), di, true)
        
        set di = null
        set t = null
    endfunction
    
    //===========================================================================
    public function Unlearn takes unit who returns boolean
        if (who != null and unitTable[who] != 0) then
            if (unitData(unitTable[who]).counter != 0) then
                call BeginUnlearn(who)
            else
                return ErrorMessage(GetOwningPlayer(who), ERROR_DIALOG)
            endif
        endif
        return true
    endfunction
    
    //===========================================================================
    private function remove takes item i returns nothing
        call TriggerSleepAction(0)
        if (GetWidgetLife(i)&gt;0) then
            if (USE_CHARGES) then
                call SetItemCharges(i, GetItemCharges(i)-1)
                if (GetItemCharges(i) &lt;= 0) then
                    call RemoveItem(i)
                endif
                return
            endif
            call RemoveItem(i)
        endif
    endfunction
    
    //===========================================================================
    // CORE - checks and makes the appropriate calls
    //===========================================================================
    private function Core takes nothing returns boolean
     local integer id = GetItemTypeId(GetManipulatedItem())
     local unit u = GetTriggerUnit()
     local spellData d = itemTable[id]
     local unitData a = unitTable<u>
     local eventid e = GetTriggerEventId()
        
        if (d!=0) then
            if (a == 0) then
                set a = unitData.create()
                set a.u = GetTriggerUnit()
                set unitTable<u> = a
            endif
            if (e == EVENT_PLAYER_UNIT_PICKUP_ITEM) then
                if (d.instant) then
                    call AddAbilityMain(GetManipulatingUnit(), d)
                    call RemoveItem(GetManipulatedItem())
                endif
            else
                call AddAbilityMain(GetManipulatingUnit(), d)
                call remove.execute(GetManipulatedItem())
            endif
        endif
        set u = null
        set e = null
        return false
    endfunction
    
    //===========================================================================
    // DEATH RECYCLER - destroys struct on dying non-hero units (as heroes are revivable)
    //===========================================================================
    private function death takes nothing returns boolean
     local unit u = GetTriggerUnit()
        
        if (unitData(unitTable<u>) != 0 and IsUnitType(u, UNIT_TYPE_HERO) == false) then
            call unitData(unitTable<u>).destroy()
        endif
        set u = null
        return false
    endfunction
    
    //===========================================================================
    // INITIALIZER - sets the stone rollin&#039;
    //===========================================================================
    private function InitTrig takes nothing returns nothing
     local trigger t = CreateTrigger()
     local integer i = 0

        set unitTable = HandleTable.create()
        set itemTable = Table.create()
        set dialogTable = HandleTable.create()
        
        call unitTable.reset()
        call itemTable.reset()
        call dialogTable.reset()
        loop
            exitwhen i == bj_MAX_PLAYER_SLOTS
            call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_USE_ITEM, null)
            call TriggerRegisterPlayerUnitEvent(t, Player(i),EVENT_PLAYER_UNIT_PICKUP_ITEM, null)
            set i = i + 1
        endloop
        call TriggerAddCondition(t, Condition(function Core))
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(t, Condition(function death))
    endfunction

endlibrary</u></u></u></u></i></i></i></i></i></i></i></i></i></i></i>


Methods for different ways of registering spells with items.
JASS:
static method create takes integer iid, integer sid, integer max returns spellData

Arguments: iid - the ItemID, sid - the SpellID, max - the maximum level

If you want to add a spell into a spellbook use;
JASS:
method operator addSpellBook= takes integer sbid returns nothing

Argument: sbid - SpellBookID

README
JASS:
 *********************************************************
*         ITEM ABILITY LEARN SYSTEM - v 2.1             *
*                  by: Tukki                            *
*            Give credits when used!                    *
*********************************************************      
*                                                       *
*   CONTENTS:                                           *        
*                                                       *
*   1 - Implementation/Misc                             *
*   2 - Available Functions                             *
*   3 - Argument Explanations                           *
*                                                       *

*********************************************************
======================================================================================
[1] &#039;Implementation/Misc&#039;
======================================================================================

=IMPLEMENTATION=======================================================================

Requirements;
    * JASS New Gen Pack 1.5b or newer
    * A dummy ability which your items use (Makes them usable) - not really required

1. Click on the Map System folder and press [Ctrl] + C (hotkey for &quot;Copy&quot;)
2. Go to your map and press [Ctrl] + V (hotkey for &quot;Paste&quot;)
3. Save. If it works, congratulations! Else maybe you already have an existing trigger
   with the same name as one of my triggers. If that is the problem then do following
   1. left-click on the name of one of my triggers (the one who is the problem) and change
   the name to something completely different.
   2. Save and if there are no problems then thumbs-up!
   3. Report the problem following the next steps.

=BUGG REPORTS=========================================================================
If you experiance that something is wrong, or see in the code that something is leaking
/missing, please post it in the thread located at thehelper.net from which you downloaded 
this map.

======================================================================================
[2] &#039;Available Functions&#039;
======================================================================================

=FUNCTION LIST========================================================================
call spellData.create(integer itemId, integer spellId, integer maxLevel)
call &lt;spellData-variable&gt;.addStatReq(integer str, integer agi, integer int, integer lvl, real factor)
call &lt;spellData-variable&gt;.addAbilReq(integer spellId, integer requiredLevel)

set  &lt;spellData-variable&gt;.addSpellBook = integer spellBookId
set  &lt;spellData-variable&gt;.instant = boolean isInstant

call AbilitySystem_Unlearn(unit whichUnit)                                                                                         

call &lt;spellData-variable&gt;.destroy()

The &lt;spellData-variable&gt; is the spellData variable you stored the struct in when you created it
using spellData.create(...). 
Example:
local spellData d = spellData.create(....)

======================================================================================
The function names are rather self-explaining. But I will give a short description of 
each of them.

--------------------------------------------------------------------------------------
create takes integer itemId, integer spellId, integer maxLevel
--------------------------------------------------------------------------------------
Syntax: call spellData.create(...) OR set &quot;someVariable&quot; = spellData.create(...)

The basic function. It gives you the spellId ability when you use/pick up the itemId 
item. Store the returned struct in order to use the functions below.

--------------------------------------------------------------------------------------
addStatReq takes integer str, integer agi, integer int, integer lvl, real factor
--------------------------------------------------------------------------------------
Syntax: call &quot;someVariable&quot;.spellStatReq(......)

Adds stat requirements to the spell. If factor &gt; 0 then all stat requirements will
increase with &quot;stat*factor&quot; per level. The hero must have higher or equal stats in order
to learn the spell.

-------------------------------------------------------------------------------------- 
addAbilReq takes integer spellId, integer requiredLevel
--------------------------------------------------------------------------------------
Syntax: call &quot;someVariable&quot;.spellAbilReq(....)

Adds an ability requirement, the hero must have the spell at same or higher level than 
the requiredLevel argument.

--------------------------------------------------------------------------------------
addSpellBook takes integer spellbookId
--------------------------------------------------------------------------------------
Syntax: set &quot;someVariable&quot;.addSpellBook = &#039;A000&#039;, where &#039;A000&#039; is the spell book id.

Adds the spell directly into a spellbook on the hero instead of onto the usual command
card.

--------------------------------------------------------------------------------------
instant takes boolean isInstant
--------------------------------------------------------------------------------------
Syntax: set &quot;someVariable&quot;.instant = true/false

Makes the unit who picks up the item instantly learn the spell or not.
Note: This will initially be set to the INSTANT_LEARN boolean.

--------------------------------------------------------------------------------------
Unlearn takes unit whichUnit
--------------------------------------------------------------------------------------
Syntax: call AbilitySystem_Unlearn(...)

Pops up a dialog with spells the hero may unlearn.

--------------------------------------------------------------------------------------
destroy 
--------------------------------------------------------------------------------------
Syntax: &quot;someVariable&quot;.destroy()

Removes the registered spell from the system.

======================================================================================
[3] - &#039;Argument Explanations&#039;
======================================================================================

=ARGUMENTS USED=======================================================================
boolean isInstant - boolean which may be true or false
unit whichUnit    - the unit who will learn/unlearn things
real factor       - factor for the stat-requirements. [STAT] * [FACTOR*ABILITY_LEVEL]
integer str/agi/int/lvl - different stat names, pretty obvious
&quot;someVariable&quot;    - the spellData variable I store the struct in.
integer ..Id      - the .. rawcode. I.e: The rawcode of the item

======================================================================================
                                    END OF README
======================================================================================

Changelog:
  • 2.0 - System revamped.
  • 2.1 - A small update, struct 'recycler' added.

Readme and examples of usage are included in the demo map provided.

Screenshots: -

If you have any questions regarding the system post them here, the same applies to bugg reports and improvements. I'm open to your suggestions.
 

Attachments

  • IAL_DemoMap.w3x
    52 KB · Views: 559
  • IAL_2.1.w3x
    52.9 KB · Views: 551
Considering that this completely rapes (I'll admit it) my Ability From Item system, bravo.
Now, would you like to show how one actually calls the system to add an ability?
 
Updated Readme.
Considering that this completely rapes (I'll admit it) my Ability From Item system, bravo.
kc102: Just found your system, and I really don't understand the raping. Mine will only be used when you require ability requirements/abilities added into spellbooks and is approx 600 lines long. Yours are much shorter and works perfectly for its purpose, so really, it's just a matter of what the user may need.

EDIT:
Now, would you like to show how one actually calls the system to add an ability?
Fixed.
 
kc102: Just found your system, and I really don't understand the raping. Mine will only be used when you require ability requirements/abilities added into spellbooks and is approx 600 lines long. Yours are much shorter and works perfectly for it's purpose, so really, it's just a matter of what the user may need.

Mine doesn't do spell book, yet. ;)
But mine doesn't require an integer to pass the ability along. You should look at my code for that.
I also hate mucking through a ton of code. lol
+rep for an awesome system.
 
But mine doesn't require an integer to pass the ability along. You should look at my code for that.

You mean those CoreActions and AddAbility functions? In that case I suppose I could merge them together, but it would decrease the easiness(?) of editing the code as it is at the moment.

+rep for an awesome system.
Thanks. :D
 
You mean those CoreActions and AddAbility functions? In that case I suppose I could merge them together, but it would decrease the easiness(?) of editing the code as it is at the moment.

Wait, my bad.
I thought this system had a limitation when it actually did not.
:)
 
Make it poop out food from your CD drive?

I seriously can't think of anything, really.
 
Oh! Heres an idea.
Make it so each item can be instant or not.
 
Make it so each item can be instant or not.
Already implemented. Change the 'INSTANT' variable in the config. menu if you want all of your items instant/non-instant or use:
JASS:
call IAL_InstantUse(integer IID, boolean instant)

for those items you want to be instant/non-instant.

But thanks for idea anyways :p
 
Ah. That works. I've yet to see a mod comment. >.>
Maybe add the ability to do all the function calls in one?
Also, allow for it to depend on an ability of a certain level.
Just a few more.
 
Maybe add the ability to do all the function calls in one?
You mean an extended call? There's an AddAbilityEx that does all things except for the required ability step.

Also, allow for it to depend on an ability of a certain level.
Check the demo map :p

But thanks for the interest! :)
 
JASS:
private constant function GetEffect takes nothing returns string
    return &quot;Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl&quot; 
    // change effect-path to your desired effect. 
    //Remember to use &quot;\\&quot; where there&#039;s one &quot;\&quot;.
endfunction


Why is that a function, and not simply a global?

JASS:
private constant string EFFECT = &quot;Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl&quot;
 
No idea ^^.
Will fix when I'm home later today, but thx for noticing me!
 
UPDATE!

[] Fixed some bugs with the UnlearnAll function. (Where it didn't remove abilities)
[] Added constant for the effect.
[] Updated test map, now it contains example of Unlearn/UnlearnAll functions.
[] Code optimized.
 
MASSIVE UPDATE!

  • Struct use!
  • Table is in use as well! No internal gamecache!
  • Error report revamped!
  • No I2U!
  • More optimized!
  • Supports resource give-back!

Newest version: 2.0
 
Update

  • Struct recycler added. Now it destroys structs on dead non-hero units.

Newest version: 2.1
 
General chit-chat
Help Users
  • The Helper The Helper:
    alternatively if you not making at least 23 an hour you could work in an Aldi warehouse
  • Varine Varine:
    Yeah I've been thinking about using AI for shit. I'm on vacation next week so I'm going to spend some time reorganizing everything and getting all my shit back in order
  • Varine Varine:
    lol I technically make less than 23 right now because I'm on salary and am there all the time, but it's a lot more than a normal wage still. I also have a meeting soon to renegotiate my pay because I want about a 25% increase to account for what I'm actually doing or a re-evaluation of our duties so that that my responsibilities are more in line with my pay. Depending on how that goes I'm prepared to give notice and move on, I don't mind taking less money so I'd have time for the rest of my life, but I'd rather they just fucking pay me enough to justify the commitment on my end. Plus right now I hold pretty much all the cards since I'm the only one actually qualified for my position.
    +1
  • Varine Varine:
    The other chef was there before me and got his position by virtue of being the only adult when the old general manager got married and didn't want to deal with the kitchen all the time, and happened to be in the position when the GM quit. New GM is fine with front of house but doesn't know enough about the kitchen side to really do anything or notice that I'm the one primarily maintaining it. Last time I left they hired like 3 people to replace me and there was still a noticeable drop in quality, so I got offered like 6 dollars an hour more and a pretty significant summer bonus to come back
  • Varine Varine:
    So honestly even if I leave I think it would last a couple of months until it's obvious that I am not exactly replaceable and then I would be in an even better position.
  • Varine Varine:
    But as of right now I have two other job offers that are reasonably close to what my hourly equivalency would be, and I would probably have more time for my other projects. The gap would be pretty easy to fill up if I had time to do my side jobs. I use to do some catering and private events, personal lessons, consultations, ect, and I charge like 120 an hour for those. But they aren't consistent enough for a full time job, too small of a town. And I'm not allowed to move for another year until my probation is over
  • Varine Varine:
    I guess I could get it transferred, but that seems like a hassle.
  • Varine Varine:
    Plus I have a storage room full of broken consoles I need to fix. I need to build a little reflow oven so I can manufacture some mod chips still, but it'll get there.
    +1
  • Varine Varine:
    I would like to get out of cooking in general at some point in the next ten years, but for the time being I can make decent money and pump that into savings. I've been taking some engineering classes online, but those aren't exactly career oriented at the moment, but I think getting into electronic or computer engineering of some sort would be ideal. I'm just going to keep taking some classes here and there until there's one that I am really into.
    +2
  • The Helper The Helper:
    There is money in fixing and reselling consoles. Problem is people know that so they are doing it
  • The Helper The Helper:
    If you can find a source of broken consoles though you can make money fixing them - sometimes some big money
  • Varine Varine:
    I was buying them on Ebay, but it's pretty competitive, so more recently I've just been telling the thrift stores to call me and I will come take all their electronics they can't sell. I've volunteered there before and people use them like a dump sometimes, and so they just have a massive amount of broken shit they throw away
  • Varine Varine:
    The local GoodWill was pretty into it, surprisingly the animal shelter store was not. The lady I talked to there seemed to think I was trying to steal stuff or something, she wasn't very nice about it. Like I'm just trying to stop you having to throw a bunch of electronics away, if you can sell it great. I'd probably pay you for the broken shit too if you wanted
  • Varine Varine:
    Then I make posts on Facebook yard sale pages sometimes saying I want your old electronics, but Facebook being Facebook people on there are also wary about why I want it, then want a bunch of money like it's going to be very worth it
  • Varine Varine:
    Sooner than later I'm going to get my archives business going a little more. I need some office space that is kind of hard to get at the moment, but without it, I have to be like "Yeah so go ahead and just leave your family heirlooms and hundred year old photographs here at my shitty apartment and give me a thousand dollars, and next month I'll give you a thumb drive. I promise I'll take care of them!"
    +1
  • Varine Varine:
    I can do some things with them at their home, but when people have thousands of slides and very delicate newspaper clippings and things, not really practical. I
  • Varine Varine:
    I would be there for days, even with my camera set up slides can take a long time, and if they want perfect captures I really need to use my scanners that are professionally made for that. My camera rig works well for what it is, but for enlargements and things it's not as good.
  • Varine Varine:
    I've only had a couple clients with that so far, though. I don't have a website or anything yet though.
  • Varine Varine:
    Console repair can be worthwhile, but it's also not a thing I can do at scale in my house. I just don't have room for the equipment. I need an office that I can segregate out for archival and then electronic restoration.
  • Varine Varine:
    But in order for that to be real, I need more time, and for more time I need to work less, and to work less I need a different job, and for a different job I need more money to fall back on so that I can make enough to just pay like, rent and utilities and use my savings to find these projects
    +1
  • Varine Varine:
    Another couple years. I just need to take it slow and it'll get there.
  • jonas jonas:
    any chance to get that stolen money back?
  • jonas jonas:
    Maybe you can do console repair just as a side thing, especially if there's so much competition business might be slow. Or do you need a lot of special equipment for that?
  • jonas jonas:
    I recently bought a used sauna and the preowner told me some component is broken, I took a look and it was just a burnt fuse, really cheap to fix. I was real proud of my self since I usually have two left hands for this kinda stuff :p
  • tom_mai78101 tom_mai78101:
    I am still playing Shapez 2. What an awful thing to happen, Varine, and hopefully everything has been sorted out soon. Always use multi-factor authentication whenever you have the opportunity to do so.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top