Handled dynamic adding and removing of inventory items and syncing with menu systems.

This commit is contained in:
sigonasr2 2023-10-17 05:35:19 -05:00
parent 6656e3d036
commit 04d6f42526
17 changed files with 254 additions and 50 deletions

View File

@ -0,0 +1,12 @@
#pragma once
#include "Crawler.h"
#include "DEFINES.h"
#include "Menu.h"
INCLUDE_game
typedef Attribute A;
void Menu::InitializeCharacterInfoWindow(){
Menu*characterInfoWindow=CreateMenu(INVENTORY,CENTERED,game->GetScreenSize()-vi2d{4,4});
}

View File

@ -105,6 +105,11 @@ bool Crawler::OnUserCreate(){
camera.EnableWorldBoundary(false);
ItemInfo::InitializeItems();
InitializeGraphics();
Menu::InitializeMenus();
Inventory::AddItem("Small Health Potion",16);
Inventory::AddItem("Large Health Potion",3);
Inventory::AddItem("Medium Mana Potion",1);
@ -121,20 +126,9 @@ bool Crawler::OnUserCreate(){
Inventory::AddItem("Dummy Item 11",8);
Inventory::AddItem("Dummy Item 12",3);
Inventory::AddItem("Dummy Item 13",6);
Inventory::AddItem("Dummy Item 14",192);
Inventory::AddItem("Dummy Item 15",35);
Inventory::AddItem("Dummy Item 16",6);
Inventory::AddItem("Dummy Item 17",3);
Inventory::AddItem("Dummy Item 18",1);
Inventory::AddItem("Dummy Item 19",8);
Inventory::AddItem("Dummy Item 20",4);
Inventory::AddItem("Bandages",10);
Inventory::AddItem("Blue Slime Remains",22);
InitializeGraphics();
Menu::InitializeMenus();
Monster::InitializeStrategies();
//Animations
sig::Animation::InitializeAnimations();

View File

@ -308,6 +308,7 @@
<ClCompile Include="Animation.cpp" />
<ClCompile Include="Arrow.cpp" />
<ClCompile Include="Bullet.cpp" />
<ClCompile Include="CharacterInfoWindow.cpp" />
<ClCompile Include="ChargedArrow.cpp" />
<ClCompile Include="Crawler.cpp" />
<ClCompile Include="DamageNumber.cpp" />
@ -378,6 +379,7 @@
</ItemGroup>
<ItemGroup>
<Image Include="assets\heart.ico" />
<Image Include="assets\menus\Character_Info.png" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Crawler.rc" />

View File

@ -55,6 +55,9 @@
<Filter Include="Configurations\Items">
<UniqueIdentifier>{09fc0cbe-06f7-4fdf-944c-9833066bb9c8}</UniqueIdentifier>
</Filter>
<Filter Include="Documentation\Menus">
<UniqueIdentifier>{bea40439-f3a2-42f8-be1a-c0a815007075}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="olcPixelGameEngine.h">
@ -326,6 +329,9 @@
<ClCompile Include="InventoryWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="CharacterInfoWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
@ -397,6 +403,9 @@
<Image Include="assets\heart.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="assets\menus\Character_Info.png">
<Filter>Documentation\Menus</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Crawler.rc">

View File

@ -1,6 +1,5 @@
#pragma once
#include "Crawler.h"
#include "DEFINES.h"
#include "olcPixelGameEngine.h"
#include "safemap.h"
#include "Item.h"
@ -8,39 +7,27 @@
#include "MenuLabel.h"
#include "ScrollableWindowComponent.h"
INCLUDE_GFX
typedef Attribute A;
void Menu::InitializeInventoryWindow(){
constexpr int invWidth=5;
constexpr int initialInvHeight=3;
int invWidth="ThemeGlobal.InventoryWidth"_I;
int initialInvHeight="ThemeGlobal.InventoryHeight"_I;
constexpr int itemSpacing=8;
constexpr int buttonSize=24;
constexpr int totalSpacing=buttonSize+itemSpacing;
int itemSpacing="ThemeGlobal.InventoryItemSpacing"_I;
int buttonSize="ThemeGlobal.InventoryButtonSize"_I;
int totalSpacing=buttonSize+itemSpacing;
vf2d windowSize={totalSpacing*invWidth-itemSpacing+2+24,totalSpacing*(3+1)-itemSpacing+24}; //Need space for the button.
vf2d windowSize={float(totalSpacing*invWidth-itemSpacing+2+24),float(totalSpacing*(3+1)-itemSpacing+24)}; //Need space for the button.
Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize);
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,totalSpacing*3-itemSpacing}},nullptr,[](MenuFuncData data){});
ScrollableWindowComponent*inventory=new ScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,float(totalSpacing*3-itemSpacing)}},nullptr,[](MenuFuncData data){});
inventoryWindow->AddComponent("inventory",inventory);
MenuFunc useItemFunc=[](MenuFuncData data){
MenuItemButton*button=(MenuItemButton*)data.component;
button->UseItem();
};
//We don't have to actually populate the inventory list because now when an item gets added, it will automatically add the correct component in for us.
for(int i=0;i<Inventory::get("Consumables").size();i++){
int x=i%invWidth;
int y=i/invWidth;
int itemIndex=y*invWidth+x;
MenuItemButton*button=new MenuItemButton{INVENTORY,{{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get("Consumables"),itemIndex,useItemFunc};
inventory->AddComponent(inventoryWindow,"item"+std::to_string(itemIndex),button);
}
MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,initialInvHeight*totalSpacing-4},windowSize),"",false,true};
MenuLabel*itemNameLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing-4)},windowSize),"",false,true};
inventoryWindow->AddComponent("itemName",itemNameLabel);
MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,initialInvHeight*totalSpacing+itemSpacing},{windowSize.x-4,windowSize.y-108}),"",true,true};
MenuLabel*itemDescriptionLabel=new MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing)},{windowSize.x-4,windowSize.y-108}),"",true,true};
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
}

