Skip to content

Commit

Permalink
auto-equip steam inventory items for now
Browse files Browse the repository at this point in the history
  • Loading branch information
BenLubar committed May 8, 2024
1 parent c0f9f68 commit e7ae204
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 20 deletions.
31 changes: 21 additions & 10 deletions src/game/client/swarm/c_asw_marine_resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ C_ASW_Marine_Resource::C_ASW_Marine_Resource()
m_iScore = -1;
m_flFinishedMissionTime = -1;
memset( m_iWeaponsInSlots, -1, sizeof( m_iWeaponsInSlots ) );
memset( m_iWeaponsInSlotsLastSeen, -1, sizeof( m_iWeaponsInSlotsLastSeen ) );
}

C_ASW_Marine_Resource::~C_ASW_Marine_Resource()
Expand Down Expand Up @@ -301,31 +302,41 @@ float C_ASW_Marine_Resource::GetFiringTimer()

void C_ASW_Marine_Resource::OnDataChanged(DataUpdateType_t updateType)
{
if ( updateType == DATA_UPDATE_CREATED )
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
{
ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );
ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh );

C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
if (pPlayer && pPlayer == GetCommander() && ASWGameRules() && ASWGameRules()->GetGameState() <= ASW_GS_BRIEFING)
C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer();
if ( pPlayer && pPlayer == GetCommander() && ASWGameRules() && ASWGameRules()->GetGameState() <= ASW_GS_BRIEFING )
{
if ( updateType == DATA_UPDATE_CREATED )
{
// we're in briefing and a marine has just been selected by us (possibly autoselection)
// send our last saved loadout
pPlayer->LoadoutSendStored(this);
pPlayer->LoadoutSendStored( this );

// see if we need to spend skill points
if ( ASWGameRules()->GetCampaignSave() && !ASWGameRules()->GetCampaignSave()->UsingFixedSkillPoints()
if ( ASWGameRules()->GetCampaignSave() && !ASWGameRules()->GetCampaignSave()->UsingFixedSkillPoints()
&& ASWGameResource() && ASWGameResource()->GetMarineSkill( this, ASW_SKILL_SLOT_SPARE ) > 0 )
{
CNB_Main_Panel::QueueSpendSkillPoints( GetProfileIndex() );
}
}

if ( V_memcmp( m_iWeaponsInSlots, m_iWeaponsInSlotsLastSeen, sizeof( m_iWeaponsInSlots ) ) )
{
V_memcpy( m_iWeaponsInSlotsLastSeen, m_iWeaponsInSlots, sizeof( m_iWeaponsInSlots ) );
pPlayer->LoadoutSendEquippedItems( this );
}
}
SetNextClientThink(gpGlobals->curtime);
}

BaseClass::OnDataChanged(updateType);
if ( updateType == DATA_UPDATE_CREATED )
{
SetNextClientThink( gpGlobals->curtime );
}

BaseClass::OnDataChanged( updateType );

if ( updateType == DATA_UPDATE_CREATED )
{
Expand Down
1 change: 1 addition & 0 deletions src/game/client/swarm/c_asw_marine_resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class C_ASW_Marine_Resource : public C_BaseEntity

int m_iWeaponsInSlots[ASW_MAX_EQUIP_SLOTS]; // index of equipment selected in loadout for primary inventory slot
int m_iInitialWeaponsInSlots[ASW_MAX_EQUIP_SLOTS];
int m_iWeaponsInSlotsLastSeen[ASW_MAX_EQUIP_SLOTS];

// stats
float m_fDamageTaken;
Expand Down
44 changes: 44 additions & 0 deletions src/game/client/swarm/c_asw_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#include <ctime>
#include "rd_player_reporting.h"
#include "rd_crafting_defs.h"
#include "rd_inventory_command.h"

#if defined( CASW_Player )
#undef CASW_Player
Expand Down Expand Up @@ -662,6 +663,49 @@ void C_ASW_Player::LoadoutSendStored( C_ASW_Marine_Resource *pMR )
SendRosterSelectCommand( "cl_loadouta", pMR->GetProfileIndex(), ASWGameResource()->GetMarineResourceIndex( pMR ) );
}

void C_ASW_Player::LoadoutSendEquippedItems( C_ASW_Marine_Resource *pMR )
{
if ( !pMR )
return;

int iMarineResourceIndex = ASWGameResource()->GetMarineResourceIndex( pMR );

CUtlVector<SteamItemInstanceID_t> ids;
ids.AddMultipleToTail( 4, &k_SteamItemInstanceIDInvalid );
CUtlVector<ReactiveDropInventory::ItemInstance_t> instances;

// until we have loadouts done, just send the first eligible item for each equip slot
ReactiveDropInventory::GetItemsForSlotAndEquipIndex( instances, "marine_any", pMR->GetProfileIndex() );
if ( instances.Count() )
ids[0] = instances[0].ItemID;
instances.Purge();

ReactiveDropInventory::GetItemsForSlotAndEquipIndex( instances, "weapon", pMR->m_iWeaponsInSlots[0] );
if ( instances.Count() )
ids[1] = instances[0].ItemID;
instances.Purge();

ReactiveDropInventory::GetItemsForSlotAndEquipIndex( instances, "weapon", pMR->m_iWeaponsInSlots[1] );
if ( pMR->m_iWeaponsInSlots[0] != pMR->m_iWeaponsInSlots[1] )
{
if ( instances.Count() )
ids[2] = instances[0].ItemID;
}
else
{
if ( instances.Count() > 1 )
ids[2] = instances[1].ItemID;
}
instances.Purge();

ReactiveDropInventory::GetItemsForSlotAndEquipIndex( instances, "extra", pMR->m_iWeaponsInSlots[2] );
if ( instances.Count() )
ids[3] = instances[0].ItemID;
instances.Purge();

UTIL_RD_SendInventoryCommandByIDs( INVCMD_MARINE_RESOURCE_EQUIPS, ids, CUtlVector<int>{ iMarineResourceIndex } );
}

void C_ASW_Player::StartReady()
{
// todo: if we're not the leader, do a cl_ready
Expand Down
1 change: 1 addition & 0 deletions src/game/client/swarm/c_asw_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class C_ASW_Player : public C_BasePlayer, public IASWPlayerAnimStateHelpers
virtual void RosterDeselectMarine( int iProfileIndex );
virtual void LoadoutSelectEquip( int iMarineIndex, int iInvSlot, int iEquipIndex, SteamItemInstanceID_t iItemInstanceID );
virtual void LoadoutSendStored( C_ASW_Marine_Resource *pMR );
virtual void LoadoutSendEquippedItems( C_ASW_Marine_Resource *pMR );
virtual void RosterSpendSkillPoint( int iProfileIndex, int iSkillIndex );

// campaign
Expand Down
14 changes: 8 additions & 6 deletions src/game/shared/swarm/asw_marine_resource_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ void CASW_Marine_Resource::ClearInvalidEquipData()
}
}

const int *pIndex = m_iInitialWeaponsInSlots[0] == -1 ? &m_iWeaponsInSlots[0] : &m_iInitialWeaponsInSlots[0];

