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

[JASS] Item Restriction System (IRS) v1.0f

ITEM RESTRICTION SYSTEM v1.0f

Features
  • Easy registration of specific item-type requirements.
  • Support item classes.
  • GUI-friendly interface and usage.
  • A single trigger with short code.
  • Vanilla World Editor JASS.
  • => A simple item restriction system, could be useful for RPGs.

Codes:

JASS:
//***************************************************************************************
//*                                                                                     *
//*                      ITEM RESTRICTION SYSTEM (IRS)                                  *
//*                                                                                     *
//*   Author:   Doomlord                                                                *
//*   Version:  1.0f                                                                    *
//*                                                                                     *
//*   Credits:                                                                          *
//*   + Vexorian:      SimError [url]http://www.wc3c.net/showthread.php?t=101260[/url]  *
//*   + Magtheridon96: Help with code optimization                                      *
//*   + SeriousEnemy:  Help with code optimization                                      *
//*                                                                                     *
//***************************************************************************************



//*************************************************************************
//* INTRODUCTION:                                                         *
//*                                                                       *
//* A simple system that allows for easy registration of requirements to  *
//* carry a specific item type. This system also utilizes Custom Scripts  *
//* to make it GUI-friendly.                                              *
//*                                                                       *
//* In addition, there is a tiny snippet that allows you to register      *
//* unit type(s) as a "class". This can be referenced later by using the  *
//* hashtable key (<Unit Raw Code>, 0) from IRS_Hashtable which will      *
//* give you the class string of said unit.                               *
//*                                                                       *
//*************************************************************************



//*******************
//* REQUIREMENTS:   *
//*                 *
//* None            *
//*                 *
//*******************



//************************************************************************************************************************************************
//* INSTALLATION INSTRUCTION:                                                                                                                    *
//*                                                                                                                                              *
//* Step 1: Copy the code for SimError to your map's Map Header Custom Code.                                                                     *
//*                                                                                                                                              *
//* Step 2: Copy the whole IRS folder to your map. Don't forget to turn on "Automatically create unknown variables while pasting trigger data".  *
//*                                                                                                                                              *
//* Step 3: Create a trigger that runs at Map Initialization. It will be where you register the items and Heroes.                                *
//*                                                                                                                                              *
//* Step 4: Register your desired unit type(s) as specific classes. Multiple unit types can be registered as one single type of Hero class.      *
//*                                                                                                                                              *
//* Step 5: Register your items as examplified in the Item Declaration trigger. Remember to use Map Initialization event.                        *
//*                                                                                                                                              *
//************************************************************************************************************************************************



//**************************************************************************************
//* Class Registration API                                                             *
//*                                                                                    *
//* call IRS_ClassRegistration (integer unitRawCode, string className)                 *
//*                                                                                    *
//**************************************************************************************



//**************************************************************************
//* Item Requirement Registration API                                      *
//*                                                                        *
//* call IRS_ItemRegistration (integer itemRawCode, string itemClass,      *
//* string heroClass, integer minLvl, integer minStr, integer minAgi,      *
//* integer minInt, integer rangeFilter)                                   *
//*                                                                        *
//**************************************************************************

//=====================================================================================

// Item Pickup Check

