System ItemGroup

Sevion

The DIY Ninja
Reaction score
413
Igs- ItemGroup
The First ItemGroup Variable Type
Current Version- v1.2

Requires-
(N/A)

Restrictions-
Max of 8190 items, but also a max of 1 itemgroup.
Default at 682 items with a max of 12 itemgroups.

News Count- 3

Overview
FAQ
What's the point of this?
There isn't an itemgroup variable type. So, I made one.

ItemGroup is very simple to use. The layout is as close to unit groups as I could get them.

To configure itemgroup, go into the ItemGroup library and look for:

JASS:
private constant integer ARRAY_SIZE = 682


682 items is the default maximum. I don't see a point in setting it very high, as it quickly diminishes your maximum amount of itemgroups, and as I see it, 682 is plenty items at a time. Add more if you need to. In fact, 819/682.5 = 12, thus giving you one itemgroup per player with a maximum of 682.5 items. Since it's an integer, we round down to 682. That's plenty.

To create an itemgroup, simply call CreateItemGroup()

JASS:
local itemgroup g = CreateItemGroup()


Now, add some items to it:

JASS:
call ItemGroupEnumItemsInRect(g, GetWorldBounds(), null)


That will add all items in the map to the itemgroup.

Next, do stuff with it:

JASS:
function do takes nothing returns nothing
    call RemoveItem(GetEnumItemGroupItem())
endfunction

function start takes nothing returns nothing
    local itemgroup g = CreateItemGroup()
    call ItemGroupEnumItemsInRect(g, GetWorldBounds(), null)
    call ForItemGroup(g, function do)
    call DestroyItemGroup(g)
endfunction


Let's look at some of the fuctions used in there:

JASS:
.
GetEnumItemGroupItem()
1. Returns the enum; essentially the same as GetEnumItem for Igs.

ForItemGroup(g, function do)
2. Executes function do for all items in the itemgroup; essentially the same as ForGroup for Igs.

DestroyItemGroup(g)
3. Destroys the itemgroup; all members of the struct are nulled in the onDestroy method; essentially the same as DestroyGroup for Igs.


There are many other Enum functions but all are the same as their respective unit group counterparts.

They should be simple enough to figure out.

And that's all there is to Igs.

-News Section-
News 1
The first release of ItemGroup. Sadly, it doesn't use linked lists. Perhaps I will make a linked lists version some time later on.
News 2
Fixed some bugs in the code and removed O(n) searching on removal.
News 3
Added CountItemsInItemGroup and IsItemInItemGroup

-System Section-

