Implemented Loadout selection item buttons, corrected inventory window missing category variables, corrected loadout item selection logic, updated inventory window layout.

pull/28/head
sigonasr2 1 year ago
parent 0c9a341e89
commit f427928ca6
  1. 30
      Crawler/Crawler.cpp
  2. 6
      Crawler/Crawler.h
  3. 4
      Crawler/Crawler.vcxproj
  4. 8
      Crawler/Crawler.vcxproj.filters
  5. 20
      Crawler/InventoryConsumableWindow.cpp
  6. 25
      Crawler/InventoryScrollableWindowComponent.h
  7. 7
      Crawler/Item.h
  8. 73
      Crawler/ItemLoadoutWindow.cpp
  9. 3
      Crawler/Menu.cpp
  10. 4
      Crawler/Menu.h
  11. 5
      Crawler/MenuComponent.h
  12. 2
      Crawler/MenuIconButton.h
  13. 49
      Crawler/MenuItemButton.h
  14. 99
      Crawler/MenuItemItemButton.h
  15. 2
      Crawler/OverworldMapLevelWindow.cpp
  16. 29
      Crawler/Player.cpp
  17. 6
      Crawler/Player.h
  18. 2
      Crawler/Version.h
  19. BIN
      x64/Release/Crawler.exe

@ -1932,3 +1932,33 @@ int Crawler::GetCurrentChapter(){
void Crawler::SetChapter(int chapter){
this->chapter=chapter;
}
Item&Crawler::GetLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
return loadout[slot];
}
void Crawler::SetLoadoutItem(int slot,std::string itemName){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
if(Inventory::GetItemCount(itemName)>0){
GetLoadoutItem(slot)=Inventory::GetItem(itemName);
GetLoadoutItem(slot).amt=std::min((uint32_t)"Player.Item Loadout Limit"_I,GetLoadoutItem(slot).Amt()); //We are only allowed to have up to 10 maximum of an item on a journey.
}else{
ERR("Trying to set item "+itemName+" in Loadout slot "+std::to_string(slot)+" when said item does not exist in our inventory!");
}
}
void Crawler::UseLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
if(GetLoadoutItem(slot).Amt()>0){
Inventory::UseItem(loadout[slot].Name());
GetLoadoutItem(slot).OnUseAction();
GetLoadoutItem(slot).amt--;
}
}
void Crawler::ClearLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
loadout[slot].amt=0;
loadout[slot].it=nullptr;
}