function IRS_ItemAcquireCheck takes nothing returns boolean
    local unit u = GetTriggerUnit ()
    local player p = GetOwningPlayer(u)
    local item it = GetManipulatedItem ()
    local integer i = GetItemTypeId (it)
    local integer k
    local integer j = 0


    if LoadStr(udg_IRS_Hashtable, GetUnitTypeId(u), 0) != LoadStr(udg_IRS_Hashtable, i, 1) and LoadStr(udg_IRS_Hashtable, i, 1) != null then
        call IRS_SimError(p, udg_IRS_String[0] + " " + LoadStr(udg_IRS_Hashtable, i, 1))
        call UnitRemoveItem(u, it)
        return false
    endif

    loop
        exitwhen j > 5

        if LoadStr(udg_IRS_Hashtable, GetItemTypeId(UnitItemInSlot (u, j)), 0) == LoadStr(udg_IRS_Hashtable, i, 0) and UnitItemInSlot (u, j) != it and LoadStr(udg_IRS_Hashtable, i, 0) != null then
        
            if udg_IRS_Switch then
                call IRS_SimNotify(p, udg_IRS_String[6] + " " + LoadStr(udg_IRS_Hashtable, i, 0))
                call UnitRemoveItem(u, UnitItemInSlot (u, j))
                call UnitRemoveItem(u, it)
                call UnitAddItem(u, it)
            else
                call IRS_SimError(p, udg_IRS_String[1] + " " + LoadStr(udg_IRS_Hashtable, i, 0))
                call UnitRemoveItem(u, it)
            endif
            
            return false
        endif

        set j = j + 1
    endloop


    set k = LoadInteger(udg_IRS_Hashtable, i, 2)

    if GetUnitLevel(u) < k then
        call IRS_SimError(p, udg_IRS_String[2] + " " + I2S(k))
        call UnitRemoveItem(u, it)
        return false
    endif

    set k = LoadInteger(udg_IRS_Hashtable, i, 3)

    if GetHeroStr(u, true) < k then
        call IRS_SimError(p, udg_IRS_String[3] + " " + I2S(k))
        call UnitRemoveItem(u, it)
        return false
    endif

    set k = LoadInteger(udg_IRS_Hashtable, i, 4)

    if GetHeroAgi(u, true) < k then
        call IRS_SimError(p, udg_IRS_String[4] + " " + I2S(k))
        call UnitRemoveItem(u, it)
        return false
    endif

    set k = LoadInteger(udg_IRS_Hashtable, i, 5)

    if GetHeroInt(u, true) < k then
        call IRS_SimError(p, udg_IRS_String[5] + " " + I2S(k))
        call UnitRemoveItem(u, it)
        return false
    endif
    
    set k = LoadInteger(udg_IRS_Hashtable, i, 6)
    
    if k >= 0 and k <= 2 then
    
        if k == 1 then
        
            if IsUnitType(u, UNIT_TYPE_MELEE_ATTACKER) then
                call IRS_SimError(p, udg_IRS_String[7])
                call UnitRemoveItem(u, it)
                return false
            endif
            
        elseif k == 2 then
        
            if IsUnitType(u, UNIT_TYPE_RANGED_ATTACKER) then
                call IRS_SimError(p, udg_IRS_String[8])
                call UnitRemoveItem(u, it)
                return false
            endif
            
        endif
        
    else
    
        call IRS_SimError(p, "Invalid range filter value for item")
        
    endif

    set p = null
    set it = null
    set u = null
    return false
endfunction

// Class Registration

function IRS_ClassRegistration takes integer unitType, string class returns nothing
    call SaveStr (udg_IRS_Hashtable, unitType, 0, class)
endfunction

// Item Requirement Registration

function IRS_RegisterRestrictedItem takes integer itemRawCode, string itemClass, string heroClass, integer minLvl, integer minStr, integer minAgi, integer minInt, integer rangeFilter returns nothing
    call SaveStr (udg_IRS_Hashtable, itemRawCode, 0, itemClass)
    call SaveStr (udg_IRS_Hashtable, itemRawCode, 1, heroClass)
    call SaveInteger (udg_IRS_Hashtable, itemRawCode, 2, minLvl)
    call SaveInteger (udg_IRS_Hashtable, itemRawCode, 3, minStr)
    call SaveInteger (udg_IRS_Hashtable, itemRawCode, 4, minAgi)
    call SaveInteger (udg_IRS_Hashtable, itemRawCode, 5, minInt)
    call SaveInteger (udg_IRS_Hashtable, itemRawCode, 6, rangeFilter)
endfunction

//===========================================================================
function InitTrig_IRS takes nothing returns nothing
    local trigger acquireItem = CreateTrigger()

    call TriggerRegisterAnyUnitEventBJ(acquireItem, EVENT_PLAYER_UNIT_PICKUP_ITEM)
    call TriggerAddCondition(acquireItem, Condition(function IRS_ItemAcquireCheck))

    set udg_IRS_Hashtable = InitHashtable()
    set acquireItem = null
endfunction

Range filter values are as follow:
  • "0" means the item can be used by both melee and ranged units.
  • "1" means the item is for ranged units only.
  • "2" means the item is for melee units only.
Other values will cause the system to throw an error.

Here is cool suggestion by zv27 for those who have difficulty remembering the numbers.

zv27;2476654 said:
Range filter values are as follow:

"0" means the item can be used by both melee and ranged units.
"1" means the item is for ranged units only.
"2" means the item is for melee units only.

small suggestions[I think it would be easier to navigate]

set IRS_MeleeRanged = 0 -> means the item can be used by both melee and ranged units.
set IRS_Ranged = 1 -> means the item is for ranged units only.
set IRS_Melee = 2 -> means the item is for melee units only.

call IRS_ItemRegistration ('afac', "Weapon", "Mountain King", 10, 20, 10, 10, udg_IRS_Melee)

JASS:
// Map Header Custom Code

// SimError by Vexorian at wc3c.net

// Modified version

function IRS_SimError takes player p, string s returns nothing
    local string msg = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00" + s + "|r"
    local sound error = CreateSoundFromLabel ("InterfaceError", false, false, false, 10, 10)

    if GetLocalPlayer() == p then
        call ClearTextMessages ()
        call DisplayTimedTextToPlayer (p, 0.52, 0.96, 2.00, msg)
        call StartSound (error)
    endif
endfunction

function IRS_SimNotify takes player p, string s returns nothing
    local string msg = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00" + s + "|r"
    local sound notify = CreateSoundFromLabel("Hint", false, false, false, 10, 10)

    if GetLocalPlayer() == p then
        call ClearTextMessages()
        call DisplayTimedTextToPlayer (p, 0.52, 0.96, 2.00, msg)
        call StartSound (notify)
    endif
endfunction

  • Setting
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set the error messages here --------
      • -------- Don't touch the indexes, modify the value only --------
      • -------- Wrong Hero Class --------
      • Set IRS_String[0] = This item is not for your Hero's class. It is reserved only for
      • -------- Hero already has an item of the same class --------
      • Set IRS_String[1] = Your Hero already has an item of type
      • -------- Insufficient Hero Level --------
      • Set IRS_String[2] = The minimum Level required to carry this item is
      • -------- Insufficient Strength --------
      • Set IRS_String[3] = The minimum Strength required to carry this item is
      • -------- Insufficient Agility --------
      • Set IRS_String[4] = The minimum Agility required to carry this item is
      • -------- Insufficient Intelligence --------
      • Set IRS_String[5] = The minimum Intelligence required to carry this item is
      • -------- Alternate for Hero already has an item of the same class, IRS_Switch = true only --------
      • Set IRS_String[6] = A new item has replaced an item in your inventory with class
      • -------- Ranged Only --------
      • Set IRS_String[7] = This item is for ranged units only
      • -------- Melee Only --------
      • Set IRS_String[8] = This item is for melee units only
      • -------- ================================================== --------
      • -------- Set to true to switch to Drop-old-item-of-same-class mode --------
      • Set IRS_Switch = False

Let us try to register the following requirements for Alleria's Flute of Accuracy (afac):
  • Mountain King class only.
  • Item Classification: Weapon.
  • A minimum Level of 10.
  • A minimum Strength of 20.
  • A minimum Agility of 10.
  • A minimum Intelligence of 10.
  • Ranged units only.

Here is the examplary code:

  • Examplary Declaration
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Item Requirements Registration --------
      • Custom script: call IRS_ItemRegistration ('afac', "Weapon", "Mountain King", 10, 20, 10, 10, 1)
      • -------- Item Requirements Registration - End --------



+ v1.0: Initial release.
+ v1.0a: Improved the API and the code alike. Fixed some bugs. Added error message configurables.
+ v1.0b: Fixed a bug with item type.
+ v1.0c: Added a variable creation method for the Hashtable.
+ v1.0d: Added a new boolean switch that drops an old item of the same class instead of the new one. Fixed Map Header code logic.
+ v1.0e: Added range filter.
+ v1.0f: Fixed an important bug with error messages.


FINAL WORDS

+ All feedback, testing, criticism, suggestions, etc. are welcome. Thanks in advance.
+ If you need help with this system, contact me or post in this thread.

Keywords:
item, restriction, ORPG, RPG, class
Contents

Item Restriction System v1.0f (Map)

Reviews
Item Restriction System v1.0a | Reviewed by Maker | 27th Feb 2013 APPROVED [tr] A very useful system

Moderator

M

Moderator


Item Restriction System v1.0a | Reviewed by Maker | 27th Feb 2013
APPROVED


126248-albums6177-picture66521.png


  • A very useful system
[tr]
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
JASS:
        set k = LoadInteger(udg_IRS_Hashtable, i, 5)

        if GetHeroStr(u, true) < k then
            call IRS_SimError("The minimum Strength required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif

        set k = LoadInteger(udg_IRS_Hashtable, i, 6)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif

        set k = LoadInteger(udg_IRS_Hashtable, i, 7)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif
    endif

->

JASS:
    local integer i2 = 7
    loop
        exitwhen 4 == i2

        set k = LoadInteger(udg_IRS_Hashtable, i, i2)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif
   
        set i2 = i2 - 1
    endloop

Change the following names of the function so that it won't be too vauge.
IRS_ItemRegistration -> RegisterRestrictedItem
IRS_ClassRegistration -> RegisterRestrictedItemClass

Also,i think that those messages should be configurable.

Btw, call SaveStr (udg_IRS_Hashtable, itemRawCode, 3, class)
I never knew that WE allows that kind of syntax(spaces before parentheses)
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
JASS:
        set k = LoadInteger(udg_IRS_Hashtable, i, 5)

        if GetHeroStr(u, true) < k then
            call IRS_SimError("The minimum Strength required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif

        set k = LoadInteger(udg_IRS_Hashtable, i, 6)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif

        set k = LoadInteger(udg_IRS_Hashtable, i, 7)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif
    endif

->

JASS:
    local integer i2 = 7
    loop
        exitwhen 4 == i2

        set k = LoadInteger(udg_IRS_Hashtable, i, i2)

        if GetHeroAgi(u, true) < k then
            call IRS_SimError("The minimum Agility required to carry this item is " + I2S(k))
            call UnitRemoveItem(u, it)
            return false
        endif
   
        set i2 = i2 - 1
    endloop

Change the following names of the function so that it won't be too vauge.
IRS_ItemRegistration -> RegisterRestrictedItem
IRS_ClassRegistration -> RegisterRestrictedItemClass

Also,i think that those messages should be configurable.

Btw, call SaveStr (udg_IRS_Hashtable, itemRawCode, 3, class)
I never knew that WE allows that kind of syntax(spaces before parentheses)

Do you know what you are writing in the first code block? It seems you misunderstood the code. I will leave it to you to figure it out yourself later.

The function names are fine :v Why so picky and lengthy?

I consulted Mag twice before uploading this so don't worry, I am sure if he has nothing to say then it is alright.

edit

I wrote the wrong code. NOOO. Damn need to fix it now.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
Well, I never thought of using items with hashtables in that fashion as a item indexer system. Smart way to save items info.

Like SetUnitUserData, you can use SetItemUserData/GetItemUserData for items as well, it can set a custom integer value to an item.
 
Level 13
Joined
Jun 3, 2011
Messages
1,058
My system supports an unlimited number of item classes. Or am I misunderstanding sth?

@Maker: Thanks. I will include that in the update.

If your done with the update send me fast :D so i can start im using my laptop right now and my pc still dosn't have any net :goblin_cry: just send me a message :D:grin:
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Hi there,

What is the difference between:
String Setting
and
Examplary Declaration
??

Could you give an example how to make restriction for any class? Leave it as null string or space? Or wildcard maybe? "*"

"String Setting" is where you change your error messages as you wish. "Examplary Declaration" is, well, a simple how-to. And it is also the example you are looking for. Consult the documentation for the APIs if you need to.
 

Deleted member 219079

D

Deleted member 219079

when hero dies, the text goes to top of the screen when the system has shown a text message some time before. that's a shame, this is otherwise a perfect system.

asdf.jpg


Edit: Restriction by wearer's range would be awesome :)
 
Last edited by a moderator:
Level 16
Joined
Dec 15, 2011
Messages
1,423
when hero dies, the text goes to top of the screen when the system has shown a text message some time before. that's a shame, this is otherwise a perfect system.

asdf.jpg


Edit: Restriction by wearer's range would be awesome :)

Hello. Thank you very much for using the system (and your compliment too). About the bug, I am afraid it is a permanent glitch with the SimError library I am using for the error messages. I don't think there is any way to get around that, I may be wrong though :p

Wielder's range? Could you elaborate a bit? But I am kinda busy atm so when I have some free time I will look into it. Do your map really need that feature?
 

Deleted member 219079

D

Deleted member 219079

Attack range that is. My map doesn't need that feature, but it's just not realistic to have claws of attack boost Archmage's attack, since he uses fire to attack and attacks with distance.

I can stack hero types who I allow to use the item (right?), so I won't need range filter on top of that. I just thought it would be more practical to have range filter...

Also, I just implemented this to my map, works like a charm, 5/5 from me :)
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Attack range that is. My map doesn't need that feature, but it's just not realistic to have claws of attack boost Archmage's attack, since he uses fire to attack and attacks with distance.

I can stack hero types who I allow to use the item (right?), so I won't need range filter on top of that. I just thought it would be more practical to have range filter...

Also, I just implemented this to my map, works like a charm, 5/5 from me :)

