Implemented Crafting enhancement window, item enhancement checks, and enhancement implementation done.

pull/28/head
sigonasr2 11 months ago
parent 8f41870b46
commit 64694e1b63
  1. 28
      Crawler/BlacksmithCraftingWindow.cpp
  2. 71
      Crawler/CraftItemWindow.cpp
  3. 12
      Crawler/Crawler.vcxproj
  4. 9
      Crawler/Crawler.vcxproj.filters
  5. 106
      Crawler/EnhancementStatsLabel.h
  6. 9
      Crawler/Item.cpp
  7. 4
      Crawler/Item.h
  8. 1
      Crawler/Menu.cpp
  9. 2
      Crawler/Menu.h
  10. 13
      Crawler/MenuComponent.h
  11. 25
      Crawler/MenuLabel.h
  12. 93
      Crawler/RequiredMaterialsList.h
  13. 2
      Crawler/Version.h
  14. 3
      Crawler/assets/config/items/Weapons.txt
  15. 2
      Crawler/assets/config/items/items.txt

@ -41,6 +41,8 @@ All rights reserved.
#include "MenuItemItemButton.h" #include "MenuItemItemButton.h"
#include "PlayerMoneyLabel.h" #include "PlayerMoneyLabel.h"
#include "RowInventoryScrollableWindowComponent.h" #include "RowInventoryScrollableWindowComponent.h"
#include "EnhancementStatsLabel.h"
#include "RequiredMaterialsList.h"
INCLUDE_game INCLUDE_game
INCLUDE_ITEM_CATEGORIES INCLUDE_ITEM_CATEGORIES
@ -90,6 +92,19 @@ void Menu::InitializeBlacksmithCraftingWindow(){
auto weaponsDisplay=blacksmithWindow->ADD("Weapon Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", auto weaponsDisplay=blacksmithWindow->ADD("Weapon Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label",
[](MenuFuncData data){ [](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; return true;
}, },
[](MenuFuncData data){ [](MenuFuncData data){
@ -109,6 +124,19 @@ void Menu::InitializeBlacksmithCraftingWindow(){
auto armorDisplay=blacksmithWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label", auto armorDisplay=blacksmithWindow->ADD("Armor Inventory Display",RowInventoryScrollableWindowComponent)({{2,28},{220,blacksmithWindow->size.y-44}},"Item Name Label","Item Description Label",
[](MenuFuncData data){ [](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; return true;
}, },
[](MenuFuncData data){ [](MenuFuncData data){

@ -0,0 +1,71 @@
#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 "EnhancementStatsLabel.h"
#include "RequiredMaterialsList.h"
void Menu::InitializeCraftItemWindow(){
Menu*craftItemWindow=CreateMenu(CRAFT_ITEM,CENTERED,{240,120});
craftItemWindow->ADD("Item Name Header",MenuLabel)({{2,-16},{craftItemWindow->size.x-4,12}},"Item Name",1.0f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
craftItemWindow->ADD("Enhancement Level Header",MenuLabel)({{2,0},{craftItemWindow->size.x-4,12}},"Level X ->#00AA00 Y",1.f,ComponentAttr::SHADOW|ComponentAttr::FIXED_WIDTH_FONT)END;
craftItemWindow->ADD("Enhancement Stats Label",EnhancementStatsLabel)({{2,16},{craftItemWindow->size.x-4,72}},Item::BLANK,1.f)END;
craftItemWindow->ADD("Materials Requirement Outline",MenuComponent)({{2,86},{craftItemWindow->size.x-4,26}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
craftItemWindow->ADD("Required Materials Label",MenuLabel)({{4,80},{craftItemWindow->size.x-8,0}},"Required Materials",1.0f,ComponentAttr::SHADOW)END;
craftItemWindow->ADD("Required Materials List",RequiredMaterialsList)({{4,88},{craftItemWindow->size.x-8,22}},Item::BLANK)END;
craftItemWindow->ADD("Back Button",MenuComponent)({{36,116},{48,12}},"Back",[](MenuFuncData data){Menu::CloseMenu();return true;})END;
craftItemWindow->ADD("Craft Button",MenuComponent)({{craftItemWindow->size.x-84,116},{48,12}},"Craft",[](MenuFuncData data){
const std::weak_ptr<Item>item=Component<EnhancementStatsLabel>(data.menu.GetType(),"Enhancement Stats Label")->GetItem();
if(item.lock()->CanEnhanceItem()){
item.lock()->EnhanceItem();
}
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>(data.menu.GetType(),"Enhancement Level Header")->SetLabel(label);
data.component->SetGrayedOut(!item.lock()->CanEnhanceItem());
return true;
})END;
}

@ -333,6 +333,10 @@
<ClInclude Include="Effect.h" /> <ClInclude Include="Effect.h" />
<ClInclude Include="Emitter.h" /> <ClInclude Include="Emitter.h" />
<ClInclude Include="EncountersSpawnListScrollableWindowComponent.h" /> <ClInclude Include="EncountersSpawnListScrollableWindowComponent.h" />
<ClInclude Include="EnhancementStatsLabel.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="EquipSlotButton.h"> <ClInclude Include="EquipSlotButton.h">
<SubType> <SubType>
</SubType> </SubType>
@ -401,6 +405,10 @@
<SubType> <SubType>
</SubType> </SubType>
</ClInclude> </ClInclude>
<ClInclude Include="RequiredMaterialsList.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="resource1.h" /> <ClInclude Include="resource1.h" />
<ClInclude Include="RowInventoryScrollableWindowComponent.h"> <ClInclude Include="RowInventoryScrollableWindowComponent.h">
@ -467,6 +475,10 @@
<SubType> <SubType>
</SubType> </SubType>
</ClCompile> </ClCompile>
<ClCompile Include="CraftItemWindow.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="Crawler.cpp" /> <ClCompile Include="Crawler.cpp" />
<ClCompile Include="DamageNumber.cpp" /> <ClCompile Include="DamageNumber.cpp" />
<ClCompile Include="discord-files\achievement_manager.cpp" /> <ClCompile Include="discord-files\achievement_manager.cpp" />

@ -381,6 +381,12 @@
<ClInclude Include="InventoryCreator.h"> <ClInclude Include="InventoryCreator.h">
<Filter>Header Files\Interface</Filter> <Filter>Header Files\Interface</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="EnhancementStatsLabel.h">
<Filter>Header Files\Interface</Filter>
</ClInclude>
<ClInclude Include="RequiredMaterialsList.h">
<Filter>Header Files\Interface</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Player.cpp"> <ClCompile Include="Player.cpp">
@ -635,6 +641,9 @@
<ClCompile Include="InventoryCreator.cpp"> <ClCompile Include="InventoryCreator.cpp">
<Filter>Source Files\Interface</Filter> <Filter>Source Files\Interface</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="CraftItemWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />

@ -0,0 +1,106 @@
#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
#pragma once
#include "MenuLabel.h"
#include "Item.h"
class EnhancementStatsLabel:public MenuLabel{
std::weak_ptr<Item>itemRef;
public:
inline EnhancementStatsLabel(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,float scale=1,ComponentAttr attributes=ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)
:MenuLabel(rect,"",scale,attributes),itemRef(itemRef){}
inline void SetItem(const std::weak_ptr<Item>itemRef){
this->itemRef=itemRef;
}
inline const std::weak_ptr<Item>GetItem()const{
return itemRef;
}
protected:
inline virtual void DrawDecal(ViewPort&window,bool focused)override final{
MenuComponent::DrawDecal(window,focused);
vf2d adjustedScale={scale,scale};
vf2d labelTextSize=vf2d(game->GetWrappedTextSizeProp(label,rect.size.x,adjustedScale));
if(fitToLabel){
float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2);
if(sizeRatio>1){
adjustedScale.x/=sizeRatio;
}
labelTextSize=vf2d(game->GetTextSizeProp(label)*adjustedScale);
}
vf2d drawPos=rect.middle()-vf2d{labelTextSize}/2; //Assume centered.
if(!centered){
drawPos=vf2d{rect.pos.x+2,rect.pos.y};
}
if(itemRef.lock()->EnhancementIsPossible()){
float maxAttributeLabelSize=0;
std::for_each(itemRef.lock()->GetEnhancementInfo()[1].stats.begin(),itemRef.lock()->GetEnhancementInfo()[1].stats.end(),[&](const auto&data){
auto&attr=data.first;
maxAttributeLabelSize=std::max(maxAttributeLabelSize,float(game->GetWrappedTextSizeProp(std::format("{}",attr.Name()),rect.size.x,adjustedScale).x));
});
for(float yOffset=0;const auto&[attr,value]:itemRef.lock()->GetEnhancementInfo()[itemRef.lock()->EnhancementLevel()].stats){
std::string attributeLabel=std::format("{}",attr.Name());
float attributeLabelWidth=game->GetTextSizeProp(attributeLabel).x;
window.DrawShadowStringPropDecal(drawPos+vf2d{maxAttributeLabelSize/2+24,yOffset}-vf2d{attributeLabelWidth/2,0},attributeLabel,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
uint8_t nextEnhanceLevel=itemRef.lock()->EnhancementLevel()+1;
float nextStageValue=0;
if(itemRef.lock()->GetEnhancementInfo().size()>nextEnhanceLevel){
nextStageValue=itemRef.lock()->GetEnhancementInfo()[nextEnhanceLevel].stats.get_readOnly(attr);
}
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),
nextStageValue!=0?
attr.ShowAsDecimal()?std::format("{:<4.1f}{}",nextStageValue,percentageSign):std::format("{}{}",nextStageValue,percentageSign)
:"MAX"),
WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
yOffset+=16;
}
}else{
std::string text="Cannot be enhanced.";
float textWidth=game->GetTextSizeProp(text).x;
window.DrawShadowStringPropDecal(rect.middle()-vf2d{textWidth,0}/2,text,RED,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
}
}
};

@ -901,12 +901,13 @@ EnhancementLevelInfo::EnhancementLevelInfo(const Stats&stats,const CraftingRequi
:stats(stats),craftingRequirement(craftingRequirement){} :stats(stats),craftingRequirement(craftingRequirement){}
const bool Item::CanEnhanceItem()const{ const bool Item::CanEnhanceItem()const{
if(ISBLANK(std::make_shared<Item>(*this)))return false;
if(!GetEnhancementInfo().CanBeEnhanced())return false; if(!GetEnhancementInfo().CanBeEnhanced())return false;
const EnhancementLevelInfo&enhanceInfo=GetEnhancementInfo()[EnhancementLevel()+1]; const EnhancementLevelInfo&enhanceInfo=GetEnhancementInfo()[EnhancementLevel()+1];
if(EnhancementLevel()>="Item.Item Max Enhancement Level"_I)return false; if(EnhancementLevel()>="Item.Item Max Enhancement Level"_I)return false;
if(game->GetPlayer()->GetMoney()<enhanceInfo.craftingRequirement.GetCost())return false; if(game->GetPlayer()->GetMoney()<enhanceInfo.craftingRequirement.GetCost())return false;
for(const Item&it:enhanceInfo.craftingRequirement.GetItems()){ for(const Item&it:enhanceInfo.craftingRequirement.GetItems()){
if(Inventory::GetItemCount(ActualName())<it.Amt()){ if(Inventory::GetItemCount(it.ActualName())<it.Amt()){
return false; return false;
} }
} }
@ -954,5 +955,9 @@ const bool Item::IsCraftable()const{
return it->IsCraftable(); return it->IsCraftable();
} }
const bool ItemInfo::IsCraftable()const{ const bool ItemInfo::IsCraftable()const{
return GetEnhancementInfo().CanBeEnhanced(); return GetEnhancementInfo().CanBeEnhanced();
}
const bool Item::EnhancementIsPossible()const{
return it->IsCraftable();
} }

@ -181,7 +181,11 @@ public:
//Use ISBLANK macro instead!! This should not be called directly!! //Use ISBLANK macro instead!! This should not be called directly!!
const bool IsBlank()const; const bool IsBlank()const;
const uint8_t EnhancementLevel()const; const uint8_t EnhancementLevel()const;
//NOTE: This function must be primed with CanEnhanceItem()! Otherwise it will cause a runtime error.
void EnhanceItem(); void EnhanceItem();
//Whether or not this item can be enhanced/crafted.
const bool EnhancementIsPossible()const;
//A verification function that confirms if we are allowed to perform an enhancement. MUST BE CALLED to prime EnhanceItem() function!!
const bool CanEnhanceItem()const; const bool CanEnhanceItem()const;
static std::shared_ptr<Item>BLANK; static std::shared_ptr<Item>BLANK;
const std::optional<const::ItemSet*const>ItemSet()const; const std::optional<const::ItemSet*const>ItemSet()const;

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

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

@ -47,12 +47,13 @@ enum class ButtonAttr{
}; };
enum class ComponentAttr{ enum class ComponentAttr{
NONE= 0b000000, NONE= 0b0'0000'0000,
LEFT_ALIGN= 0b000001, //Labels are centered by default. LEFT_ALIGN= 0b0'0000'0001, //Labels are centered by default.
SHADOW= 0b000010, //Adds shadows to the label text. SHADOW= 0b0'0000'0010, //Adds shadows to the label text.
OUTLINE= 0b000100, //Adds an outline around the component. OUTLINE= 0b0'0000'0100, //Adds an outline around the component.
BACKGROUND= 0b001000, //Renders the background of the menu theme for this component. BACKGROUND= 0b0'0000'1000, //Renders the background of the menu theme for this component.
FIT_TO_LABEL= 0b010000, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping. FIT_TO_LABEL= 0b0'0001'0000, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping.
FIXED_WIDTH_FONT= 0b0'0010'0000, //Uses a fixed-width font (instead of a proportional one) for text rendering.
}; };
enum class SelectionType{ enum class SelectionType{

@ -49,9 +49,10 @@ protected:
float scale=1; float scale=1;
bool shadow=false; bool shadow=false;
bool centered=true; bool centered=true;
bool proportional=true;
public: public:
inline MenuLabel(geom2d::rect<float>rect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE) inline MenuLabel(geom2d::rect<float>rect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE)
:MenuComponent(rect,label,MenuFunc{},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD),scale(scale),centered(!(attributes&ComponentAttr::LEFT_ALIGN)),shadow(attributes&ComponentAttr::SHADOW){ :MenuComponent(rect,label,MenuFunc{},ButtonAttr::UNSELECTABLE|ButtonAttr::UNSELECTABLE_VIA_KEYBOARD),scale(scale),centered(!(attributes&ComponentAttr::LEFT_ALIGN)),shadow(attributes&ComponentAttr::SHADOW),proportional(!(attributes&ComponentAttr::FIXED_WIDTH_FONT)){
border=attributes&ComponentAttr::OUTLINE; border=attributes&ComponentAttr::OUTLINE;
this->background=attributes&ComponentAttr::BACKGROUND; this->background=attributes&ComponentAttr::BACKGROUND;
showDefaultLabel=false; showDefaultLabel=false;
@ -67,14 +68,20 @@ protected:
inline virtual void DrawDecal(ViewPort&window,bool focused)override{ inline virtual void DrawDecal(ViewPort&window,bool focused)override{
MenuComponent::DrawDecal(window,focused); MenuComponent::DrawDecal(window,focused);
vf2d adjustedScale={scale,scale}; vf2d adjustedScale={scale,scale};
vf2d labelTextSize=vf2d(game->GetWrappedTextSizeProp(label,rect.size.x,adjustedScale)); vf2d labelTextSize=
proportional?
vf2d(game->GetWrappedTextSizeProp(label,rect.size.x,adjustedScale)):
vf2d(game->GetWrappedTextSize(label,rect.size.x,adjustedScale));
if(fitToLabel){ if(fitToLabel){
float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2); float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2);
if(sizeRatio>1){ if(sizeRatio>1){
adjustedScale.x/=sizeRatio; adjustedScale.x/=sizeRatio;
} }
labelTextSize=vf2d(game->GetTextSizeProp(label)*adjustedScale); labelTextSize=
proportional?
vf2d(game->GetTextSizeProp(label)*adjustedScale):
vf2d(game->GetTextSize(label)*adjustedScale);
} }
vf2d drawPos=rect.middle()-vf2d{labelTextSize}/2; //Assume centered. vf2d drawPos=rect.middle()-vf2d{labelTextSize}/2; //Assume centered.
@ -83,9 +90,17 @@ protected:
} }
if(shadow){ if(shadow){
window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f); if(proportional){
window.DrawShadowStringPropDecal(drawPos,label,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
}else{
window.DrawShadowStringDecal(drawPos,label,WHITE,BLACK,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
}
}else{ }else{
window.DrawStringPropDecal(drawPos,label,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f); if(proportional){
window.DrawStringPropDecal(drawPos,label,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
}else{
window.DrawStringDecal(drawPos,label,WHITE,adjustedScale,fitToLabel?std::numeric_limits<float>::max():rect.size.x,1.0f);
}
} }
} }
}; };

@ -0,0 +1,93 @@
#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
#pragma once
#include "MenuLabel.h"
#include "Item.h"
class RequiredMaterialsList:public MenuLabel{
std::weak_ptr<Item>itemRef;
public:
inline RequiredMaterialsList(geom2d::rect<float>rect,const std::weak_ptr<Item>itemRef,ComponentAttr attributes=ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)
:MenuLabel(rect,"",1.f,attributes),itemRef(itemRef){}
inline void SetItem(const std::weak_ptr<Item>itemRef){
this->itemRef=itemRef;
}
inline const std::weak_ptr<Item>GetItem()const{
return itemRef;
}
protected:
inline virtual void DrawDecal(ViewPort&window,bool focused)override final{
MenuComponent::DrawDecal(window,focused);
vf2d adjustedScale={scale,scale};
vf2d labelTextSize=vf2d(game->GetWrappedTextSizeProp(label,rect.size.x,adjustedScale));
if(fitToLabel){
float sizeRatio=((labelTextSize*adjustedScale).x)/(rect.size.x-2);
if(sizeRatio>1){
adjustedScale.x/=sizeRatio;
}
labelTextSize=vf2d(game->GetTextSizeProp(label)*adjustedScale);
}
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()){
Pixel textCol=WHITE;
if(Inventory::GetItemCount(item.ActualName())<item.Amt())textCol=RED;
vf2d drawPos=rect.pos+vf2d{drawWidth*(index%3),12.f*(index/3)};
std::string labelText=std::format("{}",item.DisplayName());
float labelWidth=game->GetTextSizeProp(labelText).x;
window.DrawShadowStringDecal(drawPos,std::format("{:>3}",item.Amt()),textCol,BLACK);
window.DrawShadowStringPropDecal(drawPos+vf2d{26,0},labelText,textCol,BLACK,{std::min(1.f,(drawWidth-26-2)/labelWidth),1.f});
index++;
}
Pixel textCol=WHITE;
uint32_t goldAmt=itemRef.lock()->GetEnhancementInfo()[itemRef.lock()->EnhancementLevel()+1].craftingRequirement.GetCost();
if(game->GetPlayer()->GetMoney()<goldAmt)textCol=RED;
vf2d drawPos=rect.pos+vf2d{drawWidth*(index%3),12.f*(index/3)};
std::string goldAmtText=std::format("{:>3}",goldAmt);
std::string labelText=std::format("{}","Item.Currency Name"_S);
float goldAmtWidth=game->GetTextSize(goldAmtText).x;
window.DrawShadowStringDecal(drawPos,goldAmtText,textCol,BLACK);
window.DrawShadowStringPropDecal(drawPos+vf2d{goldAmtWidth+2,0},labelText,textCol,BLACK);
index++;
}
}
};

@ -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 4955 #define VERSION_BUILD 5026
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -26,6 +26,9 @@ Equipment
{ {
Item[0] = Green Slime Remains,10 Item[0] = Green Slime Remains,10
Item[1] = Logs,2 Item[1] = Logs,2
Item[2] = Blue Slime Remains,4
Item[3] = Red Slime Remains,3
Item[4] = Flower Petals,1
Gold = 50 Gold = 50
} }

@ -12,6 +12,8 @@ Item
Item Cooldown Time = 5.0 Item Cooldown Time = 5.0
# The maximum enhancement level of equipment. # The maximum enhancement level of equipment.
Item Max Enhancement Level = 10 Item Max Enhancement Level = 10
# The name of the currency in the game.
Currency Name = Gold
} }
ItemDrop ItemDrop
{ {

Loading…
Cancel
Save