@ -90,6 +90,7 @@ private:
bool encounterStarted=false;
int totalBossEncounterMobs=0;
int chapter=1; //We start at chapter 1.
std::array<Item,3>loadout;
std::vector<Monster>monstersToBeSpawned;
@ -169,6 +170,11 @@ public:
MapTag GetCurrentMap();
int GetCurrentChapter();
void SetChapter(int chapter);
Item&GetLoadoutItem(int slot);
void SetLoadoutItem(int slot,std::string itemName);
void UseLoadoutItem(int slot);
//Blanks out this loadout item.
void ClearLoadoutItem(int slot);
struct TileGroupData{
vi2d tilePos;

@ -284,6 +284,7 @@
<ClInclude Include="MenuComponent.h" />
<ClInclude Include="MenuIconButton.h" />
<ClInclude Include="MenuItemButton.h" />
<ClInclude Include="MenuItemItemButton.h" />
<ClInclude Include="MenuLabel.h" />
<ClInclude Include="Key.h" />
<ClInclude Include="Map.h" />
@ -336,8 +337,9 @@
<ClCompile Include="FallingDebris.h" />
<ClCompile Include="FireBolt.cpp" />
<ClCompile Include="GameState.cpp" />
<ClCompile Include="InventoryWindow.cpp" />
<ClCompile Include="InventoryConsumableWindow.cpp" />
<ClCompile Include="Item.cpp" />
<ClCompile Include="ItemLoadoutWindow.cpp" />
<ClCompile Include="Key.cpp" />
<ClCompile Include="LightningBolt.cpp" />
<ClCompile Include="LightningBoltEmitter.cpp" />

@ -246,6 +246,9 @@
<ClInclude Include="Ability.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MenuItemItemButton.h">
<Filter>Header Files\Interface</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Player.cpp">
@ -377,7 +380,7 @@
<ClCompile Include="Item.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="InventoryWindow.cpp">
<ClCompile Include="InventoryConsumableWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="CharacterInfoWindow.cpp">
@ -410,6 +413,9 @@
<ClCompile Include="drawutil.cpp">
<Filter>Source Files\Utils</Filter>
</ClCompile>
<ClCompile Include="ItemLoadoutWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

@ -40,7 +40,7 @@ SUCH DAMAGE.
typedef Attribute A;
void Menu::InitializeInventoryWindow(){
void Menu::InitializeConsumableInventoryWindow(){
int invWidth="ThemeGlobal.InventoryWidth"_I;
int initialInvHeight="ThemeGlobal.InventoryHeight"_I;
@ -48,23 +48,27 @@ void Menu::InitializeInventoryWindow(){
int buttonSize="ThemeGlobal.InventoryButtonSize"_I;
int totalSpacing=buttonSize+itemSpacing;
vf2d windowSize={float(totalSpacing*invWidth-itemSpacing+2+24),float(totalSpacing*(3+1)-itemSpacing+24)}; //Need space for the button.
vf2d windowSize={float(totalSpacing*invWidth-itemSpacing+2+24),float(totalSpacing*(3+1)-itemSpacing+64)}; //Need space for the button.
Menu*inventoryWindow=CreateMenu(INVENTORY,CENTERED,windowSize);
inventoryWindow->I(A::LOADOUT_SLOT)=0;
InventoryScrollableWindowComponent*inventory=NEW InventoryScrollableWindowComponent(INVENTORY,{{1,0},{windowSize.x,float(totalSpacing*3-itemSpacing)}});
InventoryScrollableWindowComponent*inventory=NEW InventoryScrollableWindowComponent(INVENTORY,{{1,20},{windowSize.x,float(totalSpacing*3-itemSpacing)}},"Consumables");
inventoryWindow->AddComponent("inventory",inventory);
Menu::AddInventoryListener(inventory,"Consumables");
Menu::AddInventoryListener(inventory,"Equipment");
Menu::AddInventoryListener(inventory,"Accessories");
Menu::AddInventoryListener(inventory,"Materials");
//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.
MenuLabel*inventoryTypeLabel=NEW MenuLabel(INVENTORY,{{0,0},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE);
inventoryWindow->AddComponent("Inventory Type Label",inventoryTypeLabel);
MenuLabel*itemNameLabel=NEW MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing-16)},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW};
inventoryWindow->AddComponent("itemName",itemNameLabel);
MenuLabel*itemDescriptionLabel=NEW MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,float(initialInvHeight*totalSpacing+itemSpacing)},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW};
float itemDescriptionLabelY=float(initialInvHeight*totalSpacing+itemSpacing);
MenuLabel*itemDescriptionLabel=NEW MenuLabel{INVENTORY,geom2d::rect<float>(vf2d{2,itemDescriptionLabelY},{windowSize.x-4,windowSize.y-108}),"",1,ComponentAttr::SHADOW};
inventoryWindow->AddComponent("itemDescription",itemDescriptionLabel);
MenuComponent*okButton=NEW MenuComponent(INVENTORY,{{windowSize.x/2-24,itemDescriptionLabelY+56},{48,12}},"Ok",[](MenuFuncData data){Menu::CloseMenu();return true;});
inventoryWindow->AddComponent("OK Button",okButton);
}

