diff --git a/Crawler/BlacksmithCraftingWindow.cpp b/Crawler/BlacksmithCraftingWindow.cpp index 1ad3f32d..c6adf124 100644 --- a/Crawler/BlacksmithCraftingWindow.cpp +++ b/Crawler/BlacksmithCraftingWindow.cpp @@ -89,71 +89,75 @@ void Menu::InitializeBlacksmithCraftingWindow(){ return true; })END; armorTab->selectionType=SelectionType::HIGHLIGHT; + + #pragma region Weapon Inventory Display + auto weaponsDisplay=blacksmithWindow->ADD("Weapon Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", + [](MenuFuncData data){ + RowItemDisplay*comp=DYNAMIC_CAST(data.component); + const std::weak_ptritem=comp->GetItem(); + + std::string label=""; + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); + Menu::OpenMenu(CRAFT_ITEM); + return true; + }, + [](MenuFuncData data){ + RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); + Component(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem()); + return true; + }, + [](MenuFuncData data){ + Component(BLACKSMITH,"Item Icon")->SetItem(Item::BLANK); + return true; + }, + InventoryCreator::RowPlayerWeapons_InventoryUpdate, + {.padding=1,.size={207,28}} + )END; + AddInventoryListener(weaponsDisplay,"Equipment"); + weaponsDisplay->SetCompactDescriptions(CRAFTING_INFO); + #pragma endregion - auto weaponsDisplay=blacksmithWindow->ADD("Weapon Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", - [](MenuFuncData data){ - RowItemDisplay*comp=DYNAMIC_CAST(data.component); - const std::weak_ptritem=comp->GetItem(); - - std::string label=""; - if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ - label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); - } - Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); - Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); - Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); - Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); - Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); - Menu::OpenMenu(CRAFT_ITEM); - return true; - }, - [](MenuFuncData data){ - RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); - Component(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem()); - return true; - }, - [](MenuFuncData data){ - Component(BLACKSMITH,"Item Icon")->SetItem(Item::BLANK); - return true; - }, - InventoryCreator::RowPlayerWeapons_InventoryUpdate, - {.padding=1,.size={207,28}} - )END; - AddInventoryListener(weaponsDisplay,"Equipment"); - weaponsDisplay->SetCompactDescriptions(CRAFTING_INFO); - - auto armorDisplay=blacksmithWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", - [](MenuFuncData data){ - Menu::OpenMenu(CRAFT_ITEM); - RowItemDisplay*comp=DYNAMIC_CAST(data.component); - const std::weak_ptritem=comp->GetItem(); - - std::string label=""; - if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ - label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); - } - Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); - Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); - Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); - Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); - Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); - return true; - }, - [](MenuFuncData data){ - RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); - Component(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem()); - return true; - }, - [](MenuFuncData data){ - Component(BLACKSMITH,"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 region Armor Inventory Display + auto armorDisplay=blacksmithWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", + [](MenuFuncData data){ + Menu::OpenMenu(CRAFT_ITEM); + RowItemDisplay*comp=DYNAMIC_CAST(data.component); + const std::weak_ptritem=comp->GetItem(); + + std::string label=""; + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); + return true; + }, + [](MenuFuncData data){ + RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); + Component(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem()); + return true; + }, + [](MenuFuncData data){ + Component(BLACKSMITH,"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 region Inventory Description float inventoryDescriptionWidth=blacksmithWindow->pos.x+blacksmithWindow->size.x-26-224; diff --git a/Crawler/ConsumableCraftingWindow.cpp b/Crawler/ConsumableCraftingWindow.cpp new file mode 100644 index 00000000..e257860d --- /dev/null +++ b/Crawler/ConsumableCraftingWindow.cpp @@ -0,0 +1,185 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2018 - 2022 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. + +Portions of this software are copyright © 2023 The FreeType +Project (www.freetype.org). Please see LICENSE_FT.txt for more information. +All rights reserved. +*/ +#pragma endregion + +#include "Menu.h" +#include "Crawler.h" +#include "MenuItemItemButton.h" +#include "PlayerMoneyLabel.h" +#include "RowInventoryScrollableWindowComponent.h" +#include "EnhancementStatsLabel.h" +#include "RequiredMaterialsList.h" + +INCLUDE_game +INCLUDE_ITEM_CATEGORIES +INCLUDE_DATA +INCLUDE_GFX + +void Menu::InitializeConsumableCraftingWindow(){ + Menu*consumableCraftingWindow=CreateMenu(CRAFT_CONSUMABLE,CENTERED,game->GetScreenSize()-vi2d{52,52}); + + std::vector>categories; + std::vector>weaponInventory; + std::vector>armorInventory; + + #pragma region Build Equipment Lists + std::for_each(Inventory::get("Equipment").begin(),Inventory::get("Equipment").end(),[&](const std::shared_ptr 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(CRAFT_CONSUMABLE,"Armor Tab")->selected=false; + Component(CRAFT_CONSUMABLE,"Weapon Inventory Display")->Enable(true); + Component(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(CRAFT_CONSUMABLE,"Weapon Tab")->selected=false; + Component(CRAFT_CONSUMABLE,"Weapon Inventory Display")->Enable(false); + Component(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){ + RowItemDisplay*comp=DYNAMIC_CAST(data.component); + const std::weak_ptritem=comp->GetItem(); + + std::string label=""; + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); + Menu::OpenMenu(CRAFT_ITEM); + return true; + }, + [](MenuFuncData data){ + RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); + Component(CRAFT_CONSUMABLE,"Item Icon")->SetItem(rowItem->GetItem()); + return true; + }, + [](MenuFuncData data){ + Component(CRAFT_CONSUMABLE,"Item Icon")->SetItem(Item::BLANK); + return true; + }, + InventoryCreator::RowPlayerWeapons_InventoryUpdate, + {.padding=1,.size={207,28}} + )END; + AddInventoryListener(weaponsDisplay,"Equipment"); + weaponsDisplay->SetCompactDescriptions(CRAFTING_INFO); + #pragma endregion + + #pragma region Armor Inventory Display + auto armorDisplay=consumableCraftingWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,consumableCraftingWindow->size.y-44}},"Item Name Label","Item Description Label", + [](MenuFuncData data){ + Menu::OpenMenu(CRAFT_ITEM); + RowItemDisplay*comp=DYNAMIC_CAST(data.component); + const std::weak_ptritem=comp->GetItem(); + + std::string label=""; + if(item.lock()->EnhancementIsPossible()&&item.lock()->GetEnhancementInfo().size()>item.lock()->EnhancementLevel()+1){ + label=std::format("Level {} ->#00AA00 {}",item.lock()->EnhancementLevel(),item.lock()->EnhancementLevel()+1); + } + Component(CRAFT_ITEM,"Enhancement Level Header")->SetLabel(label); + Component(CRAFT_ITEM,"Item Name Header")->SetLabel(std::format("Crafting {}",item.lock()->DisplayName())); + Component(CRAFT_ITEM,"Enhancement Stats Label")->SetItem(item); + Component(CRAFT_ITEM,"Required Materials List")->SetItem(item); + Component(CRAFT_ITEM,"Craft Button")->SetGrayedOut(!item.lock()->CanEnhanceItem()); + return true; + }, + [](MenuFuncData data){ + RowItemDisplay*rowItem=DYNAMIC_CAST(data.component); + Component(CRAFT_CONSUMABLE,"Item Icon")->SetItem(rowItem->GetItem()); + return true; + }, + [](MenuFuncData data){ + Component(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 region Inventory Description + 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 Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)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; + #pragma endregion + + #pragma region Money Display + vf2d moneyIconPos={224+inventoryDescriptionWidth-24,28+consumableCraftingWindow->size.y-44+6}; + auto moneyIcon=consumableCraftingWindow->ADD("Money Icon",MenuIconButton)({moneyIconPos,{24,24}},GFX["money.png"].Decal(),DO_NOTHING,IconButtonAttr::NOT_SELECTABLE|IconButtonAttr::NO_OUTLINE|IconButtonAttr::NO_BACKGROUND)END; + std::string moneyText=std::to_string(game->GetPlayer()->GetMoney()); + vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*2; + auto moneyDisplay=consumableCraftingWindow->ADD("Money Label",PlayerMoneyLabel)({moneyIconPos-vf2d{2+moneyTextSize.x,-2},moneyTextSize},2,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; + moneyDisplay->SetRightAlignment(true); + Player::AddMoneyListener(moneyDisplay); + #pragma endregion + + consumableCraftingWindow->ADD("Leave Button",MenuComponent)({{consumableCraftingWindow->size.x/2-48,28+consumableCraftingWindow->size.y-44+6},{96,24}},"Leave",MenuType::ENUM_END, + [](MenuFuncData data){ + Menu::CloseMenu(); + return true; + },{2,2})END; +} \ No newline at end of file diff --git a/Crawler/CraftingRequirement.cpp b/Crawler/CraftingRequirement.cpp index b938cd2a..02d08dc8 100644 --- a/Crawler/CraftingRequirement.cpp +++ b/Crawler/CraftingRequirement.cpp @@ -37,10 +37,10 @@ All rights reserved. #pragma endregion #include "CraftingRequirement.h" -CraftingRequirement::CraftingRequirement(const std::vector&craftingItems,const uint32_t cost) +CraftingRequirement::CraftingRequirement(const std::vector>&craftingItems,const uint32_t cost) :craftingItems(craftingItems),cost(cost){} -const std::vector&CraftingRequirement::GetItems()const{ +const std::vector>&CraftingRequirement::GetItems()const{ return craftingItems; } const uint32_t CraftingRequirement::GetCost()const{ diff --git a/Crawler/CraftingRequirement.h b/Crawler/CraftingRequirement.h index de5fc0db..9927bfa7 100644 --- a/Crawler/CraftingRequirement.h +++ b/Crawler/CraftingRequirement.h @@ -39,10 +39,10 @@ All rights reserved. #include "Item.h" class CraftingRequirement{ - std::vectorcraftingItems; + std::vector>craftingItems; uint32_t cost; public: - CraftingRequirement(const std::vector&craftingItems,const uint32_t cost); - const std::vector&GetItems()const; + CraftingRequirement(const std::vector>&craftingItems,const uint32_t cost); + const std::vector>&GetItems()const; const uint32_t GetCost()const; }; \ No newline at end of file diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index 4efdc9e3..aa06174c 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -471,6 +471,7 @@ + @@ -607,6 +608,7 @@ + diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index 4751b516..10cf9119 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -644,6 +644,9 @@ Source Files\Interface + + Source Files\Interface + @@ -755,6 +758,9 @@ Configurations\Items + + Documentation\Menus + diff --git a/Crawler/EnhancementStatsLabel.h b/Crawler/EnhancementStatsLabel.h index 0770bbaf..b9c2b2d8 100644 --- a/Crawler/EnhancementStatsLabel.h +++ b/Crawler/EnhancementStatsLabel.h @@ -90,9 +90,9 @@ protected: std::string percentageSign=attr.DisplayAsPercent()?"%":""; window.DrawShadowStringDecal(drawPos+vf2d{maxAttributeLabelSize+4+24,yOffset},std::format("{:>5} ->#00AA00 {:<5}", - attr.ShowAsDecimal()?std::format("{:>4.1f}{}",value,percentageSign):std::format("{}{}",value,percentageSign), + attr.ShowAsDecimal()?std::format("{:>4.2f}{}",value,percentageSign):std::format("{}{}",value,percentageSign), nextStageValue!=0? - attr.ShowAsDecimal()?std::format("{:<4.1f}{}",nextStageValue,percentageSign):std::format("{}{}",nextStageValue,percentageSign) + attr.ShowAsDecimal()?std::format("{:<4.2f}{}",nextStageValue,percentageSign):std::format("{}{}",nextStageValue,percentageSign) :"MAX"), WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits::max():rect.size.x,1.0f); yOffset+=16; diff --git a/Crawler/Item.cpp b/Crawler/Item.cpp index 7ea26b03..fa24cec9 100644 --- a/Crawler/Item.cpp +++ b/Crawler/Item.cpp @@ -60,6 +60,7 @@ std::mapItemInfo::nameToEquipSlot; int Item::IsBlankStaticCallCounter=0; safemapStats::maxDamageReductionTable; ItemEnhancementFunctionPrimingData Item::enhanceFunctionPrimed("CanEnhanceItem()"); +std::vectorItemInfo::craftableConsumables; ItemInfo::ItemInfo() :customProps({nullptr,nullptr}),img(nullptr){} @@ -148,34 +149,47 @@ void ItemInfo::InitializeItems(){ if(statValueList.size()>0){ EnhancementInfo enhancementStats; for(int enhancementLevel=0;enhancementLevel<=10;enhancementLevel++){ + uint8_t availableChapter=1; datafile&dat=data[key]["StatValues["+std::to_string(enhancementLevel)+"]"]; int attrIndex=0; for(ItemAttribute&attr:statValueList){ enhancementStats.SetAttribute(enhancementLevel,attr,dat.GetReal(attrIndex)); attrIndex++; } - std::vectoritemsRequired; + std::vector>itemsRequired; uint32_t goldCost=0; if(enhancementLevel!=0){ //The first level does not require any crafting, skip this level. while(data[key]["Crafting"][std::format("Level[{}]",enhancementLevel)].HasProperty(std::format("Item[{}]",itemsRequired.size()))){ datafile&item=data[key]["Crafting"][std::format("Level[{}]",enhancementLevel)][std::format("Item[{}]",itemsRequired.size())]; - itemsRequired.push_back(Item(item.GetInt(1),item.GetString(0))); + itemsRequired.push_back({item.GetString(0),item.GetInt(1)}); } goldCost=data[key]["Crafting"][std::format("Level[{}]",enhancementLevel)]["Gold"].GetInt(); - }else - if(data[key].HasProperty("Crafting")&&!data[key]["Crafting"].HasProperty("Level[1]")){ - //If the item has a key called "Crafting" but did not specify a level number, then we assume this item just has one base level for normal crafting and thus we will add the requirements to craft this item under enhancement level 1. - while(data[key]["Crafting"].HasProperty(std::format("Item[{}]",itemsRequired.size()))){ - datafile&item=data[key]["Crafting"][std::format("Item[{}]",itemsRequired.size())]; - itemsRequired.push_back(Item(item.GetInt(1),item.GetString(0))); + if(data[key]["Crafting"][std::format("Level[{}]",enhancementLevel)].HasProperty("AvailableChapter")){ + availableChapter=data[key]["Crafting"][std::format("Level[{}]",enhancementLevel)]["AvailableChapter"].GetInt(); } - goldCost=data[key]["Crafting"]["Gold"].GetInt(); - enhancementLevel=1; + enhancementStats.SetCraftingRequirements(enhancementLevel,itemsRequired,goldCost,availableChapter); } - enhancementStats.SetCraftingRequirements(enhancementLevel,itemsRequired,goldCost); } it.enhancement=enhancementStats; } + + if(data[key].HasProperty("Crafting")&&!data[key]["Crafting"].HasProperty("Level[1]")){ + std::vector>itemsRequired; + uint32_t goldCost=0; + uint8_t availableChapter=1; + //If the item has a key called "Crafting" but did not specify a level number, then we assume this item just has one base level for normal crafting and thus we will add the requirements to craft this item under enhancement level 1. + while(data[key]["Crafting"].HasProperty(std::format("Item[{}]",itemsRequired.size()))){ + datafile&item=data[key]["Crafting"][std::format("Item[{}]",itemsRequired.size())]; + itemsRequired.push_back({item.GetString(0),item.GetInt(1)}); + } + goldCost=data[key]["Crafting"]["Gold"].GetInt(); + if(data[key]["Crafting"].HasProperty("AvailableChapter")){ + availableChapter=data[key]["Crafting"]["AvailableChapter"].GetInt(); + } + craftableConsumables.push_back(&it); + it.enhancement.SetCraftingRequirements(1,itemsRequired,goldCost,availableChapter); + } + if(scriptName!=""){ if(scriptName=="RestoreDuringCast"){ useDuringCast=true; @@ -533,17 +547,18 @@ const std::string Item::Description(CompactText compact)const{ description+="\n\nCrafting Requirements:\n---------\n"; if(IsEquippable()&&EnhancementLevel()<"Item.Item Max Enhancement Level"_I||IsCraftable()){ const EnhancementLevelInfo&info=GetEnhancementInfo()[EnhancementLevel()+1]; - for(const Item&itemRequirement:info.craftingRequirement.GetItems()){ + for(const auto&[name,amt]:info.craftingRequirement.GetItems()){ description+=std::format("{}{} x{} ({})\n", - Inventory::GetItemCount(itemRequirement.ActualName())GetPlayer()->GetMoney()GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost()); }; @@ -890,7 +905,7 @@ void Stats::InitializeDamageReductionTable(){ } } -void EnhancementInfo::SetCraftingRequirements(const int enhanceLevel,const std::vector&requiredItems,const uint32_t goldCost){ +void EnhancementInfo::SetCraftingRequirements(const int enhanceLevel,const std::vector>&requiredItems,const uint32_t goldCost,const uint8_t availableChapter){ while(craftingRequirements.size()<=enhanceLevel){ craftingRequirements.push_back(CraftingRequirement({},0)); } @@ -903,11 +918,14 @@ EnhancementLevelInfo::EnhancementLevelInfo(const Stats&stats,const CraftingRequi const bool Item::CanEnhanceItem()const{ if(ISBLANK(std::make_shared(*this)))return false; if(!GetEnhancementInfo().CanBeEnhanced())return false; + if(GetEnhancementInfo().AvailableChapter()GetCurrentChapter())return false; const EnhancementLevelInfo&enhanceInfo=GetEnhancementInfo()[EnhancementLevel()+1]; - if(EnhancementLevel()>="Item.Item Max Enhancement Level"_I)return false; + if(GetEnhancementInfo().size()>2){ //If the item has exactly 2 enhancement levels, then it's an item that can only simply be crafted. Therefore, don't do the max enhancement level check. + if(EnhancementLevel()>="Item.Item Max Enhancement Level"_I)return false; + } if(game->GetPlayer()->GetMoney()IsCraftable(); +} + +const uint8_t EnhancementInfo::AvailableChapter()const{ + return availableChapter; } \ No newline at end of file diff --git a/Crawler/Item.h b/Crawler/Item.h index 6999b596..791a9c1c 100644 --- a/Crawler/Item.h +++ b/Crawler/Item.h @@ -118,10 +118,12 @@ struct EnhancementInfo{ private: std::vectorenhancementStats; std::vectorcraftingRequirements; + uint8_t availableChapter=1; public: void SetAttribute(int enhanceLevel,ItemAttribute attribute,float value); - void SetCraftingRequirements(const int enhanceLevel,const std::vector&requiredItems,const uint32_t goldCost); + void SetCraftingRequirements(const int enhanceLevel,const std::vector>&requiredItems,const uint32_t goldCost,const uint8_t availableChapter); const bool CanBeEnhanced()const; + const uint8_t AvailableChapter()const; const EnhancementLevelInfo operator[](int level)const; const size_t size()const; }; @@ -285,6 +287,7 @@ private: static void InitializeScripts(); static void InitializeSets(); static std::mapnameToEquipSlot; + static std::vectorcraftableConsumables; public: static void InitializeItems(); ItemInfo(); diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 62dbd02f..aa71127f 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -108,6 +108,7 @@ void Menu::InitializeMenus(){ InitializeSellItemWindow(); InitializeBlacksmithCraftingWindow(); InitializeCraftItemWindow(); + InitializeConsumableCraftingWindow(); for(MenuType type=MenuType(int(MenuType::ENUM_START)+1);typeOnEquipStatsUpdate(); } -} +} + const float&EntityStats::GetStat(ItemAttribute stat)const{ return equipStats.A_Read(stat); } + const float&EntityStats::GetStat(std::string_view stat)const{ return equipStats.A_Read(stat); } + const float&EntityStats::GetBaseStat(ItemAttribute stat)const{ return baseStats.A_Read(stat); } + const float&EntityStats::GetBaseStat(std::string_view stat)const{ return baseStats.A_Read(stat); } diff --git a/Crawler/RequiredMaterialsList.h b/Crawler/RequiredMaterialsList.h index a62229e4..e0958ed9 100644 --- a/Crawler/RequiredMaterialsList.h +++ b/Crawler/RequiredMaterialsList.h @@ -68,13 +68,13 @@ protected: if(itemRef.lock()->EnhancementIsPossible()&&itemRef.lock()->GetEnhancementInfo().size()>itemRef.lock()->EnhancementLevel()+1){ float drawWidth=rect.size.x/3; int index=0; - for(const auto&item:itemRef.lock()->GetEnhancementInfo()[itemRef.lock()->EnhancementLevel()+1].craftingRequirement.GetItems()){ + for(const auto&[name,amt]:itemRef.lock()->GetEnhancementInfo()[itemRef.lock()->EnhancementLevel()+1].craftingRequirement.GetItems()){ Pixel textCol=WHITE; - if(Inventory::GetItemCount(item.ActualName())GetTextSizeProp(labelText).x; - window.DrawShadowStringDecal(drawPos,std::format("{:>3}",item.Amt()),textCol,BLACK); + window.DrawShadowStringDecal(drawPos,std::format("{:>3}",amt),textCol,BLACK); window.DrawShadowStringPropDecal(drawPos+vf2d{26,0},labelText,textCol,BLACK,{std::min(1.f,(drawWidth-26-2)/labelWidth),1.f}); index++; } diff --git a/Crawler/RowItemDisplay.h b/Crawler/RowItemDisplay.h index a5221eb5..f1688a9d 100644 --- a/Crawler/RowItemDisplay.h +++ b/Crawler/RowItemDisplay.h @@ -70,7 +70,8 @@ public: MenuComponent::DrawDecal(window,focused); if(!canEnhance&&fadeOutIfMissingRequirements){ - window.FillRectDecal(rect.pos+vf2d{1,1},rect.size-vf2d{1,1},VERY_DARK_GREY); + Pixel col=PixelLerp(VERY_DARK_GREY,DARK_GREY,hoverEffect/"ThemeGlobal.HighlightTime"_F); + window.FillRectDecal(rect.pos+vf2d{1,1},rect.size-vf2d{1,1},col); } float scaleFactor=(rect.size.y-4)/24; diff --git a/Crawler/TODO.txt b/Crawler/TODO.txt index a7edb971..a2a23f60 100644 --- a/Crawler/TODO.txt +++ b/Crawler/TODO.txt @@ -41,4 +41,5 @@ Story proofreading/correcting/storyboarding - Add a command to play sound effects/music. - Game Controller Support - Should use the Keybind structure that already exists. -- Loading Screen \ No newline at end of file +- Loading Screen +- Title Screen setpieces \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index fb5a8b3e..fc9ad8a6 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 5026 +#define VERSION_BUILD 5036 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/assets/config/Monsters.txt b/Crawler/assets/config/Monsters.txt index 2c730255..2bd9e346 100644 --- a/Crawler/assets/config/Monsters.txt +++ b/Crawler/assets/config/Monsters.txt @@ -27,6 +27,7 @@ Monsters # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity DROP[0] = Green Slime Remains,65%,1,2 DROP[1] = Minor Health Potion,5%,1,1 + DROP[2] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0]. Order is: # Frame Count, Frame Speed (s), Frame Cycling (Repeat,OneShot,PingPong,Reverse) @@ -58,6 +59,7 @@ Monsters # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity DROP[0] = Blue Slime Remains,65%,1,2 DROP[1] = Minor Health Potion,5%,1,1 + DROP[2] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0] #ANIMATION[0] = MY_NEW_ANIMATION @@ -88,6 +90,7 @@ Monsters # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity DROP[0] = Red Slime Remains,65%,1,2 DROP[1] = Minor Health Potion,5%,1,1 + DROP[2] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0] #ANIMATION[0] = MY_NEW_ANIMATION @@ -116,7 +119,7 @@ Monsters DeathAnimation = 10, 0.1, OneShot # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity - #DROP[0] = Bandages,30%,1,1 + DROP[0] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0] #ANIMATION[0] = MY_NEW_ANIMATION @@ -146,7 +149,7 @@ Monsters # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity DROP[0] = Bandages,30%,1,1 - DROP[1] = Shell Helmet,100%,1,1 + DROP[1] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0] #ANIMATION[0] = MY_NEW_ANIMATION @@ -176,7 +179,7 @@ Monsters DeathAnimation = 10, 0.1, OneShot # Drop Item Name, Drop Percentage(0-100%), Drop Min Quantity, Drop Max Quantity - #DROP[0] = Bandages,30%,1,1 + DROP[0] = Berries,5%,1,1 #Additional custom animations go down below. Start with ANIMATION[0] ANIMATION[0] = monsters/Slime King - Cast.png diff --git a/Crawler/assets/config/items/ItemDatabase.txt b/Crawler/assets/config/items/ItemDatabase.txt index 50a7438d..4892d3a1 100644 --- a/Crawler/assets/config/items/ItemDatabase.txt +++ b/Crawler/assets/config/items/ItemDatabase.txt @@ -10,12 +10,6 @@ ItemDatabase Cooldown Time = 5.0 Cast Time = 0.0 SellValue = 8 - Crafting - { - Item[0] = Green Slime Remains,2 - - Gold = 8 - } } Minor Health Potion { @@ -27,6 +21,16 @@ ItemDatabase Cast Time = 0.0 SellValue = 16 BuyValue = 23 + Crafting + { + # When this crafting recipe is available. + AvailableChapter = 1 + + Item[0] = Green Slime Remains,3 + Item[1] = Blue Slime Remains,1 + + Gold = 0 + } } Minor Mana Potion { @@ -38,6 +42,16 @@ ItemDatabase Cast Time = 0.0 SellValue = 21 BuyValue = 30 + Crafting + { + # When this crafting recipe is available. + AvailableChapter = 1 + + Item[0] = Red Slime Remains,1 + Item[1] = Yellow Slime Remains,1 + + Gold = 0 + } } Minor Recovery Potion { @@ -47,6 +61,18 @@ ItemDatabase ItemCategory = Consumables Cooldown Time = 5.0 Cast Time = 0.0 + SellValue = 15 + Crafting + { + # When this crafting recipe is available. + AvailableChapter = 1 + + Item[0] = Blue Slime Remains,1 + Item[1] = Red Slime Remains,1 + Item[2] = Flower Petals,1 + + Gold = 0 + } } Elixir of Bear Strength { @@ -56,6 +82,17 @@ ItemDatabase ItemCategory = Consumables Cooldown Time = 5.0 Cast Time = 0.0 + SellValue = 30 + Crafting + { + # When this crafting recipe is available. + AvailableChapter = 1 + + Item[0] = Bear Claw,1 + Item[1] = Bear Blood,1 + + Gold = 0 + } } Bandages {