Igs Code Area
JASS:
/*System Information
===================================================================
Name: ItemGroup
Version: 1.2
Author: Sevion
Helpers: Flare

Description: ItemGroup Variable Type

Requirements: None

Usage:
------------------------------------------------------------------
local itemgroup g = CreateItemGroup()
call ItemGroupEnumItemsInRect(g, gg_rct_Region_000, null)
call ForItemGroup(g, function DoStuff)
call DestroyItemGroup(g)

Function List:
-CreateItemGroup()
-DestroyItemGroup()
-ItemGroupAddItem(itemgroup, item)
-ItemGroupRemoveItem(itemgroup, item)
-ItemGroupAddItemGroup(itemgroup, itemgroup)
-ItemGroupClear(itemgroup)
-ForItemGroup(itemgroup, code)
-CountItemsInItemGroup(itemgroup)
-IsItemInItemGroup(itemgroup)
-ItemGroupEnumItemsInRect(itemgroup, rect, boolexpr)
-ItemGroupEnumItemsInRectCount(itemgroup, rect, boolexpr, integer)
-ItemGroupEnumItemsInRange(itemgroup, real, real, real, boolexpr)
-ItemGroupEnumItemsInRangeCounted(itemgroup, real, real, real, boolexpr, integer)
-ItemGroupEnumItemsOfPlayer(itemgroup, player, boolexpr)
-ItemGroupEnumItemsOfType(itemgroup, integer, boolexpr)
-ItemGroupEnumItemsOfTypeCount(itemgroup, integer, boolexpr, integer)
-ItemGroupEnumItemsInRect(itemgroup, rect, boolexpr)
-ItemGroupEnumItemsInRect(itemgroup, rect, boolexpr)
-ItemGroupPickRandomItem(itemgroup)

Configuration:
-------------------------------------------------------------------
-Set ARRAY_SIZE to whatever you wish. The smaller it is, the fewer
-items you can have in an itemgroup. The larger, the fewer itemgroups
-you can have at one time.
===================================================================*/
library ItemGroup initializer Ini
    globals
        private constant integer ARRAY_SIZE = 682
    endglobals
    
    struct itemgroup
        item array items[ARRAY_SIZE]
        integer total = 0
        
        method onDestroy takes nothing returns nothing
            local integer i = .total
            loop
                exitwhen i == 0
                set .items<i> = null
                set i = i - 1
            endloop
            set .total = 0
        endmethod
    endstruct
    
    globals
        private real temp_x
        private real temp_y
        private rect temp_rect
        private real temp_radius
        private integer temp_count
        private integer temp_typeid
        private player temp_playerid
        private boolexpr temp_filter
        private itemgroup temp_itemgroup
        private integer temp_current_count
        private item enumitem
        private trigger t = CreateTrigger()
        private hashtable hasht = null
        private rect worldbounds
        public real trig = 0.
    endglobals
    
    function ItemGroupAddItem takes itemgroup g, item i returns nothing
        set g.total = g.total + 1
        set g.items[g.total] = i
        call SaveInteger (hasht, GetHandleId(i), g, g.total)
    endfunction
    
    function ItemGroupRemoveItem takes itemgroup g, item itm returns nothing
      local integer id = GetHandleId (itm)
      local integer id2 = GetHandleId (g.items[g.total])
      local integer index = LoadInteger (hasht, id, g)
      if HaveSavedInteger (hasht, id, g) then
        set g.items[index] = g.items[g.total]
        call RemoveSavedInteger (hasht, id, g)
        call RemoveSavedInteger (hasht, id2, g)
        call SaveInteger (hasht, id2, g, index)
        set g.total = g.total - 1
      endif
    endfunction
    
    private function EnumOfType takes nothing returns nothing
        if GetItemTypeId(GetEnumItem()) == temp_typeid then
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
        endif
    endfunction
    
    private function EnumOfTypeCount takes nothing returns nothing
        if GetItemTypeId(GetEnumItem()) == temp_typeid then
            if temp_current_count &gt; temp_count then
                return
            endif
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
        endif
    endfunction
    
    private function EnumOfPlayer takes nothing returns nothing
        if GetItemPlayer(GetEnumItem()) == temp_playerid then
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
        endif
    endfunction
    
    private function EnumInRect takes nothing returns nothing
        local real x = GetItemX(GetEnumItem())
        local real y = GetItemY(GetEnumItem())
        if x &gt;= GetRectMinX(temp_rect) and x &lt;= GetRectMaxX(temp_rect) and y &gt;= GetRectMinY(temp_rect) and y &lt;= GetRectMaxY(temp_rect) then
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
        endif
    endfunction
    
    private function EnumInRectCount takes nothing returns nothing
        local real x = GetItemX(GetEnumItem())
        local real y = GetItemY(GetEnumItem())
        if x &gt;= GetRectMinX(temp_rect) and x &lt;= GetRectMaxX(temp_rect) and y &gt;= GetRectMinY(temp_rect) and y &lt;= GetRectMaxY(temp_rect) then
            if temp_current_count &gt; temp_count then
                return
            endif
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
            set temp_current_count = temp_current_count + 1
        endif
    endfunction
    
    private function EnumInRange takes nothing returns nothing
        local real x = GetItemX(GetEnumItem()) - temp_x
        local real y = GetItemY(GetEnumItem()) - temp_y
        if SquareRoot(x*x+y*y) &lt;= temp_radius then
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
        endif
    endfunction
    
    private function EnumInRangeCount takes nothing returns nothing
        local real x = GetItemX(GetEnumItem()) - temp_x
        local real y = GetItemY(GetEnumItem()) - temp_y
        if SquareRoot(x*x+y*y) &lt;= temp_radius then
            if temp_current_count &gt; temp_count then
                return
            endif
            call ItemGroupAddItem(temp_itemgroup, GetEnumItem())
            set temp_current_count = temp_current_count + 1
        endif
    endfunction
    
    function ItemGroupEnumItemsInRange takes itemgroup g, real x, real y, real radius, boolexpr filter returns nothing
        set temp_x = x
        set temp_y = y
        set temp_radius = radius
        set temp_itemgroup = g
        call EnumItemsInRect(worldbounds, filter, function EnumInRange)
    endfunction
    
    function ItemGroupEnumItemsInRangeCounted takes itemgroup g, real x, real y, real radius, boolexpr filter, integer count returns nothing
        set temp_x = x
        set temp_y = y
        set temp_count = count
        set temp_radius = radius
        set temp_itemgroup = g
        set temp_current_count = 0
        call EnumItemsInRect(worldbounds, filter, function EnumInRangeCount)
    endfunction
    
    function ItemGroupEnumItemsInRect takes itemgroup g, rect r, boolexpr filter returns nothing
        set temp_rect = r
        set temp_itemgroup = g
        call EnumItemsInRect(worldbounds, filter, function EnumInRect)
    endfunction
    
    function ItemGroupEnumItemsInRectCounted takes itemgroup g, rect r, boolexpr filter, integer count returns nothing
        set temp_rect = r
        set temp_count = count
        set temp_itemgroup = g
        set temp_current_count = 0
        call EnumItemsInRect(worldbounds, filter, function EnumInRectCount)
    endfunction
    
    function ItemGroupEnumItemsOfPlayer takes itemgroup g, player playerid, boolexpr filter returns nothing
        set temp_playerid = playerid
        set temp_itemgroup = g
        call EnumItemsInRect(worldbounds, filter, function EnumOfPlayer)
    endfunction
    
    function ItemGroupEnumItemsOfType takes itemgroup g, integer typeid, boolexpr filter returns nothing
        set temp_typeid = typeid
        set temp_itemgroup = g
        call EnumItemsInRect(worldbounds, filter, function EnumOfType)
    endfunction
    
    function ItemGroupEnumItemsOfTypeCount takes itemgroup g, integer typeid, boolexpr filter, integer count returns nothing
        set temp_count = count
        set temp_typeid = typeid
        set temp_itemgroup = g
        set temp_current_count = 0
        call EnumItemsInRect(worldbounds, filter, function EnumOfType)
    endfunction
    
    function ItemGroupClear takes itemgroup g returns nothing
        local integer i = g.total
        loop
            exitwhen i == 0
            set g.items<i> = null
            set i = i - 1
        endloop
    endfunction
    
    function ItemGroupAddItemGroup takes itemgroup g1, itemgroup g2 returns nothing
        local integer i = g2.total
        loop
            exitwhen i ==0 or g1.total == 100
            call ItemGroupAddItem(g1, g2.items<i>)
            set i = i - 1
        endloop
    endfunction
    
    function GetEnumItemGroupItem takes nothing returns item
        return enumitem
    endfunction
    
    function CountItemsInItemGroup takes itemgroup g returns integer
        return g.total
    endfunction
    
    function IsItemInItemGroup takes itemgroup g, item it returns boolean
        local integer i = g.total
        loop
            exitwhen i == 0
            if g.items<i> == it then
                return true
            endif
            set i = i + 1
        endloop
        return false
    endfunction
    
    function ForItemGroup takes itemgroup g, code callback returns nothing
        local integer i = g.total
        loop
            exitwhen i == 0
            set enumitem = g.items<i>
            call TriggerAddAction(t, callback)
            set trig = 1.
            set trig = 0.
            call TriggerClearActions(t)
            set i = i - 1
        endloop
        set enumitem = null
    endfunction
    
    function ItemGroupPickRandomItem takes itemgroup g returns item
        return g.items[GetRandomInt(1, g.total)]
    endfunction
    
    function DestroyItemGroup takes itemgroup g returns nothing
        call g.destroy()
    endfunction
    
    function CreateItemGroup takes nothing returns itemgroup
        if hasht == null then
            set hasht = InitHashtable()
        endif
        return itemgroup.create()
    endfunction
    
    private function Ini takes nothing returns nothing
        call TriggerRegisterVariableEvent(t, &quot;ItemGroup_trig&quot;, GREATER_THAN, 0.)
        set worldbounds = GetWorldBounds()
    endfunction
