#pragma once #include "ProtoParse.h" #include "ProtobuffMessages.h" #include #include "Options.hpp" struct wskin { int wId; int paintkit; }; #define START_MUSICKIT_INDEX 1500000 #define START_ITEM_INDEX 2000000 static void clear_equip_state(CMsgClientWelcome::SubscribedType& object); static void apply_medals(CMsgClientWelcome::SubscribedType& object); static void apply_music_kits(CMsgClientWelcome::SubscribedType& object); static void add_item(CMsgClientWelcome::SubscribedType& object, int index, ItemDefinitionIndex itemIndex, int quality, int rarity, int paintKit, int seed, float wear, std::string name, std::string desc, sticker stickers[5], int stattrak, int flag); static int GetAvailableClassID(int definition_index); static int GetSlotID(int definition_index); static std::vector music_kits = { 3, 4, 5, 6, 7, 8 }; template inline std::string get_4bytes(T value) { return std::string{ reinterpret_cast(reinterpret_cast(&value)), 4 }; } template inline CSOEconItemAttribute make_econ_item_attribute(int def_index, T value) { CSOEconItemAttribute attribute; attribute.def_index().set(def_index); attribute.value_bytes().set(get_4bytes(value)); return attribute; } inline CSOEconItemEquipped make_equipped_state(int team, int slot) { CSOEconItemEquipped equipped_state; equipped_state.new_class().set(team); equipped_state.new_slot().set(slot); return equipped_state; } static std::string inventory_changer(void* pubDest, uint32_t* pcubMsgSize) { CMsgClientWelcome msg((void*)((DWORD)pubDest + 8), *pcubMsgSize - 8); if (!msg.outofdate_subscribed_caches().has()) return msg.serialize(); auto cache = msg.outofdate_subscribed_caches().get(); static auto fix_null_inventory = [&cache]() { auto objects = cache.objects().get_all(); auto it = std::find_if(objects.begin(), objects.end(), [](decltype(objects.front()) o) { return o.type_id().has() && o.type_id().get() == 1; }); if (it == objects.end()) { CMsgClientWelcome::SubscribedType null_object; null_object.type_id().set(1); cache.objects().add(null_object); } }; fix_null_inventory(); auto objects = cache.objects().get_all(); for (size_t i = 0; i < objects.size(); i++) { auto object = objects[i]; if (!object.type_id().has()) continue; switch (object.type_id().get()) { case 1: { if (true) object.object_data().clear(); int indexcount = 0; for (int i = 0; i < g_Options.weapons.value->weaponzcount; i++) if (g_Options.weapons.value->arr[i].active) { indexcount++; add_item(object, indexcount, (ItemDefinitionIndex)g_Options.weapons.value->arr[i].modeldefindex, g_Options.weapons.value->arr[i].quality, g_Options.weapons.value->arr[i].rarity, g_Options.weapons.value->arr[i].skinid, g_Options.weapons.value->arr[i].seed, g_Options.weapons.value->arr[i].wear, g_Options.weapons.value->arr[i].nametag, g_Options.weapons.value->arr[i].desctag, g_Options.weapons.value->arr[i].stickers, g_Options.weapons.value->arr[i].stattrak, i); } cache.objects().set(object, i); } break; } } msg.outofdate_subscribed_caches().set(cache); return msg.serialize(); } static bool inventory_changer_presend(void* pubData, uint32_t& cubData) { CMsgAdjustItemEquippedState msg((void*)((DWORD)pubData + 8), cubData - 8); if (msg.item_id().has() && (msg.new_class().get() == 0 || msg.new_slot().get() == 54)) { auto ItemIndex = msg.item_id().get() - START_MUSICKIT_INDEX; if (ItemIndex > 38 || ItemIndex < 3) return true; msg.new_slot().get() == 0xFFFF ? 0 : ItemIndex - 2; return false; } if (!msg.item_id().has() || !msg.new_class().get() || !msg.new_slot().get()) return true; return false; } static void clear_equip_state(CMsgClientWelcome::SubscribedType& object) { auto object_data = object.object_data().get_all(); for (size_t j = 0; j < object_data.size(); j++) { auto item = object_data[j]; if (!item.equipped_state().has()) continue; auto null_equipped_state = make_equipped_state(0, 0); auto equipped_state = item.equipped_state().get_all(); for (size_t k = 0; k < equipped_state.size(); k++) item.equipped_state().set(null_equipped_state, k); object.object_data().set(item, j); } } static void add_item(CMsgClientWelcome::SubscribedType& object, int index, ItemDefinitionIndex itemIndex, int quality, int rarity, int paintKit, int seed, float wear, std::string name, std::string desc, sticker stickers[5], int stattrak, int flag) { uint32_t steamid = iff.g_SteamUser->GetSteamID().GetAccountID(); CSOEconItem item; item.id().set(START_ITEM_INDEX + itemIndex); item.account_id().set(steamid); if (flag == 5) item.def_index().set(1314); else item.def_index().set(itemIndex); item.inventory().set(START_ITEM_INDEX + index); item.origin().set(24); item.quantity().set(1); item.level().set(1); item.style().set(0); item.flags().set(0); item.in_use().set(true); item.original_id().set(0); item.rarity().set(rarity); item.quality().set(quality); if (name.size() > 0) item.custom_name().set(name); if (desc.size() > 0) item.custom_desc().set(desc); if (flag > 5) { int avalTeam = GetAvailableClassID(itemIndex); if (avalTeam == TEAM_SPECTATOR || avalTeam == TEAM_TERRORIST) { item.equipped_state().add(make_equipped_state(TEAM_TERRORIST, GetSlotID(itemIndex))); } if (avalTeam == TEAM_SPECTATOR || avalTeam == TEAM_CT) { item.equipped_state().add(make_equipped_state(TEAM_CT, GetSlotID(itemIndex))); } } item.attribute().add(make_econ_item_attribute(6, float(paintKit))); item.attribute().add(make_econ_item_attribute(7, float(seed))); item.attribute().add(make_econ_item_attribute(8, float(wear))); for (int j = 0; j < 5; j++) { item.attribute().add(make_econ_item_attribute(113 + 4 * j, stickers[j].stickerid )); item.attribute().add(make_econ_item_attribute(114 + 4 * j, stickers[j].wear)); item.attribute().add(make_econ_item_attribute(115 + 4 * j, stickers[j].scale)); item.attribute().add(make_econ_item_attribute(116 + 4 * j, stickers[j].rotation)); } if (stattrak != -1) { item.attribute().add(make_econ_item_attribute(80, stattrak)); item.attribute().add(make_econ_item_attribute(81, 0)); } if (flag == 0) { item.equipped_state().add(make_equipped_state(TEAM_TERRORIST, 0)); item.equipped_state().add(make_equipped_state(TEAM_CT, 0)); } if (flag == 1) { item.equipped_state().add(make_equipped_state(TEAM_TERRORIST, 41)); item.equipped_state().add(make_equipped_state(TEAM_CT, 41)); } if (flag == 2) item.equipped_state().set(make_equipped_state(2, 38)); if (flag == 3) item.equipped_state().set(make_equipped_state(3, 38)); if (flag == 4) item.equipped_state().set(make_equipped_state(0, 55)); if (flag == 5) { item.attribute().add(make_econ_item_attribute(166, itemIndex)); item.inventory().set(START_MUSICKIT_INDEX + itemIndex); item.id().set(START_MUSICKIT_INDEX + itemIndex); item.equipped_state().set(make_equipped_state(0, 54)); } object.object_data().add(item); } static int GetAvailableClassID(int definition_index) { switch (definition_index) { case WEAPON_KNIFE_BAYONET: case WEAPON_KNIFE_FLIP: case WEAPON_KNIFE_GUT: case WEAPON_KNIFE_KARAMBIT: case WEAPON_KNIFE_M9_BAYONET: case WEAPON_KNIFE_TACTICAL: case WEAPON_KNIFE_FALCHION: case WEAPON_KNIFE_SURVIVAL_BOWIE: case WEAPON_KNIFE_BUTTERFLY: case WEAPON_KNIFE_PUSH: case WEAPON_ELITE: case WEAPON_P250: case WEAPON_CZ75A: case WEAPON_DEAGLE: case WEAPON_REVOLVER: case WEAPON_MP7: case WEAPON_UMP45: case WEAPON_P90: case WEAPON_BIZON: case WEAPON_SSG08: case WEAPON_AWP: case WEAPON_NOVA: case WEAPON_XM1014: case WEAPON_M249: case WEAPON_NEGEV: case GLOVE_STUDDED_BLOODHOUND: case GLOVE_SPORTY: case GLOVE_SLICK: case GLOVE_LEATHER_WRAP: case GLOVE_MOTORCYCLE: case GLOVE_SPECIALIST: return TEAM_SPECTATOR; case WEAPON_GLOCK: case WEAPON_AK47: case WEAPON_MAC10: case WEAPON_G3SG1: case WEAPON_TEC9: case WEAPON_GALILAR: case WEAPON_SG553: case WEAPON_SAWEDOFF: case WEAPON_C4: return TEAM_TERRORIST; case WEAPON_AUG: case WEAPON_FAMAS: case WEAPON_MAG7: case WEAPON_FIVESEVEN: case WEAPON_USP_SILENCER: case WEAPON_HKP2000: case WEAPON_MP9: case WEAPON_M4A1_SILENCER: case WEAPON_M4A1: case WEAPON_SCAR20: return TEAM_CT; default: return TEAM_UNASSIGNED; } } static int GetSlotID(int definition_index) { switch (definition_index) { case WEAPON_KNIFE_BAYONET: case WEAPON_KNIFE_FLIP: case WEAPON_KNIFE_GUT: case WEAPON_KNIFE_KARAMBIT: case WEAPON_KNIFE_M9_BAYONET: case WEAPON_KNIFE_TACTICAL: case WEAPON_KNIFE_FALCHION: case WEAPON_KNIFE_SURVIVAL_BOWIE: case WEAPON_KNIFE_BUTTERFLY: case WEAPON_KNIFE_PUSH: return 0; case WEAPON_C4: return 1; case WEAPON_USP_SILENCER: case WEAPON_HKP2000: case WEAPON_GLOCK: return 2; case WEAPON_ELITE: return 3; case WEAPON_P250: return 4; case WEAPON_TEC9: case WEAPON_CZ75A: case WEAPON_FIVESEVEN: return 5; case WEAPON_DEAGLE: case WEAPON_REVOLVER: return 6; case WEAPON_MP9: case WEAPON_MAC10: return 8; case WEAPON_MP7: return 9; case WEAPON_UMP45: return 10; case WEAPON_P90: return 11; case WEAPON_BIZON: return 12; case WEAPON_FAMAS: case WEAPON_GALILAR: return 14; case WEAPON_M4A1_SILENCER: case WEAPON_M4A1: case WEAPON_AK47: return 15; case WEAPON_SSG08: return 16; case WEAPON_SG553: case WEAPON_AUG: return 17; case WEAPON_AWP: return 18; case WEAPON_G3SG1: case WEAPON_SCAR20: return 19; case WEAPON_NOVA: return 20; case WEAPON_XM1014: return 21; case WEAPON_SAWEDOFF: case WEAPON_MAG7: return 22; case WEAPON_M249: return 23; case WEAPON_NEGEV: return 24; case GLOVE_STUDDED_BLOODHOUND: case GLOVE_SPORTY: case GLOVE_SLICK: case GLOVE_LEATHER_WRAP: case GLOVE_MOTORCYCLE: case GLOVE_SPECIALIST: return 41; default: return -1; } }