| 11-12-2009, 01:18 AM | #1 |
Hi all, Here is my latest rendition of itemMenu its included in a demo map. But it can work as a standalone script. ItemMenu is out to make it easy to use items as a menu system. It does so by giving you a bunch of event handlers and having really drop dead simple implementation. Included is a customizable Storage Menu, an Annoying Menu, and a Build menu. Check it out let me know what you think. There is more documentation in the readme, but the premise is you implement an OnOpen, an OnInterupt, and any event handler you'd like and it sets up the rest. ItemMenus can be registed to state that they provide storage, and you get granular control on how things will be placed. If none of the default settings meet your need you can always write your own. The system was coded in Zinc. To be fair and partisan to non-zinc users, I wrote the most "complicated" of the menus included (the build Menu) in Vjass to demo how easy it is to use. Credit:: Vexorian -- For Zinc/VJass and SimError. The map is using Table and Cohandlar's version of GetItemCostById. Neither are required for core operation. It also includes a library I created call Collections that implements list_$$ Obviously its less awesome in Zinc compared to its CJass equivalent, but CJass is toxic on this site. Code by request:: ItemMenu Library Zinc:library ItemMenu requires Collections,SimError { hashtable Table = InitHashtable(); constant integer BlankID = 'W001'; constant integer NextID = 'W000'; constant integer InvSize = 5; constant integer ActivatorID= 'WA01'; function GetItemSlot(unit u, item it)->integer { integer i; for(i = 0; i < 6; i+=1) { if(UnitItemInSlot(u,i) == it) return i; } return -1; } function ItemUseEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; item it=GetManipulatedItem(); integer slot; if(handler == 0) return; slot = GetItemSlot(h.Hero,it); if(it==h.NextItem) h.MenuNextPage(handler); else handler.OnItemUse(it,slot); t=null; it=null; } function TargetOrderEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; integer order=GetIssuedOrderId(); integer offset = (h.CurrentPage-1)*4; integer dragSlot; integer dropSlot; item dragItem; item dropItem; if(handler == 0) return; if(852001 < order && order < 852008 ) { dropSlot=order-852002; dropItem=UnitItemInSlot(h.Hero,dropSlot); dragItem=GetOrderTargetItem(); dragSlot=GetItemSlot(h.Hero,dragItem); if(order == 852007 || (handler.DoubleClickRemove && dragSlot == dropSlot)) { h.DropItem(dragItem,dragSlot); h.StoreItem(dragItem,(dragSlot == dropSlot),dropSlot); if(!handler.RemoveOnDrop) h.PageAfterDelay(0); } else if(handler.OnItemDrag(dragItem,dropItem,dragSlot,dropSlot)) { handler.Items[offset+dragSlot]=dropItem; handler.Items[offset+dropSlot]=dragItem; } } t=null; dragItem=null; dropItem=null; } function DropItemEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; integer offset; item it = GetManipulatedItem(); integer slot = GetItemSlot(h.Hero,it); if(handler == 0 || GetItemTypeId(it) == BlankID || slot == 5) return; h.DropItem(it,slot); t=null; it=null; } function NoTargetOrderEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; integer order=GetIssuedOrderId(); integer last; if(order != 852542 || handler == 0 || handler == h.ActivatorMenu) return; if(h.ItemMenus.Size == 2) { UnitRemoveAbility(h.Hero,ActivatorID); last = h.ItemMenus.IndexOf(handler); h.ChangeMenu(h.ItemMenus[1-last]); h.DelayExecution(function(Hero h){UnitAddAbility(h.Hero,ActivatorID);},0); } else { h.ChangeMenu(h.ActivatorMenu); } t=null; } function OrderItemEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; integer order=GetIssuedOrderId(); item it; integer slot; if(handler == 0) return; if(852007 < order && order < 852013 ) { slot=order-852008; it = UnitItemInSlot(h.Hero,slot); if(it == h.NextItem) return; handler.OnItemOrder(it,slot); } } function PickUpItemEvent() { trigger t=GetTriggeringTrigger(); Hero h = LoadInteger(Table,GetHandleId(t),0); ItemMenu handler= h.CurrentMenu; item it = GetManipulatedItem(); integer slot = GetItemSlot(h.Hero,it); integer offset = (h.CurrentPage-1)*4; if(handler == 0 || GetItemTypeId(it)== BlankID) return; h.StoreItem(it,false,slot); t = null; } type Action_Hero extends function(Hero); public struct Hero { private unit m_hero; private ActivatorMenu m_activatorMenu; private ItemMenu m_currentMenu; private List_ItemMenu m_ItemMenus; private item m_Blanks[5]; private item m_nextItem; private integer m_currentPage=0; private integer m_availableStorage = 0; method operator ItemMenus()-> List_ItemMenu { return m_ItemMenus; } method operator ActivatorMenu()-> ActivatorMenu { return m_activatorMenu; } method operator AvailableStorage()->integer { return m_availableStorage; } method operator AvailableStorage=(integer value) { m_availableStorage = value; } method operator Hero()->unit { return m_hero; } method operator CurrentMenu()->ItemMenu { return m_currentMenu; } method operator CurrentMenu=(ItemMenu value) { m_currentMenu = value; } method operator CurrentPage()->integer { return m_currentPage; } method operator NextItem()->item { return m_nextItem; } method operator CurrentPage=(integer value) { m_currentPage = value; } method RemoveBlanks() { integer i; item temp; integer end = 5; integer decrement; if(UnitItemInSlot(m_hero,4) == m_nextItem) end = 4; decrement = m_currentMenu.Items.Size - (m_currentPage * end); if(decrement< 0) end = end + decrement; for(i = 0; i < end; i+=1) { temp=UnitItemInSlot(m_hero,i); if(temp==m_Blanks[i]) { UnitRemoveItem(m_hero,temp); SetItemVisible(temp,false); } } temp=null; } //clear must be in escape state. method ClearInventory() { integer i; item temp; for(i = 0; i < InvSize; i+=1) { temp=UnitRemoveItemFromSlot(m_hero,i); SetItemVisible(temp,false); } temp=null; } // must be run in escape state. Inventory is blank. method NextPage(List_item iv)->integer { integer size= iv.Size; integer i = 0; item temp; integer start; integer end = 4; integer maxPage= (size/4); if(size < 6) end = 5; if(size-(maxPage*end)>0) maxPage=maxPage+1; if( m_currentPage >= maxPage ) m_currentPage=0; start=(m_currentPage)*4; for(m_currentPage+=1; i < end; i+=1) { temp=iv[start+i]; if(temp==null) temp=m_Blanks[i]; UnitAddItem(m_hero,temp); } if(end == 4) UnitAddItem(m_hero,m_nextItem); temp=null; return m_currentPage; } method DropItem(item it,integer slot) { integer offset =(m_currentPage-1)*4; if(m_currentMenu.OnItemDrop(it,slot,(GetWidgetLife(it)<.405))) { m_availableStorage += 1; m_currentMenu.StorageProvided+=1; if(m_currentMenu.RemoveOnDrop) { m_currentMenu.Items.RemoveAt(offset+slot); PageAfterDelay(0); } else m_currentMenu.Items[offset+slot] = null; if(GetItemTypeId(UnitItemInSlot(m_hero,5)) == BlankID && m_availableStorage == 1) { RemoveItem(UnitItemInSlot(m_hero,5)); } } } // returns whether it worked or not. method StoreItem(item it, boolean excludeCurrent,integer slot)->boolean { integer offset = (m_currentPage-1)*4; ItemMenu handler = m_currentMenu; ItemMenu old = 0; integer result = 0; integer i; integer end = 4; if(!excludeCurrent && handler.StorageProvided > 0) { result = handler.AddItem(it,slot); if(result == 1) { if(slot != 5) { handler.Items[offset+slot] = it; } else { m_currentMenu = 0; UnitRemoveItem(m_hero,it); SetItemVisible(it,false); m_currentMenu = handler; if(UnitItemInSlot(m_hero,4) == m_nextItem) end = 4; if(handler.RemoveOnDrop) m_currentMenu.Items.Add(it); else handler.Items[handler.Items.IndexOf(null)] = it; if(handler.RemoveOnDrop) PageAfterDelay(0); } } } if(result == 0) { for(i = 0; i < ItemMenus.Size; i+=1) { handler = ItemMenus[i]; if(handler!= m_currentMenu && handler.StorageProvided > 0 ) { result = ItemMenus[i].AddItem(it,slot); if(result > 0) { if(result > 1) break; old = m_currentMenu; m_currentMenu = 0; UnitRemoveItem(m_hero,it); SetItemVisible(it,false); m_currentMenu = old; if(handler.RemoveOnDrop) m_currentMenu.Items.Add(it); else handler.Items[handler.Items.IndexOf(null)] = it; break; } } } } if(result > 0) { m_availableStorage-=1; handler.StorageProvided-=1; } else { old = m_currentMenu; m_currentMenu = 0; UnitRemoveItem(m_hero,it); m_currentMenu = old; SimError(GetOwningPlayer(m_hero),"Item can't be stored"); } if(m_availableStorage == 0) UnitAddItemById(m_hero,BlankID); return (result > 0); } method MenuNextPage(ItemMenu handler) { m_currentMenu=0; ClearInventory(); NextPage(handler.Items); if(handler.ShowPage) SetItemCharges(m_nextItem,m_currentPage); m_currentMenu=handler; if(!handler.RemoveOnDrop) RemoveBlanks(); } method PageAfterDelay(real interval) { m_currentPage-=1; DelayExecution(function(Hero h){h.MenuNextPage(h.CurrentMenu);},interval); } method DelayExecution(Action_Hero f,real duration) { timer ti=CreateTimer(); SaveInteger(Table,GetHandleId(ti),0,this); SaveInteger(Table,GetHandleId(ti),1,f); TimerStart(ti,duration,false,function() { timer t=GetExpiredTimer(); Hero h =LoadInteger(Table,GetHandleId(t),0); Action_Hero f=LoadInteger(Table,GetHandleId(t),1); f.execute(h); FlushChildHashtable(Table,GetHandleId(t)); DestroyTimer(t); t=null; }); ti=null; } method ChangeMenu(ItemMenu handler) { ItemMenu current=m_currentMenu; m_currentMenu=0; current.OnInterupt(); ClearInventory(); handler.OnOpen(); m_currentPage=0; MenuNextPage(handler); } method RegisterMenu(ItemMenu menu) { m_ItemMenus.Add(menu); menu.Hero = this; m_availableStorage+=menu.StorageProvided; if(m_ItemMenus.Size == 2) UnitAddAbility(m_hero,ActivatorID); } static method create(unit u,ItemMenu defaultMenu)->thistype { thistype h=thistype.allocate(); trigger t; item n = null; integer i; h.m_ItemMenus = List_ItemMenu.create(0); h.m_activatorMenu = ActivatorMenu.create(); h.m_activatorMenu.Hero = h; h.m_hero = u; h.RegisterMenu(defaultMenu); for( i = 0; i < m_Blanks.size; i+=1) { n = CreateItem(BlankID,0,0); SetItemVisible(n,false); h.m_Blanks[i] = n; } h.m_nextItem=CreateItem(NextID,0,0); SetItemVisible(h.m_nextItem,false); h.ChangeMenu(defaultMenu); t=CreateTrigger(); TriggerRegisterUnitEvent(t,h.m_hero,EVENT_UNIT_USE_ITEM); TriggerAddAction(t,function ItemUseEvent); SaveInteger(Table,GetHandleId(t),0,h); t=CreateTrigger(); TriggerRegisterUnitEvent(t,h.m_hero,EVENT_UNIT_ISSUED_ORDER); TriggerAddAction(t,function NoTargetOrderEvent); SaveInteger(Table,GetHandleId(t),0,h); t=CreateTrigger(); TriggerRegisterUnitEvent(t,h.m_hero, EVENT_UNIT_DROP_ITEM ); TriggerAddAction(t,function DropItemEvent); SaveInteger(Table,GetHandleId(t),0,h); t=CreateTrigger(); TriggerRegisterUnitEvent(t,h.m_hero,EVENT_UNIT_ISSUED_TARGET_ORDER); TriggerAddAction(t,function TargetOrderEvent); SaveInteger(Table,GetHandleId(t),0,h); t= CreateTrigger(); TriggerRegisterUnitEvent( t,h.m_hero, EVENT_UNIT_PICKUP_ITEM); TriggerAddAction(t,function PickUpItemEvent); SaveInteger(Table,GetHandleId(t),0,h); t = CreateTrigger(); TriggerRegisterUnitEvent( t, h.m_hero, EVENT_UNIT_ISSUED_ORDER); TriggerRegisterUnitEvent( t, h.m_hero, EVENT_UNIT_ISSUED_TARGET_ORDER); TriggerRegisterUnitEvent( t, h.m_hero, EVENT_UNIT_ISSUED_POINT_ORDER); TriggerAddAction(t,function OrderItemEvent); SaveInteger(Table,GetHandleId(t),0,h); t = null; return h; } } public interface IMenu { Hero m_hero; //The owner of this itemMenu List_item m_items; //The itemvector that this itemMenu wraps and handles. boolean m_showPage; boolean m_removeOnDrop; boolean m_doubleClickRemove; integer m_storageProvided; item m_OpenItem; // Required Methods. //The following methods must be implmented method OnOpen(); method OnInterupt(); // Optional Methods // called when this Menu is registered/unregister to a Hero. method OnRegister() = null; method OnUnregister() = null; // returns if this menu was able to store the item. // This method return type is tested for the following:: // 0 means failure to store. // 1 means success and you'd like the default storage code behavior. // 2 means success and you had your own storage solution. method AddItem(item manipulatedItem,integer slot)->integer = 1; //What action to take when an Item is used? method OnItemUse(item manipulatedItem,integer slot) = null; // What action to take when an Item is Dragged? method OnItemDrag(item dragItem,item dropItem,integer dragSlot,integer dropSlot)->boolean = true; // What action to take when an Item is Dropped? method OnItemDrop(item manipulatedItem,integer slot,boolean wasRemoved)->boolean = true; // what action to take on issueing a use order on the item method OnItemOrder(item manipulatedItem,integer slot) = null; } public struct ItemMenu extends IMenu { method operator Items()->List_item { return m_items; } method operator Hero()->Hero { return m_hero; } method operator Hero=(Hero hero) { if(m_hero != null) OnUnregister(); m_hero=hero; if(hero == null) OnRegister(); } method operator ShowPage()->boolean { return m_showPage; } method operator RemoveOnDrop()->boolean { return m_removeOnDrop; } method operator StorageProvided()->integer { return m_storageProvided; } method operator DoubleClickRemove()->boolean { return m_doubleClickRemove; } method operator StorageProvided=(integer storageProvided) { m_storageProvided= storageProvided; } method operator OpenItem()->item { return m_OpenItem; } // this is the stub ancestor but I still got to put them here. method OnOpen() { } method OnInterupt() { } static method create()->thistype { thistype m=thistype.allocate(); return m; } } public struct ActivatorMenu extends ItemMenu { method OnOpen() { integer i; item temp; for(i = 0; i < Hero.ItemMenus.Size ; i+=1) { temp =Hero.ItemMenus[i].OpenItem; if(temp != null) { SetItemDroppable(temp,false); m_items.Add(temp); } } UnitRemoveAbility(Hero.Hero,ActivatorID); } method OnInterupt() { m_items.Clear(); UnitAddAbility(Hero.Hero,ActivatorID); } method OnItemUse(item manipulatedItem,integer slot) { ItemMenu target = GetItemUserData(manipulatedItem); Hero.ChangeMenu(target); } static method create()->thistype { thistype m = thistype.allocate(); integer i; m.m_removeOnDrop = true; m.m_items = m_items.create(0); return m; } } } Zinc:library Collections { //! textmacro ListTemplate takes T,typename,baseName,DefaultVal public struct List_$T$ { private integer m_Size; private integer m_Capacity; private static hashtable Table = InitHashtable(); method operator Size()->integer { return m_Size; } method operator Capacity()->integer { return m_Capacity; } method operator[](integer index)->$T$ { $T$ retVal = $DefaultVal$; if( - 1 < index && index < m_Size) { retVal = Load$typename$(Table,integer(this),index); } return retVal; } method operator[]=(integer index,$T$ value) { if( -1 < index && index < m_Size) { // Storing null doesn't actually do anything. It won't override values. So we have to remove things in that case. // Since staticif currently does not support reading parameters from macros this is all that can be done. if(value == $DefaultVal$) RemoveSaved$baseName$(Table,integer(this),index); else Save$typename$(Table,integer(this),index,value); } } method Add($T$ obj)->boolean { boolean retVal = false; if(m_Capacity == 0 || m_Size < m_Capacity) { m_Size+=1; this[m_Size-1]= obj; retVal = true; } return retVal; } method RemoveAt(integer index)->$T$ { $T$ retVal = $DefaultVal$; integer i; if(-1 < index && index < m_Size) { retVal = this[index]; for(i = index; i < m_Size-1; i+=1) { this[i] = this[i+1]; } m_Size-=1; RemoveSaved$baseName$(Table,integer(this),m_Size); } return retVal; } // Performs at O(1) time, but moves things about // in the process. method UnStableRemoveAt(integer index)-> $T$ { $T$ retVal = $DefaultVal$; if( - 1 < index && index < m_Size) { retVal = this[index]; this[index] = this[m_Size-1]; m_Size-=1; RemoveSaved$baseName$(Table,integer(this),m_Size); } return retVal; } method IndexOf($T$ value)->integer { integer i = 0; integer retVal = -1; for(i = 0; i < m_Size; i+=1) { if(this[i] == value) { retVal = i; break; } } return retVal; } method Contains($T$ value)->boolean { return IndexOf(value) > -1; } method Remove($T$ value)->boolean { integer index = IndexOf(value); if(index > -1) RemoveAt(index); return (index > -1); } method Clear() { FlushChildHashtable(Table,integer(this)); m_Size = 0; } private method onDestroy() { Clear(); } // This is a shallow clone static method Clone(thistype list)->thistype { thistype retVal = thistype.create(list.m_Capacity); integer i; for(i = 0; i < list.m_Size; i+=1) { retVal.Add(list[i]); } return retVal; } // Yes, I suppose I could've wrote List(T) but hey thistype sweet! // passing 0 creates a list without a fixed cap. static method create(integer capacity)->thistype { thistype retVal = thistype.allocate(); retVal.m_Capacity = capacity; return retVal; } } //! endtextmacro //! runtextmacro ListTemplate("item","ItemHandle","Handle","null") //! runtextmacro ListTemplate("ItemMenu","Integer","Integer","0") } Implementation guide text:: Zinc:This is the 3rd release of the ItemMenu engine. The goal of this system is to make it easier to use item panel as a menu system. It does so by giving abstracted event handlers so that you can create interfaces easily without having to worry about interop between your menu systems. The system is interupt based. Whenever a menu wants to take control of the gui, the current menu fires its OnInterupt method. Afterwards the new menu can fire its OnOpen code. OnOpen fires before the menu is displayed. Includes is the activator menu. The activator menu is built in to the framework and allows you to easily create a toggle dashboard between multiple menus without having to write your own. it functions with the following behavior:: 1 menu registered -- do nothing. 2 menus registered -- give the player the activator ability, which will be a toggle between the two. 3+ menus registered -- give the player the activator ability, which will open a menu of menus. All heroes are given an activator menu. Part of this release is an inventory management system. A menu may register to its hero that it provides storage, and in doing so will allow the hero to use it as fallover storage, if the current menu is out of storage or if currentMenus.AddItem() event returned 0, then it will fallover into the any menus that register storage on the hero. However, this comes at a cost. The 6th item slot cannot be used at all. All menus can only display 5 items at a time, or 4 once they need to resort to paging. There is no cancel button, the 6th slot is left empty to allow the logic to work. Dragging an item to the 6th slot will try to reAdd the item to the current heroes storage. Useful if you want to consolidate pages. Another big thing in this system is default behavior. The default behavior may not be your bag. It is completely overwritable. If you do not like the assumption the code makes, don't use'em! The following are setting variables:: Hero m_hero; //The owner of this itemMenu List_item m_items; //The itemvector that this itemMenu wraps and handles. boolean m_showPage; // would you like next page to show the pageNumber? boolean m_removeOnDrop; // used if you are using array storage vs list storage. boolean m_doubleClickRemove; // would you like double right click to behave like remove from current? integer m_storageProvided; // how many slots does this menu provide? item m_OpenItem; // what item should represent this in the activator menu? The Required Methods. //The following methods must be implemented // On open fires before the menu actually opens. method OnOpen(); // On interupt fires before the menu actually closes. method OnInterupt(); Optional Methods // called when this Menu is registered/unregister to a Hero. method OnRegister() = null; method OnUnregister() = null; // returns if this menu was able to store the item. // This method return type is tested for the following:: // 0 means failure to store. // 1 means success and you'd like the default storage code behavior. // 2 means success and you had your own storage solution. method AddItem(item manipulatedItem,integer slot)->integer = 1; //What action to take when an Item is used? method OnItemUse(item manipulatedItem,integer slot) = null; // What action to take when an Item is Dragged? // DOES NOT FIRE If the item is dragged onto itself and doubleClickRemove is set. method OnItemDrag(item dragItem,item dropItem,integer dragSlot,integer dropSlot)->boolean = true; // What action to take when an Item is Dropped? method OnItemDrop(item manipulatedItem,integer slot,boolean wasRemoved)->boolean = true; // what action to take on issueing a use order on the item method OnItemOrder(item manipulatedItem,integer slot) = null; A note that there are 3 event handlers that in theory could fire when a user uses an item: OnItemOrder -- before the item is used. OnItemUse -- right after the item is used. OnItemDrop -- after the item dies. Determine which of these meet your need. Default Behavior: Finally, you will notice that the event handlers have returns. Most of them are with how to deal with action modifying the inventory. The behavior is the following:: AddItem (Default success = 1, override = 2):: will find the first available slot if the inventory is array like (removeOnDrop = false), or add it to teh first slot if it is list like (removeOnDrop = true). It will also decrement the storage of the menu and the hero. OnItemDrag (Default = true) Will store the items in the slots that they end up in. If you marked DoubleClickRemove it will not fire when dropped on itself. OnItemDrop (Default = true) Will remove the item from the slot if it is list like. Or if it is array like it will set it to null. Sample menus: Included are some sample menus. The storage menu is pretty much out to just demonstrate how the default menu works. itemMenu makes an excellent bag system. The annoying menu is out to be annoying. Just a simple event handler demo. The buildMenu gives a build menu in the item panel. Template is not actually a menu, its just there so that you can find all of the interface elements easily, as ItemMenu is scary long. |
| 11-12-2009, 02:41 AM | #2 |
I tested just the test map (as in, I didn't change a single thing) and I think I bugged out the system. Initially, I had 12 free slots, and I picked up all the Reports on the ground. When I paged through the inventory, there was 4 on page one. But, 3 on page 2 with the pseduo-item "Next Page" in the 4th inventory slot and an empty item slot in the 5th slot (where normally the "Next Page" item is). Page 3 was fine, it had all the reports... This next bug is based on the previous. Keeping Page 2 open and picking up another item will place it in Page 2, Slot 5. Cycling through the pages and returning to it causes the item to vanish completely. In my experiment, I used a crown of kings and it was gone when I cycled back. EDIT: More elaboration. Picking up an item causes the 6th item slot to become open again BUT the item does not get added to the inventory. Attempting to pick up the item will add it to your inventory. Upon picking up said item, the 6th item slot becomes filled with a black pseudo-item. EDIT 2: Another bug. In the small inventory, I filled it with 4 items and swapped to another inventory. When I went back to the 4-slot inventory, I dropped one item. For some reason, the black square pseudo-item in the 6th slot gets removed. Upon picking up an item, it replaces the black square into slot 6. |
| 11-12-2009, 03:15 AM | #3 |
Thanks a lot for testing. I thought I ironed out most of the kinks. I did find a bit of a bug and fixed, I'm not sure about the next getting stuck on a wrong slot. I don't know how that happens. I'm trying to see if I can reproduce it. Obviously if the nextItem is part of the inventory that is a bad thing. I'm not sure how to catch that easily. As for the small inventory bug this is unfortunately correct behavior. When all inventory space is full it seals up the 6th slot with the blank item so that you cna't pick up more items. Once you drop something, a space is freed so you can pick something up. I'm uploading a fixed version of the map. Change: Fix issue where dropping an item on itself caused an incorrect count change in storage. Fix issue where orderItem gave the wrong item back. |
| 11-12-2009, 04:04 AM | #4 |
Please include the code in the first post. Also, it wouldn't hurt if you made your first post a bit easier on the eyes. |
| 11-12-2009, 06:57 AM | #5 | |
Quote:
Ah, gotcha. I'll post back (later today) with (hopefully) no bugs! I'm going to try really hard this time, though, to bug it out. =P |
| 11-12-2009, 09:02 AM | #6 |
I made the same system, but I never decided to upload. |
| 11-12-2009, 02:55 PM | #7 |
Err, your library has to actually require the SimError in the database, you can't submit your own ZINC version. Also, your "Collections" library is not an approved script, so you cannot use it in your submission per the submission rules. |
| 11-13-2009, 12:18 AM | #8 |
I couldn't find simerror when I looked so I just stole one from an old map written in Vjass and switched it over to zinc as it made it so when I was developing I could save everything as Zn file. As for collections its a simple arraylist class. I have no idea if there is an equivalent arraylist in the database. I suppose I could submit Collection and its list_$type$. |
| 11-13-2009, 01:04 AM | #9 | |
Found it on a ten second search. Quote:
|
| 11-13-2009, 11:41 PM | #10 |
There wasn't so I submitted it. I realize that it isn't approved but I don't think anyone has done one yet. |
| 11-14-2009, 01:57 AM | #11 |
Okay so, this is strange and I don't remembering it happen in my first test. I picked up enough items to fill all 6 slots in the AnnoyingMenu, which I believe acts as storage. (The debug messages did say I was storing the correct item into the AnnoyingMenu.) However, when I opened up the AnnoyingMenu, there were NO items there, just the black box things in all 6 slots. |
| 11-14-2009, 09:53 PM | #12 |
Yeah I was able to repeat it I'll try to figure out whats cause it. |
