Added Merchant/Buy/Sell Menu windows. Added sorted item callbacks for traveling merchant inventory modifications.
This commit is contained in:
parent
d9e1a1ebaf
commit
71fe49162d
48
Crawler/BuyItemWindow.cpp
Normal file
48
Crawler/BuyItemWindow.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#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 "MenuLabel.h"
|
||||
|
||||
void Menu::InitializeBuyItemWindow(){
|
||||
Menu*buyItemWindow=CreateMenu(BUY_ITEM,CENTERED,{192,72});
|
||||
|
||||
buyItemWindow->ADD("Item Purchase Header",MenuLabel)({{2,2},{188,12}},"Buying ",1,ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND|ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL)END;
|
||||
|
||||
|
||||
}
|
@ -403,6 +403,10 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RowMerchantInventoryScrollableWindowComponent.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="safemap.h" />
|
||||
<ClInclude Include="ScrollableWindowComponent.h" />
|
||||
<ClInclude Include="InventoryScrollableWindowComponent.h" />
|
||||
@ -439,6 +443,10 @@
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Bullet.cpp" />
|
||||
<ClCompile Include="BuyItemWindow.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CharacterInfoWindow.cpp" />
|
||||
<ClCompile Include="CharacterMenuWindow.cpp">
|
||||
<SubType>
|
||||
@ -491,6 +499,10 @@
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MerchantWindow.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Meteor.cpp" />
|
||||
<ClCompile Include="OverworldMapLevelWindow.cpp" />
|
||||
<ClCompile Include="OverworldMenuWindow.cpp">
|
||||
@ -507,6 +519,10 @@
|
||||
<ClCompile Include="PulsatingFire.cpp" />
|
||||
<ClCompile Include="Ranger.cpp" />
|
||||
<ClCompile Include="RUN_STRATEGY.cpp" />
|
||||
<ClCompile Include="SellItemWindow.cpp">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ShootAfar.cpp" />
|
||||
<ClCompile Include="SlimeKing.cpp" />
|
||||
<ClCompile Include="State_GameRun.cpp" />
|
||||
|
@ -369,6 +369,9 @@
|
||||
<ClInclude Include="discord-files\types.h">
|
||||
<Filter>Header Files\discord-files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RowMerchantInventoryScrollableWindowComponent.h">
|
||||
<Filter>Header Files\Interface</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
@ -605,6 +608,15 @@
|
||||
<ClCompile Include="discord-files\user_manager.cpp">
|
||||
<Filter>Source Files\discord-files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MerchantWindow.cpp">
|
||||
<Filter>Source Files\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BuyItemWindow.cpp">
|
||||
<Filter>Source Files\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SellItemWindow.cpp">
|
||||
<Filter>Source Files\Interface</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
@ -55,7 +55,7 @@ void Menu::InitializeConsumableInventoryWindow(){
|
||||
|
||||
inventoryWindow->I(A::LOADOUT_SLOT)=0;
|
||||
|
||||
inventoryWindow->ADD("inventory",InventoryScrollableWindowComponent)({{1,20},{windowSize.x,96.f}},"Consumables","itemName","itemDescription",
|
||||
auto consumableWindow=inventoryWindow->ADD("inventory",InventoryScrollableWindowComponent)({{1,20},{windowSize.x,96.f}},"Consumables","itemName","itemDescription",
|
||||
[&](MenuFuncData data){
|
||||
MenuItemButton*button=(MenuItemButton*)data.component;
|
||||
data.game->ClearLoadoutItem(data.menu.I(A::LOADOUT_SLOT));
|
||||
@ -78,6 +78,7 @@ void Menu::InitializeConsumableInventoryWindow(){
|
||||
data.game->SetLoadoutItem(button->selected,button->GetItem().ActualName());
|
||||
return true;
|
||||
})END;
|
||||
Menu::AddInventoryListener(consumableWindow,"Consumables");
|
||||
|
||||
//We don't have to actually populate the inventory list because now when an item gets added, it will automatically add the correct component in for us.
|
||||
inventoryWindow->ADD("Inventory Type Label",MenuLabel)({{0,0},{windowSize.x-1,18}},"Consumables",2,ComponentAttr::SHADOW|ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)END;
|
||||
|
@ -72,9 +72,7 @@ public:
|
||||
}
|
||||
inline InventoryScrollableWindowComponent(geom2d::rect<float>rect,ITCategory invType,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::function<bool(MenuFuncData)>inventoryButtonClickAction,std::function<bool(MenuFuncData)>inventoryButtonHoverAction,std::function<bool(MenuFuncData)>inventoryButtonMouseOutAction,InventoryWindowOptions options={.padding=8,.size={24,24}},bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
|
||||
:ScrollableWindowComponent(rect,attributes),inventoryButtonHoverAction(inventoryButtonHoverAction),inventoryButtonMouseOutAction(inventoryButtonMouseOutAction),inventoryType(invType),itemNameLabelName(itemNameLabelName),itemDescriptionLabelName(itemDescriptionLabelName),
|
||||
options(options),inventoryButtonClickAction(inventoryButtonClickAction),inventoryButtonsActive(inventoryButtonsActive){
|
||||
Menu::AddInventoryListener(this,invType);
|
||||
}
|
||||
options(options),inventoryButtonClickAction(inventoryButtonClickAction),inventoryButtonsActive(inventoryButtonsActive){}
|
||||
virtual inline void Update(Crawler*game)override{
|
||||
ScrollableWindowComponent::Update(game);
|
||||
bool noneHovered=true;
|
||||
@ -122,7 +120,7 @@ protected:
|
||||
}
|
||||
CalculateBounds(); //Recalculate the bounds as it's possible the width/height of the component has changed.
|
||||
}
|
||||
virtual inline void OnInventorySlotsUpdate(ITCategory cat)override final{
|
||||
virtual inline void OnInventorySlotsUpdate(ITCategory cat)override{
|
||||
size_t invSize=Inventory::get(cat).size();
|
||||
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
|
||||
if(components.size()<invSize){//We need more space to display our items.
|
||||
|
@ -81,7 +81,7 @@ void Menu::InitializeInventoryWindow(){
|
||||
//Close the old inventory window and show the proper one.
|
||||
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+lastInventoryTypeOpened)->Enable(false);
|
||||
Component<MenuComponent>(data.menu.GetType(),lastInventoryTypeOpened+" Inventory Tab")->SetSelected(false);
|
||||
Component<InventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component->S(A::CATEGORY_NAME))->Enable(true);
|
||||
Component<RowInventoryScrollableWindowComponent>(data.menu.GetType(),"Inventory Display - "+data.component->S(A::CATEGORY_NAME))->Enable(true);
|
||||
Component<MenuComponent>(data.menu.GetType(),data.component->S(A::CATEGORY_NAME)+" Inventory Tab")->SetSelected(true);
|
||||
lastInventoryTypeOpened=data.component->S(A::CATEGORY_NAME);
|
||||
return true;
|
||||
@ -106,6 +106,7 @@ void Menu::InitializeInventoryWindow(){
|
||||
button->onClick(MenuFuncData{*inventoryWindow,game,button}); //Simulate a click of this button if it's the top one for an initial inventory display.
|
||||
}
|
||||
|
||||
Menu::AddInventoryListener(inventoryDisplay,category);
|
||||
inventoryDisplay->Enable(first);
|
||||
inventoryDisplay->SetCompactDescriptions(false);
|
||||
|
||||
|
@ -86,7 +86,7 @@ void ItemInfo::InitializeItems(){
|
||||
for(auto&[key,value]:DATA["ItemCategory"].GetKeys()){
|
||||
ITEM_CATEGORIES[key];
|
||||
Inventory::sortedInv[key];
|
||||
Menu::inventoryListeners[key];
|
||||
Menu::InitializeMenuListenerCategory(key);
|
||||
}
|
||||
|
||||
auto ReadItems=[&](datafile&data){
|
||||
@ -197,7 +197,7 @@ void ItemInfo::InitializeItems(){
|
||||
|
||||
ITEM_DATA.SetInitialized();
|
||||
ITEM_CATEGORIES.SetInitialized();
|
||||
Menu::inventoryListeners.SetInitialized();
|
||||
Menu::LockInListeners();
|
||||
|
||||
for(auto&[name,info]:ITEM_DATA){
|
||||
Item tempItem{1,name};
|
||||
|
@ -55,11 +55,13 @@ void Menu::InitializeLevelCompleteWindow(){
|
||||
|
||||
levelCompleteWindow->ADD("Monster Loot Outline",MenuComponent)({{0,32},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
|
||||
levelCompleteWindow->ADD("Monster Loot Label",MenuLabel)({{0,32},{windowSize.size.x-80.f,12}},"Monster Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END;
|
||||
levelCompleteWindow->ADD("Monster Loot Window",InventoryScrollableWindowComponent)({{0,44},{windowSize.size.x-80.f,60}},"Monster Loot","Monster Loot Popup Item Name","Monster Loot Popup Item Description",DO_NOTHING)END;
|
||||
auto monsterLootWindow=levelCompleteWindow->ADD("Monster Loot Window",InventoryScrollableWindowComponent)({{0,44},{windowSize.size.x-80.f,60}},"Monster Loot","Monster Loot Popup Item Name","Monster Loot Popup Item Description",DO_NOTHING)END;
|
||||
Menu::AddInventoryListener(monsterLootWindow,"Monster Loot");
|
||||
|
||||
levelCompleteWindow->ADD("Stage Loot Outline",MenuComponent)({{0,108},{windowSize.size.x-80.f,72}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE)END;
|
||||
levelCompleteWindow->ADD("Stage Loot Label",MenuLabel)({{0,108},{windowSize.size.x-80.f,12}},"Stage Loot",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW|ComponentAttr::OUTLINE)END;
|
||||
levelCompleteWindow->ADD("Stage Loot Window",InventoryScrollableWindowComponent)({{0,120},{windowSize.size.x-80.f,60}},"Stage Loot","Stage Loot Popup Item Name","Stage Loot Popup Item Description",DO_NOTHING)END;
|
||||
auto stageLootWindow=levelCompleteWindow->ADD("Stage Loot Window",InventoryScrollableWindowComponent)({{0,120},{windowSize.size.x-80.f,60}},"Stage Loot","Stage Loot Popup Item Name","Stage Loot Popup Item Description",DO_NOTHING)END;
|
||||
Menu::AddInventoryListener(stageLootWindow,"Stage Loot");
|
||||
|
||||
auto nextButtonAction=[](MenuFuncData data){
|
||||
Unlock::UnlockArea(State_OverworldMap::GetCurrentConnectionPoint().map);
|
||||
|
@ -49,6 +49,7 @@ std::map<MenuType,Menu*>Menu::menus;
|
||||
std::string Menu::themeSelection="BlueDefault";
|
||||
safeunorderedmap<std::string,Theme>Menu::themes;
|
||||
safemap<ITCategory,std::vector<MenuComponent*>>Menu::inventoryListeners;
|
||||
safemap<ITCategory,std::vector<MenuComponent*>>Menu::merchantInventoryListeners;
|
||||
std::vector<MenuComponent*>Menu::equipStatListeners;
|
||||
const vf2d Menu::CENTERED = {-456,-456};
|
||||
std::vector<MenuComponent*>Menu::unhandledComponents;
|
||||
@ -97,6 +98,9 @@ void Menu::InitializeMenus(){
|
||||
InitializeOverworldMenuWindow();
|
||||
InitializeCharacterMenuWindow();
|
||||
InitializeInventoryWindow();
|
||||
InitializeMerchantWindow();
|
||||
InitializeBuyItemWindow();
|
||||
InitializeSellItemWindow();
|
||||
|
||||
for(MenuType type=MenuType(int(MenuType::ENUM_START)+1);type<MenuType::ENUM_END;type=MenuType(int(type+1))){
|
||||
if(menus.count(type)==0){
|
||||
@ -573,6 +577,13 @@ void Menu::InventorySlotsUpdated(ITCategory cat){
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::MerchantInventorySlotsUpdated(ITCategory cat){
|
||||
//Update the inventory with a new inventory slot, since there's one additional item to interact with now.
|
||||
for(MenuComponent*component:merchantInventoryListeners.at(cat)){
|
||||
component->OnInventorySlotsUpdate(cat);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::AddInventoryListener(MenuComponent*component,ITCategory category){
|
||||
if(inventoryListeners.count(category)){
|
||||
std::vector<MenuComponent*>&listenerList=inventoryListeners.at(category);
|
||||
@ -585,6 +596,23 @@ void Menu::AddInventoryListener(MenuComponent*component,ITCategory category){
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::InitializeMenuListenerCategory(const std::string&category){
|
||||
inventoryListeners[category];
|
||||
merchantInventoryListeners[category];
|
||||
}
|
||||
|
||||
void Menu::AddMerchantInventoryListener(MenuComponent*component,ITCategory category){
|
||||
if(merchantInventoryListeners.count(category)){
|
||||
std::vector<MenuComponent*>&listenerList=merchantInventoryListeners.at(category);
|
||||
if(std::find(listenerList.begin(),listenerList.end(),component)!=listenerList.end()){
|
||||
ERR("WARNING! Component "<<component->name<<" has already been added to the "<<category<<" merchant listener list! There should not be any duplicates!!")
|
||||
}
|
||||
listenerList.push_back(component);
|
||||
}else{
|
||||
ERR("WARNING! Inventory category "<<category<<" does not exist!")
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::AddEquipStatListener(MenuComponent*component){
|
||||
if(std::find(equipStatListeners.begin(),equipStatListeners.end(),component)!=equipStatListeners.end()){
|
||||
ERR("WARNING! Component "<<component->name<<" has already been added to the Equip Stat listener list! There should not be any duplicates!!")
|
||||
@ -654,4 +682,9 @@ void Menu::RecalculateComponentCount(){
|
||||
|
||||
MenuType Menu::GetType(){
|
||||
return type;
|
||||
}
|
||||
|
||||
void Menu::LockInListeners(){
|
||||
inventoryListeners.SetInitialized();
|
||||
merchantInventoryListeners.SetInitialized();
|
||||
}
|
@ -72,6 +72,9 @@ enum MenuType{
|
||||
OVERWORLD_MENU,
|
||||
CHARACTER_MENU,
|
||||
INVENTORY,
|
||||
MERCHANT,
|
||||
BUY_ITEM,
|
||||
SELL_ITEM,
|
||||
#pragma region Enum End //DO NOT REMOVE
|
||||
///////////////////////////////////////////////////////////
|
||||
/*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
|
||||
@ -90,6 +93,9 @@ class Menu:public IAttributable{
|
||||
static void InitializeOverworldMenuWindow();
|
||||
static void InitializeCharacterMenuWindow();
|
||||
static void InitializeInventoryWindow();
|
||||
static void InitializeMerchantWindow();
|
||||
static void InitializeBuyItemWindow();
|
||||
static void InitializeSellItemWindow();
|
||||
|
||||
friend class Crawler;
|
||||
friend struct Player;
|
||||
@ -104,6 +110,7 @@ class Menu:public IAttributable{
|
||||
MenuComponent*draggingComponent=nullptr;
|
||||
ViewPort window;
|
||||
static safemap<ITCategory,std::vector<MenuComponent*>>inventoryListeners; //All menu components that care about inventory updates subscribe to this list indirectly (See Menu::AddInventoryListener()).
|
||||
static safemap<ITCategory,std::vector<MenuComponent*>>merchantInventoryListeners; //All menu components that care about merchant inventory updates subscribe to this list indirectly (See Menu::AddMerchantInventoryListener()).
|
||||
static std::vector<MenuComponent*>equipStatListeners; //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!
|
||||
@ -167,7 +174,9 @@ public:
|
||||
}
|
||||
void Update(Crawler*game);
|
||||
void Draw(Crawler*game);
|
||||
static void InitializeMenuListenerCategory(const std::string&category);
|
||||
static void InitializeMenus();
|
||||
static void LockInListeners();
|
||||
static void OpenMenu(MenuType menu,bool cover=true);
|
||||
static void CloseMenu();
|
||||
static void CloseAllMenus();
|
||||
@ -190,8 +199,10 @@ public:
|
||||
static Theme&GetCurrentTheme();
|
||||
bool UsingMouseNavigation();
|
||||
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 InventorySlotsUpdated(ITCategory cat); //Called whenever the player's inventory gets modified.
|
||||
static void MerchantInventorySlotsUpdated(ITCategory cat); //Called whenever a traveling merchant's inventory item gets updated.
|
||||
static void AddInventoryListener(MenuComponent*component,ITCategory category); //Adds a component to be in a given listener category.
|
||||
static void AddMerchantInventoryListener(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.
|
||||
|
@ -45,7 +45,7 @@ INCLUDE_game
|
||||
using A=Attribute;
|
||||
|
||||
MenuComponent::MenuComponent(geom2d::rect<float>rect,std::string label,MenuFunc onClick,ButtonAttr attributes)
|
||||
:rect(rect),originalPos(rect.pos),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()){
|
||||
:rect(rect),originalPos(rect.pos),label(label),menuDest(MenuType::ENUM_END),onClick(onClick),hoverEffect(0),selectable(!(attributes&ButtonAttr::UNSELECTABLE)),selectableViaKeyboard(!(attributes&ButtonAttr::UNSELECTABLE_VIA_KEYBOARD)),memoryLeakInfo(Menu::GetMemoryLeakReportInfo()),fitToLabel(attributes&ButtonAttr::FIT_TO_LABEL){
|
||||
Menu::unhandledComponents.push_back(this);
|
||||
}
|
||||
|
||||
@ -114,7 +114,14 @@ void MenuComponent::DrawDecal(ViewPort&window,bool focused){
|
||||
window.FillRectDecal(rect.pos+V(A::DRAW_OFFSET)+vf2d{0,rect.size.y-1+1},{rect.size.x+1,1});
|
||||
}
|
||||
if(showDefaultLabel){
|
||||
window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*labelScaling,label,WHITE,labelScaling);
|
||||
vf2d adjustedScale=labelScaling;
|
||||
if(fitToLabel){
|
||||
float sizeRatio=((game->GetTextSizeProp(label)*adjustedScale).x)/(rect.size.x-2);
|
||||
if(sizeRatio>1){
|
||||
adjustedScale.x/=sizeRatio;
|
||||
}
|
||||
}
|
||||
window.DrawStringPropDecal(rect.pos+V(A::DRAW_OFFSET)+rect.size/2-vf2d(game->GetTextSizeProp(label))/2.f*adjustedScale,label,WHITE,adjustedScale);
|
||||
}
|
||||
if(selected){
|
||||
switch(selectionType){
|
||||
|
@ -40,17 +40,19 @@ All rights reserved.
|
||||
#include "BitwiseEnum.h"
|
||||
|
||||
enum class ButtonAttr{
|
||||
NONE=0b00,
|
||||
UNSELECTABLE=0b01, //Makes the component unselectable.
|
||||
UNSELECTABLE_VIA_KEYBOARD=0b10, //Makes the component unselectable via keyboard.
|
||||
NONE= 0b000,
|
||||
UNSELECTABLE= 0b001, //Makes the component unselectable.
|
||||
UNSELECTABLE_VIA_KEYBOARD= 0b010, //Makes the component unselectable via keyboard.
|
||||
FIT_TO_LABEL= 0b100, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping.
|
||||
};
|
||||
|
||||
enum class ComponentAttr{
|
||||
NONE=0b0000,
|
||||
LEFT_ALIGN=0b0001, //Labels are centered by default.
|
||||
SHADOW=0b0010, //Adds shadows to the label text.
|
||||
OUTLINE=0b0100, //Adds an outline around the component.
|
||||
BACKGROUND=0b1000, //Renders the background of the menu theme for this component.
|
||||
NONE= 0b00000,
|
||||
LEFT_ALIGN= 0b00001, //Labels are centered by default.
|
||||
SHADOW= 0b00010, //Adds shadows to the label text.
|
||||
OUTLINE= 0b00100, //Adds an outline around the component.
|
||||
BACKGROUND= 0b01000, //Renders the background of the menu theme for this component.
|
||||
FIT_TO_LABEL= 0b10000, //Scales the text horizontally to fit the label if the text takes up more space rather than wrapping.
|
||||
};
|
||||
|
||||
enum class SelectionType{
|
||||
@ -105,6 +107,7 @@ protected:
|
||||
bool disabled=false; //If set to true, this component will not be rendered or updated.
|
||||
bool renderInMain=true; //If set to false, this component is the responsibility of some other windowing system and won't be rendered or updated via the main window loop.
|
||||
bool valid=true; //If set to false, this would cause the component to be removed.
|
||||
bool fitToLabel=false; //Will shrink text horizontally to fit the size of the label if the display text is too large.
|
||||
vf2d labelScaling={1,1};
|
||||
virtual void Update(Crawler*game);
|
||||
virtual void DrawDecal(ViewPort&window,bool focused);
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
border=attributes&ComponentAttr::OUTLINE;
|
||||
this->background=attributes&ComponentAttr::BACKGROUND;
|
||||
showDefaultLabel=false;
|
||||
fitToLabel=attributes&ComponentAttr::FIT_TO_LABEL;
|
||||
}
|
||||
inline virtual void SetLabel(std::string text){
|
||||
label=text;
|
||||
@ -66,15 +67,27 @@ protected:
|
||||
}
|
||||
virtual void inline DrawDecal(ViewPort&window,bool focused)override{
|
||||
MenuComponent::DrawDecal(window,focused);
|
||||
std::string wrappedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
|
||||
vf2d drawPos=rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered.
|
||||
if(!centered){
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}; //We should at least vertically align here.
|
||||
std::string adjustedText=label;
|
||||
if(!fitToLabel){
|
||||
adjustedText=util::WrapText(game,label,int(rect.size.x),true,{float(scale),float(scale)});
|
||||
}
|
||||
vf2d adjustedScale={scale,scale};
|
||||
if(fitToLabel){
|
||||
float sizeRatio=((game->GetTextSizeProp(label)*adjustedScale).x)/(rect.size.x-2);
|
||||
if(sizeRatio>1){
|
||||
adjustedScale.x/=sizeRatio;
|
||||
}
|
||||
}
|
||||
|
||||
vf2d drawPos=rect.middle()-vf2d{game->GetTextSizeProp(adjustedText)}*float(adjustedScale.x)/2; //Assume centered.
|
||||
if(!centered){
|
||||
drawPos=vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(adjustedText).y/2}; //We should at least vertically align here.
|
||||
}
|
||||
|
||||
if(shadow){
|
||||
window.DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,{float(scale),float(scale)});
|
||||
window.DrawShadowStringPropDecal(drawPos,adjustedText,WHITE,BLACK,adjustedScale);
|
||||
}else{
|
||||
window.DrawStringPropDecal(drawPos,wrappedText,WHITE,{float(scale),float(scale)});
|
||||
window.DrawStringPropDecal(drawPos,adjustedText,WHITE,adjustedScale);
|
||||
}
|
||||
}
|
||||
};
|
@ -36,18 +36,22 @@ All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
|
||||
#include "Menu.h"
|
||||
#include "Merchant.h"
|
||||
#include "Crawler.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_ITEM_CATEGORIES
|
||||
|
||||
std::map<Chapter,std::vector<Merchant>>Merchant::merchants;
|
||||
std::map<ITCategory,std::vector<Item*>>Merchant::sortedItems;
|
||||
MerchantFunctionPrimingData Merchant::purchaseFunctionPrimed("CanPurchaseItem()");
|
||||
MerchantFunctionPrimingData Merchant::sellFunctionPrimed("CanSellItem()");
|
||||
Merchant Merchant::travelingMerchant;
|
||||
|
||||
const Merchant&Merchant::GetRandomMerchant(Chapter chapter){
|
||||
return merchants[chapter][rand()%(merchants[chapter].size()-1)];
|
||||
const Merchant&newMerchant=merchants[chapter][rand()%(merchants[chapter].size()-1)];
|
||||
return newMerchant;
|
||||
}
|
||||
|
||||
const std::string&Merchant::GetDisplayName()const{
|
||||
@ -58,6 +62,10 @@ const std::vector<Item>&Merchant::GetShopItems()const{
|
||||
return shopItems;
|
||||
}
|
||||
|
||||
const std::vector<Item*>&Merchant::GetShopItems(ITCategory category){
|
||||
return sortedItems[category];
|
||||
}
|
||||
|
||||
Merchant&Merchant::AddMerchant(Chapter chapter){
|
||||
merchants[chapter].push_back({});
|
||||
return merchants[chapter].back();
|
||||
@ -65,6 +73,20 @@ Merchant&Merchant::AddMerchant(Chapter chapter){
|
||||
|
||||
void Merchant::AddItem(IT item,uint32_t amt,uint8_t enhancementLevel){
|
||||
shopItems.push_back(Item{amt,item,enhancementLevel});
|
||||
if(&GetCurrentTravelingMerchant()==this){
|
||||
UpdateSortedItemsList();
|
||||
Menu::MerchantInventorySlotsUpdated(ITEM_DATA[item].Category());
|
||||
}
|
||||
}
|
||||
|
||||
void Merchant::UpdateSortedItemsList(){
|
||||
const Merchant&merchant=GetCurrentTravelingMerchant();
|
||||
for(auto&[key,items]:ITEM_CATEGORIES){
|
||||
sortedItems[key].clear();
|
||||
}
|
||||
std::for_each(merchant.shopItems.begin(),merchant.shopItems.end(),[](const Item&item){
|
||||
sortedItems[item.Category()].push_back(const_cast<Item*>(&item));
|
||||
});
|
||||
}
|
||||
|
||||
INCLUDE_DATA
|
||||
@ -137,7 +159,7 @@ bool Merchant::CanSellItem(IT item,uint32_t amt)const{
|
||||
};
|
||||
void Merchant::PurchaseItem(IT item,uint32_t amt){
|
||||
purchaseFunctionPrimed.Validate(item,amt);
|
||||
|
||||
|
||||
uint32_t totalCost=0U;
|
||||
for(Item&it:shopItems){
|
||||
if(it==item){
|
||||
@ -181,6 +203,10 @@ void Merchant::SellItem(IT item,uint32_t amt){
|
||||
|
||||
void Merchant::RandomizeTravelingMerchant(){
|
||||
travelingMerchant=GetRandomMerchant(game->GetCurrentChapter());
|
||||
for(auto&[key,items]:ITEM_CATEGORIES){
|
||||
Menu::MerchantInventorySlotsUpdated(key);
|
||||
}
|
||||
UpdateSortedItemsList();
|
||||
};
|
||||
Merchant&Merchant::GetCurrentTravelingMerchant(){
|
||||
return travelingMerchant;
|
||||
|
@ -42,6 +42,7 @@ class Item;
|
||||
|
||||
using Chapter=int;
|
||||
using IT=std::string;
|
||||
using ITCategory=std::string;
|
||||
|
||||
class Merchant{
|
||||
public:
|
||||
@ -49,6 +50,7 @@ public:
|
||||
static Merchant&GetCurrentTravelingMerchant();
|
||||
const std::string&GetDisplayName()const;
|
||||
const std::vector<Item>&GetShopItems()const;
|
||||
const static std::vector<Item*>&GetShopItems(ITCategory category);
|
||||
void AddItem(IT item,uint32_t amt=1,uint8_t enhancementLevel=0U);
|
||||
bool CanPurchaseItem(IT item,uint32_t amt=1U)const;
|
||||
bool CanSellItem(IT item,uint32_t amt=1U)const;
|
||||
@ -65,4 +67,6 @@ private:
|
||||
static std::map<Chapter,std::vector<Merchant>>merchants;
|
||||
std::string displayName;
|
||||
std::vector<Item>shopItems;
|
||||
static std::map<ITCategory,std::vector<Item*>>sortedItems;
|
||||
static void UpdateSortedItemsList();
|
||||
};
|
92
Crawler/MerchantWindow.cpp
Normal file
92
Crawler/MerchantWindow.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#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 "RowMerchantInventoryScrollableWindowComponent.h"
|
||||
#include "MenuItemItemButton.h"
|
||||
#include "MenuComponent.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_ITEM_CATEGORIES
|
||||
INCLUDE_DATA
|
||||
|
||||
void Menu::InitializeMerchantWindow(){
|
||||
Menu*merchantWindow=CreateMenu(MERCHANT,CENTERED,game->GetScreenSize()-vi2d{24,24});
|
||||
|
||||
static std::string lastInventoryTypeOpened="";
|
||||
|
||||
std::vector<std::pair<std::string,int>>categories;
|
||||
for(auto&[category,items]:ITEM_CATEGORIES){
|
||||
if(DATA["ItemCategory"][category].GetString(0)=="!HIDE")continue; //This category is meant to be hidden!
|
||||
categories.push_back({category,DATA["ItemCategory"][category].GetInt(0)}); //We assume the first value becomes the sort order we wish to use.
|
||||
}
|
||||
std::sort(categories.begin(),categories.end(),[](std::pair<std::string,int>&cat1,std::pair<std::string,int>&cat2){return cat1.second<cat2.second;});
|
||||
|
||||
|
||||
auto inventoryDisplay=merchantWindow->ADD("Merchant Inventory Display",RowMerchantInventoryScrollableWindowComponent)({{2,28},{220,merchantWindow->size.y-44}},"Item Name Label","Item Description Label",
|
||||
[](MenuFuncData data){
|
||||
RowItemDisplay*item=dynamic_cast<RowItemDisplay*>(data.component);
|
||||
Component<MenuLabel>(BUY_ITEM,"Item Purchase Header")->S(A::ITEM_NAME)=item->GetItem().ActualName();
|
||||
Component<MenuLabel>(BUY_ITEM,"Item Purchase Header")->SetLabel("Buying "+item->GetItem().DisplayName());
|
||||
Menu::OpenMenu(BUY_ITEM);
|
||||
return true;
|
||||
},
|
||||
[](MenuFuncData data){
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->SetItem(dynamic_cast<RowItemDisplay*>(data.component)->GetItem());
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->UpdateIcon();
|
||||
return true;
|
||||
},
|
||||
[](MenuFuncData data){
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->SetItem(Item::BLANK);
|
||||
Component<MenuItemItemButton>(data.menu.GetType(),"Item Icon")->UpdateIcon();
|
||||
return true;
|
||||
},{.padding=1,.size={220-13,28}})END;
|
||||
|
||||
for(auto&[category,items]:ITEM_CATEGORIES){
|
||||
Menu::AddMerchantInventoryListener(inventoryDisplay,category);
|
||||
}
|
||||
|
||||
#pragma region Inventory Description
|
||||
float inventoryDescriptionWidth=merchantWindow->pos.x+merchantWindow->size.x-26-224;
|
||||
merchantWindow->ADD("Item Description Outline",MenuLabel)({{224,28},{inventoryDescriptionWidth,merchantWindow->size.y-44}},"",1,ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::BACKGROUND)END;
|
||||
merchantWindow->ADD("Item Icon",MenuItemItemButton)({{226+inventoryDescriptionWidth/2-24,30},{48,48}},Item::BLANK,MenuType::ENUM_END,DO_NOTHING,"","",IconButtonAttr::NOT_SELECTABLE)END;
|
||||
merchantWindow->ADD("Item Name Label",MenuLabel)({{226,84},{inventoryDescriptionWidth-6,12}},"",0.75f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
|
||||
merchantWindow->ADD("Item Description Label",MenuLabel)({{226,94},{inventoryDescriptionWidth-6,merchantWindow->size.y-44-66}},"",0.5f,ComponentAttr::LEFT_ALIGN|ComponentAttr::SHADOW)END;
|
||||
#pragma endregion
|
||||
}
|
@ -72,4 +72,5 @@ enum class Attribute{
|
||||
BASE_TEXT,
|
||||
CATEGORY_NAME,
|
||||
DRAW_OFFSET,
|
||||
ITEM_NAME,
|
||||
};
|
@ -44,7 +44,7 @@ public:
|
||||
inline RowInventoryScrollableWindowComponent(geom2d::rect<float>rect,ITCategory invType,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::function<bool(MenuFuncData)>inventoryButtonClickAction,std::function<bool(MenuFuncData)>inventoryButtonHoverAction,std::function<bool(MenuFuncData)>inventoryButtonMouseOutAction,InventoryWindowOptions options={.padding=8,.size={24,24}},bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
|
||||
:InventoryScrollableWindowComponent(rect,invType,itemNameLabelName,itemDescriptionLabelName,inventoryButtonClickAction,inventoryButtonHoverAction,inventoryButtonMouseOutAction,options,inventoryButtonsActive,attributes){}
|
||||
|
||||
virtual inline void SetCompactDescriptions(bool compact)override{
|
||||
virtual inline void SetCompactDescriptions(bool compact)override final{
|
||||
if(compact)this->compact=COMPACT;
|
||||
else this->compact=NON_COMPACT;
|
||||
for(MenuComponent*component:components){
|
||||
|
86
Crawler/RowMerchantInventoryScrollableWindowComponent.h
Normal file
86
Crawler/RowMerchantInventoryScrollableWindowComponent.h
Normal file
@ -0,0 +1,86 @@
|
||||
#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 "RowInventoryScrollableWindowComponent.h"
|
||||
|
||||
class RowMerchantInventoryScrollableWindowComponent:public RowInventoryScrollableWindowComponent{
|
||||
public:
|
||||
inline RowMerchantInventoryScrollableWindowComponent(geom2d::rect<float>rect,std::string itemNameLabelName,std::string itemDescriptionLabelName,std::function<bool(MenuFuncData)>inventoryButtonClickAction,std::function<bool(MenuFuncData)>inventoryButtonHoverAction,std::function<bool(MenuFuncData)>inventoryButtonMouseOutAction,InventoryWindowOptions options={.padding=8,.size={24,24}},bool inventoryButtonsActive=true,ComponentAttr attributes=ComponentAttr::BACKGROUND|ComponentAttr::OUTLINE)
|
||||
:RowInventoryScrollableWindowComponent(rect,"",itemNameLabelName,itemDescriptionLabelName,inventoryButtonClickAction,inventoryButtonHoverAction,inventoryButtonMouseOutAction,options,inventoryButtonsActive,attributes){}
|
||||
|
||||
|
||||
virtual inline void OnInventorySlotsUpdate(ITCategory cat)override{
|
||||
const std::vector<Item>&merchantInv=Merchant::GetCurrentTravelingMerchant().GetShopItems();
|
||||
//We only want to refresh the inventory slots if the component count no longer matches what's actually in our inventory.
|
||||
if(components.size()<merchantInv.size()){//We need more space to display our items.
|
||||
AddButtonOnSlotUpdate(cat);
|
||||
}else
|
||||
if(components.size()>merchantInv.size()){ //There are empty spots, so let's clean up.
|
||||
RemoveEmptySlots();
|
||||
}
|
||||
}
|
||||
|
||||
virtual inline void AddButtonOnSlotUpdate(ITCategory cat)override{
|
||||
const std::vector<Item>&merchantInv=Merchant::GetCurrentTravelingMerchant().GetShopItems();
|
||||
size_t invSize=merchantInv.size();
|
||||
int invWidth=int(rect.size.x/(float(options.size.x)+options.padding));
|
||||
int x=int((invSize-1)%invWidth);
|
||||
int y=int((invSize-1)/invWidth);
|
||||
int itemIndex=y*invWidth+x;
|
||||
|
||||
vf2d buttonSize=options.size;
|
||||
vf2d totalSpacing={options.padding+buttonSize.x,options.padding+buttonSize.y};
|
||||
|
||||
auto newItem=ADD("item_"+cat+"_"+std::to_string(itemIndex),RowItemDisplay)({totalSpacing*vf2d{float(x),float(y)},buttonSize},Merchant::GetCurrentTravelingMerchant().GetShopItems()[itemIndex],inventoryButtonClickAction,itemNameLabelName,itemDescriptionLabelName,inventoryButtonsActive?ButtonAttr::NONE:ButtonAttr::UNSELECTABLE)END;
|
||||
newItem->SetCompactDescriptions(compact==COMPACT);
|
||||
newItem->SetHoverFunc(inventoryButtonHoverAction);
|
||||
newItem->SetMouseOutFunc(inventoryButtonMouseOutAction);
|
||||
|
||||
//Since we are indexing into a vector reference which is inevitably going to get erased as we add more items,
|
||||
//we must update all previous menu component references in case that memory has been overwritten!
|
||||
for(int counter=0;MenuComponent*component:components){
|
||||
RowItemDisplay*item=dynamic_cast<RowItemDisplay*>(component);
|
||||
if(item!=nullptr){
|
||||
item->SetItem(merchantInv[itemIndex]);
|
||||
}else{
|
||||
ERR("WARNING! Could not properly cast item to RowItemDisplay* type!");
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
};
|
45
Crawler/SellItemWindow.cpp
Normal file
45
Crawler/SellItemWindow.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#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 "MenuLabel.h"
|
||||
|
||||
void Menu::InitializeSellItemWindow(){
|
||||
Menu*sellItemWindow=CreateMenu(SELL_ITEM,CENTERED,{120,72});
|
||||
|
||||
}
|
@ -92,6 +92,10 @@ void State_OverworldMap::OnUserUpdate(Crawler*game){
|
||||
Menu::OpenMenu(OVERWORLD_MENU);
|
||||
}
|
||||
|
||||
if(game->GetKey(S).bPressed){
|
||||
Menu::OpenMenu(MERCHANT);
|
||||
}
|
||||
|
||||
#pragma region Handle Connection Point Clicking and Movement
|
||||
for(ConnectionPoint&cp:connections){
|
||||
if(game->GetMouse(Mouse::LEFT).bPressed&&geom2d::overlaps(game->GetWorldMousePos(),cp.rect)){
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
#define VERSION_PATCH 1
|
||||
#define VERSION_BUILD 4187
|
||||
#define VERSION_BUILD 4220
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user