2026-03-01 12:16:08 +08:00
# include "stdafx.h"
# include "..\..\..\Minecraft.World\net.minecraft.world.item.crafting.h"
# include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
# include "..\..\..\Minecraft.World\net.minecraft.stats.h"
# include "..\..\LocalPlayer.h"
# include "IUIScene_CraftingMenu.h"
Recipy : : _eGroupType IUIScene_CraftingMenu : : m_GroupTypeMapping4GridA [ IUIScene_CraftingMenu : : m_iMaxGroup2x2 ] =
{
Recipy : : eGroupType_Structure ,
Recipy : : eGroupType_Tool ,
Recipy : : eGroupType_Food ,
Recipy : : eGroupType_Mechanism ,
Recipy : : eGroupType_Transport ,
Recipy : : eGroupType_Decoration ,
} ;
Recipy : : _eGroupType IUIScene_CraftingMenu : : m_GroupTypeMapping9GridA [ IUIScene_CraftingMenu : : m_iMaxGroup3x3 ] =
{
Recipy : : eGroupType_Structure ,
Recipy : : eGroupType_Tool ,
Recipy : : eGroupType_Food ,
Recipy : : eGroupType_Armour ,
Recipy : : eGroupType_Mechanism ,
Recipy : : eGroupType_Transport ,
Recipy : : eGroupType_Decoration ,
} ;
LPCWSTR IUIScene_CraftingMenu : : m_GroupIconNameA [ m_iMaxGroup3x3 ] =
{
L " Structures " , //Recipy::eGroupType_Structure,
L " Tools " , //Recipy::eGroupType_Tool,
L " Food " , //Recipy::eGroupType_Food,
L " Armour " , //Recipy::eGroupType_Armour,
L " Mechanisms " , //Recipy::eGroupType_Mechanism,
L " Transport " , //Recipy::eGroupType_Transport,
L " Decoration " , //Recipy::eGroupType_Decoration,
} ;
IUIScene_CraftingMenu : : _eGroupTab IUIScene_CraftingMenu : : m_GroupTabBkgMapping2x2A [ m_iMaxGroup2x2 ] =
{
eGroupTab_Left ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Right ,
} ;
IUIScene_CraftingMenu : : _eGroupTab IUIScene_CraftingMenu : : m_GroupTabBkgMapping3x3A [ m_iMaxGroup3x3 ] =
{
eGroupTab_Left ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Middle ,
eGroupTab_Right ,
} ;
// mapping array to map the base objects to their description string
// This should map the enums
// enum
// {
// eBaseItemType_undefined=0,
// eBaseItemType_sword,
// eBaseItemType_shovel,
// eBaseItemType_pickaxe,
// eBaseItemType_hatchet,
// eBaseItemType_hoe,
// eBaseItemType_door,
// eBaseItemType_helmet,
// eBaseItemType_chestplate,
// eBaseItemType_leggings,
// eBaseItemType_boots,
// eBaseItemType_ingot,
// eBaseItemType_rail,
// eBaseItemType_block,
// eBaseItemType_pressureplate,
// eBaseItemType_stairs,
// eBaseItemType_cloth,
// eBaseItemType_dyepowder,
// eBaseItemType_structplanks
// eBaseItemType_structblock,
// eBaseItemType_slab,
// eBaseItemType_halfslab,
// eBaseItemType_torch,
// eBaseItemType_bow,
// eBaseItemType_pockettool,
// eBaseItemType_utensil,
2026-03-02 15:58:20 +07:00
//
2026-03-01 12:16:08 +08:00
// }
// eBaseItemType;
IUIScene_CraftingMenu : : IUIScene_CraftingMenu ( )
{
m_iCurrentSlotHIndex = 0 ;
m_iCurrentSlotVIndex = 1 ;
for ( int i = 0 ; i < m_iMaxHSlotC ; i + + )
{
CanBeMadeA [ i ] . iCount = 0 ;
CanBeMadeA [ i ] . iItemBaseType = 0 ;
}
memset ( CanBeMadeA , 0 , sizeof ( CANBEMADE ) * m_iMaxHSlotC ) ;
m_iRecipeC = 0 ;
m_iGroupIndex = 0 ;
for ( int i = 0 ; i < m_iMaxDisplayedVSlotC ; i + + )
{
iVSlotIndexA [ i ] = i ; // start with 0,1,2
}
m_iDisplayDescription = DISPLAY_INVENTORY ;
m_iIngredientsC = 0 ;
}
LPCWSTR IUIScene_CraftingMenu : : GetGroupNameText ( int iGroupType )
{
switch ( iGroupType )
{
case ShapedRecipy : : eGroupType_Tool :
return app . GetString ( IDS_GROUPNAME_TOOLS ) ;
case ShapedRecipy : : eGroupType_Food :
return app . GetString ( IDS_GROUPNAME_FOOD ) ;
case ShapedRecipy : : eGroupType_Structure :
return app . GetString ( IDS_GROUPNAME_STRUCTURES ) ;
case ShapedRecipy : : eGroupType_Armour :
return app . GetString ( IDS_GROUPNAME_ARMOUR ) ;
case ShapedRecipy : : eGroupType_Mechanism :
return app . GetString ( IDS_GROUPNAME_MECHANISMS ) ;
case ShapedRecipy : : eGroupType_Transport :
return app . GetString ( IDS_GROUPNAME_TRANSPORT ) ;
case ShapedRecipy : : eGroupType_Decoration :
default :
return app . GetString ( IDS_GROUPNAME_DECORATIONS ) ;
}
}
bool IUIScene_CraftingMenu : : handleKeyDown ( int iPad , int iAction , bool bRepeat )
{
bool bHandled = false ;
if ( m_bIgnoreKeyPresses ) return bHandled ;
// ignore key repeats of the X key - because it's X to open this menu, it can come through as a repeat on opening
if ( bRepeat & & ( iAction = = ACTION_MENU_X ) )
{
return S_OK ;
}
Minecraft * pMinecraft = Minecraft : : GetInstance ( ) ;
if ( pMinecraft - > localgameModes [ getPad ( ) ] ! = NULL )
{
Tutorial * tutorial = pMinecraft - > localgameModes [ getPad ( ) ] - > getTutorial ( ) ;
if ( tutorial ! = NULL )
{
tutorial - > handleUIInput ( iAction ) ;
if ( ui . IsTutorialVisible ( getPad ( ) ) & & ! tutorial - > isInputAllowed ( iAction ) )
{
return S_OK ;
}
}
}
switch ( iAction )
{
case ACTION_MENU_X :
// change the display
m_iDisplayDescription + + ;
if ( m_iDisplayDescription = = DISPLAY_MAX ) m_iDisplayDescription = DISPLAY_INVENTORY ;
ui . PlayUISFX ( eSFX_Focus ) ;
UpdateMultiPanel ( ) ;
UpdateTooltips ( ) ;
break ;
case ACTION_MENU_PAUSEMENU :
2026-03-02 15:58:20 +07:00
case ACTION_MENU_B :
2026-03-01 12:16:08 +08:00
ui . ShowTooltip ( iPad , eToolTipButtonX , false ) ;
ui . ShowTooltip ( iPad , eToolTipButtonB , false ) ;
2026-03-02 15:58:20 +07:00
ui . ShowTooltip ( iPad , eToolTipButtonA , false ) ;
ui . ShowTooltip ( iPad , eToolTipButtonRB , false ) ;
2026-03-01 12:16:08 +08:00
// kill the crafting xui
//ui.PlayUISFX(eSFX_Back);
ui . CloseUIScenes ( iPad ) ;
bHandled = true ;
break ;
case ACTION_MENU_A :
# ifdef __ORBIS__
case ACTION_MENU_TOUCHPAD_PRESS :
# endif
// Do some crafting!
if ( m_pPlayer & & m_pPlayer - > inventory )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
// Force a make if the debug is on
if ( app . DebugSettingsOn ( ) & & app . GetGameSettingsDebugMask ( ProfileManager . GetPrimaryPad ( ) ) & ( 1L < < eDebugSetting_CraftAnything ) )
{
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
int iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
int iRecipe = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ;
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ iRecipe ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
//int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue());
if ( pMinecraft - > localgameModes [ iPad ] ! = NULL )
{
Tutorial * tutorial = pMinecraft - > localgameModes [ iPad ] - > getTutorial ( ) ;
if ( tutorial ! = NULL )
{
tutorial - > onCrafted ( pTempItemInst ) ;
}
}
pMinecraft - > localgameModes [ iPad ] - > handleCraftItem ( iRecipe , m_pPlayer ) ;
if ( m_pPlayer - > inventory - > add ( pTempItemInst ) = = false )
{
// no room in inventory, so throw it down
m_pPlayer - > drop ( pTempItemInst ) ;
}
// play a sound
//pMinecraft->soundEngine->playUI( L"random.pop", 1.0f, 1.0f);
ui . PlayUISFX ( eSFX_Craft ) ;
}
}
else if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 )
{
int iSlot ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
}
else
{
iSlot = 0 ;
}
int iRecipe = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ;
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ iRecipe ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
//int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue());
if ( pMinecraft - > localgameModes [ iPad ] ! = NULL )
{
Tutorial * tutorial = pMinecraft - > localgameModes [ iPad ] - > getTutorial ( ) ;
if ( tutorial ! = NULL )
{
tutorial - > createItemSelected ( pTempItemInst , pRecipeIngredientsRequired [ iRecipe ] . bCanMake [ iPad ] ) ;
}
}
2026-03-02 15:58:20 +07:00
if ( pRecipeIngredientsRequired [ iRecipe ] . bCanMake [ iPad ] )
2026-03-01 12:16:08 +08:00
{
pTempItemInst - > onCraftedBy ( m_pPlayer - > level , dynamic_pointer_cast < Player > ( m_pPlayer - > shared_from_this ( ) ) , pTempItemInst - > count ) ;
// TODO 4J Stu - handleCraftItem should do a lot more than what it does, loads of the "can we craft" code should also probably be
// shifted to the GameMode
pMinecraft - > localgameModes [ iPad ] - > handleCraftItem ( iRecipe , m_pPlayer ) ;
// play a sound
//pMinecraft->soundEngine->playUI( L"random.pop", 1.0f, 1.0f);
ui . PlayUISFX ( eSFX_Craft ) ;
// and remove those resources from your inventory
for ( int i = 0 ; i < pRecipeIngredientsRequired [ iRecipe ] . iIngC ; i + + )
{
for ( int j = 0 ; j < pRecipeIngredientsRequired [ iRecipe ] . iIngValA [ i ] ; j + + )
{
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > ingItemInst = nullptr ;
2026-03-01 12:16:08 +08:00
// do we need to remove a specific aux value?
if ( pRecipeIngredientsRequired [ iRecipe ] . iIngAuxValA [ i ] ! = Recipes : : ANY_AUX_VALUE )
{
ingItemInst = m_pPlayer - > inventory - > getResourceItem ( pRecipeIngredientsRequired [ iRecipe ] . iIngIDA [ i ] , pRecipeIngredientsRequired [ iRecipe ] . iIngAuxValA [ i ] ) ;
m_pPlayer - > inventory - > removeResource ( pRecipeIngredientsRequired [ iRecipe ] . iIngIDA [ i ] , pRecipeIngredientsRequired [ iRecipe ] . iIngAuxValA [ i ] ) ;
}
else
{
ingItemInst = m_pPlayer - > inventory - > getResourceItem ( pRecipeIngredientsRequired [ iRecipe ] . iIngIDA [ i ] ) ;
m_pPlayer - > inventory - > removeResource ( pRecipeIngredientsRequired [ iRecipe ] . iIngIDA [ i ] ) ;
}
// 4J Stu - Fix for #13097 - Bug: Milk Buckets are removed when crafting Cake
if ( ingItemInst ! = NULL )
{
if ( ingItemInst - > getItem ( ) - > hasCraftingRemainingItem ( ) )
{
// replace item with remaining result
2026-03-02 15:58:20 +07:00
m_pPlayer - > inventory - > add ( std : : shared_ptr < ItemInstance > ( new ItemInstance ( ingItemInst - > getItem ( ) - > getCraftingRemainingItem ( ) ) ) ) ;
2026-03-01 12:16:08 +08:00
}
}
}
}
// 4J Stu - Fix for #13119 - We should add the item after we remove the ingredients
if ( m_pPlayer - > inventory - > add ( pTempItemInst ) = = false )
{
// no room in inventory, so throw it down
m_pPlayer - > drop ( pTempItemInst ) ;
}
//4J Gordon: Achievements
switch ( pTempItemInst - > id )
{
case Tile : : workBench_Id : m_pPlayer - > awardStat ( GenericStats : : buildWorkbench ( ) , GenericStats : : param_buildWorkbench ( ) ) ; break ;
case Item : : pickAxe_wood_Id : m_pPlayer - > awardStat ( GenericStats : : buildPickaxe ( ) , GenericStats : : param_buildPickaxe ( ) ) ; break ;
case Tile : : furnace_Id : m_pPlayer - > awardStat ( GenericStats : : buildFurnace ( ) , GenericStats : : param_buildFurnace ( ) ) ; break ;
case Item : : hoe_wood_Id : m_pPlayer - > awardStat ( GenericStats : : buildHoe ( ) , GenericStats : : param_buildHoe ( ) ) ; break ;
case Item : : bread_Id : m_pPlayer - > awardStat ( GenericStats : : makeBread ( ) , GenericStats : : param_makeBread ( ) ) ; break ;
case Item : : cake_Id : m_pPlayer - > awardStat ( GenericStats : : bakeCake ( ) , GenericStats : : param_bakeCake ( ) ) ; break ;
case Item : : pickAxe_stone_Id : m_pPlayer - > awardStat ( GenericStats : : buildBetterPickaxe ( ) , GenericStats : : param_buildBetterPickaxe ( ) ) ; break ;
case Item : : sword_wood_Id : m_pPlayer - > awardStat ( GenericStats : : buildSword ( ) , GenericStats : : param_buildSword ( ) ) ; break ;
case Tile : : dispenser_Id : m_pPlayer - > awardStat ( GenericStats : : dispenseWithThis ( ) , GenericStats : : param_dispenseWithThis ( ) ) ; break ;
case Tile : : enchantTable_Id : m_pPlayer - > awardStat ( GenericStats : : enchantments ( ) , GenericStats : : param_enchantments ( ) ) ; break ;
case Tile : : bookshelf_Id : m_pPlayer - > awardStat ( GenericStats : : bookcase ( ) , GenericStats : : param_bookcase ( ) ) ; break ;
}
// We've used some ingredients from our inventory, so update the recipes we can make
CheckRecipesAvailable ( ) ;
// don't reset the vertical slots - we want to stay where we are
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
}
else
{
//pMinecraft->soundEngine->playUI( L"btn.back", 1.0f, 1.0f);
ui . PlayUISFX ( eSFX_CraftFail ) ;
}
}
}
break ;
case ACTION_MENU_LEFT_SCROLL :
2026-03-02 15:58:20 +07:00
// turn off the old group tab
2026-03-01 12:16:08 +08:00
showTabHighlight ( m_iGroupIndex , false ) ;
if ( m_iGroupIndex = = 0 )
{
if ( m_iContainerType = = RECIPE_TYPE_3x3 )
{
m_iGroupIndex = m_iMaxGroup3x3 - 1 ;
}
else
{
m_iGroupIndex = m_iMaxGroup2x2 - 1 ;
}
}
else
{
m_iGroupIndex - - ;
}
// turn on the new group
showTabHighlight ( m_iGroupIndex , true ) ;
m_iCurrentSlotHIndex = 0 ;
m_iCurrentSlotVIndex = 1 ;
CheckRecipesAvailable ( ) ;
// reset the vertical slots
iVSlotIndexA [ 0 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
iVSlotIndexA [ 1 ] = 0 ;
iVSlotIndexA [ 2 ] = 1 ;
ui . PlayUISFX ( eSFX_Focus ) ;
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
setGroupText ( GetGroupNameText ( m_pGroupA [ m_iGroupIndex ] ) ) ;
break ;
case ACTION_MENU_RIGHT_SCROLL :
// turn off the old group tab
showTabHighlight ( m_iGroupIndex , false ) ;
m_iGroupIndex + + ;
if ( m_iContainerType = = RECIPE_TYPE_3x3 )
{
if ( m_iGroupIndex = = m_iMaxGroup3x3 ) m_iGroupIndex = 0 ;
}
else
{
if ( m_iGroupIndex = = m_iMaxGroup2x2 ) m_iGroupIndex = 0 ;
}
// turn on the new group
showTabHighlight ( m_iGroupIndex , true ) ;
m_iCurrentSlotHIndex = 0 ;
m_iCurrentSlotVIndex = 1 ;
CheckRecipesAvailable ( ) ;
// reset the vertical slots
iVSlotIndexA [ 0 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
iVSlotIndexA [ 1 ] = 0 ;
iVSlotIndexA [ 2 ] = 1 ;
ui . PlayUISFX ( eSFX_Focus ) ;
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
setGroupText ( GetGroupNameText ( m_pGroupA [ m_iGroupIndex ] ) ) ;
break ;
}
// 4J-Tomk - check if we've only got one vertical scroll slot (480, splits & Vita)
bool bNoScrollSlots = false ;
if ( m_bSplitscreen | | ( ! RenderManager . IsHiDef ( ) & & ! RenderManager . IsWidescreen ( ) ) )
{
bNoScrollSlots = true ;
}
# ifdef __PSVITA__
bNoScrollSlots = true ;
# endif
// 4J Stu - We did used to swap the thumsticks based on Southpaw in this scene, but ONLY in this scene
switch ( iAction )
{
case ACTION_MENU_OTHER_STICK_UP :
scrollDescriptionUp ( ) ;
break ;
case ACTION_MENU_OTHER_STICK_DOWN :
scrollDescriptionDown ( ) ;
break ;
case ACTION_MENU_RIGHT :
{
int iOldHSlot = m_iCurrentSlotHIndex ;
m_iCurrentSlotHIndex + + ;
if ( m_iCurrentSlotHIndex > = m_iCraftablesMaxHSlotC ) m_iCurrentSlotHIndex = 0 ;
m_iCurrentSlotVIndex = 1 ;
// clear the indices
iVSlotIndexA [ 0 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
iVSlotIndexA [ 1 ] = 0 ;
2026-03-02 15:58:20 +07:00
iVSlotIndexA [ 2 ] = 1 ;
2026-03-01 12:16:08 +08:00
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
// re-enable the old hslot
if ( CanBeMadeA [ iOldHSlot ] . iCount > 0 )
{
setShowCraftHSlot ( iOldHSlot , true ) ;
}
ui . PlayUISFX ( eSFX_Focus ) ;
bHandled = true ;
}
break ;
case ACTION_MENU_LEFT :
{
if ( m_iCraftablesMaxHSlotC ! = 0 )
{
int iOldHSlot = m_iCurrentSlotHIndex ;
if ( m_iCurrentSlotHIndex = = 0 ) m_iCurrentSlotHIndex = m_iCraftablesMaxHSlotC - 1 ;
else m_iCurrentSlotHIndex - - ;
m_iCurrentSlotVIndex = 1 ;
// clear the indices
iVSlotIndexA [ 0 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
iVSlotIndexA [ 1 ] = 0 ;
iVSlotIndexA [ 2 ] = 1 ;
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
// re-enable the old hslot
if ( CanBeMadeA [ iOldHSlot ] . iCount > 0 )
{
setShowCraftHSlot ( iOldHSlot , true ) ;
}
ui . PlayUISFX ( eSFX_Focus ) ;
}
bHandled = true ;
}
break ;
case ACTION_MENU_UP :
{
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
if ( bNoScrollSlots )
{
if ( iVSlotIndexA [ 1 ] = = 0 )
{
iVSlotIndexA [ 1 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
}
else
{
iVSlotIndexA [ 1 ] - - ;
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
ui . PlayUISFX ( eSFX_Focus ) ;
}
else
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 2 )
{
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
if ( m_iCurrentSlotVIndex ! = 0 )
{
// just move the highlight
m_iCurrentSlotVIndex - - ;
ui . PlayUISFX ( eSFX_Focus ) ;
}
else
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
//move the slots
iVSlotIndexA [ 2 ] = iVSlotIndexA [ 1 ] ;
iVSlotIndexA [ 1 ] = iVSlotIndexA [ 0 ] ;
2026-03-02 15:58:20 +07:00
// on 0 and went up, so cycle the values
2026-03-01 12:16:08 +08:00
if ( iVSlotIndexA [ 0 ] = = 0 )
{
iVSlotIndexA [ 0 ] = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ;
}
else
{
iVSlotIndexA [ 0 ] - - ;
}
ui . PlayUISFX ( eSFX_Focus ) ;
}
}
}
else
{
if ( m_iCurrentSlotVIndex ! = 1 )
{
// just move the highlight
m_iCurrentSlotVIndex - - ;
ui . PlayUISFX ( eSFX_Focus ) ;
}
}
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
}
}
break ;
case ACTION_MENU_DOWN :
{
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
if ( bNoScrollSlots )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
if ( iVSlotIndexA [ 1 ] = = ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ) )
{
iVSlotIndexA [ 1 ] = 0 ;
}
else
{
iVSlotIndexA [ 1 ] + + ;
}
ui . PlayUISFX ( eSFX_Focus ) ;
}
else
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 2 )
{
if ( m_iCurrentSlotVIndex ! = 2 )
{
m_iCurrentSlotVIndex + + ;
ui . PlayUISFX ( eSFX_Focus ) ;
}
else
{
iVSlotIndexA [ 0 ] = iVSlotIndexA [ 1 ] ;
iVSlotIndexA [ 1 ] = iVSlotIndexA [ 2 ] ;
if ( iVSlotIndexA [ m_iCurrentSlotVIndex ] = = ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount - 1 ) )
{
iVSlotIndexA [ 2 ] = 0 ;
}
else
{
iVSlotIndexA [ 2 ] + + ;
}
ui . PlayUISFX ( eSFX_Focus ) ;
}
}
else
{
if ( m_iCurrentSlotVIndex ! = ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ) )
{
m_iCurrentSlotVIndex + + ;
ui . PlayUISFX ( eSFX_Focus ) ;
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
}
UpdateVerticalSlots ( ) ;
UpdateHighlight ( ) ;
}
}
break ;
}
return bHandled ;
}
//////////////////////////////////////////////////////////////////////////
//
// CheckRecipesAvailable
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : CheckRecipesAvailable ( )
{
int iHSlotBrushControl = 0 ;
// clear the current list
memset ( CanBeMadeA , 0 , sizeof ( CANBEMADE ) * m_iCraftablesMaxHSlotC ) ;
hideAllHSlots ( ) ;
if ( m_pPlayer & & m_pPlayer - > inventory )
{
// dump out the inventory
/* for (unsigned int k = 0; k < m_pPlayer->inventory->items.length; k++)
{
if ( m_pPlayer - > inventory - > items [ k ] ! = NULL )
{
wstring itemstring = m_pPlayer - > inventory - > items [ k ] - > toString ( ) ;
//printf("--- Player has ");
OutputDebugStringW ( itemstring . c_str ( ) ) ;
//printf(" with Aux val = %d, base type = %d, Material = %d\n",m_pPlayer->inventory->items[k]->getAuxValue(),m_pPlayer->inventory->items[k]->getItem()->getBaseItemType(),m_pPlayer->inventory->items[k]->getItem()->getMaterial());
}
}
*/
RecipyList * recipes = ( ( Recipes * ) Recipes : : getInstance ( ) ) - > getRecipies ( ) ;
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
int iRecipeC = ( int ) recipes - > size ( ) ;
AUTO_VAR ( itRecipe , recipes - > begin ( ) ) ;
// dump out the recipe products
// for (int i = 0; i < iRecipeC; i++)
// {
2026-03-02 15:58:20 +07:00
// std::shared_ptr<ItemInstance> pTempItemInst=pRecipeIngredientsRequired[i].pRecipy->assemble(NULL);
2026-03-01 12:16:08 +08:00
// if (pTempItemInst != NULL)
// {
// wstring itemstring=pTempItemInst->toString();
2026-03-02 15:58:20 +07:00
//
2026-03-01 12:16:08 +08:00
// printf("Recipe [%d] = ",i);
// OutputDebugStringW(itemstring.c_str());
// if(pTempItemInst->id!=0)
// {
// if(pTempItemInst->id<256)
// {
// Tile *pTile=Tile::tiles[pTempItemInst->id];
// printf("[TILE] ID\t%d\tAux val\t%d\tBase type\t%d\tMaterial\t%d\t Count=%d\n",pTempItemInst->id, pTempItemInst->getAuxValue(),pTile->getBaseItemType(),pTile->getMaterial(),pTempItemInst->GetCount());
// }
// else
// {
// printf("ID\t%d\tAux val\t%d\tBase type\t%d\tMaterial\t%d Count=%d\n",pTempItemInst->id, pTempItemInst->getAuxValue(),pTempItemInst->getItem()->getBaseItemType(),pTempItemInst->getItem()->getMaterial(),pTempItemInst->GetCount());
// }
2026-03-02 15:58:20 +07:00
//
2026-03-01 12:16:08 +08:00
// }
// }
// }
for ( int i = 0 ; i < iRecipeC ; i + + )
{
Recipy * r = * itRecipe ;
// If this recipe isn't in the current grouptype, skip it
if ( r - > getGroup ( ) ! = m_pGroupA [ m_iGroupIndex ] )
{
itRecipe + + ;
pRecipeIngredientsRequired [ i ] . bCanMake [ getPad ( ) ] = false ;
continue ;
}
// if we are in the inventory menu, then we have 2x2 crafting available only
if ( ( m_iContainerType = = RECIPE_TYPE_2x2 ) & & ( pRecipeIngredientsRequired [ i ] . iType = = RECIPE_TYPE_3x3 ) )
{
// need a crafting table for this recipe
itRecipe + + ;
pRecipeIngredientsRequired [ i ] . bCanMake [ getPad ( ) ] = false ;
continue ;
}
// clear the mask showing which ingredients are missing
pRecipeIngredientsRequired [ i ] . usBitmaskMissingGridIngredients [ getPad ( ) ] = 0 ;
//bool bCanMakeRecipe=true;
bool * bFoundA = new bool [ pRecipeIngredientsRequired [ i ] . iIngC ] ;
for ( int j = 0 ; j < pRecipeIngredientsRequired [ i ] . iIngC ; j + + )
{
bFoundA [ j ] = false ;
int iTotalCount = 0 ;
// Does the player have this ingredient?
for ( unsigned int k = 0 ; k < m_pPlayer - > inventory - > items . length ; k + + )
{
if ( m_pPlayer - > inventory - > items [ k ] ! = NULL )
{
// do they have the ingredient, and the aux value matches, and enough off it?
2026-03-02 15:58:20 +07:00
if ( ( m_pPlayer - > inventory - > items [ k ] - > id = = pRecipeIngredientsRequired [ i ] . iIngIDA [ j ] ) & &
2026-03-01 12:16:08 +08:00
// check if the ingredient required doesn't care about the aux value, or if it does, does the inventory item aux match it
2026-03-02 15:58:20 +07:00
( ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = Recipes : : ANY_AUX_VALUE ) | | ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = m_pPlayer - > inventory - > items [ k ] - > getAuxValue ( ) ) )
2026-03-01 12:16:08 +08:00
)
{
// do they have enough? We need to check the whole inventory, since they may have enough in different slots (milk isn't milkx3, but milk,milk,milk)
if ( m_pPlayer - > inventory - > items [ k ] - > GetCount ( ) > = pRecipeIngredientsRequired [ i ] . iIngValA [ j ] )
{
// they have enough with one slot
bFoundA [ j ] = true ;
}
else
{
// look at the combined value from the whole inventory
for ( unsigned int l = 0 ; l < m_pPlayer - > inventory - > items . length ; l + + )
{
if ( m_pPlayer - > inventory - > items [ l ] ! = NULL )
{
if (
( m_pPlayer - > inventory - > items [ l ] - > id = = pRecipeIngredientsRequired [ i ] . iIngIDA [ j ] ) & &
( ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = Recipes : : ANY_AUX_VALUE ) | | ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = m_pPlayer - > inventory - > items [ l ] - > getAuxValue ( ) ) )
)
{
iTotalCount + = m_pPlayer - > inventory - > items [ l ] - > GetCount ( ) ;
}
}
}
if ( iTotalCount > = pRecipeIngredientsRequired [ i ] . iIngValA [ j ] )
{
bFoundA [ j ] = true ;
}
}
// 4J Stu - TU-1 hotfix
// Fix for #13143 - Players are able to craft items they do not have enough ingredients for if they store the ingredients in multiple, smaller stacks
break ;
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
}
}
// if bFoundA[j] is false, then we didn't have enough of the ingredient required by the recipe, so mark the grid items we're short of
if ( bFoundA [ j ] = = false )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
int iMissing = pRecipeIngredientsRequired [ i ] . iIngValA [ j ] - iTotalCount ;
int iGridIndex = 0 ;
while ( iMissing ! = 0 )
{
// need to check if there is an aux val and match that
2026-03-02 15:58:20 +07:00
if ( ( ( pRecipeIngredientsRequired [ i ] . uiGridA [ iGridIndex ] & 0x00FFFFFF ) = = pRecipeIngredientsRequired [ i ] . iIngIDA [ j ] ) & &
2026-03-01 12:16:08 +08:00
( ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = Recipes : : ANY_AUX_VALUE ) | | ( pRecipeIngredientsRequired [ i ] . iIngAuxValA [ j ] = = ( ( pRecipeIngredientsRequired [ i ] . uiGridA [ iGridIndex ] & 0xFF000000 ) > > 24 ) ) ) )
{
// this grid entry is the ingredient we don't have enough of
pRecipeIngredientsRequired [ i ] . usBitmaskMissingGridIngredients [ getPad ( ) ] | = 1 < < iGridIndex ;
iMissing - - ;
}
iGridIndex + + ;
}
}
}
// so can we make it?
bool bCanMake = true ;
for ( int j = 0 ; j < pRecipeIngredientsRequired [ i ] . iIngC ; j + + )
{
if ( bFoundA [ j ] = = false )
{
bCanMake = false ;
break ;
}
}
pRecipeIngredientsRequired [ i ] . bCanMake [ getPad ( ) ] = bCanMake ;
// Add the recipe to the CanBeMade list of lists
if ( iHSlotBrushControl < = m_iCraftablesMaxHSlotC )
{
bool bFound = false ;
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ i ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
//int iIcon=pTempItemInst->getItem()->getIcon(pTempItemInst->getAuxValue());
int iID = pTempItemInst - > getItem ( ) - > id ;
int iBaseType ;
if ( iID < 256 ) // is it a tile?
{
iBaseType = Tile : : tiles [ iID ] - > getBaseItemType ( ) ;
}
else
{
iBaseType = pTempItemInst - > getItem ( ) - > getBaseItemType ( ) ;
}
// ignore for the misc base type - these have not been placed in a base type group
if ( iBaseType ! = Item : : eBaseItemType_undefined )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
for ( int k = 0 ; k < iHSlotBrushControl ; k + + )
{
// if the item base type is the same as one already in, then add it to that list
if ( CanBeMadeA [ k ] . iItemBaseType = = iBaseType )
{
// base item type already in our list
bFound = true ;
if ( CanBeMadeA [ k ] . iCount < m_iMaxVSlotC )
{
CanBeMadeA [ k ] . iRecipeA [ CanBeMadeA [ k ] . iCount + + ] = i ;
}
else
{
app . DebugPrintf ( " Need more V slots \n " ) ;
}
break ;
}
}
}
if ( ! bFound )
{
if ( iHSlotBrushControl < m_iCraftablesMaxHSlotC )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
// add to the list
CanBeMadeA [ iHSlotBrushControl ] . iItemBaseType = iBaseType ;
CanBeMadeA [ iHSlotBrushControl ] . iRecipeA [ CanBeMadeA [ iHSlotBrushControl ] . iCount + + ] = i ;
iHSlotBrushControl + + ;
}
else
{
app . DebugPrintf ( " Need more H slots - " ) ;
# ifndef _CONTENT_PACKAGE
OutputDebugStringW ( app . GetString ( pTempItemInst - > getDescriptionId ( ) ) ) ;
# endif
app . DebugPrintf ( " \n " ) ;
}
}
}
else
{
app . DebugPrintf ( " Need more HSlots \n " ) ;
}
delete [ ] bFoundA ;
2026-03-02 15:58:20 +07:00
itRecipe + + ;
2026-03-01 12:16:08 +08:00
}
}
// run through the canbemade list and update the icons displayed
int iIndex = 0 ;
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
while ( ( iIndex < m_iCraftablesMaxHSlotC ) & & CanBeMadeA [ iIndex ] . iCount ! = 0 )
{
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ CanBeMadeA [ iIndex ] . iRecipeA [ 0 ] ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
assert ( pTempItemInst - > id ! = 0 ) ;
unsigned int uiAlpha ;
if ( app . DebugSettingsOn ( ) & & app . GetGameSettingsDebugMask ( ProfileManager . GetPrimaryPad ( ) ) & ( 1L < < eDebugSetting_CraftAnything ) )
{
uiAlpha = 31 ;
}
else
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
if ( pRecipeIngredientsRequired [ CanBeMadeA [ iIndex ] . iRecipeA [ 0 ] ] . bCanMake [ getPad ( ) ] )
{
uiAlpha = 31 ;
}
else
{
uiAlpha = 16 ;
}
}
// 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture
// rather than the dynamic one for the player
if ( pTempItemInst - > id = = Item : : clock_Id | | pTempItemInst - > id = = Item : : compass_Id )
{
pTempItemInst - > setAuxValue ( 255 ) ;
}
setCraftHSlotItem ( getPad ( ) , iIndex , pTempItemInst , uiAlpha ) ;
iIndex + + ;
}
// 4J-PB - Removed - UpdateTooltips will do this
// Update tooltips
/*if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0)
{
ui . ShowTooltip ( getPad ( ) , eToolTipButtonA , true ) ;
// 4J-PB - not implemented !
//ui.EnableTooltip( getPad(), eToolTipButtonA, true );
}
else
{
ui . ShowTooltip ( getPad ( ) , eToolTipButtonA , false ) ;
} */
}
//////////////////////////////////////////////////////////////////////////
//
// UpdateHighlight
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : UpdateHighlight ( )
{
updateHighlightAndScrollPositions ( ) ;
bool bCanBeMade = CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 ;
if ( bCanBeMade )
{
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
int iSlot ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
}
else
{
iSlot = 0 ;
}
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInstAdditional = pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
// special case for the torch coal/charcoal
int id = pTempItemInstAdditional - > getDescriptionId ( ) ;
LPCWSTR itemstring ;
switch ( id )
{
case IDS_TILE_TORCH :
{
if ( pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . iIngAuxValA [ 0 ] = = 1 )
{
itemstring = app . GetString ( IDS_TILE_TORCHCHARCOAL ) ;
}
else
{
itemstring = app . GetString ( IDS_TILE_TORCHCOAL ) ;
}
}
break ;
case IDS_ITEM_FIREBALL :
{
if ( pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . iIngAuxValA [ 2 ] = = 1 )
{
itemstring = app . GetString ( IDS_ITEM_FIREBALLCHARCOAL ) ;
}
else
{
itemstring = app . GetString ( IDS_ITEM_FIREBALLCOAL ) ;
}
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
break ;
default :
2026-03-02 15:58:20 +07:00
itemstring = app . GetString ( id ) ;
2026-03-01 12:16:08 +08:00
break ;
}
setItemText ( itemstring ) ;
}
else
{
setItemText ( L " " ) ;
}
UpdateDescriptionText ( bCanBeMade ) ;
DisplayIngredients ( ) ;
UpdateMultiPanel ( ) ;
UpdateTooltips ( ) ;
}
//////////////////////////////////////////////////////////////////////////
//
// UpdateVerticalSlots
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : UpdateVerticalSlots ( )
{
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
// update the vertical items for the current horizontal slot
hideAllVSlots ( ) ;
// could have either 1 or 2 vertical slots, above and below the horizontal slot
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
// turn off the horizontal one since we could be cycling through others
setShowCraftHSlot ( m_iCurrentSlotHIndex , false ) ;
int iSlots = ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 2 ) ? 3 : 2 ;
// 4J-Tomk - check if we've only got one vertical scroll slot (480, splits & Vita)
bool bNoScrollSlots = false ;
if ( m_bSplitscreen | | ( ! RenderManager . IsHiDef ( ) & & ! RenderManager . IsWidescreen ( ) ) )
{
bNoScrollSlots = true ;
}
# ifdef __PSVITA__
bNoScrollSlots = true ;
# endif
for ( int i = 0 ; i < iSlots ; i + + )
{
// 4J this check determines if the crafting scene has only one vertical scroll slot
if ( bNoScrollSlots )
{
if ( i ! = 1 ) continue ;
}
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInstAdditional = pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iVSlotIndexA [ i ] ] ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
assert ( pTempItemInstAdditional - > id ! = 0 ) ;
unsigned int uiAlpha ;
if ( app . DebugSettingsOn ( ) & & app . GetGameSettingsDebugMask ( ProfileManager . GetPrimaryPad ( ) ) & ( 1L < < eDebugSetting_CraftAnything ) )
{
uiAlpha = 31 ;
}
else
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
if ( pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iVSlotIndexA [ i ] ] ] . bCanMake [ getPad ( ) ] )
{
uiAlpha = 31 ;
}
else
{
uiAlpha = 16 ;
}
}
// 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture
// rather than the dynamic one for the player
if ( pTempItemInstAdditional - > id = = Item : : clock_Id | | pTempItemInstAdditional - > id = = Item : : compass_Id )
{
pTempItemInstAdditional - > setAuxValue ( 255 ) ;
}
setCraftVSlotItem ( getPad ( ) , i , pTempItemInstAdditional , uiAlpha ) ;
updateVSlotPositions ( iSlots , i ) ;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// DisplayIngredients
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : DisplayIngredients ( )
{
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
// hide the previous ingredients
hideAllIngredientsSlots ( ) ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
int iSlot , iRecipy ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
iRecipy = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ;
}
else
{
iSlot = 0 ;
iRecipy = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ 0 ] ;
}
// show the 2x2 or 3x3 to make the current item
int iBoxWidth = ( m_iContainerType = = RECIPE_TYPE_2x2 ) ? 2 : 3 ;
int iRecipe = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ;
bool bCanMakeRecipe = pRecipeIngredientsRequired [ iRecipe ] . bCanMake [ getPad ( ) ] ;
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ iRecipe ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
m_iIngredientsC = pRecipeIngredientsRequired [ iRecipe ] . iIngC ;
// update the ingredients required - these will all be hidden until cycled by the user
for ( int i = 0 ; i < pRecipeIngredientsRequired [ iRecipe ] . iIngC ; i + + )
{
int id = pRecipeIngredientsRequired [ iRecipe ] . iIngIDA [ i ] ;
int iAuxVal = pRecipeIngredientsRequired [ iRecipe ] . iIngAuxValA [ i ] ;
Item * item = Item : : items [ id ] ;
if ( ( iAuxVal & 0xFF ) = = 0xFF ) // 4J Stu - If the aux value is set to match any
iAuxVal = 0 ;
// 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture
// rather than the dynamic one for the player
if ( id = = Item : : clock_Id | | id = = Item : : compass_Id )
{
iAuxVal = 0xFF ;
}
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > itemInst = std : : shared_ptr < ItemInstance > ( new ItemInstance ( item , pRecipeIngredientsRequired [ iRecipe ] . iIngValA [ i ] , iAuxVal ) ) ;
2026-03-01 12:16:08 +08:00
setIngredientDescriptionItem ( getPad ( ) , i , itemInst ) ;
setIngredientDescriptionRedBox ( i , false ) ;
// 4J-PB - a very special case - the bed can use any kind of wool, so we can't use the item description
// and the same goes for the painting
int idescID ;
if ( ( ( pTempItemInst - > id = = Item : : bed_Id ) & & ( id = = Tile : : cloth_Id ) ) | |
( ( pTempItemInst - > id = = Item : : painting_Id ) & & ( id = = Tile : : cloth_Id ) ) )
{
idescID = IDS_ANY_WOOL ;
}
else
{
idescID = itemInst - > getDescriptionId ( ) ;
}
setIngredientDescriptionText ( i , app . GetString ( idescID ) ) ;
}
// 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture
// rather than the dynamic one for the player
if ( pTempItemInst - > id = = Item : : clock_Id | | pTempItemInst - > id = = Item : : compass_Id )
{
pTempItemInst - > setAuxValue ( 255 ) ;
}
// don't grey out the output icon
setCraftingOutputSlotItem ( getPad ( ) , pTempItemInst ) ;
if ( app . DebugSettingsOn ( ) & & app . GetGameSettingsDebugMask ( ProfileManager . GetPrimaryPad ( ) ) & ( 1L < < eDebugSetting_CraftAnything ) )
{
setCraftingOutputSlotRedBox ( false ) ;
}
else
{
if ( bCanMakeRecipe = = false )
{
setCraftingOutputSlotRedBox ( true ) ;
}
else
{
setCraftingOutputSlotRedBox ( false ) ;
}
}
2026-03-02 15:58:20 +07:00
for ( int x = 0 ; x < iBoxWidth ; x + + )
2026-03-01 12:16:08 +08:00
{
2026-03-02 15:58:20 +07:00
for ( int y = 0 ; y < iBoxWidth ; y + + )
2026-03-01 12:16:08 +08:00
{
int index = x + y * iBoxWidth ;
if ( pRecipeIngredientsRequired [ iRecipy ] . uiGridA [ x + y * 3 ] ! = 0 )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
int id = pRecipeIngredientsRequired [ iRecipy ] . uiGridA [ x + y * 3 ] & 0x00FFFFFF ;
assert ( id ! = 0 ) ;
int iAuxVal = ( pRecipeIngredientsRequired [ iRecipy ] . uiGridA [ x + y * 3 ] & 0xFF000000 ) > > 24 ;
// 4J Stu - For clocks and compasses we set the aux value to a special one that signals we should use a default texture
// rather than the dynamic one for the player
if ( id = = Item : : clock_Id | | id = = Item : : compass_Id )
{
iAuxVal = 0xFF ;
}
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > itemInst = std : : shared_ptr < ItemInstance > ( new ItemInstance ( id , 1 , iAuxVal ) ) ;
2026-03-01 12:16:08 +08:00
setIngredientSlotItem ( getPad ( ) , index , itemInst ) ;
// show the ingredients we don't have if we can't make the recipe
if ( app . DebugSettingsOn ( ) & & app . GetGameSettingsDebugMask ( ProfileManager . GetPrimaryPad ( ) ) & ( 1L < < eDebugSetting_CraftAnything ) )
{
setIngredientSlotRedBox ( index , false ) ;
}
else
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
if ( ( pRecipeIngredientsRequired [ iRecipy ] . usBitmaskMissingGridIngredients [ getPad ( ) ] & ( 1 < < ( x + y * 3 ) ) ) ! = 0 )
{
setIngredientSlotRedBox ( index , true ) ;
}
else
{
setIngredientSlotRedBox ( index , false ) ;
}
}
}
else
{
setIngredientSlotRedBox ( index , false ) ;
setIngredientSlotItem ( getPad ( ) , index , nullptr ) ;
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
}
}
}
else
{
setCraftingOutputSlotItem ( getPad ( ) , nullptr ) ;
setCraftingOutputSlotRedBox ( false ) ;
m_iIngredientsC = 0 ;
int iIngredientsSlots ;
// if it's a 2x2 , only clear the 4 m_pCraftingIngredientA slots
if ( m_iContainerType = = RECIPE_TYPE_2x2 )
{
iIngredientsSlots = 4 ;
}
else
{
iIngredientsSlots = m_iIngredients3x3SlotC ;
}
for ( int i = 0 ; i < iIngredientsSlots ; i + + )
{
setIngredientSlotRedBox ( i , false ) ;
setIngredientSlotItem ( getPad ( ) , i , nullptr ) ;
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
}
}
//////////////////////////////////////////////////////////////////////////
//
// UpdateDescriptionText
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : UpdateDescriptionText ( bool bCanBeMade )
{
int iIDSString = 0 ;
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
if ( bCanBeMade )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
int iSlot ; //,iRecipy;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
//iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[iSlot];
}
else
{
iSlot = 0 ;
//iRecipy=CanBeMadeA[m_iCurrentSlotHIndex].iRecipeA[0];
}
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > pTempItemInst = pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . pRecipy - > assemble ( nullptr ) ;
2026-03-01 12:16:08 +08:00
int iID = pTempItemInst - > getItem ( ) - > id ;
int iAuxVal = pTempItemInst - > getAuxValue ( ) ;
int iBaseType ;
if ( iID < 256 ) // is it a tile?
{
iBaseType = Tile : : tiles [ iID ] - > getBaseItemType ( ) ;
iIDSString = Tile : : tiles [ iID ] - > getUseDescriptionId ( ) ;
}
else
{
iBaseType = pTempItemInst - > getItem ( ) - > getBaseItemType ( ) ;
iIDSString = pTempItemInst - > getUseDescriptionId ( ) ;
}
// A few special cases where the description required is specific to crafting, rather than the normal description
if ( iBaseType ! = Item : : eBaseItemType_undefined )
{
switch ( iBaseType )
{
case Item : : eBaseItemType_cloth :
switch ( iAuxVal )
{
case 0 :
iIDSString = IDS_DESC_WOOLSTRING ;
break ;
}
break ;
}
}
// set the string mapped to by the base object mapping array
if ( iIDSString > = 0 )
{
// this is an html control now, so set the font size and colour
//wstring wsText=app.GetString(iIDSString);
wstring wsText = app . FormatHTMLString ( getPad ( ) , app . GetString ( iIDSString ) ) ;
// 12 for splitscreen, 14 for normal
EHTMLFontSize size = eHTMLSize_Normal ;
if ( m_bSplitscreen | | ( ! RenderManager . IsHiDef ( ) & & ! RenderManager . IsWidescreen ( ) ) )
{
size = eHTMLSize_Splitscreen ;
}
wchar_t startTags [ 64 ] ;
swprintf ( startTags , 64 , L " <font color= \" #%08x \" ><P ALIGN=LEFT> " , app . GetHTMLColour ( eHTMLColor_Black ) ) ;
wsText = startTags + wsText + L " </P> " ;
setDescriptionText ( wsText . c_str ( ) ) ;
}
else
{
/// Missing string!
# ifdef _DEBUG
setDescriptionText ( L " This is some placeholder description text about the craftable item. " ) ;
# else
2026-03-02 15:58:20 +07:00
setDescriptionText ( L " " ) ;
2026-03-01 12:16:08 +08:00
# endif
2026-03-02 15:58:20 +07:00
}
2026-03-01 12:16:08 +08:00
}
else
{
2026-03-02 15:58:20 +07:00
setDescriptionText ( L " " ) ;
2026-03-01 12:16:08 +08:00
}
}
//////////////////////////////////////////////////////////////////////////
//
// UpdateTooltips
//
//////////////////////////////////////////////////////////////////////////
void IUIScene_CraftingMenu : : UpdateTooltips ( )
{
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
// Update tooltips
bool bDisplayCreate ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 )
{
int iSlot ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
}
2026-03-02 15:58:20 +07:00
else
2026-03-01 12:16:08 +08:00
{
iSlot = 0 ;
}
if ( pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . bCanMake [ getPad ( ) ] )
{
bDisplayCreate = true ;
}
else
{
bDisplayCreate = false ;
}
}
else
{
bDisplayCreate = false ;
}
switch ( m_iDisplayDescription )
{
case DISPLAY_INVENTORY :
ui . SetTooltips ( getPad ( ) , bDisplayCreate ? IDS_TOOLTIPS_CREATE : - 1 , IDS_TOOLTIPS_EXIT , IDS_TOOLTIPS_SHOW_DESCRIPTION , - 1 , - 1 , - 1 , - 2 , IDS_TOOLTIPS_CHANGE_GROUP ) ;
break ;
case DISPLAY_DESCRIPTION :
ui . SetTooltips ( getPad ( ) , bDisplayCreate ? IDS_TOOLTIPS_CREATE : - 1 , IDS_TOOLTIPS_EXIT , IDS_TOOLTIPS_SHOW_INGREDIENTS , - 1 , - 1 , - 1 , - 2 , IDS_TOOLTIPS_CHANGE_GROUP ) ;
break ;
case DISPLAY_INGREDIENTS :
ui . SetTooltips ( getPad ( ) , bDisplayCreate ? IDS_TOOLTIPS_CREATE : - 1 , IDS_TOOLTIPS_EXIT , IDS_TOOLTIPS_SHOW_INVENTORY , - 1 , - 1 , - 1 , - 2 , IDS_TOOLTIPS_CHANGE_GROUP ) ;
break ;
}
/*if(CanBeMadeA[m_iCurrentSlotHIndex].iCount!=0)
{
int iSlot ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
}
2026-03-02 15:58:20 +07:00
else
2026-03-01 12:16:08 +08:00
{
iSlot = 0 ;
}
if ( pRecipeIngredientsRequired [ CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ] . bCanMake [ getPad ( ) ] )
{
ui . EnableTooltip ( getPad ( ) , eToolTipButtonA , true ) ;
}
else
{
ui . EnableTooltip ( getPad ( ) , eToolTipButtonA , false ) ;
}
}
else
{
ui . ShowTooltip ( getPad ( ) , eToolTipButtonA , false ) ;
} */
}
bool IUIScene_CraftingMenu : : isItemSelected ( int itemId )
{
bool isSelected = false ;
if ( m_pPlayer & & m_pPlayer - > inventory )
2026-03-02 15:58:20 +07:00
{
2026-03-01 12:16:08 +08:00
//RecipyList *recipes = ((Recipes *)Recipes::getInstance())->getRecipies();
Recipy : : INGREDIENTS_REQUIRED * pRecipeIngredientsRequired = Recipes : : getInstance ( ) - > getRecipeIngredientsArray ( ) ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount ! = 0 )
{
int iSlot ;
if ( CanBeMadeA [ m_iCurrentSlotHIndex ] . iCount > 1 )
{
iSlot = iVSlotIndexA [ m_iCurrentSlotVIndex ] ;
}
else
{
iSlot = 0 ;
}
int iRecipe = CanBeMadeA [ m_iCurrentSlotHIndex ] . iRecipeA [ iSlot ] ;
ItemInstance * pTempItemInst = ( ItemInstance * ) pRecipeIngredientsRequired [ iRecipe ] . pRecipy - > getResultItem ( ) ;
if ( pTempItemInst - > id = = itemId )
{
isSelected = true ;
}
}
}
return isSelected ;
}