Implemented split between consumable crafting initialization and equipment enhancement initialization.

pull/28/head
sigonasr2 11 months ago
parent b02936fcb5
commit 4e3c9877e7
  1. 132
      Crawler/BlacksmithCraftingWindow.cpp
  2. 185
      Crawler/ConsumableCraftingWindow.cpp
  3. 4
      Crawler/CraftingRequirement.cpp
  4. 6
      Crawler/CraftingRequirement.h
  5. 2
      Crawler/Crawler.vcxproj
  6. 6
      Crawler/Crawler.vcxproj.filters
  7. 4
      Crawler/EnhancementStatsLabel.h
  8. 70
      Crawler/Item.cpp
  9. 5
      Crawler/Item.h
  10. 1
      Crawler/Menu.cpp
  11. 2
      Crawler/Menu.h
  12. 12
      Crawler/Merchant's Items.txt
  13. 6
      Crawler/Player.cpp
  14. 8
      Crawler/RequiredMaterialsList.h
  15. 3
      Crawler/RowItemDisplay.h
  16. 3
      Crawler/TODO.txt
  17. 2
      Crawler/Version.h
  18. 9
      Crawler/assets/config/Monsters.txt
  19. 49
      Crawler/assets/config/items/ItemDatabase.txt

@ -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<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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());
Menu::OpenMenu(CRAFT_ITEM);
return true;
},
[](MenuFuncData data){
RowItemDisplay*rowItem=DYNAMIC_CAST<RowItemDisplay*>(data.component);
Component<MenuItemItemButton>(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem());
return true;
},
[](MenuFuncData data){
Component<MenuItemItemButton>(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<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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());
Menu::OpenMenu(CRAFT_ITEM);
return true;
},
[](MenuFuncData data){
RowItemDisplay*rowItem=DYNAMIC_CAST<RowItemDisplay*>(data.component);
Component<MenuItemItemButton>(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem());
return true;
},
[](MenuFuncData data){
Component<MenuItemItemButton>(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<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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>(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem());
return true;
},
[](MenuFuncData data){
Component<MenuItemItemButton>(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<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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>(BLACKSMITH,"Item Icon")->SetItem(rowItem->GetItem());
return true;
},
[](MenuFuncData data){
Component<MenuItemItemButton>(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;

@ -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<std::pair<std::string,int>>categories;
std::vector<std::weak_ptr<Item>>weaponInventory;
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){
RowItemDisplay*comp=DYNAMIC_CAST<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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());
Menu::OpenMenu(CRAFT_ITEM);
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::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<RowItemDisplay*>(data.component);
const std::weak_ptr<Item>item=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<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 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;
}

@ -37,10 +37,10 @@ All rights reserved.
#pragma endregion
#include "CraftingRequirement.h"
CraftingRequirement::CraftingRequirement(const std::vector<Item>&craftingItems,const uint32_t cost)
CraftingRequirement::CraftingRequirement(const std::vector<std::pair<IT,int>>&craftingItems,const uint32_t cost)
:craftingItems(craftingItems),cost(cost){}
const std::vector<Item>&CraftingRequirement::GetItems()const{
const std::vector<std::pair<IT,int>>&CraftingRequirement::GetItems()const{
return craftingItems;
}
const uint32_t CraftingRequirement::GetCost()const{

@ -39,10 +39,10 @@ All rights reserved.
#include "Item.h"
class CraftingRequirement{
std::vector<Item>craftingItems;
std::vector<std::pair<IT,int>>craftingItems;
uint32_t cost;
public:
CraftingRequirement(const std::vector<Item>&craftingItems,const uint32_t cost);
const std::vector<Item>&GetItems()const;
CraftingRequirement(const std::vector<std::pair<IT,int>>&craftingItems,const uint32_t cost);
const std::vector<std::pair<IT,int>>&GetItems()const;
const uint32_t GetCost()const;
};

@ -471,6 +471,7 @@
<ClCompile Include="ChargedArrow.cpp" />
<ClCompile Include="ClassSelectionWindow.cpp" />
<ClCompile Include="ConnectionPoint.cpp" />
<ClCompile Include="ConsumableCraftingWindow.cpp" />
<ClCompile Include="CraftingRequirement.cpp">
<SubType>
</SubType>
@ -607,6 +608,7 @@
<Text Include="assets\config\story\Chapter 1.txt" />
<Text Include="Crawler_Story_Chapter_1 (2).txt" />
<Text Include="Crawler_System_Overview.txt" />
<Text Include="Merchant%27s Items.txt" />
<Text Include="NewClasses.txt" />
<Text Include="InitialConcept.txt" />
<Text Include="Slime_King_Encounter.txt" />

@ -644,6 +644,9 @@
<ClCompile Include="CraftItemWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
<ClCompile Include="ConsumableCraftingWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
@ -755,6 +758,9 @@
<Text Include="assets\config\items\Weapons.txt">
<Filter>Configurations\Items</Filter>
</Text>
<Text Include="Merchant%27s Items.txt">
<Filter>Documentation\Menus</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<Image Include="assets\heart.ico">

@ -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<float>::max():rect.size.x,1.0f);
yOffset+=16;

@ -60,6 +60,7 @@ std::map<std::string,EquipSlot>ItemInfo::nameToEquipSlot;
int Item::IsBlankStaticCallCounter=0;
safemap<int,float>Stats::maxDamageReductionTable;
ItemEnhancementFunctionPrimingData Item::enhanceFunctionPrimed("CanEnhanceItem()");
std::vector<ItemInfo*>ItemInfo::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::vector<Item>itemsRequired;
std::vector<std::pair<IT,int>>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<std::pair<IT,int>>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())<itemRequirement.Amt()?"#FF0000":"#FFFFFF",
itemRequirement.DisplayName(),
itemRequirement.Amt(),
Inventory::GetItemCount(itemRequirement.ActualName()));
Inventory::GetItemCount(name)<amt?"#FF0000":"#FFFFFF",
name,
amt,
Inventory::GetItemCount(name));
}
description+="\n";
description+=std::format("{}Crafting Cost: {}",
description+=std::format("{}Crafting Cost: {} {}",
game->GetPlayer()->GetMoney()<info.craftingRequirement.GetCost()?"#FF0000":"#FFFFFF",
info.craftingRequirement.GetCost());
info.craftingRequirement.GetCost(),
"Item.Currency Name"_S);
}
}
}
@ -758,8 +773,8 @@ void Item::EnhanceItem(){
const CraftingRequirement&consumedResources=GetEnhancementInfo()[EnhancementLevel()].craftingRequirement;
for(const Item&it:consumedResources.GetItems()){
Inventory::RemoveItem(it.ActualName(),it.Amt());
for(const auto&[name,amt]:consumedResources.GetItems()){
Inventory::RemoveItem(name,amt);
}
game->GetPlayer()->SetMoney(game->GetPlayer()->GetMoney()-consumedResources.GetCost());
};
@ -890,7 +905,7 @@ void Stats::InitializeDamageReductionTable(){
}
}
void EnhancementInfo::SetCraftingRequirements(const int enhanceLevel,const std::vector<Item>&requiredItems,const uint32_t goldCost){
void EnhancementInfo::SetCraftingRequirements(const int enhanceLevel,const std::vector<std::pair<IT,int>>&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<Item>(*this)))return false;
if(!GetEnhancementInfo().CanBeEnhanced())return false;
if(GetEnhancementInfo().AvailableChapter()<game->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()<enhanceInfo.craftingRequirement.GetCost())return false;
for(const Item&it:enhanceInfo.craftingRequirement.GetItems()){
if(Inventory::GetItemCount(it.ActualName())<it.Amt()){
for(const auto&[name,amt]:enhanceInfo.craftingRequirement.GetItems()){
if(Inventory::GetItemCount(name)<amt){
return false;
}
}
@ -960,4 +978,8 @@ const bool ItemInfo::IsCraftable()const{
const bool Item::EnhancementIsPossible()const{
return it->IsCraftable();
}
const uint8_t EnhancementInfo::AvailableChapter()const{
return availableChapter;
}

@ -118,10 +118,12 @@ struct EnhancementInfo{
private:
std::vector<Stats>enhancementStats;
std::vector<CraftingRequirement>craftingRequirements;
uint8_t availableChapter=1;
public:
void SetAttribute(int enhanceLevel,ItemAttribute attribute,float value);
void SetCraftingRequirements(const int enhanceLevel,const std::vector<Item>&requiredItems,const uint32_t goldCost);
void SetCraftingRequirements(const int enhanceLevel,const std::vector<std::pair<IT,int>>&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::map<std::string,EquipSlot>nameToEquipSlot;
static std::vector<ItemInfo*>craftableConsumables;
public:
static void InitializeItems();
ItemInfo();

@ -108,6 +108,7 @@ void Menu::InitializeMenus(){
InitializeSellItemWindow();
InitializeBlacksmithCraftingWindow();
InitializeCraftItemWindow();
InitializeConsumableCraftingWindow();
for(MenuType type=MenuType(int(MenuType::ENUM_START)+1);type<MenuType::ENUM_END;type=MenuType(int(type+1))){
if(menus.count(type)==0){

@ -77,6 +77,7 @@ enum MenuType{
SELL_ITEM,
BLACKSMITH,
CRAFT_ITEM,
CRAFT_CONSUMABLE,
#pragma region Enum End //DO NOT REMOVE
///////////////////////////////////////////////////////////
/*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
@ -100,6 +101,7 @@ class Menu:public IAttributable{
static void InitializeSellItemWindow();
static void InitializeBlacksmithCraftingWindow();
static void InitializeCraftItemWindow();
static void InitializeConsumableCraftingWindow();
friend class Crawler;
friend struct Player;

@ -0,0 +1,12 @@
Merchants items
Minor Health Potion (s: 16g b: 23g) // Buyable or crafted with 3x Green Slime Remains + 1 Blue Slime Remains
Minor Mana Potion (s: 21g b: 30g) // Buyable or crafted with 1 Red Slime Remains + 1 Yellow Slime Remains
Bandages (s: 7g b: 10g) // Buyable
other Consumables
Berries (s: 8g) // 5% dropp from every Flower or Slime
Elixir of Bear Strength (s: 30g) // crafted with 1 Bear Claw + 1 Bear Blood
Minor Recovery Potion (s: 15g) // crafted with 1 Blue Slime Remains, 1 Red Slime Remains and 1 Flower Petal"
Only for 4 potions to craft in chapter 1.
But guess if every chapter has 4-5 potions that should be enough

@ -946,16 +946,20 @@ void EntityStats::RecalculateEquipStats(){
for(MenuComponent*component:Menu::equipStatListeners){
component->OnEquipStatsUpdate();
}
}
}
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);
}

@ -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())<item.Amt())textCol=RED;
if(Inventory::GetItemCount(name)<amt)textCol=RED;
vf2d drawPos=rect.pos+vf2d{drawWidth*(index%3),12.f*(index/3)};
std::string labelText=std::format("{}",item.DisplayName());
std::string labelText=std::format("{}",name);
float labelWidth=game->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++;
}

@ -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;

@ -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
- Loading Screen
- Title Screen setpieces

@ -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

@ -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

@ -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
{

Loading…
Cancel
Save