View File

@ -3,6 +3,7 @@
#include "safemap.h"
#include "DEFINES.h"
#include "Crawler.h"
#include "Menu.h"
INCLUDE_game
INCLUDE_DATA
@ -159,6 +160,9 @@ void Inventory::RemoveItem(IT it,uint32_t amt){
}
sortedList.erase(sortedList.begin()+count);
_inventory.erase(it);
ITCategory cat=ITEM_DATA[it].category;
//Callback for GUI inventories.
Menu::InventorySlotsUpdated(cat);
}else{
_inventory.at(it).amt-=amt;
}
@ -170,6 +174,8 @@ std::vector<IT>&Inventory::get(ITCategory itemCategory){
void Inventory::InsertIntoSortedInv(IT item){
sortedInv.at(ITEM_DATA[item].category).push_back(item);
//This should be a callback to menus that we need to update the interface with another item slot since a new one has appeared.
Menu::InventorySlotsUpdated(ITEM_DATA[item].category);
}
bool Inventory::ExecuteAction(IT item){

View File

@ -2,6 +2,9 @@
#include "MenuComponent.h"
#include "DEFINES.h"
#include "safemap.h"
#include "Item.h"
#include "MenuItemButton.h"
#include "ScrollableWindowComponent.h"
bool Menu::MOUSE_NAVIGATION=true;
std::vector<Menu*>Menu::stack;
@ -32,11 +35,13 @@ void Menu::InitializeMenus(){
std::cout<<"WARNING! Menu Type "<<type<<" does not exist!"<<std::endl;
throw;
}
//Lock up everything once it's done.
menus[type]->buttons.SetInitialized();
menus[type]->keyboardButtons.SetInitialized();
for(auto&key:menus[type]->components){
MenuComponent*component=key.second;
component->AfterCreate();
}
menus[type]->components.SetInitialized(); //Lock all known components to prevent invalid access.
}
}
@ -47,9 +52,33 @@ Menu*Menu::CreateMenu(MenuType type,vf2d pos,vf2d size){
void Menu::AddComponent(std::string key,MenuComponent*button){
if(button->selectable){
buttons[button->rect.pos.y].push_back(button);
buttons.Unlock();
if(buttons.count(button->rect.pos.y)){
buttons.at(button->rect.pos.y).push_back(button);
}else{
buttons[button->rect.pos.y].push_back(button);
}
if(button->selectableViaKeyboard){
keyboardButtons[button->rect.pos.y].push_back(button);
keyboardButtons.Unlock();
if(keyboardButtons.count(button->rect.pos.y)){
keyboardButtons.at(button->rect.pos.y).push_back(button);
}else{
keyboardButtons[button->rect.pos.y].push_back(button);
}
}
//We must lock the values before calling sort. Sort seems to try and create new accesses.
buttons.SetInitialized();
keyboardButtons.SetInitialized();
//We make an assumption that menu components are supposed to be in left-to-right order. Sometimes we may add things out-of-order, so this fixes the problem by sorting the items afterwards.
std::sort(buttons[button->rect.pos.y].begin(),buttons[button->rect.pos.y].end(),[](MenuComponent*c1,MenuComponent*c2){
return c1->GetPos().x<c2->GetPos().x;
});
if(keyboardButtons.count(button->rect.pos.y)){ //Keyboard buttons may not necessarily contain this key...Let's be sure.
std::sort(keyboardButtons[button->rect.pos.y].begin(),keyboardButtons[button->rect.pos.y].end(),[](MenuComponent*c1,MenuComponent*c2){
return c1->GetPos().x<c2->GetPos().x;
});
}
}else{
displayComponents.push_back(button);
@ -59,7 +88,9 @@ void Menu::AddComponent(std::string key,MenuComponent*button){
throw;
}
button->name=key;
components.Unlock(); //It's possible we can add a component later on, so we will make sure we remove the lock first.
components[key]=button;
components.SetInitialized();
}
void Menu::CheckClickAndPerformMenuSelect(Crawler*game){
@ -84,7 +115,6 @@ void Menu::HoverMenuSelect(Crawler*game){
void Menu::MenuSelect(Crawler*game){
if(selection==vi2d{-1,-1}||buttons[selection.y][selection.x]->disabled)return;
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
if(buttons[selection.y][selection.x]->menuDest!=MenuType::ENUM_END){
if(stack.size()<32){
stack.push_back(menus[buttons[selection.y][selection.x]->menuDest]);//Navigate to the next menu.
@ -93,6 +123,7 @@ void Menu::MenuSelect(Crawler*game){
throw;
}
}
buttons[selection.y][selection.x]->onClick(MenuFuncData{*this,game,buttons[selection.y][selection.x]});
}
void Menu::Update(Crawler*game){
@ -315,9 +346,9 @@ void Menu::KeyboardButtonNavigation(Crawler*game,vf2d menuPos){
selectedItem=true;
break;
}
if(key.first==selection.y&&
if(key.first==selection.y
//It's entirely possible this button was selected from the button selection list and may be out-of-bounds here.
selection.x>=0&&selection.x<keyboardButtons[selection.y].size()){
&&selection.x>=0&&selection.x<keyboardButtons[selection.y].size()){
found=true;
}
}
@ -528,4 +559,54 @@ void Menu::SetMouseNavigation(bool mouseNavigation){
lastActiveMousePos=game->GetMousePos();
}
MOUSE_NAVIGATION=mouseNavigation;
};
};
void Menu::InventorySlotsUpdated(ITCategory cat){
//Update the inventory with a new inventory slot, since there's one additional item to interact with now.
std::vector<std::string>&inv=Inventory::get(cat);
MenuType inventoryWindow;
if(cat=="Consumables"){
inventoryWindow=INVENTORY;
}else
if(cat=="Equipment"){
//TODO: Update different inventories depending on what the item's category is.
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
return; //Currenly a no-op
}else
if(cat=="Accesories"){
//TODO: Update different inventories depending on what the item's category is.
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
return; //Currenly a no-op
}else
if(cat=="Materials"){
//TODO: Update different inventories depending on what the item's category is.
std::cout<<"WARNING! Unimplemented inventory slot addition for category "<<cat<<"!"<<std::endl;
return; //Currenly a no-op
}else{
throw;
std::cout<<"WARNING! Attempting to add an inventory to a category that does not exist. THIS SHOULD NOT BE HAPPENING!"<<std::endl;
}
//HACK ALERT!! We make a very bold assumption here that every inventory window will contain a ScrollableWindowComponent called "inventory"! Because it's a safemap, if it doesn't exist it will let us know as such, we won't include any extra checks here.
ScrollableWindowComponent*inventory=((ScrollableWindowComponent*)menus[inventoryWindow]->components["inventory"]);
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
if(inventory->ComponentCount()<inv.size()){//We need more space to display our items.
int invWidth="ThemeGlobal.InventoryWidth"_I;
int x=(inv.size()-1)%invWidth;
int y=(inv.size()-1)/invWidth;
int itemIndex=y*invWidth+x;
int buttonSize="ThemeGlobal.InventoryButtonSize"_I;
int totalSpacing="ThemeGlobal.InventoryItemSpacing"_I+buttonSize;
MenuFunc useItemFunc=[](MenuFuncData data){
MenuItemButton*button=(MenuItemButton*)data.component;
button->UseItem();
};
MenuItemButton*button=new MenuItemButton{inventoryWindow,{{float(totalSpacing*x),float(totalSpacing*y)},{float(buttonSize),float(buttonSize)}},Inventory::get("Consumables"),itemIndex,useItemFunc};
inventory->AddComponent(menus[inventoryWindow],"item"+std::to_string(itemIndex),button);
}else
if(inventory->ComponentCount()>inv.size()){ //There are empty spots, so let's clean up.
inventory->RemoveEmptySlots();
}
}

View File

@ -1,11 +1,10 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "Item.h"
#include <stack>
#include "safemap.h"
#include "Theme.h"
#include "Attributable.h"
#include "olcUTIL_Geometry2D.h"
#include <functional>
class Crawler;
class MenuComponent;
@ -25,8 +24,6 @@ class Menu:IAttributable{
friend class Player;
float buttonHoldTime=0;
std::map<int/*Y*/,std::vector<MenuComponent*>>buttons; //Buttons are stored in rows followed by their column order.
std::map<int/*Y*/,std::vector<MenuComponent*>>keyboardButtons; //Button ordered storage for keyboard/menu
std::vector<MenuComponent*>displayComponents; //Components that are only for displaying purposes.
vi2d selection={-1,-1};
vi2d lastActiveMousePos={};
@ -50,11 +47,13 @@ public:
static std::map<MenuType,Menu*>menus;
vf2d pos; //Specify the upper-left corner of the window. Using CENTERED will always put this where the upper-left corner would center the window.
vf2d size; //Size in tiles (24x24), every menu will be tile-based
safemap<int/*Y*/,std::vector<MenuComponent*>>buttons; //Buttons are stored in rows followed by their column order.
safemap<int/*Y*/,std::vector<MenuComponent*>>keyboardButtons; //Button ordered storage for keyboard/menu
static Theme&GetCurrentTheme();
bool UsingMouseNavigation();
void SetMouseNavigation(bool mouseNavigation);
static void InventorySlotsUpdated(ITCategory cat); //Called whenever an inventory item gets added to the player's inventory, thus increasing the total number of slots in our bag.
private:
Menu(vf2d pos,vf2d size);
void HoverMenuSelect(Crawler*game);
@ -65,6 +64,7 @@ private:
static void InitializeTestMenu();
static void InitializeTestSubMenu();
static void InitializeInventoryWindow();
static void InitializeCharacterInfoWindow();
//X (0-3), Y (0-2) for specific 9-patch tile (tiled version).
static Renderable&GetPatchPart(int x,int y);

View File

@ -1,6 +1,8 @@
#include "Crawler.h"
#include "MenuComponent.h"
typedef Attribute A;
MenuComponent::MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,bool selectable,bool selectableViaKeyboard)
:parentMenu(parent),rect(rect),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(selectable),selectableViaKeyboard(selectableViaKeyboard){}
@ -78,4 +80,8 @@ bool MenuComponent::PointWithinParent(MenuComponent*child,vi2d drawPos){
bool MenuComponent::HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton){
return false;
};
};
vf2d MenuComponent::GetPos(){
return rect.pos;
}

View File

@ -25,6 +25,7 @@ protected:
bool selectableViaKeyboard=true;
bool disabled=false; //If set to true, this component will not be rendered or updated.
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
bool valid=true; //If set to false, this would cause the component to be removed.
virtual void Update(Crawler*game);
virtual void Draw(Crawler*game,vf2d parentPos,bool focused);
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
@ -36,6 +37,7 @@ public:
void _Update(Crawler*game);
void _Draw(Crawler*game,vf2d parentPos,bool focused);
void _DrawDecal(Crawler*game,vf2d parentPos,bool focused);
vf2d GetPos();
//We picked up a draggable component, we should make a copy and return it here. If a nullptr is returned here, the pickup is not allowed.
//WARNING!!! This allocates a brand new component when successful!!! Be prepared to clear it!
virtual MenuComponent*PickUpDraggableItem();

View File

@ -13,7 +13,6 @@ class MenuItemButton:public MenuIconButton{
private:
std::vector<IT>&invRef;
int inventoryIndex=0;
bool valid=false;
public:
inline MenuItemButton(MenuType parent,geom2d::rect<float>rect,std::vector<IT>&invRef,int invIndex,MenuFunc onClick)
:MenuIconButton(parent,rect,invRef.size()>invIndex?ITEM_DATA.at(invRef[invIndex]).Decal():nullptr,onClick),invRef(invRef),inventoryIndex(invIndex){

View File

@ -127,6 +127,31 @@ protected:
virtual bool GetHoverState(Crawler*game,MenuComponent*child)override{
return geom2d::overlaps(geom2d::rect<float>{Menu::menus[parentMenu]->pos+rect.pos+child->rect.pos+V(A::SCROLL_OFFSET),child->rect.size},game->GetMousePos());
}
//Calculates the bounds of all components.
geom2d::rect<float> inline CalculateBounds(){
geom2d::rect<float>bounds;
for(MenuComponent*component:components){
if(component->rect.pos.x<bounds.pos.x){
float sizeIncrease=bounds.pos.x-component->rect.pos.x;
bounds.size.x+=sizeIncrease;
bounds.pos.x=component->rect.pos.x;
}
if(component->rect.right().start.x>bounds.right().start.x){
float sizeIncrease=component->rect.right().start.x-bounds.right().start.x;
bounds.size.x+=sizeIncrease;
}
if(component->rect.pos.y<bounds.pos.y){
float sizeIncrease=bounds.pos.y-component->rect.pos.y;
bounds.size.y+=sizeIncrease;
bounds.pos.y=component->rect.pos.y;
}
if(component->rect.bottom().start.y>bounds.bottom().start.y){
float sizeIncrease=component->rect.bottom().start.y-bounds.bottom().start.y;
bounds.size.y+=sizeIncrease;
}
}
return bounds;
}
public:
void inline AddComponent(Menu*parentMenu,std::string key,MenuComponent*button){
components.push_back(button);
@ -163,4 +188,53 @@ public:
V(A::SCROLL_OFFSET).y+=rect.size.y/2;
return true;
};
virtual inline size_t ComponentCount(){
return components.size();
}
virtual void RemoveButton(MenuComponent*button){
std::vector<MenuComponent*>&buttonList=Menu::menus[button->parentMenu]->buttons.at(button->GetPos().y);
std::vector<MenuComponent*>&keyboardButtonList=Menu::menus[button->parentMenu]->keyboardButtons.at(button->GetPos().y);
size_t removedCount=0;
removedCount+=std::erase(buttonList,button);
removedCount+=std::erase(keyboardButtonList,button);
if(removedCount!=2){
std::cout<<"WARNING! Attempted to remove buttons from button listing, but not found!";
throw;
}
if(buttonList.size()==0){
if(!Menu::menus[button->parentMenu]->buttons.erase(button->GetPos().y)){
std::cout<<"WARNING! Attempted to erase key "<<button->GetPos().y<<" from button map, but the list still exists!";
throw;
}
}
if(keyboardButtonList.size()==0){
if(!Menu::menus[button->parentMenu]->keyboardButtons.erase(button->GetPos().y)){
std::cout<<"WARNING! Attempted to erase key "<<button->GetPos().y<<" from button map, but the list still exists!";
throw;
}
}
}
virtual void RemoveEmptySlots(){
//Algorithm will iterate through all slots, finding blank slots. Each time a blank slot is found, all items will shift over by one, and then the last item will be removed. Repeat until all slots iterated through.
for(int i=0;i<components.size();i++){
MenuComponent*button=components[i];
button->Update(game); //We have to call update to update the validation state.
//HACK ALERT!! This only gets called on inventories...And only on inventory items, which would have the valid flag set. We only care about components that are inventory slots.
if(!button->valid){
for(int j=i;j<components.size()-1;j++){
//Take the item in the next slot and move it to this slot.
Menu::menus[components[j]->parentMenu]->components.at(components[j]->name)=components[j+1];
components[j]=components[j+1];
}
MenuComponent*lastButton=Menu::menus[components[components.size()-1]->parentMenu]->components.at(components[components.size()-1]->name);
//Now we have to fix up the keyboard button list.
RemoveButton(lastButton);
Menu::menus[components[components.size()-1]->parentMenu]->components.erase(components[components.size()-1]->name);
//Now delete the last slot.
components.erase(components.end()-1);
i--; //Subtract one from the index so we don't accidently skip slots.
}
}
bounds=CalculateBounds(); //Recalculate the bounds as it's possible the width/height of the component has changed.
}
};

View File

@ -2,6 +2,7 @@
#include "Crawler.h"
#include "DEFINES.h"
#include "Menu.h"
#include "Item.h"
INCLUDE_MONSTER_LIST
@ -13,6 +14,21 @@ void State_GameRun::OnUserUpdate(Crawler*game){
if(game->encounterStarted&&game->totalBossEncounterMobs>0){
game->encounterDuration+=game->GetElapsedTime();
}
if(game->GetKey(O).bPressed){
Inventory::AddItem("Dummy Item 14",192);
Inventory::AddItem("Dummy Item 15",35);
Inventory::AddItem("Dummy Item 16",6);
Inventory::AddItem("Dummy Item 17",3);
Inventory::AddItem("Dummy Item 18",1);
Inventory::AddItem("Dummy Item 19",8);
Inventory::AddItem("Dummy Item 20",4);
}
if(game->GetKey(P).bPressed){
Inventory::AddItem("Medium Mana Potion",1);
}
game->HandleUserInput(game->GetElapsedTime());
if(game->GetKey(T).bPressed){

View File

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 2127
#define VERSION_BUILD 2167
#define stringify(a) stringify_(a)
#define stringify_(a) #a

View File

@ -13,6 +13,15 @@ ThemeGlobal
# How far the mouse has to move before mouse mode becomes active from keyboard/controller input mode.
MouseActivationDistance = 8
# How many slots wide the inventory list is.
InventoryWidth = 5
# How tall the view is for the inventory window (before scrolling)
InventoryHeight = 3
# Space between each item slot.
InventoryItemSpacing = 8
# Size of each button.
InventoryButtonSize = 24
}
Themes

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -6,7 +6,7 @@ class safemap{
std::map<T,O>map;
bool initialized=false;
public:
O&operator[](T key){
O&operator[](T key){
if(initialized&&map.count(key)==0){
std::cout<<"WARNING! Trying to get non-existent key "<<key<<"!"<<std::endl;
throw;
@ -35,6 +35,10 @@ public:
size_t size(){
return map.size();
}
//Unlocks the map so items can be added to it again. USE WITH CAUTION! And make sure to lock the map again.
void Unlock(){
initialized=false;
}
//Clears the entire map and unlocks the map so items can be added to it again.
void Reset(){
initialized=false;
@ -46,6 +50,9 @@ public:
auto end()const{
return map.end();
}
size_t erase(const T&key){
return map.erase(key);
}
};
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.