@ -40,9 +40,12 @@ typedef Attribute A;
class InventoryScrollableWindowComponent:public ScrollableWindowComponent{
protected:
ITCategory inventoryType;
public:
inline InventoryScrollableWindowComponent(MenuType parent,geom2d::rect<float>rect,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
:ScrollableWindowComponent(parent,rect,attributes){}
inline InventoryScrollableWindowComponent(MenuType parent,geom2d::rect<float>rect,ITCategory invType,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
:ScrollableWindowComponent(parent,rect,attributes),inventoryType(invType){
Menu::AddInventoryListener(this,invType);
}
protected:
virtual inline void RemoveButton(MenuComponent*button){
std::vector<MenuComponent*>&buttonList=Menu::menus[button->parentMenu]->buttons.at(button->GetPos().y);
@ -102,19 +105,25 @@ protected:
MenuFunc useItemFunc=[&](MenuFuncData data){
MenuItemButton*button=(MenuItemButton*)data.component;
if(!data.game->GetPlayer()->GetLoadoutItem(data.menu.I(A::LOADOUT_SLOT)).IsBlank()){ //This loadout slot seems to have an item in it already, so deselect that one first.
data.game->GetPlayer()->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
if(!data.game->GetLoadoutItem(data.menu.I(A::LOADOUT_SLOT)).IsBlank()){ //This loadout slot seems to have an item in it already, so deselect that one first.
data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
for(MenuComponent*component:components){
if(component->GetName().starts_with("item")){
MenuItemButton*button=(MenuItemButton*)component;//HACK ALERT! This is probably an item since we populated item lists using this name for the components. So we assume these are MenuItemButton classes.
if(button->selected==data.menu.I(A::LOADOUT_SLOT)){
button->selected=-1;
MenuItemButton*button2=(MenuItemButton*)component;//HACK ALERT! This is probably an item since we populated item lists using this name for the components. So we assume these are MenuItemButton classes.
if(button2==button){
if(button2->selected!=-1){
data.game->ClearLoadoutItem(button2->selected);
}
button2->selected=-1;
}
if(button2->selected==data.menu.I(A::LOADOUT_SLOT)){
button2->selected=-1;
}
}
}
}
button->selected=data.menu.I(A::LOADOUT_SLOT);
data.game->GetPlayer()->SetLoadoutItem(button->selected,button->GetItem().Name());
data.game->SetLoadoutItem(button->selected,button->GetItem().Name());
return true;
};

@ -48,7 +48,7 @@ typedef std::function<bool(Crawler*,ItemProps)> ItemScript;
class Item{
friend class Inventory;
friend class Player;
friend class Crawler;
private:
uint32_t amt;
ItemInfo*it;
@ -77,6 +77,11 @@ public:
static std::vector<IT>&get(ITCategory itemCategory);
static bool SwapItems(ITCategory itemCategory,uint32_t slot1,uint32_t slot2);
//Makes sure this is a valid category. Will error out if it doesn't exist! Use for ERROR HANDLING!
static bool ValidateItemCategory(ITCategory itemCategory){
get(itemCategory);
return true;
}
private:
static void InsertIntoSortedInv(IT item);
static bool ExecuteAction(IT item);

@ -0,0 +1,73 @@
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2023 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#pragma once
#include "Crawler.h"
#include "DEFINES.h"
#include "Menu.h"
#include "MenuLabel.h"
#include "MenuItemItemButton.h"
#include "State_OverworldMap.h"
INCLUDE_game
typedef Attribute A;
void Menu::InitializeItemLoadoutWindow(){
Menu*itemLoadoutWindow=CreateMenu(ITEM_LOADOUT,CENTERED,game->GetScreenSize()-vi2d{4,4});
float itemLoadoutWindowWidth=(game->GetScreenSize().x-5.f);
MenuLabel*loadoutLabel=NEW MenuLabel(ITEM_LOADOUT,{{0,24},{itemLoadoutWindowWidth,24}},"Loadout",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE);
itemLoadoutWindow->AddComponent("Loadout Label",loadoutLabel);
float buttonBorderPadding=64;
MenuItemItemButton*loadoutItem1=NEW MenuItemItemButton(ITEM_LOADOUT,{{64,120},{48,48}},game->GetLoadoutItem(0),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=0; return true;});
MenuItemItemButton*loadoutItem2=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth/2-24,120},{48,48}},game->GetLoadoutItem(1),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=1;return true;});
MenuItemItemButton*loadoutItem3=NEW MenuItemItemButton(ITEM_LOADOUT,{{itemLoadoutWindowWidth-48-64,120},{48,48}},game->GetLoadoutItem(2),INVENTORY,[](MenuFuncData data){Menu::menus.at(INVENTORY)->I(A::LOADOUT_SLOT)=2;return true;});
//TODO: Make these two do something.
MenuLabel*itemNameLabel=NEW MenuLabel(ITEM_LOADOUT,{{0,182},{itemLoadoutWindowWidth,12}},"",1,ComponentAttr::SHADOW);
MenuLabel*itemDescription=NEW MenuLabel(ITEM_LOADOUT,{{0,194},{itemLoadoutWindowWidth,24}},"",1,ComponentAttr::SHADOW);
itemLoadoutWindow->AddComponent("Loadout Item 1",loadoutItem1);
itemLoadoutWindow->AddComponent("Loadout Item 2",loadoutItem2);
itemLoadoutWindow->AddComponent("Loadout Item 3",loadoutItem3);
itemLoadoutWindow->AddComponent("Item Name Label",itemNameLabel);
itemLoadoutWindow->AddComponent("Item Description",itemDescription);
MenuComponent*startLevelButton=NEW MenuComponent(ITEM_LOADOUT,{{itemLoadoutWindowWidth/2-32,214},{64,16}},"Start",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;});
itemLoadoutWindow->AddComponent("Start Level Button",startLevelButton);
}

@ -82,11 +82,12 @@ void Menu::InitializeMenus(){
stack.reserve(32);
InitializeTestMenu();
InitializeTestSubMenu();
InitializeInventoryWindow();
InitializeConsumableInventoryWindow();
InitializeClassSelectionWindow();
InitializeClassInfoWindow();
InitializeMainMenuWindow();
InitializeOverworldMapLevelWindow();
InitializeItemLoadoutWindow();
for(MenuType type=TEST;type<MenuType::ENUM_END;type=MenuType(int(type+1))){
if(menus.count(type)==0){

@ -48,6 +48,7 @@ enum MenuType{
CLASS_SELECTION,
MAIN_MENU,
OVERWORLD_LEVEL_SELECT,
ITEM_LOADOUT,
///////////////////////////////////////////////////////////
/*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
///////////////////////////////////////////////////////////
@ -116,11 +117,12 @@ private:
static Menu*CreateMenu(MenuType type,vf2d pos,vf2d size);
static void InitializeTestMenu();
static void InitializeTestSubMenu();
static void InitializeInventoryWindow();
static void InitializeConsumableInventoryWindow();
static void InitializeClassInfoWindow();
static void InitializeClassSelectionWindow();
static void InitializeMainMenuWindow();
static void InitializeOverworldMapLevelWindow();
static void InitializeItemLoadoutWindow();
//X (0-2), Y (0-2) for specific 9-patch tile (tiled version).
static Renderable&GetPatchPart(int x,int y);

@ -51,11 +51,10 @@ class MenuComponent:IAttributable{
friend class MenuItemButton;
friend class ScrollableWindowComponent;
friend class InventoryScrollableWindowComponent;
friend class MenuItemItemButton;
MenuType menuDest;
private:
virtual bool GetHoverState(Crawler*game);
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
virtual bool PointWithinParent(MenuComponent*child,vi2d drawPos);
std::pair<MenuType,std::string>memoryLeakInfo; //Used to identify memory leak hints for this component.
protected:
float hoverEffect=0;
@ -80,6 +79,8 @@ protected:
virtual void DrawDecal(Crawler*game,vf2d parentPos,bool focused);
virtual bool GetHoverState(Crawler*game,MenuComponent*child);
virtual void AfterCreate(); //Called after the creation of all menus finish.
//CALL THIS FOR A PARENT to check a child's DrawDecal validity!
virtual bool PointWithinParent(MenuComponent*child,vi2d drawPos);
public:
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE);
MenuComponent(MenuType parent,geom2d::rect<float>rect,std::string label,MenuType menuDest,MenuFunc onClick,ButtonAttr attributes=ButtonAttr::NONE);

@ -47,6 +47,8 @@ protected:
public:
inline MenuIconButton(MenuType parent,geom2d::rect<float>rect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE)
:MenuComponent(parent,rect,"",onClick,ButtonAttr(attributes)),icon(icon){}
inline MenuIconButton(MenuType parent,geom2d::rect<float>rect,Decal*icon,MenuType menuDest,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE)
:MenuComponent(parent,rect,"",menuDest,onClick,ButtonAttr(attributes)),icon(icon){}
protected:
virtual inline void Update(Crawler*game)override{
MenuComponent::Update(game);

@ -66,31 +66,28 @@ protected:
virtual inline void Update(Crawler*game)override{
MenuIconButton::Update(game);
valid=invRef.size()>inventoryIndex&&ITEM_DATA.count(invRef[inventoryIndex]);
if(Menu::stack.size()>0){
Menu*menu=Menu::stack.back();
if(valid){
icon=ITEM_DATA.at(invRef[inventoryIndex]).Decal();
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(INVENTORY,"itemName")->label=ITEM_DATA.at(invRef[inventoryIndex]).Name();
//There should be an itemDescription label to modify.
Component<MenuLabel>(INVENTORY,"itemDescription")->label=ITEM_DATA.at(invRef[inventoryIndex]).Description();
}break;
}
if(valid){
icon=ITEM_DATA.at(invRef[inventoryIndex]).Decal();
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(INVENTORY,"itemName")->label=ITEM_DATA.at(invRef[inventoryIndex]).Name();
//There should be an itemDescription label to modify.
Component<MenuLabel>(INVENTORY,"itemDescription")->label=ITEM_DATA.at(invRef[inventoryIndex]).Description();
}break;
}
}else{
icon=nullptr;
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(INVENTORY,"itemName")->label="";
//There should be an itemDescription label to modify.
Component<MenuLabel>(INVENTORY,"itemDescription")->label="";
}break;
}
}
}else{
icon=nullptr;
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(INVENTORY,"itemName")->label="";
//There should be an itemDescription label to modify.
Component<MenuLabel>(INVENTORY,"itemDescription")->label="";
}break;
}
}
}
@ -112,7 +109,7 @@ protected:
}
}
}
virtual inline MenuComponent*PickUpDraggableItem()override{
inline MenuComponent*PickUpDraggableItem()override sealed{
if(valid){
MenuItemButton*pickUp=NEW MenuItemButton(parentMenu,rect,invRef,inventoryIndex,onClick);
valid=false;
@ -122,7 +119,7 @@ protected:
}
}
virtual inline bool DropDraggableItem(MenuComponent*draggable)override{
inline bool DropDraggableItem(MenuComponent*draggable)override sealed{
//HACK Warning! We're making a bold assumption that every component that is draggable is of the same type! This may change in the future....
MenuItemButton*draggedItem=(MenuItemButton*)draggable;
ITCategory cat=ITEM_DATA.at(draggedItem->invRef.at(draggedItem->inventoryIndex)).Category();

@ -0,0 +1,99 @@
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2023 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#pragma once
#include "Menu.h"
#include "MenuLabel.h"
#include "MenuItemButton.h"
#include "DEFINES.h"
#include "Crawler.h"
#include "Item.h"
#include "safemap.h"
#include "olcPGEX_Graphics2D.h"
#include "drawutil.h"
INCLUDE_game
INCLUDE_ITEM_DATA
class MenuItemItemButton:public MenuIconButton{
private:
Item&itemRef;
public:
inline MenuItemItemButton(MenuType parent,geom2d::rect<float>rect,Item&itemRef,MenuType menuDest,MenuFunc onClick)
:MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef){
draggable=false;
valid=!itemRef.IsBlank();
}
protected:
virtual inline void Update(Crawler*game)override{
MenuIconButton::Update(game);
valid=!itemRef.IsBlank();
if(valid){
icon=itemRef.Decal();
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(ITEM_LOADOUT,"Item Name Label")->label=itemRef.Name();
//There should be an itemDescription label to modify.
Component<MenuLabel>(ITEM_LOADOUT,"Item Description")->label=itemRef.Description();
}break;
}
}
}else{
icon=nullptr;
if(hovered){
switch(parentMenu){
case INVENTORY:{
//There should be an itemName label to modify.
Component<MenuLabel>(ITEM_LOADOUT,"Item Name Label")->label="";
//There should be an itemDescription label to modify.
Component<MenuLabel>(ITEM_LOADOUT,"Item Description")->label="";
}break;
}
}
}
}
virtual inline void Draw(Crawler*game,vf2d parentPos)override{
MenuIconButton::Draw(game,parentPos);
}
virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
MenuIconButton::DrawDecal(game,parentPos,focused);
if(valid){
std::string quantityText="x"+std::to_string(itemRef.Amt());
vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*0.5;
vf2d drawPos=parentPos+rect.pos+rect.size-textSize;
if(PointWithinParent(this,drawPos)){
game->DrawShadowStringDecal(drawPos,quantityText,WHITE,BLACK,{0.5,0.5},0.5);
}
}
}
};

@ -75,7 +75,7 @@ void Menu::InitializeOverworldMapLevelWindow(){
levelSelectWindow->AddComponent("Encounters Label",encountersLabel);
levelSelectWindow->AddComponent("Spawns List",spawns);
MenuComponent*changeLoadoutButton=NEW MenuComponent(OVERWORLD_LEVEL_SELECT,{{0,152},{windowSize.x-1,12}},"Change Loadout",INVENTORY,[](MenuFuncData data){return true;});
MenuComponent*changeLoadoutButton=NEW MenuComponent(OVERWORLD_LEVEL_SELECT,{{0,152},{windowSize.x-1,12}},"Change Loadout",ITEM_LOADOUT,[](MenuFuncData data){return true;});
MenuComponent*enterButton=NEW MenuComponent(OVERWORLD_LEVEL_SELECT,{{0,166},{windowSize.x-1,16}},"Enter",[](MenuFuncData data){State_OverworldMap::StartLevel();return true;});
levelSelectWindow->AddComponent("Change Loadout Button",changeLoadoutButton);

@ -750,32 +750,3 @@ void Player::ConsumeMana(int amt){
void Player::SetSizeMult(float size){
this->size=size;
}
Item&Player::GetLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
return loadout[slot];
}
void Player::SetLoadoutItem(int slot,std::string itemName){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
if(Inventory::GetItemCount(itemName)>0){
GetLoadoutItem(slot)=Inventory::GetItem(itemName);
GetLoadoutItem(slot).amt=std::min((uint32_t)"Player.Item Loadout Limit"_I,GetLoadoutItem(slot).Amt()); //We are only allowed to have up to 10 maximum of an item on a journey.
}else{
ERR("Trying to set item "+itemName+" in Loadout slot "+std::to_string(slot)+" when said item does not exist in our inventory!");
}
}
void Player::UseLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
if(GetLoadoutItem(slot).Amt()>0){
Inventory::UseItem(loadout[slot].Name());
GetLoadoutItem(slot).OnUseAction();
GetLoadoutItem(slot).amt--;
}
}
void Player::ClearLoadoutItem(int slot){
if(slot<0||slot>loadout.size()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(loadout.size()-1)+").");
loadout[slot]={};
}

@ -77,7 +77,6 @@ private:
float spin_angle=0;
float lastAnimationFlip=0;
float manaTickTimer=0;
std::array<Item,3>loadout;
std::pair<std::string,float> notEnoughManaDisplay={"",0};
float teleportAttemptWaitTime=0; //If a teleport fails, we wait awhile before trying again, it's expensive.
State::State state=State::NORMAL;
@ -190,11 +189,6 @@ public:
Key GetLastReleasedMovementKey();
float GetSwordSwingTimer();
bool OnUpperLevel();
Item&GetLoadoutItem(int slot);
void SetLoadoutItem(int slot,std::string itemName);
void UseLoadoutItem(int slot);
//Blanks out this loadout item.
void ClearLoadoutItem(int slot);
//Triggers when the player has moved.
void Moved();
virtual ~Player()=default;

@ -33,7 +33,7 @@ SUCH DAMAGE.
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 1
#define VERSION_BUILD 2815
#define VERSION_BUILD 2854
#define stringify(a) stringify_(a)
#define stringify_(a) #a

Binary file not shown.
Loading…
Cancel
Save