endlibrary
</i></i></i></i></i>

[/spoiler]
 

Attachments

  • ItemGroup.w3x
    20.8 KB · Views: 246

quraji

zap
Reaction score
144
LOL, I just noticed this after submitting HandleGroup! Hilarious!!

Anyways, neat code..but does it do other handles? :p

I suppose you've got those enum functions over me >.<
 

Flare

Stops copies me!
Reaction score
662
Code:
    struct itemgroup
        item array items[ARRAY_SIZE]
        integer total = 0
        
        method onDestroy takes nothing returns nothing
            local integer i = [B]total[/B]
            loop
                exitwhen i == 0
                set items[i] = null
                set i = i - 1
            endloop
            set [B]total[/B] = 0
        [B]endfunction[/B]
    endstruct
1) Shouldn't those total's be .total? I can't see any globals outside the struct named total
2) Does endfunction work with a method declaration? I'm fairly sure that JASSHelper catches that as an error

EDIT: Ye, JASSHelper catches the endfunction here
JASS:
struct test
  method mymethod takes nothing returns nothing
  endfunction
endstruct

as an Unexpected 'endfunction'.

Also, for your RemoveItem, you could avoid the O(n) search, and store the item's appropriate array index in a hashtable or gamecache e.g.
JASS:
//When adding to a group, and once you&#039;ve incremented .total
call SaveInteger (myHashTable, GetHandleId (myItem), myItemGroup, total)

