diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj index f2e8c52b..6125752b 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj @@ -531,6 +531,10 @@ + + + + diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters index 70fa620a..feaf00b6 100644 --- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters +++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters @@ -696,6 +696,9 @@ Header Files\Interface + + Header Files\Interface + diff --git a/Adventures in Lestoria/ArtificerRefineWindow.cpp b/Adventures in Lestoria/ArtificerRefineWindow.cpp index c34e34e0..da61377f 100644 --- a/Adventures in Lestoria/ArtificerRefineWindow.cpp +++ b/Adventures in Lestoria/ArtificerRefineWindow.cpp @@ -39,52 +39,72 @@ All rights reserved. #include "Menu.h" #include "AdventuresInLestoria.h" #include "RowInventoryScrollableWindowComponent.h" -#include "MenuLabel.h" #include "MenuItemItemButton.h" +#include "MenuRefineLabel.h" +#include "PlayerMoneyLabel.h" INCLUDE_game void Menu::InitializeArtificerRefineWindow(){ - Menu*artificerRefineWindow=CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52}); + Menu*const artificerRefineWindow{CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52})}; - auto disassemblyTitleLabel{artificerRefineWindow->ADD("Disassembly Title Label",MenuLabel)(geom2d::rect{{},{artificerRefineWindow->size.x,24.f}},"Accessory Disassembly",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END}; + auto disassemblyTitleLabel{artificerRefineWindow->ADD("Disassembly Title Label",MenuLabel)(geom2d::rect{{0.f,-16.f},{artificerRefineWindow->size.x,24.f}},"Accessory Disassembly",2.f,ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END}; - auto inventoryLabel=artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect{{0.f,28.f},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END; + auto inventoryLabel{artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect{{0.f,12.f},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END}; - auto itemIcon{artificerRefineWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect({artificerRefineWindow->size.x/2+4.f,44.f},{48,48}),Item::BLANK,DO_NOTHING,"","Item Description",IconButtonAttr::NOT_SELECTABLE)END}; + auto itemIcon{artificerRefineWindow->ADD("Item Icon",MenuItemItemButton)(geom2d::rect({artificerRefineWindow->size.x/2+4.f,28.f},{48,48}),Item::BLANK,DO_NOTHING,"","Item Description",IconButtonAttr::NOT_SELECTABLE)END}; itemIcon->SetIconScale({2.f,2.f}); itemIcon->SetCompactDescriptions(true); - auto accessoryDescription{artificerRefineWindow->ADD("Item Description",MenuLabel)(geom2d::rect{{artificerRefineWindow->size.x/2+56.f,44.f},{artificerRefineWindow->size.x/2-56.f,72.f}},"",0.5f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END}; + auto accessoryDescription{artificerRefineWindow->ADD("Item Description",MenuLabel)(geom2d::rect{{artificerRefineWindow->size.x/2+56.f,28.f},{artificerRefineWindow->size.x/2-56.f,72.f}},"",0.5f,ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END}; - const auto ResetDisassemblyDisplay=[artificerRefineWindow](){ + const auto ResetRefineDisplay{[artificerRefineWindow](){ MenuType menuType{artificerRefineWindow->GetType()}; - }; - const auto EnableDisassemblyDisplay=[artificerRefineWindow](){ + Component(menuType,"Item Icon")->SetItem(Item::BLANK); + Component(menuType,"Stats Block")->SetItem(Item::BLANK); + }}; + const auto EnableRefineDisplay{[artificerRefineWindow](){ MenuType menuType{artificerRefineWindow->GetType()}; - }; + }}; - auto inventoryDisplay=artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect{{0.f,44.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-60}},"","",[](MenuFuncData data){ + auto inventoryDisplay{artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect{{0.f,28.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-44}},"","",[](MenuFuncData data){ + OnClick: RowItemDisplay&item{*DYNAMIC_POINTER_CAST(data.component)}; DYNAMIC_POINTER_CAST(data.parentComponent.lock())->SelectChild(DYNAMIC_POINTER_CAST(data.component)); return true; - },[](MenuFuncData data){ + },[EnableRefineDisplay](MenuFuncData data){OnHover: RowItemDisplay&item{*DYNAMIC_POINTER_CAST(data.component)}; - return true; - },[](MenuFuncData data){ + EnableRefineDisplay(); + Component(data.menu.type,"Item Icon")->SetItem(item.GetItem()); + Component(data.menu.type,"Stats Block")->SetItem(item.GetItem()); + return true; + },[ResetRefineDisplay,EnableRefineDisplay](MenuFuncData data){OnMouseOut: + ResetRefineDisplay(); auto childComponent{DYNAMIC_POINTER_CAST(data.parentComponent.lock())->GetSelectedChild()}; if(childComponent){ RowItemDisplay&item{childComponent.value().get()}; + EnableRefineDisplay(); } return true; }, InventoryCreator::RowPlayer_InventoryUpdate, - InventoryWindowOptions{.padding=1,.size={artificerRefineWindow->size.x/2-5.f-12.f,28}})END; + InventoryWindowOptions{.padding=1,.size={artificerRefineWindow->size.x/2-5.f-12.f,28}})END}; - auto backButton=artificerRefineWindow->ADD("Back",MenuComponent)(geom2d::rect{{0.f,artificerRefineWindow->size.y-12.f},{96.f,16.f}},"Back",[](MenuFuncData data){ + auto statsBlock{artificerRefineWindow->ADD("Stats Block",MenuRefineLabel)(geom2d::rect{{artificerRefineWindow->size.x/2+4.f,104.f},{artificerRefineWindow->size.x/2-4.f,44.f}},Item::BLANK,1.f,ComponentAttr::BACKGROUND|ComponentAttr::SHADOW|ComponentAttr::OUTLINE|ComponentAttr::FIXED_WIDTH_FONT|ComponentAttr::FIT_TO_LABEL|ComponentAttr::LEFT_ALIGN)END}; + + #pragma region Money Display + vf2d moneyIconPos{artificerRefineWindow->size.x/2-28.f,artificerRefineWindow->size.y-12.f}; + auto moneyIcon=artificerRefineWindow->ADD("Money Icon",MenuIconButton)(geom2d::rect{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=artificerRefineWindow->ADD("Money Label",PlayerMoneyLabel)(geom2d::rect{moneyIconPos+vf2d{26.f,4.f},moneyTextSize},2,1.85f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN|ComponentAttr::FIT_TO_LABEL)END; + Player::AddMoneyListener(moneyDisplay); + #pragma endregion + + auto backButton{artificerRefineWindow->ADD("Back",MenuComponent)(geom2d::rect{{0.f,artificerRefineWindow->size.y-12.f},{96.f,16.f}},"Back",[](MenuFuncData data){ Menu::CloseMenu(); return true; - })END; + })END}; Menu::AddInventoryListener(inventoryDisplay,"Accessories"); diff --git a/Adventures in Lestoria/Error.h b/Adventures in Lestoria/Error.h index b87d5bdb..e1d22ce3 100644 --- a/Adventures in Lestoria/Error.h +++ b/Adventures in Lestoria/Error.h @@ -115,15 +115,15 @@ type DYNAMIC_CAST(auto variable){ } template -std::shared_ptrDYNAMIC_POINTER_CAST(const std::shared_ptr&variable){ - std::shared_ptr newVariable=dynamic_pointer_cast(variable); +const std::shared_ptrDYNAMIC_POINTER_CAST(const std::shared_ptr&variable){ + const std::shared_ptr newVariable=dynamic_pointer_cast(variable); if(!newVariable)ERR("Could not dynamic cast to pointer type "< -std::shared_ptrDYNAMIC_POINTER_CAST(const std::weak_ptr&variable){ - std::shared_ptr newVariable=dynamic_pointer_cast(variable.lock()); +const std::shared_ptrDYNAMIC_POINTER_CAST(const std::weak_ptr&variable){ + const std::shared_ptr newVariable=dynamic_pointer_cast(variable.lock()); if(!newVariable)ERR("Could not dynamic cast to pointer type "<=int(maxStats.attributes.at(attr))){ - Pixel shimmeringCol=PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f)); - col=shimmeringCol.toHTMLColorCode(); + col=Stats::GetShimmeringColor().toHTMLColorCode(); } description+=col+std::string(attr.Name())+": "+statNumber+(attr.DisplayAsPercent()?"%":"")+"#FFFFFF"; @@ -1513,4 +1512,8 @@ const bool Item::SelectedEquipIsDifferent(const std::weak_ptrequipAttempti } const std::optional&ItemInfo::FragmentIcon()const{ return fragmentIcon; +} + +const Pixel Stats::GetShimmeringColor(){ + return PixelLerp({255,196,60},{254,217,133},sin((70*game->GetRunTime())/2.f+0.5f)); } \ No newline at end of file diff --git a/Adventures in Lestoria/Item.h b/Adventures in Lestoria/Item.h index 6ca0117d..69e19323 100644 --- a/Adventures in Lestoria/Item.h +++ b/Adventures in Lestoria/Item.h @@ -111,6 +111,7 @@ public: } const std::string GetStatsString(const Stats&maxStats,CompactText compact=NON_COMPACT)const; friend const bool operator==(const Stats&lhs,const Stats&rhs){return lhs.attributes==rhs.attributes;} + static const Pixel GetShimmeringColor(); }; struct Stats; diff --git a/Adventures in Lestoria/MenuRefineLabel.h b/Adventures in Lestoria/MenuRefineLabel.h new file mode 100644 index 00000000..01be42a4 --- /dev/null +++ b/Adventures in Lestoria/MenuRefineLabel.h @@ -0,0 +1,78 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2024 Joshua Sigona + +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 © 2024 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_DATA +INCLUDE_ITEM_DATA + +class MenuRefineLabel:public MenuLabel{ +public: + inline MenuRefineLabel(const geom2d::rectrect,const std::weak_ptritemRef,const float scale=1,ComponentAttr attributes=ComponentAttr::NONE) + :itemRef(itemRef),MenuLabel(rect,"",scale,attributes){} + + inline virtual void Update(AiL*game)override{ + std::string label{}; + + if(!ISBLANK(itemRef)){ + std::string longestStatName{}; + const Stats&maxStats{ITEM_DATA.at(itemRef.lock()->ActualName()).GetMaxStats()}; + for(const auto&[attr,val]:maxStats){ + const std::string displayName{attr.Name()}; + if(displayName.size()>longestStatName.size())longestStatName=displayName; + } + const std::string statNameVFormatStr{"{:"+std::to_string(longestStatName.size()+1)+"}"}; + + for(const auto&[attr,val]:itemRef.lock()->RandomStats()){ + const bool IsMaxedOut{val>=maxStats.A_Read(attr.ActualName())}; + label+=util::vformat("{}"+statNameVFormatStr+"+{:3}{:1}{}{:>5}\n",IsMaxedOut?Stats::GetShimmeringColor().toHTMLColorCode():"#FFFFFF",attr.Name(),int(round(val)),attr.DisplayAsPercent()?"%":"",IsMaxedOut?"#FF0000":"#00FF00",IsMaxedOut?"MAX":" +???"); + } + } + + SetLabel(label); + MenuLabel::Update(game); + } + + inline void SetItem(const std::weak_ptritemRef){ + this->itemRef=itemRef; + } + +private: + std::weak_ptritemRef; +}; \ No newline at end of file diff --git a/Adventures in Lestoria/PlayerMoneyLabel.h b/Adventures in Lestoria/PlayerMoneyLabel.h index 61b4ab6c..7c4cb63a 100644 --- a/Adventures in Lestoria/PlayerMoneyLabel.h +++ b/Adventures in Lestoria/PlayerMoneyLabel.h @@ -56,7 +56,7 @@ public: SetLabel(std::to_string(newMoney)); std::string moneyText=std::to_string(newMoney); vf2d moneyTextSize=game->GetTextSizeProp(moneyText)*scale; - rect.pos.x=anchorPointX-moneyTextSize.x; + if(rightAligned)rect.pos.x=anchorPointX-moneyTextSize.x; rect.size=moneyTextSize; } diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index ab370ce3..fa67972c 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_PATCH 5 -#define VERSION_BUILD 11417 +#define VERSION_BUILD 11440 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/util.h b/Adventures in Lestoria/util.h index b8a29686..6b6688c8 100644 --- a/Adventures in Lestoria/util.h +++ b/Adventures in Lestoria/util.h @@ -86,17 +86,17 @@ namespace olc::util{ std::wstring to_wstring(const std::string&str); template - std::string vformat(std::string str,_Args&..._Vals){ + const std::string vformat(const std::string_view str,_Args..._Vals){ return std::vformat(str,std::make_format_args(_Vals...)); } template - std::wstring wformat(std::string str,_Args&..._Vals){ + const std::wstring wformat(const std::string_view str,_Args..._Vals){ return util::to_wstring(std::vformat(str,std::make_format_args(_Vals...))); } template T map_range(T x, T in_min, T in_max, T out_min, T out_max) { - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } } diff --git a/x64/Release/Adventures in Lestoria.exe b/x64/Release/Adventures in Lestoria.exe index 95c9084c..94800c1d 100644 Binary files a/x64/Release/Adventures in Lestoria.exe and b/x64/Release/Adventures in Lestoria.exe differ