diff --git a/Crawler/CharacterMenuWindow.cpp b/Crawler/CharacterMenuWindow.cpp index 2be0436b..edbb3ba6 100644 --- a/Crawler/CharacterMenuWindow.cpp +++ b/Crawler/CharacterMenuWindow.cpp @@ -37,13 +37,14 @@ All rights reserved. #pragma endregion #include "Menu.h" #include "MenuComponent.h" -#include "MenuLabel.h" +#include "PopupMenuLabel.h" +#include "StatLabel.h" #include "CharacterRotatingDisplay.h" #include "Crawler.h" #include "ClassInfo.h" #include "MenuItemItemButton.h" +#include "EquipSlotButton.h" #include "Item.h" -#include "PopupMenuLabel.h" #include "ScrollableWindowComponent.h" INCLUDE_game @@ -62,6 +63,16 @@ void Menu::InitializeCharacterMenuWindow(){ characterMenuWindow->AddComponent("Equip Slot Outline",equipSlotOutline); characterMenuWindow->AddComponent("Character Rotating Display",charDisplay); + const static std::arraydisplayAttrs{ + ItemAttribute::health, + ItemAttribute::attack, + ItemAttribute::defense, + ItemAttribute::moveSpdPct, + ItemAttribute::cdrPct, + ItemAttribute::critPct, + ItemAttribute::critDmgPct, + }; + MenuComponent*equipSelectionOutline=NEW MenuComponent(CHARACTER_MENU,{{123,36},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); ScrollableWindowComponent*equipmentList=NEW ScrollableWindowComponent(CHARACTER_MENU,{{123,36},{120,windowSize.y-37-24}}); MenuComponent*equipSelectionBottomOutline=NEW MenuComponent(CHARACTER_MENU,{{123,36+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); @@ -71,6 +82,10 @@ void Menu::InitializeCharacterMenuWindow(){ Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(false); Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(false); Component(data.component->parentMenu,"Character Rotating Display")->Enable(true); + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + statDisplayLabel->SetStatChangeAmt(0); + } return true; }); @@ -84,14 +99,14 @@ void Menu::InitializeCharacterMenuWindow(){ characterMenuWindow->AddComponent("Equip Selection Bottom Outline",equipSelectionBottomOutline); characterMenuWindow->AddComponent("Equip Selection Select Button",equipSelectionSelectButton); - const static std::arraydisplayAttrs{ - ItemAttribute::health, - ItemAttribute::attack, - ItemAttribute::defense, - ItemAttribute::moveSpdPct, - ItemAttribute::cdrPct, - ItemAttribute::critPct, - ItemAttribute::critDmgPct, + const static auto GetLabelText=[](ItemAttribute attribute){ + AttributeData data=ItemAttributable::GetDisplayInfo(attribute); + std::string attrStr=data.name+":\n "; + attrStr+=std::to_string(game->GetPlayer()->GetStat(attribute)); + if(data.displayAsPercent){ + attrStr+="%"; + } + return attrStr; }; int equipSlot=1; @@ -104,10 +119,10 @@ void Menu::InitializeCharacterMenuWindow(){ y-=8; labelY-=8; } - const std::arrayslotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"}; + const static std::arrayslotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"}; EquipSlot slot=EquipSlot(equipSlot); - MenuItemItemButton*equipmentSlot=NEW MenuItemItemButton(CHARACTER_MENU,{{x,y+36},{24,24}},Item::BLANK,MenuType::ENUM_END, + EquipSlotButton*equipmentSlot=NEW EquipSlotButton(CHARACTER_MENU,{{x,y+36},{24,24}},slot,MenuType::ENUM_END, [&](MenuFuncData data){ EquipSlot slot=EquipSlot(data.component->I(Attribute::EQUIP_TYPE)); @@ -129,6 +144,17 @@ void Menu::InitializeCharacterMenuWindow(){ MenuItemItemButton*equip=NEW MenuItemItemButton(CHARACTER_MENU,{{2+xOffset,2},{24,24}},itemInvRef,MenuType::ENUM_END,[](MenuFuncData data){ MenuItemItemButton*comp=(MenuItemItemButton*)data.component; Inventory::EquipItem(comp->GetItem(),EquipSlot(comp->I(Attribute::EQUIP_TYPE))); + for(MenuComponent*button:((ScrollableWindowComponent*)data.parentComponent)->GetComponents()){ + MenuItemItemButton*comp=(MenuItemItemButton*)button; + comp->SetSelected(false); + } + comp->SetSelected(true); + for(int counter=0;ItemAttribute attribute:displayAttrs){ + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + statDisplayLabel->SetStatChangeAmt(0); + } + MenuItemItemButton*equipButton=Component(CHARACTER_MENU,"Equip Slot "+slotNames[data.parentComponent->I(A::INDEXED_THEME)]); + equipButton->SetItem(comp->GetItem()); return true; },[&](MenuFuncData data){ MenuItemItemButton*button=(MenuItemItemButton*)data.component; @@ -141,16 +167,9 @@ void Menu::InitializeCharacterMenuWindow(){ Item*equippedItem=Inventory::GetEquip(slot); Inventory::EquipItem(buttonItem,slot); for(int counter=0;ItemAttribute attribute:displayAttrs){ - MenuLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); + StatLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); int statChangeAmt=game->GetPlayer()->GetStat(attribute)-statsBeforeEquip[counter]; - std::string baseLabel=statDisplayLabel->S(Attribute::BASE_TEXT); - if(statChangeAmt>0){ - baseLabel+=Color::Green+"(+"+std::to_string(statChangeAmt)+")"; - }else - if(statChangeAmt<0){ - baseLabel+=Color::Red+"("+std::to_string(statChangeAmt)+")"; - } - statDisplayLabel->SetLabel(baseLabel); + statDisplayLabel->SetStatChangeAmt(statChangeAmt); counter++; } Inventory::UnequipItem(slot); @@ -158,32 +177,30 @@ void Menu::InitializeCharacterMenuWindow(){ Inventory::EquipItem(*equippedItem,slot); } return true; - },[&](MenuFuncData data){ - MenuItemItemButton*button=(MenuItemItemButton*)data.component; - Item&buttonItem=button->GetItem(); - for(ItemAttribute attribute:displayAttrs){ - MenuLabel*statDisplayLabel=Component(CHARACTER_MENU,"Attribute "+ItemAttributable::GetDisplayInfo(attribute).name+" Label"); - statDisplayLabel->SetLabel(statDisplayLabel->S(Attribute::BASE_TEXT)); - } - return true; - }); + },DO_NOTHING); equip->I(Attribute::EQUIP_TYPE)=int(slot); + if(Inventory::GetEquip(slot)==&itemInvRef){ + equip->SetSelected(true); + } equipList->AddComponent(Menu::menus[CHARACTER_MENU],"Equip Item "+std::to_string(counter),equip); counter++; } - + equipList->I(Attribute::INDEXED_THEME)=data.component->I(Attribute::INDEXED_THEME); Component(data.component->parentMenu,"Equip Selection Outline")->Enable(true); equipList->Enable(true); Component(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(true); Component(data.component->parentMenu,"Equip Selection Select Button")->Enable(true); Component(data.component->parentMenu,"Character Rotating Display")->Enable(false); return true; - },MenuType::ENUM_END,"",""); + },DO_NOTHING,DO_NOTHING); PopupMenuLabel*equipmentLabel=NEW PopupMenuLabel(CHARACTER_MENU,{{labelX,labelY},{29,24}},slotNames[i],{0.5,1},ComponentAttr::SHADOW); equipmentSlot->I(Attribute::EQUIP_TYPE)=int(slot); + equipmentSlot->I(Attribute::INDEXED_THEME)=i; + equipmentSlot->SetShowQuantity(false); equipSlot<<=1; characterMenuWindow->AddComponent("Equip Slot "+slotNames[i],equipmentSlot); characterMenuWindow->AddComponent("Equip Label "+slotNames[i],equipmentLabel); + Menu::AddEquipStatListener(equipmentSlot); } MenuComponent*statDisplayOutline=NEW MenuComponent(CHARACTER_MENU,{{245,36},{62,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE); @@ -192,15 +209,11 @@ void Menu::InitializeCharacterMenuWindow(){ int yOffset=0; for(ItemAttribute attribute:displayAttrs){ - AttributeData data=ItemAttributable::GetDisplayInfo(attribute); - std::string attrStr=data.name+":\n "; - attrStr+=std::to_string(game->GetPlayer()->GetStat(attribute)); - if(data.displayAsPercent){ - attrStr+="%"; - } - MenuLabel*attrLabel=NEW MenuLabel(CHARACTER_MENU,{{245,36+2+float(yOffset)},{62,18}},attrStr,1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); - attrLabel->S(Attribute::BASE_TEXT)=attrStr; + std::string attrStr=GetLabelText(attribute); + StatLabel*attrLabel=NEW StatLabel(CHARACTER_MENU,{{245,36+2+float(yOffset)},{62,18}},attribute,1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN); yOffset+=20; + AttributeData data=ItemAttributable::GetDisplayInfo(attribute); characterMenuWindow->AddComponent("Attribute "+data.name+" Label",attrLabel); + Menu::AddEquipStatListener(attrLabel); } } \ No newline at end of file diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index b7421cb0..6c827a4d 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -193,6 +193,13 @@ bool Crawler::OnUserCreate(){ Inventory::AddItem("Bandages",10); Inventory::AddItem("Blue Slime Remains",22); Inventory::AddItem("Copper Armor"); + Inventory::AddItem("Copper Pants"); + Inventory::AddItem("Shell Helmet"); + Inventory::AddItem("Shell Armor"); + Inventory::AddItem("Shell Gloves"); + Inventory::AddItem("Shell Shoes"); + Inventory::AddItem("Bone Pants"); + Inventory::AddItem("Bone Gloves"); LoadLevel(LEVEL_NAMES["starting_map"_S]); ChangePlayerClass(WARRIOR); diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index 6452f093..e087f67a 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -303,6 +303,10 @@ + + + + @@ -366,6 +370,10 @@ + + + + diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index 19c558de..bcdf4403 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -291,6 +291,12 @@ Header Files + + Header Files\Interface + + + Header Files\Interface + diff --git a/Crawler/EquipSlotButton.h b/Crawler/EquipSlotButton.h new file mode 100644 index 00000000..8ac1f3cd --- /dev/null +++ b/Crawler/EquipSlotButton.h @@ -0,0 +1,62 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2018 - 2023 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 "MenuItemItemButton.h" +#include "DEFINES.h" +#include "Crawler.h" + +INCLUDE_game +INCLUDE_ITEM_DATA + +class EquipSlotButton:public MenuItemItemButton{ +private: + EquipSlot slot; +public: + inline EquipSlotButton(MenuType parent,geom2d::rectrect,EquipSlot slot,MenuType menuDest,MenuFunc onClick,MenuFunc onHover,MenuFunc onMouseOut) + :MenuItemItemButton(parent,rect,Item::BLANK,menuDest,onClick,onHover,onMouseOut),slot(slot){} + inline void OnEquipStatsUpdate()override{ + Item&equip=*Inventory::GetEquip(slot); + if(!equip.IsBlank()){ + icon=equip.Decal(); + SetItem(equip); + }else{ + icon=nullptr; + SetItem(Item::BLANK); + } + } +}; \ No newline at end of file diff --git a/Crawler/Item.h b/Crawler/Item.h index 604a1b1c..a648c99f 100644 --- a/Crawler/Item.h +++ b/Crawler/Item.h @@ -105,6 +105,7 @@ public: class Item{ friend class Inventory; friend class Crawler; + friend class Menu; private: //The amount in the current item stack. uint32_t amt; diff --git a/Crawler/Menu.cpp b/Crawler/Menu.cpp index 8f9eca0e..35786060 100644 --- a/Crawler/Menu.cpp +++ b/Crawler/Menu.cpp @@ -49,6 +49,7 @@ std::mapMenu::menus; std::string Menu::themeSelection="BlueDefault"; safeunorderedmapMenu::themes; safemap>Menu::inventoryListeners; +std::vectorMenu::equipStatListeners; const vf2d Menu::CENTERED = {-456,-456}; std::vectorMenu::unhandledComponents; ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -663,6 +664,13 @@ void Menu::AddInventoryListener(MenuComponent*component,ITCategory category){ } } +void Menu::AddEquipStatListener(MenuComponent*component){ + if(std::find(equipStatListeners.begin(),equipStatListeners.end(),component)!=equipStatListeners.end()){ + ERR("WARNING! Component "<name<<" has already been added to the Equip Stat listener list! There should not be any duplicates!!") + } + equipStatListeners.push_back(component); +} + vf2d Menu::center(){ return size/2; } @@ -716,4 +724,4 @@ void Menu::DrawThemedWindow(vf2d menuPos,vf2d size,Pixel renderColor){ DrawTiledWindowBackground(game,menuPos,size,renderColor); DrawTiledWindowBorder(game,menuPos,size,renderColor); } -} \ No newline at end of file +} diff --git a/Crawler/Menu.h b/Crawler/Menu.h index 68a31a35..0bc6934e 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -68,6 +68,7 @@ class Menu:public IAttributable{ friend class Crawler; friend struct Player; friend class ItemInfo; + friend class PlayerStats; float buttonHoldTime=0; vi2d selection={-1,-1}; @@ -76,6 +77,7 @@ class Menu:public IAttributable{ MenuComponent*draggingComponent=nullptr; Renderable r,overlay; static safemap>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()). + static std::vectorequipStatListeners; //All menu components that care about stat/equip updates subscribe to this list indirectly (See Menu::AddStatListener()). public: //The constructor is private. Use CreateMenu() instead! Menu()=default; @@ -107,6 +109,7 @@ public: void SetMouseNavigation(bool mouseNavigation); static void InventorySlotsUpdated(ITCategory cat); //Called whenever an inventory item gets added to the player's inventory, thus increasing the total number of slots in our bag. static void AddInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category. + static void AddEquipStatListener(MenuComponent*component); //Adds a component to be in an equip stat listener. Will receive updates whenever stats are updated via equips. vf2d center(); //Returns the last menu type created and last registered component, in case a component is detected as memory leaking, provides this information to each component for safety. static std::pairGetMemoryLeakReportInfo(); diff --git a/Crawler/MenuComponent.cpp b/Crawler/MenuComponent.cpp index 185ec621..a72f8010 100644 --- a/Crawler/MenuComponent.cpp +++ b/Crawler/MenuComponent.cpp @@ -93,6 +93,8 @@ void MenuComponent::Draw(Crawler*game,vf2d parentPos){ } } +void MenuComponent::OnEquipStatsUpdate(){} + void MenuComponent::_Draw(Crawler*game){ _Draw(game,{0,0}); } diff --git a/Crawler/MenuComponent.h b/Crawler/MenuComponent.h index f1f00413..283d2d3b 100644 --- a/Crawler/MenuComponent.h +++ b/Crawler/MenuComponent.h @@ -107,6 +107,8 @@ public: virtual bool HandleOutsideDisabledButtonSelection(MenuComponent*disabledButton); //Called whenever an inventory slot gets updated, whether it's adding or removing an item. virtual void OnInventorySlotsUpdate(ITCategory cat); + //Called whenever equipment and base stats are updated, notifying a component that numbers that may be displayed have changed. + virtual void OnEquipStatsUpdate(); std::string GetLabel(); std::string GetName(); virtual void Enable(bool enabled); diff --git a/Crawler/MenuItemItemButton.h b/Crawler/MenuItemItemButton.h index b401e87d..ac6f2605 100644 --- a/Crawler/MenuItemItemButton.h +++ b/Crawler/MenuItemItemButton.h @@ -51,7 +51,7 @@ INCLUDE_ITEM_DATA class MenuItemItemButton:public MenuIconButton{ private: - Item&itemRef; + std::reference_wrapperitemRef; MenuType itemDescriptionMenu; std::string itemNameLabelName; std::string itemDescriptionLabelName; @@ -59,6 +59,8 @@ private: MenuFunc onHover; MenuFunc onMouseOut; bool hoverState=false; + bool selected=false; + bool hideQty=false; public: inline MenuItemItemButton(MenuType parent,geom2d::rectrect,Item&itemRef,MenuType menuDest,MenuFunc onClick,MenuType itemDescriptionMenu,std::string itemNameLabelName,std::string itemDescriptionLabelName) :MenuIconButton(parent,rect,(!itemRef.IsBlank())?itemRef.Decal():nullptr,menuDest,onClick),itemRef(itemRef),itemDescriptionMenu(itemDescriptionMenu),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),onHover(DO_NOTHING){ @@ -72,18 +74,27 @@ public: valid=!itemRef.IsBlank(); } inline Item&GetItem(){ - return itemRef; + return itemRef.get(); + } + inline Item&SetItem(Item&newItem){ + return itemRef=std::reference_wrapper(newItem); + } + inline void SetSelected(bool selected){ + this->selected=selected; + } + inline void SetShowQuantity(bool show){ + this->hideQty=!show; } protected: virtual inline void Update(Crawler*game)override{ MenuIconButton::Update(game); - valid=!itemRef.IsBlank(); + valid=!itemRef.get().IsBlank(); std::string labelNameText; std::string labelDescriptionText; if(valid){ - icon=itemRef.Decal(); - labelNameText=itemRef.Name(); - labelDescriptionText=itemRef.Description(); + icon=itemRef.get().Decal(); + labelNameText=itemRef.get().Name(); + labelDescriptionText=itemRef.get().Description(); }else{ icon=nullptr; labelNameText=""; @@ -107,11 +118,14 @@ protected: } virtual inline void Draw(Crawler*game,vf2d parentPos)override{ MenuIconButton::Draw(game,parentPos); + if(selected){ + drawutil::DrawCrosshair(game,{parentPos+rect.pos,rect.size},0); + } } virtual inline void DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{ MenuIconButton::DrawDecal(game,parentPos,focused); - if(valid){ - std::string quantityText="x"+std::to_string(itemRef.Amt()); + if(valid&&!hideQty){ + std::string quantityText="x"+std::to_string(itemRef.get().Amt()); vf2d textSize=vf2d(game->GetTextSizeProp(quantityText))*0.5; vf2d drawPos=parentPos+rect.pos+rect.size-textSize; if(PointWithinParent(this,drawPos)){ diff --git a/Crawler/MenuLabel.h b/Crawler/MenuLabel.h index 405105ed..1e13e9ea 100644 --- a/Crawler/MenuLabel.h +++ b/Crawler/MenuLabel.h @@ -56,7 +56,7 @@ public: this->background=attributes&ComponentAttr::BACKGROUND; showDefaultLabel=false; } - inline void SetLabel(std::string text){ + inline virtual void SetLabel(std::string text){ label=text; } protected: diff --git a/Crawler/Player.cpp b/Crawler/Player.cpp index fe39e40f..7aa5517e 100644 --- a/Crawler/Player.cpp +++ b/Crawler/Player.cpp @@ -47,6 +47,7 @@ All rights reserved. #include "Key.h" #include "Menu.h" #include "GameState.h" +#include "MenuComponent.h" INCLUDE_MONSTER_DATA INCLUDE_MONSTER_LIST @@ -873,6 +874,9 @@ void PlayerStats::RecalculateEquipStats(){ equipStats.get(a)+=equip->GetStats().A(a); } } + for(MenuComponent*component:Menu::equipStatListeners){ + component->OnEquipStatsUpdate(); + } } const int PlayerStats::GetStat(ItemAttribute stat){ return equipStats.A(stat); diff --git a/Crawler/ScrollableWindowComponent.h b/Crawler/ScrollableWindowComponent.h index 1c831686..c45c68d4 100644 --- a/Crawler/ScrollableWindowComponent.h +++ b/Crawler/ScrollableWindowComponent.h @@ -71,8 +71,8 @@ public: Menu::menus[parentMenu]->AddComponent(name+downButton->rect.pos.str()+"_"+downButton->rect.size.str(),downButton); } virtual inline void RemoveAllComponents(){ - for(MenuComponent*item:components){ - RemoveButton(item); + while(components.size()>0){ + RemoveButton(components.back()); } } virtual inline void RemoveButton(MenuComponent*button){ diff --git a/Crawler/StatLabel.h b/Crawler/StatLabel.h new file mode 100644 index 00000000..dd61f0a4 --- /dev/null +++ b/Crawler/StatLabel.h @@ -0,0 +1,89 @@ +#pragma region License +/* +License (OLC-3) +~~~~~~~~~~~~~~~ + +Copyright 2018 - 2023 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 "DEFINES.h" +#include "Crawler.h" +#include "util.h" + +INCLUDE_game + +class StatLabel:public MenuLabel{ +private: + ItemAttribute stat; + int value=0; + int statChangeAmt=0; +public: + inline StatLabel(MenuType parent,geom2d::rectrect,ItemAttribute stat,int scale=1,ComponentAttr attributes=ComponentAttr::NONE) + :MenuLabel(parent,rect,"",scale,attributes),stat(stat){ + border=attributes&ComponentAttr::OUTLINE; + this->background=attributes&ComponentAttr::BACKGROUND; + showDefaultLabel=false; + SetValue(game->GetPlayer()->GetStat(stat)); + } + void SetValue(int value){ + this->value=value; + UpdateLabel(); + } + void SetStatChangeAmt(int changeAmt){ + this->statChangeAmt=changeAmt; + UpdateLabel(); + } +protected: + inline void SetLabel(std::string text)override final{ + MenuLabel::SetLabel(text); + } + inline void OnEquipStatsUpdate()override final{ + SetValue(game->GetPlayer()->GetStat(stat)); + } + inline void UpdateLabel(){ + AttributeData data=ItemAttributable::GetDisplayInfo(stat); + std::string attrStr=data.name+":\n "; + attrStr+=std::to_string(value); + if(data.displayAsPercent){ + attrStr+="%"; + } + if(statChangeAmt>0){ + attrStr+=Color::Green+"(+"+std::to_string(statChangeAmt)+")"; + }else + if(statChangeAmt<0){ + attrStr+=Color::Red+"("+std::to_string(statChangeAmt)+")"; + } + SetLabel(attrStr); + } +}; \ No newline at end of file diff --git a/Crawler/Version.h b/Crawler/Version.h index 28b337e7..6415be00 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 3534 +#define VERSION_BUILD 3570 #define stringify(a) stringify_(a) #define stringify_(a) #a