-
Автор темы
- #1
Пожалуйста, авторизуйтесь для просмотра ссылки.
valve_sdk/csgostructs.hpp
После void SetGloveModelIndex(int modelIndex); добавляем
Код:
void SetModelIndex(const int index)
{
return CallVFunction<void(__thiscall*)(C_BaseEntity*, int)>(this, 75)(this, index);
}
Код:
#pragma once
using LocalizeStringIndex_t = unsigned;
class ILocalizeTextQuery
{
public:
virtual int ComputeTextWidth(const wchar_t* pString) = 0;
};
class ILocalizationChangeCallback
{
public:
virtual void OnLocalizationChanged() = 0;
};
class ILocalize : public IAppSystem
{
public:
virtual bool AddFile(const char* fileName, const char* pPathID = nullptr, bool bIncludeFallbackSearchPaths = false) = 0;
virtual void RemoveAll() = 0;
virtual wchar_t* Find(const char* tokenName) = 0;
virtual const wchar_t* FindSafe(const char* tokenName) = 0;
virtual int ConvertANSIToUnicode(const char* ansi, wchar_t* unicode, int unicodeBufferSizeInBytes) = 0;
virtual int ConvertUnicodeToANSI(const wchar_t* unicode, char* ansi, int ansiBufferSize) = 0;
virtual LocalizeStringIndex_t FindIndex(const char* tokenName) = 0;
virtual void ConstructString(wchar_t* unicodeOuput, int unicodeBufferSizeInBytes, const wchar_t* formatString, int numFormatParameters, ...) = 0;
virtual const char* GetNameByIndex(LocalizeStringIndex_t index) = 0;
virtual wchar_t* GetValueByIndex(LocalizeStringIndex_t index) = 0;
};
Код:
m_nDeltaTick = -1;
Код:
*reinterpret_cast<int*>(std::uintptr_t(this) + 0x174) = -1;
Код:
class IGameEvent
{
public:
virtual ~IGameEvent() {};
virtual const char* GetName() const = 0;
virtual bool IsReliable() const = 0;
virtual bool IsLocal() const = 0;
virtual bool IsEmpty(const char* keyname = nullptr) = 0;
virtual bool GetBool(const char* keyname = nullptr, bool default_value = false) = 0;
virtual int GetInt(const char* keyname = nullptr, int default_value = 0) = 0;
virtual uint64_t GetUint64(const char* keyname = nullptr, uint64_t default_value = 0) = 0;
virtual float GetFloat(const char* keyname = nullptr, float default_value = 0.0f) = 0;
virtual const char* GetString(const char* keyname = nullptr, const char* default_value = "") = 0;
virtual const wchar_t* GetWString(const char* keyname = nullptr, const wchar_t* default_value = L"") = 0;
virtual const void* GetPtr(const char* keyname = nullptr, const void* default_values = nullptr) = 0;
virtual void SetBool(const char* keyname, bool value) = 0;
virtual void SetInt(const char* keyname, int value) = 0;
virtual void SetUint64(const char* keyname, uint64_t value) = 0;
virtual void SetFloat(const char* keyname, float value) = 0;
virtual void SetString(const char* keyname, const char* value) = 0;
virtual void SetWString(const char* keyname, const wchar_t* value) = 0;
virtual void SetPtr(const char* keyname, const void* value) = 0;
};
Код:
class recv_prop_hook
{
public:
recv_prop_hook(RecvProp* prop, const RecvVarProxyFn proxy_fn) : m_property(prop), m_original_proxy_fn(prop->m_ProxyFn)
{
set_proxy_function(proxy_fn);
}
~recv_prop_hook()
{
m_property->m_ProxyFn = m_original_proxy_fn;
}
auto get_original_function() const -> RecvVarProxyFn
{
return m_original_proxy_fn;
}
auto set_proxy_function(const RecvVarProxyFn proxy_fn) const -> void
{
m_property->m_ProxyFn = proxy_fn;
}
private:
RecvProp* m_property;
RecvVarProxyFn m_original_proxy_fn;
};
Добавляем #include "Interfaces/ILocalize.hpp"
После extern IPhysicsSurfaceProps* g_PhysSurface; добавляем extern ILocalize* g_Localize;
valve_sdk/sdk.cpp
Добавляем
Код:
ILocalize* g_Localize = nullptr;
auto localizeFactory = get_module_factory(GetModuleHandleW(L"localize.dll"));
g_Localize = get_interface<ILocalize>(localizeFactory, "Localize_001");
Код:
enum ItemDefinitionIndex
{
WEAPON_DEAGLE = 1,
WEAPON_ELITE = 2,
WEAPON_FIVESEVEN = 3,
WEAPON_GLOCK = 4,
WEAPON_AK47 = 7,
WEAPON_AUG = 8,
WEAPON_AWP = 9,
WEAPON_FAMAS = 10,
WEAPON_G3SG1 = 11,
WEAPON_GALILAR = 13,
WEAPON_M249 = 14,
WEAPON_M4A1 = 16,
WEAPON_MAC10 = 17,
WEAPON_P90 = 19,
WEAPON_UMP45 = 24,
WEAPON_XM1014 = 25,
WEAPON_BIZON = 26,
WEAPON_MAG7 = 27,
WEAPON_NEGEV = 28,
WEAPON_SAWEDOFF = 29,
WEAPON_TEC9 = 30,
WEAPON_TASER = 31,
WEAPON_HKP2000 = 32,
WEAPON_MP7 = 33,
WEAPON_MP9 = 34,
WEAPON_NOVA = 35,
WEAPON_P250 = 36,
WEAPON_SCAR20 = 38,
WEAPON_SG556 = 39,
WEAPON_SSG08 = 40,
WEAPON_KNIFE = 42,
WEAPON_FLASHBANG = 43,
WEAPON_HEGRENADE = 44,
WEAPON_SMOKEGRENADE = 45,
WEAPON_MOLOTOV = 46,
WEAPON_DECOY = 47,
WEAPON_INCGRENADE = 48,
WEAPON_C4 = 49,
WEAPON_KNIFE_T = 59,
WEAPON_M4A1_SILENCER = 60,
WEAPON_USP_SILENCER = 61,
WEAPON_CZ75A = 63,
WEAPON_REVOLVER = 64,
WEAPON_KNIFE_BAYONET = 500,
WEAPON_KNIFE_FLIP = 505,
WEAPON_KNIFE_GUT = 506,
WEAPON_KNIFE_KARAMBIT = 507,
WEAPON_KNIFE_M9_BAYONET = 508,
WEAPON_KNIFE_TACTICAL = 509,
WEAPON_KNIFE_FALCHION = 512,
WEAPON_KNIFE_SURVIVAL_BOWIE = 514,
WEAPON_KNIFE_BUTTERFLY = 515,
WEAPON_KNIFE_PUSH = 516,
GLOVE_STUDDED_BLOODHOUND = 5027,
GLOVE_T_SIDE = 5028,
GLOVE_CT_SIDE = 5029,
GLOVE_SPORTY = 5030,
GLOVE_SLICK = 5031,
GLOVE_LEATHER_WRAP = 5032,
GLOVE_MOTORCYCLE = 5033,
GLOVE_SPECIALIST = 5034,
GLOVE_HYDRA = 5035
};
Код:
#pragma once
#include <map>
#include <vector>
#include "valve_sdk\csgostructs.hpp"
static auto is_knife(const int i) -> bool
{
return (i >= WEAPON_KNIFE_BAYONET && i < GLOVE_STUDDED_BLOODHOUND) || i == WEAPON_KNIFE_T || i == WEAPON_KNIFE;
}
struct weapon_info
{
constexpr weapon_info(const char* model, const char* icon = nullptr) :
model(model),
icon(icon)
{}
const char* model;
const char* icon;
};
struct weapon_name
{
constexpr weapon_name(const int definition_index, const char* name) :
definition_index(definition_index),
name(name)
{}
int definition_index = 0;
const char* name = nullptr;
};
extern const std::map<size_t, weapon_info> k_weapon_info;
extern const std::vector<weapon_name> k_knife_names;
extern const std::vector<weapon_name> k_glove_names;
extern const std::vector<weapon_name> k_weapon_names;
Код:
#include "item_definitions.hpp"
const std::map<size_t, weapon_info> k_weapon_info =
{
{ WEAPON_KNIFE,{ "models/weapons/v_knife_default_ct.mdl", "knife_default_ct" } },
{ WEAPON_KNIFE_T,{ "models/weapons/v_knife_default_t.mdl", "knife_t" } },
{ WEAPON_KNIFE_BAYONET,{ "models/weapons/v_knife_bayonet.mdl", "bayonet" } },
{ WEAPON_KNIFE_FLIP,{ "models/weapons/v_knife_flip.mdl", "knife_flip" } },
{ WEAPON_KNIFE_GUT,{ "models/weapons/v_knife_gut.mdl", "knife_gut" } },
{ WEAPON_KNIFE_KARAMBIT,{ "models/weapons/v_knife_karam.mdl", "knife_karambit" } },
{ WEAPON_KNIFE_M9_BAYONET,{ "models/weapons/v_knife_m9_bay.mdl", "knife_m9_bayonet" } },
{ WEAPON_KNIFE_TACTICAL,{ "models/weapons/v_knife_tactical.mdl", "knife_tactical" } },
{ WEAPON_KNIFE_FALCHION,{ "models/weapons/v_knife_falchion_advanced.mdl", "knife_falchion" } },
{ WEAPON_KNIFE_SURVIVAL_BOWIE,{ "models/weapons/v_knife_survival_bowie.mdl", "knife_survival_bowie" } },
{ WEAPON_KNIFE_BUTTERFLY,{ "models/weapons/v_knife_butterfly.mdl", "knife_butterfly" } },
{ WEAPON_KNIFE_PUSH,{ "models/weapons/v_knife_push.mdl", "knife_push" } },
{ GLOVE_STUDDED_BLOODHOUND,{ "models/weapons/v_models/arms/glove_bloodhound/v_glove_bloodhound.mdl" } },
{ GLOVE_T_SIDE,{ "models/weapons/v_models/arms/glove_fingerless/v_glove_fingerless.mdl" } },
{ GLOVE_CT_SIDE,{ "models/weapons/v_models/arms/glove_hardknuckle/v_glove_hardknuckle.mdl" } },
{ GLOVE_SPORTY,{ "models/weapons/v_models/arms/glove_sporty/v_glove_sporty.mdl" } },
{ GLOVE_SLICK,{ "models/weapons/v_models/arms/glove_slick/v_glove_slick.mdl" } },
{ GLOVE_LEATHER_WRAP,{ "models/weapons/v_models/arms/glove_handwrap_leathery/v_glove_handwrap_leathery.mdl" } },
{ GLOVE_MOTORCYCLE,{ "models/weapons/v_models/arms/glove_motorcycle/v_glove_motorcycle.mdl" } },
{ GLOVE_SPECIALIST,{ "models/weapons/v_models/arms/glove_specialist/v_glove_specialist.mdl" } },
{ GLOVE_HYDRA,{ "models/weapons/v_models/arms/glove_bloodhound/v_glove_bloodhound_hydra.mdl" } }
};
const std::vector<weapon_name> k_knife_names =
{
{ 0, "Default" },
{ WEAPON_KNIFE_BAYONET, "Bayonet" },
{ WEAPON_KNIFE_FLIP, "Flip Knife" },
{ WEAPON_KNIFE_GUT, "Gut Knife" },
{ WEAPON_KNIFE_KARAMBIT, "Karambit" },
{ WEAPON_KNIFE_M9_BAYONET, "M9 Bayonet" },
{ WEAPON_KNIFE_TACTICAL, "Huntsman Knife" },
{ WEAPON_KNIFE_FALCHION, "Falchion Knife" },
{ WEAPON_KNIFE_SURVIVAL_BOWIE, "Bowie Knife" },
{ WEAPON_KNIFE_BUTTERFLY, "Butterfly Knife" },
{ WEAPON_KNIFE_PUSH, "Shadow Daggers" }
};
const std::vector<weapon_name> k_glove_names =
{
{ 0, "Default" },
{ GLOVE_STUDDED_BLOODHOUND, "Bloodhound" },
{ GLOVE_T_SIDE, "Default (Terrorists)" },
{ GLOVE_CT_SIDE, "Default (Counter-Terrorists)" },
{ GLOVE_SPORTY, "Sporty" },
{ GLOVE_SLICK, "Slick" },
{ GLOVE_LEATHER_WRAP, "Handwrap" },
{ GLOVE_MOTORCYCLE, "Motorcycle" },
{ GLOVE_SPECIALIST, "Specialist" },
{ GLOVE_HYDRA, "Hydra" }
};
const std::vector<weapon_name> k_weapon_names =
{
{ WEAPON_KNIFE, "Knife" },
{ GLOVE_T_SIDE, "Glove" },
{ 7, "AK-47" },
{ 8, "AUG" },
{ 9, "AWP" },
{ 63, "CZ75 Auto" },
{ 1, "Desert Eagle" },
{ 2, "Dual Berettas" },
{ 10, "FAMAS" },
{ 3, "Five-SeveN" },
{ 11, "G3SG1" },
{ 13, "Galil AR" },
{ 4, "Glock-18" },
{ 14, "M249" },
{ 60, "M4A1-S" },
{ 16, "M4A4" },
{ 17, "MAC-10" },
{ 27, "MAG-7" },
{ 33, "MP7" },
{ 34, "MP9" },
{ 28, "Negev" },
{ 35, "Nova" },
{ 32, "P2000" },
{ 36, "P250" },
{ 19, "P90" },
{ 26, "PP-Bizon" },
{ 64, "R8 Revolver" },
{ 29, "Sawed-Off" },
{ 38, "SCAR-20" },
{ 40, "SSG 08" },
{ 39, "SG 553" },
{ 30, "Tec-9" },
{ 24, "UMP-45" },
{ 61, "USP-S" },
{ 25, "XM1014" },
};
Код:
#pragma once
#include <vector>
struct paint_kit
{
int id;
std::string name;
auto operator < (const paint_kit& other) const -> bool
{
return name < other.name;
}
};
extern std::vector<paint_kit> k_skins;
extern std::vector<paint_kit> k_gloves;
extern auto initialize_kits() -> void;
Код:
#include <algorithm>
#include "kit_parser.hpp"
#include "helpers\utils.hpp"
std::vector<paint_kit> k_skins;
std::vector<paint_kit> k_gloves;
class CCStrike15ItemSchema;
class CCStrike15ItemSystem;
template <typename Key, typename Value>
struct Node_t
{
int previous_id; //0x0000
int next_id; //0x0004
void* _unknown_ptr; //0x0008
int _unknown; //0x000C
Key key; //0x0010
Value value; //0x0014
};
template <typename Key, typename Value>
struct Head_t
{
Node_t<Key, Value>* memory; //0x0000
int allocation_count; //0x0004
int grow_size; //0x0008
int start_element; //0x000C
int next_available; //0x0010
int _unknown; //0x0014
int last_element; //0x0018
}; //Size=0x001C
// could use CUtlString but this is just easier and CUtlString isn't needed anywhere else
struct String_t
{
char* buffer; //0x0000
int capacity; //0x0004
int grow_size; //0x0008
int length; //0x000C
}; //Size=0x0010
struct CPaintKit
{
int id; //0x0000
String_t name; //0x0004
String_t description; //0x0014
String_t item_name; //0x0024
String_t material_name; //0x0034
String_t image_inventory; //0x0044
char pad_0x0054[0x8C]; //0x0054
}; //Size=0x00E0
auto get_export(const char* module_name, const char* export_name) -> void*
{
HMODULE mod;
while (!((mod = GetModuleHandleA(module_name))))
Sleep(100);
return reinterpret_cast<void*>(GetProcAddress(mod, export_name));
}
auto initialize_kits() -> void
{
const auto V_UCS2ToUTF8 = static_cast<int(*)(const wchar_t* ucs2, char* utf8, int len)>(get_export("vstdlib.dll", "V_UCS2ToUTF8"));
// Search the relative calls
// call ItemSystem
// push dword ptr [esi+0Ch]
// lea ecx, [eax+4]
// call CEconItemSchema::GetPaintKitDefinition
const auto sig_address = Utils::PatternScan(GetModuleHandle(L"client.dll"), "E8 ? ? ? ? FF 76 0C 8D 48 04 E8");
// Skip the opcode, read rel32 address
const auto item_system_offset = *reinterpret_cast<std::int32_t*>(sig_address + 1);
// Add the offset to the end of the instruction
const auto item_system_fn = reinterpret_cast<CCStrike15ItemSystem* (*)()>(sig_address + 5 + item_system_offset);
// Skip VTable, first member variable of ItemSystem is ItemSchema
const auto item_schema = reinterpret_cast<CCStrike15ItemSchema*>(std::uintptr_t(item_system_fn()) + sizeof(void*));
// Dump paint kits
{
// Skip the instructions between, skip the opcode, read rel32 address
const auto get_paint_kit_definition_offset = *reinterpret_cast<std::int32_t*>(sig_address + 11 + 1);
// Add the offset to the end of the instruction
const auto get_paint_kit_definition_fn = reinterpret_cast<CPaintKit*(__thiscall*)(CCStrike15ItemSchema*, int)>(sig_address + 11 + 5 + get_paint_kit_definition_offset);
// The last offset is start_element, we need that
// push ebp
// mov ebp, esp
// sub esp, 0Ch
// mov eax, [ecx+298h]
// Skip instructions, skip opcode, read offset
const auto start_element_offset = *reinterpret_cast<std::intptr_t*>(std::uintptr_t(get_paint_kit_definition_fn) + 8 + 2);
// Calculate head base from start_element's offset
const auto head_offset = start_element_offset - 12;
const auto map_head = reinterpret_cast<Head_t<int, CPaintKit*>*>(std::uintptr_t(item_schema) + head_offset);
for (auto i = 0; i <= map_head->last_element; ++i)
{
const auto paint_kit = map_head->memory[i].value;
if (paint_kit->id == 9001)
continue;
const auto wide_name = g_Localize->Find(paint_kit->item_name.buffer + 1);
char name[256];
//size_t retval;
//wcstombs_s(&retval, name, sizeof(name) - 1, wide_name, sizeof(name) - 1);
//g_localize->ConvertUnicodeToANSI(wide_name, name, sizeof(name));
V_UCS2ToUTF8(wide_name, name, sizeof(name));
if (paint_kit->id < 10000)
k_skins.push_back({ paint_kit->id, name });
else
k_gloves.push_back({ paint_kit->id, name });
}
std::sort(k_skins.begin(), k_skins.end());
std::sort(k_gloves.begin(), k_gloves.end());
}
}
Добавляем
Код:
#include "kit_parser.hpp"
#include "item_definitions.hpp"
struct item_setting
{
char name[32] = "Default";
bool enabled = false;
int definition_vector_index = 0;
int definition_index = 1;
int paint_kit_vector_index = 0;
int paint_kit_index = 0;
int definition_override_vector_index = 0;
int definition_override_index = 0;
int seed = 0;
int stat_trak = 0;
float wear = std::numeric_limits<float>::min();
char custom_name[32] = "";
};
Код:
struct {
std::map<int, item_setting> m_items;
std::unordered_map<std::string, std::string> m_icon_overrides;
auto get_icon_override(const std::string original) const -> const char*
{
return m_icon_overrides.count(original) ? m_icon_overrides.at(original).data() : nullptr;
}
} skins;
Код:
void RenderSkinsTab()
{
if (k_skins.size() == 0) {
initialize_kits();
}
auto& entries = g_Options.skins.m_items;
static auto definition_vector_index = 0;
ImGui::Columns(2, nullptr, false);
{
ImGui::PushItemWidth(-1);
ImGui::ListBoxHeader("##config");
{
for (size_t w = 0; w < k_weapon_names.size(); w++) {
if (ImGui::Selectable(k_weapon_names[w].name, definition_vector_index == w)) {
definition_vector_index = w;
}
}
}
ImGui::ListBoxFooter();
if (ImGui::Button("Update"))
g_ClientState->ForceFullUpdate();
ImGui::PopItemWidth();
}
ImGui::NextColumn();
{
auto& selected_entry = entries[k_weapon_names[definition_vector_index].definition_index];
selected_entry.definition_index = k_weapon_names[definition_vector_index].definition_index;
selected_entry.definition_vector_index = definition_vector_index;
ImGui::Checkbox("Enabled", &selected_entry.enabled);
ImGui::InputInt("Seed", &selected_entry.seed);
ImGui::InputInt("StatTrak", &selected_entry.stat_trak);
ImGui::SliderFloat("Wear", &selected_entry.wear, FLT_MIN, 1.f, "%.10f", 5);
if (selected_entry.definition_index != GLOVE_T_SIDE)
{
ImGui::Combo("Paint Kit", &selected_entry.paint_kit_vector_index, [](void* data, int idx, const char** out_text)
{
*out_text = k_skins[idx].name.c_str();
return true;
}, nullptr, k_skins.size(), 10);
selected_entry.paint_kit_index = k_skins[selected_entry.paint_kit_vector_index].id;
}
else
{
ImGui::Combo("Paint Kit", &selected_entry.paint_kit_vector_index, [](void* data, int idx, const char** out_text)
{
*out_text = k_gloves[idx].name.c_str();
return true;
}, nullptr, k_gloves.size(), 10);
selected_entry.paint_kit_index = k_gloves[selected_entry.paint_kit_vector_index].id;
}
if (selected_entry.definition_index == WEAPON_KNIFE)
{
ImGui::Combo("Knife", &selected_entry.definition_override_vector_index, [](void* data, int idx, const char** out_text)
{
*out_text = k_knife_names.at(idx).name;
return true;
}, nullptr, k_knife_names.size(), 5);
selected_entry.definition_override_index = k_knife_names.at(selected_entry.definition_override_vector_index).definition_index;
}
else if (selected_entry.definition_index == GLOVE_T_SIDE)
{
ImGui::Combo("Glove", &selected_entry.definition_override_vector_index, [](void* data, int idx, const char** out_text)
{
*out_text = k_glove_names.at(idx).name;
return true;
}, nullptr, k_glove_names.size(), 5);
selected_entry.definition_override_index = k_glove_names.at(selected_entry.definition_override_vector_index).definition_index;
}
else
{
static auto unused_value = 0;
selected_entry.definition_override_vector_index = 0;
ImGui::Combo("Unavailable", &unused_value, "For knives or gloves\0");
}
ImGui::InputText("Name Tag", selected_entry.custom_name, 32);
}
ImGui::Columns(1, nullptr, false);
}
Код:
#pragma once
#include "../valve_sdk/csgostructs.hpp"
#include "../options.hpp"
namespace Skins {
void OnFrameStageNotify(ClientFrameStage_t stage);
};
Код:
#include "skins.h"
static auto erase_override_if_exists_by_index(const int definition_index) -> void
{
if (k_weapon_info.count(definition_index))
{
auto& icon_override_map = g_Options.skins.m_icon_overrides;
const auto& original_item = k_weapon_info.at(definition_index);
if (original_item.icon && icon_override_map.count(original_item.icon))
icon_override_map.erase(icon_override_map.at(original_item.icon)); // Remove the leftover override
}
}
static auto apply_config_on_attributable_item(C_BaseAttributableItem* item, const item_setting* config,
const unsigned xuid_low) -> void
{
if (!config->enabled) {
return;
}
item->m_Item().m_iItemIDHigh() = -1;
item->m_Item().m_iAccountID() = xuid_low;
if (config->custom_name[0])
strcpy_s(item->m_Item().m_iCustomName(), config->custom_name);
if (config->paint_kit_index)
item->m_nFallbackPaintKit() = config->paint_kit_index;
if (config->seed)
item->m_nFallbackSeed() = config->seed;
if (config->stat_trak) {
item->m_nFallbackStatTrak() = config->stat_trak;
item->m_Item().m_iEntityQuality() = 9;
}
else {
item->m_Item().m_iEntityQuality() = is_knife(config->definition_index) ? 3 : 0;
}
item->m_flFallbackWear() = config->wear;
auto& definition_index = item->m_Item().m_iItemDefinitionIndex();
auto& icon_override_map = g_Options.skins.m_icon_overrides;
if (config->definition_override_index && config->definition_override_index != definition_index && k_weapon_info.count(config->definition_override_index))
{
const auto old_definition_index = definition_index;
definition_index = config->definition_override_index;
const auto& replacement_item = k_weapon_info.at(config->definition_override_index);
item->m_nModelIndex() = g_MdlInfo->GetModelIndex(replacement_item.model);
item->SetModelIndex(g_MdlInfo->GetModelIndex(replacement_item.model));
item->GetClientNetworkable()->PreDataUpdate(0);
if (old_definition_index && k_weapon_info.count(old_definition_index))
{
const auto& original_item = k_weapon_info.at(old_definition_index);
if (original_item.icon && replacement_item.icon) {
icon_override_map[original_item.icon] = replacement_item.icon;
}
}
}
else
{
erase_override_if_exists_by_index(definition_index);
}
}
static auto get_wearable_create_fn() -> CreateClientClassFn
{
auto clazz = g_CHLClient->GetAllClasses();
// Please, if you gonna paste it into a cheat use classids here. I use names because they
// won't change in the foreseeable future and i dont need high speed, but chances are
// you already have classids, so use them instead, they are faster.
while (strcmp(clazz->m_pNetworkName, "CEconWearable"))
clazz = clazz->m_pNext;
return clazz->m_pCreateFn;
}
void Skins::OnFrameStageNotify(ClientFrameStage_t stage)
{
if (stage != FRAME_NET_UPDATE_POSTDATAUPDATE_START)
return;
const auto local_index = g_EngineClient->GetLocalPlayer();
const auto local = static_cast<C_BasePlayer*>(g_EntityList->GetClientEntity(local_index));
if (!local)
return;
player_info_t player_info;
if (!g_EngineClient->GetPlayerInfo(local_index, &player_info))
return;
{
const auto wearables = local->m_hMyWearables();
const auto glove_config = &g_Options.skins.m_items[GLOVE_T_SIDE];
static auto glove_handle = CBaseHandle(0);
auto glove = reinterpret_cast<C_BaseAttributableItem*>(g_EntityList->GetClientEntityFromHandle(wearables[0]));
if (!glove)
{
const auto our_glove = reinterpret_cast<C_BaseAttributableItem*>(g_EntityList->GetClientEntityFromHandle(glove_handle));
if (our_glove) // Our glove still exists
{
wearables[0] = glove_handle;
glove = our_glove;
}
}
if (!local->IsAlive())
{
if (glove)
{
glove->GetClientNetworkable()->SetDestroyedOnRecreateEntities();
glove->GetClientNetworkable()->Release();
}
return;
}
if (glove_config && glove_config->definition_override_index)
{
if (!glove)
{
static auto create_wearable_fn = get_wearable_create_fn();
const auto entry = g_EntityList->GetHighestEntityIndex() + 1;
const auto serial = rand() % 0x1000;
//glove = static_cast<C_BaseAttributableItem*>(create_wearable_fn(entry, serial));
create_wearable_fn(entry, serial);
glove = reinterpret_cast<C_BaseAttributableItem*>(g_EntityList->GetClientEntity(entry));
assert(glove);
{
static auto set_abs_origin_addr = Utils::PatternScan(GetModuleHandle(L"client.dll"), "55 8B EC 83 E4 F8 51 53 56 57 8B F1");
const auto set_abs_origin_fn = reinterpret_cast<void(__thiscall*)(void*, const std::array<float, 3>&)>(set_abs_origin_addr);
static constexpr std::array<float, 3> new_pos = { 10000.f, 10000.f, 10000.f };
set_abs_origin_fn(glove, new_pos);
}
const auto wearable_handle = reinterpret_cast<CBaseHandle*>(&wearables[0]);
*wearable_handle = entry | serial << 16;
glove_handle = wearables[0];
}
// Thanks, Beakers
glove->SetGloveModelIndex(-1);
apply_config_on_attributable_item(glove, glove_config, player_info.xuid_low);
}
}
{
auto weapons = local->m_hMyWeapons();
for (int i = 0; weapons[i].IsValid(); i++)
{
C_BaseAttributableItem *weapon = (C_BaseAttributableItem*)g_EntityList->GetClientEntityFromHandle(weapons[i]);
if (!weapon)
continue;
auto& definition_index = weapon->m_Item().m_iItemDefinitionIndex();
const auto active_conf = &g_Options.skins.m_items[is_knife(definition_index) ? WEAPON_KNIFE : definition_index];
apply_config_on_attributable_item(weapon, active_conf, player_info.xuid_low);
}
}
const auto view_model_handle = local->m_hViewModel();
if (!view_model_handle.IsValid())
return;
const auto view_model = static_cast<C_BaseViewModel*>(g_EntityList->GetClientEntityFromHandle(view_model_handle));
if (!view_model)
return;
const auto view_model_weapon_handle = view_model->m_hWeapon();
if (!view_model_weapon_handle.IsValid())
return;
const auto view_model_weapon = static_cast<C_BaseCombatWeapon*>(g_EntityList->GetClientEntityFromHandle(view_model_weapon_handle));
if (!view_model_weapon)
return;
if (k_weapon_info.count(view_model_weapon->m_Item().m_iItemDefinitionIndex()))
{
const auto override_model = k_weapon_info.at(view_model_weapon->m_Item().m_iItemDefinitionIndex()).model;
auto override_model_index = g_MdlInfo->GetModelIndex(override_model);
view_model->m_nModelIndex() = override_model_index;
auto world_model_handle = view_model_weapon->m_hWeaponWorldModel();
if (!world_model_handle.IsValid())
return;
const auto world_model = static_cast<C_BaseWeaponWorldModel*>(g_EntityList->GetClientEntityFromHandle(world_model_handle));
if (!world_model)
return;
world_model->m_nModelIndex() = override_model_index + 1;
}
}
После constexpr auto OverrideView = 18; добавляем constexpr auto FireEvent = 9;
После bool __fastcall hkSvCheatsGetBool(PVOID pConVar, void* edx); добавляем
Код:
bool __stdcall hkFireEvent(IGameEvent* pEvent);
void hkRecvProxy(const CRecvProxyData* pData, void* entity, void* output);
Добавляем #include "features/skins.h"
После vfunc_hook sv_cheats; добавляем vfunc_hook gameevents_hook; recv_prop_hook* sequence_hook;
После sv_cheats.setup(sv_cheats_con); добавляем
Код:
gameevents_hook.setup(g_GameEvents);
gameevents_hook.hook_index(index::FireEvent, hkFireEvent);
sequence_hook = new recv_prop_hook(C_BaseViewModel::m_nSequence(), hkRecvProxy);
Код:
gameevents_hook.unhook_all();
sequence_hook->~recv_prop_hook();
После bool __fastcall hkSvCheatsGetBool(PVOID pConVar, void* edx) {...} добавляем
Код:
bool __stdcall hkFireEvent(IGameEvent* pEvent)
{
static auto oFireEvent = gameevents_hook.get_original<FireEvent>(index::FireEvent);
if (!strcmp(pEvent->GetName(), "player_death") && g_EngineClient->GetPlayerForUserID(pEvent->GetInt("attacker")) == g_EngineClient->GetLocalPlayer()) {
auto& weapon = g_LocalPlayer->m_hActiveWeapon();
if (weapon && weapon->IsWeapon()) {
auto& skin_data = g_Inventory.m_items[weapon->m_Item().m_iItemDefinitionIndex()];
if (skin_data.enabled && skin_data.stat_trak) {
skin_data.stat_trak++;
weapon->m_nFallbackStatTrak() = skin_data.stat_trak;
weapon->GetClientNetworkable()->PostDataUpdate(0);
weapon->GetClientNetworkable()->OnDataChanged(0);
}
}
const auto icon_override = g_Options.skins.get_icon_override(pEvent->GetString("weapon"));
if (icon_override) {
pEvent->SetString("weapon", icon_override);
}
}
return oFireEvent(g_GameEvents, pEvent);
}
//--------------------------------------------------------------------------------
static auto random_sequence(const int low, const int high) -> int
{
return rand() % (high - low + 1) + low;
}
static auto fix_animation(const char* model, const int sequence) -> int
{
enum ESequence
{
SEQUENCE_DEFAULT_DRAW = 0,
SEQUENCE_DEFAULT_IDLE1 = 1,
SEQUENCE_DEFAULT_IDLE2 = 2,
SEQUENCE_DEFAULT_LIGHT_MISS1 = 3,
SEQUENCE_DEFAULT_LIGHT_MISS2 = 4,
SEQUENCE_DEFAULT_HEAVY_MISS1 = 9,
SEQUENCE_DEFAULT_HEAVY_HIT1 = 10,
SEQUENCE_DEFAULT_HEAVY_BACKSTAB = 11,
SEQUENCE_DEFAULT_LOOKAT01 = 12,
SEQUENCE_BUTTERFLY_DRAW = 0,
SEQUENCE_BUTTERFLY_DRAW2 = 1,
SEQUENCE_BUTTERFLY_LOOKAT01 = 13,
SEQUENCE_BUTTERFLY_LOOKAT03 = 15,
SEQUENCE_FALCHION_IDLE1 = 1,
SEQUENCE_FALCHION_HEAVY_MISS1 = 8,
SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP = 9,
SEQUENCE_FALCHION_LOOKAT01 = 12,
SEQUENCE_FALCHION_LOOKAT02 = 13,
SEQUENCE_DAGGERS_IDLE1 = 1,
SEQUENCE_DAGGERS_LIGHT_MISS1 = 2,
SEQUENCE_DAGGERS_LIGHT_MISS5 = 6,
SEQUENCE_DAGGERS_HEAVY_MISS2 = 11,
SEQUENCE_DAGGERS_HEAVY_MISS1 = 12,
SEQUENCE_BOWIE_IDLE1 = 1,
};
if (strstr(model, "models/weapons/v_knife_butterfly.mdl")) {
switch (sequence)
{
case SEQUENCE_DEFAULT_DRAW:
return random_sequence(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2);
case SEQUENCE_DEFAULT_LOOKAT01:
return random_sequence(SEQUENCE_BUTTERFLY_LOOKAT01, SEQUENCE_BUTTERFLY_LOOKAT03);
default:
return sequence + 1;
}
}
else if (strstr(model, "models/weapons/v_knife_falchion_advanced.mdl")) {
switch (sequence)
{
case SEQUENCE_DEFAULT_IDLE2:
return SEQUENCE_FALCHION_IDLE1;
case SEQUENCE_DEFAULT_HEAVY_MISS1:
return random_sequence(SEQUENCE_FALCHION_HEAVY_MISS1, SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP);
case SEQUENCE_DEFAULT_LOOKAT01:
return random_sequence(SEQUENCE_FALCHION_LOOKAT01, SEQUENCE_FALCHION_LOOKAT02);
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
return sequence;
default:
return sequence - 1;
}
}
else if (strstr(model, "models/weapons/v_knife_push.mdl")) {
switch (sequence)
{
case SEQUENCE_DEFAULT_IDLE2:
return SEQUENCE_DAGGERS_IDLE1;
case SEQUENCE_DEFAULT_LIGHT_MISS1:
case SEQUENCE_DEFAULT_LIGHT_MISS2:
return random_sequence(SEQUENCE_DAGGERS_LIGHT_MISS1, SEQUENCE_DAGGERS_LIGHT_MISS5);
case SEQUENCE_DEFAULT_HEAVY_MISS1:
return random_sequence(SEQUENCE_DAGGERS_HEAVY_MISS2, SEQUENCE_DAGGERS_HEAVY_MISS1);
case SEQUENCE_DEFAULT_HEAVY_HIT1:
case SEQUENCE_DEFAULT_HEAVY_BACKSTAB:
case SEQUENCE_DEFAULT_LOOKAT01:
return sequence + 3;
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
return sequence;
default:
return sequence + 2;
}
}
else if (strstr(model, "models/weapons/v_knife_survival_bowie.mdl")) {
switch (sequence)
{
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
return sequence;
case SEQUENCE_DEFAULT_IDLE2:
return SEQUENCE_BOWIE_IDLE1;
default:
return sequence - 1;
}
}
else {
return sequence;
}
}
void hkRecvProxy(const CRecvProxyData* pData, void* entity, void* output)
{
static auto original_fn = sequence_hook->get_original_function();
const auto local = static_cast<C_BasePlayer*>(g_EntityList->GetClientEntity(g_EngineClient->GetLocalPlayer()));
if (local && local->IsAlive())
{
const auto proxy_data = const_cast<CRecvProxyData*>(pData);
const auto view_model = static_cast<C_BaseViewModel*>(entity);
if (view_model && view_model->m_hOwner() && view_model->m_hOwner().IsValid())
{
const auto owner = static_cast<C_BasePlayer*>(g_EntityList->GetClientEntityFromHandle(view_model->m_hOwner()));
if (owner == g_EntityList->GetClientEntity(g_EngineClient->GetLocalPlayer()))
{
const auto view_model_weapon_handle = view_model->m_hWeapon();
if (view_model_weapon_handle.IsValid())
{
const auto view_model_weapon = static_cast<C_BaseAttributableItem*>(g_EntityList->GetClientEntityFromHandle(view_model_weapon_handle));
if (view_model_weapon)
{
if (k_weapon_info.count(view_model_weapon->m_Item().m_iItemDefinitionIndex()))
{
auto original_sequence = proxy_data->m_Value.m_Int;
const auto override_model = k_weapon_info.at(view_model_weapon->m_Item().m_iItemDefinitionIndex()).model;
proxy_data->m_Value.m_Int = fix_animation(override_model, proxy_data->m_Value.m_Int);
}
}
}
}
}
}
original_fn(pData, entity, output);
}
Последнее редактирование: