Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 129 additions & 34 deletions csgo_gc/inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,23 @@ bool Inventory::UnlockCrate(uint64_t crateId,
return false;
}

if (keyId)
{
auto key = m_items.find(keyId);
if (key == m_items.end())
{
Platform::Print("UnlockCrate: key item %llu not found for crate %llu\n", keyId, crateId);
return false;
}

if (!m_itemSchema.IsKeyToolDefIndex(key->second.def_index()))
{
Platform::Print("UnlockCrate: item %llu def %u is not a key tool for crate %llu\n",
keyId, key->second.def_index(), crateId);
return false;
}
}

// CASE OPENING
CaseOpening caseOpening{ m_itemSchema, m_random };

Expand All @@ -532,9 +549,8 @@ bool Inventory::UnlockCrate(uint64_t crateId,
{
DestroyItem(crate, destroyCrate);

// remove the key if one was used (yes, we don't validate keys...)
auto key = m_items.find(keyId);
if (key != m_items.end())
if (keyId && key != m_items.end())
{
DestroyItem(key, destroyKey);
}
Expand Down Expand Up @@ -822,6 +838,21 @@ bool Inventory::ApplySticker(const CMsgApplySticker &message,
return false;
}

if (message.sticker_slot() >= MaxStickers)
{
Platform::Print("ApplySticker: invalid slot %u for tool %llu\n",
message.sticker_slot(), message.sticker_item_id());
return false;
}

if (sticker->second.def_index() != ItemSchema::ItemSticker
&& sticker->second.def_index() != ItemSchema::ItemPatch)
{
Platform::Print("ApplySticker: item %llu def %u is not a sticker or patch tool\n",
message.sticker_item_id(), sticker->second.def_index());
return false;
}

CSOEconItem *item = nullptr;

if (message.baseitem_defidx())
Expand Down Expand Up @@ -856,6 +887,8 @@ bool Inventory::ApplySticker(const CMsgApplySticker &message,

if (!stickerKit)
{
Platform::Print("ApplySticker: item %llu def %u has no sticker kit attribute\n",
message.sticker_item_id(), sticker->second.def_index());
assert(false);
return false;
}
Expand Down Expand Up @@ -1119,6 +1152,21 @@ bool Inventory::NameItem(uint64_t nameTagId,
CMsgSOSingleObject &destroy,
CMsgGCItemCustomizationNotification &notification)
{
auto tag = m_items.find(nameTagId);
if (tag == m_items.end())
{
Platform::Print("NameItem: name tag item %llu not found for target %llu\n",
nameTagId, itemId);
return false;
}

if (!m_itemSchema.IsNameTagToolDefIndex(tag->second.def_index()))
{
Platform::Print("NameItem: item %llu def %u is not a name tag for target %llu\n",
nameTagId, tag->second.def_index(), itemId);
return false;
}

auto it = m_items.find(itemId);
if (it == m_items.end())
{
Expand All @@ -1132,13 +1180,6 @@ bool Inventory::NameItem(uint64_t nameTagId,

if (GetConfig().DestroyUsedItems())
{
auto tag = m_items.find(nameTagId);
if (tag == m_items.end())
{
assert(false);
return false;
}

DestroyItem(tag, destroy);
}

Expand All @@ -1155,6 +1196,21 @@ bool Inventory::NameBaseItem(uint64_t nameTagId,
CMsgSOSingleObject &destroy,
CMsgGCItemCustomizationNotification &notification)
{
auto tag = m_items.find(nameTagId);
if (tag == m_items.end())
{
Platform::Print("NameBaseItem: name tag item %llu not found for base def %u\n",
nameTagId, defIndex);
return false;
}

if (!m_itemSchema.IsNameTagToolDefIndex(tag->second.def_index()))
{
Platform::Print("NameBaseItem: item %llu def %u is not a name tag for base def %u\n",
nameTagId, tag->second.def_index(), defIndex);
return false;
}

CSOEconItem &item = CreateItem(defIndex, ItemOriginBaseItem, UnacknowledgedInvalid);

item.mutable_custom_name()->assign(name);
Expand All @@ -1163,13 +1219,6 @@ bool Inventory::NameBaseItem(uint64_t nameTagId,

if (GetConfig().DestroyUsedItems())
{
auto tag = m_items.find(nameTagId);
if (tag == m_items.end())
{
assert(false);
return false;
}

DestroyItem(tag, destroy);
}

Expand Down Expand Up @@ -1659,11 +1708,55 @@ void Inventory::ConsumeToolItem(uint64_t toolId, CMsgSOSingleObject &removalMsg)
DestroyItem(it, removalMsg);
}

struct CounterSwapWeaponCounters
{
CSOEconItemAttribute *killEater = nullptr;
bool usesWeaponKillCounter = false;
};

static CounterSwapWeaponCounters FindCounterSwapWeaponCounters(ItemSchema &schema, CSOEconItem &weapon)
{
CounterSwapWeaponCounters counters{};

for (int i = 0; i < weapon.attribute_size(); ++i)
{
CSOEconItemAttribute *attribute = weapon.mutable_attribute(i);
if (attribute->def_index() == ItemSchema::AttributeKillEater)
{
counters.killEater = attribute;
}
else if (attribute->def_index() == ItemSchema::AttributeKillEaterScoreType
&& schema.AttributeUint32(attribute) == 0)
{
counters.usesWeaponKillCounter = true;
}
}

return counters;
}

Inventory::CounterSwapResult Inventory::PerformCounterSwap(uint64_t toolId, uint64_t weaponAId, uint64_t weaponBId)
{
CounterSwapResult result{};
result.weaponAId = weaponAId;
result.weaponBId = weaponBId;

auto toolIt = m_items.find(toolId);
if (toolIt == m_items.end())
{
Platform::Print("StatTrakSwap: tool item %llu not found for weapons %llu and %llu\n",
toolId, weaponAId, weaponBId);
result.status = CounterSwapStatus::ToolMissing;
return result;
}

if (!m_itemSchema.IsStatTrakSwapToolDefIndex(toolIt->second.def_index()))
{
Platform::Print("StatTrakSwap: item %llu def %u is not a StatTrak Swap Tool\n",
toolId, toolIt->second.def_index());
result.status = CounterSwapStatus::InvalidTool;
return result;
}

auto itA = m_items.find(weaponAId);
auto itB = m_items.find(weaponBId);
Expand All @@ -1677,34 +1770,36 @@ Inventory::CounterSwapResult Inventory::PerformCounterSwap(uint64_t toolId, uint

CSOEconItem &weaponA = itA->second;
CSOEconItem &weaponB = itB->second;

CSOEconItemAttribute *attrA = nullptr;
CSOEconItemAttribute *attrB = nullptr;

for (int i = 0; i < weaponA.attribute_size(); ++i)

if (weaponA.quality() != ItemSchema::QualityStrange
|| weaponB.quality() != ItemSchema::QualityStrange)
{
if (weaponA.attribute(i).def_index() == ItemSchema::AttributeKillEater)
{
attrA = weaponA.mutable_attribute(i);
break;
}
Platform::Print("StatTrakSwap: weapons must both be Strange quality (weapon %llu quality %u, weapon %llu quality %u)\n",
weaponAId, weaponA.quality(), weaponBId, weaponB.quality());
result.status = CounterSwapStatus::InvalidWeaponState;
return result;
}

for (int i = 0; i < weaponB.attribute_size(); ++i)
{
if (weaponB.attribute(i).def_index() == ItemSchema::AttributeKillEater)
{
attrB = weaponB.mutable_attribute(i);
break;
}
}
CounterSwapWeaponCounters countersA = FindCounterSwapWeaponCounters(m_itemSchema, weaponA);
CounterSwapWeaponCounters countersB = FindCounterSwapWeaponCounters(m_itemSchema, weaponB);
CSOEconItemAttribute *attrA = countersA.killEater;
CSOEconItemAttribute *attrB = countersB.killEater;

bool bothHaveCounters = attrA && attrB;
if (!bothHaveCounters)
{
result.status = CounterSwapStatus::CounterAttributeAbsent;
return result;
}

if (!countersA.usesWeaponKillCounter || !countersB.usesWeaponKillCounter)
{
Platform::Print("StatTrakSwap: weapons must both use weapon kill counters (weapon %llu score type ok=%d, weapon %llu score type ok=%d)\n",
weaponAId, countersA.usesWeaponKillCounter ? 1 : 0,
weaponBId, countersB.usesWeaponKillCounter ? 1 : 0);
result.status = CounterSwapStatus::InvalidWeaponState;
return result;
}

uint32_t valA = m_itemSchema.AttributeUint32(attrA);
uint32_t valB = m_itemSchema.AttributeUint32(attrB);
Expand Down
5 changes: 4 additions & 1 deletion csgo_gc/inventory.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,11 @@ class Inventory
enum class CounterSwapStatus
{
Completed,
ToolMissing,
InvalidTool,
WeaponMissing,
CounterAttributeAbsent
CounterAttributeAbsent,
InvalidWeaponState
};

struct CounterSwapResult
Expand Down
Loading
Loading