Fixed detection of craftable items that aren't enhanceable (failed out of bounds checks). Hide information about craftable items that have yet to be unlocked.

pull/28/head
sigonasr2 1 year ago
parent 4e3c9877e7
commit c876f8a6ea
  1. 106
      Crawler/ConsumableCraftingWindow.cpp
  2. 3
      Crawler/Crawler.cpp
  3. 12
      Crawler/Item.cpp
  4. 3
      Crawler/Item.h
  5. 8
      Crawler/Menu.cpp
  6. 2
      Crawler/Menu.h
  7. 2
      Crawler/MenuComponent.cpp
  8. 1
      Crawler/MenuComponent.h
  9. 3
      Crawler/MenuIconButton.h
  10. 14
      Crawler/MenuItemItemButton.h
  11. 1
      Crawler/RowInventoryScrollableWindowComponent.h
  12. 23
      Crawler/RowItemDisplay.h
  13. 3
      Crawler/State_OverworldMap.cpp
  14. 2
      Crawler/Version.h
  15. 2
      Crawler/assets/config/items/ItemDatabase.txt

@ -52,46 +52,8 @@ INCLUDE_GFX
void Menu::InitializeConsumableCraftingWindow(){ void Menu::InitializeConsumableCraftingWindow(){
Menu*consumableCraftingWindow=CreateMenu(CRAFT_CONSUMABLE,CENTERED,game->GetScreenSize()-vi2d{52,52}); Menu*consumableCraftingWindow=CreateMenu(CRAFT_CONSUMABLE,CENTERED,game->GetScreenSize()-vi2d{52,52});
std::vector<std::pair<std::string,int>>categories; #pragma region Craftables Inventory Display
std::vector<std::weak_ptr<Item>>weaponInventory; auto craftingItemsDisplay=consumableCraftingWindow->ADD("Crafting Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,consumableCraftingWindow->size.y-44}},"Item Name Label","Item Description Label",
std::vector<std::weak_ptr<Item>>armorInventory;
#pragma region Build Equipment Lists
std::for_each(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),[&](const std::shared_ptr<Item> item){
switch(item.get()->GetEquipSlot()){
case EquipSlot::WEAPON:{
weaponInventory.push_back(item);
}break;
case EquipSlot::NONE:
case EquipSlot::RING1:
case EquipSlot::RING2:break;//No-op
default:{ //We assume everything else is armor.
armorInventory.push_back(item);
}
}
});
#pragma endregion
auto weaponTab=consumableCraftingWindow->ADD("Weapon Tab",MenuComponent)({{2,0},{consumableCraftingWindow->size.x/2-4,24}},"Weapon",[](MenuFuncData data){
Component<MenuComponent>(CRAFT_CONSUMABLE,"Armor Tab")->selected=false;
Component<RowInventoryScrollableWindowComponent>(CRAFT_CONSUMABLE,"Weapon Inventory Display")->Enable(true);
Component<RowInventoryScrollableWindowComponent>(CRAFT_CONSUMABLE,"Armor Inventory Display")->Enable(false);
data.component->selected=true;
return true;
})END;
weaponTab->selected=true;
weaponTab->selectionType=SelectionType::HIGHLIGHT;
auto armorTab=consumableCraftingWindow->ADD("Armor Tab",MenuComponent)({{consumableCraftingWindow->size.x/2+2,0},{consumableCraftingWindow->size.x/2-4,24}},"Armor",[](MenuFuncData data){
Component<MenuComponent>(CRAFT_CONSUMABLE,"Weapon Tab")->selected=false;
Component<RowInventoryScrollableWindowComponent>(CRAFT_CONSUMABLE,"Weapon Inventory Display")->Enable(false);
Component<RowInventoryScrollableWindowComponent>(CRAFT_CONSUMABLE,"Armor Inventory Display")->Enable(true);
data.component->selected=true;
return true;
})END;
armorTab->selectionType=SelectionType::HIGHLIGHT;
#pragma region Weapon Inventory Display
auto weaponsDisplay=consumableCraftingWindow->ADD("Weapon Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,consumableCraftingWindow->size.y-44}},"Item Name Label","Item Description Label",
[](MenuFuncData data){ [](MenuFuncData data){
RowItemDisplay*comp=DYNAMIC_CAST<RowItemDisplay*>(data.component); RowItemDisplay*comp=DYNAMIC_CAST<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=comp->GetItem(); const std::weak_ptr<Item>item=comp->GetItem();
@ -110,6 +72,11 @@ void Menu::InitializeConsumableCraftingWindow(){
}, },
[](MenuFuncData data){ [](MenuFuncData data){
RowItemDisplay*rowItem=DYNAMIC_CAST<RowItemDisplay*>(data.component); RowItemDisplay*rowItem=DYNAMIC_CAST<RowItemDisplay*>(data.component);
if(rowItem->GetItem().lock()->GetEnhancementInfo().AvailableChapter()<=game->GetCurrentChapter()){
Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetHideDetails(false);
}else{
Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetHideDetails(true);
}
Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetItem(rowItem->GetItem()); Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetItem(rowItem->GetItem());
return true; return true;
}, },
@ -120,49 +87,36 @@ void Menu::InitializeConsumableCraftingWindow(){
InventoryCreator::RowPlayerWeapons_InventoryUpdate, InventoryCreator::RowPlayerWeapons_InventoryUpdate,
{.padding=1,.size={207,28}} {.padding=1,.size={207,28}}
)END; )END;
AddInventoryListener(weaponsDisplay,"Equipment");
weaponsDisplay->SetCompactDescriptions(CRAFTING_INFO);
#pragma endregion
#pragma region Armor Inventory Display craftingItemsDisplay->SetCompactDescriptions(CRAFTING_INFO);
auto armorDisplay=consumableCraftingWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,consumableCraftingWindow->size.y-44}},"Item Name Label","Item Description Label",
[](MenuFuncData data){ vf2d buttonSize=craftingItemsDisplay->options.size;
Menu::OpenMenu(CRAFT_ITEM); vf2d totalSpacing={craftingItemsDisplay->options.padding+buttonSize.x,craftingItemsDisplay->options.padding+buttonSize.y};
RowItemDisplay*comp=DYNAMIC_CAST<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=comp->GetItem(); for(auto item:ItemInfo::craftableConsumables){
size_t invSize=craftingItemsDisplay->components.size()+1;
std::string label=""; int invWidth=int(craftingItemsDisplay->rect.size.x/(float(craftingItemsDisplay->options.size.x)+craftingItemsDisplay->options.padding));
if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ int x=int((invSize-1)%invWidth);
label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); int y=int((invSize-1)/invWidth);
int itemIndex=y*invWidth+x;
auto newItem=craftingItemsDisplay->ADD("item_Craftables_"+std::to_string(itemIndex),RowItemDisplay)({totalSpacing*vf2d{float(x),float(y)},buttonSize},item,craftingItemsDisplay->inventoryButtonClickAction,craftingItemsDisplay->itemNameLabelName,craftingItemsDisplay->itemDescriptionLabelName,craftingItemsDisplay->inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
newItem->SetShowQuantity(false);
newItem->SetCompactDescriptions(craftingItemsDisplay->compact);
newItem->SetPriceLabelType(craftingItemsDisplay->priceLabel);
newItem->SetHoverFunc(craftingItemsDisplay->inventoryButtonHoverAction);
newItem->SetMouseOutFunc(craftingItemsDisplay->inventoryButtonMouseOutAction);
newItem->SetCheckCraftingRequirements(true);
newItem->SetHideLabelWhileLocked(true);
} }
Component<MenuLabel>(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label);
Component<MenuLabel>(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName()));
Component<EnhancementStatsLabel>(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item);
Component<RequiredMaterialsList>(CRAFT_ITEM,"Required Materials List")->SetItem(item);
Component<MenuComponent>(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem());
return true;
},
[](MenuFuncData data){
RowItemDisplay*rowItem=DYNAMIC_CAST<RowItemDisplay*>(data.component);
Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetItem(rowItem->GetItem());
return true;
},
[](MenuFuncData data){
Component<MenuItemItemButton>(CRAFT_CONSUMABLE,"Item Icon")->SetItem(Item::BLANK);
return true;
},
InventoryCreator::RowPlayerArmor_InventoryUpdate,
{.padding=1,.size={207,28}}
)END;
AddInventoryListener(armorDisplay,"Equipment");
armorDisplay->Enable(false);
armorDisplay->SetCompactDescriptions(CRAFTING_INFO);
#pragma endregion #pragma endregion
#pragma region Inventory Description #pragma region Inventory Description
float inventoryDescriptionWidth=consumableCraftingWindow->pos.x+consumableCraftingWindow->size.x-26-224; float inventoryDescriptionWidth=consumableCraftingWindow->pos.x+consumableCraftingWindow->size.x-26-224;
consumableCraftingWindow->ADD("Item Description Outline",MenuLabel)({{224,28},{inventoryDescriptionWidth,consumableCraftingWindow->size.y-44}},"",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END; consumableCraftingWindow->ADD("Item Description Outline",MenuLabel)({{224,28},{inventoryDescriptionWidth,consumableCraftingWindow->size.y-44}},"",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
consumableCraftingWindow->ADD("Item Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END; consumableCraftingWindow->ADD("Item Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END
->SetShowQuantity(false);
consumableCraftingWindow->ADD("Item Name Label",MenuLabel)({{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END; consumableCraftingWindow->ADD("Item Name Label",MenuLabel)({{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
consumableCraftingWindow->ADD("Item Description Label",MenuLabel)({{226,94},{inventoryDescriptionWidth-6,consumableCraftingWindow->size.y-44-66}},"",0.5f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END; consumableCraftingWindow->ADD("Item Description Label",MenuLabel)({{226,94},{inventoryDescriptionWidth-6,consumableCraftingWindow->size.y-44-66}},"",0.5f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
#pragma endregion #pragma endregion

@ -2337,6 +2337,9 @@ int Crawler::GetCurrentChapter(){
void Crawler::SetChapter(int chapter){ void Crawler::SetChapter(int chapter){
this->chapter=chapter; this->chapter=chapter;
for(MenuComponent*component:Menu::chapterListeners){
component->OnChapterUpdate(chapter);
}
} }
const std::weak_ptr<Item>Crawler::GetLoadoutItem(int slot){ const std::weak_ptr<Item>Crawler::GetLoadoutItem(int slot){

@ -60,7 +60,7 @@ std::map<std::string,EquipSlot>ItemInfo::nameToEquipSlot;
int Item::IsBlankStaticCallCounter=0; int Item::IsBlankStaticCallCounter=0;
safemap<int,float>Stats::maxDamageReductionTable; safemap<int,float>Stats::maxDamageReductionTable;
ItemEnhancementFunctionPrimingData Item::enhanceFunctionPrimed("CanEnhanceItem()"); ItemEnhancementFunctionPrimingData Item::enhanceFunctionPrimed("CanEnhanceItem()");
std::vector<ItemInfo*>ItemInfo::craftableConsumables; std::vector<std::shared_ptr<Item>>ItemInfo::craftableConsumables;
ItemInfo::ItemInfo() ItemInfo::ItemInfo()
:customProps({nullptr,nullptr}),img(nullptr){} :customProps({nullptr,nullptr}),img(nullptr){}
@ -186,7 +186,8 @@ void ItemInfo::InitializeItems(){
if(data[key]["Crafting"].HasProperty("AvailableChapter")){ if(data[key]["Crafting"].HasProperty("AvailableChapter")){
availableChapter=data[key]["Crafting"]["AvailableChapter"].GetInt(); availableChapter=data[key]["Crafting"]["AvailableChapter"].GetInt();
} }
craftableConsumables.push_back(&it); craftableConsumables.push_back(std::make_shared<Item>(1,key));
it.enhancement.SetAttribute(1,ItemAttribute::Get("Attack"),0.f);
it.enhancement.SetCraftingRequirements(1,itemsRequired,goldCost,availableChapter); it.enhancement.SetCraftingRequirements(1,itemsRequired,goldCost,availableChapter);
} }
@ -543,9 +544,10 @@ const std::string Item::Description(CompactText compact)const{
first=false; first=false;
} }
} }
}
if(compact==CRAFTING_INFO){ if(compact==CRAFTING_INFO){
description+="\n\nCrafting Requirements:\n---------\n"; description+="\n\nCrafting Requirements:\n---------\n";
if(IsEquippable()&&EnhancementLevel()<"Item.Item Max Enhancement Level"_I||IsCraftable()){ if(IsCraftable()){
const EnhancementLevelInfo&info=GetEnhancementInfo()[EnhancementLevel()+1]; const EnhancementLevelInfo&info=GetEnhancementInfo()[EnhancementLevel()+1];
for(const auto&[name,amt]:info.craftingRequirement.GetItems()){ for(const auto&[name,amt]:info.craftingRequirement.GetItems()){
description+=std::format("{}{} x{} ({})\n", description+=std::format("{}{} x{} ({})\n",
@ -561,7 +563,6 @@ const std::string Item::Description(CompactText compact)const{
"Item.Currency Name"_S); "Item.Currency Name"_S);
} }
} }
}
return description; return description;
} }
const ITCategory Item::Category()const{ const ITCategory Item::Category()const{
@ -909,6 +910,7 @@ void EnhancementInfo::SetCraftingRequirements(const int enhanceLevel,const std::
while(craftingRequirements.size()<=enhanceLevel){ while(craftingRequirements.size()<=enhanceLevel){
craftingRequirements.push_back(CraftingRequirement({},0)); craftingRequirements.push_back(CraftingRequirement({},0));
} }
this->availableChapter=availableChapter;
craftingRequirements[enhanceLevel]=CraftingRequirement(requiredItems,goldCost); craftingRequirements[enhanceLevel]=CraftingRequirement(requiredItems,goldCost);
} }
@ -944,7 +946,7 @@ const EnhancementInfo&Item::GetEnhancementInfo()const{
} }
const bool EnhancementInfo::CanBeEnhanced()const{ const bool EnhancementInfo::CanBeEnhanced()const{
return enhancementStats.size()>0&&craftingRequirements.size()>0; return craftingRequirements.size()>0;
}; };

@ -265,6 +265,7 @@ public:
class ItemInfo{ class ItemInfo{
friend class Inventory; friend class Inventory;
friend class Menu;
std::string name; std::string name;
std::string description; std::string description;
std::string category; std::string category;
@ -287,7 +288,7 @@ private:
static void InitializeScripts(); static void InitializeScripts();
static void InitializeSets(); static void InitializeSets();
static std::map<std::string,EquipSlot>nameToEquipSlot; static std::map<std::string,EquipSlot>nameToEquipSlot;
static std::vector<ItemInfo*>craftableConsumables; static std::vector<std::shared_ptr<Item>>craftableConsumables;
public: public:
static void InitializeItems(); static void InitializeItems();
ItemInfo(); ItemInfo();

@ -56,6 +56,7 @@ safeunorderedmap<std::string,Theme>Menu::themes;
safemap<ITCategory,std::vector<MenuComponent*>>Menu::inventoryListeners; safemap<ITCategory,std::vector<MenuComponent*>>Menu::inventoryListeners;
safemap<ITCategory,std::vector<MenuComponent*>>Menu::merchantInventoryListeners; safemap<ITCategory,std::vector<MenuComponent*>>Menu::merchantInventoryListeners;
std::vector<MenuComponent*>Menu::equipStatListeners; std::vector<MenuComponent*>Menu::equipStatListeners;
std::vector<MenuComponent*>Menu::chapterListeners;
const vf2d Menu::CENTERED = {-456,-456}; const vf2d Menu::CENTERED = {-456,-456};
std::vector<MenuComponent*>Menu::unhandledComponents; std::vector<MenuComponent*>Menu::unhandledComponents;
////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////
@ -701,3 +702,10 @@ void Menu::LockInListeners(){
inventoryListeners.SetInitialized(); inventoryListeners.SetInitialized();
merchantInventoryListeners.SetInitialized(); merchantInventoryListeners.SetInitialized();
} }
void Menu::AddChapterListener(MenuComponent*component){
if(std::find(chapterListeners.begin(),chapterListeners.end(),component)!=chapterListeners.end()){
ERR("WARNING! Component "<<component->name<<" has already been added to the Chapter listener list! There should not be any duplicates!!")
}
chapterListeners.push_back(component);
}

@ -118,6 +118,7 @@ class Menu:public IAttributable{
static safemap<ITCategory,std::vector<MenuComponent*>>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()). static safemap<ITCategory,std::vector<MenuComponent*>>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()).
static safemap<ITCategory,std::vector<MenuComponent*>>merchantInventoryListeners; //All menu components that care about merchant inventory updates subscribe to this list indirectly (See Menu::AddMerchantInventoryListener()). static safemap<ITCategory,std::vector<MenuComponent*>>merchantInventoryListeners; //All menu components that care about merchant inventory updates subscribe to this list indirectly (See Menu::AddMerchantInventoryListener()).
static std::vector<MenuComponent*>equipStatListeners; //All menu components that care about stat/equip updates subscribe to this list indirectly (See Menu::AddStatListener()). static std::vector<MenuComponent*>equipStatListeners; //All menu components that care about stat/equip updates subscribe to this list indirectly (See Menu::AddStatListener()).
static std::vector<MenuComponent*>chapterListeners; //All menu components that care about story chapter updates subscribe to this list indirectly (See Menu::AddChapterListener()).
public: public:
//The constructor is private. Use CreateMenu() instead! //The constructor is private. Use CreateMenu() instead!
Menu()=default; Menu()=default;
@ -210,6 +211,7 @@ public:
static void AddInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category. static void AddInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category.
static void AddMerchantInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category. static void AddMerchantInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category.
static void AddEquipStatListener(MenuComponent*component); //Adds a component to be in an equip stat listener. Will receive updates whenever stats are updated via equips. static void AddEquipStatListener(MenuComponent*component); //Adds a component to be in an equip stat listener. Will receive updates whenever stats are updated via equips.
static void AddChapterListener(MenuComponent*component); //Adds a component to be in a chapter listener. Will receive updates anytime the chapter in-game changes.
vf2d center(); vf2d center();
//Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety. //Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety.
static std::pair<MenuType,std::string>GetMemoryLeakReportInfo(); static std::pair<MenuType,std::string>GetMemoryLeakReportInfo();

@ -251,3 +251,5 @@ void MenuComponent::SetGrayedOut(bool grayedOut){
} }
void MenuComponent::OnPlayerMoneyUpdate(uint32_t newMoney){} void MenuComponent::OnPlayerMoneyUpdate(uint32_t newMoney){}
void MenuComponent::OnChapterUpdate(uint8_t newChapter){}

@ -151,4 +151,5 @@ public:
virtual void SetMouseOutFunc(std::function<bool(MenuFuncData)>func); virtual void SetMouseOutFunc(std::function<bool(MenuFuncData)>func);
void SetGrayedOut(bool grayedOut); void SetGrayedOut(bool grayedOut);
virtual void OnPlayerMoneyUpdate(uint32_t newMoney); virtual void OnPlayerMoneyUpdate(uint32_t newMoney);
virtual void OnChapterUpdate(uint8_t newChapter);
}; };

@ -53,6 +53,7 @@ enum class IconButtonAttr{
class MenuIconButton:public MenuComponent{ class MenuIconButton:public MenuComponent{
protected: protected:
Decal*icon; Decal*icon;
Pixel tint=WHITE;
public: public:
inline MenuIconButton(geom2d::rect<float>rect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) inline MenuIconButton(geom2d::rect<float>rect,Decal*icon,MenuFunc onClick,IconButtonAttr attributes=IconButtonAttr::SELECTABLE)
:MenuIconButton(rect,icon,MenuType::ENUM_END,onClick,attributes){} :MenuIconButton(rect,icon,MenuType::ENUM_END,onClick,attributes){}
@ -69,7 +70,7 @@ protected:
MenuComponent::DrawDecal(window,focused); MenuComponent::DrawDecal(window,focused);
if(icon!=nullptr){ if(icon!=nullptr){
vf2d iconScale=rect.size/24.f; vf2d iconScale=rect.size/24.f;
window.DrawDecal(rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale); window.DrawDecal(rect.middle()-icon->sprite->Size()*iconScale/2,icon,iconScale,tint);
} }
} }
}; };

@ -54,6 +54,7 @@ private:
std::string itemDescriptionLabelName; std::string itemDescriptionLabelName;
bool hideQty=false; bool hideQty=false;
CompactText compact=COMPACT; CompactText compact=COMPACT;
bool hideDetails=false;
public: public:
inline MenuItemItemButton(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuType menuDest,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,IconButtonAttr attributes=IconButtonAttr::SELECTABLE) inline MenuItemItemButton(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuType menuDest,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,IconButtonAttr attributes=IconButtonAttr::SELECTABLE)
:MenuIconButton(rect,!ISBLANK(itemRef)?const_cast<Decal*>(itemRef.lock()->Decal()):nullptr,menuDest,onClick,attributes),itemRef(itemRef),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName){ :MenuIconButton(rect,!ISBLANK(itemRef)?const_cast<Decal*>(itemRef.lock()->Decal()):nullptr,menuDest,onClick,attributes),itemRef(itemRef),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName){
@ -74,6 +75,7 @@ public:
inline const std::weak_ptr<Item>SetItem(const std::weak_ptr<Item>newItem){ inline const std::weak_ptr<Item>SetItem(const std::weak_ptr<Item>newItem){
itemRef=newItem; itemRef=newItem;
UpdateIcon(); UpdateIcon();
UpdateLabel();
return itemRef; return itemRef;
} }
inline void SetShowQuantity(bool show){ inline void SetShowQuantity(bool show){
@ -90,6 +92,14 @@ public:
} }
icon=const_cast<Decal*>(itemRef.lock()->Decal()); icon=const_cast<Decal*>(itemRef.lock()->Decal());
} }
inline void SetHideDetails(bool hideDetails){
this->hideDetails=hideDetails;
if(hideDetails){
tint=BLACK;
}else{
tint=WHITE;
}
}
protected: protected:
virtual inline void OnMouseOut()override{ virtual inline void OnMouseOut()override{
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
@ -116,6 +126,10 @@ protected:
icon=const_cast<Decal*>(itemRef.lock()->Decal()); icon=const_cast<Decal*>(itemRef.lock()->Decal());
labelNameText=itemRef.lock()->DisplayName(); labelNameText=itemRef.lock()->DisplayName();
labelDescriptionText=itemRef.lock()->Description(compact); labelDescriptionText=itemRef.lock()->Description(compact);
if(hideDetails){
std::for_each(labelNameText.begin(),labelNameText.end(),[](char&c){c='?';});
std::for_each(labelDescriptionText.begin(),labelDescriptionText.end(),[](char&c){c='?';});
}
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText; Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true);

@ -42,6 +42,7 @@ All rights reserved.
class RowInventoryScrollableWindowComponent:public InventoryScrollableWindowComponent{ class RowInventoryScrollableWindowComponent:public InventoryScrollableWindowComponent{
friend class InventoryCreator; friend class InventoryCreator;
friend class Menu;
protected: protected:
PriceLabel::PriceLabel priceLabel=PriceLabel::NONE; PriceLabel::PriceLabel priceLabel=PriceLabel::NONE;
public: public:

@ -52,20 +52,23 @@ namespace PriceLabel{
} }
class RowItemDisplay:public MenuComponent{ class RowItemDisplay:public MenuComponent{
std::weak_ptr<Item>itemRef;
std::string itemNameLabelName; std::string itemNameLabelName;
std::string itemDescriptionLabelName; std::string itemDescriptionLabelName;
CompactText compact=NON_COMPACT; CompactText compact=NON_COMPACT;
bool showQuantity=true; bool showQuantity=true;
PriceLabel::PriceLabel priceLabel=PriceLabel::NONE; PriceLabel::PriceLabel priceLabel=PriceLabel::NONE;
bool fadeOutIfMissingRequirements=false; bool fadeOutIfMissingRequirements=false;
bool hideLabelWhileLocked=false;
protected:
std::weak_ptr<Item>itemRef;
public: public:
inline RowItemDisplay(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,ButtonAttr attributes=ButtonAttr::NONE) inline RowItemDisplay(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,MenuFunc onClick,std::string itemNameLabelName,std::string itemDescriptionLabelName,ButtonAttr attributes=ButtonAttr::NONE)
:MenuComponent(rect,"",onClick,attributes),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),itemRef(itemRef){ :MenuComponent(rect,"",onClick,attributes),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),itemRef(itemRef){
if(itemRef.lock()->IsEquippable())SetShowQuantity(false); if(itemRef.lock()->IsEquippable())SetShowQuantity(false);
} }
virtual inline void DrawDecal(ViewPort&window,bool focused)final{ virtual inline void DrawDecal(ViewPort&window,bool focused)override{
bool canEnhance=itemRef.lock()->CanEnhanceItem(); bool canEnhance=itemRef.lock()->CanEnhanceItem();
bool locked=itemRef.lock()->EnhancementIsPossible()&&itemRef.lock()->GetEnhancementInfo().AvailableChapter()>game->GetCurrentChapter();
MenuComponent::DrawDecal(window,focused); MenuComponent::DrawDecal(window,focused);
@ -77,9 +80,13 @@ public:
float scaleFactor=(rect.size.y-4)/24; float scaleFactor=(rect.size.y-4)/24;
vf2d iconSize=vf2d{scaleFactor,scaleFactor}*24.f; vf2d iconSize=vf2d{scaleFactor,scaleFactor}*24.f;
window.DrawDecal(rect.pos+vf2d{2,2},const_cast<Decal*>(itemRef.lock()->Decal()),{scaleFactor,scaleFactor}); Pixel tint=WHITE;
if(locked)tint=BLACK;
window.DrawDecal(rect.pos+vf2d{2,2},const_cast<Decal*>(itemRef.lock()->Decal()),{scaleFactor,scaleFactor},tint);
window.DrawRectDecal(rect.pos+vf2d{2,2},iconSize); window.DrawRectDecal(rect.pos+vf2d{2,2},iconSize);
#pragma region Item Name Display
std::string itemName=itemRef.lock()->DisplayName(); std::string itemName=itemRef.lock()->DisplayName();
vf2d scaledSize={std::min(1.f,(rect.size.x-6-iconSize.x)/game->GetTextSizeProp(itemName).x),1}; vf2d scaledSize={std::min(1.f,(rect.size.x-6-iconSize.x)/game->GetTextSizeProp(itemName).x),1};
@ -87,7 +94,10 @@ public:
itemName="#666666"+itemName; itemName="#666666"+itemName;
} }
if(locked&&hideLabelWhileLocked)std::for_each(itemName.begin(),itemName.end(),[](char&c){if(c>='0'&&c<='z'){c='?';}});
window.DrawShadowStringPropDecal(rect.pos+vf2d{4,4}+vf2d{iconSize.x,iconSize.y/2-4},itemName,WHITE,BLACK,scaledSize); window.DrawShadowStringPropDecal(rect.pos+vf2d{4,4}+vf2d{iconSize.x,iconSize.y/2-4},itemName,WHITE,BLACK,scaledSize);
#pragma endregion
if(showQuantity&&itemRef.lock()->Amt()!=INFINITE){ if(showQuantity&&itemRef.lock()->Amt()!=INFINITE){
std::string quantityText=std::format("x{}",itemRef.lock()->Amt()); std::string quantityText=std::format("x{}",itemRef.lock()->Amt());
@ -161,6 +171,10 @@ public:
labelNameText=""; labelNameText="";
labelDescriptionText=""; labelDescriptionText="";
} }
if(hideLabelWhileLocked&&itemRef.lock()->EnhancementIsPossible()&&itemRef.lock()->GetEnhancementInfo().AvailableChapter()>game->GetCurrentChapter()){
std::for_each(labelNameText.begin(),labelNameText.end(),[](char&c){if(c>='0'&&c<='z'){c='?';}});
std::for_each(labelDescriptionText.begin(),labelDescriptionText.end(),[](char&c){if(c>='0'&&c<='z'){c='?';}});
}
if(itemNameLabelName!=""){ if(itemNameLabelName!=""){
Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText; Component<MenuLabel>(parentMenu,itemNameLabelName)->label=labelNameText;
Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true); Component<MenuLabel>(parentMenu,itemNameLabelName)->Enable(true);
@ -179,4 +193,7 @@ public:
inline void SetCheckCraftingRequirements(bool check){ inline void SetCheckCraftingRequirements(bool check){
this->fadeOutIfMissingRequirements=check; this->fadeOutIfMissingRequirements=check;
} }
inline void SetHideLabelWhileLocked(bool hideWhileLocked){
hideLabelWhileLocked=hideWhileLocked;
}
}; };

@ -99,6 +99,9 @@ void State_OverworldMap::OnUserUpdate(Crawler*game){
if(game->GetKey(B).bPressed){ if(game->GetKey(B).bPressed){
Menu::OpenMenu(BLACKSMITH); Menu::OpenMenu(BLACKSMITH);
} }
if(game->GetKey(C).bPressed){
Menu::OpenMenu(CRAFT_CONSUMABLE);
}
#pragma region Handle Connection Point Clicking and Movement #pragma region Handle Connection Point Clicking and Movement
for(ConnectionPoint&cp:connections){ for(ConnectionPoint&cp:connections){

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 1 #define VERSION_PATCH 1
#define VERSION_BUILD 5036 #define VERSION_BUILD 5056
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -86,7 +86,7 @@ ItemDatabase
Crafting Crafting
{ {
# When this crafting recipe is available. # When this crafting recipe is available.
AvailableChapter = 1 AvailableChapter = 2
Item[0] = Bear Claw,1 Item[0] = Bear Claw,1
Item[1] = Bear Blood,1 Item[1] = Bear Blood,1

Loading…
Cancel
Save