if ( m_EquippedItemData.m_Weapon1.IsSet() )
{
const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( m_EquippedItemData.m_Weapon1.m_iItemDefID );
Assert( pDef );
if ( !pDef || !pDef->ItemSlotMatches( "weapon" ) || pDef->EquipIndex != m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_PRIMARY] )
if ( !pDef || !pDef->ItemSlotMatches( "weapon" ) || pDef->EquipIndex != pIndex[ASW_INVENTORY_SLOT_PRIMARY] )
{
Warning( "Clearing primary weapon item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Weapon1.m_iItemInstanceID, m_EquippedItemData.m_Weapon1.m_iItemDefID, m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_PRIMARY] );
Warning( "Clearing primary weapon item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Weapon1.m_iItemInstanceID, m_EquippedItemData.m_Weapon1.m_iItemDefID, pIndex[ASW_INVENTORY_SLOT_PRIMARY] );
m_EquippedItemData.m_Weapon1.GetForModify().Reset();
}
}
Expand All @@ -44,9 +46,9 @@ void CASW_Marine_Resource::ClearInvalidEquipData()
{
const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( m_EquippedItemData.m_Weapon2.m_iItemDefID );
Assert( pDef );
if ( !pDef || !pDef->ItemSlotMatches( "weapon" ) || pDef->EquipIndex != m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_SECONDARY] )
if ( !pDef || !pDef->ItemSlotMatches( "weapon" ) || pDef->EquipIndex != pIndex[ASW_INVENTORY_SLOT_SECONDARY] )
{
Warning( "Clearing secondary weapon item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Weapon2.m_iItemInstanceID, m_EquippedItemData.m_Weapon2.m_iItemDefID, m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_SECONDARY] );
Warning( "Clearing secondary weapon item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Weapon2.m_iItemInstanceID, m_EquippedItemData.m_Weapon2.m_iItemDefID, pIndex[ASW_INVENTORY_SLOT_SECONDARY] );
m_EquippedItemData.m_Weapon2.GetForModify().Reset();
}
}
Expand All @@ -55,9 +57,9 @@ void CASW_Marine_Resource::ClearInvalidEquipData()
{
const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( m_EquippedItemData.m_Extra.m_iItemDefID );
Assert( pDef );
if ( !pDef || !pDef->ItemSlotMatches( "extra" ) || pDef->EquipIndex != m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_EXTRA] )
if ( !pDef || !pDef->ItemSlotMatches( "extra" ) || pDef->EquipIndex != pIndex[ASW_INVENTORY_SLOT_EXTRA] )
{
Warning( "Clearing equipment item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Extra.m_iItemInstanceID, m_EquippedItemData.m_Extra.m_iItemDefID, m_iInitialWeaponsInSlots[ASW_INVENTORY_SLOT_EXTRA] );
Warning( "Clearing equipment item for marine resource entindex %d (player %s) - item %llu (def %d) is not valid for this slot (equip %d)\n", entindex(), COMMANDER_ID, m_EquippedItemData.m_Extra.m_iItemInstanceID, m_EquippedItemData.m_Extra.m_iItemDefID, pIndex[ASW_INVENTORY_SLOT_EXTRA] );
m_EquippedItemData.m_Extra.GetForModify().Reset();
}
}
Expand Down
134 changes: 130 additions & 4 deletions src/game/shared/swarm/rd_inventory_command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ static class CRD_Inventory_Command_Queue final : public CAutoGameSystem
}

m_PayloadChunks.Purge();

if ( ISteamInventory *pInventory = SteamInventory())
{
FOR_EACH_VEC( m_ItemIDQueue, i )
{
pInventory->DestroyResult( m_ItemIDQueue[i].m_hResult );
}
}

m_ItemIDQueue.Purge();
}

bool DiscardPayload( int iPayloadID )
Expand Down Expand Up @@ -158,6 +168,15 @@ static class CRD_Inventory_Command_Queue final : public CAutoGameSystem

int m_iNextPayloadID;
CUtlVector<KeyValues *> m_PayloadChunks;

struct ItemIDCommand_t
{
EInventoryCommand m_eCmd;
CCopyableUtlVector<int> m_Args;
CCopyableUtlVector<SteamItemInstanceID_t> m_IDs;
SteamInventoryResult_t m_hResult;
};
CUtlVector<ItemIDCommand_t> m_ItemIDQueue;
} s_RD_Inventory_Command_Queue;

int UTIL_RD_SendInventoryCommand( EInventoryCommand eCmd, const CUtlVector<int> &args, SteamInventoryResult_t hResult )
Expand Down Expand Up @@ -203,6 +222,77 @@ int UTIL_RD_SendInventoryCommand( EInventoryCommand eCmd, const CUtlVector<int>
return s_RD_Inventory_Command_Queue.CreateCommandPayload( eCmd, args.Base(), args.Count(), buf.Base(), nSize );
}