Thank you.

Anyhow, I added the range filter function since it seems legitimate enough :)

edit

@Others: yeah I am still alive. And 4 months of non-coding really takes its toll :S
 

Deleted member 219079

D

Deleted member 219079

Nice range feature :)

It seems like the effect of item is still applied to wielder, even when it's removed the second it's acquired. This is probably caused because the event is EVENT_PLAYER_UNIT_PICKUP_ITEM, it first goes through wc3's code, which applies any buffs item gives, then reads custom triggers. The buff stays for couple of seconds, along with stats buff. Maybe just adding possible buff id item gives to hero onto hashtable, and removing it if there's anything ?
nimet%C3%B6n.jpg


Edit:
I added this:
JASS:
call UnitRemoveAbility(u,'BEar')
to beginning of the code after declaring locals to test it out, the effect of the flute didn't appear anymore.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Not worth it. It would require a lot of extra space to store all these information.
Also this effect might influence units in an aoe and not only the carrier.

In order to safely remove all buffs from all affected units the code would be incredible long with alot of condition checks.
 

Deleted member 219079

D

Deleted member 219079

Also this effect might influence units in an aoe and not only the carrier.
It doesn't do that at the same moment the item is acquired, at least on flute.

Edit:
irs.jpg
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
^What BPower said. I am bothered about that too but those extra miles are not worth going in the slightest. Coding is more or less about coping with not knowing what the users are going to throw at your system, that is why some mapmakers prefer to create simple systems running on a logic limited to a particular map of theirs where they can control everything.

It doesn't do that at the same moment the item is acquired, at least on flute.

The buff is removed immediately so I guess it cannot affect nearby units.
 

Deleted member 219079

D

Deleted member 219079

It hurts me as a perfectionist (sry, nothing I can do about it :/ ), but I guess as long as players playing my map I have this on won't complain about it, I won't get bothered too much about it.

Again the range feature was really nice add-on, I will update the version I used on my map to this one now :)
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
This system is not MUI ?

Because I placed it in my map, properly configured.. and as soon as another player picks up an item that is restricted for that player, I also get the error messages on my screen

That is indeed an important bug. I probably overlooked that when I first made the system (then there was still no way to test multiplayer without someone to help). Anyway, thank you for reporting. Oh and it is called MPI, not MUI.

The issue has been addressed in the new version. Please update the system ASAP.
 
Level 5
Joined
Feb 1, 2009
Messages
111
Update:

So I have updated to version 1.0.f however upon importing, I get the errors :

"Undeclared function IRS_RegisterRestrictedItem" as well as "Undeclared function IRS_ClassRegistration"

even though I imported the map-specific custom code at the start as well as replacing the old IRS trigger with the new one. Am I missing something?


Update 2:

Solved the problem of importing the update: It was totally weird but I had to basically cut and paste my item configuration trigger from 1.0e to 1.0f .. and then the map saved without giving errors. Isn't that weird?
 
Last edited:
Level 16
Joined
Dec 15, 2011
Messages
1,423
Update:

So I have updated to version 1.0.f however upon importing, I get the errors :

"Undeclared function IRS_RegisterRestrictedItem" as well as "Undeclared function IRS_ClassRegistration"

even though I imported the map-specific custom code at the start as well as replacing the old IRS trigger with the new one. Am I missing something?


Update 2:

Solved the problem of importing the update: It was totally weird but I had to basically cut and paste my item configuration trigger from 1.0e to 1.0f .. and then the map saved without giving errors. Isn't that weird?

Well that is really weird indeed. So, does everything work fine now? Is there still any issue?
 
Level 10
Joined
Aug 21, 2010
Messages
316
Range filter values are as follow:

"0" means the item can be used by both melee and ranged units.
"1" means the item is for ranged units only.
"2" means the item is for melee units only.

small suggestions[I think it would be easier to navigate]

set IRS_MeleeRanged = 0 -> means the item can be used by both melee and ranged units.
set IRS_Ranged = 1 -> means the item is for ranged units only.
set IRS_Melee = 2 -> means the item is for melee units only.

call IRS_ItemRegistration ('afac', "Weapon", "Mountain King", 10, 20, 10, 10, IRS_Melee)
 
Top