# pragma region License
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Copyright 2024 Joshua Sigona < sigonasr2 @ gmail . 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 © 2024 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
*/
# pragma endregion
# include "Menu.h"
# include "AdventuresInLestoria.h"
# include "MenuItemItemButton.h"
# include "PlayerMoneyLabel.h"
# include "RowInventoryScrollableWindowComponent.h"
# include "EnhancementStatsLabel.h"
# include "RequiredMaterialsList.h"
INCLUDE_game
INCLUDE_ITEM_CATEGORIES
INCLUDE_DATA
INCLUDE_GFX
void Menu : : InitializeBlacksmithCraftingWindow ( ) {
Menu * blacksmithWindow = CreateMenu ( BLACKSMITH , CENTERED , game - > GetScreenSize ( ) - vi2d { 52 , 52 } ) ;
std : : vector < std : : pair < std : : string , int > > categories ;
std : : vector < std : : weak_ptr < Item > > weaponInventory ;
std : : vector < std : : weak_ptr < Item > > armorInventory ;
# pragma region Build Equipment Lists
std : : for_each ( Inventory : : get ( " Equipment " ) . begin ( ) , Inventory : : get ( " Equipment " ) . end ( ) , [ & ] ( const std : : weak_ptr < Item > item ) {
switch ( item . lock ( ) - > GetEquipSlot ( ) ) {
case EquipSlot : : WEAPON : {
weaponInventory . push_back ( item ) ;
} break ;
case EquipSlot : : NONE :
case EquipSlot : : RING1 :
case EquipSlot : : RING2 : break ; //No-op
default : { //We assume everything else is armor.
armorInventory . push_back ( item ) ;
}
}
} ) ;
# pragma endregion
auto weaponTab = blacksmithWindow - > ADD ( " Weapon Tab " , MenuComponent ) ( geom2d : : rect < float > { { 2 , 0 } , { blacksmithWindow - > size . x / 2 - 4 , 24 } } , " Weapon " , [ ] ( MenuFuncData data ) {
Component < MenuComponent > ( BLACKSMITH , " Armor Tab " ) - > selected = false ;
Component < RowInventoryScrollableWindowComponent > ( BLACKSMITH , " Weapon Inventory Display " ) - > Enable ( true ) ;
Component < RowInventoryScrollableWindowComponent > ( BLACKSMITH , " Armor Inventory Display " ) - > Enable ( false ) ;
data . component . lock ( ) - > selected = true ;
return true ;
} ) END ;
weaponTab - > selected = true ;
weaponTab - > selectionType = SelectionType : : HIGHLIGHT ;
auto armorTab = blacksmithWindow - > ADD ( " Armor Tab " , MenuComponent ) ( geom2d : : rect < float > { { blacksmithWindow - > size . x / 2 + 2 , 0 } , { blacksmithWindow - > size . x / 2 - 4 , 24 } } , " Armor " , [ ] ( MenuFuncData data ) {
Component < MenuComponent > ( BLACKSMITH , " Weapon Tab " ) - > selected = false ;
Component < RowInventoryScrollableWindowComponent > ( BLACKSMITH , " Weapon Inventory Display " ) - > Enable ( false ) ;
Component < RowInventoryScrollableWindowComponent > ( BLACKSMITH , " Armor Inventory Display " ) - > Enable ( true ) ;
data . component . lock ( ) - > selected = true ;
return true ;
} ) END ;
armorTab - > selectionType = SelectionType : : HIGHLIGHT ;
# pragma region Weapon Inventory Display
auto weaponsDisplay = blacksmithWindow - > ADD ( " Weapon Inventory Display " , RowInventoryScrollableWindowComponent ) ( geom2d : : rect < float > { { 2 , 28 } , { 220 , blacksmithWindow - > size . y - 44 } } , " Item Name Label " , " Item Description Label " ,
[ ] ( MenuFuncData data ) {
std : : weak_ptr < RowItemDisplay > comp = DYNAMIC_POINTER_CAST < RowItemDisplay > ( data . component . lock ( ) ) ;
const std : : weak_ptr < Item > item = comp . lock ( ) - > GetItem ( ) ;
std : : string label = " " ;
if ( Inventory : : GetItemCount ( item . lock ( ) - > ActualName ( ) ) = = 0 ) { //If we don't own the item we have to create it first.
if ( item . lock ( ) - > EnhancementIsPossible ( ) & & item . lock ( ) - > GetEnhancementInfo ( ) . size ( ) > item . lock ( ) - > EnhancementLevel ( ) + 1 ) {
label = " " ;
}
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 ( ) ) ;
} else { //We will open the menu that lets us enhance by one level.
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 ( " Enhancing {} " , item . lock ( ) - > DisplayName ( ) ) ) ;
Component < EnhancementStatsLabel > ( CRAFT_ITEM , " Enhancement Stats Label " ) - > SetItem ( item ) ;
Component < RequiredMaterialsList > ( CRAFT_ITEM , " Required Materials List " ) - > SetItem ( item ) ;
Component < MenuComponent > ( CRAFT_ITEM , " Craft Button " ) - > SetGrayedOut ( ! item . lock ( ) - > CanEnhanceItem ( ) ) ;
}
Menu : : OpenMenu ( CRAFT_ITEM ) ;
return true ;
} ,
[ ] ( MenuFuncData data ) {
std : : weak_ptr < RowItemDisplay > rowItem = DYNAMIC_POINTER_CAST < RowItemDisplay > ( data . component . lock ( ) ) ;
Component < MenuItemItemButton > ( BLACKSMITH , " Item Icon " ) - > SetItem ( rowItem . lock ( ) - > GetItem ( ) ) ;
return true ;
} ,
[ ] ( MenuFuncData data ) {
Component < MenuItemItemButton > ( BLACKSMITH , " Item Icon " ) - > SetItem ( Item : : BLANK ) ;
return true ;
} ,
InventoryCreator : : RowPlayerWeapons_InventoryUpdate ,
InventoryWindowOptions { . padding = 1 , . size = { 207 , 28 } }
) END ;
weaponsDisplay - > SetCompactDescriptions ( CRAFTING_INFO ) ;
# pragma endregion
# pragma region Armor Inventory Display
auto armorDisplay = blacksmithWindow - > ADD ( " Armor Inventory Display " , RowInventoryScrollableWindowComponent ) ( geom2d : : rect < float > { { 2 , 28 } , { 220 , blacksmithWindow - > size . y - 44 } } , " Item Name Label " , " Item Description Label " ,
[ ] ( MenuFuncData data ) {
Menu : : OpenMenu ( CRAFT_ITEM ) ;
std : : weak_ptr < RowItemDisplay > comp = DYNAMIC_POINTER_CAST < RowItemDisplay > ( data . component . lock ( ) ) ;
const std : : weak_ptr < Item > item = comp . lock ( ) - > GetItem ( ) ;
std : : string label = " " ;
if ( Inventory : : GetItemCount ( item . lock ( ) - > ActualName ( ) ) = = 0 ) { //If we don't own the item we have to create it first.
if ( item . lock ( ) - > EnhancementIsPossible ( ) & & item . lock ( ) - > GetEnhancementInfo ( ) . size ( ) > item . lock ( ) - > EnhancementLevel ( ) + 1 ) {
label = " " ;
}
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 ( ) ) ;
} else { //We will open the menu that lets us enhance by one level.
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 ( " Enhancing {} " , item . lock ( ) - > DisplayName ( ) ) ) ;
Component < EnhancementStatsLabel > ( CRAFT_ITEM , " Enhancement Stats Label " ) - > SetItem ( item ) ;
Component < RequiredMaterialsList > ( CRAFT_ITEM , " Required Materials List " ) - > SetItem ( item ) ;
Component < MenuComponent > ( CRAFT_ITEM , " Craft Button " ) - > SetGrayedOut ( ! item . lock ( ) - > CanEnhanceItem ( ) ) ;
}
return true ;
} ,
[ ] ( MenuFuncData data ) {
std : : weak_ptr < RowItemDisplay > rowItem = DYNAMIC_POINTER_CAST < RowItemDisplay > ( data . component . lock ( ) ) ;
Component < MenuItemItemButton > ( BLACKSMITH , " Item Icon " ) - > SetItem ( rowItem . lock ( ) - > GetItem ( ) ) ;
return true ;
} ,
[ ] ( MenuFuncData data ) {
Component < MenuItemItemButton > ( BLACKSMITH , " Item Icon " ) - > SetItem ( Item : : BLANK ) ;
return true ;
} ,
InventoryCreator : : RowPlayerArmor_InventoryUpdate ,
InventoryWindowOptions { . padding = 1 , . size = { 207 , 28 } }
) END ;
armorDisplay - > Enable ( false ) ;
armorDisplay - > SetCompactDescriptions ( CRAFTING_INFO ) ;
# pragma endregion
# pragma region Inventory Description
float inventoryDescriptionWidth = blacksmithWindow - > pos . x + blacksmithWindow - > size . x - 26 - 224 ;
blacksmithWindow - > ADD ( " Item Description Outline " , MenuLabel ) ( geom2d : : rect < float > { { 224 , 28 } , { inventoryDescriptionWidth , blacksmithWindow - > size . y - 44 } } , " " , 1 , ComponentAttr : : LEFT_ALIGN | ComponentAttr : : OUTLINE | ComponentAttr : : BACKGROUND ) END ;
blacksmithWindow - > ADD ( " Item Icon " , MenuItemItemButton ) ( geom2d : : rect < float > { { 226 + inventoryDescriptionWidth / 2 - 24 , 30 } , { 48 , 48 } } , Item : : BLANK , MenuType : : ENUM_END , DO_NOTHING , " " , " " , IconButtonAttr : : NOT_SELECTABLE ) END ;
blacksmithWindow - > ADD ( " Item Name Label " , MenuLabel ) ( geom2d : : rect < float > { { 226 , 84 } , { inventoryDescriptionWidth - 6 , 12 } } , " " , 0.75f , ComponentAttr : : LEFT_ALIGN | ComponentAttr : : SHADOW ) END ;
blacksmithWindow - > ADD ( " Item Description Label " , MenuLabel ) ( geom2d : : rect < float > { { 226 , 94 } , { inventoryDescriptionWidth - 6 , blacksmithWindow - > size . y - 44 - 66 } } , " " , 0.5f , ComponentAttr : : LEFT_ALIGN | ComponentAttr : : SHADOW ) END ;
# pragma endregion
# pragma region Money Display
vf2d moneyIconPos = { 224 + inventoryDescriptionWidth - 24 , 28 + blacksmithWindow - > size . y - 44 + 6 } ;
auto moneyIcon = blacksmithWindow - > ADD ( " Money Icon " , MenuIconButton ) ( geom2d : : rect < float > { 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 = blacksmithWindow - > ADD ( " Money Label " , PlayerMoneyLabel ) ( geom2d : : rect < float > { moneyIconPos - vf2d { 2 + moneyTextSize . x , - 2 } , moneyTextSize } , 2 , ComponentAttr : : SHADOW | ComponentAttr : : LEFT_ALIGN | ComponentAttr : : FIT_TO_LABEL ) END ;
moneyDisplay - > SetRightAlignment ( true ) ;
Player : : AddMoneyListener ( moneyDisplay ) ;
# pragma endregion
blacksmithWindow - > ADD ( " Leave Button " , MenuComponent ) ( geom2d : : rect < float > { { blacksmithWindow - > size . x / 2 - 48 , 28 + blacksmithWindow - > size . y - 44 + 6 } , { 96 , 24 } } , " Leave " , MenuType : : ENUM_END ,
[ ] ( MenuFuncData data ) {
Menu : : CloseMenu ( ) ;
return true ;
} , vf2d { 2 , 2 } ) END ;
}