void UTIL_RD_SendInventoryCommandByIDs( EInventoryCommand eCmd, const CUtlVector<SteamItemInstanceID_t> &ids, const CUtlVector<int> &args )
{
CUtlVector<SteamItemInstanceID_t> realIDs;
realIDs.EnsureCapacity( ids.Count() );
FOR_EACH_VEC( ids, i )
{
if ( ids[i] != k_SteamItemInstanceIDInvalid )
{
realIDs.AddToTail( ids[i] );
}
}

if ( realIDs.Count() == 0 )
{
UTIL_RD_SendInventoryCommand( eCmd, args, k_SteamInventoryResultInvalid );
return;
}

ISteamInventory *pInventory = SteamInventory();
if ( !pInventory )
{
Warning( "Cannot send inventory command %d: no ISteamInventory\n", eCmd );
return;
}

int i = s_RD_Inventory_Command_Queue.m_ItemIDQueue.AddToTail();
s_RD_Inventory_Command_Queue.m_ItemIDQueue[i].m_eCmd = eCmd;
s_RD_Inventory_Command_Queue.m_ItemIDQueue[i].m_Args.AddVectorToTail( args );
s_RD_Inventory_Command_Queue.m_ItemIDQueue[i].m_IDs.AddVectorToTail( ids );
pInventory->GetItemsByID( &s_RD_Inventory_Command_Queue.m_ItemIDQueue[i].m_hResult, realIDs.Base(), realIDs.Count() );
}

bool RDCheckForInventoryCommandResult( ISteamInventory *pInventory, SteamInventoryResult_t hResult )
{
FOR_EACH_VEC( s_RD_Inventory_Command_Queue.m_ItemIDQueue, i )
{
const CRD_Inventory_Command_Queue::ItemIDCommand_t &cmd = s_RD_Inventory_Command_Queue.m_ItemIDQueue[i];
if ( cmd.m_hResult != hResult )
continue;

CUtlVector<int> args;
args.AddVectorToTail( cmd.m_Args );

uint32 nItems{};
pInventory->GetResultItems( hResult, NULL, &nItems );
CUtlMemory<SteamItemDetails_t> items{ 0, int( nItems ) };
pInventory->GetResultItems( hResult, items.Base(), &nItems );

FOR_EACH_VEC( items, j )
{
int index = args.AddToTail( -1 );
FOR_EACH_VEC( cmd.m_IDs, k )
{
if ( items[j].m_itemId == cmd.m_IDs[k] )
{
args[index] = k;
break;
}
}
}

UTIL_RD_SendInventoryCommand( cmd.m_eCmd, args, hResult );
pInventory->DestroyResult( hResult );

s_RD_Inventory_Command_Queue.m_ItemIDQueue.Remove( i );
return true;
}

return false;
}

