diff --git a/reactivedrop/resource/ui/CollectionPanelInventoryUnboxChoice.res b/reactivedrop/resource/ui/CollectionPanelInventoryUnboxChoice.res index f58cd1129..dab7cc634 100644 --- a/reactivedrop/resource/ui/CollectionPanelInventoryUnboxChoice.res +++ b/reactivedrop/resource/ui/CollectionPanelInventoryUnboxChoice.res @@ -101,22 +101,22 @@ "command" "PreviousSelection" "enabledImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_left" "color" "224 224 224 255" } "mouseOverImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_left" "color" "255 255 255 255" } "pressedImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_left" "color" "255 255 255 255" } "disabledImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_left" "color" "96 96 96 255" } } @@ -131,22 +131,22 @@ "command" "NextSelection" "enabledImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_right" "color" "224 224 224 255" } "mouseOverImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_right" "color" "255 255 255 255" } "pressedImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_right" "color" "255 255 255 255" } "disabledImage" { - "material" "vgui/TODO" + "material" "vgui/swarm/big_arrow_right" "color" "96 96 96 255" } } @@ -161,13 +161,14 @@ } "BtnConfirm" { - "ControlName" "CNB_Button" + "ControlName" "CNB_Button_Hold" "fieldName" "BtnConfirm" "xpos" "250" "ypos" "385" "wide" "150" "tall" "23" "font" "DefaultMedium" + "labelText" "#rd_unbox_strange_confirm" "textAlignment" "center" } "BtnCancel" @@ -179,6 +180,8 @@ "wide" "150" "tall" "23" "font" "DefaultMedium" + "labelText" "#rd_unbox_strange_cancel" "textAlignment" "center" + "command" "CancelSelection" } } diff --git a/src/game/client/swarm/gameui/swarm/vitemshowcase.cpp b/src/game/client/swarm/gameui/swarm/vitemshowcase.cpp index b1af9c233..7dd003319 100644 --- a/src/game/client/swarm/gameui/swarm/vitemshowcase.cpp +++ b/src/game/client/swarm/gameui/swarm/vitemshowcase.cpp @@ -135,6 +135,7 @@ void ItemShowcase::OnThink() case MODE_ITEM_DROP: case MODE_ITEM_CLAIMED: case MODE_ITEM_UPGRADED: + case MODE_ITEM_CRAFTED: { const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( m_Queue[0]->ItemDefID ); diff --git a/src/game/client/swarm/rd_collections_inventory.cpp b/src/game/client/swarm/rd_collections_inventory.cpp index 98135bf45..dd3c999bb 100644 --- a/src/game/client/swarm/rd_collections_inventory.cpp +++ b/src/game/client/swarm/rd_collections_inventory.cpp @@ -2,6 +2,7 @@ #include "rd_collections.h" #include "rd_inventory_shared.h" #include "rd_crafting_defs.h" +#include #include #include #include @@ -15,7 +16,8 @@ #include "asw_equipment_list.h" #include "asw_weapon_shared.h" #include "vgui_bitmapbutton.h" -#include "nb_button.h" +#include "nb_button_hold.h" +#include "gameui/swarm/vgenericconfirmation.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -24,6 +26,28 @@ ConVar rd_briefing_item_details_displaytype( "rd_briefing_item_details_displaytype", "170 170 170 255" ); extern ConVar rd_equipped_medal[RD_STEAM_INVENTORY_NUM_MEDAL_SLOTS]; +static SteamItemDef_t s_iDeferredCraftingRecipe = 0; +static CUtlVector s_DeferredCraftingIngredients; +static CUtlVector s_DeferredCraftingQuantities; + +static void DeferredCraftingConfirm() +{ + if ( !s_iDeferredCraftingRecipe ) + return; + + ReactiveDropInventory::PerformCraftingAction( s_iDeferredCraftingRecipe, std::initializer_list( &s_DeferredCraftingIngredients.Head(), &s_DeferredCraftingIngredients.Tail() ), std::initializer_list( &s_DeferredCraftingQuantities.Head(), &s_DeferredCraftingQuantities.Tail() ) ); + + s_iDeferredCraftingRecipe = 0; + s_DeferredCraftingIngredients.Purge(); + s_DeferredCraftingQuantities.Purge(); +} +static void DeferredCraftingCancel() +{ + s_iDeferredCraftingRecipe = 0; + s_DeferredCraftingIngredients.Purge(); + s_DeferredCraftingQuantities.Purge(); +} + CRD_Collection_Tab_Inventory::CRD_Collection_Tab_Inventory( TabbedGridDetails *parent, const char *szLabel, const char *szSlot ) : BaseClass( parent, szLabel ) { @@ -412,7 +436,7 @@ class CRD_Collection_Panel_Inventory_Unbox_Choice : public vgui::EditablePanel m_pBtnNext = new CBitmapButton( this, "BtnNext", " " ); m_pBtnNext->AddActionSignalTarget( this ); m_pBtnNext->SetCommand( "NextSelection" ); - m_pBtnConfirm = new CNB_Button( this, "BtnConfirm", "#rd_unbox_strange_confirm", this, "ConfirmSelection" ); + m_pBtnConfirm = new CNB_Button_Hold( this, "BtnConfirm", "#rd_unbox_strange_confirm", this, "ConfirmSelection" ); m_pBtnConfirm->SetControllerButton( KEY_XBUTTON_X ); m_pBtnCancel = new CNB_Button( this, "BtnCancel", "#rd_unbox_strange_cancel", this, "CancelSelection" ); m_pBtnCancel->SetControllerButton( KEY_XBUTTON_B ); @@ -656,14 +680,36 @@ class CRD_Collection_Panel_Inventory_Unbox_Choice : public vgui::EditablePanel if ( m_Warnings.Count() ) { - // "#rd_unbox_strange_warnings_title" - // "#rd_unbox_strange_warnings_desc" - - DebuggerBreakIfDebugging(); // TODO! + Assert( s_iDeferredCraftingRecipe == 0 ); + Assert( s_DeferredCraftingIngredients.Count() == 0 ); + Assert( s_DeferredCraftingQuantities.Count() == 0 ); + s_iDeferredCraftingRecipe = m_Choices[m_iChoice]; + s_DeferredCraftingIngredients.Purge(); + s_DeferredCraftingIngredients.AddToTail( m_pEntry->m_Details.ItemID ); + s_DeferredCraftingQuantities.Purge(); + s_DeferredCraftingQuantities.AddToTail( 1 ); + + BaseModUI::GenericConfirmation::Data_t data; + data.pWindowTitle = "#rd_unbox_strange_warnings_title"; + data.pMessageText = "#rd_unbox_strange_warnings_desc"; + data.bOkButtonEnabled = true; + data.bCancelButtonEnabled = true; + data.pfnOkCallback = DeferredCraftingConfirm; + data.pfnCancelCallback = DeferredCraftingCancel; + + BaseModUI::CBaseModPanel::GetSingleton().OpenFrontScreen(); + + BaseModUI::GenericConfirmation *pConfirm = assert_cast< BaseModUI::GenericConfirmation * >( BaseModUI::CBaseModPanel::GetSingleton().OpenWindow( BaseModUI::WT_GENERICCONFIRMATION, BaseModUI::CBaseModPanel::GetSingleton().GetWindow( BaseModUI::WT_MAINMENU ) ) ); + pConfirm->SetUsageData( data ); } else { - DebuggerBreakIfDebugging(); // TODO! + SteamItemDef_t iRecipe = m_Choices[m_iChoice]; + SteamItemInstanceID_t iIngredient = m_pEntry->m_Details.ItemID; + + BaseModUI::CBaseModPanel::GetSingleton().OpenFrontScreen(); + + ReactiveDropInventory::PerformCraftingAction( iRecipe, { iIngredient }, { 1 } ); } } else if ( FStrEq( command, "CancelSelection" ) ) @@ -773,7 +819,7 @@ class CRD_Collection_Panel_Inventory_Unbox_Choice : public vgui::EditablePanel vgui::Panel *m_pPnlDetails; CBitmapButton *m_pBtnPrevious; CBitmapButton *m_pBtnNext; - CNB_Button *m_pBtnConfirm; + CNB_Button_Hold *m_pBtnConfirm; CNB_Button *m_pBtnCancel; CUtlVector m_Warnings; struct ItemIconSection_t diff --git a/src/game/client/swarm/vgui/nb_button.cpp b/src/game/client/swarm/vgui/nb_button.cpp index e51a8f644..ee486db0d 100644 --- a/src/game/client/swarm/vgui/nb_button.cpp +++ b/src/game/client/swarm/vgui/nb_button.cpp @@ -25,6 +25,7 @@ CNB_Button::CNB_Button( Panel *parent, const char *panelName, const char *text, m_hButtonFont = INVALID_FONT; m_szControllerButton = NULL; + m_iControllerButton = KEY_NONE; } CNB_Button::CNB_Button( Panel *parent, const char *panelName, const wchar_t *text, Panel *pActionSignalTarget, const char *pCmd, bool bSuppressAddToFocusList ) : BaseClass( parent, panelName, text, pActionSignalTarget, pCmd ) @@ -35,6 +36,7 @@ CNB_Button::CNB_Button( Panel *parent, const char *panelName, const wchar_t *tex m_hButtonFont = INVALID_FONT; m_szControllerButton = NULL; + m_iControllerButton = KEY_NONE; } CNB_Button::~CNB_Button() @@ -89,6 +91,12 @@ void CNB_Button::PaintBackground() { DrawRoundedBox( nBorder, nBorder, wide - nBorder * 2, tall - nBorder * 2, m_DisabledColor, m_DisabledHighlightColor ); } + + if ( m_szControllerButton && g_RD_Steam_Input.GetJoystickCount() ) + { + int padding = ( tall - nBorder * 2 - surface()->GetFontTall( m_hButtonFont ) ) / 2; + g_RD_Steam_Input.DrawLegacyControllerGlyph( m_szControllerButton, nBorder + padding, nBorder + padding, false, false, m_hButtonFont ); + } } void CNB_Button::OnCursorEntered() @@ -150,16 +158,12 @@ void CNB_Button::DrawRoundedBox( int x, int y, int wide, int tall, Color color, surface()->DrawFilledRectFade( x + cornerWide, y, x + wide * 0.5f, y + tall, 0, 255, true ); surface()->DrawFilledRectFade( x + wide * 0.5f, y, x + wide - cornerWide, y + tall, 255, 0, true ); } - - if ( m_szControllerButton && g_RD_Steam_Input.GetJoystickCount() ) - { - int padding = ( tall - surface()->GetFontTall( m_hButtonFont ) ) / 2; - g_RD_Steam_Input.DrawLegacyControllerGlyph( m_szControllerButton, x + padding, y + padding, false, false, m_hButtonFont ); - } } void CNB_Button::SetControllerButton( KeyCode code ) { + m_iControllerButton = code; + switch ( code ) { case KEY_XBUTTON_A: @@ -213,6 +217,7 @@ void CNB_Button::SetControllerButton( KeyCode code ) default: Warning( "CNB_Button: Unhandled controller button code %d\n", code ); m_szControllerButton = NULL; + m_iControllerButton = KEY_NONE; break; } } diff --git a/src/game/client/swarm/vgui/nb_button.h b/src/game/client/swarm/vgui/nb_button.h index e3f17d2c2..6adc45be5 100644 --- a/src/game/client/swarm/vgui/nb_button.h +++ b/src/game/client/swarm/vgui/nb_button.h @@ -17,12 +17,12 @@ class CNB_Button : public vgui::Button CNB_Button( Panel *parent, const char *panelName, const char *text, Panel *pActionSignalTarget = NULL, const char *pCmd = NULL, bool bSuppressAddToFocusList = false ); CNB_Button( Panel *parent, const char *panelName, const wchar_t *text, Panel *pActionSignalTarget = NULL, const char *pCmd = NULL, bool bSuppressAddToFocusList = false ); virtual ~CNB_Button(); - - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - virtual void Paint(); - virtual void PaintBackground(); - virtual void OnCursorEntered(); - virtual void NavigateTo(); + + void ApplySchemeSettings( vgui::IScheme *pScheme ) override; + void Paint() override; + void PaintBackground() override; + void OnCursorEntered() override; + void NavigateTo() override; void DrawRoundedBox( int x, int y, int wide, int tall, Color color, Color highlightCenterColor ); void SetControllerButton( vgui::KeyCode code ); @@ -32,6 +32,7 @@ class CNB_Button : public vgui::Button vgui::HFont m_hButtonFont; const char *m_szControllerButton; + vgui::KeyCode m_iControllerButton; bool m_bAddedToControllerFocus; CPanelAnimationVar( bool, m_bAutoFocus, "autoFocus", "0" ); diff --git a/src/game/client/swarm/vgui/nb_button_hold.cpp b/src/game/client/swarm/vgui/nb_button_hold.cpp new file mode 100644 index 000000000..2807c1bb5 --- /dev/null +++ b/src/game/client/swarm/vgui/nb_button_hold.cpp @@ -0,0 +1,165 @@ +#include "cbase.h" +#include "nb_button_hold.h" +#include "vgui/ISurface.h" +#include "inputsystem/iinputsystem.h" +#include "rd_steam_input.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +DECLARE_BUILD_FACTORY_DEFAULT_TEXT( CNB_Button_Hold, CNB_Button_Hold ); + +CNB_Button_Hold::CNB_Button_Hold( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget, const char *pCmd, bool bSuppressAddToFocusList ) : + BaseClass{ parent, panelName, text, pActionSignalTarget, pCmd, bSuppressAddToFocusList } +{ +} + +CNB_Button_Hold::CNB_Button_Hold( vgui::Panel *parent, const char *panelName, const wchar_t *text, vgui::Panel *pActionSignalTarget, const char *pCmd, bool bSuppressAddToFocusList ) : + BaseClass{ parent, panelName, text, pActionSignalTarget, pCmd, bSuppressAddToFocusList } +{ +} + +void CNB_Button_Hold::PaintBackground() +{ + BaseClass::PaintBackground(); + + if ( m_flHoldProgress <= -1.0f ) + { + return; + } + + if ( m_nNBBgTextureId1 == -1 || m_nNBBgTextureId2 == -1 || m_nNBBgTextureId3 == -1 || m_nNBBgTextureId4 == -1 ) + { + return; + } + + float flHoldProgress = clamp( m_flHoldProgress, 0.0f, 1.0f ); + + int wide, tall; + GetSize( wide, tall ); + + int nBorder = MAX( m_nBorderThick, m_nBorderThickMin ); + int x = nBorder, y = nBorder; + wide -= nBorder * 2; + tall -= nBorder * 2; + + int wide2 = wide * ( m_flHoldProgress >= 0.0f ? Lerp( m_flHoldHighlightLip, flHoldProgress, 1.0f ) : m_flHoldHighlightLip * ( 1.0f + m_flHoldProgress ) ); + + int cornerWide, cornerTall; + GetCornerTextureSize( cornerWide, cornerTall ); + + int r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3; + m_HoldHighlightColorStart.GetColor( r1, g1, b1, a1 ); + m_HoldHighlightColorFlash1.GetColor( r2, g2, b2, a2 ); + m_HoldHighlightColorFlash2.GetColor( r3, g3, b3, a3 ); + float flFlashInterp = sinf( m_flHoldProgress * m_flHoldHighlightColorSpeed ) * 0.5f + 0.5f; + +#define INTERP( channel ) Lerp( Bias( flHoldProgress, m_flHoldHighlightColorBias ), channel##1, Lerp( flFlashInterp, channel##2, channel##3 ) ) + vgui::surface()->DrawSetColor( INTERP( r ), INTERP( g ), INTERP( b ), INTERP( a ) ); +#undef INTERP + if ( wide2 >= cornerWide ) + vgui::surface()->DrawFilledRect( x + cornerWide, y, x + MIN( wide - cornerWide, wide2 ), y + cornerTall ); + vgui::surface()->DrawFilledRect( x, y + cornerTall, x + wide2, y + tall - cornerTall ); + if ( wide2 >= cornerWide ) + vgui::surface()->DrawFilledRect( x + cornerWide, y + tall - cornerTall, x + MIN( wide - cornerWide, wide2 ), y + tall ); + + float s1 = RemapValClamped( wide2, 0.0f, cornerWide, 0.0f, 1.0f ); + float s2 = RemapValClamped( wide2, wide - cornerWide, wide, 0.0f, 1.0f ); + vgui::surface()->DrawSetTexture( m_nNBBgTextureId1 ); + vgui::surface()->DrawTexturedSubRect( x, y, x + MIN( cornerWide, wide2 ), y + cornerTall, 0.0f, 0.0f, s1, 1.0f ); + if ( wide2 >= wide - cornerWide ) + { + vgui::surface()->DrawSetTexture( m_nNBBgTextureId2 ); + vgui::surface()->DrawTexturedSubRect( x + wide - cornerWide, y, x + wide2, y + cornerTall, 0.0f, 0.0f, s2, 1.0f ); + vgui::surface()->DrawSetTexture( m_nNBBgTextureId3 ); + vgui::surface()->DrawTexturedSubRect( x + wide - cornerWide, y + tall - cornerTall, x + wide2, y + tall, 0.0f, 0.0f, s2, 1.0f ); + } + vgui::surface()->DrawSetTexture( m_nNBBgTextureId4 ); + vgui::surface()->DrawTexturedSubRect( x + 0, y + tall - cornerTall, x + MIN( cornerWide, wide2 ), y + tall, 0.0f, 0.0f, s1, 1.0f ); + + // re-draw the controller button icon so it's on top of the wipe + if ( m_szControllerButton && g_RD_Steam_Input.GetJoystickCount() ) + { + int padding = ( tall - vgui::surface()->GetFontTall( m_hButtonFont ) ) / 2; + g_RD_Steam_Input.DrawLegacyControllerGlyph( m_szControllerButton, nBorder + padding, nBorder + padding, false, false, m_hButtonFont ); + } +} + +void CNB_Button_Hold::PaintTraverse( bool Repaint, bool allowForce ) +{ + bool bBeingHeld = m_flHoldProgress > 0.0f; + int origX, origY; + GetPos( origX, origY ); + + if ( bBeingHeld ) + { + float flHoldProgress = MIN( m_flHoldProgress, 1.0f ); + + int offX = 0, offY = 0; + offX = cosf( Bias( flHoldProgress, m_flShakeSpeedBiasX ) * m_flShakeSpeedX ) * Bias( flHoldProgress, m_flShakeAmountBiasX ) * m_flShakeAmountX; + offY = sinf( Bias( flHoldProgress, m_flShakeSpeedBiasY ) * m_flShakeSpeedY ) * Bias( flHoldProgress, m_flShakeAmountBiasY ) * m_flShakeAmountY; + + SetPos( origX + offX, origY + offY ); + vgui::ipanel()->Solve( GetVPanel() ); + } + + BaseClass::PaintTraverse( Repaint, allowForce ); + + if ( bBeingHeld ) + { + SetPos( origX, origY ); + vgui::ipanel()->Solve( GetVPanel() ); + } +} + +void CNB_Button_Hold::DoClick() +{ + SetSelected( false ); +} + +void CNB_Button_Hold::OnThink() +{ + BaseClass::OnThink(); + + if ( m_iControllerButton != KEY_NONE ) + { + ForceDepressed( g_pInputSystem->IsButtonDown( m_iControllerButton ) ); + } + + double now = Plat_FloatTime(); + double dt = clamp( now - m_flLastThink, 0.0f, 0.1f ); + m_flLastThink = now; + + if ( IsDepressed() && !m_bClickReset ) + { + float flNextProgress = MAX( m_flHoldProgress, 0.0f ) + dt / m_flHoldTime; + bool bFinishedHold = m_flHoldProgress < 1.0f && flNextProgress >= 1.0f; + m_flHoldProgress = flNextProgress; + Repaint(); + + if ( bFinishedHold ) + { + FireActionSignal(); + } + } + else + { + if ( m_flHoldProgress >= 1.0f ) + { + m_bClickReset = true; + m_flHoldProgress = 1.0f; + } + + if ( m_flHoldProgress > -1.0f ) + { + m_flHoldProgress = MAX( m_flHoldProgress - dt / m_flResetTime, -1.0f ); + Repaint(); + } + + if ( m_bClickReset && m_flHoldProgress <= 0.0f ) + { + m_flHoldProgress = -1.0f; + m_bClickReset = false; + } + } +} diff --git a/src/game/client/swarm/vgui/nb_button_hold.h b/src/game/client/swarm/vgui/nb_button_hold.h new file mode 100644 index 000000000..5b45c2d59 --- /dev/null +++ b/src/game/client/swarm/vgui/nb_button_hold.h @@ -0,0 +1,37 @@ +#pragma once + +#include "nb_button.h" + +class CNB_Button_Hold : public CNB_Button +{ + DECLARE_CLASS_SIMPLE( CNB_Button_Hold, CNB_Button ); +public: + CNB_Button_Hold( vgui::Panel *parent, const char *panelName, const char *text, vgui::Panel *pActionSignalTarget = NULL, const char *pCmd = NULL, bool bSuppressAddToFocusList = false ); + CNB_Button_Hold( vgui::Panel *parent, const char *panelName, const wchar_t *text, vgui::Panel *pActionSignalTarget = NULL, const char *pCmd = NULL, bool bSuppressAddToFocusList = false ); + + void PaintBackground() override; + void PaintTraverse( bool Repaint, bool allowForce = true ) override; + void DoClick() override; + void OnThink() override; + + float m_flHoldProgress{ -1.0f }; + double m_flLastThink{ Plat_FloatTime() }; + bool m_bClickReset{ false }; + + CPanelAnimationVar( float, m_flHoldTime, "hold_time", "2.30410" ); + CPanelAnimationVar( float, m_flResetTime, "reset_time", "0.548430" ); + CPanelAnimationVar( float, m_flShakeSpeedX, "shake_speed_x", "83.0" ); + CPanelAnimationVar( float, m_flShakeSpeedY, "shake_speed_y", "172.0" ); + CPanelAnimationVar( float, m_flShakeSpeedBiasX, "shake_speed_bias_x", "0.7" ); + CPanelAnimationVar( float, m_flShakeSpeedBiasY, "shake_speed_bias_y", "0.7" ); + CPanelAnimationVarAliasType( float, m_flShakeAmountX, "shake_amount_x", "2.5", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flShakeAmountY, "shake_amount_y", "2.0", "proportional_float" ); + CPanelAnimationVar( float, m_flShakeAmountBiasX, "shake_amount_bias_x", "0.5" ); + CPanelAnimationVar( float, m_flShakeAmountBiasY, "shake_amount_bias_y", "0.5" ); + CPanelAnimationVar( float, m_flHoldHighlightLip, "hold_highlight_lip", "0.1" ); + CPanelAnimationVar( Color, m_HoldHighlightColorStart, "hold_highlight_color_start", "40 80 130 192" ); + CPanelAnimationVar( Color, m_HoldHighlightColorFlash1, "hold_highlight_color_flash1", "254 100 1 192" ); + CPanelAnimationVar( Color, m_HoldHighlightColorFlash2, "hold_highlight_color_flash2", "255 196 0 192" ); + CPanelAnimationVar( float, m_flHoldHighlightColorBias, "hold_highlight_color_bias", "0.2" ); + CPanelAnimationVar( float, m_flHoldHighlightColorSpeed, "hold_highlight_color_speed", "25" ); +}; diff --git a/src/game/client/swarm_sdk_client.vcxproj b/src/game/client/swarm_sdk_client.vcxproj index 60f3c5954..12af02ce7 100644 --- a/src/game/client/swarm_sdk_client.vcxproj +++ b/src/game/client/swarm_sdk_client.vcxproj @@ -2316,6 +2316,7 @@ if exist ..\..\devtools\bin\postbuild.cmd ..\..\devtools\bin\postbuild.cmd clien + @@ -3437,6 +3438,7 @@ if exist ..\..\devtools\bin\postbuild.cmd ..\..\devtools\bin\postbuild.cmd clien + diff --git a/src/game/shared/swarm/rd_inventory_shared.cpp b/src/game/shared/swarm/rd_inventory_shared.cpp index 4f85398ab..a036e1fde 100644 --- a/src/game/shared/swarm/rd_inventory_shared.cpp +++ b/src/game/shared/swarm/rd_inventory_shared.cpp @@ -38,6 +38,7 @@ #include "rd_collections.h" #include "rd_hoiaf_utils.h" #include "rd_inventory_command.h" +#include "vstdlib/jobthread.h" #define CASW_Sentry_Base C_ASW_Sentry_Base #define CASW_Sentry_Top C_ASW_Sentry_Top #else @@ -101,6 +102,8 @@ static void ResetAccessoryIconsOnMaterialsReleased( int nChangeFlags ) static const char s_szHexDigits[] = "0123456789abcdef"; +static void WriteInventoryCacheHelper(); + static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameEventListener { public: @@ -248,12 +251,6 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE Warning( "Failed to cache user inventory for offline play: no ISteamInventory\n" ); return; } - ISteamUser *pUser = SteamUser(); - if ( !pUser ) - { - Warning( "Failed to cache user inventory for offline play: no ISteamUser\n" ); - return; - } uint32 nItems{}; if ( !pInventory->GetResultItems( hResult, NULL, &nItems ) ) @@ -267,13 +264,10 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE m_HighOwnedInventoryDefIDs.Purge(); - KeyValues::AutoDelete pCache{ "IC" }; - for ( uint32 i = 0; i < nItems; i++ ) { ReactiveDropInventory::ItemInstance_t instance{ hResult, i }; m_LocalInventoryCache.AddToTail( instance ); - pCache->AddSubKey( instance.ToKeyValues() ); // precache item def + icon ( void )ReactiveDropInventory::GetItemDef( instance.ItemDefID ); @@ -288,6 +282,24 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE } } + ReactiveDropInventory::g_nFullInventoryUpdates++; + + HoIAF()->RebuildNotificationList(); + + ThreadExecute( WriteInventoryCacheHelper ); + } + + void WriteInventoryCache() + { + CFastTimer timer; + timer.Start(); + + KeyValues::AutoDelete pCache{ "IC" }; + FOR_EACH_VEC( m_LocalInventoryCache, i ) + { + pCache->AddSubKey( m_LocalInventoryCache[i].ToKeyValues() ); + } + CUtlBuffer buf; if ( !pCache->WriteAsBinary( buf ) ) { @@ -295,6 +307,13 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE return; } + ISteamUser *pUser = SteamUser(); + if ( !pUser ) + { + Warning( "Failed to cache user inventory for offline play: no ISteamUser\n" ); + return; + } + CFmtStr szCacheFileName{ "cfg/clienti_%llu.dat", pUser->GetSteamID().ConvertToUint64() }; if ( !g_pFullFileSystem->WriteFile( szCacheFileName, "MOD", buf ) ) { @@ -302,23 +321,23 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE return; } + timer.End(); if ( rd_debug_inventory.GetBool() ) { - Msg( "Successfully wrote inventory cache with %d items\n", nItems ); + Msg( "Successfully wrote inventory cache with %d items in %fs\n", m_LocalInventoryCache.Count(), timer.GetDuration().GetSeconds() ); } - ReactiveDropInventory::g_nFullInventoryUpdates++; - if ( m_HighOwnedInventoryDefIDs.Count() ) { CacheItemSchema(); } - - HoIAF()->RebuildNotificationList(); } void CacheItemSchema() { + CFastTimer timer; + timer.Start(); + ISteamInventory *pInventory = SteamInventory(); if ( !pInventory ) { @@ -438,9 +457,10 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE return; } + timer.End(); if ( rd_debug_inventory.GetBool() ) { - Msg( "Successfully wrote item schema cache with %d items (skipped %d)\n", nItemDefs - nSkippedDefs, nSkippedDefs ); + Msg( "Successfully wrote item schema cache with %d items (skipped %d) in %fs\n", nItemDefs - nSkippedDefs, nSkippedDefs, timer.GetDuration().GetSeconds() ); } #ifdef DBGFLAG_ASSERT @@ -2197,6 +2217,13 @@ static class CRD_Inventory_Manager final : public CAutoGameSystem, public CGameE } } s_RD_Inventory_Manager; +static void WriteInventoryCacheHelper() +{ +#ifdef CLIENT_DLL + s_RD_Inventory_Manager.WriteInventoryCache(); +#endif +} + #ifdef CLIENT_DLL static void RD_Equipped_Item_Changed( IConVar *var, const char *pOldValue, float flOldValue ) { @@ -3452,6 +3479,21 @@ namespace ReactiveDropInventory return nCount; } #endif + void PerformCraftingAction( SteamItemDef_t recipe, std::initializer_list ingredient, std::initializer_list quantity ) + { + Assert( ingredient.size() == quantity.size() ); + if ( ingredient.size() != quantity.size() ) + { + Warning( "Crafting action failed due to programmer error: %d ingredients but %d ingredient quantities! (recipe=%d)\n", ingredient.size(), quantity.size(), recipe ); + return; + } + + GET_INVENTORY_OR_BAIL; + + const uint32 one = 1; + pInventory->ExchangeItems( s_RD_Inventory_Manager.AddCraftItemTask( CRD_Inventory_Manager::CRAFT_RECIPE ), + &recipe, &one, 1, ingredient.begin(), quantity.begin(), ingredient.size() ); + } void RequestFullInventoryRefresh() { if ( s_RD_Inventory_Manager.m_CraftingQueue.Count() ) diff --git a/src/game/shared/swarm/rd_inventory_shared.h b/src/game/shared/swarm/rd_inventory_shared.h index 2552974b7..f860f73ea 100644 --- a/src/game/shared/swarm/rd_inventory_shared.h +++ b/src/game/shared/swarm/rd_inventory_shared.h @@ -193,6 +193,7 @@ namespace ReactiveDropInventory int GetCraftingMaterialsFound(); int GetCraftingMaterialsMissed(); #endif + void PerformCraftingAction( SteamItemDef_t recipe, std::initializer_list ingredient, std::initializer_list quantity ); void RequestFullInventoryRefresh(); #endif void OnHitConfirm( CBaseEntity *pAttacker, CBaseEntity *pTarget, Vector vecDamagePosition, bool bKilled, bool bDamageOverTime, bool bBlastDamage, int iDisposition, float flDamage, CBaseEntity *pWeapon );