That way, when removing your item, you simply have to do
JASS:
function ItemGroupRemoveItem takes itemgroup g, item itm returns nothing
  local integer id = GetHandleId (itm)
  local integer id2 = GetHandleId (g.items[g.total])
  local integer index = LoadInteger (myHashTable, id, g)
  if HaveSavedInteger (myHashTable, id, g) then
    set g.items[index] = g.items[g.total]
    call RemoveSavedInteger (myHashTable, id, g)
    call RemoveSavedInteger (myHashTable, id2, g)
    call SaveInteger (myHashTable, id2, g, index)
    set g.total = g.total - 1
  endif
endfunction

which would remove the necessity for that RefreshItems function (since you should be just moving the item at the top of the array down to the newly available array slot, rather than pushing every single item above the free slot down

EDIT: Forgot to clear the array reference for the indexes that were cleared, and update the index for the item moving down the array :p
 

quraji

zap
Reaction score
144
Including what Flare said (although his solution for the O(n) search won't work :p), this also will cause an error:

JASS:

    struct itemgroup
        item array items[ARRAY_SIZE]
        integer total = 0
        
        method onDestroy takes nothing returns nothing
            local integer i = total
            loop
                exitwhen i == 0
                set items<i> = null  // should be .items<i>
                set i = i - 1
            endloop
            set total = 0
        endfunction
    endstruct
</i></i>


Sev, did you even try to compile this? :D
Now that I've stopped laughing about my posting a group system right after you...I notice that your code isn't as 'neat' as I first said. Come on Sev, you can do better!
 

Flare

Stops copies me!
Reaction score
662
Code:
    function ItemGroupPickRandomItem takes itemgroup g returns nothing
        call ItemGroupEnumItemsInRect(g, GetWorldBounds(), Filter(function Random))
        if g.total == 0 then
            call ItemGroupPickRandomItem(g)
        endif
    endfunction
Oh gawd... what in the world possessed you to do that? You could've enumerated the items then done
JASS:
return g.items[GetRandomInt (0, g.total)]

The way you've gone and done it, there's no guarantee an item will ever be returned.

Also, as regards how that function works, it really should return a unit from the given group, rather than giving you a random item anywhere on the map.

Finally...
1) If the group already has at least 1 item in it when you call ItemGroupPickRandomItem, there's a chance that no item will be picked (since the chances of getting a single specific number when returning a random number between 1 and 100 will be 1%) and if no item is returned, the recursion won't take place because g.total would already be greater than 0 (due to the fact that the taken group already had items in it)

2) GetWorldBounds leaks... either set it to a global and use the global throughout the code, or use bj_mapInitialPlayableArea
 

Larcenist

REP: Respect, Envy, Prosperity?
Reaction score
211
He didn't? It's a struct (which would've been quite obvious with a single glance at the code).
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
I looked at it. I just didn't know that you could do use this that way...
I usually only use the struct name with
local <structname> d = <structname>.create()
 

Romek

Super Moderator
Reaction score
964
Graveyarded.

And what's with the Nestharus style post? o_O
 

Sevion

The DIY Ninja
Reaction score
413
>Compiling

Yes, I did complile this. Though, the latest JassHelper (J) doesn't like me. It gives me I/O error 105 whenever I try to run it.

I have to use clijasshelper which doesn't show errors. I thought I fixed that total to .total o_o' I saw it and fixed it somewhere.

Bleh, my contacts are giving me trouble too. I can barely read the posts o_o'


Keep it mind, I wrote this system at 12 AM o_o'

I was tired ;p
 

Sevion

The DIY Ninja
Reaction score
413
No ;o Cleeezzz and Ren pulled me into a Last Stand game -_-' (We won cuz my haxxorz bounce ;o)

That caused me to burn about an hour and a half >_>

Edit: Whoops. My fail contacts made me miss Igor's post.

Yes, we can make Unit-Type groups. Just would be a struct [extending array/with an integer array member].

Yeh, using the latest clijasshelper is annoying. It's a real bugger finding stuff like:

JASS:
        call SaveInteger (hasht id2, g, index)


Notice the missing , between hasht and id2. That was getting me for about 15 minutes until I spotted it -_-'

(The only way I can test for errors is to test map and see if it loads o_o'
 

Sevion

The DIY Ninja
Reaction score
413
Read up on the stuff.

I'm fixing it right now :rolleyes:

Edit, when I fixed the bug in the Overview pointed out by Flare, I highlighted units and typed units. <-- Failure.

Edit, ;o Now that I think about it, Link Lists aren't all that complicated. And here I thought they were. o_o'
 

cleeezzz

The Undead Ranger.
Reaction score
268
its actually useful when i needed something like this half a year ago.

(i created items in a secret region and picked a random one)
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top