void UTIL_RD_SendInventoryCommandOffline( EInventoryCommand eCmd, const CUtlVector<int> &args, const CUtlVector<SteamItemInstanceID_t> &items )
{
// we should only be calling this function in offline singleplayer mode (we need to be able to access the item cache on the server)
Expand Down Expand Up @@ -276,6 +366,7 @@ CASW_Player::InventoryCommandData_t::~InventoryCommandData_t()
static bool PreValidateInventoryCommand( CASW_Player *pPlayer, EInventoryCommand eCmd, const CUtlVector<int> &args, uint32_t nSize )
{
size_t nMaxSize = 65536;
int iArgsAreIndicesSkip = 0;
int iArgsAreIndices = 0;
switch ( eCmd )
{
Expand All @@ -290,13 +381,38 @@ static bool PreValidateInventoryCommand( CASW_Player *pPlayer, EInventoryCommand

break;
case INVCMD_MARINE_RESOURCE_EQUIPS:
if ( args.Count() > RD_NUM_STEAM_INVENTORY_EQUIP_SLOTS_MARINE_RESOURCE )
if ( args.Count() < 1 )
{
Warning( "Player %s sent invalid InvCmdInit - marine resource equip slots missing marine ID.\n", pPlayer->GetASWNetworkID() );
return false;
}

if ( args[0] < 0 || args[0] >= ASW_MAX_MARINE_RESOURCES )
{
Warning( "Player %s sent invalid InvCmdInit - marine resource %d is out of range.\n", pPlayer->GetASWNetworkID(), args[0] );
return false;
}

if ( !ASWGameResource() || !ASWGameResource()->GetMarineResource( args[0] ) )
{
Warning( "Player %s sent invalid InvCmdInit - marine resource %d does not exist.\n", pPlayer->GetASWNetworkID(), args[0] );
return false;
}

if ( ASWGameResource()->GetMarineResource( args[0] )->GetCommander() != pPlayer )
{
Warning( "Player %s sent invalid InvCmdInit - marine resource %d is owned by a different player.\n", pPlayer->GetASWNetworkID(), args[0] );
return false;
}

if ( args.Count() > RD_NUM_STEAM_INVENTORY_EQUIP_SLOTS_MARINE_RESOURCE + 1 )
{
Warning( "Player %s sent invalid InvCmdInit - marine resource equip slots (%d) exceeds limit (%d).\n", pPlayer->GetASWNetworkID(), args.Count(), RD_NUM_STEAM_INVENTORY_EQUIP_SLOTS_MARINE_RESOURCE );
return false;
}

iArgsAreIndices = RD_NUM_STEAM_INVENTORY_EQUIP_SLOTS_MARINE_RESOURCE;
iArgsAreIndicesSkip = 1;

break;
case INVCMD_MATERIAL_SPAWN:
Expand Down Expand Up @@ -366,6 +482,11 @@ static bool PreValidateInventoryCommand( CASW_Player *pPlayer, EInventoryCommand
CUtlVector<int> seen;
FOR_EACH_VEC( args, i )
{
if ( i < iArgsAreIndicesSkip )
{
continue;
}

if ( args[i] < 0 || args[i] >= iArgsAreIndices )
{
Warning( "Player %s sent invalid InvCmdInit(%d) - out of range equip slot number (%d).\n", pPlayer->GetASWNetworkID(), eCmd, args[i] );
Expand Down Expand Up @@ -530,13 +651,18 @@ static void ExecuteInventoryCommand( CASW_Player *pPlayer, EInventoryCommand eCm

FOR_EACH_VEC( args, i )
{
if ( i == 0 )
{
continue;
}

if ( args[i] < 0 || args[i] >= RD_NUM_STEAM_INVENTORY_EQUIP_SLOTS_MARINE_RESOURCE )
{
Assert( args[i] == -1 );
continue;
}

const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( items[i].ItemDefID );
const ReactiveDropInventory::ItemDef_t *pDef = ReactiveDropInventory::GetItemDef( items[i - 1].ItemDefID );
Assert( pDef );
if ( !pDef )
{
Expand All @@ -545,11 +671,11 @@ static void ExecuteInventoryCommand( CASW_Player *pPlayer, EInventoryCommand eCm

if ( pDef->ItemSlotMatches( ReactiveDropInventory::g_MarineResourceInventorySlotNames[args[i]] ) )
{
pMR->m_EquippedItemData.GetForModify()[args[i]].SetFromInstance( items[i] );
pMR->m_EquippedItemData.GetForModify()[args[i]].SetFromInstance( items[i - 1] );
}
else
{
Warning( "Player %s sent invalid INVCMD_MARINE_RESOURCE_EQUIPS - item %llu (%d \"%s\") does not fit in slot \"%s\".\n", pPlayer->GetASWNetworkID(), items[i].ItemID, items[i].ItemDefID, pDef->Name.Get(), ReactiveDropInventory::g_MarineResourceInventorySlotNames[args[i]] );
Warning( "Player %s sent invalid INVCMD_MARINE_RESOURCE_EQUIPS - item %llu (%d \"%s\") does not fit in slot \"%s\".\n", pPlayer->GetASWNetworkID(), items[i - 1].ItemID, items[i - 1].ItemDefID, pDef->Name.Get(), ReactiveDropInventory::g_MarineResourceInventorySlotNames[args[i]] );
}
}

Expand Down
1 change: 1 addition & 0 deletions src/game/shared/swarm/rd_inventory_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ enum EInventoryCommand

#ifdef CLIENT_DLL
int UTIL_RD_SendInventoryCommand( EInventoryCommand eCmd, const CUtlVector<int> &args, SteamInventoryResult_t hResult );
void UTIL_RD_SendInventoryCommandByIDs( EInventoryCommand eCmd, const CUtlVector<SteamItemInstanceID_t> &ids, const CUtlVector<int> &args = CUtlVector<int>{} );
void UTIL_RD_SendInventoryCommandOffline( EInventoryCommand eCmd, const CUtlVector<int> &args, const CUtlVector<SteamItemInstanceID_t> &items );
void UTIL_RD_AbortInventoryCommand( int iCommandID );
#endif
Loading

0 comments on commit e7ae204

Please sign in to comment.