Add files via upload

This commit is contained in:
0TheSpy
2021-06-16 18:43:45 +03:00
committed by GitHub
parent 9cb9fd6180
commit 0c3506cec2
68 changed files with 58942 additions and 0 deletions

1295
SpyCustom/ConVars.cpp Normal file

File diff suppressed because it is too large Load Diff

107
SpyCustom/Config.hpp Normal file
View File

@ -0,0 +1,107 @@
#ifndef CONFIG
#define CONFIG
#pragma once
#include "Options.hpp"
#include "Singleton.hpp"
#include <fstream>
#include <sstream>
std::vector<char> HexToBytes(const std::string& hex) {
std::vector<char> res;
for (auto i = 0u; i < hex.length(); i += 2) {
std::string byteString = hex.substr(i, 2);
char byte = (char)strtol(byteString.c_str(), NULL, 16);
res.push_back(byte);
}
return res;
}
std::string BytesToString(unsigned char* data, int len) {
constexpr char hexmap[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
std::string res(len * 2, ' ');
for (int i = 0; i < len; ++i) {
res[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
res[2 * i + 1] = hexmap[data[i] & 0x0F];
}
return res;
}
std::vector<std::string> Split(const std::string& str, const char* delim) {
std::vector<std::string> res;
char* pTempStr = _strdup(str.c_str());
char* context = NULL;
char* pWord = strtok_s(pTempStr, delim, &context);
while (pWord != NULL) {
res.push_back(pWord);
pWord = strtok_s(NULL, delim, &context);
}
free(pTempStr);
return res;
}
class Config : public Singleton<Config> {
public:
void Save() {
std::ofstream fout("seaside210616.cfg", std::ios::binary);
const auto sz = sizeof(Options);
const auto var_sz = sizeof(Var<bool>);
const auto cnt = sz / var_sz;
for (auto i = 0; i < cnt; i++) {
const auto el = &(*(Var<int>*)(&g_Options)) + i;
auto name = el->name;
auto val = el->value;
auto sizeof_val = el->size;
fout << name << "\t" << BytesToString((unsigned char*)*(int*)&val, sizeof_val) << std::endl;
}
fout.close();
}
bool file_exists(std::string filename) {
std::ifstream ifile(filename);
return (bool)ifile;
}
void Load() {
opt.loading = 1;
if (file_exists("seaside210616.cfg") ) {
std::ifstream fin("seaside210616.cfg", std::ios::binary);
std::stringstream ss;
ss << fin.rdbuf();
auto lines = Split(ss.str(), "\n");
for (auto line : lines) {
auto data = Split(line, "\t");
const auto sz = sizeof(Options);
const auto var_sz = sizeof(Var<bool>);
const auto cnt = sz / var_sz;
for (auto i = 0; i < cnt; i++) {
const auto& el = &(*(Var<bool>*)(&g_Options)) + i;
if (data[0] == el->name) {
auto bytes = HexToBytes(data[1]);
memcpy(*(void**)&el->value, bytes.data(), el->size);
}
}
}
fin.close();
OnLoadCfg();
}
else iff.g_pGameUI->CreateCommandMsgBox("Seaside Error", "Unable to find configuration file!", true, false, "", "", "", "", "");
}
};
#endif

407
SpyCustom/EventListener.hpp Normal file
View File

@ -0,0 +1,407 @@
#ifndef EVENTLISTEN
#define EVENTLISTEN
#pragma once
#pragma comment( lib, "Winmm.lib" )
#include "Interfaces.hpp"
#include "sdk/c_baseentity.h"
#include "Options.hpp"
struct bullet
{
bullet(int userID, Vector pos, int dmg, bool hs, float curtime)
{
this->userid = userid;
this->hs = hs;
this->curtime = curtime;
this->time = curtime + 0.0f;
this->pos = pos;
this->dmg = dmg;
}
int userid;
bool hs;
float time;
float curtime;
Vector pos;
int dmg;
};
std::vector<bullet> bulletdata;
#define PI 3.14159265
class EventListener : public IGameEventListener2
{
public:
EventListener()
{
if (!iff.g_pGameEvents->AddListener(this, "bullet_impact", false))
{
#ifdef DEBUG
std::cout << "Can't add listener bullet_impact\n";
#endif
}
if (!iff.g_pGameEvents->AddListener(this, "player_hurt", false))
{
#ifdef DEBUG
std::cout << "Can't add listener player_hurt\n";
#endif
}
if (!iff.g_pGameEvents->AddListener(this, "vote_cast", false))
{
#ifdef DEBUG
std::cout << "Can't add listener vote_cast\n";
#endif
}
if (!iff.g_pGameEvents->AddListener(this, "game_newmap", false))
{
#ifdef DEBUG
std::cout << "Can't add listener game_newmap\n";
#endif
}
#ifdef DEBUG
std::cout << "Event Listener created\n";
#endif
}
~EventListener()
{
iff.g_pGameEvents->RemoveListener(this);
}
int GetEventDebugID() override
{
return EVENT_DEBUG_ID_INIT;
}
virtual void FireGameEvent(IGameEvent* event)
{
if (*g_Options.hitmarker || *g_Options.hitsound) {
if (!strcmp(event->GetName(), "player_hurt"))
{
short hitgroup = event->GetInt("hitgroup");
short attacker = event->GetInt("attacker");
short userid = event->GetInt("userid");
short dmg_health = event->GetInt("dmg_health");
if (iff.g_pEngineClient->GetPlayerForUserID(attacker) == iff.g_pEngineClient->GetLocalPlayer()) {
int pid = iff.g_pEngineClient->GetPlayerForUserID(userid);
C_BasePlayer* pEntity = (C_BasePlayer*)iff.g_pEntityList->GetClientEntity(pid);
Vector pos = pEntity->GetBonePosition(8);
if (hitgroup == 1)
{
bool badInput = false;
int i_dec = 0;
if (*g_Options.hitsound) {
try
{
i_dec = std::stoi(g_Options.hspath.value->mystring);
}
catch (...)
{
badInput = true;
PlaySoundA(g_Options.hspath.value->mystring, NULL, SND_ASYNC);
}
if (!badInput && FindResource(opt.hModuleGlobal, MAKEINTRESOURCE(i_dec), "WAVE")) {
PlaySoundA((char*)i_dec, opt.hModuleGlobal, SND_RESOURCE | SND_ASYNC);
}
}
if (*g_Options.hitmarker)
bulletdata.push_back(bullet(userid, pos, dmg_health, 1, iff.g_pGlobals->curtime));
}
else
{
bool badInput = false;
int i_dec = 0;
if (*g_Options.hitsound) {
try
{
i_dec = std::stoi(g_Options.obpath.value->mystring);
}
catch (...)
{
badInput = true;
PlaySoundA(g_Options.obpath.value->mystring, NULL, SND_ASYNC);
}
if (!badInput && FindResource(opt.hModuleGlobal, MAKEINTRESOURCE(i_dec), "WAVE")) {
PlaySoundA((char*)i_dec, opt.hModuleGlobal, SND_RESOURCE | SND_ASYNC);
}
}
if (*g_Options.hitmarker)
bulletdata.push_back(bullet(userid, pos, dmg_health, 0, iff.g_pGlobals->curtime));
}
}
}
}
if (!strcmp(event->GetName(), "bullet_impact"))
{
short userid = event->GetInt("userid");
int localplayer = iff.g_pEngineClient->GetLocalPlayer();
if (iff.g_pEngineClient->GetPlayerForUserID(userid) == localplayer) {
float x = event->GetFloat("x");
float y = event->GetFloat("y");
float z = event->GetFloat("z");
C_BasePlayer* pEntity = (C_BasePlayer*)iff.g_pEntityList->GetClientEntity(localplayer);
Vector src = pEntity->GetOrigin() + pEntity->GetViewOffset();
Vector dst = { x,y,z };
Vector ang = pEntity->GetAngles();
ang.x -= 90.0f; ang.y -= 90.0f;
static float margin = 3.0f;
static float coeff = 1.5f;
src.x += cos(ang.x * PI / 180) * margin * sin(ang.y * PI / 180) + cos(ang.y * PI / 180) * margin * coeff;
src.y += -cos(ang.x * PI / 180) * margin * cos(ang.y * PI / 180) + sin(ang.y * PI / 180) * margin * coeff;
src.z += sin(ang.x * PI / 180) * margin;
if (*g_Options.beamtrace) {
BeamInfo_t beamInfo;
beamInfo.m_nType = *g_Options.beamtype;
beamInfo.m_pszModelName = g_Options.beampath.value->mystring;
beamInfo.m_nModelIndex = -1;
beamInfo.m_flHaloScale = 0.0f;
beamInfo.m_pStartEnt = pEntity;
beamInfo.m_pEndEnt = NULL;
beamInfo.m_vecEnd = dst;
beamInfo.m_vecStart = src;
beamInfo.m_flLife = *g_Options.beamlife;
beamInfo.m_flFadeLength = *g_Options.beamfadelength;
beamInfo.m_flAmplitude = *g_Options.beamamplitude;
beamInfo.m_nSegments = *g_Options.beamsegments;
beamInfo.m_bRenderable = true;
beamInfo.m_flSpeed = *g_Options.beamspeed;
beamInfo.m_nStartFrame = *g_Options.beamstartframe;
beamInfo.m_flFrameRate = *g_Options.beamframerate;
beamInfo.m_flWidth = *g_Options.beamwidth;
beamInfo.m_flEndWidth = *g_Options.beamwidth;
beamInfo.m_flBlue = g_Options.beamcolor.value->b * 255.0f;
beamInfo.m_flGreen = g_Options.beamcolor.value->g * 255.0f;
beamInfo.m_flRed = g_Options.beamcolor.value->r * 255.0f;
beamInfo.m_flBrightness = g_Options.beamcolor.value->a * 255.0f;
beamInfo.m_nFlags = *g_Options.beamflags;
Beam_t* myBeam = iff.g_pViewRenderBeams->CreateBeamPoints(beamInfo);
if (myBeam) iff.g_pViewRenderBeams->DrawBeam(myBeam);
else
{
}
}
if (*g_Options.attacheffects) {
switch (g_Options.effects.value->type) {
case 0:
{
switch (g_Options.effects.value->selectedc)
{
case 0:
{
iff.g_pEffects->Smoke(dst, -1, g_Options.effects.value->fx_fsize, g_Options.effects.value->fx_fspeed);
break;
}
case 2:
{
iff.g_pEffects->Dust(dst, Vector(0.0f, 0.0f, 1.0f), g_Options.effects.value->fx_fsize, g_Options.effects.value->fx_fspeed);
break;
}
case 1:
{
iff.g_pEffects->Sparks(dst, g_Options.effects.value->fx_magnitude, g_Options.effects.value->fx_traillength);
break;
}
case 3:
{
iff.g_pEffects->MuzzleFlash(dst, CalcAngle(dst, src), g_Options.effects.value->fx_fsize, g_Options.effects.value->fx_itype);
break;
}
case 4:
{
iff.g_pEffects->MetalSparks(dst, Vector( 0.0f, 0.0f, 0.0f ) );
break;
}
case 6:
{
iff.g_pEffects->Ricochet(dst, Vector(0.0f, 0.0f, 1.0f));
break;
}
case 5:
{
iff.g_pEffects->EnergySplash(dst, src, g_Options.effects.value->fx_bexplosive);
break;
}
}
break;
}
case 1:
{
CEffectData asscock;
asscock.m_fFlags = g_Options.effects.value->fflags;
asscock.m_vOrigin = dst;
asscock.m_vStart = src;
asscock.m_vNormal.Init(0.0f, 0.0f, 1.0f);
asscock.m_flScale = g_Options.effects.value->fscale;
asscock.m_nColor = g_Options.effects.value->icolors;
asscock.m_flMagnitude = g_Options.effects.value->fmagtinude;
asscock.m_flRadius = g_Options.effects.value->fradius;
iff.DispatchEffect(opt.DispatchEffect.at(g_Options.effects.value->selectedc).c_str(), asscock);
break;
}
case 2:
{
switch (g_Options.effects.value->selectedc)
{
case 0:
{
CTeslaInfo teslaInfo;
teslaInfo.m_flBeamWidth = g_Options.effects.value->fbeamwidth;
teslaInfo.m_flRadius = g_Options.effects.value->teslaradius;
teslaInfo.m_nEntIndex = -1;
teslaInfo.m_vColor.Init(g_Options.effects.value->teslacolor[0], g_Options.effects.value->teslacolor[1], g_Options.effects.value->teslacolor[2]);
teslaInfo.m_vPos = dst;
teslaInfo.m_flTimeVisible = g_Options.effects.value->fltimevisible;
teslaInfo.m_nBeams = g_Options.effects.value->ibeams;
teslaInfo.m_pszSpriteName = g_Options.effects.value->szSpriteName;
iff.FX_Tesla(teslaInfo);
break;
}
case 1:
{
dlight_t* pDlight = iff.g_pEfx->CL_AllocDlight(1);
pDlight->origin = dst;
pDlight->radius = g_Options.effects.value->frad;
pDlight->color.r = g_Options.effects.value->dlightcolor[0]*255.0f;
pDlight->color.g = g_Options.effects.value->dlightcolor[1] * 255.0f;
pDlight->color.b = g_Options.effects.value->dlightcolor[2] * 255.0f;
pDlight->color.exponent = 5;
pDlight->die = iff.g_pGlobals->curtime + g_Options.effects.value->fdie;
pDlight->decay = 0;
pDlight->key = g_Options.effects.value->key;
pDlight->style = g_Options.effects.value->style;
break;
}
}
break;
}
}
}
}
}
if (*g_Options.votereveal) {
if (!strcmp(event->GetName(), "vote_cast"))
{
int vote = event->GetInt("vote_option");
int id = event->GetInt("entityid");
if (iff.g_pChatElement)
{
player_info_t pinfo;
iff.g_pEngineClient->GetPlayerInfo(id, &pinfo);
if (pinfo.name) {
#ifdef DEBUG
printf("%s voted %d\n", pinfo.name, vote);
#endif
iff.g_pChatElement->ChatPrintf2(0, 0, std::string("").
append(" \x06").
append(pinfo.name).
append(" \x01").
append("voted").
append((vote == 0 ? std::string(" \x04").append("YES") : std::string(" \x02").append("NO"))).c_str());
}
}
}
}
if (!strcmp(event->GetName(), "game_newmap"))
{
#ifdef DEBUG
printf("game_newmap\n");
#endif
OnLevelInit();
}
}
};
#endif

56
SpyCustom/GetVfunc.hpp Normal file
View File

@ -0,0 +1,56 @@
#ifndef GETVFUNC
#define GETVFUNC
#pragma once
inline void**& getvtable(void* inst, size_t offset = 0)
{
return *reinterpret_cast<void***>((size_t)inst + offset);
}
inline const void** getvtable(const void* inst, size_t offset = 0)
{
return *reinterpret_cast<const void***>((size_t)inst + offset);
}
template<typename Fn>
inline Fn getvfunc(const void* inst, size_t index, size_t offset = 0)
{
return reinterpret_cast<Fn>(getvtable(inst, offset)[index]);
}
template <typename Fn = void*>
Fn get_vfunc(void* class_base, const size_t index)
{
return (*reinterpret_cast<Fn**>(class_base))[index];
}
#include <string>
#include <memory>
inline char* MakeControlChars(char str[1024]) {
char name[1024];
strcpy(name, str);
for (int i = 0; i < 1024; i++)
{
if (name[i] == 0x5C && name[i + 1] == 0x78)
{
char controlchar[3]; controlchar[0] = name[i + 2]; controlchar[1] = name[i + 3]; controlchar[2] = 0x0;
short x = std::stoul(controlchar, nullptr, 16);
name[i] = x;
for (int j = i + 4; j < 1024; j++)
{
name[j - 3] = name[j];
if (name[j] == 0x0)
break;
}
}
if (name[i] == 0x0)
break;
}
return name;
}
#endif

201
SpyCustom/Hooks.hpp Normal file
View File

@ -0,0 +1,201 @@
#pragma once
VMTHook* SoundHook = nullptr;
void __fastcall hkEmitSound1(void* _this, int edx, IRecipientFilter& filter, int iEntIndex, int iChannel, char* pSoundEntry, unsigned int nSoundEntryHash, const char* pSample, float flVolume, int nSeed, float flAttenuation, int iFlags, int iPitch, const Vector* pOrigin, const Vector* pDirection, void* pUtlVecOrigins, bool bUpdatePositions, float soundtime, int speakerentity, int unk) {
static auto ofunc = SoundHook->GetOriginal<decltype(&hkEmitSound1)>(5);
if (*g_Options.soundhook_count) {
soundlist vv = GetCfgWavpathBySoundHash(nSoundEntryHash);
if (vv.cfgindex != -1)
{
Sounds ff = g_Options.models.value->arr[vv.cfgindex].sounds[vv.sndindex];
return ofunc(iff.g_pEngineSound, edx, filter, iEntIndex, iChannel, pSoundEntry, -1, ff.wavpath, ff.volume, nSeed, flAttenuation, 0, ff.pitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, unk);
}
}
return ofunc(iff.g_pEngineSound, edx, filter, iEntIndex, iChannel, pSoundEntry, nSoundEntryHash, pSample, flVolume, nSeed, flAttenuation, iFlags, iPitch, pOrigin, pDirection, pUtlVecOrigins, bUpdatePositions, soundtime, speakerentity, unk);
}
VMTHook* DMEHook = nullptr;
void replacemat(int d)
{
IMaterial* material;
if (g_Options.materials.value->arr[d].customtextureselected != -1)
if (g_Options.customtextures.value->arr[g_Options.materials.value->arr[d].customtextureselected].texturelink != nullptr)
material = (IMaterial*)g_Options.customtextures.value->arr[g_Options.materials.value->arr[d].customtextureselected].texturelink;
else material = iff.g_pMaterialSystem->FindMaterial("__err", TEXTURE_GROUP_MODEL);
else
material = iff.g_pMaterialSystem->FindMaterial(g_Options.materials.value->arr[d].texture, TEXTURE_GROUP_MODEL);
material->SetMaterialVarFlag(MATERIAL_VAR_WIREFRAME, g_Options.materials.value->arr[d].wireframe);
material->SetMaterialVarFlag(MATERIAL_VAR_FLAT, g_Options.materials.value->arr[d].flat);
material->SetMaterialVarFlag(MATERIAL_VAR_NO_DRAW, g_Options.materials.value->arr[d].nodraw);
material->ColorModulate(g_Options.materials.value->arr[d].coloralpha.x, g_Options.materials.value->arr[d].coloralpha.y, g_Options.materials.value->arr[d].coloralpha.z);
material->AlphaModulate(g_Options.materials.value->arr[d].coloralpha.w);
iff.g_pMdlRender->ForcedMaterialOverride(material);
}
void __stdcall DrawModelExecute(IMatRenderContext* ctx, const DrawModelState_t& state, const ModelRenderInfo_t& pInfo, matrix3x4_t* pCustomBoneToWorld)
{
static auto ofunc = DMEHook->GetOriginal<void(__thiscall*)(IVModelRender*, IMatRenderContext*, const DrawModelState_t&, const ModelRenderInfo_t&, matrix3x4_t*)>(21);
if (iff.g_pMdlRender->IsForcedMaterialOverride() || opt.loading || !*g_Options.dmeloop_count)
return ofunc(iff.g_pMdlRender, ctx, state, pInfo, pCustomBoneToWorld);
const char* szName = iff.g_pMdlInfo->GetModelName(pInfo.pModel);
if (g_Options.materials.value->arr[3].active)
if (strstr(szName, "player/legacy/t") != nullptr)
replacemat(3);
if (g_Options.materials.value->arr[4].active)
if (strstr(szName, "player/legacy/ct") != nullptr)
replacemat(4);
if (strstr(szName, "weapons/v_")) {
int namehash = fnv2::hashRuntime(szName);
bool is_arm = strstr(szName, "arms") != nullptr;
bool is_sleeve = strstr(szName, "sleeve") != nullptr;
bool is_wep = !is_arm && !is_sleeve;
for (int d = 0; d < g_Options.materials.value->itemcount; d++)
{
if (d == 1 && !is_arm) continue;
if (d == 2 && !is_sleeve) continue;
if (d == 0 && !is_wep) continue;
if (d == 3 || d == 4) continue;
if ((d > 2 && d != 5) && namehash != g_Options.materials.value->arr[d].model_hash) continue;
if (d == 5 && !strstr(szName, "knife")) continue;
if (g_Options.materials.value->arr[d].active) {
replacemat(d);
}
}
}
ofunc(iff.g_pMdlRender, ctx, state, pInfo, pCustomBoneToWorld);
iff.g_pMdlRender->ForcedMaterialOverride(nullptr);
}
VMTHook* CacheHook = nullptr;
MDLHandle_t __fastcall hkFindMDL(void* ecx, void* edx, char* FilePath)
{
static auto oFindMDL = CacheHook->GetOriginal<MDLHandle_t(__thiscall*)(void*, char*)>(10);
if (g_Options.models.value->arr[2].active && strstr(FilePath, "models/weapons/v_models/arms") && !strstr(FilePath, "gloves"))
{
#ifdef DEBUG
printf("Replacing %s with %s\n", FilePath, g_Options.models.value->arr[2].vmodel_repl);
#endif
sprintf(FilePath, g_Options.models.value->arr[2].vmodel_repl);
}
if (g_Options.models.value->arr[3].active && strstr(FilePath, "models/weapons/v_knife"))
{
#ifdef DEBUG
printf("Replacing %s with %s\n", FilePath, g_Options.models.value->arr[3].vmodel_repl);
#endif
sprintf(FilePath, g_Options.models.value->arr[3].vmodel_repl);
}
for (int i = 4; i < g_Options.models.value->itemcount; i++)
{
if (g_Options.models.value->arr[i].active && g_Options.models.value->arr[i].findMDLmethode && strstr(FilePath, g_Options.models.value->arr[i].vmodel_orig))
{
#ifdef DEBUG
printf("Replacing %s with %s\n", FilePath, g_Options.models.value->arr[i].vmodel_repl);
#endif
sprintf(FilePath, g_Options.models.value->arr[i].vmodel_repl);
}
}
return oFindMDL(ecx, FilePath);
}
VMTHook* ClientModeHook = nullptr;
static void __stdcall hkdoPostScreenEffects(void* param) noexcept
{
static auto ofunc = ClientModeHook->GetOriginal<void(__thiscall*)(IClientMode*, void*)>(44);
if (*g_Options.entityloop_count) {
if (iff.g_pEngineClient->IsInGame())
{
int localplayer_index = iff.g_pEngineClient->GetLocalPlayer();
C_BasePlayer* localplayer = static_cast<C_BasePlayer*>(iff.g_pEntityList->GetClientEntity(localplayer_index));
for (int i = iff.g_pEngineClient->GetMaxClients() + 1; i <= iff.g_pEntityList->GetHighestEntityIndex(); ++i)
{
C_BasePlayer* pEntity = (C_BasePlayer*)iff.g_pEntityList->GetClientEntity(i);
if (!pEntity)
continue;
bool bDormant = pEntity->IsDormant();
if (bDormant)
continue;
int cfgindex = GetCfgIndexByClassId(fnv2::hashRuntime(pEntity->GetClientClass()->GetName()));
if (cfgindex != -1)
{
if (g_Options.models.value->arr[cfgindex].active_scale)
pEntity->GetModelScale() = g_Options.models.value->arr[cfgindex].scale;
if (g_Options.models.value->arr[cfgindex].active_w)
{
char* model = g_Options.models.value->arr[cfgindex].wmodel_repl;
pEntity->SetModelIndex(iff.g_pMdlInfo->GetModelIndex(model));
if (const auto modelprecache = iff.g_pNetworkStringTableContainer->FindTable("modelprecache"))
modelprecache->AddString(false, model);
}
}
}
}
}
ofunc(iff.g_ClientMode, param);
}
VMTHook* VGUISurfHook = nullptr;
void __fastcall hkLockCursor(void* _this)
{
static auto ofunc = VGUISurfHook->GetOriginal<decltype(&hkLockCursor)>(67);
if (opt.show) {
iff.g_pVGuiSurface->UnlockCursor();
iff.g_pInputSystem->ResetInputState();
return;
}
ofunc(iff.g_pVGuiSurface);
}
VMTHook* FileSystemHook = nullptr;
int __stdcall hkGetUnverifiedFileHashes(void* _this, void* someclass, int nMaxFiles)
{
return 0;
}

180
SpyCustom/Interfaces.cpp Normal file
View File

@ -0,0 +1,180 @@
#include "Interfaces.hpp"
#include "PatternScan.hpp"
IF iff;
void* IF::GetInterface(const char* dllname, const char* interfacename)
{
tCreateInterface CreateInterface = (tCreateInterface)GetProcAddress(GetModuleHandleA(dllname), "CreateInterface");
int returnCode = 0;
void* ointerface = CreateInterface(interfacename, &returnCode);
#ifdef DEBUG
printf("%s = %x\n", interfacename, ointerface);
#endif
return ointerface;
}
PVOID FindHudElement(const char* name)
{
void* pointer1 = (void*)(FindPatternV2("client.dll", "B9 ? ? ? ? E8 ? ? ? ? 8B 5D 08") + 1);
static void* pThis = *reinterpret_cast<DWORD**>(pointer1);
void* pointer2 = (void*)(FindPatternV2("client.dll", "55 8B EC 53 8B 5D 08 56 57 8B F9 33 F6 39 77 28"));
static auto find_hud_element
= reinterpret_cast<DWORD(__thiscall*)(void*, const char*)>(
pointer2
);
return (void*)find_hud_element(pThis, name);
}
#define VTBL(classptr) (*(DWORD*)classptr)
#define PVFN_(classptr, offset) (VTBL(classptr) + offset)
#define VFN_(classptr, offset) *(DWORD*)PVFN_(classptr, offset)
#define VFN(classptr, offset) VFN_(classptr, (offset * sizeof(void*)))
void IF::Init()
{
g_pEntityList = (IClientEntityList*)GetInterface("client.dll", "VClientEntityList003");
g_pGameUI = (CGameUI*)GetInterface("client.dll", "GameUI011");
g_pVGuiPanel = (vgui::IPanel*)GetInterface("vgui2.dll", "VGUI_Panel009");
g_pGameEvents = (CGameEventManager*)GetInterface("engine.dll", "GAMEEVENTSMANAGER002");
g_pEngineClient = (IVEngineClient*)GetInterface("engine.dll", "VEngineClient014");
g_pEnginetrace = (IEngineTrace*)GetInterface("engine.dll", "EngineTraceClient004");
g_pEnginevgui = (IEngineVGui*)GetInterface("engine.dll", "VEngineVGui001");
g_pVGui = (vgui::IVGui*)GetInterface("vgui2.dll", "VGUI_ivgui008");
g_pClient = (IBaseClientDLL*)GetInterface("client.dll", "VClient018");
g_pMdlInfo = (IVModelInfoClient*)GetInterface("engine.dll", "VModelInfoClient004");
g_pMdlRender = (IVModelRender*)GetInterface("engine.dll", "VEngineModel016");
g_pMaterialSystem = (IMaterialSystem*)GetInterface("materialsystem.dll", "VMaterialSystem080");
g_pCVar = (ICvar*)GetInterface("vstdlib.dll", "VEngineCvar007");
g_pVGuiSystem = (vgui::ISystem*)GetInterface("vgui2.dll", "VGUI_System010");
g_pVGuiSchemeManager = (vgui::ISchemeManager*)GetInterface("vgui2.dll", "VGUI_Scheme010");
g_pVGuiInput = (vgui::IInput*)GetInterface("vgui2.dll", "VGUI_Input005");
g_pFullFileSystem = (IFileSystem*)GetInterface("filesystem_stdio.dll", "VFileSystem017");
g_pGameConsole = (IGameConsole*)GetInterface("client.dll", "GameConsole004");
g_pEfx = (IVEfx*)GetInterface("engine.dll", "VEngineEffects001");
g_pPhysProps = (IPhysicsSurfaceProps*)GetInterface("vphysics.dll", "VPhysicsSurfaceProps001");
g_pRenderView = (IVRenderView*)GetInterface("engine.dll", "VEngineRenderView014");
g_pDebugOverlay = (IVDebugOverlay*)GetInterface("engine.dll", "VDebugOverlay004");
g_pEffects = (IEffects*)GetInterface("client.dll", "IEffects001");
g_pStudioRender = (IStudioRender*)GetInterface("studiorender.dll", "VStudioRender026");
typedef PVOID(__cdecl* oKeyValuesSystem)();
oKeyValuesSystem pkeyValuesSystem = (oKeyValuesSystem)GetProcAddress(GetModuleHandleA("vstdlib.dll"), "KeyValuesSystem");
keyValuesSystem = (IKeyValuesSystem*)pkeyValuesSystem();
#ifdef DEBUG
printf("KeyValuesSystem = %x\n", keyValuesSystem);
#endif
myConMsg = (CONMSGPROC)GetProcAddress(GetModuleHandleA("tier0.dll"), "?ConMsg@@YAXPBDZZ");
myConColorMsg = (CONCOLORMSGPROC)GetProcAddress(GetModuleHandleA("tier0.dll"), "?ConColorMsg@@YAXABVColor@@PBDZZ");
g_pGlobals = **(CGlobalVarsBase***)(FindPatternV2("client.dll", "A1 ? ? ? ? 5E 8B 40 10") + 1);
g_pInput = *(CInput**)(FindPatternV2("client.dll", "B9 ? ? ? ? F3 0F 11 04 24 FF 50 10") + 1);
g_pViewRenderBeams = *(IViewRenderBeams**)(FindPatternV2("client.dll", "B9 ?? ?? ?? ?? A1 ?? ?? ?? ?? FF 10 A1 ?? ?? ?? ?? B9") + 0x1);
#ifdef DEBUG
printf("g_pGlobals = %x\n", g_pGlobals);
printf("g_pInput = %x\n", g_pInput);
printf("g_pViewRenderBeams = %x\n", g_pViewRenderBeams);
#endif
FX_Tesla = (FX_TeslaFn)FindPatternV2("client.dll", "55 8B EC 81 EC ? ? ? ? 56 57 8B F9 8B 47 18");
#ifdef DEBUG
printf("FX_TeslaFn %x\n", FX_Tesla);
#endif
BloodSprayFn = (FX_BloodSprayFn)FindPatternV2("client.dll", "55 8B EC 8B 4D 08 F3 0F 10 51 ? 8D");
#ifdef DEBUG
printf("FX_BloodSprayFn %x\n", BloodSprayFn);
#endif
DispatchEffect = (FXDispatchEffect)FindPatternV2("client.dll", "55 8B EC 83 E4 F8 83 EC 20 56 57 8B F9 C7 44 24");
#ifdef DEBUG
printf("DispatchEffect %x\n", DispatchEffect);
#endif
g_pChatElement = (CHudChat*)FindHudElement("CHudChat");
#ifdef DEBUG
printf("Chat element %x\n", g_pChatElement);
#endif
LoadFromFile = (void*)FindPatternV2("client.dll", "55 8B EC 83 EC 0C 53 8B 5D 08 56 8B F1 3B");
#ifdef DEBUG
printf("LoadFromFile %x\n", LoadFromFile);
#endif
g_pD3DDevice9 = **(IDirect3DDevice9***)(FindPatternV2("shaderapidx9.dll", "A1 ? ? ? ? 50 8B 08 FF 51 0C") + 1);
#ifdef DEBUG
printf("g_pD3DDevice9 %x\n", g_pD3DDevice9);
#endif
g_pMemAlloc = *(IMemAlloc**)(GetProcAddress(GetModuleHandle("tier0.dll"), "g_pMemAlloc"));
#ifdef DEBUG
printf("g_pMemAlloc %x\n", g_pMemAlloc);
#endif
g_pClientState = **reinterpret_cast<CClientState***>(getvfunc<uintptr_t>(g_pEngineClient, 12) + 0x10);
#ifdef DEBUG
printf("g_pClientState %x\n", g_pClientState);
#endif
CHudElement* g_pHudElement = (CHudElement*)FindHudElement("CCSGO_HudDeathNotice");
#ifdef DEBUG
printf("Hud element %x\n", g_pHudElement);
#endif
auto SteamClient = ((ISteamClient * (__cdecl*)(void))GetProcAddress(GetModuleHandleA("steam_api.dll"), "SteamClient"))();
g_SteamGameCoordinator = (ISteamGameCoordinator*)SteamClient->GetISteamGenericInterface((void*)1, (void*)1, "SteamGameCoordinator001");
g_SteamUser = SteamClient->GetISteamUser((void*)1, (void*)1, "SteamUser019");
#ifdef DEBUG
printf("SteamClient %X\n", SteamClient);
printf("g_SteamGameCoordinator %X\n", g_SteamGameCoordinator);
printf("g_SteamUser %X\n", g_SteamUser);
#endif
g_pClientLeafSystem = (IClientLeafSystem*)GetInterface("client.dll", "ClientLeafSystem002");
#ifdef DEBUG
printf("g_pClientLeafSystem %x\n", g_pClientLeafSystem);
#endif
g_pNetworkStringTableContainer = (INetworkStringTableContainer*)GetInterface("engine.dll", "VEngineClientStringTable001");
#ifdef DEBUG
printf("g_pNetworkStringTableContainer %x\n", g_pNetworkStringTableContainer);
#endif
getPlayerViewmodelArmConfigForPlayerModel = relativeToAbsolute<decltype(getPlayerViewmodelArmConfigForPlayerModel)>(FindPatternV2("client.dll", "E8 ? ? ? ? 89 87 ? ? ? ? 6A") + 1);
g_pMdlCache = (IMDLCache*)GetInterface("datacache.dll", "MDLCache004");
g_pEngineSound = (IEngineSound*)GetInterface("engine.dll", "IEngineSoundClient003");
g_pClientShadowMgr = *(IClientShadowMgr**)(FindPatternV2("client.dll", "A1 ? ? ? ? FF 90 ? ? ? ? 6A 00 6A 00") + 1);
#ifdef DEBUG
printf("g_pClientShadowMgr %x\n", g_pClientShadowMgr);
#endif
g_ViewRender = *(CCSViewRender**)(FindPatternV2("client.dll", "A1 ? ? ? ? B9 ? ? ? ? C7 05 ? ? ? ? ? ? ? ? FF 10") + 1);
#ifdef DEBUG
printf("g_ViewRender %x\n", g_ViewRender);
#endif
g_ClientMode = **(IClientMode***)((*(DWORD**)g_pClient)[10] + 0x5);
#ifdef DEBUG
printf("g_ClientMode %x\n", g_ClientMode);
#endif
g_pInputSystem = (IInputSystem*)GetInterface("inputsystem.dll", "InputSystemVersion001");
g_pVGuiSurface = (vgui::ISurface*)GetInterface("vguimatsurface.dll", "VGUI_Surface031");
prime = (uint8_t*)FindPatternV2("client.dll", "A1 ? ? ? ? 85 C0 75 07 83 F8 05 0F 94 C0 C3");
#ifdef DEBUG
printf("Prime found at %x\n", prime);
#endif
}
auto is_code_ptr(void* ptr) -> bool
{
constexpr const DWORD protect_flags = PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
MEMORY_BASIC_INFORMATION out;
VirtualQuery(ptr, &out, sizeof out);
return out.Type
&& !(out.Protect & (PAGE_GUARD | PAGE_NOACCESS))
&& out.Protect & protect_flags;
}

326
SpyCustom/Interfaces.hpp Normal file
View File

@ -0,0 +1,326 @@
#ifndef INTERFACES
#define INTERFACES
#pragma once
#define DEBUG
#define CLIENT_DLL
#include "GetVfunc.hpp"
#include <iostream>
#include <windows.h>
#include "sdk/icliententitylist.h"
#include "sdk/CGameUI.h"
#include "sdk/GameEventManager.h"
#include "sdk/cdll_int.h"
#include "sdk/ISurface.h"
#include "sdk/IEngineVgui.h"
#include "sdk/ivmodelinfo.h"
#include "sdk/idatacache.h"
#include "sdk/ILocalize.h"
#include "sdk/IGameUI.h"
#include "sdk/dt_recv.h"
#include "sdk/client_class.h"
#include "sdk/enginetrace.h"
#include "sdk/gameconsole.h"
#include "sdk/ivrenderview.h"
#include "sdk/ivdebugoverlay.h"
#include "sdk/vphysics_interface.h"
#include "sdk/iefx.h"
#include "sdk/c_input.h"
#include "sdk/IEffects.h"
#include "sdk/iviewrender_beams.h"
#include "sdk/sdk_hud_chat.h"
#include "sdk/fx.h"
#include "sdk/globalvars_base.h"
#include "sdk/IInput.h"
#include "sdk/icliententity.h"
#include "sdk/iclient.h"
#include "sdk/cdll_int.h"
#include "sdk/baseclientstate.h"
#include "imgui/imgui_impl_dx9.h"
#include "sdk/flashlighteffect.h"
#include "sdk/inetchannel.h"
#include "sdk/steam.h"
#include "sdk/animationlayer.h"
#include "sdk/clientleafsystem.h"
#include "sdk/filesystem.h"
#include "sdk/modelloader.h"
#include "sdk/IEngineSound.h"
#include "sdk/iclientshadowmgr.h"
#include "sdk/cs_view_scene.h"
#include "sdk/iclientmode.h"
#include "sdk/itexture.h"
#include "sdk/precipitation_shared.h"
#include "sdk/iinputsystem.h"
#include "vpkparser.h"
#include "sdk/itempents.h"
#include "sdk/c_te_legacytempents.h"
#include "XorStr.hpp"
PVOID FindHudElement(const char* name);
auto is_code_ptr(void* ptr) -> bool;
#include "resource.h"
class IF {
public:
IClientEntityList* g_pEntityList = nullptr;
CGameUI* g_pGameUI = nullptr;
vgui::IPanel* g_pVGuiPanel = nullptr;
CGameEventManager* g_pGameEvents = nullptr;
IVEngineClient* g_pEngineClient = nullptr;
vgui::ISurface* g_pVGuiSurface = nullptr;
IEngineVGui* g_pEnginevgui = nullptr;
vgui::IVGui* g_pVGui = nullptr;
IBaseClientDLL* g_pClient = nullptr;
IVModelInfoClient* g_pMdlInfo = nullptr;
IVModelRender* g_pMdlRender = nullptr;
IMaterialSystem* g_pMaterialSystem = nullptr;
IKeyValuesSystem* keyValuesSystem = nullptr;
ICvar* g_pCVar = nullptr;
vgui::ISystem* g_pVGuiSystem = nullptr;
vgui::ISchemeManager* g_pVGuiSchemeManager = nullptr;
vgui::IInput* g_pVGuiInput = nullptr;
IFileSystem* g_pFullFileSystem = nullptr;
vgui::ILocalize* g_pVGuiLocalize = nullptr;
IEngineTrace* g_pEnginetrace = nullptr;
IVEfx* g_pEfx = nullptr;
IGameConsole* g_pGameConsole = nullptr;
IPhysicsSurfaceProps* g_pPhysProps = nullptr;
IVRenderView* g_pRenderView = nullptr;
IVDebugOverlay* g_pDebugOverlay = nullptr;
CGlobalVarsBase* g_pGlobals = nullptr;
CInput* g_pInput = nullptr;
IEffects* g_pEffects = nullptr;
IViewRenderBeams* g_pViewRenderBeams = nullptr;
IStudioRender* g_pStudioRender = nullptr;
CHudChat* g_pChatElement = nullptr;
using FX_TeslaFn = void(__thiscall*)(CTeslaInfo&);
FX_TeslaFn FX_Tesla = nullptr;
using FX_BloodSprayFn = bool(__cdecl*)(const CEffectData&);
FX_BloodSprayFn BloodSprayFn = nullptr;
using FXDispatchEffect = int(__fastcall*)(const char* name, const CEffectData&);
FXDispatchEffect DispatchEffect = nullptr;
void Init();
void* GetInterface(const char* dllname, const char* interfacename);
typedef void(__cdecl* CONMSGPROC)(const char*, ...);
CONMSGPROC myConMsg = nullptr;
typedef void(__cdecl* CONCOLORMSGPROC)(Color& clr, const char*, ...);
CONCOLORMSGPROC myConColorMsg = nullptr;
PVOID LoadFromFile = nullptr;
IDirect3DDevice9* g_pD3DDevice9 = nullptr;
IMemAlloc* g_pMemAlloc = nullptr;
ISteamGameCoordinator* g_SteamGameCoordinator = nullptr;
ISteamUser* g_SteamUser = nullptr;
CClientState* g_pClientState = nullptr;
CHudElement* g_pHudElement = nullptr;
IClientLeafSystem* g_pClientLeafSystem = nullptr;
INetworkStringTableContainer* g_pNetworkStringTableContainer = nullptr;
std::add_pointer_t<const char** __fastcall(const char* playerModelName)> getPlayerViewmodelArmConfigForPlayerModel;
IMDLCache* g_pMdlCache = nullptr;
IModelLoader* g_ModelLoader = nullptr;
IEngineSound* g_pEngineSound = nullptr;
IClientShadowMgr* g_pClientShadowMgr = nullptr;
CCSViewRender* g_ViewRender = nullptr;
IClientMode* g_ClientMode = nullptr;
CGlobalVarsBase* g_Globals = nullptr;
IInputSystem* g_pInputSystem = nullptr;
ITempEnts* g_pTempEnts = nullptr;
uint8_t* prime;
char oldprime[5];
};
extern IF iff;
typedef void* (__cdecl* tCreateInterface)(const char* name, int* returnCode);
template <typename T>
static constexpr auto relativeToAbsolute(uintptr_t address) noexcept
{
return (T)(address + 4 + *reinterpret_cast<std::int32_t*>(address));
}
namespace vgui {
inline vgui::IInput* input()
{
return iff.g_pVGuiInput;
}
inline vgui::ISchemeManager* scheme()
{
return iff.g_pVGuiSchemeManager;
}
inline vgui::ISurface* surface()
{
return iff.g_pVGuiSurface;
}
inline vgui::ISystem* system()
{
return iff.g_pVGuiSystem;
}
inline vgui::IVGui* ivgui()
{
return iff.g_pVGui;
}
inline vgui::IPanel* ipanel()
{
return iff.g_pVGuiPanel;
}
}
class ICvar2 : public ICvar
{
public:
ConVar* FindVar2(const char* var)
{
printf("Trying to find var %s\n", var);
typedef ConVar* (*oFindVar)(void*, const char*);
return getvfunc<oFindVar>(this, 16)(this, var);
}
template <typename... Values>
void ConsoleColorPrintf2(const Color& MsgColor, const char* szMsgFormat, Values... Parameters)
{
printf("Trying to print %s\n", szMsgFormat);
typedef void(*oConsoleColorPrintf)(void*, const Color&, const char*, ...);
return getvfunc<oConsoleColorPrintf>(this, 25)(this, MsgColor, szMsgFormat, Parameters...);
}
};
struct model_t
{
void* fnHandle;
char szName[260];
__int32 nLoadFlags;
__int32 nServerCount;
__int32 type;
__int32 flags;
Vector vecMins;
Vector vecMaxs;
float radius;
char pad[0x1C];
};
void AngleVectors(const Vector& angles, Vector* forward, Vector* right, Vector* up);
enum ItemDefinitionIndex
{
ITEM_NONE = 0,
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_SG553 = 39,
WEAPON_SSG08 = 40,
WEAPON_KNIFE_GOLD = 41,
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,
MAX_ITEMDEFINITIONINDEX
};
static int random(int min, int max) noexcept
{
return rand() % (max - min + 1) + min;
}
enum Sequence
{
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,
};
#endif

1830
SpyCustom/KeyValues.cpp Normal file

File diff suppressed because it is too large Load Diff

1949
SpyCustom/Menu.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
#include "NetVarManager.hpp"
#include <cctype>
#ifdef DUMP_NETVARS
#define IF_DUMPING(...) __VA_ARGS__
#else
#define IF_DUMPING(...)
#endif
IF_DUMPING(static FILE* s_fp;)
netvar_manager::netvar_manager()
{
IF_DUMPING(fopen_s(&s_fp, "netvar_dump.txt", "w");)
for (auto clazz = iff.g_pClient->GetAllClasses(); clazz; clazz = clazz->m_pNext)
if (clazz->m_pRecvTable)
dump_recursive(clazz->m_pNetworkName, clazz->m_pRecvTable, 0);
IF_DUMPING(fclose(s_fp);)
}
auto netvar_manager::dump_recursive(const char* base_class, RecvTable* table, const std::uint16_t offset) -> void
{
for (auto i = 0; i < table->m_nProps; ++i)
{
const auto prop_ptr = &table->m_pProps[i];
if (!prop_ptr || isdigit(prop_ptr->m_pVarName[0]))
continue;
if (fnv::hash_runtime(prop_ptr->m_pVarName) == FNV("baseclass"))
continue;
if (prop_ptr->m_RecvType == DPT_DataTable &&
prop_ptr->m_pDataTable != nullptr &&
prop_ptr->m_pDataTable->m_pNetTableName[0] == 'D')
{
dump_recursive(base_class, prop_ptr->m_pDataTable, std::uint16_t(offset + prop_ptr->m_Offset));
}
char hash_name[256];
strcpy_s(hash_name, base_class);
strcat_s(hash_name, "->");
strcat_s(hash_name, prop_ptr->m_pVarName);
const auto hash = fnv::hash_runtime(hash_name);
const auto total_offset = std::uint16_t(offset + prop_ptr->m_Offset);
IF_DUMPING(fprintf(s_fp, "%s\t0x%04X\t%s\n", base_class, total_offset, prop_ptr->m_pVarName);)
m_props[hash] =
{
prop_ptr,
total_offset
};
}
}

217
SpyCustom/NetVarManager.hpp Normal file
View File

@ -0,0 +1,217 @@
#ifndef NETVARMGR
#define NETVARMGR
#pragma once
#include "sdk/cdll_int.h"
#include "sdk/dt_recv.h"
#include "sdk/client_class.h"
#include <vector>
#include "Interfaces.hpp"
#include <cstdlib>
namespace detail
{
template <typename Type, Type OffsetBasis, Type Prime>
struct size_dependant_data
{
using type = Type;
constexpr static auto k_offset_basis = OffsetBasis;
constexpr static auto k_prime = Prime;
};
template <size_t Bits>
struct size_selector;
template <>
struct size_selector<32>
{
using type = size_dependant_data<std::uint32_t, 0x811c9dc5ul, 16777619ul>;
};
template <>
struct size_selector<64>
{
using type = size_dependant_data<std::uint64_t, 0xcbf29ce484222325ull, 1099511628211ull>;
};
template <std::size_t Size>
class fnv_hash
{
private:
using data_t = typename size_selector<Size>::type;
public:
using hash = typename data_t::type;
private:
constexpr static auto k_offset_basis = data_t::k_offset_basis;
constexpr static auto k_prime = data_t::k_prime;
public:
template <std::size_t N>
static __forceinline constexpr auto hash_constexpr(const char(&str)[N], const std::size_t size = N) -> hash
{
return static_cast<hash>(1ull * (size == 1
? (k_offset_basis ^ str[0])
: (hash_constexpr(str, size - 1) ^ str[size - 1])) * k_prime);
}
static auto __forceinline hash_runtime(const char* str) -> hash
{
auto result = k_offset_basis;
do
{
result ^= *str++;
result *= k_prime;
} while (*(str - 1) != '\0');
return result;
}
};
}
namespace fnv2 {
constexpr uint32_t offsetBasis = 0x811c9dc5;
constexpr uint32_t prime = 0x1000193;
constexpr uint32_t hash(const char* str, const uint32_t value = offsetBasis) noexcept
{
return *str ? hash(str + 1, (value ^ *str) * static_cast<unsigned long long>(prime)) : value;
}
constexpr uint32_t hashRuntime(const char* str) noexcept
{
auto value = offsetBasis;
while (*str) {
value ^= *str++;
value *= prime;
}
return value;
}
}
using fnv = ::detail::fnv_hash<sizeof(void*) * 8>;
#define FNV(str) (std::integral_constant<fnv::hash, fnv::hash_constexpr(str)>::value)
#include <map>
#include <type_traits>
class netvar_manager
{
private:
struct stored_data
{
RecvProp* prop_ptr;
std::uint16_t class_relative_offset;
};
public:
static auto get() -> const netvar_manager&
{
static netvar_manager instance;
return instance;
}
auto get_offset(const fnv::hash hash) const -> std::uint16_t
{
return m_props.at(hash).class_relative_offset;
}
auto get_prop(const fnv::hash hash) const -> RecvProp*
{
return m_props.at(hash).prop_ptr;
}
__declspec(noinline) static auto get_offset_by_hash(const fnv::hash hash) -> std::uint16_t
{
return get().get_offset(hash);
}
template<fnv::hash Hash>
static auto get_offset_by_hash_cached() -> std::uint16_t
{
static auto offset = std::uint16_t(0);
if (!offset)
offset = get_offset_by_hash(Hash);
return offset;
}
private:
netvar_manager();
auto dump_recursive(const char* base_class, RecvTable* table, std::uint16_t offset) -> void;
private:
std::map<fnv::hash, stored_data> m_props;
};
#define PNETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \
auto funcname() -> std::add_pointer_t<__VA_ARGS__> \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached<hash>(); \
return reinterpret_cast<std::add_pointer_t<__VA_ARGS__>>(addr); \
}
#define PNETVAR(funcname, class_name, var_name, ...) \
PNETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__)
#define NETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \
auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
const auto addr = std::uintptr_t(this) + offset + netvar_manager::get_offset_by_hash_cached<hash>(); \
return *reinterpret_cast<std::add_pointer_t<__VA_ARGS__>>(addr); \
}
#define NETVAR(funcname, class_name, var_name, ...) \
NETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__)
#define NETPROP(funcname, class_name, var_name) \
static auto funcname() -> RecvProp* \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
static RecvProp* prop_ptr; \
if(!prop_ptr) prop_ptr = netvar_manager::get().get_prop(hash); \
return prop_ptr; \
}
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;
};
#endif

1102
SpyCustom/Options.hpp Normal file

File diff suppressed because it is too large Load Diff

265
SpyCustom/Other.cpp Normal file
View File

@ -0,0 +1,265 @@
#include "Other.hpp"
#include "PatternScan.hpp"
void UpdateFlashLight(CFlashlightEffect* pFlashLight, const Vector& vecPos, const Vector& vecForward, const Vector& vecRight, const Vector& vecUp)
{
typedef void(__thiscall* UpdateLight_t)(void*, int, const Vector&, const Vector&, const Vector&, const Vector&, float, float, float, bool, const char*);
static UpdateLight_t oUpdateLight = NULL;
if (!oUpdateLight)
{
DWORD callInstruction = FindPatternV2("client.dll", "E8 ? ?? ? ? 8B 06 F3 0F 10 46");
DWORD relativeAddress = *(DWORD*)(callInstruction + 1);
DWORD nextInstruction = callInstruction + 5;
oUpdateLight = (UpdateLight_t)(nextInstruction + relativeAddress);
}
oUpdateLight(pFlashLight, pFlashLight->m_nEntIndex, vecPos, vecForward, vecRight, vecUp,
pFlashLight->m_flFov, pFlashLight->m_flFarZ, pFlashLight->m_flLinearAtten, pFlashLight->m_bCastsShadows,
pFlashLight->m_textureName);
}
CFlashlightEffect* CreateFlashLight(int nEntIndex, const char* pszTextureName, float flFov, float flFarZ, float flLinearAtten)
{
CFlashlightEffect* pFlashLight = reinterpret_cast<CFlashlightEffect*>(iff.g_pMemAlloc->Alloc(sizeof(CFlashlightEffect)));
if (!pFlashLight)
return NULL;
static DWORD oConstructor = FindPatternV2("client.dll", "55 8B EC F3 0F 10 45 ? B8");
__asm
{
movss xmm3, flFov
mov ecx, pFlashLight
push flLinearAtten
push flFarZ
push pszTextureName
push nEntIndex
call oConstructor
}
pFlashLight->m_bIsOn = true;
return pFlashLight;
}
void DestroyFlashLight(CFlashlightEffect* pFlashLight)
{
static DWORD oDestructor = FindPatternV2("client.dll", "56 8B F1 E8 ? ? ? ? 8B 4E 28");
__asm
{
mov ecx, pFlashLight
push ecx
call oDestructor
}
}
void AngleVectors(const Vector& angles, Vector* forward, Vector* right, Vector* up)
{
float sr, sp, sy, cr, cp, cy;
SinCos(DEG2RAD(angles[1]), &sy, &cy);
SinCos(DEG2RAD(angles[0]), &sp, &cp);
SinCos(DEG2RAD(angles[2]), &sr, &cr);
if (forward)
{
forward->x = cp * cy;
forward->y = cp * sy;
forward->z = -sp;
}
if (right)
{
right->x = (-1 * sr * sp * cy + -1 * cr * -sy);
right->y = (-1 * sr * sp * sy + -1 * cr * cy);
right->z = -1 * sr * cp;
}
if (up)
{
up->x = (cr * sp * cy + -sr * -sy);
up->y = (cr * sp * sy + -sr * cy);
up->z = cr * cp;
}
}
static bool ToggleButton(ButtonCode_t code)
{
static int buttonPressedTick = 0;
if (iff.g_pInputSystem->IsButtonDown(code) && (GetTickCount64() - buttonPressedTick) > 300)
{
buttonPressedTick = GetTickCount64();
return true;
}
return false;
}
void FlashlightRun(C_BasePlayer* local)
{
static CFlashlightEffect* pFlashLight = NULL;
if (opt.disconnected)
{
#ifdef DEBUG
printf("nullify pFlashlight bc disconnected\n");
#endif
pFlashLight = NULL;
opt.disconnected = 0;
}
if (ToggleButton(KEY_L))
{
if (!pFlashLight)
{
#ifdef DEBUG
printf("creating fl\n");
#endif
pFlashLight = CreateFlashLight(local->GetIndex(), g_Options.flashlightTexture.value->mystring, *g_Options.flashlightFOV, *g_Options.flashlightFarZ, *g_Options.flashlightLinearAtten);
iff.g_pEngineClient->ExecuteClientCmd("play items/flashlight1.wav");
}
else
{
#ifdef DEBUG
printf("destroying fl\n");
#endif
DestroyFlashLight(pFlashLight);
pFlashLight = NULL;
iff.g_pEngineClient->ExecuteClientCmd("play items/flashlight1.wav");
}
}
if (pFlashLight)
{
Vector f, r, u;
Vector viewAngles;
iff.g_pEngineClient->GetViewAngles(viewAngles);
AngleVectors(viewAngles, &f, &r, &u);
pFlashLight->m_bIsOn = true;
pFlashLight->m_bCastsShadows = *g_Options.flashlightShadows;
pFlashLight->m_flFov = *g_Options.flashlightFOV;
UpdateFlashLight(pFlashLight, local->GetOrigin() + local->GetViewOffset(), f, r, u);
}
}
#define DRAW_SCREEN_EFFECT(material) \
{ \
const auto drawFunction = relativeToAbsolute<uintptr_t>(FindPatternV2("client.dll", "E8 ? ? ? ? 83 C4 0C 8D 4D F8") + 1); \
int w, h; \
iff.g_pVGuiSurface->GetScreenSize(w, h); \
__asm { \
__asm push h \
__asm push w \
__asm push 0 \
__asm xor edx, edx \
__asm mov ecx, material \
__asm call drawFunction \
__asm add esp, 12 \
} \
}
void NightvisionRun(C_BasePlayer* local) {
static int m_flNightVisionAlpha = NetvarSys::Get().GetOffset("DT_CSPlayer", "m_flFlashDuration") - 0x1C;
if (ToggleButton(KEY_N) )
{
if (!local->GetNightvision())
{
local->GetNightvision() = true;
*(float*)(uintptr_t(local) + m_flNightVisionAlpha) = 1.0f;
iff.g_pEngineClient->ExecuteClientCmd("play items/nvg_on.wav");
}
else
{
local->GetNightvision() = false;
*(float*)(uintptr_t(local) + m_flNightVisionAlpha) = 0;
iff.g_pEngineClient->ExecuteClientCmd("play items/nvg_off.wav");
}
}
}
void do_precipitation() {
static void* rain_networkable = nullptr;
C_Precipitation* rain_ent = (C_Precipitation*)iff.g_pEntityList->GetClientEntity(MAX_EDICTS - 1);
static ClientClass* precipitation_client_class = nullptr;
if (!iff.g_pEngineClient->IsInGame() || !iff.g_pEngineClient->IsConnected()) {
rain_networkable = rain_ent = nullptr;
return;
}
int localplayer_index = iff.g_pEngineClient->GetLocalPlayer();
C_BasePlayer* localplayer = static_cast<C_BasePlayer*>(iff.g_pEntityList->GetClientEntity(localplayer_index));
if (!localplayer) return;
if (!(localplayer->GetLifeState() == LIFE_ALIVE && localplayer->GetHealth() > 0))
return;
if (!precipitation_client_class) {
for (auto pclass = iff.g_pClient->GetAllClasses(); pclass && !precipitation_client_class; pclass = pclass->m_pNext)
if (strstr(pclass->GetName(), "CPrecipitation"))
{
#ifdef DEBUG
printf("class found %x\n", pclass);
#endif
precipitation_client_class = pclass;
}
}
else {
if (!rain_ent && precipitation_client_class && precipitation_client_class->m_pCreateFn) {
#ifdef DEBUG
printf("Creating precipitation\n");
#endif
rain_networkable = ((void* (*)(int, int))precipitation_client_class->m_pCreateFn)(MAX_EDICTS - 1, 0);
if (rain_networkable) {
rain_ent = (C_Precipitation*)iff.g_pEntityList->GetClientEntity(MAX_EDICTS - 1);
rain_ent->GetPrecipitationType() = (PrecipitationType_t)*g_Options.weathertype;
rain_ent->PreDataUpdate(DataUpdateType_t::DATA_UPDATE_CREATED);
rain_ent->OnPreDataChanged(DataUpdateType_t::DATA_UPDATE_CREATED);
rain_ent->GetMins() = Vector(-32767.0f, -32767.0f, -32767.0f);
rain_ent->GetMaxs() = Vector(32767.0f, 32767.0f, 32767.0f);
rain_ent->OnDataChanged(DataUpdateType_t::DATA_UPDATE_CREATED);
rain_ent->PostDataUpdate(DataUpdateType_t::DATA_UPDATE_CREATED);
#ifdef DEBUG
printf("Created precipitation %x\n", rain_ent);
#endif
}
}
}
}

15
SpyCustom/Other.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef OTHER
#define OTHER
#pragma once
#include "Interfaces.hpp"
#include "Options.hpp"
#include "sdk/c_baseentity.h"
void FlashlightRun(C_BasePlayer* local);
void NightvisionRun(C_BasePlayer* local);
void do_precipitation();
#endif OTHER

76
SpyCustom/PatternScan.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "PatternScan.hpp"
DWORD WaitOnModuleHandle(std::string moduleName)
{
DWORD ModuleHandle = NULL;
while (!ModuleHandle)
{
ModuleHandle = (DWORD)GetModuleHandle(moduleName.c_str());
if (!ModuleHandle)
Sleep(50);
}
return ModuleHandle;
}
DWORD FindPatternV2(std::string moduleName, std::string pattern)
{
const char* pat = pattern.c_str();
DWORD firstMatch = 0;
DWORD rangeStart = (DWORD)GetModuleHandleA(moduleName.c_str());
MODULEINFO miModInfo; GetModuleInformation(GetCurrentProcess(), (HMODULE)rangeStart, &miModInfo, sizeof(MODULEINFO));
DWORD rangeEnd = rangeStart + miModInfo.SizeOfImage;
for (DWORD pCur = rangeStart; pCur < rangeEnd; pCur++)
{
if (!*pat)
return firstMatch;
if (*(PBYTE)pat == '\?' || *(BYTE*)pCur == getByte(pat))
{
if (!firstMatch)
firstMatch = pCur;
if (!pat[2])
return firstMatch;
if (*(PWORD)pat == '\?\?' || *(PBYTE)pat != '\?')
pat += 3;
else
pat += 2;
}
else
{
pat = pattern.c_str();
firstMatch = 0;
}
}
return NULL;
}
bool bCompare(const BYTE* Data, const BYTE* Mask, const char* szMask)
{
for (; *szMask; ++szMask, ++Mask, ++Data)
{
if (*szMask == 'x' && *Mask != *Data)
{
return false;
}
}
return (*szMask) == 0;
}
DWORD FindPattern(std::string moduleName, BYTE* Mask, char* szMask)
{
DWORD Address = WaitOnModuleHandle(moduleName.c_str());
MODULEINFO ModInfo; GetModuleInformation(GetCurrentProcess(), (HMODULE)Address, &ModInfo, sizeof(MODULEINFO));
DWORD Length = ModInfo.SizeOfImage;
for (DWORD c = 0; c < Length; c += 1)
{
if (bCompare((BYTE*)(Address + c), Mask, szMask))
{
return (DWORD)(Address + c);
}
}
return 0;
}

20
SpyCustom/PatternScan.hpp Normal file
View File

@ -0,0 +1,20 @@
#ifndef PATTERNSCAN
#define PATTERNSCAN
#pragma once
#include <Windows.h>
#include <Psapi.h>
#include <string>
#define INRANGE(x,a,b) (x >= a && x <= b)
#define getBits( x ) (INRANGE((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xa) : (INRANGE(x,'0','9') ? x - '0' : 0))
#define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1]))
DWORD WaitOnModuleHandle(std::string moduleName);
DWORD FindPatternV2(std::string moduleName, std::string pattern);
bool bCompare(const BYTE* Data, const BYTE* Mask, const char* szMask);
DWORD FindPattern(std::string moduleName, BYTE* Mask, char* szMask);
#endif

View File

@ -0,0 +1,207 @@
#include "PlayerInventory.hpp"
void CSharedObjectTypeCache::AddObject(void* obj)
{
typedef void(__thiscall* tOriginal)(void*, void*);
getvfunc<tOriginal>(this, 1)(this, obj);
}
void CSharedObjectTypeCache::RemoveObject(void* obj)
{
typedef void(__thiscall* tOriginal)(void*, void*);
getvfunc<tOriginal>(this, 3)(this, obj);
}
std::vector<CEconItem*> CSharedObjectTypeCache::GetEconItems()
{
std::vector<CEconItem*> ret;
auto size = *reinterpret_cast<size_t*>(this + 0x18);
auto data = *reinterpret_cast<uintptr_t**>(this + 0x4);
for (size_t i = 0; i < size; i++)
ret.push_back(reinterpret_cast<CEconItem*>(data[i]));
return ret;
}
template<typename TYPE>
void CEconItem::SetAttributeValue(int index, TYPE val)
{
auto v15 = (DWORD*)GetItemSchema();
auto v16 = *(DWORD*)(v15[72] + 4 * index);
static auto fnSetDynamicAttributeValue
= reinterpret_cast<int(__thiscall*)(CEconItem*, DWORD, void*)>(
FindPatternV2("client.dll", "55 8B EC 83 E4 F8 83 EC 3C 53 8B 5D 08 56 57 6A 00")
);
fnSetDynamicAttributeValue(this, v16, &val);
}
int C_EconItemDefinition::get_equipped_position()
{
return *reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(this) + 0x24C);
}
const char* C_EconItemDefinition::get_world_model_name()
{
return *reinterpret_cast<const char**>(uintptr_t(this) + 0x9C);
}
uint32_t* CEconItem::GetAccountID()
{
return reinterpret_cast<uint32_t*>(this + 0x1C);
}
uint64_t* CEconItem::GetItemID()
{
return reinterpret_cast<uint64_t*>(this + 0x8);
}
uint64_t* CEconItem::GetOriginalID()
{
return reinterpret_cast<uint64_t*>(this + 0x10);
}
uint16_t* CEconItem::GetDefIndex()
{
return reinterpret_cast<uint16_t*>(this + 0x24);
}
uint32_t* CEconItem::GetInventory()
{
return reinterpret_cast<uint32_t*>(this + 0x20);
}
unsigned char* CEconItem::GetFlags()
{
return reinterpret_cast<unsigned char*>(this + 0x30);
}
unsigned short* CEconItem::GetEconItemData()
{
return reinterpret_cast<unsigned short*>(this + 0x26);
}
C_EconItemDefinition* C_EconItemView::get_static_data()
{
static auto fn = reinterpret_cast<C_EconItemDefinition * (__thiscall*)(void*)>(FindPatternV2("client.dll", "55 8B EC 51 53 8B D9 8B ? ? ? ? ? 56 57 8B ? ? ? ? ? 85 FF 74 16"));
return fn(this);
}
CEconItem* C_EconItemView::get_soc_data()
{
static auto fn = reinterpret_cast<CEconItem * (__thiscall*)(C_EconItemView*)>(FindPatternV2("client.dll", "55 8B EC 83 E4 F0 83 EC 18 56 8B F1 57 8B 86"));
return fn(this);
}
void CPlayerInventory::RemoveItem(uint64_t ID)
{
static auto fnRemoveItem
= reinterpret_cast<int(__thiscall*)(void*, int64_t)>(
FindPatternV2("client.dll", "55 8B EC 83 E4 F8 56 57 FF 75 0C 8B F1")
);
fnRemoveItem(this, ID);
}
CSharedObjectTypeCache* CPlayerInventory::GetBaseTypeCache()
{
static auto fnGCSDK_CGCClient_FindSOCache
= reinterpret_cast<uintptr_t(__thiscall*)(uintptr_t, uint64_t, uint64_t, bool)>(
FindPatternV2("client.dll", "55 8B EC 83 E4 F8 83 EC 1C 0F 10 45 08")
);
static auto fnGCSDK_CSharedObjectCache_CreateBaseTypeCache
= reinterpret_cast<CSharedObjectTypeCache * (__thiscall*)(uintptr_t, int)>(
FindPatternV2("client.dll", "55 8B EC 51 53 56 8B D9 8D 45 08")
);
static auto g_GCClientSystem = **reinterpret_cast<uintptr_t**>(FindPatternV2("client.dll", "8B 0D ? ? ? ? 6A 00 83 EC 10") + 0x2);
auto SOCahce = fnGCSDK_CGCClient_FindSOCache(g_GCClientSystem + 0x60, *reinterpret_cast<uint64_t*>(this + 0x8), *reinterpret_cast<uint64_t*>(this + 0x10), 0);
return fnGCSDK_CSharedObjectCache_CreateBaseTypeCache(SOCahce, 1);
}
void CPlayerInventory::RemoveItem(CEconItem* item)
{
RemoveItem(*item->GetItemID());
GetBaseTypeCache()->RemoveObject(item);
}
void CPlayerInventory::ClearInventory()
{
auto BaseTypeCache = this->GetBaseTypeCache();
auto items = BaseTypeCache->GetEconItems();
for (auto item : items)
{
RemoveItem(*item->GetItemID());
BaseTypeCache->RemoveObject(item);
}
}
uint32_t CPlayerInventory::GetSteamID()
{
return *reinterpret_cast<uint32_t*>(this + 0x8);
}
CUtlVector< C_EconItemView* >* CPlayerInventory::GetInventoryItems()
{
return reinterpret_cast<CUtlVector<C_EconItemView*>*>(this + 0x2C);
}
bool CPlayerInventory::AddEconItem(CEconItem* item, int a3, int a4, char a5)
{
static auto fnAddEconItem
= reinterpret_cast<C_EconItemView * (__thiscall*)(void*, CEconItem*, int, int, char)>(
FindPatternV2("client.dll", "55 8B EC 83 E4 F8 A1 ? ? ? ? 83 EC 14 53 56 57 8B F9 8B 08")
);
GetBaseTypeCache()->AddObject(item);
auto ret = fnAddEconItem(this, item, a3, a4, a5);
return ret;
}
CPlayerInventory* CSInventoryManager::GetLocalPlayerInventory()
{
static auto local_inventory_offset = *reinterpret_cast<uintptr_t*>(FindPatternV2("client.dll", "8B 8B ? ? ? ? E8 ? ? ? ? 89 44 24 18") + 0x2);
return *reinterpret_cast<CPlayerInventory**>(this + local_inventory_offset);
}
CEconItem* CreateEconItem()
{
static auto fnCreateSharedObjectSubclass_EconItem_
= reinterpret_cast<CEconItem * (__stdcall*)()>(
*reinterpret_cast<uintptr_t*>(FindPatternV2("client.dll", "C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4 C7 45 ? ? ? ? ? 50 C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? C7 45 ? ? ? ? ? E8 ? ? ? ? 83 F8 FF 75 09 8D 45 E4 50 E8 ? ? ? ? 8D 45 E4") + 3)
);
return fnCreateSharedObjectSubclass_EconItem_();
}
uintptr_t GetItemSchema()
{
static auto fnGetItemSchema
= reinterpret_cast<uintptr_t(__stdcall*)()>(
FindPatternV2("client.dll", "A1 ? ? ? ? 85 C0 75 53")
);
return fnGetItemSchema();
}

View File

@ -0,0 +1,138 @@
#ifndef PLAYERINV
#define PLAYERINV
#pragma once
#include "PatternScan.hpp"
#include "Interfaces.hpp"
#include "sdk/utlvector.h"
#include "stdint.h"
#include <vector>
#include "sdk/icliententity.h"
enum ItemQuality
{
ITEM_QUALITY_DEFAULT,
ITEM_QUALITY_GENUINE,
ITEM_QUALITY_VINTAGE,
ITEM_QUALITY_UNUSUAL,
ITEM_QUALITY_SKIN,
ITEM_QUALITY_COMMUNITY,
ITEM_QUALITY_DEVELOPER,
ITEM_QUALITY_SELFMADE,
ITEM_QUALITY_CUSTOMIZED,
ITEM_QUALITY_STRANGE,
ITEM_QUALITY_COMPLETED,
ITEM_QUALITY_UNK2,
ITEM_QUALITY_TOURNAMENT
};
enum ItemRarity
{
ITEM_RARITY_DEFAULT,
ITEM_RARITY_COMMON,
ITEM_RARITY_UNCOMMON,
ITEM_RARITY_RARE,
ITEM_RARITY_MYTHICAL,
ITEM_RARITY_LEGENDARY,
ITEM_RARITY_ANCIENT,
ITEM_RARITY_IMMORTAL
};
class CEconItem
{
unsigned short* GetEconItemData();
void UpdateEquippedState(unsigned int state);
public:
uint32_t* GetInventory();
uint32_t* GetAccountID();
uint16_t* GetDefIndex();
uint64_t* GetItemID();
uint64_t* GetOriginalID();
unsigned char* GetFlags();
void SetQuality(ItemQuality quality);
void SetRarity(ItemRarity rarity);
void SetOrigin(int origin);
void SetLevel(int level);
void SetInUse(bool in_use);
void SetCustomName(const char* name);
void SetCustomDesc(const char* name);
void SetPaintSeed(float seed);
void SetPaintKit(float kit);
void SetPaintWear(float wear);
void SetStatTrak(int val);
void AddSticker(int index, int kit, float wear, float scale, float rotation);
template<typename TYPE>
void SetAttributeValue(int index, TYPE val);
};
class C_EconItemDefinition
{
public:
int get_equipped_position();
const char* get_world_model_name();
};
class C_EconItemView
{
private:
using str_32 = char[32];
public:
int32_t m_bInitialized;
int16_t m_iItemDefinitionIndex;
int32_t m_iEntityLevel;
int32_t m_iAccountID;
int32_t m_iItemIDLow;
int32_t m_iItemIDHigh;
int32_t m_iEntityQuality;
str_32 m_iCustomName;
CUtlVector<IRefCounted*>& m_CustomMaterials();
CUtlVector<IRefCounted*>& m_VisualsDataProcessors();
C_EconItemDefinition* get_static_data();
CEconItem* get_soc_data();
};
class CSharedObjectTypeCache
{
public:
void AddObject(void* obj);
void RemoveObject(void* obj);
std::vector<CEconItem*> GetEconItems();
};
class CPlayerInventory
{
public:
void RemoveItem(uint64_t ID);
void RemoveItem(CEconItem* item);
void ClearInventory();
CSharedObjectTypeCache* GetBaseTypeCache();
uint32_t GetSteamID();
CUtlVector<C_EconItemView*>* GetInventoryItems();
bool AddEconItem(CEconItem* item, int a3, int a4, char a5);
};
class CSInventoryManager
{
public:
CPlayerInventory* GetLocalPlayerInventory();
};
uintptr_t GetItemSchema();
CEconItem* CreateEconItem();
#endif

581
SpyCustom/ProtoParse.h Normal file
View File

@ -0,0 +1,581 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#define MAKE_TAG(FIELD_NUMBER, TYPE) static_cast<uint32_t>(((FIELD_NUMBER) << kTagTypeBits) | (TYPE))
#define make_struct(_name_, _size_) \
struct _name_ : ProtoWriter { \
constexpr static size_t MAX_FIELD = _size_; \
_name_() : ProtoWriter(MAX_FIELD) {} \
_name_(void* data, size_t size) : ProtoWriter(data, size, MAX_FIELD) {} \
_name_(std::string data) : ProtoWriter(data, MAX_FIELD) {}
#define make_field(_name_, _id_, _type_) \
constexpr static Tag _name_ = { _id_, _type_ }; \
void clear_##_name_() { this->clear(_name_); } \
bool has_##_name_() { return this->has(_name_); } \
Field get_##_name_() { return this->get(_name_); } \
std::vector<Field> getAll_##_name_() { return this->getAll(_name_); } \
\
void add_##_name_(std::string v) { this->add(_name_, v); } \
template<typename T> void add_##_name_(T v) { this->add(_name_, v); } \
void replace_##_name_(std::string v) { this->replace(_name_, v); } \
void replace_##_name_(std::string v, uint32_t index) { this->replace(_name_, v, index); } \
template<typename T> void replace_##_name_(T v) { this->replace(_name_, v); } \
template<typename T> void replace_##_name_(T v, uint32_t index) { this->replace(_name_, v, index); } \
template<class T> T get_##_name_() { return std::move( T(this->get(_name_).String()) ); }
struct Tag
{
unsigned field;
unsigned type;
};
enum FieldType {
TYPE_DOUBLE = 1,
TYPE_FLOAT = 2,
TYPE_INT64 = 3,
TYPE_UINT64 = 4,
TYPE_INT32 = 5,
TYPE_FIXED64 = 6,
TYPE_FIXED32 = 7,
TYPE_BOOL = 8,
TYPE_STRING = 9,
TYPE_GROUP = 10,
TYPE_MESSAGE = 11,
TYPE_BYTES = 12,
TYPE_UINT32 = 13,
TYPE_ENUM = 14,
TYPE_SFIXED32 = 15,
TYPE_SFIXED64 = 16,
TYPE_SINT32 = 17,
TYPE_SINT64 = 18,
MAX_FIELD_TYPE = 18,
};
struct Field
{
friend class ProtoWriter;
public:
inline Field& operator=(const Field& f);
Field() : tag({ 0,0 }), value(""), full("") { }
Field(unsigned field, unsigned type, std::string value, std::string full);
Field(Tag tag, std::string value);
Field(unsigned field, unsigned type, std::string value);
template<typename T>
Field(Tag tag, T value);
template<typename T>
Field(unsigned field, unsigned type, T value);
public:
static Field ReadField(void* data, size_t& bytesRead);
public:
inline float Float();
inline double Double();
inline int32_t Int32();
inline int64_t Int64();
inline uint32_t UInt32();
inline uint64_t UInt64();
inline uint32_t Fixed32();
inline uint64_t Fixed64();
inline int32_t SFixed32();
inline int64_t SFixed64();
inline bool Bool();
inline std::string String();
private:
Tag tag;
std::string value;
std::string full;
static std::string getBytesVarint32(uint32_t value);
static std::string getBytesVarint64(uint64_t value);
static uint32_t readVarUint32(void* data, size_t& bytesRead);
static uint64_t readVarUint64(void* data, size_t& bytesRead);
enum WireType {
WIRETYPE_VARINT = 0,
WIRETYPE_FIXED64 = 1,
WIRETYPE_LENGTH_DELIMITED = 2,
WIRETYPE_START_GROUP = 3,
WIRETYPE_END_GROUP = 4,
WIRETYPE_FIXED32 = 5,
};
constexpr static WireType kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = {
static_cast<WireType>(-1),
WIRETYPE_FIXED64,
WIRETYPE_FIXED32,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_FIXED64,
WIRETYPE_FIXED32,
WIRETYPE_VARINT,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_START_GROUP,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_FIXED32,
WIRETYPE_FIXED64,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
};
constexpr static int kTagTypeBits = 3;
constexpr static uint32_t kTagTypeMask = (1 << kTagTypeBits) - 1;
constexpr static int kMaxVarintBytes = 10;
constexpr static int kMaxVarint32Bytes = 5;
};
class ProtoWriter
{
public:
inline ProtoWriter();
inline ProtoWriter(size_t maxFields);
inline ProtoWriter(void* data, size_t size, size_t maxFields);
inline ProtoWriter(std::string dataStr, size_t maxFields);
public:
inline void add(Field field);
inline void replace(Field field);
inline void replace(Field field, uint32_t index);
inline void clear(unsigned fieldId);
inline bool has(unsigned fieldId);
inline Field get(unsigned fieldId);
inline std::vector<Field> getAll(unsigned fieldId);
public:
inline void add(Tag tag, std::string value);
inline void replace(Tag tag, std::string value);
inline void replace(Tag tag, std::string value, uint32_t index);
inline void clear(Tag tag);
inline bool has(Tag tag);
inline Field get(Tag tag);
inline std::vector<Field> getAll(Tag tag);
template<typename T>
inline void add(Tag tag, T value);
template<typename T>
inline void replace(Tag tag, T value);
template<typename T>
inline void replace(Tag tag, T value, uint32_t index);
std::string serialize();
void print();
private:
std::vector<std::vector<Field>> fields;
};
#pragma region Helper Functions
std::string Field::getBytesVarint32(uint32_t value)
{
uint8_t bytes[kMaxVarint32Bytes];
int size = 0;
while (value > 0x7F) {
bytes[size++] = (static_cast<uint8_t>(value) & 0x7F) | 0x80;
value >>= 7;
}
bytes[size++] = static_cast<uint8_t>(value) & 0x7F;
return std::string{ reinterpret_cast<const char*>(&bytes[0]), (size_t)size };
}
std::string Field::getBytesVarint64(uint64_t value)
{
uint8_t bytes[kMaxVarintBytes];
int size = 0;
while (value > 0x7F) {
bytes[size++] = (static_cast<uint8_t>(value) & 0x7F) | 0x80;
value >>= 7;
}
bytes[size++] = static_cast<uint8_t>(value) & 0x7F;
return std::string{ reinterpret_cast<const char*>(&bytes[0]), (size_t)size };
}
uint32_t Field::readVarUint32(void* data, size_t& bytesRead)
{
auto ptr = reinterpret_cast<const uint8_t*>(data);
auto value = 0u;
auto bytes = 0u;
do {
value |= static_cast<uint32_t>(*ptr & 0x7f) << (7 * bytes);
bytes++;
} while (*(ptr++) & 0x80 && bytes <= 5);
bytesRead = bytes;
return value;
}
uint64_t Field::readVarUint64(void* data, size_t& bytesRead)
{
auto ptr = reinterpret_cast<const uint8_t*>(data);
auto value = 0ull;
auto bytes = 0u;
do
{
value |= static_cast<uint64_t>(*ptr & 0x7f) << (7 * bytes);
bytes++;
} while (*(ptr++) & 0x80 && bytes <= 10);
bytesRead = bytes;
return value;
}
Field Field::ReadField(void* data, size_t& bytesRead)
{
unsigned field = *reinterpret_cast<uint16_t*>(data);
unsigned type = field & kTagTypeMask;
if (field == 0xffff) {
bytesRead = 0;
return Field();
}
if (field & 0x80) {
field = ((field & 0x7f) | ((field & 0xff00) >> 1)) >> kTagTypeBits;
bytesRead = 2;
}
else {
field = (field & 0xff) >> kTagTypeBits;
bytesRead = 1;
}
size_t length, sizeDelimited;
std::string value, full;
switch (type)
{
case WIRETYPE_VARINT:
readVarUint64((void*)((ptrdiff_t)data + bytesRead), length);
value = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytesRead)), length };
full = std::string{ reinterpret_cast<const char*>(data), bytesRead + length };
bytesRead += length;
break;
case WIRETYPE_FIXED64:
value = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytesRead)), 8 };
full = std::string{ reinterpret_cast<const char*>(data), bytesRead + 8 };
bytesRead += 8;
break;
case WIRETYPE_LENGTH_DELIMITED:
sizeDelimited = readVarUint32((void*)((ptrdiff_t)data + bytesRead), length);
value = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytesRead)), length + sizeDelimited };
full = std::string{ reinterpret_cast<const char*>(data), bytesRead + length + sizeDelimited };
bytesRead += length + sizeDelimited;
break;
case WIRETYPE_START_GROUP:
throw("WIRETYPE_START_GROUP unrealised");
break;
case WIRETYPE_END_GROUP:
throw("WIRETYPE_END_GROUP unrealised");
break;
case WIRETYPE_FIXED32:
value = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytesRead)), 4 };
full = std::string{ reinterpret_cast<const char*>(data), bytesRead + 4 };
bytesRead += 4;
break;
default:
throw("Unknown type %i", type);
break;
}
return Field(field, type, value, full);
}
#pragma endregion
#pragma region Field Definition
Field& Field::operator=(const Field& f) {
this->tag = f.tag;
this->value = f.value;
this->full = f.full;
return *this;
}
Field::Field(unsigned field, unsigned type, std::string value, std::string full) {
this->tag = { field, type };
this->value = value;
this->full = full;
}
template<typename T>
Field::Field(Tag tag, T value) {
auto wireType = kWireTypeForFieldType[tag.type];
full = getBytesVarint32(MAKE_TAG(tag.field, wireType));
switch (wireType) {
case WIRETYPE_VARINT:
full += getBytesVarint64(static_cast<uint64_t>(value));
break;
case WIRETYPE_FIXED32:
full += std::string{ reinterpret_cast<const char*>(&value), 4 };
break;
case WIRETYPE_FIXED64:
full += std::string{ reinterpret_cast<const char*>(&value), 8 };
break;
}
}
template<typename T>
Field::Field(unsigned field, unsigned type, T value) {
auto wireType = kWireTypeForFieldType[type];
tag = { field, (unsigned)wireType };
full = getBytesVarint32(MAKE_TAG(field, wireType));
switch (wireType) {
case WIRETYPE_VARINT:
full += getBytesVarint64(static_cast<uint64_t>(value));
break;
case WIRETYPE_FIXED32:
full += std::string{ reinterpret_cast<const char*>(&value), 4 };
break;
case WIRETYPE_FIXED64:
full += std::string{ reinterpret_cast<const char*>(&value), 8 };
break;
}
}
Field::Field(Tag tag, std::string value) {
auto wireType = kWireTypeForFieldType[tag.type];
full = getBytesVarint32(MAKE_TAG(tag.field, wireType));
full += getBytesVarint32(value.size());
full += value;
}
Field::Field(unsigned field, unsigned type, std::string value) {
auto wireType = kWireTypeForFieldType[type];
tag = { field, (unsigned)wireType };
full = getBytesVarint32(MAKE_TAG(field, wireType));
full += getBytesVarint32(value.size());
full += value;
}
float Field::Float() {
return *reinterpret_cast<float*>((void*)value.data());
}
double Field::Double() {
return *reinterpret_cast<double*>((void*)value.data());
}
int32_t Field::Int32() {
size_t bytesRead;
return static_cast<int32_t>(readVarUint64((void*)value.data(), bytesRead));
}
int64_t Field::Int64() {
size_t bytesRead;
return readVarUint64((void*)value.data(), bytesRead);
}
uint32_t Field::UInt32() {
size_t bytesRead;
return readVarUint32((void*)value.data(), bytesRead);
}
uint64_t Field::UInt64() {
size_t bytesRead;
return readVarUint64((void*)value.data(), bytesRead);
}
uint32_t Field::Fixed32() {
return *reinterpret_cast<uint32_t*>((void*)value.data());
}
uint64_t Field::Fixed64() {
return *reinterpret_cast<uint64_t*>((void*)value.data());
}
int32_t Field::SFixed32() {
return *reinterpret_cast<int32_t*>((void*)value.data());
}
int64_t Field::SFixed64() {
return *reinterpret_cast<int64_t*>((void*)value.data());
}
bool Field::Bool() {
size_t bytesRead;
return !!readVarUint32((void*)value.data(), bytesRead);
}
std::string Field::String()
{
size_t bytesRead;
void* data = (void*)value.data();
auto length = readVarUint32((void*)value.data(), bytesRead);
auto value = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytesRead)), length };
return value;
}
#pragma endregion
#pragma region ProtoWriter Definition
ProtoWriter::ProtoWriter()
{
}
ProtoWriter::ProtoWriter(size_t maxFields)
{
size_t vector_size = maxFields + 1;
fields.resize(vector_size);
fields.reserve(vector_size);
}
ProtoWriter::ProtoWriter(void* data, size_t size, size_t maxFields) : ProtoWriter(maxFields)
{
size_t vector_size = maxFields + 1,
pos = 0,
bytesRead;
if (data == nullptr)
return;
while (pos < size) {
auto field = Field::ReadField((void*)((ptrdiff_t)data + pos), bytesRead);
if (!bytesRead) break;
auto index = field.tag.field;
if (index >= vector_size) throw("fields range error: field[%i]", index);
fields[index].push_back(field);
pos += bytesRead;
}
}
ProtoWriter::ProtoWriter(std::string dataStr, size_t maxFields) : ProtoWriter((void*)dataStr.data(), dataStr.size(), maxFields)
{
}
std::string ProtoWriter::serialize()
{
std::string result;
for (auto& f0 : fields) {
for (auto& f1 : f0) {
result += f1.full;
}
}
return result;
}
void ProtoWriter::print()
{
auto data = serialize();
void* mem = (void*)data.data();
size_t size = data.size();
int j = 0;
for (size_t i = 0; i <= size; ++i) {
printf("%.2X ", *(unsigned char*)((uintptr_t)mem + i));
j++;
if (j == 16)
{
j = 0;
printf("\n");
}
}
printf("\n");
}
void ProtoWriter::add(Field field)
{
fields[field.tag.field].push_back(field);
}
void ProtoWriter::replace(Field field)
{
fields[field.tag.field].clear();
fields[field.tag.field].push_back(field);
}
void ProtoWriter::replace(Field field, uint32_t index)
{
fields[field.tag.field][index] = field;
}
void ProtoWriter::clear(unsigned fieldId)
{
return fields[fieldId].clear();
}
bool ProtoWriter::has(unsigned fieldId)
{
return fields[fieldId].size() > 0;
}
Field ProtoWriter::get(unsigned fieldId)
{
if (fields[fieldId].empty())
return Field();
return fields[fieldId][0];
}
std::vector<Field> ProtoWriter::getAll(unsigned fieldId)
{
return fields[fieldId];
}
template<typename T>
void ProtoWriter::add(Tag tag, T value)
{
fields[tag.field].push_back(Field(tag, value));
}
template<typename T>
void ProtoWriter::replace(Tag tag, T value)
{
fields[tag.field].clear();
fields[tag.field].push_back(Field(tag, value));
}
template<typename T>
void ProtoWriter::replace(Tag tag, T value, uint32_t index)
{
fields[tag.field][index] = Field(tag, value);
}
void ProtoWriter::add(Tag tag, std::string value)
{
fields[tag.field].push_back(Field(tag, value));
}
void ProtoWriter::replace(Tag tag, std::string value)
{
fields[tag.field].clear();
fields[tag.field].push_back(Field(tag, value));
}
void ProtoWriter::replace(Tag tag, std::string value, uint32_t index)
{
fields[tag.field][index] = Field(tag, value);
}
void ProtoWriter::clear(Tag tag)
{
return fields[tag.field].clear();
}
bool ProtoWriter::has(Tag tag)
{
return fields[tag.field].size() > 0;
}
Field ProtoWriter::get(Tag tag)
{
if (fields[tag.field].empty())
return Field();
return fields[tag.field][0];
}
std::vector<Field> ProtoWriter::getAll(Tag tag)
{
return fields[tag.field];
}
#pragma endregion

View File

@ -0,0 +1,105 @@
#pragma once
#include "pbwrap.hpp"
#define k_EMsgGCCStrike15_v2_MatchmakingGC2ClientReserve 9107
#define k_EMsgGCClientWelcome 4004
#define k_EMsgGCClientHello 4006
#define k_EMsgGCAdjustItemEquippedState 1059
#define k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello 9109
#define k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello 9110
#define k_EMsgGCCStrike15_v2_ClientGCRankUpdate 9194
using namespace pbwrap;
struct CMsgClientHello : pbmsg<8> {
PBMSG_CTOR;
PBFIELD(3, types::Uint32, client_session_need);
};
struct MatchmakingGC2ClientHello : pbmsg<20> {
struct PlayerRankingInfo : pbmsg<6> {
PBMSG_CTOR;
PBFIELD(1, types::Uint32, account_id);
PBFIELD(2, types::Uint32, rank_id);
PBFIELD(3, types::Uint32, wins);
PBFIELD(6, types::Uint32, rank_type_id);
};
struct PlayerCommendationInfo : pbmsg<4> {
PBMSG_CTOR;
PBFIELD(1, types::Uint32, cmd_friendly);
PBFIELD(2, types::Uint32, cmd_teaching);
PBFIELD(4, types::Uint32, cmd_leader);
};
PBMSG_CTOR;
PBFIELD(7, PlayerRankingInfo, ranking);
PBFIELD(8, PlayerCommendationInfo, commendation);
PBFIELD(17, types::Int32, player_level);
PBFIELD(18, types::Int32, player_cur_xp);
PBFIELD(4, types::Uint32, penalty_seconds);
PBFIELD(5, types::Uint32, penalty_reason);
PBFIELD(6, types::Int32, vac_banned);
};
struct CMsgGCCStrike15_v2_ClientGCRankUpdate : pbmsg<1> {
PBMSG_CTOR;
PBFIELD(1, MatchmakingGC2ClientHello::PlayerRankingInfo, ranking);
};
struct CSOEconItemEquipped : pbmsg<2> {
PBMSG_CTOR;
PBFIELD(1, types::Int32, new_class);
PBFIELD(2, types::Int32, new_slot);
};
struct CSOEconItemAttribute : pbmsg<3> {
PBMSG_CTOR;
PBFIELD(1, types::Uint32, def_index);
PBFIELD(2, types::Uint32, value);
PBFIELD(3, types::Bytes, value_bytes);
};
struct CSOEconItem : pbmsg<19> {
PBMSG_CTOR;
PBFIELD(1, types::Uint64, id);
PBFIELD(2, types::Uint32, account_id);
PBFIELD(3, types::Uint32, inventory);
PBFIELD(4, types::Int32, def_index);
PBFIELD(5, types::Uint32, quantity);
PBFIELD(6, types::Uint32, level);
PBFIELD(7, types::Uint32, quality);
PBFIELD(8, types::Uint32, flags);
PBFIELD(9, types::Uint32, origin);
PBFIELD(10, types::String, custom_name);
PBFIELD(11, types::String, custom_desc);
PBFIELD(12, CSOEconItemAttribute, attribute);
PBFIELD(14, types::Bool, in_use);
PBFIELD(15, types::Uint32, style);
PBFIELD(16, types::Uint64, original_id);
PBFIELD(18, CSOEconItemEquipped, equipped_state);
PBFIELD(19, types::Uint32, rarity);
};
struct CMsgClientWelcome : pbmsg<11> {
struct SubscribedType : pbmsg<2> {
PBMSG_CTOR;
PBFIELD(1, types::Int32, type_id);
PBFIELD(2, CSOEconItem, object_data);
};
struct CMsgSOCacheSubscribed : pbmsg<4> {
PBMSG_CTOR;
PBFIELD(2, SubscribedType, objects);
};
PBMSG_CTOR;
PBFIELD(3, CMsgSOCacheSubscribed, outofdate_subscribed_caches);
};
struct CMsgAdjustItemEquippedState : pbmsg<4> {
PBMSG_CTOR;
PBFIELD(1, types::Uint64, item_id);
PBFIELD(2, types::Uint32, new_class);
PBFIELD(3, types::Uint32, new_slot);
PBFIELD(4, types::Bool, swap);
};

28
SpyCustom/Singleton.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef SINGLETON
#define SINGLETON
#pragma once
template<typename T>
class Singleton
{
protected:
Singleton() {}
~Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
public:
static T& Get()
{
static T inst{};
return inst;
}
};
#endif

427
SpyCustom/SkinChanger.hpp Normal file
View File

@ -0,0 +1,427 @@
#ifndef SKINCHANGER
#define SKINCHANGER
#pragma once
#include <vector>
#include <string>
#include "sdk/GameEventManager.h"
#include "VMT.hpp"
#include "Interfaces.hpp"
#include "Options.hpp"
#include "sdk/c_baseentity.h"
#include "PatternScan.hpp"
extern VMTHook* GameEventManagerHook;
extern VMTHook* ClientHook;
#include "NetVarManager.hpp"
extern bool needupdate;
#include "vmt_smart_hook.hpp"
struct iitem
{
iitem(int defindex1, std::string name1, std::string viewmodel1, std::string worldmodel1)
{
defindex = defindex1;
name = name1;
viewmodel = viewmodel1;
worldmodel = worldmodel1;
Preview = std::to_string(defindex1).append(": ").append(name1);
}
int defindex;
std::string name;
std::string viewmodel;
std::string worldmodel;
std::string Preview;
bool isSelected;
};
struct hud_weapons_t
{
std::int32_t* get_weapon_count()
{
return reinterpret_cast<std::int32_t*>(std::uintptr_t(this) + 0x80);
}
};
struct String_t
{
char* szBuffer;
int nCapacity;
int _unknown;
int nLength;
};
class CEconItemRarityDefinition
{
public:
int id;
int color;
String_t name;
String_t loc_key;
String_t loc_key_weapon;
String_t loot_list;
String_t recycle_list;
String_t drop_sound;
String_t endmatchitemrevealrarity;
String_t pointertosomething3;
void* pointertosomething4;
void* pointertosomething5;
char dumb10[8];
};
class CStickerKit
{
public:
int id;
int item_rarity;
String_t name;
String_t description;
String_t item_name;
String_t material_name;
String_t image_inventory;
int tournament_event_id;
int tournament_team_id;
int tournament_player_id;
bool is_custom_sticker_material;
float rotate_end;
float rotate_start;
float scale_min;
float scale_max;
float wear_min;
float wear_max;
String_t image_inventory2;
String_t image_inventory_large;
std::uint32_t pad0[4];
};
class CPaintKit
{
public:
int nID;
String_t sName;
String_t sDescriptionString;
String_t sDescriptionTag;
String_t pad;
String_t pattern;
String_t pad1;
String_t sLogoMaterial;
int bBaseDiffuseOverride;
int rarity;
int nStyle;
int color1;
int color2;
int color3;
int color4;
int logoColor1;
int logoColor2;
int logoColor3;
int logoColor4;
float flWearDefault;
float flWearRemapMin;
float flWearRemapMax;
char nFixedSeed;
char uchPhongExponent;
char uchPhongAlbedoBoost;
char uchPhongIntensity;
float flPatternScale;
float flPatternOffsetXStart;
float flPatternOffsetXEnd;
float flPatternOffsetYStart;
float flPatternOffsetYEnd;
float flPatternRotateStart;
float flPatternRotateEnd;
float flLogoScale;
float flLogoOffsetX;
float flLogoOffsetY;
float flLogoRotation;
int bIgnoreWeaponSizeScale;
int nViewModelExponentOverrideSize;
int bOnlyFirstMaterial;
float pearlescent;
int sVmtPath[4];
int kvVmtOverrides;
};
struct EconItemQualityDefinition {
int id;
const char* name;
unsigned weight;
bool explicitMatchesOnly;
bool canSupportSet;
const char* hexColor;
};
extern std::vector<iitem> rarities;
extern std::vector<iitem> knives;
extern std::vector<iitem> gloves;
extern std::vector<iitem> agents;
extern std::vector<iitem> medals;
extern std::vector<iitem> musickits;
extern std::vector <iitem> qualities;
static inline auto is_knife(const int di) -> bool
{
for (short i = 0; i < knives.size(); i++)
if (knives[i].defindex == di) return true;
return false;
}
bool __fastcall hkFireEventClientSide(void* thisptr, void* edx, IGameEvent* event);
void __fastcall hkFrameStageNotify(IBaseClientDLL* thisptr, void* edx, ClientFrameStage_t stage);
class CCStrike15ItemSchema;
class CCStrike15ItemSystem
{
public:
virtual CCStrike15ItemSchema* GetItemSchemaInterface() = 0;
};
template <typename Key, typename Value>
struct Node_t
{
int nPreviousId;
int nNextId;
void* parent;
int type;
Key iPaintKitId;
Value value;
};
template <typename Key, typename Value>
struct Head_t
{
Node_t<Key, Value>* pMemory;
int nAllocationCount;
int nGrowSize;
int nStartElement;
int nNextAvailable;
int _unknown;
int nLastElement;
};
class CEconItemDefinition
{
public:
VIRTUAL_METHOD(int, getWeaponId, 0, (), (this))
VIRTUAL_METHOD(const char*, getItemBaseName, 2, (), (this))
VIRTUAL_METHOD(const char*, getItemTypeName, 3, (), (this))
VIRTUAL_METHOD(const char*, getPlayerDisplayModel, 6, (), (this))
VIRTUAL_METHOD(const char*, getWorldDisplayModel, 7, (), (this))
VIRTUAL_METHOD(std::uint8_t, getRarity, 12, (), (this))
char pad_0x0000[0x8];
int32_t m_iItemDefinitionIndex;
char pad_0x000C[0x40];
char* m_szHudName;
char pad_0x0050[0x4];
char* m_szWeaponType;
char pad_0x0058[0x4];
char* m_szWeaponDescription;
char pad_0x0060[0x34];
char* m_szViewModel;
char pad_0x0098[0x4];
char* m_szWorldModel;
char* m_szWorldModelDropped;
char pad_0x001[0x58];
char* stickersdecalmdl;
char pad_0x002[0x0C];
char* stickersdecalmdl1;
char* inventoryicon;
char pad_0x003[0xA4];
char* m_szWeaponName1;
char pad_0x004[0x14];
char* m_szWeaponName;
char pad_0x005[0x8];
char* m_szWeaponName3;
char pad_0x01C4[0x27C];
};
void InitSkinChanger();
template <typename T>
struct UtlMemory {
T& operator[](int i) const noexcept { return memory[i]; };
T* memory;
int allocationCount;
int growSize;
};
template <typename Key, typename Value>
struct UtlMap {
auto begin() const noexcept { return memory.memory; }
auto end() const noexcept { return memory.memory + numElements; }
int find(Key key) const noexcept
{
auto curr = root;
while (curr != -1) {
const auto el = memory[curr];
if (el.iPaintKitId < key)
curr = el.nNextId;
else if (el.iPaintKitId > key)
curr = el.nPreviousId;
else
break;
}
return curr;
}
void* lessFunc;
UtlMemory<Node_t<Key, Value>> memory;
int root;
int numElements;
int firstFree;
int lastAlloc;
Node_t<Key, Value>* elements;
};
struct AlternateIconData {
String_t simpleName;
String_t largeSimpleName;
String_t iconURLSmall;
String_t iconURLLarge;
PAD(28)
};
template <typename T>
class UtlVector {
public:
constexpr T& operator[](int i) noexcept { return memory[i]; };
constexpr const T& operator[](int i) const noexcept { return memory[i]; };
T* memory;
int allocationCount;
int growSize;
int size;
T* elements;
};
struct ItemListEntry {
int itemDef;
int paintKit;
PAD(20)
auto weaponId() const noexcept
{
return itemDef;
}
};
class EconLootListDefinition {
public:
VIRTUAL_METHOD(const char*, getName, 0, (), (this))
VIRTUAL_METHOD(const UtlVector<ItemListEntry>&, getLootListContents, 1, (), (this))
};
class EconItemSetDefinition {
public:
VIRTUAL_METHOD(const char*, getLocKey, 1, (), (this))
VIRTUAL_METHOD(int, getItemCount, 4, (), (this))
VIRTUAL_METHOD(int, getItemDef, 5, (int index), (this, index))
VIRTUAL_METHOD(int, getItemPaintKit, 6, (int index), (this, index))
};
class CEconColorDefinition
{
public:
int xz;
int xz2;
};
class CEconGraffitiTintDefinition
{
public:
int xz;
int xz2;
};
class CEconMusicDefinition
{
public:
int id;
char* name;
char* desc;
char* model;
char* music;
};
template <typename T>
class MusicVector {
public:
constexpr T& operator[](int i) noexcept { return memory[i]; };
constexpr const T& operator[](int i) const noexcept { return memory[i]; };
T* memory;
PAD(0xC)
int itemcount;
};
class ItemSchema {
public:
PAD(0x64)
UtlMap<int, CEconItemRarityDefinition> rars;
UtlMap<int, EconItemQualityDefinition> qualities;
PAD(0x48)
UtlMap<int, CEconItemDefinition*> itemsSorted;
PAD(0x104)
UtlMap<std::uint64_t, AlternateIconData> alternateIcons;
PAD(0x48)
UtlMap<int, CPaintKit*> paintKits;
UtlMap<int, CStickerKit*> stickerKits;
UtlMap<const char*, CStickerKit*> sticker_kits_namekey;
int32_t pad6[24];
UtlMap<const char*, KeyValues*> prefabs;
UtlVector<CEconColorDefinition*> colors;
UtlVector<CEconGraffitiTintDefinition*> graffiti_tints;
int32_t pad7[20];
MusicVector<CEconMusicDefinition*> music_definitions;
VIRTUAL_METHOD(CEconItemDefinition*, getItemDefinitionInterface, 4, (int id), (this, id))
VIRTUAL_METHOD(int, getItemSetCount, 28, (), (this))
VIRTUAL_METHOD(EconItemSetDefinition*, getItemSet, 29, (int index), (this, index))
VIRTUAL_METHOD(EconLootListDefinition*, getLootList, 32, (int index), (this, index))
VIRTUAL_METHOD(int, getLootListCount, 34, (), (this))
VIRTUAL_METHOD(CEconItemDefinition*, getItemDefinitionByName, 42, (const char* name), (this, name))
};
class ItemSystem {
public:
VIRTUAL_METHOD(ItemSchema*, getItemSchema, 0, (), (this))
};
extern std::add_pointer_t<ItemSystem* __cdecl()> itemSystem;
#endif

678
SpyCustom/Skinchanger.cpp Normal file
View File

@ -0,0 +1,678 @@
#include "SkinChanger.hpp"
#include "Other.hpp"
VMTHook* GameEventManagerHook = nullptr;
VMTHook* ClientHook = nullptr;
std::vector<iitem> rarities;
std::vector<iitem> knives;
std::vector<iitem> gloves;
std::vector<iitem> agents;
std::vector<iitem> medals;
std::vector<iitem> musickits;
std::vector <iitem> qualities;
std::add_pointer_t<ItemSystem* __cdecl()> itemSystem;
enum class EStickerAttributeType
{
Index,
Wear,
Scale,
Rotation
};
static auto s_econ_item_interface_wrapper_offset = std::uint16_t(0);
struct GetStickerAttributeBySlotIndexFloat
{
static auto __fastcall hooked(void* thisptr, void*, const int slot,
const EStickerAttributeType attribute, const float unknown) -> float
{
auto item = reinterpret_cast<C_BaseAttributableItem*>(std::uintptr_t(thisptr) - s_econ_item_interface_wrapper_offset);
const auto defindex = item->GetItemDefinitionIndex();
int config = GetCfgIndex(defindex);
if (config != -1)
{
switch (attribute)
{
case EStickerAttributeType::Wear:
return g_Options.weapons.value->arr[config].stickers[slot].wear;
case EStickerAttributeType::Scale:
return g_Options.weapons.value->arr[config].stickers[slot].scale;
case EStickerAttributeType::Rotation:
return g_Options.weapons.value->arr[config].stickers[slot].rotation;
default:
break;
}
}
return m_original(thisptr, nullptr, slot, attribute, unknown);
}
static decltype(&hooked) m_original;
};
decltype(GetStickerAttributeBySlotIndexFloat::m_original) GetStickerAttributeBySlotIndexFloat::m_original;
struct GetStickerAttributeBySlotIndexInt
{
static auto __fastcall hooked(void* thisptr, void*, const int slot,
const EStickerAttributeType attribute, const int unknown) -> int
{
auto item = reinterpret_cast<C_BaseAttributableItem*>(std::uintptr_t(thisptr) - s_econ_item_interface_wrapper_offset);
if (attribute == EStickerAttributeType::Index)
{
const auto defindex = item->GetItemDefinitionIndex();
int config = GetCfgIndex(defindex);
if (config != -1)
return g_Options.weapons.value->arr[config].stickers[slot].stickerid;
}
return m_original(thisptr, nullptr, slot, attribute, unknown);
}
static decltype(&hooked) m_original;
};
decltype(GetStickerAttributeBySlotIndexInt::m_original) GetStickerAttributeBySlotIndexInt::m_original;
void ApplyStickers(C_BaseAttributableItem* item)
{
if (!s_econ_item_interface_wrapper_offset)
s_econ_item_interface_wrapper_offset = netvar_manager::get().get_offset(FNV("CBaseAttributableItem->m_Item")) + 0xC;
static vmt_multi_hook hook;
const auto econ_item_interface_wrapper = std::uintptr_t(item) + s_econ_item_interface_wrapper_offset;
if (hook.initialize_and_hook_instance(reinterpret_cast<void*>(econ_item_interface_wrapper)))
{
hook.apply_hook<GetStickerAttributeBySlotIndexFloat>(4);
hook.apply_hook<GetStickerAttributeBySlotIndexInt>(5);
}
}
bool __fastcall hkFireEventClientSide(void* thisptr, void* edx, IGameEvent* event)
{
static auto ofunc = GameEventManagerHook->GetOriginal<bool(__fastcall*)(void*, void*, IGameEvent*)>(9);
if (event) {
if (!strcmp(event->GetName(), "player_death") && iff.g_pEngineClient->GetPlayerForUserID(event->GetInt("attacker")) == iff.g_pEngineClient->GetLocalPlayer())
{
#ifdef DEBUG
printf("BE playerdeath with %s\n", event->GetString("weapon"));
#endif
for (int i = 0; i < g_Options.weapons.value->weaponzcount; i++)
{
if (_tcsstr(g_Options.weapons.value->arr[i].killfeedicon, event->GetString("weapon")))
{
if (g_Options.weapons.value->arr[i].active && g_Options.weapons.value->arr[i].killfeediconactive)
event->SetString("weapon", g_Options.weapons.value->arr[i].killfeediconreplace);
if (!g_Options.weapons.value->arr[i].ownerunk && g_Options.weapons.value->arr[i].stattrak != -1)
g_Options.weapons.value->arr[i].stattrak += 1;
}
}
}
}
return ofunc(thisptr, edx, event);
}
C_CS_PlayerResource** g_player_resource;
#include <array>
bool Changer()
{
static bool initinterface = 0;
if (!initinterface) {
const auto team_arr_prop = C_CS_PlayerResource::GetTeamProp();
const auto team_prop = team_arr_prop->m_pDataTable->m_pProps;
const auto proxy_addr = std::uintptr_t(team_prop->m_ProxyFn);
g_player_resource = *reinterpret_cast<C_CS_PlayerResource***>(proxy_addr + 0x10);
#ifdef DEBUG
printf("g_player_resource initiated %x\n", g_player_resource);
#endif
initinterface = 1;
}
if (!iff.g_pEngineClient->IsConnected()) {
return 0;
}
int localplayer_index = iff.g_pEngineClient->GetLocalPlayer();
C_BasePlayer* localplayer = static_cast<C_BasePlayer*>(iff.g_pEntityList->GetClientEntity(localplayer_index));
if (!localplayer)
return 0;
auto player_resource = *g_player_resource;
if (g_Options.weapons.value->arr[4].active)
player_resource->GetCoins()[localplayer_index] = g_Options.weapons.value->arr[4].modeldefindex;
if (g_Options.weapons.value->arr[5].active)
player_resource->GetMusicKits()[localplayer_index] = g_Options.weapons.value->arr[5].modeldefindex;
if (g_Options.profile_active)
{
int ranktype = player_resource->GetRankType()[localplayer_index];
int selectedrank = 0;
if (ranktype == 7) selectedrank = 1;
if (ranktype == 10) selectedrank = 2;
player_resource->GetRanks()[localplayer_index] = g_Options.rankz.value->arr[selectedrank].rank;
player_resource->GetWins()[localplayer_index] = g_Options.rankz.value->arr[selectedrank].wins;
player_resource->GetLevel()[localplayer_index] = g_Options.level;
player_resource->GetComLeader()[localplayer_index] = g_Options.comleader;
player_resource->GetComTeacher()[localplayer_index] = g_Options.comteacher;
player_resource->GetComFriendly()[localplayer_index] = g_Options.comfriendly;
}
if (g_Options.fakescore)
{
player_resource->GetMVPs()[localplayer_index] = g_Options.MVPs;
player_resource->GetScore()[localplayer_index] = g_Options.score;
player_resource->GetKills()[localplayer_index] = g_Options.kills;
player_resource->GetAssists()[localplayer_index] = g_Options.assists;
player_resource->GetDeaths()[localplayer_index] = g_Options.deaths;
}
int team = localplayer->GetTeam(); char* model = 0;
if (team == TEAM_TERRORIST && g_Options.weapons.value->arr[2].active && g_Options.weapons.value->arr[2].modelactive)
model = g_Options.weapons.value->arr[2].model;
if (team == TEAM_CT && g_Options.weapons.value->arr[3].active && g_Options.weapons.value->arr[3].modelactive)
model = g_Options.weapons.value->arr[3].model;
if (model != 0) {
localplayer->GetModelIndex() = iff.g_pMdlInfo->GetModelIndex(model);
if (const auto modelprecache = iff.g_pNetworkStringTableContainer->FindTable("modelprecache"))
{
modelprecache->AddString(false, model);
const auto viewmodelArmConfig = iff.getPlayerViewmodelArmConfigForPlayerModel(model);
modelprecache->AddString(false, viewmodelArmConfig[2]);
modelprecache->AddString(false, viewmodelArmConfig[3]);
}
const auto m_hRagdoll = (C_BaseEntity*)iff.g_pEntityList->GetClientEntityFromHandle(localplayer->Ragdoll());
if (m_hRagdoll)
m_hRagdoll->GetModelIndex() = iff.g_pMdlInfo->GetModelIndex(model);
}
if (localplayer->GetLifeState() != LIFE_ALIVE)
{
if (g_Options.weapons.value->arr[1].active && g_Options.weapons.value->arr[1].modelactive) {
auto destroyglove = iff.g_pEntityList->GetClientEntityFromHandle(localplayer->GetWearables()[0]);
if (destroyglove) {
destroyglove->GetClientNetworkable()->SetDestroyedOnRecreateEntities();
destroyglove->GetClientNetworkable()->Release();
#ifdef DEBUG
printf("destroyed glove\n");
#endif
}
}
return 0;
}
player_info_t localplayer_info;
if (!iff.g_pEngineClient->GetPlayerInfo(localplayer_index, &localplayer_info))
return 0;
CBaseHandle viewmodelHandle = localplayer->GetViewModel();
C_BaseViewModel* pViewModel = (C_BaseViewModel*)iff.g_pEntityList->GetClientEntityFromHandle(viewmodelHandle);
const auto view_model_weapon = (C_BaseAttributableItem*)iff.g_pEntityList->GetClientEntityFromHandle(pViewModel->GetWeapon());
int idi = view_model_weapon->GetItemDefinitionIndex();
if (idi == WEAPON_KNIFE) idi = WEAPON_KNIFE_T;
int modelcfgindex = GetCfgIndex2(idi);
if (modelcfgindex != -1 && g_Options.models.value->arr[modelcfgindex].active)
{
char* model = g_Options.models.value->arr[modelcfgindex].vmodel_repl;
const auto override_model_index = iff.g_pMdlInfo->GetModelIndex(model);
view_model_weapon->SetModelIndex(override_model_index) ;
pViewModel->SetModelIndex(override_model_index) ;
if (const auto modelprecache = iff.g_pNetworkStringTableContainer->FindTable("modelprecache"))
{
modelprecache->AddString(false, model);
}
}
int seqact = opt.needtogetseqact;
if (seqact)
{
int oldmodelindex = pViewModel->GetModelIndex();
pViewModel->SetModelIndex(iff.g_pMdlInfo->GetModelIndex(g_Options.models.value->arr[seqact].vmodel_orig));
for (int i = 0; i < 20; i++)
strcpy(g_Options.models.value->arr[seqact].seqs[i].seq_orig_def, (char*)pViewModel->GetSequenceActivity(i));
pViewModel->SetModelIndex(iff.g_pMdlInfo->GetModelIndex(g_Options.models.value->arr[seqact].vmodel_repl));
for (int i = 0; i < 20; i++)
{
strcpy(g_Options.models.value->arr[seqact].seqs[i].seq_repl_def, (char*)pViewModel->GetSequenceActivity(i));
char newpreview[32] = "";
strcat_s(newpreview, std::to_string(i).c_str());
strcat_s(newpreview, ": ");
strcat_s(newpreview, g_Options.models.value->arr[seqact].seqs[i].seq_repl_def);
strcpy(g_Options.models.value->arr[seqact].seqs[i].seq_repl_def_preview, newpreview);
}
pViewModel->SetModelIndex(oldmodelindex);
opt.needtogetseqact = 0;
}
if (g_Options.weapons.value->arr[1].active && g_Options.weapons.value->arr[1].modelactive)
{
auto hWearables = localplayer->GetWearables();
static int glove_handle;
C_BaseAttributableItem* glove = (C_BaseAttributableItem*)iff.g_pEntityList->GetClientEntityFromHandle(hWearables[0] );
if (!glove)
{
C_BaseAttributableItem* our_glove = (C_BaseAttributableItem*)iff.g_pEntityList->GetClientEntityFromHandle(glove_handle);
if (our_glove)
{
hWearables[0] = glove_handle;
glove = our_glove;
}
}
if (!glove)
{
static std::add_pointer_t<C_BaseEntity* __cdecl(int, int)> createWearable = nullptr;
if (!createWearable) {
createWearable = []() -> decltype(createWearable)
{
for (auto clientClass = iff.g_pClient->GetAllClasses(); clientClass; clientClass = clientClass->m_pNext)
if (clientClass->m_ClassID == 54)
return (std::add_pointer_t<C_BaseEntity* __cdecl(int, int)>)clientClass->m_pCreateFn;
return nullptr;
}();
}
const auto serial = rand() % 0x1000;
auto entry = iff.g_pEntityList->GetHighestEntityIndex() + 1;
for (int i = 65; i < iff.g_pEntityList->GetHighestEntityIndex(); i++)
{
auto pEntity = iff.g_pEntityList->GetClientEntity(i);
if (pEntity && pEntity->GetClientClass()->m_ClassID == 70)
{
entry = i;
break;
}
}
createWearable(entry, serial);
glove = (C_BaseAttributableItem*)iff.g_pEntityList->GetClientEntity(entry);
glove->initialized() = true;
hWearables[0] = entry | serial << 16;
static int(__thiscall * equipWearable)(void* wearable, void* player) = reinterpret_cast<decltype(equipWearable)>(FindPatternV2("client.dll", "55 8B EC 83 EC 10 53 8B 5D 08 57 8B F9"));
equipWearable(glove, localplayer);
localplayer->body() = 1;
glove->SetModelIndex(iff.g_pMdlInfo->GetModelIndex(g_Options.weapons.value->arr[1].worldmodel));
iff.g_pClientState->ForceFullUpdate();
}
if (glove)
{
glove->GetItemDefinitionIndex() = g_Options.weapons.value->arr[1].modeldefindex;
glove->GetItemIDHigh() = -1;
glove->GetAccountID() = localplayer_info.xuidlow;
glove->GetFallbackPaintKit() = g_Options.weapons.value->arr[1].skinid;
glove->GetFallbackSeed() = g_Options.weapons.value->arr[1].seed;
glove->GetFallbackWear() = g_Options.weapons.value->arr[1].wear;
}
}
if (g_Options.weapons.value->arr[0].active && g_Options.weapons.value->arr[0].modelactive)
{
static int lastmdlindex = -1;
int curmdlindex = pViewModel->GetModelIndex();
if (lastmdlindex != curmdlindex)
{
lastmdlindex = curmdlindex;
int defindex = view_model_weapon->GetItemDefinitionIndex();
if (!is_knife(defindex)) {
for (int i = 0; i < 20; i++)
if (_tcsstr(pViewModel->GetSequenceActivity(i), "draw"))
{
pViewModel->SendViewModelMatchingSequence(i); break;
}
}
}
if (view_model_weapon && is_knife(view_model_weapon->GetItemDefinitionIndex()))
{
const auto override_model_index = iff.g_pMdlInfo->GetModelIndex(g_Options.weapons.value->arr[0].model);
pViewModel->GetModelIndex() = override_model_index;
}
}
auto& weapons = localplayer->GetWeapons();
for (auto weapon_handle : weapons)
{
if (weapon_handle == INVALID_EHANDLE_INDEX)
break;
C_BaseAttributableItem* weapon = static_cast<C_BaseAttributableItem*>(iff.g_pEntityList->GetClientEntityFromHandle(weapon_handle));
if (!weapon)
continue;
short item_definition_index = weapon->GetItemDefinitionIndex();
if (item_definition_index == WEAPON_C4 && g_Options.weapons.value->arr[GetCfgIndex(item_definition_index)].active)
weapon->body() = 2;
if (item_definition_index == 42) item_definition_index = 59;
int configindex = GetCfgIndex(item_definition_index);
if (configindex == -1) continue;
if (g_Options.weapons.value->arr[configindex].active)
{
if (is_knife(item_definition_index) && g_Options.weapons.value->arr[0].modelactive)
{
weapon->GetItemDefinitionIndex() = g_Options.weapons.value->arr[0].modeldefindex;
short mdlindex = iff.g_pMdlInfo->GetModelIndex(g_Options.weapons.value->arr[0].model);
weapon->GetModelIndex() = mdlindex;
auto m_pWorld = (C_BaseEntity*)iff.g_pEntityList->GetClientEntityFromHandle(weapon->GetWeaponWorldModel());
m_pWorld->GetModelIndex() = mdlindex+1;
}
weapon->GetItemIDHigh() = -1;
if (!g_Options.weapons.value->arr[configindex].ownerunk)
weapon->GetAccountID() = localplayer_info.xuidlow;
weapon->GetEntityQuality() = g_Options.weapons.value->arr[configindex].quality;
snprintf(weapon->GetCustomName(), 32, "%s", g_Options.weapons.value->arr[configindex].nametag);
weapon->GetFallbackPaintKit() = g_Options.weapons.value->arr[configindex].skinid;
weapon->GetFallbackSeed() = g_Options.weapons.value->arr[configindex].seed;
weapon->GetFallbackWear() = g_Options.weapons.value->arr[configindex].wear;
weapon->GetFallbackStatTrak() = g_Options.weapons.value->arr[configindex].stattrak;
ApplyStickers(weapon);
}
}
if (*g_Options.nvgsON)
NightvisionRun(localplayer);
if (*g_Options.flashlightON)
FlashlightRun(localplayer);
if (*g_Options.weatheractive)
do_precipitation();
return 1;
}
void __fastcall hkFrameStageNotify(IBaseClientDLL* thisptr, void* edx, ClientFrameStage_t stage)
{
static auto oFrameStageNotify = ClientHook->GetOriginal<void(__thiscall*)(IBaseClientDLL*, ClientFrameStage_t stage)>(37);
if ( (*g_Options.playerloop_count || *g_Options.entityloop_count) && stage == ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_END)
{
for (int i = 1; i < 65; i++)
{
C_BasePlayer* pEntity = (C_BasePlayer*)iff.g_pEntityList->GetClientEntity(i);
if (i == iff.g_pEngineClient->GetLocalPlayer()) continue;
if (!pEntity || pEntity->IsDormant())
continue;
int team = pEntity->GetTeam();
if ((team < 2) | (team > 3)) continue;
team -= 2;
if (g_Options.models.value->arr[team].active) {
char* model = g_Options.models.value->arr[team].vmodel_repl;
pEntity->GetModelIndex() = iff.g_pMdlInfo->GetModelIndex(model);
if (const auto modelprecache = iff.g_pNetworkStringTableContainer->FindTable("modelprecache"))
{
modelprecache->AddString(false, model);
const auto viewmodelArmConfig = iff.getPlayerViewmodelArmConfigForPlayerModel(model);
modelprecache->AddString(false, viewmodelArmConfig[2]);
modelprecache->AddString(false, viewmodelArmConfig[3]);
}
const auto m_hRagdoll = (C_BaseEntity*)iff.g_pEntityList->GetClientEntityFromHandle(pEntity->Ragdoll());
if (m_hRagdoll)
m_hRagdoll->SetModelIndex(iff.g_pMdlInfo->GetModelIndex(model));
}
if (g_Options.models.value->arr[team].active_scale)
pEntity->GetModelScale() = g_Options.models.value->arr[team].scale;
}
}
if (stage == ClientFrameStage_t::FRAME_NET_UPDATE_POSTDATAUPDATE_START) {
Changer();
if (opt.needupdate) {
static auto clear_hud_weapon_icon_ptr = FindPatternV2("client.dll", "55 8B EC 51 53 56 8B 75 08 8B D9 57 6B FE 2C");
static auto clearHudWeapon = reinterpret_cast<std::int32_t(__thiscall*)(void*, std::int32_t)>(clear_hud_weapon_icon_ptr);
auto element = FindHudElement("CCSGO_HudWeaponSelection");
auto hud_weapons = reinterpret_cast<hud_weapons_t*>(std::uintptr_t(element) - 0xA0);
if (hud_weapons && *hud_weapons->get_weapon_count() > 0)
for (std::int32_t i = 0; i < *hud_weapons->get_weapon_count(); i++)
i = clearHudWeapon(hud_weapons, i);
opt.needupdate = 0;
}
}
oFrameStageNotify(thisptr, stage);
}
void InitSkinChanger()
{
itemSystem = relativeToAbsolute<decltype(itemSystem)>(FindPatternV2("client.dll", "E8 ? ? ? ? 0F B7 0F") + 1);
#ifdef DEBUG
printf("itemschema2 %x\n", itemSystem()->getItemSchema());
#endif
for (const auto& node : itemSystem()->getItemSchema()->itemsSorted) {
const auto item = node.value;
if (std::strcmp(item->m_szWeaponType, "#CSGO_Type_Knife") == 0)
if (item->m_szWorldModel)
knives.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, item->m_szWorldModel));
else knives.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, ""));
if (std::strcmp(item->m_szWeaponType, "#CSGO_Type_Collectible") == 0)
medals.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, "", ""));
if (std::strcmp(item->m_szWeaponType, "#Type_Hands") == 0)
if (item->m_szWorldModel)
gloves.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, item->m_szWorldModel));
else gloves.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, ""));
if (std::strcmp(item->m_szWeaponType, "#Type_CustomPlayer") == 0)
if (item->m_szWorldModel)
agents.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, item->m_szWorldModel));
else agents.push_back(iitem(item->m_iItemDefinitionIndex, item->m_szWeaponName3, item->m_szViewModel, ""));
}
for (const auto& node : itemSystem()->getItemSchema()->qualities) {
const auto item = node.value;
qualities.push_back(iitem(item.id, item.name, "", ""));
}
for (const auto& node : itemSystem()->getItemSchema()->rars) {
const auto item = node.value;
rarities.push_back(iitem(item.id, item.name.szBuffer, "", ""));
}
auto musickitsS = itemSystem()->getItemSchema()->music_definitions;
#ifdef DEBUG
std::cout << musickitsS.memory << " " << musickitsS.itemcount << std::endl;
#endif
for (int i = (int)musickitsS.memory; i < (int)musickitsS.memory + musickitsS.itemcount * 0x18; i += 0x18)
{
CEconMusicDefinition* music = *(CEconMusicDefinition**)(i + 0x14);
musickits.push_back(iitem(music->id, music->name, "", ""));
}
const auto& paintkitMap = itemSystem()->getItemSchema()->paintKits;
int paintkitcount = 0;
for (const auto& node : paintkitMap) {
const auto pKit = node.value;
opt.sc_skins.push_back(Options_my::skinstruct(pKit->nID, pKit->sName.szBuffer, paintkitcount, pKit->rarity, pKit->color1, pKit->color2, pKit->color3, pKit->color4, pKit->pearlescent, (DWORD)&pKit->nID));
paintkitcount++;
}
const auto& stickerMap = itemSystem()->getItemSchema()->stickerKits;
int stickercount = 0;
for (const auto& node : stickerMap) {
const auto stickerKit = node.value;
opt.sc_stickers.push_back(Options_my::stickerstruct(stickerKit->id, stickerKit->name.szBuffer, stickercount));
stickercount++;
}
#ifdef DEBUG
printf("counts %d %d %d %d %d %d %d\n",
knives.size(), gloves.size(), agents.size(), medals.size(), musickits.size(), opt.sc_skins.size(), opt.sc_stickers.size());
#endif
const auto& prefabMap = itemSystem()->getItemSchema()->prefabs;
for (const auto& node : prefabMap) {
KeyValues* kv = node.value;
int cfgindex = GetCfgIndexByPrefab(fnv2::hash(kv->GetName()));
if (cfgindex == -1) continue;
int soundcount = 0;
const char* vmodel_orig = kv->GetString("model_player");
strcpy(g_Options.models.value->arr[cfgindex].vmodel_orig, vmodel_orig);
strcpy(g_Options.models.value->arr[cfgindex].vmodel_repl_temp, vmodel_orig);
strcpy(g_Options.models.value->arr[cfgindex].vmodel_repl, vmodel_orig);
g_Options.materials.value->arr[cfgindex + 2].model_hash = fnv2::hash(vmodel_orig);
kv = kv->FindKey("visuals");
if (kv) {
char* sound_single_shot = (char*)kv->GetString("sound_single_shot");
if (sound_single_shot[0] != 0x0) {
strcpy(g_Options.models.value->arr[cfgindex].sounds[soundcount].name, sound_single_shot);
g_Options.models.value->arr[cfgindex].sounds[soundcount].hash = GenerateSoundEntryHash(sound_single_shot);
soundcount++;
}
char* sound_single_shot_accurate = (char*)kv->GetString("sound_single_shot_accurate");
if (sound_single_shot_accurate[0] != 0x0) {
strcpy(g_Options.models.value->arr[cfgindex].sounds[soundcount].name, sound_single_shot);
g_Options.models.value->arr[cfgindex].sounds[soundcount].hash = GenerateSoundEntryHash(sound_single_shot);
soundcount++;
}
char* sound_special1 = (char*)kv->GetString("sound_special1");
if (sound_special1[0] != 0x0) {
strcpy(g_Options.models.value->arr[cfgindex].sounds[soundcount].name, sound_special1);
g_Options.models.value->arr[cfgindex].sounds[soundcount].hash = GenerateSoundEntryHash(sound_special1);
soundcount++;
}
}
g_Options.models.value->arr[cfgindex].soundcount = soundcount;
}
c_vpk_archive pak01_archive;
if (pak01_archive.load("csgo/pak01_dir.vpk"))
for (auto const& pair : pak01_archive.files)
if (!pair.first.find("materials/panorama/images/icons/equipment"))
opt.killfeedicons.push_back(pair.first.substr(42, pair.first.length() - 46));
g_Options.weapons.value->arr[0].modeldefindex = knives[0].defindex;
strcpy(g_Options.weapons.value->arr[0].model, knives[0].viewmodel.c_str());
strcpy(g_Options.weapons.value->arr[0].worldmodel, knives[0].worldmodel.c_str());
g_Options.weapons.value->arr[0].modelactive = 1;
g_Options.weapons.value->arr[1].modeldefindex = gloves[0].defindex;
strcpy(g_Options.weapons.value->arr[1].model, gloves[0].viewmodel.c_str());
strcpy(g_Options.weapons.value->arr[1].worldmodel, gloves[0].worldmodel.c_str());
g_Options.weapons.value->arr[1].modelactive = 1;
g_Options.weapons.value->arr[2].modeldefindex = agents[0].defindex;
strcpy(g_Options.weapons.value->arr[2].model, agents[0].viewmodel.c_str());
g_Options.weapons.value->arr[2].modelactive = 1;
g_Options.weapons.value->arr[3].modelcount = 1;
g_Options.weapons.value->arr[3].modeldefindex = agents[1].defindex;
strcpy(g_Options.weapons.value->arr[3].model, agents[1].viewmodel.c_str());
g_Options.weapons.value->arr[3].modelactive = 1;
g_Options.weapons.value->arr[4].modeldefindex = medals[0].defindex;
g_Options.weapons.value->arr[4].modelactive = 1;
g_Options.weapons.value->arr[5].modeldefindex = musickits[0].defindex;
g_Options.weapons.value->arr[5].modelactive = 1;
g_Options.models.value->arr[2].findMDLmethode = 1;
}

BIN
SpyCustom/SpyCustom.aps Normal file

Binary file not shown.

80
SpyCustom/SpyCustom.rc Normal file
View File

@ -0,0 +1,80 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Russian (Russia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Russian (Russia) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
/////////////////////////////////////////////////////////////////////////////
//
// WAVE
//
IDR_WAVE1 WAVE "cod.wav"
IDR_WAVE2 WAVE "crit.wav"
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

560
SpyCustom/SpyCustom.vcxproj Normal file
View File

@ -0,0 +1,560 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{bde23281-b75d-4fb2-9b8e-08e1ae0a9bbd}</ProjectGuid>
<RootNamespace>SpyCustom</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>Seaside</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Program Files (x86)\GnuWin32\include;C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include;$(IncludePath)</IncludePath>
<LibraryPath>C:\Program Files (x86)\GnuWin32\lib;C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x86;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;SPYCUSTOM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;SPYCUSTOM_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<AdditionalLibraryDirectories>Winmm.lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;SPYCUSTOM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;SPYCUSTOM_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ai_activity.h" />
<ClInclude Include="AnalogCode.h" />
<ClInclude Include="animationlayer.h" />
<ClInclude Include="annotations.h" />
<ClInclude Include="baseclientstate.h" />
<ClInclude Include="baseentity.h" />
<ClInclude Include="baseentity_shared.h" />
<ClInclude Include="basehandle.h" />
<ClInclude Include="basetypes.h" />
<ClInclude Include="beam_flags.h" />
<ClInclude Include="bitbuf.h" />
<ClInclude Include="bittools.h" />
<ClInclude Include="bitvec.h" />
<ClInclude Include="bone_accessor.h" />
<ClInclude Include="bone_merge_cache.h" />
<ClInclude Include="bspfile.h" />
<ClInclude Include="bspflags.h" />
<ClInclude Include="BuildGroup.h" />
<ClInclude Include="bumpvects.h" />
<ClInclude Include="Button.h" />
<ClInclude Include="ButtonCode.h" />
<ClInclude Include="byteswap.h" />
<ClInclude Include="cdll_client_int.h" />
<ClInclude Include="cdll_int.h" />
<ClInclude Include="cdll_util.h" />
<ClInclude Include="CGameUI.h" />
<ClInclude Include="CheckButton.h" />
<ClInclude Include="checksum_crc.h" />
<ClInclude Include="checksum_md5.h" />
<ClInclude Include="cliententitylist.h" />
<ClInclude Include="clientleafsystem.h" />
<ClInclude Include="client_class.h" />
<ClInclude Include="client_render_handle.h" />
<ClInclude Include="client_thinklist.h" />
<ClInclude Include="client_virtualreality.h" />
<ClInclude Include="cmodel.h" />
<ClInclude Include="collisionproperty.h" />
<ClInclude Include="Color.h" />
<ClInclude Include="commonmacros.h" />
<ClInclude Include="compressed_light_cube.h" />
<ClInclude Include="compressed_vector.h" />
<ClInclude Include="Config.hpp" />
<ClInclude Include="const.h" />
<ClInclude Include="Controls.h" />
<ClInclude Include="convar.h" />
<ClInclude Include="csgosdk.h" />
<ClInclude Include="cs_achievementdefs.h" />
<ClInclude Include="cs_shareddefs.h" />
<ClInclude Include="cs_view_scene.h" />
<ClInclude Include="Cursor.h" />
<ClInclude Include="c_baseanimating.h" />
<ClInclude Include="c_baseanimatingoverlay.h" />
<ClInclude Include="c_basecombatcharacter.h" />
<ClInclude Include="c_baseentity.h" />
<ClInclude Include="c_baseflex.h" />
<ClInclude Include="c_baseplayer.h" />
<ClInclude Include="c_basetempentity.h" />
<ClInclude Include="c_input.h" />
<ClInclude Include="c_pixel_visibility.h" />
<ClInclude Include="c_playerlocaldata.h" />
<ClInclude Include="c_recipientfilter.h" />
<ClInclude Include="c_te_legacytempents.h" />
<ClInclude Include="Dar.h" />
<ClInclude Include="datamap.h" />
<ClInclude Include="dbg.h" />
<ClInclude Include="dbgflag.h" />
<ClInclude Include="deformations.h" />
<ClInclude Include="detours.h" />
<ClInclude Include="dlight.h" />
<ClInclude Include="dmattributetypes.h" />
<ClInclude Include="dmelementhandle.h" />
<ClInclude Include="dmxattribute.h" />
<ClInclude Include="dmxelement.h" />
<ClInclude Include="dmxloader.h" />
<ClInclude Include="dt_common.h" />
<ClInclude Include="dt_recv.h" />
<ClInclude Include="dt_send.h" />
<ClInclude Include="econ_item_constants.h" />
<ClInclude Include="econ_item_interface.h" />
<ClInclude Include="econ_item_schema.h" />
<ClInclude Include="econ_item_view.h" />
<ClInclude Include="edict.h" />
<ClInclude Include="EditablePanel.h" />
<ClInclude Include="ehandle.h" />
<ClInclude Include="eiface.h" />
<ClInclude Include="enginetrace.h" />
<ClInclude Include="entitylist.h" />
<ClInclude Include="entitylist_base.h" />
<ClInclude Include="EventListener.hpp" />
<ClInclude Include="expressioncalculator.h" />
<ClInclude Include="exprevaluator.h" />
<ClInclude Include="fasttimer.h" />
<ClInclude Include="filesystem.h" />
<ClInclude Include="filesystem_passthru.h" />
<ClInclude Include="flashlighteffect.h" />
<ClInclude Include="fltx4.h" />
<ClInclude Include="FocusNavGroup.h" />
<ClInclude Include="Frame.h" />
<ClInclude Include="functors.h" />
<ClInclude Include="fx.h" />
<ClInclude Include="gameconsole.h" />
<ClInclude Include="GameEventListener.h" />
<ClInclude Include="GameEventManager.h" />
<ClInclude Include="gamestringpool.h" />
<ClInclude Include="gametrace.h" />
<ClInclude Include="game_item_schema.h" />
<ClInclude Include="generichash.h" />
<ClInclude Include="GetVfunc.hpp" />
<ClInclude Include="globalvars_base.h" />
<ClInclude Include="groundlink.h" />
<ClInclude Include="Hooks.hpp" />
<ClInclude Include="htmlmessages.h" />
<ClInclude Include="hud.h" />
<ClInclude Include="hudelement.h" />
<ClInclude Include="hudtexturehandle.h" />
<ClInclude Include="hud_basechat.h" />
<ClInclude Include="hud_element_helper.h" />
<ClInclude Include="IAppSystem.h" />
<ClInclude Include="IBorder.h" />
<ClInclude Include="ichromehtmlwrapper.h" />
<ClInclude Include="iclassmap.h" />
<ClInclude Include="iclient.h" />
<ClInclude Include="icliententity.h" />
<ClInclude Include="icliententityinternal.h" />
<ClInclude Include="icliententitylist.h" />
<ClInclude Include="IClientLeafSystem.h" />
<ClInclude Include="iclientmode.h" />
<ClInclude Include="iclientnetworkable.h" />
<ClInclude Include="IClientPanel.h" />
<ClInclude Include="iclientrenderable.h" />
<ClInclude Include="iclientshadowmgr.h" />
<ClInclude Include="iclientthinkable.h" />
<ClInclude Include="iclientunknown.h" />
<ClInclude Include="iclientvirtualreality.h" />
<ClInclude Include="ICollideable.h" />
<ClInclude Include="IColorCorrection.h" />
<ClInclude Include="icommandline.h" />
<ClInclude Include="iconvar.h" />
<ClInclude Include="icvar.h" />
<ClInclude Include="idatacache.h" />
<ClInclude Include="IEffects.h" />
<ClInclude Include="iefx.h" />
<ClInclude Include="ienginetrace.h" />
<ClInclude Include="IEngineVgui.h" />
<ClInclude Include="ifilelist.h" />
<ClInclude Include="igameconsole.h" />
<ClInclude Include="igameevents.h" />
<ClInclude Include="IGameSystem.h" />
<ClInclude Include="IGameUI.h" />
<ClInclude Include="ihandleentity.h" />
<ClInclude Include="IHTML.h" />
<ClInclude Include="IImage.h" />
<ClInclude Include="IInput.h" />
<ClInclude Include="iinputsystem.h" />
<ClInclude Include="IKeyValuesSystem.h" />
<ClInclude Include="ILocalize.h" />
<ClInclude Include="Image.h" />
<ClInclude Include="imageformat.h" />
<ClInclude Include="imaterial.h" />
<ClInclude Include="imaterialsystem.h" />
<ClInclude Include="imaterialsystemhardwareconfig.h" />
<ClInclude Include="imdlcache.h" />
<ClInclude Include="IMesh.h" />
<ClInclude Include="imgui\imconfig.h" />
<ClInclude Include="imgui\imgui.h" />
<ClInclude Include="imgui\imgui_impl_dx9.h" />
<ClInclude Include="imgui\imgui_impl_win32.h" />
<ClInclude Include="imgui\imgui_internal.h" />
<ClInclude Include="imgui\imstb_rectpack.h" />
<ClInclude Include="imgui\imstb_textedit.h" />
<ClInclude Include="imgui\imstb_truetype.h" />
<ClInclude Include="imovehelper.h" />
<ClInclude Include="inetchannel.h" />
<ClInclude Include="inetchannelinfo.h" />
<ClInclude Include="inetmessage.h" />
<ClInclude Include="inetmsghandler.h" />
<ClInclude Include="InputEnums.h" />
<ClInclude Include="interface.h" />
<ClInclude Include="Interfaces.hpp" />
<ClInclude Include="interpolatedvar.h" />
<ClInclude Include="inventory_changer.h" />
<ClInclude Include="IPanel.h" />
<ClInclude Include="ipredictionsystem.h" />
<ClInclude Include="iscenetokenprocessor.h" />
<ClInclude Include="IScheme.h" />
<ClInclude Include="iserverentity.h" />
<ClInclude Include="iservernetworkable.h" />
<ClInclude Include="iserverplugin.h" />
<ClInclude Include="iserverunknown.h" />
<ClInclude Include="ishadowmgr.h" />
<ClInclude Include="ispatialpartition.h" />
<ClInclude Include="istudiorender.h" />
<ClInclude Include="ISurface.h" />
<ClInclude Include="ISystem.h" />
<ClInclude Include="itempents.h" />
<ClInclude Include="item_selection_criteria.h" />
<ClInclude Include="itexture.h" />
<ClInclude Include="itoolentity.h" />
<ClInclude Include="ivdebugoverlay.h" />
<ClInclude Include="IVGUI.h" />
<ClInclude Include="IVguiMatInfo.h" />
<ClInclude Include="IVguiMatInfoVar.h" />
<ClInclude Include="iviewrender.h" />
<ClInclude Include="iviewrender_beams.h" />
<ClInclude Include="ivmodelinfo.h" />
<ClInclude Include="ivmodelrender.h" />
<ClInclude Include="ivrenderview.h" />
<ClInclude Include="jobthread.h" />
<ClInclude Include="KeyBindingMap.h" />
<ClInclude Include="KeyCode.h" />
<ClInclude Include="keyvalues.h" />
<ClInclude Include="l2cache.h" />
<ClInclude Include="Label.h" />
<ClInclude Include="lerp_functions.h" />
<ClInclude Include="lightdesc.h" />
<ClInclude Include="ListPanel.h" />
<ClInclude Include="localflexcontroller.h" />
<ClInclude Include="logging.h" />
<ClInclude Include="MaterialSystemUtil.h" />
<ClInclude Include="mathlib.h" />
<ClInclude Include="math_pfns.h" />
<ClInclude Include="mem.h" />
<ClInclude Include="memalloc.h" />
<ClInclude Include="memdbgoff.h" />
<ClInclude Include="memdbgon.h" />
<ClInclude Include="mempool.h" />
<ClInclude Include="Menu.h" />
<ClInclude Include="Menu.hpp" />
<ClInclude Include="MenuItem.h" />
<ClInclude Include="meshreader.h" />
<ClInclude Include="meshutils.h" />
<ClInclude Include="messagebox.h" />
<ClInclude Include="MessageMap.h" />
<ClInclude Include="minidump.h" />
<ClInclude Include="modelloader.h" />
<ClInclude Include="modes.h" />
<ClInclude Include="MouseCode.h" />
<ClInclude Include="mouthinfo.h" />
<ClInclude Include="netchannel.hpp" />
<ClInclude Include="NetVarManager.hpp" />
<ClInclude Include="netvars.hpp" />
<ClInclude Include="networkvar.h" />
<ClInclude Include="Options.hpp" />
<ClInclude Include="Other.hpp" />
<ClInclude Include="particledraw.h" />
<ClInclude Include="particlemgr.h" />
<ClInclude Include="particles.h" />
<ClInclude Include="ParticleSphereRenderer.h" />
<ClInclude Include="particles_new.h" />
<ClInclude Include="particles_simple.h" />
<ClInclude Include="particle_iterators.h" />
<ClInclude Include="particle_parse.h" />
<ClInclude Include="particle_property.h" />
<ClInclude Include="particle_property_inlines.h" />
<ClInclude Include="particle_util.h" />
<ClInclude Include="PatternScan.hpp" />
<ClInclude Include="pbwrap.hpp" />
<ClInclude Include="PlayerInventory.hpp" />
<ClInclude Include="playernet_vars.h" />
<ClInclude Include="precipitation_shared.h" />
<ClInclude Include="predictableid.h" />
<ClInclude Include="predictable_entity.h" />
<ClInclude Include="predictioncopy.h" />
<ClInclude Include="ProtobuffMessages.h" />
<ClInclude Include="protobuffs.hpp" />
<ClInclude Include="ProtoParse.h" />
<ClInclude Include="proxies.hpp" />
<ClInclude Include="ragdoll.h" />
<ClInclude Include="ragdoll_shared.h" />
<ClInclude Include="rangecheckedvar.h" />
<ClInclude Include="recvproxy.h" />
<ClInclude Include="refcount.h" />
<ClInclude Include="networkstringtabledefs.h" />
<ClInclude Include="Panel.h" />
<ClInclude Include="PanelAnimationVar.h" />
<ClInclude Include="PHandle.h" />
<ClInclude Include="platform.h" />
<ClInclude Include="random.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="RichText.h" />
<ClInclude Include="sceneentity_shared.h" />
<ClInclude Include="sdk_hud_chat.h" />
<ClInclude Include="seemath.h" />
<ClInclude Include="sendproxy.h" />
<ClInclude Include="sequence_Transitioner.h" />
<ClInclude Include="shake.h" />
<ClInclude Include="shareddefs.h" />
<ClInclude Include="shared_classnames.h" />
<ClInclude Include="shattersurfacetypes.h" />
<ClInclude Include="Singleton.hpp" />
<ClInclude Include="SkinChanger.hpp" />
<ClInclude Include="smartptr.h" />
<ClInclude Include="ssemath.h" />
<ClInclude Include="steam.h" />
<ClInclude Include="SteamCommon.h" />
<ClInclude Include="steamtypes.h" />
<ClInclude Include="stringpool.h" />
<ClInclude Include="string_t.h" />
<ClInclude Include="strtools.h" />
<ClInclude Include="studio.h" />
<ClInclude Include="tempentity.h" />
<ClInclude Include="TextEntry.h" />
<ClInclude Include="TextImage.h" />
<ClInclude Include="texture_group_names.h" />
<ClInclude Include="threadtools.h" />
<ClInclude Include="tier1.h" />
<ClInclude Include="tier2.h" />
<ClInclude Include="tier2_logging.h" />
<ClInclude Include="tier3.h" />
<ClInclude Include="timedevent.h" />
<ClInclude Include="timeutils.h" />
<ClInclude Include="ToggleButton.h" />
<ClInclude Include="Tooltip.h" />
<ClInclude Include="touchlink.h" />
<ClInclude Include="trace.h" />
<ClInclude Include="tslist.h" />
<ClInclude Include="uniqueid.h" />
<ClInclude Include="usercmd.h" />
<ClInclude Include="userid.h" />
<ClInclude Include="utlblockmemory.h" />
<ClInclude Include="utlbuffer.h" />
<ClInclude Include="utldict.h" />
<ClInclude Include="utlenvelope.h" />
<ClInclude Include="utlfixedmemory.h" />
<ClInclude Include="utlflags.h" />
<ClInclude Include="utlhandletable.h" />
<ClInclude Include="utlhash.h" />
<ClInclude Include="utlintrusivelist.h" />
<ClInclude Include="utllinkedlist.h" />
<ClInclude Include="utlmap.h" />
<ClInclude Include="utlmemory.h" />
<ClInclude Include="utlobjectreference.h" />
<ClInclude Include="utlpriorityqueue.h" />
<ClInclude Include="utlqueue.h" />
<ClInclude Include="utlrbtree.h" />
<ClInclude Include="utlsoacontainer.h" />
<ClInclude Include="utlstack.h" />
<ClInclude Include="UtlStringMap.h" />
<ClInclude Include="utltshash.h" />
<ClInclude Include="UtlSortVector.h" />
<ClInclude Include="utlstring.h" />
<ClInclude Include="utlsymbol.h" />
<ClInclude Include="utlsymbollarge.h" />
<ClInclude Include="utlvector.h" />
<ClInclude Include="valve_minmax_on.h" />
<ClInclude Include="valve_off.h" />
<ClInclude Include="valve_on.h" />
<ClInclude Include="vcollide.h" />
<ClInclude Include="vcrmode.h" />
<ClInclude Include="vector.h" />
<ClInclude Include="vector2d.h" />
<ClInclude Include="vector4d.h" />
<ClInclude Include="vertexcolor.h" />
<ClInclude Include="VGUI.h" />
<ClInclude Include="vgui_basepanel.h" />
<ClInclude Include="viewrender.h" />
<ClInclude Include="view_shared.h" />
<ClInclude Include="vmatrix.h" />
<ClInclude Include="VMT.hpp" />
<ClInclude Include="vmt_smart_hook.hpp" />
<ClInclude Include="volumeculler.h" />
<ClInclude Include="vphysics_interface.h" />
<ClInclude Include="vpkparser.h" />
<ClInclude Include="vplane.h" />
<ClInclude Include="vprof.h" />
<ClInclude Include="vprof_sn.h" />
<ClInclude Include="vprof_telemetry.h" />
<ClInclude Include="vstdlib.h" />
<ClInclude Include="vtf.h" />
<ClInclude Include="wchartypes.h" />
<ClInclude Include="weapon_parse.h" />
<ClInclude Include="win32consoleio.h" />
<ClInclude Include="xboxstubs.h" />
<ClInclude Include="XorStr.hpp" />
<ClInclude Include="zip_uncompressed.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ConVars.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="imgui\imgui.cpp" />
<ClCompile Include="imgui\imgui_demo.cpp" />
<ClCompile Include="imgui\imgui_draw.cpp" />
<ClCompile Include="imgui\imgui_impl_dx9.cpp" />
<ClCompile Include="imgui\imgui_impl_win32.cpp" />
<ClCompile Include="imgui\imgui_tables.cpp" />
<ClCompile Include="imgui\imgui_widgets.cpp" />
<ClCompile Include="Interfaces.cpp" />
<ClCompile Include="KeyValues.cpp" />
<ClCompile Include="NetVarManager.cpp" />
<ClCompile Include="netvars.cpp" />
<ClCompile Include="Other.cpp" />
<ClCompile Include="PatternScan.cpp" />
<ClCompile Include="PlayerInventory.cpp" />
<ClCompile Include="protobuffs.cpp" />
<ClCompile Include="Skinchanger.cpp" />
<ClCompile Include="textinputcombobox.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SpyCustom.rc" />
</ItemGroup>
<ItemGroup>
<Media Include="cod.wav">
<DeploymentContent>true</DeploymentContent>
</Media>
<Media Include="crit.wav">
<DeploymentContent>true</DeploymentContent>
</Media>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

75
SpyCustom/VMT.hpp Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#include <cstdint>
#include <Windows.h>
#include <iostream>
class VMTHook
{
public:
VMTHook(void* classptr)
{
this->class_pointer = reinterpret_cast<uintptr_t**>(classptr);
int table_size = 0;
while (reinterpret_cast<uintptr_t*>(*this->class_pointer)[table_size])
table_size++;
original_pointer = *this->class_pointer;
new_table_pointer = new uintptr_t[sizeof(uintptr_t) * table_size];
memcpy(new_table_pointer, original_pointer, sizeof(uintptr_t) * table_size);
}
~VMTHook()
{
RestoreOldTable();
delete original_pointer;
delete new_table_pointer;
}
void SwapPointer(size_t index, void* new_function)
{
#ifdef DEBUG
printf("Swapping pointer 0x%X to 0x%X\n", new_table_pointer[index], reinterpret_cast<uintptr_t>(new_function));
#endif
new_table_pointer[index] = reinterpret_cast<uintptr_t>(new_function);
#ifdef DEBUG
printf("Swapped pointer!\n");
#endif
}
void ApplyNewTable()
{
#ifdef DEBUG
printf("Applying new table... (0x%X to 0x%X)\n", reinterpret_cast<uintptr_t>(*class_pointer), reinterpret_cast<uintptr_t>(new_table_pointer));
#endif
*class_pointer = new_table_pointer;
#ifdef DEBUG
printf("New table applyed!\n");
#endif
}
void RestoreOldTable()
{
#ifdef DEBUG
printf("Restoring old table... (0x%X to 0x%X)\n", reinterpret_cast<uintptr_t>(*class_pointer), reinterpret_cast<uintptr_t>(original_pointer));
#endif
*class_pointer = original_pointer;
#ifdef DEBUG
printf("Old table restored!\n");
#endif
}
template<typename T>
T GetOriginal(size_t index)
{
return reinterpret_cast<T>(original_pointer[index]);
}
private:
uintptr_t** class_pointer = nullptr;
uintptr_t* original_pointer = nullptr;
uintptr_t* new_table_pointer = nullptr;
};

109
SpyCustom/XorStr.hpp Normal file
View File

@ -0,0 +1,109 @@
#pragma once
#include <string>
#include <array>
#include <cstdarg>
#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }
BEGIN_NAMESPACE(XorCompileTime)
constexpr auto time = __TIME__;
constexpr auto seed = static_cast<int>(time[7]) + static_cast<int>(time[6]) * 10 + static_cast<int>(time[4]) * 60 + static_cast<int>(time[3]) * 600 + static_cast<int>(time[1]) * 3600 + static_cast<int>(time[0]) * 36000;
template < int N >
struct RandomGenerator {
private:
static constexpr unsigned a = 16807;
static constexpr unsigned m = 2147483647;
static constexpr unsigned s = RandomGenerator< N - 1 >::value;
static constexpr unsigned lo = a * (s & 0xFFFF);
static constexpr unsigned hi = a * (s >> 16);
static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16);
static constexpr unsigned hi2 = hi >> 15;
static constexpr unsigned lo3 = lo2 + hi;
public:
static constexpr unsigned max = m;
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};
template <>
struct RandomGenerator< 0 > {
static constexpr unsigned value = seed;
};
template < int N, int M >
struct RandomInt {
static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};
template < int N >
struct RandomChar {
static const char value = static_cast<char>(1 + RandomInt< N, 0x7F - 1 >::value);
};
template < size_t N, int K >
struct XorString {
private:
const char _key;
std::array< char, N + 1 > _encrypted;
constexpr char enc(char c) const {
return c ^ _key;
}
char dec(char c) const {
return c ^ _key;
}
public:
template < size_t... Is >
constexpr __forceinline XorString(const char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... } {
}
__forceinline decltype(auto) decrypt(void) {
for (size_t i = 0; i < N; ++i) {
_encrypted[i] = dec(_encrypted[i]);
}
_encrypted[N] = '\0';
return _encrypted.data();
}
};
static auto w_printf = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_printf_s = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_sprintf = [](char* buf, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
};
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf_s(buf, buf_size, fmt, args);
va_end(args);
};
#ifdef NDEBUG
#define XorStr( s ) ( XorCompileTime::XorString< sizeof( s ) - 1, __COUNTER__ >( s, std::make_index_sequence< sizeof( s ) - 1>() ).decrypt() )
#else
#define XorStr( s ) ( s )
#endif
END_NAMESPACE

BIN
SpyCustom/cheat1.aps Normal file

Binary file not shown.

BIN
SpyCustom/cod.wav Normal file

Binary file not shown.

BIN
SpyCustom/crit.wav Normal file

Binary file not shown.

55
SpyCustom/csgosdk.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include <iostream>
#include <windows.h>
#include <string>
#include "sdk/icliententitylist.h"
#include "sdk/CGameUI.h"
#include "sdk/GameEventManager.h"
#include "sdk/cdll_int.h"
#include "sdk/ISurface.h"
#include "sdk/IEngineVgui.h"
#include "sdk/ivmodelinfo.h"
#include "sdk/idatacache.h"
#include "sdk/ILocalize.h"
#include "sdk/Panel.h"
#include "sdk/IGameUI.h"
#include "sdk/dt_recv.h"
#include "sdk/client_class.h"
#include "sdk/enginetrace.h"
#include "sdk/gameconsole.h"
#include "sdk/ivrenderview.h"
#include "sdk/ivdebugoverlay.h"
#include "sdk/vphysics_interface.h"
#include "sdk/iefx.h"
#include "sdk/iclient.h"
#include "sdk/icliententity.h"
#include "sdk/globalvars_base.h"
#include "sdk/cmodel.h"
#include "sdk/IInput.h"
#include "sdk/IEffects.h"
#include "sdk/iviewrender_beams.h"
#include "sdk/sdk_hud_chat.h"
#include "sdk/fx.h"
#include "sdk/c_input.h"
#include "EventListener.hpp"
#include "VMT.hpp"
#include "PatternScan.hpp"
#include "PlayerInventory.hpp"

561
SpyCustom/detours.h Normal file
View File

@ -0,0 +1,561 @@
#pragma once
#ifndef _DETOURS_H_
#define _DETOURS_H_
#pragma comment(lib, "detours")
#ifndef GUID_DEFINED
#define GUID_DEFINED
typedef struct _GUID
{
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[ 8 ];
} GUID;
#endif
#if defined(__cplusplus)
#ifndef _REFGUID_DEFINED
#define _REFGUID_DEFINED
#define REFGUID const GUID &
#endif
#else
#ifndef _REFGUID_DEFINED
#define _REFGUID_DEFINED
#define REFGUID const GUID * const
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define DETOUR_INSTRUCTION_TARGET_NONE ((PBYTE)0)
#define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PBYTE)~0ul)
#define DETOUR_TRAMPOLINE_SIZE 32
#define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444
#define DETOUR_TRAMPOLINE(trampoline,target) \
static PVOID __fastcall _Detours_GetVA_##target(VOID) \
{ \
return &target; \
} \
\
__declspec(naked) trampoline \
{ \
__asm { nop };\
__asm { nop };\
__asm { call _Detours_GetVA_##target };\
__asm { jmp eax };\
__asm { ret };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
}
#define DETOUR_TRAMPOLINE_EMPTY(trampoline) \
__declspec(naked) trampoline \
{ \
__asm { nop };\
__asm { nop };\
__asm { xor eax, eax };\
__asm { mov eax, [eax] };\
__asm { ret };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
__asm { nop };\
}
#pragma pack(push, 8)
typedef struct _DETOUR_SECTION_HEADER
{
DWORD cbHeaderSize;
DWORD nSignature;
DWORD nDataOffset;
DWORD cbDataSize;
DWORD nOriginalImportVirtualAddress;
DWORD nOriginalImportSize;
DWORD nOriginalBoundImportVirtualAddress;
DWORD nOriginalBoundImportSize;
DWORD nOriginalIatVirtualAddress;
DWORD nOriginalIatSize;
DWORD nOriginalSizeOfImage;
DWORD nReserve;
} DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER;
typedef struct _DETOUR_SECTION_RECORD
{
DWORD cbBytes;
DWORD nReserved;
GUID guid;
} DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD;
#pragma pack(pop)
#define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \
{ \
sizeof(DETOUR_SECTION_HEADER),\
DETOUR_SECTION_HEADER_SIGNATURE,\
sizeof(DETOUR_SECTION_HEADER),\
(cbSectionSize),\
\
0,\
0,\
0,\
0,\
\
0,\
0,\
0,\
0,\
}
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(PVOID pContext,
PCHAR pszFile,
PCHAR *ppszOutFile);
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)(PVOID pContext,
PCHAR pszOrigFile,
PCHAR pszFile,
PCHAR *ppszOutFile);
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)(PVOID pContext,
DWORD nOrdinal,
PCHAR pszOrigSymbol,
PCHAR pszSymbol,
PCHAR *ppszOutSymbol);
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FINAL_CALLBACK)(PVOID pContext);
typedef BOOL (CALLBACK *PF_DETOUR_BINARY_EXPORT_CALLBACK)(PVOID pContext,
DWORD nOrdinal,
PCHAR pszName,
PBYTE pbCode);
typedef VOID * PDETOUR_BINARY;
typedef VOID * PDETOUR_LOADED_BINARY;
PBYTE WINAPI DetourFunction(PBYTE pbTargetFunction,
PBYTE pbDetourFunction);
BOOL WINAPI DetourFunctionWithEmptyTrampoline(PBYTE pbTrampoline,
PBYTE pbTarget,
PBYTE pbDetour);
BOOL WINAPI DetourFunctionWithEmptyTrampolineEx(PBYTE pbTrampoline,
PBYTE pbTarget,
PBYTE pbDetour,
PBYTE *ppbRealTrampoline,
PBYTE *ppbRealTarget,
PBYTE *ppbRealDetour);
BOOL WINAPI DetourFunctionWithTrampoline(PBYTE pbTrampoline,
PBYTE pbDetour);
BOOL WINAPI DetourFunctionWithTrampolineEx(PBYTE pbTrampoline,
PBYTE pbDetour,
PBYTE *ppbRealTrampoline,
PBYTE *ppbRealTarget);
BOOL WINAPI DetourRemove(PBYTE pbTrampoline, PBYTE pbDetour);
PBYTE WINAPI DetourFindFunction(PCHAR pszModule, PCHAR pszFunction);
PBYTE WINAPI DetourGetFinalCode(PBYTE pbCode, BOOL fSkipJmp);
PBYTE WINAPI DetourCopyInstruction(PBYTE pbDst, PBYTE pbSrc, PBYTE *ppbTarget);
PBYTE WINAPI DetourCopyInstructionEx(PBYTE pbDst,
PBYTE pbSrc,
PBYTE *ppbTarget,
LONG *plExtra);
HMODULE WINAPI DetourEnumerateModules(HMODULE hModuleLast);
PBYTE WINAPI DetourGetEntryPoint(HMODULE hModule);
BOOL WINAPI DetourEnumerateExports(HMODULE hModule,
PVOID pContext,
PF_DETOUR_BINARY_EXPORT_CALLBACK pfExport);
PBYTE WINAPI DetourFindPayload(HMODULE hModule, REFGUID rguid, DWORD *pcbData);
DWORD WINAPI DetourGetSizeOfPayloads(HMODULE hModule);
BOOL WINAPI DetourBinaryBindA(PCHAR pszFile, PCHAR pszDll, PCHAR pszPath);
BOOL WINAPI DetourBinaryBindW(PWCHAR pwzFile, PWCHAR pwzDll, PWCHAR pwzPath);
#ifdef UNICODE
#define DetourBinaryBind DetourBinaryBindW
#else
#define DetourBinaryBind DetourBinaryBindA
#endif
PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile);
PBYTE WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pBinary,
GUID *pGuid,
DWORD *pcbData,
DWORD *pnIterator);
PBYTE WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pBinary,
REFGUID rguid,
DWORD *pcbData);
PBYTE WINAPI DetourBinarySetPayload(PDETOUR_BINARY pBinary,
REFGUID rguid,
PBYTE pbData,
DWORD cbData);
BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pBinary, REFGUID rguid);
BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pBinary);
BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pBinary);
BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pBinary,
PVOID pContext,
PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway,
PF_DETOUR_BINARY_FILE_CALLBACK pfFile,
PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol,
PF_DETOUR_BINARY_FINAL_CALLBACK pfFinal);
BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pBinary, HANDLE hFile);
BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pBinary);
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
DetourFirstChanceExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelFilter);
typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)
(LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)
(LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);
BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
LPCSTR lpDllName,
PDETOUR_CREATE_PROCESS_ROUTINEA
pfCreateProcessA);
BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
LPCWSTR lpDllName,
PDETOUR_CREATE_PROCESS_ROUTINEW
pfCreateProcessW);
#ifdef UNICODE
#define DetourCreateProcessWithDll DetourCreateProcessWithDllW
#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW
#else
#define DetourCreateProcessWithDll DetourCreateProcessWithDllA
#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA
#endif
BOOL WINAPI DetourContinueProcessWithDllA(HANDLE hProcess, LPCSTR lpDllName);
BOOL WINAPI DetourContinueProcessWithDllW(HANDLE hProcess, LPCWSTR lpDllName);
#ifdef UNICODE
#define DetourContinueProcessWithDll DetourContinueProcessWithDllW
#else
#define DetourContinueProcessWithDll DetourContinueProcessWithDllA
#endif
#ifdef __cplusplus
}
#endif
#define ContinueProcessWithDll DetourContinueProcessWithDll
#define ContinueProcessWithDllA DetourContinueProcessWithDllA
#define ContinueProcessWithDllW DetourContinueProcessWithDllW
#define CreateProcessWithDll DetourCreateProcessWithDll
#define CreateProcessWithDllA DetourCreateProcessWithDllA
#define CreateProcessWithDllW DetourCreateProcessWithDllW
#define DETOUR_TRAMPOLINE_WO_TARGET DETOUR_TRAMPOLINE_EMPTY
#define DetourBinaryPurgePayload DetourBinaryPurgePayloads
#define DetourEnumerateExportsForInstance DetourEnumerateExports
#define DetourEnumerateInstances DetourEnumerateModules
#define DetourFindEntryPointForInstance DetourGetEntryPoint
#define DetourFindFinalCode DetourGetFinalCode
#define DetourFindPayloadInBinary DetourFindPayload
#define DetourGetSizeOfBinary DetourGetSizeOfPayloads
#define DetourRemoveWithTrampoline DetourRemove
#define PCREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINE
#define PCREATE_PROCESS_ROUTINEA PDETOUR_CREATE_PROCESS_ROUTINEA
#define PCREATE_PROCESS_ROUTINEW PDETOUR_CREATE_PROCESS_ROUTINEW
#ifdef __cplusplus
#ifdef DETOURS_INTERNAL
#ifdef IMAGEAPI
typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion);
typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess,
IN LPSTR UserSearchPath,
IN BOOL fInvadeProcess);
typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions);
typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
typedef BOOL (NTAPI *PF_SymLoadModule)(IN HANDLE hProcess,
IN HANDLE hFile,
IN PSTR ImageName,
IN PSTR ModuleName,
IN DWORD BaseOfDll,
IN DWORD SizeOfDll);
typedef BOOL (NTAPI *PF_SymGetModuleInfo)(IN HANDLE hProcess,
IN DWORD dwAddr,
OUT PIMAGEHLP_MODULE ModuleInfo);
typedef BOOL (NTAPI *PF_SymGetSymFromName)(IN HANDLE hProcess,
IN LPSTR Name,
OUT PIMAGEHLP_SYMBOL Symbol);
typedef BOOL (NTAPI *PF_BindImage)(IN LPSTR pszImageName,
IN LPSTR pszDllPath,
IN LPSTR pszSymbolPath);
typedef struct _DETOUR_SYM_INFO
{
HANDLE hProcess;
HMODULE hImageHlp;
PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx;
PF_SymInitialize pfSymInitialize;
PF_SymSetOptions pfSymSetOptions;
PF_SymGetOptions pfSymGetOptions;
PF_SymLoadModule pfSymLoadModule;
PF_SymGetModuleInfo pfSymGetModuleInfo;
PF_SymGetSymFromName pfSymGetSymFromName;
PF_BindImage pfBindImage;
} DETOUR_SYM_INFO, *PDETOUR_SYM_INFO;
PDETOUR_SYM_INFO DetourLoadImageHlp(VOID);
#endif
class CDetourEnableWriteOnCodePage
{
public:
CDetourEnableWriteOnCodePage(PBYTE pbCode, LONG cbCode = DETOUR_TRAMPOLINE_SIZE)
{
m_pbCode = pbCode;
m_cbCode = cbCode;
m_dwOldPerm = 0;
m_hProcess = GetCurrentProcess();
if (m_pbCode && m_cbCode) {
if (!FlushInstructionCache(m_hProcess, pbCode, cbCode)) {
return;
}
if (!VirtualProtect(pbCode,
cbCode,
PAGE_EXECUTE_READWRITE,
&m_dwOldPerm)) {
return;
}
}
}
~CDetourEnableWriteOnCodePage()
{
if (m_dwOldPerm && m_pbCode && m_cbCode) {
DWORD dwTemp = 0;
if (!FlushInstructionCache(m_hProcess, m_pbCode, m_cbCode)) {
return;
}
if (!VirtualProtect(m_pbCode, m_cbCode, m_dwOldPerm, &dwTemp)) {
return;
}
}
}
BOOL SetPermission(DWORD dwPerms)
{
if (m_dwOldPerm && m_pbCode && m_cbCode) {
m_dwOldPerm = dwPerms;
return TRUE;
}
return FALSE;
}
BOOL IsValid(VOID)
{
return m_pbCode && m_cbCode && m_dwOldPerm;
}
private:
HANDLE m_hProcess;
PBYTE m_pbCode;
LONG m_cbCode;
DWORD m_dwOldPerm;
};
inline PBYTE DetourGenMovEax(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xB8;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEbx(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBB;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEcx(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xB9;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEdx(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBA;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEsi(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBE;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEdi(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBF;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEbp(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBD;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenMovEsp(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0xBC;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenPush(PBYTE pbCode, UINT32 nValue)
{
*pbCode++ = 0x68;
*((UINT32*&)pbCode)++ = nValue;
return pbCode;
}
inline PBYTE DetourGenPushad(PBYTE pbCode)
{
*pbCode++ = 0x60;
return pbCode;
}
inline PBYTE DetourGenPopad(PBYTE pbCode)
{
*pbCode++ = 0x61;
return pbCode;
}
inline PBYTE DetourGenJmp(PBYTE pbCode, PBYTE pbJmpDst, PBYTE pbJmpSrc = 0)
{
if (pbJmpSrc == 0) {
pbJmpSrc = pbCode;
}
*pbCode++ = 0xE9;
*((INT32*&)pbCode)++ = pbJmpDst - (pbJmpSrc + 5);
return pbCode;
}
inline PBYTE DetourGenCall(PBYTE pbCode, PBYTE pbJmpDst, PBYTE pbJmpSrc = 0)
{
if (pbJmpSrc == 0) {
pbJmpSrc = pbCode;
}
*pbCode++ = 0xE8;
*((INT32*&)pbCode)++ = pbJmpDst - (pbJmpSrc + 5);
return pbCode;
}
inline PBYTE DetourGenBreak(PBYTE pbCode)
{
*pbCode++ = 0xcc;
return pbCode;
}
inline PBYTE DetourGenRet(PBYTE pbCode)
{
*pbCode++ = 0xc3;
return pbCode;
}
inline PBYTE DetourGenNop(PBYTE pbCode)
{
*pbCode++ = 0x90;
return pbCode;
}
#endif DETOURS_INTERAL
#endif
#endif

BIN
SpyCustom/detours.lib Normal file

Binary file not shown.

389
SpyCustom/dllmain.cpp Normal file
View File

@ -0,0 +1,389 @@
#pragma once
#include <iostream>
#include "Interfaces.hpp"
#include "NetVarManager.hpp"
#include "VMT.hpp"
#include "EventListener.hpp"
#include <string>
#include "detours.h"
#pragma comment(lib, "detours.lib")
#include "imgui/imgui.h"
#include "imgui/imgui_impl_dx9.h"
#include "imgui/imgui_impl_win32.h"
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#include "Other.hpp"
#include "sdk/c_baseentity.h"
#include "PatternScan.hpp"
#include "SkinChanger.hpp"
#include "Config.hpp"
#include "protobuffs.hpp"
using namespace std;
#include "proxies.hpp"
#include "netchannel.hpp"
#include "Hooks.hpp"
#include "Menu.hpp"
#include "SkinChanger.hpp"
void OnLevelInit()
{
if (g_Options.skyboxactive)
{
iff.g_pCVar->FindVar("sv_skyname")->SetValue((char*)g_Options.skyboxtemp.value.get());
iff.g_pCVar->FindVar("r_3dsky")->SetValue(false);
}
if (g_Options.fogactive)
{
iff.g_pCVar->FindVar("fog_override")->SetValue(true);
iff.g_pCVar->FindVar("fog_color")->SetValue(
std::string("").
append(std::to_string(g_Options.fogcolor.value->r * 255)).
append(" ").
append(std::to_string(g_Options.fogcolor.value->g * 255)).
append(" ").
append(std::to_string(g_Options.fogcolor.value->b * 255)).
append(" ").c_str()
);
iff.g_pCVar->FindVar("fog_colorskybox")->SetValue(
std::string("").
append(std::to_string(g_Options.fogcolor.value->r * 255)).
append(" ").
append(std::to_string(g_Options.fogcolor.value->g * 255)).
append(" ").
append(std::to_string(g_Options.fogcolor.value->b * 255)).
append(" ").c_str()
);
iff.g_pCVar->FindVar("fog_maxdensity")->SetValue(g_Options.fogdensity);
iff.g_pCVar->FindVar("fog_maxdensityskybox")->SetValue(g_Options.fogdensity);
iff.g_pCVar->FindVar("fog_start")->SetValue(g_Options.fogstart);
iff.g_pCVar->FindVar("fog_startskybox")->SetValue(g_Options.fogstart);
iff.g_pCVar->FindVar("fog_end")->SetValue(g_Options.fogend);
iff.g_pCVar->FindVar("fog_endskybox")->SetValue(g_Options.fogend);
}
iff.g_pCVar->FindVar("r_rainlength")->SetValue(*g_Options.rainlength);
iff.g_pCVar->FindVar("r_rainspeed")->SetValue(*g_Options.rainspeed);
iff.g_pCVar->FindVar("r_rainradius")->SetValue(*g_Options.rainradius);
iff.g_pCVar->FindVar("cl_windspeed")->SetValue(*g_Options.windspeed);
iff.g_pCVar->FindVar("r_rainwidth")->SetValue(*g_Options.rainwidth);
iff.g_pCVar->FindVar("r_RainSideVel")->SetValue(*g_Options.rainsidevel);
iff.g_pCVar->FindVar("r_rainalpha")->SetValue(*g_Options.rainalpha);
iff.g_pCVar->FindVar("mat_force_tonemap_scale")->SetValue(g_Options.tonemapscale);
colorWorld();
if (g_Options.prime)
{
DWORD old_protect;
VirtualProtect(iff.prime, 5, PAGE_EXECUTE_READWRITE, &old_protect);
char patch[] = { 0x31, 0xC0, 0xFE, 0xC0, 0xC3 };
memcpy(iff.prime, patch, 5);
VirtualProtect(iff.prime, 5, old_protect, nullptr);
}
}
void OnLoadCfg()
{
for (int i = 0; i < 5; i++)
{
if (g_Options.customtextures.value->arr[i].texturelink) {
g_Options.customtextures.value->arr[i].texturelink = CreateMaterial(
string(g_Options.customtextures.value->arr[i].Name),
string(g_Options.customtextures.value->arr[i].keyvalue));
opt.dmeitems.at(i) = g_Options.customtextures.value->arr[i].Preview;
}
}
OnLevelInit();
const auto& paintkitMap = itemSystem()->getItemSchema()->paintKits;
for (int n = 0; n < g_Options.weapons.value->weaponzcount; n++)
{
CPaintKit* pk = (CPaintKit*)paintkitMap.memory[g_Options.weapons.value->arr[n].skinidc].value;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].link = (DWORD)pk;
pk->rarity = g_Options.weapons.value->arr[n].rarity;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].rarity = g_Options.weapons.value->arr[n].rarity;
pk->pearlescent = g_Options.weapons.value->arr[n].pearl;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].pearl = g_Options.weapons.value->arr[n].pearl;
pk->color1 = g_Options.weapons.value->arr[n].color1;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].color1 = g_Options.weapons.value->arr[n].color1;
pk->color2 = g_Options.weapons.value->arr[n].color2;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].color2 = g_Options.weapons.value->arr[n].color2;
pk->color3 = g_Options.weapons.value->arr[n].color3;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].color3 = g_Options.weapons.value->arr[n].color3;
pk->color4 = g_Options.weapons.value->arr[n].color4;
opt.sc_skins[g_Options.weapons.value->arr[n].skinidc].color4 = g_Options.weapons.value->arr[n].color4;
}
iff.g_pClientState->ForceFullUpdate();
opt.needupdate = 1;
ProtoFeatures.SendClientHello();
ProtoFeatures.SendMatchmakingClient2GCHello();
opt.loading = 0;
}
DWORD WINAPI HackThread(HMODULE hModule)
{
while (!GetModuleHandleA("serverbrowser.dll"))
Sleep(1000);
#ifdef DEBUG
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
printf("Cheat launched\n");
#endif
iff.Init();
opt.hModuleGlobal = hModule;
NetvarSys::Get().Initialize();
DMEHook = new VMTHook(iff.g_pMdlRender);
DMEHook->SwapPointer(21, reinterpret_cast<void*>(DrawModelExecute));
DMEHook->ApplyNewTable();
D3DHook = new VMTHook(iff.g_pD3DDevice9);
D3DHook->SwapPointer(42, reinterpret_cast<void*>(hkEndScene));
D3DHook->ApplyNewTable();
GameEventManagerHook = new VMTHook(iff.g_pGameEvents);
GameEventManagerHook->SwapPointer(9, reinterpret_cast<void*>(hkFireEventClientSide));
GameEventManagerHook->ApplyNewTable();
ProtoHook = new VMTHook(iff.g_SteamGameCoordinator);
ProtoHook->SwapPointer(0, reinterpret_cast<void*>(hkGCSendMessage));
ProtoHook->SwapPointer(2, reinterpret_cast<void*>(hkGCRetrieveMessage));
ProtoHook->ApplyNewTable();
CacheHook = new VMTHook(iff.g_pMdlCache);
CacheHook->SwapPointer(10, reinterpret_cast<void*>(hkFindMDL));
CacheHook->ApplyNewTable();
SoundHook = new VMTHook(iff.g_pEngineSound);
SoundHook->SwapPointer(5, reinterpret_cast<void*>(hkEmitSound1));
SoundHook->ApplyNewTable();
VGUISurfHook = new VMTHook(iff.g_pVGuiSurface);
VGUISurfHook->SwapPointer(67, reinterpret_cast<void*>(hkLockCursor));
VGUISurfHook->ApplyNewTable();
ClientModeHook = new VMTHook(iff.g_ClientMode);
ClientModeHook->SwapPointer(44, reinterpret_cast<void*>(hkdoPostScreenEffects));
ClientModeHook->ApplyNewTable();
FileSystemHook = new VMTHook(iff.g_pFullFileSystem);
FileSystemHook->SwapPointer(101, reinterpret_cast<void*>(hkGetUnverifiedFileHashes));
FileSystemHook->ApplyNewTable();
InitSkinChanger();
Sleep(1000);
ClientHook = new VMTHook(iff.g_pClient);
ClientHook->SwapPointer(37, reinterpret_cast<void*>(hkFrameStageNotify));
ClientHook->ApplyNewTable();
iff.g_pGameConsole->Clear();
EventListener* eventListener = new EventListener();
Color color = { 255,255,0,255 };
iff.g_pCVar->ConsoleColorPrintf(color, "zdarova\n");
ConVar* sv_skyname = iff.g_pCVar->FindVar("sv_skyname");
int proxyindex = 0;
for (ClientClass* pClass = iff.g_pClient->GetAllClasses(); pClass; pClass = pClass->m_pNext) {
if (!strcmp(pClass->m_pNetworkName, "CBaseViewModel")) {
RecvTable* pClassTable = pClass->m_pRecvTable;
for (int nIndex = 0; nIndex < pClassTable->m_nProps; nIndex++) {
RecvProp* pProp = &pClassTable->m_pProps[nIndex];
if (!pProp || strcmp(pProp->m_pVarName, "m_nSequence"))
continue;
proxyindex = nIndex;
fnSequenceProxyFn = pProp->m_ProxyFn;
pProp->m_ProxyFn = (RecvVarProxyFn)SetViewModelSequence;
break;
}
break;
}
}
ifstream loadcfg("seaside_autoload");
if (loadcfg.is_open())
{
#ifdef DEBUG
printf("autoload found\n");
#endif
opt.autoload = true;
Sleep(1000);
Config::Get().Load();
loadcfg.close();
}
else
{
#ifdef DEBUG
printf("autoload NOT found, creatin mat\n");
#endif
opt.autoload = false;
g_Options.customtextures.value->arr[0].texturelink = CreateMaterial(
string(g_Options.customtextures.value->arr[0].Name),
string(g_Options.customtextures.value->arr[0].keyvalue));
}
while (!opt.unhook)
{
if (GetAsyncKeyState(VK_INSERT) & 1)
{
opt.show = !opt.show;
#ifdef DEBUG
cout << "Show " << opt.show << endl;
#endif
if (!opt.show)
iff.g_pInputSystem->EnableInput(1);
else
iff.g_pInputSystem->EnableInput(0);
}
if (!opt.netchannedlhooked && iff.g_pEngineClient->IsConnected())
HookNetchannel();
if (iff.g_pEngineClient->IsInGame()) {
if (!*g_Options.dme_gettextures)
{
IMaterial* mats[1];
for (int i = 5; i < g_Options.materials.value->itemcount; i++) {
int mdlindex = iff.g_pMdlInfo->GetModelIndex(g_Options.models.value->arr[i - 2].vmodel_orig);
if (mdlindex != -1) {
model_t* pModel = (model_t*)iff.g_pMdlInfo->GetModel(mdlindex);
iff.g_pMdlInfo->GetModelMaterials(pModel, 1, mats);
const char* matname = mats[0]->GetName();
if (g_Options.materials.value->arr[i].texture[0] == 0x0)
strcpy(g_Options.materials.value->arr[i].texture, matname);
if (g_Options.materials.value->arr[i].texture_temp[0] == 0x0)
strcpy(g_Options.materials.value->arr[i].texture_temp, matname);
}
}
#ifdef DEBUG
printf("Model materials dumped\n");
#endif
*g_Options.dme_gettextures = true;
}
}
else
{
opt.disconnected = 1;
}
Sleep(20);
}
opt.show = false;
for (ClientClass* pClass = iff.g_pClient->GetAllClasses(); pClass; pClass = pClass->m_pNext) {
if (!strcmp(pClass->m_pNetworkName, "CBaseViewModel")) {
RecvTable* pClassTable = pClass->m_pRecvTable;
RecvProp* pProp = &pClassTable->m_pProps[proxyindex];
pProp->m_ProxyFn = fnSequenceProxyFn;
}
}
if (iff.g_pEngineClient->IsConnected()) {
iff.g_pClientState->ForceFullUpdate();
}
iff.g_pInputSystem->EnableInput(1);
iff.g_pCVar->FindVar("r_3dsky")->SetValue(true);
sv_skyname->m_nFlags &= FCVAR_CHEAT;
sv_skyname->SetValue("sky_urb01");
iff.g_pCVar->FindVar("fog_override")->SetValue(0);
iff.g_pCVar->FindVar("mat_force_tonemap_scale")->SetValue(0.0f);
DMEHook->RestoreOldTable();
D3DHook->RestoreOldTable();
ClientHook->RestoreOldTable();
GameEventManagerHook->RestoreOldTable();
ProtoHook->RestoreOldTable();
CacheHook->RestoreOldTable();
SoundHook->RestoreOldTable();
VGUISurfHook->RestoreOldTable();
ClientModeHook->RestoreOldTable();
FileSystemHook->RestoreOldTable();
if (opt.netchannedlhooked)
DetourRemove(reinterpret_cast<BYTE*>(oShutdown), reinterpret_cast<BYTE*>(hkShutdown));
ImGui_ImplDX9_Shutdown();
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)oWndProc);
delete eventListener;
ProtoFeatures.SendClientHello();
ProtoFeatures.SendMatchmakingClient2GCHello();
ProtoFeatures.SendClientGcRankUpdate();
if (g_Options.prime)
{
DWORD old_protect;
VirtualProtect(iff.prime, 5, PAGE_EXECUTE_READWRITE, &old_protect);
memcpy(iff.prime, iff.oldprime, 5);
VirtualProtect(iff.prime, 5, old_protect, nullptr);
}
Sleep(1000);
#ifdef DEBUG
if (f) fclose(f);
FreeConsole();
#endif
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
HANDLE hdl = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)HackThread, hModule, 0, nullptr);
if (hdl) CloseHandle(hdl);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

118
SpyCustom/imgui/imconfig.h Normal file
View File

@ -0,0 +1,118 @@
//-----------------------------------------------------------------------------
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
//-----------------------------------------------------------------------------
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
//-----------------------------------------------------------------------------
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
//-----------------------------------------------------------------------------
#pragma once
//---- Define assertion handler. Defaults to calling assert().
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using dear imgui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
//---- Disable all of Dear ImGui or don't implement standard windows.
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
//---- Don't implement some functions to reduce linkage requirements.
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//---- Include imgui_user.h at the end of imgui.h as a convenience
//#define IMGUI_INCLUDE_IMGUI_USER_H
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
//#define IMGUI_USE_BGRA_PACKED_COLOR
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
//#define IMGUI_USE_WCHAR32
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
// #define IMGUI_USE_STB_SPRINTF
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE
//---- Use stb_truetype to build and rasterize the font atlas (default)
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
//#define IMGUI_ENABLE_STB_TRUETYPE
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
/*
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
//#define ImDrawIdx unsigned int
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
//struct ImDrawList;
//struct ImDrawCmd;
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
//#define ImDrawCallback MyImDrawCallback
//---- Debug Tools: Macro to break in Debugger
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
//#define IM_DEBUG_BREAK IM_ASSERT(0)
//#define IM_DEBUG_BREAK __debugbreak()
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
// This adds a small runtime cost which is why it is not enabled by default.
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
//---- Debug Tools: Enable slower asserts
//#define IMGUI_DEBUG_PARANOID
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
/*
namespace ImGui
{
void MyFunction(const char* name, const MyMatrix44& v);
}
*/

9268
SpyCustom/imgui/imgui.cpp Normal file

File diff suppressed because it is too large Load Diff

2036
SpyCustom/imgui/imgui.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,232 @@
#include "imgui.h"
#include "imgui_impl_dx9.h"
#include <d3d9.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;
static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
static LPDIRECT3DTEXTURE9 g_FontTexture = NULL;
static int g_VertexBufferSize = 5000, g_IndexBufferSize = 10000;
struct CUSTOMVERTEX
{
float pos[3];
D3DCOLOR col;
float uv[2];
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
{
D3DVIEWPORT9 vp;
vp.X = vp.Y = 0;
vp.Width = (DWORD)draw_data->DisplaySize.x;
vp.Height = (DWORD)draw_data->DisplaySize.y;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
g_pd3dDevice->SetViewport(&vp);
g_pd3dDevice->SetPixelShader(NULL);
g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
{
float L = draw_data->DisplayPos.x + 0.5f;
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
float T = draw_data->DisplayPos.y + 0.5f;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
D3DMATRIX mat_projection =
{ { {
2.0f/(R-L), 0.0f, 0.0f, 0.0f,
0.0f, 2.0f/(T-B), 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
(L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
} } };
g_pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
}
}
void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
{
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
return;
if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount)
{
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
g_VertexBufferSize = draw_data->TotalVtxCount + 5000;
if (g_pd3dDevice->CreateVertexBuffer(g_VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) < 0)
return;
}
if (!g_pIB || g_IndexBufferSize < draw_data->TotalIdxCount)
{
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
g_IndexBufferSize = draw_data->TotalIdxCount + 10000;
if (g_pd3dDevice->CreateIndexBuffer(g_IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &g_pIB, NULL) < 0)
return;
}
IDirect3DStateBlock9* d3d9_state_block = NULL;
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
return;
D3DMATRIX last_world, last_view, last_projection;
g_pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
CUSTOMVERTEX* vtx_dst;
ImDrawIdx* idx_dst;
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
return;
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
return;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
{
vtx_dst->pos[0] = vtx_src->pos.x;
vtx_dst->pos[1] = vtx_src->pos.y;
vtx_dst->pos[2] = 0.0f;
vtx_dst->col = (vtx_src->col & 0xFF00FF00) | ((vtx_src->col & 0xFF0000) >> 16) | ((vtx_src->col & 0xFF) << 16);
vtx_dst->uv[0] = vtx_src->uv.x;
vtx_dst->uv[1] = vtx_src->uv.y;
vtx_dst++;
vtx_src++;
}
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
idx_dst += cmd_list->IdxBuffer.Size;
}
g_pVB->Unlock();
g_pIB->Unlock();
g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
g_pd3dDevice->SetIndices(g_pIB);
g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
ImGui_ImplDX9_SetupRenderState(draw_data);
int global_vtx_offset = 0;
int global_idx_offset = 0;
ImVec2 clip_off = draw_data->DisplayPos;
for (int n = 0; n < draw_data->CmdListsCount; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
if (pcmd->UserCallback != NULL)
{
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
ImGui_ImplDX9_SetupRenderState(draw_data);
else
pcmd->UserCallback(cmd_list, pcmd);
}
else
{
const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId;
g_pd3dDevice->SetTexture(0, texture);
g_pd3dDevice->SetScissorRect(&r);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
g_pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
d3d9_state_block->Apply();
d3d9_state_block->Release();
}
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
{
ImGuiIO& io = ImGui::GetIO();
io.BackendRendererName = "imgui_impl_dx9";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
g_pd3dDevice = device;
g_pd3dDevice->AddRef();
return true;
}
void ImGui_ImplDX9_Shutdown()
{
ImGui_ImplDX9_InvalidateDeviceObjects();
if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
}
static bool ImGui_ImplDX9_CreateFontsTexture()
{
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height, bytes_per_pixel;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
g_FontTexture = NULL;
if (g_pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_FontTexture, NULL) < 0)
return false;
D3DLOCKED_RECT tex_locked_rect;
if (g_FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
return false;
for (int y = 0; y < height; y++)
memcpy((unsigned char*)tex_locked_rect.pBits + tex_locked_rect.Pitch * y, pixels + (width * bytes_per_pixel) * y, (width * bytes_per_pixel));
g_FontTexture->UnlockRect(0);
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
return true;
}
bool ImGui_ImplDX9_CreateDeviceObjects()
{
if (!g_pd3dDevice)
return false;
if (!ImGui_ImplDX9_CreateFontsTexture())
return false;
return true;
}
void ImGui_ImplDX9_InvalidateDeviceObjects()
{
if (!g_pd3dDevice)
return;
if (g_pVB) { g_pVB->Release(); g_pVB = NULL; }
if (g_pIB) { g_pIB->Release(); g_pIB = NULL; }
if (g_FontTexture) { g_FontTexture->Release(); g_FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); }
}
void ImGui_ImplDX9_NewFrame()
{
if (!g_FontTexture)
ImGui_ImplDX9_CreateDeviceObjects();
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "imgui.h"
struct IDirect3DDevice9;
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();

View File

@ -0,0 +1,396 @@
#include "imgui.h"
#include "imgui_impl_win32.h"
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <tchar.h>
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <XInput.h>
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif
static HWND g_hWnd = NULL;
static INT64 g_Time = 0;
static INT64 g_TicksPerSecond = 0;
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT;
static bool g_HasGamepad = false;
static bool g_WantUpdateHasGamepad = true;
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
static HMODULE g_XInputDLL = NULL;
static PFN_XInputGetCapabilities g_XInputGetCapabilities = NULL;
static PFN_XInputGetState g_XInputGetState = NULL;
#endif
bool ImGui_ImplWin32_Init(void* hwnd)
{
if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&g_TicksPerSecond))
return false;
if (!::QueryPerformanceCounter((LARGE_INTEGER*)&g_Time))
return false;
g_hWnd = (HWND)hwnd;
ImGuiIO& io = ImGui::GetIO();
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos;
io.BackendPlatformName = "imgui_impl_win32";
io.ImeWindowHandle = hwnd;
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
io.KeyMap[ImGuiKey_Home] = VK_HOME;
io.KeyMap[ImGuiKey_End] = VK_END;
io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
io.KeyMap[ImGuiKey_Space] = VK_SPACE;
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
io.KeyMap[ImGuiKey_X] = 'X';
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
const char* xinput_dll_names[] =
{
"xinput1_4.dll",
"xinput1_3.dll",
"xinput9_1_0.dll",
"xinput1_2.dll",
"xinput1_1.dll"
};
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
{
g_XInputDLL = dll;
g_XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
g_XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
break;
}
#endif
return true;
}
void ImGui_ImplWin32_Shutdown()
{
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
if (g_XInputDLL)
::FreeLibrary(g_XInputDLL);
g_XInputDLL = NULL;
g_XInputGetCapabilities = NULL;
g_XInputGetState = NULL;
#endif
g_hWnd = NULL;
g_Time = 0;
g_TicksPerSecond = 0;
g_LastMouseCursor = ImGuiMouseCursor_COUNT;
g_HasGamepad = false;
g_WantUpdateHasGamepad = true;
}
static bool ImGui_ImplWin32_UpdateMouseCursor()
{
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false;
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
{
::SetCursor(NULL);
}
else
{
LPTSTR win32_cursor = IDC_ARROW;
switch (imgui_cursor)
{
case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
}
::SetCursor(::LoadCursor(NULL, win32_cursor));
}
return true;
}
static void ImGui_ImplWin32_UpdateMousePos()
{
ImGuiIO& io = ImGui::GetIO();
if (io.WantSetMousePos)
{
POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y };
if (::ClientToScreen(g_hWnd, &pos))
::SetCursorPos(pos.x, pos.y);
}
io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
POINT pos;
if (HWND active_window = ::GetForegroundWindow())
if (active_window == g_hWnd || ::IsChild(active_window, g_hWnd))
if (::GetCursorPos(&pos) && ::ScreenToClient(g_hWnd, &pos))
io.MousePos = ImVec2((float)pos.x, (float)pos.y);
}
static void ImGui_ImplWin32_UpdateGamepads()
{
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
ImGuiIO& io = ImGui::GetIO();
memset(io.NavInputs, 0, sizeof(io.NavInputs));
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
return;
if (g_WantUpdateHasGamepad)
{
XINPUT_CAPABILITIES caps;
g_HasGamepad = g_XInputGetCapabilities ? (g_XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
g_WantUpdateHasGamepad = false;
}
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
XINPUT_STATE xinput_state;
if (g_HasGamepad && g_XInputGetState && g_XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
{
const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
#define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; }
#define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A);
MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B);
MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X);
MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y);
MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT);
MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT);
MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP);
MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN);
MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER);
MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER);
MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER);
MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER);
MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767);
#undef MAP_BUTTON
#undef MAP_ANALOG
}
#endif
}
void ImGui_ImplWin32_NewFrame()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer backend. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
RECT rect = { 0, 0, 0, 0 };
::GetClientRect(g_hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
INT64 current_time = 0;
::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
io.DeltaTime = (float)(current_time - g_Time) / g_TicksPerSecond;
g_Time = current_time;
io.KeyCtrl = (::GetKeyState(VK_CONTROL) & 0x8000) != 0;
io.KeyShift = (::GetKeyState(VK_SHIFT) & 0x8000) != 0;
io.KeyAlt = (::GetKeyState(VK_MENU) & 0x8000) != 0;
io.KeySuper = false;
ImGui_ImplWin32_UpdateMousePos();
ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
if (g_LastMouseCursor != mouse_cursor)
{
g_LastMouseCursor = mouse_cursor;
ImGui_ImplWin32_UpdateMouseCursor();
}
ImGui_ImplWin32_UpdateGamepads();
}
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef DBT_DEVNODES_CHANGED
#define DBT_DEVNODES_CHANGED 0x0007
#endif
#if 0
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (ImGui::GetCurrentContext() == NULL)
return 0;
ImGuiIO& io = ImGui::GetIO();
switch (msg)
{
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
{
int button = 0;
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
::SetCapture(hwnd);
io.MouseDown[button] = true;
return 0;
}
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_XBUTTONUP:
{
int button = 0;
if (msg == WM_LBUTTONUP) { button = 0; }
if (msg == WM_RBUTTONUP) { button = 1; }
if (msg == WM_MBUTTONUP) { button = 2; }
if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
io.MouseDown[button] = false;
if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
::ReleaseCapture();
return 0;
}
case WM_MOUSEWHEEL:
io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
return 0;
case WM_MOUSEHWHEEL:
io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
return 0;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (wParam < 256)
io.KeysDown[wParam] = 1;
return 0;
case WM_KEYUP:
case WM_SYSKEYUP:
if (wParam < 256)
io.KeysDown[wParam] = 0;
return 0;
case WM_CHAR:
if (wParam > 0 && wParam < 0x10000)
io.AddInputCharacterUTF16((unsigned short)wParam);
return 0;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
return 1;
return 0;
case WM_DEVICECHANGE:
if ((UINT)wParam == DBT_DEVNODES_CHANGED)
g_WantUpdateHasGamepad = true;
return 0;
}
return 0;
}
#if !defined(_versionhelpers_H_INCLUDED_) && !defined(_INC_VERSIONHELPERS)
static BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, { 0 }, sp, 0, 0, 0, 0 };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = ::VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = ::VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = ::VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
return ::VerifyVersionInfoW(&osvi, mask, cond);
}
#define IsWindows8Point1OrGreater() IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0)
#endif
#ifndef DPI_ENUMS_DECLARED
typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
#endif
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
#endif
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4
#endif
typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*);
typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
void ImGui_ImplWin32_EnableDpiAwareness()
{
{
static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll");
if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
{
SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
return;
}
}
if (IsWindows8Point1OrGreater())
{
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll");
if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
{
SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
return;
}
}
#if _WIN32_WINNT >= 0x0600
::SetProcessDPIAware();
#endif
}
#if defined(_MSC_VER) && !defined(NOGDI)
#pragma comment(lib, "gdi32")
#endif
float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
{
UINT xdpi = 96, ydpi = 96;
static BOOL bIsWindows8Point1OrGreater = IsWindows8Point1OrGreater();
if (bIsWindows8Point1OrGreater)
{
static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll");
if (PFN_GetDpiForMonitor GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor"))
GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
}
#ifndef NOGDI
else
{
const HDC dc = ::GetDC(NULL);
xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
::ReleaseDC(NULL, dc);
}
#endif
IM_ASSERT(xdpi == ydpi);
return xdpi / 96.0f;
}
float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
{
HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
}

View File

@ -0,0 +1,14 @@
#pragma once
#include "imgui.h"
IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
#if 0
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
#endif
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd);
IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,403 @@
#ifndef STB_INCLUDE_STB_RECT_PACK_H
#define STB_INCLUDE_STB_RECT_PACK_H
#define STB_RECT_PACK_VERSION 1
#ifdef STBRP_STATIC
#define STBRP_DEF static
#else
#define STBRP_DEF extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
#else
typedef unsigned short stbrp_coord;
#endif
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
struct stbrp_rect
{
int id;
stbrp_coord w, h;
stbrp_coord x, y;
int was_packed;
};
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
};
struct stbrp_node
{
stbrp_coord x,y;
stbrp_node *next;
};
struct stbrp_context
{
int width;
int height;
int align;
int init_mode;
int heuristic;
int num_nodes;
stbrp_node *active_head;
stbrp_node *free_head;
stbrp_node extra[2];
};
#ifdef __cplusplus
}
#endif
#endif
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
#define STBRP_ASSERT assert
#endif
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
#define STBRP__CDECL
#endif
enum
{
STBRP__INIT_skyline = 1
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
{
switch (context->init_mode) {
case STBRP__INIT_skyline:
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
context->heuristic = heuristic;
break;
default:
STBRP_ASSERT(0);
}
}
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
{
if (allow_out_of_mem)
context->align = 1;
else {
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
}
}
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
#ifndef STBRP_LARGE_RECTS
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
nodes[i].next = NULL;
context->init_mode = STBRP__INIT_skyline;
context->heuristic = STBRP_HEURISTIC_Skyline_default;
context->free_head = &nodes[0];
context->active_head = &context->extra[0];
context->width = width;
context->height = height;
context->num_nodes = num_nodes;
stbrp_setup_allow_out_of_mem(context, 0);
context->extra[0].x = 0;
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
#else
context->extra[1].y = 65535;
#endif
context->extra[1].next = NULL;
}
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
STBRP__NOTUSED(c);
STBRP_ASSERT(first->x <= x0);
#if 0
while (node->next->x <= x0)
++node;
#else
STBRP_ASSERT(node->next->x > x0);
#endif
STBRP_ASSERT(node->x <= x0);
min_y = 0;
waste_area = 0;
visited_width = 0;
while (node->x < x1) {
if (node->y > min_y) {
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
if (node->x < x0)
visited_width += node->next->x - x0;
else
visited_width += node->next->x - node->x;
} else {
int under_width = node->next->x - node->x;
if (under_width + visited_width > width)
under_width = width - visited_width;
waste_area += under_width * (min_y - node->y);
visited_width += under_width;
}
node = node->next;
}
*pwaste = waste_area;
return min_y;
}
typedef struct
{
int x,y;
stbrp_node **prev_link;
} stbrp__findresult;
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
{
int best_waste = (1<<30), best_x, best_y = (1 << 30);
stbrp__findresult fr;
stbrp_node **prev, *node, *tail, **best = NULL;
width = (width + c->align - 1);
width -= width % c->align;
STBRP_ASSERT(width % c->align == 0);
if (width > c->width || height > c->height) {
fr.prev_link = NULL;
fr.x = fr.y = 0;
return fr;
}
node = c->active_head;
prev = &c->active_head;
while (node->x + width <= c->width) {
int y,waste;
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) {
if (y < best_y) {
best_y = y;
best = prev;
}
} else {
if (y + height <= c->height) {
if (y < best_y || (y == best_y && waste < best_waste)) {
best_y = y;
best_waste = waste;
best = prev;
}
}
}
prev = &node->next;
node = node->next;
}
best_x = (best == NULL) ? 0 : (*best)->x;
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
tail = c->active_head;
node = c->active_head;
prev = &c->active_head;
while (tail->x < width)
tail = tail->next;
while (tail) {
int xpos = tail->x - width;
int y,waste;
STBRP_ASSERT(xpos >= 0);
while (node->next->x <= xpos) {
prev = &node->next;
node = node->next;
}
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
if (y + height <= c->height) {
if (y <= best_y) {
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
best_x = xpos;
STBRP_ASSERT(y <= best_y);
best_y = y;
best_waste = waste;
best = prev;
}
}
}
tail = tail->next;
}
}
fr.prev_link = best;
fr.x = best_x;
fr.y = best_y;
return fr;
}
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
{
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
stbrp_node *node, *cur;
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
res.prev_link = NULL;
return res;
}
node = context->free_head;
node->x = (stbrp_coord) res.x;
node->y = (stbrp_coord) (res.y + height);
context->free_head = node->next;
cur = *res.prev_link;
if (cur->x < res.x) {
stbrp_node *next = cur->next;
cur->next = node;
cur = next;
} else {
*res.prev_link = node;
}
while (cur->next && cur->next->x <= res.x + width) {
stbrp_node *next = cur->next;
cur->next = context->free_head;
context->free_head = cur;
cur = next;
}
node->next = cur;
if (cur->x < res.x + width)
cur->x = (stbrp_coord) (res.x + width);
#ifdef _DEBUG
cur = context->active_head;
while (cur->x < context->width) {
STBRP_ASSERT(cur->x < cur->next->x);
cur = cur->next;
}
STBRP_ASSERT(cur->next == NULL);
{
int count=0;
cur = context->active_head;
while (cur) {
cur = cur->next;
++count;
}
cur = context->free_head;
while (cur) {
cur = cur->next;
++count;
}
STBRP_ASSERT(count == context->num_nodes+2);
}
#endif
return res;
}
static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
if (p->h > q->h)
return -1;
if (p->h < q->h)
return 1;
return (p->w > q->w) ? -1 : (p->w < q->w);
}
static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
#ifdef STBRP_LARGE_RECTS
#define STBRP__MAXVAL 0xffffffff
#else
#define STBRP__MAXVAL 0xffff
#endif
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = i;
}
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0;
} else {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
for (i=0; i < num_rects; ++i) {
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
if (!rects[i].was_packed)
all_rects_packed = 0;
}
return all_rects_packed;
}
#endif

View File

@ -0,0 +1,968 @@
#ifndef INCLUDE_STB_TEXTEDIT_H
#define INCLUDE_STB_TEXTEDIT_H
#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
#define STB_TEXTEDIT_UNDOSTATECOUNT 99
#endif
#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
#define STB_TEXTEDIT_UNDOCHARCOUNT 999
#endif
#ifndef STB_TEXTEDIT_CHARTYPE
#define STB_TEXTEDIT_CHARTYPE int
#endif
#ifndef STB_TEXTEDIT_POSITIONTYPE
#define STB_TEXTEDIT_POSITIONTYPE int
#endif
typedef struct
{
STB_TEXTEDIT_POSITIONTYPE where;
STB_TEXTEDIT_POSITIONTYPE insert_length;
STB_TEXTEDIT_POSITIONTYPE delete_length;
int char_storage;
} StbUndoRecord;
typedef struct
{
StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
short undo_point, redo_point;
int undo_char_point, redo_char_point;
} StbUndoState;
typedef struct
{
int cursor;
int select_start;
int select_end;
unsigned char insert_mode;
int row_count_per_page;
unsigned char cursor_at_end_of_line;
unsigned char initialized;
unsigned char has_preferred_x;
unsigned char single_line;
unsigned char padding1, padding2, padding3;
float preferred_x;
StbUndoState undostate;
} STB_TexteditState;
typedef struct
{
float x0,x1;
float baseline_y_delta;
float ymin,ymax;
int num_chars;
} StbTexteditRow;
#endif
#ifdef STB_TEXTEDIT_IMPLEMENTATION
#ifndef STB_TEXTEDIT_memmove
#include <string.h>
#define STB_TEXTEDIT_memmove memmove
#endif
static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
{
StbTexteditRow r;
int n = STB_TEXTEDIT_STRINGLEN(str);
float base_y = 0, prev_x;
int i=0, k;
r.x0 = r.x1 = 0;
r.ymin = r.ymax = 0;
r.num_chars = 0;
while (i < n) {
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
if (r.num_chars <= 0)
return n;
if (i==0 && y < base_y + r.ymin)
return 0;
if (y < base_y + r.ymax)
break;
i += r.num_chars;
base_y += r.baseline_y_delta;
}
if (i >= n)
return n;
if (x < r.x0)
return i;
if (x < r.x1) {
prev_x = r.x0;
for (k=0; k < r.num_chars; ++k) {
float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
if (x < prev_x+w) {
if (x < prev_x+w/2)
return k+i;
else
return k+i+1;
}
prev_x += w;
}
}
if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)
return i+r.num_chars-1;
else
return i+r.num_chars;
}
static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
if( state->single_line )
{
StbTexteditRow r;
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
y = r.ymin;
}
state->cursor = stb_text_locate_coord(str, x, y);
state->select_start = state->cursor;
state->select_end = state->cursor;
state->has_preferred_x = 0;
}
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
int p = 0;
if( state->single_line )
{
StbTexteditRow r;
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
y = r.ymin;
}
if (state->select_start == state->select_end)
state->select_start = state->cursor;
p = stb_text_locate_coord(str, x, y);
state->cursor = state->select_end = p;
}
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
typedef struct
{
float x,y;
float height;
int first_char, length;
int prev_first;
} StbFindState;
static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
{
StbTexteditRow r;
int prev_start = 0;
int z = STB_TEXTEDIT_STRINGLEN(str);
int i=0, first;
if (n == z) {
if (single_line) {
STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
find->y = 0;
find->first_char = 0;
find->length = z;
find->height = r.ymax - r.ymin;
find->x = r.x1;
} else {
find->y = 0;
find->x = 0;
find->height = 1;
while (i < z) {
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
prev_start = i;
i += r.num_chars;
}
find->first_char = i;
find->length = 0;
find->prev_first = prev_start;
}
return;
}
find->y = 0;
for(;;) {
STB_TEXTEDIT_LAYOUTROW(&r, str, i);
if (n < i + r.num_chars)
break;
prev_start = i;
i += r.num_chars;
find->y += r.baseline_y_delta;
}
find->first_char = first = i;
find->length = r.num_chars;
find->height = r.ymax - r.ymin;
find->prev_first = prev_start;
find->x = r.x0;
for (i=0; first+i < n; ++i)
find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
}
#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
int n = STB_TEXTEDIT_STRINGLEN(str);
if (STB_TEXT_HAS_SELECTION(state)) {
if (state->select_start > n) state->select_start = n;
if (state->select_end > n) state->select_end = n;
if (state->select_start == state->select_end)
state->cursor = state->select_start;
}
if (state->cursor > n) state->cursor = n;
}
static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
{
stb_text_makeundo_delete(str, state, where, len);
STB_TEXTEDIT_DELETECHARS(str, where, len);
state->has_preferred_x = 0;
}
static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
stb_textedit_clamp(str, state);
if (STB_TEXT_HAS_SELECTION(state)) {
if (state->select_start < state->select_end) {
stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);
state->select_end = state->cursor = state->select_start;
} else {
stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);
state->select_start = state->cursor = state->select_end;
}
state->has_preferred_x = 0;
}
}
static void stb_textedit_sortselection(STB_TexteditState *state)
{
if (state->select_end < state->select_start) {
int temp = state->select_end;
state->select_end = state->select_start;
state->select_start = temp;
}
}
static void stb_textedit_move_to_first(STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state);
state->cursor = state->select_start;
state->select_end = state->select_start;
state->has_preferred_x = 0;
}
}
static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_sortselection(state);
stb_textedit_clamp(str, state);
state->cursor = state->select_end;
state->select_start = state->select_end;
state->has_preferred_x = 0;
}
}
#ifdef STB_TEXTEDIT_IS_SPACE
static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
{
return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
}
#ifndef STB_TEXTEDIT_MOVEWORDLEFT
static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
{
--c;
while( c >= 0 && !is_word_boundary( str, c ) )
--c;
if( c < 0 )
c = 0;
return c;
}
#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
#endif
#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
{
const int len = STB_TEXTEDIT_STRINGLEN(str);
++c;
while( c < len && !is_word_boundary( str, c ) )
++c;
if( c > len )
c = len;
return c;
}
#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
#endif
#endif
static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
{
if (!STB_TEXT_HAS_SELECTION(state))
state->select_start = state->select_end = state->cursor;
else
state->cursor = state->select_end;
}
static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
if (STB_TEXT_HAS_SELECTION(state)) {
stb_textedit_delete_selection(str,state);
state->has_preferred_x = 0;
return 1;
}
return 0;
}
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
{
stb_textedit_clamp(str, state);
stb_textedit_delete_selection(str,state);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
stb_text_makeundo_insert(state, state->cursor, len);
state->cursor += len;
state->has_preferred_x = 0;
return 1;
}
if (state->undostate.undo_point)
--state->undostate.undo_point;
return 0;
}
#ifndef STB_TEXTEDIT_KEYTYPE
#define STB_TEXTEDIT_KEYTYPE int
#endif
static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
{
retry:
switch (key) {
default: {
int c = STB_TEXTEDIT_KEYTOTEXT(key);
if (c > 0) {
STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
if (c == '\n' && state->single_line)
break;
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
++state->cursor;
state->has_preferred_x = 0;
}
} else {
stb_textedit_delete_selection(str,state);
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
stb_text_makeundo_insert(state, state->cursor, 1);
++state->cursor;
state->has_preferred_x = 0;
}
}
}
break;
}
#ifdef STB_TEXTEDIT_K_INSERT
case STB_TEXTEDIT_K_INSERT:
state->insert_mode = !state->insert_mode;
break;
#endif
case STB_TEXTEDIT_K_UNDO:
stb_text_undo(str, state);
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_REDO:
stb_text_redo(str, state);
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_LEFT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_first(state);
else
if (state->cursor > 0)
--state->cursor;
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_RIGHT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str, state);
else
++state->cursor;
stb_textedit_clamp(str, state);
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT:
stb_textedit_clamp(str, state);
stb_textedit_prep_selection_at_cursor(state);
if (state->select_end > 0)
--state->select_end;
state->cursor = state->select_end;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_MOVEWORDLEFT
case STB_TEXTEDIT_K_WORDLEFT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_first(state);
else {
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
stb_textedit_clamp( str, state );
}
break;
case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT:
if( !STB_TEXT_HAS_SELECTION( state ) )
stb_textedit_prep_selection_at_cursor(state);
state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
state->select_end = state->cursor;
stb_textedit_clamp( str, state );
break;
#endif
#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
case STB_TEXTEDIT_K_WORDRIGHT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str, state);
else {
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
stb_textedit_clamp( str, state );
}
break;
case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:
if( !STB_TEXT_HAS_SELECTION( state ) )
stb_textedit_prep_selection_at_cursor(state);
state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
state->select_end = state->cursor;
stb_textedit_clamp( str, state );
break;
#endif
case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
++state->select_end;
stb_textedit_clamp(str, state);
state->cursor = state->select_end;
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_DOWN:
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGDOWN:
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
int row_count = is_page ? state->row_count_per_page : 1;
if (!is_page && state->single_line) {
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
}
if (sel)
stb_textedit_prep_selection_at_cursor(state);
else if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_last(str, state);
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
int start = find.first_char + find.length;
if (find.length == 0)
break;
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
break;
state->cursor = start;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
if (x > goal_x)
break;
++state->cursor;
}
stb_textedit_clamp(str, state);
state->has_preferred_x = 1;
state->preferred_x = goal_x;
if (sel)
state->select_end = state->cursor;
find.first_char = find.first_char + find.length;
find.length = row.num_chars;
}
break;
}
case STB_TEXTEDIT_K_UP:
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
case STB_TEXTEDIT_K_PGUP:
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
StbTexteditRow row;
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
int row_count = is_page ? state->row_count_per_page : 1;
if (!is_page && state->single_line) {
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
goto retry;
}
if (sel)
stb_textedit_prep_selection_at_cursor(state);
else if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_move_to_first(state);
stb_textedit_clamp(str, state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
for (j = 0; j < row_count; ++j) {
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
if (find.prev_first == find.first_char)
break;
state->cursor = find.prev_first;
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
x = row.x0;
for (i=0; i < row.num_chars; ++i) {
float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
#ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
break;
#endif
x += dx;
if (x > goal_x)
break;
++state->cursor;
}
stb_textedit_clamp(str, state);
state->has_preferred_x = 1;
state->preferred_x = goal_x;
if (sel)
state->select_end = state->cursor;
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
--prev_scan;
find.first_char = find.prev_first;
find.prev_first = prev_scan;
}
break;
}
case STB_TEXTEDIT_K_DELETE:
case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_delete_selection(str, state);
else {
int n = STB_TEXTEDIT_STRINGLEN(str);
if (state->cursor < n)
stb_textedit_delete(str, state, state->cursor, 1);
}
state->has_preferred_x = 0;
break;
case STB_TEXTEDIT_K_BACKSPACE:
case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT:
if (STB_TEXT_HAS_SELECTION(state))
stb_textedit_delete_selection(str, state);
else {
stb_textedit_clamp(str, state);
if (state->cursor > 0) {
stb_textedit_delete(str, state, state->cursor-1, 1);
--state->cursor;
}
}
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2:
#endif
case STB_TEXTEDIT_K_TEXTSTART:
state->cursor = state->select_start = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTEND2
case STB_TEXTEDIT_K_TEXTEND2:
#endif
case STB_TEXTEDIT_K_TEXTEND:
state->cursor = STB_TEXTEDIT_STRINGLEN(str);
state->select_start = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
state->cursor = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTEND2
case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_LINESTART2
case STB_TEXTEDIT_K_LINESTART2:
#endif
case STB_TEXTEDIT_K_LINESTART:
stb_textedit_clamp(str, state);
stb_textedit_move_to_first(state);
if (state->single_line)
state->cursor = 0;
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
--state->cursor;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_LINEEND2
case STB_TEXTEDIT_K_LINEEND2:
#endif
case STB_TEXTEDIT_K_LINEEND: {
int n = STB_TEXTEDIT_STRINGLEN(str);
stb_textedit_clamp(str, state);
stb_textedit_move_to_first(state);
if (state->single_line)
state->cursor = n;
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
++state->cursor;
state->has_preferred_x = 0;
break;
}
#ifdef STB_TEXTEDIT_K_LINESTART2
case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
stb_textedit_clamp(str, state);
stb_textedit_prep_selection_at_cursor(state);
if (state->single_line)
state->cursor = 0;
else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
--state->cursor;
state->select_end = state->cursor;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_LINEEND2
case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
int n = STB_TEXTEDIT_STRINGLEN(str);
stb_textedit_clamp(str, state);
stb_textedit_prep_selection_at_cursor(state);
if (state->single_line)
state->cursor = n;
else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
++state->cursor;
state->select_end = state->cursor;
state->has_preferred_x = 0;
break;
}
}
}
static void stb_textedit_flush_redo(StbUndoState *state)
{
state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
}
static void stb_textedit_discard_undo(StbUndoState *state)
{
if (state->undo_point > 0) {
if (state->undo_rec[0].char_storage >= 0) {
int n = state->undo_rec[0].insert_length, i;
state->undo_char_point -= n;
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage -= n;
}
--state->undo_point;
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
}
}
static void stb_textedit_discard_redo(StbUndoState *state)
{
int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
if (state->redo_point <= k) {
if (state->undo_rec[k].char_storage >= 0) {
int n = state->undo_rec[k].insert_length, i;
state->redo_char_point += n;
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage += n;
}
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
++state->redo_point;
}
}
static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
{
stb_textedit_flush_redo(state);
if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
stb_textedit_discard_undo(state);
if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
state->undo_point = 0;
state->undo_char_point = 0;
return NULL;
}
while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
stb_textedit_discard_undo(state);
return &state->undo_rec[state->undo_point++];
}
static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
{
StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
if (r == NULL)
return NULL;
r->where = pos;
r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
if (insert_len == 0) {
r->char_storage = -1;
return NULL;
} else {
r->char_storage = state->undo_char_point;
state->undo_char_point += insert_len;
return &state->undo_char[r->char_storage];
}
}
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord u, *r;
if (s->undo_point == 0)
return;
u = s->undo_rec[s->undo_point-1];
r = &s->undo_rec[s->redo_point-1];
r->char_storage = -1;
r->insert_length = u.delete_length;
r->delete_length = u.insert_length;
r->where = u.where;
if (u.delete_length) {
if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
r->insert_length = 0;
} else {
int i;
while (s->undo_char_point + u.delete_length > s->redo_char_point) {
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
return;
stb_textedit_discard_redo(s);
}
r = &s->undo_rec[s->redo_point-1];
r->char_storage = s->redo_char_point - u.delete_length;
s->redo_char_point = s->redo_char_point - u.delete_length;
for (i=0; i < u.delete_length; ++i)
s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
}
STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
}
if (u.insert_length) {
STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
s->undo_char_point -= u.insert_length;
}
state->cursor = u.where + u.insert_length;
s->undo_point--;
s->redo_point--;
}
static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
StbUndoState *s = &state->undostate;
StbUndoRecord *u, r;
if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
return;
u = &s->undo_rec[s->undo_point];
r = s->undo_rec[s->redo_point];
u->delete_length = r.insert_length;
u->insert_length = r.delete_length;
u->where = r.where;
u->char_storage = -1;
if (r.delete_length) {
if (s->undo_char_point + u->insert_length > s->redo_char_point) {
u->insert_length = 0;
u->delete_length = 0;
} else {
int i;
u->char_storage = s->undo_char_point;
s->undo_char_point = s->undo_char_point + u->insert_length;
for (i=0; i < u->insert_length; ++i)
s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);
}
STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
}
if (r.insert_length) {
STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
s->redo_char_point += r.insert_length;
}
state->cursor = r.where + r.insert_length;
s->undo_point++;
s->redo_point++;
}
static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
{
stb_text_createundo(&state->undostate, where, 0, length);
}
static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
if (p) {
for (i=0; i < length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
}
}
static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
{
int i;
STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
if (p) {
for (i=0; i < old_length; ++i)
p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
}
}
static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
{
state->undostate.undo_point = 0;
state->undostate.undo_char_point = 0;
state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
state->select_end = state->select_start = 0;
state->cursor = 0;
state->has_preferred_x = 0;
state->preferred_x = 0;
state->cursor_at_end_of_line = 0;
state->initialized = 1;
state->single_line = (unsigned char) is_single_line;
state->insert_mode = 0;
state->row_count_per_page = 0;
}
static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
{
stb_textedit_clear_state(state, is_single_line);
}
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
#endif
static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
{
return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
}
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,397 @@
#pragma once
#include "ProtoParse.h"
#include "ProtobuffMessages.h"
#include <ctime>
#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<uint32_t> music_kits = { 3, 4, 5, 6, 7, 8 };
template<typename T>
inline std::string get_4bytes(T value)
{
return std::string{ reinterpret_cast<const char*>(reinterpret_cast<void*>(&value)), 4 };
}
template<typename T>
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;
}
}

1785
SpyCustom/mathlib.h Normal file

File diff suppressed because it is too large Load Diff

36
SpyCustom/netchannel.hpp Normal file
View File

@ -0,0 +1,36 @@
#pragma once
typedef const void(__thiscall* pShutdown)(void*, void*, const char*);
pShutdown oShutdown;
void __fastcall hkShutdown(void* thisptr, void* unk1, void* unk2, const char* reason) noexcept
{
#ifdef DEBUG
printf("shutdown (%x) HOOKED %s\n", thisptr, reason);
#endif
if (*g_Options.discmsg_active) {
#ifdef DEBUG
printf("set new reason %s\n", g_Options.discmsg.value->mystring);
#endif
char customreason[256] = "#";
strcat_s( customreason, MakeControlChars(g_Options.discmsg.value->mystring));
oShutdown(thisptr, nullptr, customreason);
}
else
oShutdown(thisptr, nullptr, reason);
}
inline void HookNetchannel()
{
DWORD ptrShutdown = *((DWORD*)iff.g_pEngineClient->GetNetChannelInfo()) + 36 * 4;
DWORD addrShutdown = *(DWORD*)ptrShutdown;
oShutdown = (pShutdown)DetourFunction(
(PBYTE)(addrShutdown),
(PBYTE)hkShutdown);
#ifdef DEBUG
printf("Detoured at %x\n", addrShutdown);
#endif
opt.netchannedlhooked = 1;
}

110
SpyCustom/netvars.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "netvars.hpp"
#include <fstream>
#include <utility>
#include "interfaces.hpp"
void NetvarSys::Initialize()
{
m_tables.clear();
ClientClass* clientClass = iff.g_pClient->GetAllClasses();
if (!clientClass)
return;
while (clientClass)
{
RecvTable* recvTable = clientClass->m_pRecvTable;
m_tables.push_back(recvTable);
clientClass = clientClass->m_pNext;
}
}
#undef GetProp
int NetvarSys::GetOffset(const char* tableName, const char* propName)
{
int offset = this->GetProp(tableName, propName);
if (!offset)
{
#ifdef DEBUG
printf("%s not found!\n", propName);
#endif
return 0;
}
#ifdef DEBUG
printf("%s: 0x%02X\n", propName, offset);
#endif
return offset;
}
int NetvarSys::GetProp(const char* tableName, const char* propName, RecvProp** prop)
{
RecvTable* recvTable = GetTable(tableName);
if (!recvTable)
return 0;
int offset = this->GetProp(recvTable, propName, prop);
if (!offset)
return 0;
return offset;
}
int NetvarSys::GetProp(RecvTable* recvTable, const char* propName, RecvProp** prop)
{
int extraOffset = 0;
for (int i = 0; i < recvTable->m_nProps; ++i)
{
RecvProp* recvProp = &recvTable->m_pProps[i];
RecvTable* child = recvProp->m_pDataTable;
if (child && (child->m_nProps > 0))
{
int tmp = this->GetProp(child, propName, prop);
if (tmp)
extraOffset += (recvProp->m_Offset + tmp);
}
if (_stricmp(recvProp->m_pVarName, propName))
continue;
if (prop)
*prop = recvProp;
return (recvProp->m_Offset + extraOffset);
}
return extraOffset;
}
RecvTable* NetvarSys::GetTable(const char* tableName)
{
if (m_tables.empty())
return 0;
for (const auto& table : m_tables)
{
if (!table)
continue;
if (_stricmp(table->m_pNetTableName, tableName) == 0)
return table;
}
return 0;
}

37
SpyCustom/netvars.hpp Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <memory>
#include <iostream>
#include <unordered_map>
#include "dt_recv.h"
#include "Singleton.hpp"
class NetvarSys
: public Singleton<NetvarSys>
{
public:
void Initialize();
int GetOffset(const char* tableName, const char* propName);
RecvTable* GetTable(const char* tableName);
std::vector<RecvTable*> m_tables;
private:
int GetProp(const char* tableName, const char* propName, RecvProp** prop = 0);
int GetProp(RecvTable* recvTable, const char* propName, RecvProp** prop = 0);
};
#define NETVAR_OFFSET2(funcname, class_name, var_name, offset, ...) \
auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \
{ \
static int netvar = NetvarSys::Get().GetOffset(class_name, var_name); \
auto addr = std::uintptr_t(this) + offset + netvar; \
return *reinterpret_cast<std::add_pointer_t<__VA_ARGS__>>(addr); \
}
#define NETVAR2(funcname, class_name, var_name, ...) \
NETVAR_OFFSET2(funcname, class_name, var_name, 0, __VA_ARGS__)

779
SpyCustom/pbwrap.hpp Normal file
View File

@ -0,0 +1,779 @@
#pragma once
#include <stdint.h>
#include <string>
#include <vector>
#include <tuple>
#define PBFIELD(number, type, name) \
pbfield<number, type> name() const { \
return std::move(pbfield<number, type>( fv_ )); \
}
#if defined(__GNUC__)
#include <cstring>
#include <memory>
#define __forceinline __attribute__((always_inline))
#define PBMSG_CTOR(class_name) \
class_name() : pbmsg() {} \
class_name(void* buf, size_t bytes) : pbmsg(buf, bytes) {} \
class_name(const std::string& buf) : pbmsg(buf) {}
#elif defined(_MSC_VER)
#define PBMSG_CTOR using pbmsg::pbmsg
#endif
namespace pbwrap
{
static constexpr int32_t k_invalid_id = -1;
enum e_field_type
{
TYPE_DOUBLE = 1,
TYPE_FLOAT = 2,
TYPE_INT64 = 3,
TYPE_UINT64 = 4,
TYPE_INT32 = 5,
TYPE_FIXED64 = 6,
TYPE_FIXED32 = 7,
TYPE_BOOL = 8,
TYPE_STRING = 9,
TYPE_GROUP = 10,
TYPE_MESSAGE = 11,
TYPE_BYTES = 12,
TYPE_UINT32 = 13,
TYPE_ENUM = 14,
TYPE_SFIXED32 = 15,
TYPE_SFIXED64 = 16,
TYPE_SINT32 = 17,
TYPE_SINT64 = 18,
MAX_FIELD_TYPE = 18,
};
enum e_wire_type
{
WIRETYPE_VARINT = 0,
WIRETYPE_FIXED64 = 1,
WIRETYPE_LENGTH_DELIMITED = 2,
WIRETYPE_START_GROUP = 3,
WIRETYPE_END_GROUP = 4,
WIRETYPE_FIXED32 = 5,
};
static constexpr e_wire_type k_wire_type_for_field_type[MAX_FIELD_TYPE + 1] = {
static_cast<e_wire_type>(k_invalid_id),
WIRETYPE_FIXED64,
WIRETYPE_FIXED32,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_FIXED64,
WIRETYPE_FIXED32,
WIRETYPE_VARINT,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_START_GROUP,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_LENGTH_DELIMITED,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
WIRETYPE_FIXED32,
WIRETYPE_FIXED64,
WIRETYPE_VARINT,
WIRETYPE_VARINT,
};
namespace utils
{
static constexpr int k_tag_type_bits = 3;
static constexpr uint32_t k_tag_type_mask = (1 << k_tag_type_bits) - 1;
static constexpr int k_max_varint_bytes = 10;
static constexpr int k_max_varint32_bytes = 5;
__forceinline auto make_tag(uint32_t field_number, uint32_t wire_type) -> uint32_t
{
return static_cast<uint32_t>((field_number << k_tag_type_bits) | wire_type);
}
static auto get_bytes_varint32(uint32_t value) -> std::string
{
uint8_t bytes[k_max_varint32_bytes];
int size = 0;
while (value > 0x7F)
{
bytes[size++] = (static_cast<uint8_t>(value) & 0x7F) | 0x80;
value >>= 7;
}
bytes[size++] = static_cast<uint8_t>(value) & 0x7F;
return std::string{ reinterpret_cast<const char*>(&bytes[0]), (size_t)size };
}
static auto get_bytes_varint64(uint64_t value) -> std::string
{
uint8_t bytes[k_max_varint_bytes];
int size = 0;
while (value > 0x7F)
{
bytes[size++] = (static_cast<uint8_t>(value) & 0x7F) | 0x80;
value >>= 7;
}
bytes[size++] = static_cast<uint8_t>(value) & 0x7F;
return std::string{ reinterpret_cast<const char*>(&bytes[0]), (size_t)size };
}
static auto read_varuint32(const void* data, size_t& bytes_read) -> uint32_t
{
auto ptr = reinterpret_cast<const uint8_t*>(data);
auto value = 0u;
auto bytes = 0u;
do
{
value |= static_cast<uint32_t>(*ptr & 0x7f) << (7 * bytes);
bytes++;
} while (*(ptr++) & 0x80 && bytes <= 5);
bytes_read = bytes;
return value;
}
static auto read_varuint64(const void* data, size_t& bytes_read) -> uint64_t
{
auto ptr = reinterpret_cast<const uint8_t*>(data);
auto value = 0ull;
auto bytes = 0u;
do
{
value |= static_cast<uint64_t>(*ptr & 0x7f) << (7 * bytes);
bytes++;
} while (*(ptr++) & 0x80 && bytes <= 10);
bytes_read = bytes;
return value;
}
static auto read_field(const void* data, size_t& bytes_read)
-> std::tuple<uint32_t, uint32_t, std::string, std::string>
{
uint32_t field = *reinterpret_cast<const uint16_t*>(data);
uint32_t wire_type = field & k_tag_type_mask;
if (field == 0xffff)
{
bytes_read = 0;
return std::make_tuple(k_invalid_id, k_invalid_id, "", "");
}
if (field & 0x80)
{
field = ((field & 0x7f) | ((field & 0xff00) >> 1)) >> k_tag_type_bits;
bytes_read = 2;
}
else
{
field = (field & 0xff) >> k_tag_type_bits;
bytes_read = 1;
}
std::string value_bytes, full_bytes;
size_t length, size_delimited;
switch (wire_type)
{
case WIRETYPE_VARINT:
read_varuint64((void*)((ptrdiff_t)data + bytes_read), length);
value_bytes = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytes_read)), length };
full_bytes = std::string{ reinterpret_cast<const char*>(data), bytes_read + length };
bytes_read += length;
break;
case WIRETYPE_FIXED64:
value_bytes = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytes_read)), 8 };
full_bytes = std::string{ reinterpret_cast<const char*>(data), bytes_read + 8 };
bytes_read += 8;
break;
case WIRETYPE_LENGTH_DELIMITED:
size_delimited = read_varuint32((void*)((ptrdiff_t)data + bytes_read), length);
value_bytes = std::string{
reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytes_read)), length + size_delimited
};
full_bytes = std::string{ reinterpret_cast<const char*>(data), bytes_read + length + size_delimited };
bytes_read += length + size_delimited;
break;
case WIRETYPE_START_GROUP:
throw std::runtime_error("WIRETYPE_START_GROUP not implemented");
break;
case WIRETYPE_END_GROUP:
throw std::runtime_error("WIRETYPE_END_GROUP not implemented");
break;
case WIRETYPE_FIXED32:
value_bytes = std::string{ reinterpret_cast<const char*>((void*)((ptrdiff_t)data + bytes_read)), 4 };
full_bytes = std::string{ reinterpret_cast<const char*>(data), bytes_read + 4 };
bytes_read += 4;
break;
default:
throw std::runtime_error("Unknown wire type");
break;
}
return std::make_tuple(field, wire_type, std::move(value_bytes), std::move(full_bytes));
}
template <typename T>
auto get_field_bytes(uint32_t field, uint32_t wire_type, T value)
-> std::pair<std::string, std::string>
{
const auto tag = get_bytes_varint32(make_tag(field, wire_type));
std::string bytes{};
switch (wire_type)
{
case WIRETYPE_VARINT:
bytes += get_bytes_varint64(static_cast<uint64_t>(value));
break;
case WIRETYPE_FIXED32:
bytes += std::string{ reinterpret_cast<const char*>(&value), 4 };
break;
case WIRETYPE_FIXED64:
bytes += std::string{ reinterpret_cast<const char*>(&value), 8 };
break;
}
return { bytes, tag + bytes };
}
template <>
inline auto get_field_bytes<std::string>(uint32_t field, uint32_t wire_type, std::string value)
-> std::pair<std::string, std::string>
{
const auto tag = get_bytes_varint32(make_tag(field, wire_type));
std::string bytes{};
bytes += get_bytes_varint32(value.size());
bytes += value;
return { bytes, tag + bytes };
}
template <>
inline auto get_field_bytes<const char*>(uint32_t field, uint32_t wire_type, const char* value)
-> std::pair<std::string, std::string>
{
const auto tag = get_bytes_varint32(make_tag(field, wire_type));
std::string bytes{};
bytes += get_bytes_varint32(strlen(value));
bytes += value;
return { bytes, tag + bytes };
}
}
namespace types
{
struct Int32
{
static constexpr e_field_type field_type = TYPE_INT32;
using type = int32_t;
static __forceinline auto get(const std::string& value) -> int32_t
{
size_t bytes_read;
return utils::read_varuint32(value.data(), bytes_read);
}
};
struct Uint32
{
static constexpr e_field_type field_type = TYPE_UINT32;
using type = uint32_t;
static __forceinline auto get(const std::string& value) -> uint32_t
{
size_t bytes_read;
return utils::read_varuint32(value.data(), bytes_read);
}
};
struct Int64
{
static constexpr e_field_type field_type = TYPE_INT64;
using type = int64_t;
static __forceinline auto get(const std::string& value) -> int64_t
{
size_t bytes_read;
return utils::read_varuint64(value.data(), bytes_read);
}
};
struct Uint64
{
static constexpr e_field_type field_type = TYPE_UINT64;
using type = uint64_t;
static __forceinline auto get(const std::string& value) -> uint64_t
{
size_t bytes_read;
return utils::read_varuint64(value.data(), bytes_read);
}
};
struct Float
{
static constexpr e_field_type field_type = TYPE_FLOAT;
using type = float;
static __forceinline auto get(const std::string& value) -> float
{
return *reinterpret_cast<const float*>(value.data());
}
};
struct Double
{
static constexpr e_field_type field_type = TYPE_DOUBLE;
using type = double;
static __forceinline auto get(const std::string& value) -> double
{
return *reinterpret_cast<const double*>(value.data());
}
};
struct Fixed32
{
static constexpr e_field_type field_type = TYPE_FIXED32;
using type = int32_t;
static __forceinline auto get(const std::string& value) -> int32_t
{
return *reinterpret_cast<const int32_t*>(value.data());
}
};
struct Fixed64
{
static constexpr e_field_type field_type = TYPE_FIXED64;
using type = int64_t;
static __forceinline auto get(const std::string& value) -> int64_t
{
return *reinterpret_cast<const int64_t*>(value.data());
}
};
struct Bool
{
static constexpr e_field_type field_type = TYPE_BOOL;
using type = bool;
static __forceinline auto get(const std::string& value) -> bool
{
size_t bytes_read;
return !!utils::read_varuint32(value.data(), bytes_read);
}
};
struct String
{
static constexpr e_field_type field_type = TYPE_STRING;
using type = std::string;
static __forceinline auto get(const std::string& value) -> std::string
{
size_t bytes_read;
const auto length = utils::read_varuint32(value.data(), bytes_read);
auto result = std::string{ value.data() + bytes_read, length };
return std::move(result);
}
};
struct Group : String
{
static constexpr e_field_type field_type = TYPE_GROUP;
};
struct Message : String
{
static constexpr e_field_type field_type = TYPE_MESSAGE;
};
struct Bytes : String
{
static constexpr e_field_type field_type = TYPE_BYTES;
};
struct Enum : Int32
{
static constexpr e_field_type field_type = TYPE_ENUM;
};
struct Sfixed32 : Fixed32
{
static constexpr e_field_type field_type = TYPE_SFIXED32;
};
struct Sfixed64 : Fixed64
{
static constexpr e_field_type field_type = TYPE_SFIXED64;
};
struct Sint32
{
static constexpr e_field_type field_type = TYPE_SINT32;
using type = int32_t;
};
struct Sint64
{
static constexpr e_field_type field_type = TYPE_SINT64;
using type = int64_t;
};
}
namespace base
{
struct field_vector
{
using Entry = std::pair<std::string, std::string>;
using Field = std::vector<Entry>;
using Fields = std::vector<Field>;
const std::shared_ptr<Fields> fields;
const size_t max_size;
explicit field_vector(const size_t max_size) : fields{ std::make_shared<Fields>() }, max_size{ max_size + 1 }
{
fields->resize(this->max_size);
}
auto clear(const uint32_t field) const -> void
{
if (field >= max_size)
throw std::runtime_error("field range error");
auto& fld = fields->at(field);
if (!fld.empty())
fld.clear();
}
auto has(const uint32_t field, const size_t index = 0) const -> bool
{
if (field >= max_size)
throw std::runtime_error("field range error");
auto& fld = fields->at(field);
return fld.size() > index;
}
auto count(const uint32_t field) const -> size_t
{
if (field >= max_size)
throw std::runtime_error("field range error");
auto& fld = fields->at(field);
return fld.size();
}
auto add(const uint32_t field, const Entry& entry) const -> void
{
if (field >= max_size)
throw std::runtime_error("field range error");
fields->at(field).emplace_back(entry);
}
auto set(const uint32_t field, const Entry& entry, const size_t index = 0) const -> void
{
if (field >= max_size)
throw std::runtime_error("field range error");
auto& fld = fields->at(field);
if (index == 0 && fld.empty())
{
fld.emplace_back(entry);
}
else
{
if (index >= fld.size())
throw std::runtime_error("field range error");
fld.at(index) = entry;
}
}
auto get(const uint32_t field, const size_t index = 0) const -> std::string
{
if (field >= max_size)
throw std::runtime_error("field range error");
const auto& fld = fields->at(field);
if (index >= fld.size())
throw std::runtime_error("field range error");
return fld.at(index).first;
}
auto get_all(const uint32_t field) const -> std::vector<std::string>
{
if (field >= max_size)
throw std::runtime_error("field range error");
const auto& fld = fields->at(field);
std::vector<std::string> ret;
for (const auto& v : fld)
ret.emplace_back(v.first);
return std::move(ret);
}
};
template <int Field, typename Type>
struct header
{
static constexpr uint32_t field = Field;
static constexpr e_field_type type = Type::field_type;
static constexpr e_wire_type wire_type = k_wire_type_for_field_type[type];
};
struct msg
{
static constexpr e_field_type field_type = TYPE_STRING;
using type = std::string;
virtual ~msg() = default;
msg() = delete;
explicit msg(const size_t max_size) : fv_{ field_vector(max_size) }
{
}
auto serialize() const -> std::string
{
std::string result;
for (const auto& f0 : *fv_.fields)
for (const auto& f1 : f0)
result.append(f1.second);
return std::move(result);
}
auto parse(const uint8_t* buf, size_t bytes) -> void
{
if (buf == nullptr)
return;
size_t pos = 0, bytes_read;
uint32_t field, wire_type;
std::string field_value_bytes, field_full_bytes;
while (pos < bytes)
{
std::tie(field, wire_type, field_value_bytes, field_full_bytes) = utils::read_field(buf + pos, bytes_read);
if (bytes_read == 0)
break;
if (field >= fv_.max_size)
throw std::runtime_error("field range error");
fv_.fields->at(field).emplace_back(field_value_bytes, field_full_bytes);
pos += bytes_read;
}
}
protected:
const field_vector fv_;
};
template <int Field, typename Type>
struct field
{
virtual ~field() = default;
explicit field(const field_vector& fv) : fv_{ fv }
{
}
auto clear() const -> void
{
fv_.clear(hdr.field);
}
auto has(size_t index = 0) const -> bool
{
return fv_.has(hdr.field, index);
}
auto count() const -> size_t
{
return fv_.count(hdr.field);
}
protected:
static constexpr header<Field, Type> hdr{};
const field_vector fv_;
};
}
template <int Field, typename Type, typename S = void>
struct pbfield;
template <int Field, typename Type>
struct pbfield<Field, Type, typename std::enable_if<!std::is_base_of<base::msg, Type>::value>::type
> : base::field<Field, Type>
{
virtual ~pbfield() = default;
explicit pbfield(const base::field_vector& fv) : base::field<Field, Type>{ fv }
{
}
using type = typename Type::type;
auto add(type&& value) const -> void
{
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value);
fv_.add(hdr.field, pair);
}
auto set(type&& value, size_t index = 0) const -> void
{
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value);
fv_.set(hdr.field, pair, index);
}
auto set(const type& value, size_t index = 0) const -> void
{
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, value);
fv_.set(hdr.field, pair, index);
}
auto set(std::vector<type>&& values) const -> void
{
fv_.clear(hdr.field);
for (auto& v : values)
{
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v);
fv_.add(hdr.field, pair);
}
}
auto set(std::vector<type>& values) const -> void
{
fv_.clear(hdr.field);
for (auto& v : values)
{
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v);
fv_.add(hdr.field, pair);
}
}
auto get_all() const -> std::vector<type>
{
const auto values = fv_.get_all(hdr.field);
std::vector<type> ret;
for (const auto& v : values)
ret.emplace_back(Type::get(v));
return std::move(ret);
}
auto get(size_t index = 0) const -> type
{
const auto value = fv_.get(hdr.field, index);
return Type::get(value);
}
private:
using base::field<Field, Type>::hdr;
using base::field<Field, Type>::fv_;
};
template <int Field, typename Type>
struct pbfield<Field, Type, typename std::enable_if<std::is_base_of<base::msg, Type>::value>::type
> : base::field<Field, Type>
{
virtual ~pbfield() = default;
explicit pbfield(const base::field_vector& fv) : base::field<Field, Type>{ fv }
{
}
using type = typename Type::type;
auto add(const Type& value) const -> void
{
const auto v = value.serialize();
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v);
fv_.add(hdr.field, pair);
}
auto set(const Type& value, size_t index = 0) const -> void
{
const auto v = value.serialize();
const auto pair = utils::get_field_bytes(hdr.field, hdr.wire_type, v);
fv_.set(hdr.field, pair, index);
}
auto get_all() const -> std::vector<Type>
{
const auto values = fv_.get_all(hdr.field);
std::vector<Type> ret;
for (const auto& v : values)
{
const auto s = types::String::get(v);
ret.emplace_back(s);
}
return std::move(ret);
}
auto get(size_t index = 0) const -> Type
{
const auto value = fv_.get(hdr.field, index);
const auto s = types::String::get(value);
return std::move(Type(s));
}
private:
using base::field<Field, Type>::hdr;
using base::field<Field, Type>::fv_;
};
template <size_t MsgSize>
struct pbmsg : base::msg
{
virtual ~pbmsg() = default;
explicit pbmsg() : msg(MsgSize)
{
}
explicit pbmsg(void* buf, size_t bytes) : msg(MsgSize)
{
parse(reinterpret_cast<const uint8_t*>(buf), bytes);
}
explicit pbmsg(const std::string& buf) : msg(MsgSize)
{
parse(reinterpret_cast<const uint8_t*>(buf.data()), buf.size());
}
};
}

1280
SpyCustom/platform.h Normal file

File diff suppressed because it is too large Load Diff

262
SpyCustom/protobuffs.cpp Normal file
View File

@ -0,0 +1,262 @@
#include "Protobuffs.hpp"
#include "Interfaces.hpp"
#include "inventory_changer.h"
extern Protobuffs ProtoFeatures;
#define CAST(cast, address, add) reinterpret_cast<cast>((uint32_t)address + (uint32_t)add)
void Protobuffs::WritePacket(std::string packet, void* thisPtr, void* oldEBP, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize)
{
if ((uint32_t)packet.size() <= cubDest - 8)
{
memcpy((void*)((DWORD)pubDest + 8), (void*)packet.data(), packet.size());
*pcubMsgSize = packet.size() + 8;
}
else if (iff.g_pMemAlloc)
{
auto memPtr = *CAST(void**, thisPtr, 0x18);
auto memPtrSize = *CAST(uint32_t*, thisPtr, 0x1C);
auto newSize = (memPtrSize - cubDest) + packet.size() + 8;
auto memory = iff.g_pMemAlloc->Realloc(memPtr, newSize + 4);
*CAST(void**, thisPtr, 0x18) = memory;
*CAST(uint32_t*, thisPtr, 0x1C) = newSize;
*CAST(void**, oldEBP, -0x14) = memory;
memcpy(CAST(void*, memory, 0x1C), (void*)packet.data(), packet.size());
*pcubMsgSize = packet.size() + 8;
}
}
static bool onceChanger = false;
void Protobuffs::ReceiveMessage(void* thisPtr, void* oldEBP, uint32_t messageType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize)
{
if (messageType == k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello)
{
#ifdef DEBUG
printf("Packet == k_EMsgGCCStrike15_v2_MatchmakingGC2ClientHello\n");
#endif
if (g_Options.profile_active) {
MatchmakingGC2ClientHello msg((void*)((DWORD)pubDest + 8), *pcubMsgSize - 8);
MatchmakingGC2ClientHello::PlayerCommendationInfo commendations;
commendations.cmd_friendly().set(g_Options.comfriendly);
commendations.cmd_teaching().set(g_Options.comteacher);
commendations.cmd_leader().set(g_Options.comleader);
msg.commendation().set(commendations);
msg.player_level().set(g_Options.level);
msg.player_cur_xp().set(g_Options.xp);
if (g_Options.banduration != 0) {
msg.penalty_reason().set(g_Options.banreason);
msg.penalty_seconds().set(g_Options.banduration);
}
msg.vac_banned().set(g_Options.vacban);
MatchmakingGC2ClientHello::PlayerRankingInfo ranking;
ranking.account_id().set(iff.g_SteamUser->GetSteamID().GetAccountID());
ranking.rank_type_id().set(6);
ranking.rank_id().set(g_Options.rankz.value->arr[0].rank);
ranking.wins().set(g_Options.rankz.value->arr[0].wins);
msg.ranking().set(ranking);
auto packet = msg.serialize();
WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize);
#ifdef DEBUG
printf("send packet 0 6 rank %d wins %d\n", g_Options.rankz.value->arr[0].rank, g_Options.rankz.value->arr[0].wins);
#endif
}
}
else if (messageType == k_EMsgGCCStrike15_v2_ClientGCRankUpdate)
{
#ifdef DEBUG
printf("Packet == k_EMsgGCCStrike15_v2_ClientGCRankUpdate\n");
#endif
if (g_Options.profile_active) {
CMsgGCCStrike15_v2_ClientGCRankUpdate msg((void*)((DWORD)pubDest + 8), *pcubMsgSize - 8);
auto ranking = msg.ranking().get();
int ranktype = ranking.rank_type_id().get();
#ifdef DEBUG
printf("ranktype = %d\n", ranktype);
#endif
int rankcount = 0;
if (ranktype == 7) rankcount = 1;
if (ranktype == 10) rankcount = 2;
ranking.rank_id().set(g_Options.rankz.value->arr[rankcount].rank);
ranking.wins().set(g_Options.rankz.value->arr[rankcount].wins);
msg.ranking().set(ranking);
auto packet = msg.serialize();
WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize);
}
}
else if (messageType == k_EMsgGCClientWelcome)
{
#ifdef DEBUG
printf("Packet == k_EMsgGCClientWelcome\n");
#endif
auto packet = inventory_changer(pubDest, pcubMsgSize);
WritePacket(packet, thisPtr, oldEBP, pubDest, cubDest, pcubMsgSize);
}
#ifdef DEBUG
printf(".GC Receive: %d\n", messageType);
#endif
}
bool Protobuffs::PreSendMessage(uint32_t& unMsgType, void* pubData, uint32_t& cubData)
{
uint32_t MessageType = unMsgType & 0x7FFFFFFF;
#ifdef DEBUG
printf(".GC Sent: %d\n", MessageType);
#endif
return true;
}
bool Protobuffs::SendClientHello()
{
CMsgClientHello msg;
msg.client_session_need().set(1);
auto packet = msg.serialize();
void* ptr = malloc(packet.size() + 8);
if (!ptr)
return false;
((uint32_t*)ptr)[0] = k_EMsgGCClientHello | ((DWORD)1 << 31);
((uint32_t*)ptr)[1] = 0;
memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size());
bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCClientHello | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK;
free(ptr);
return result;
}
bool Protobuffs::SendMatchmakingClient2GCHello()
{
ProtoWriter msg(0);
auto packet = msg.serialize();
void* ptr = malloc(packet.size() + 8);
if (!ptr)
return false;
((uint32_t*)ptr)[0] = k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello | ((DWORD)1 << 31);
((uint32_t*)ptr)[1] = 0;
memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size());
bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCCStrike15_v2_MatchmakingClient2GCHello | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK;
free(ptr);
return result;
}
bool Protobuffs::SendClientGcRankUpdate()
{
MatchmakingGC2ClientHello::PlayerRankingInfo rank_wingman;
rank_wingman.rank_type_id().set(7);
CMsgGCCStrike15_v2_ClientGCRankUpdate msg;
msg.ranking().set(rank_wingman);
auto packet = msg.serialize();
void* ptr = malloc(packet.size() + 8);
if (!ptr)
return false;
((uint32_t*)ptr)[0] = k_EMsgGCCStrike15_v2_ClientGCRankUpdate | ((DWORD)1 << 31);
((uint32_t*)ptr)[1] = 0;
memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size());
bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCCStrike15_v2_ClientGCRankUpdate | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK;
free(ptr);
return result;
}
bool Protobuffs::EquipWeapon(int weaponid, int classid, int slotid)
{
CMsgAdjustItemEquippedState msg;
msg.item_id().set(START_ITEM_INDEX + weaponid);
msg.new_class().set(classid);
msg.new_slot().set(slotid);
msg.swap().set(true);
auto packet = msg.serialize();
void* ptr = malloc(packet.size() + 8);
if (!ptr)
return false;
((uint32_t*)ptr)[0] = k_EMsgGCAdjustItemEquippedState | ((DWORD)1 << 31);
((uint32_t*)ptr)[1] = 0;
memcpy((void*)((DWORD)ptr + 8), (void*)packet.data(), packet.size());
bool result = iff.g_SteamGameCoordinator->GCSendMessage(k_EMsgGCAdjustItemEquippedState | ((DWORD)1 << 31), ptr, packet.size() + 8) == k_EGCResultOK;
free(ptr);
return result;
}
VMTHook* ProtoHook = nullptr;
Protobuffs ProtoFeatures;
EGCResult __fastcall hkGCRetrieveMessage(void* ecx, void*, uint32_t* punMsgType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize)
{
static auto oGCRetrieveMessage = ProtoHook->GetOriginal<EGCResult(__thiscall*)(void*, uint32_t* punMsgType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize)>(2);
auto status = oGCRetrieveMessage(ecx, punMsgType, pubDest, cubDest, pcubMsgSize);
if (status == k_EGCResultOK)
{
void* thisPtr = nullptr;
__asm mov thisPtr, ebx;
auto oldEBP = *reinterpret_cast<void**>((uint32_t)_AddressOfReturnAddress() - 4);
uint32_t messageType = *punMsgType & 0x7FFFFFFF;
ProtoFeatures.ReceiveMessage(thisPtr, oldEBP, messageType, pubDest, cubDest, pcubMsgSize);
}
return status;
}
EGCResult __fastcall hkGCSendMessage(void* ecx, void*, uint32_t unMsgType, const void* pubData, uint32_t cubData)
{
static auto oGCSendMessage = ProtoHook->GetOriginal<EGCResult(__thiscall*)(void*, uint32_t unMsgType, const void* pubData, uint32_t cubData)>(0);
bool sendMessage = ProtoFeatures.PreSendMessage(unMsgType, const_cast<void*>(pubData), cubData);
if (!sendMessage)
return k_EGCResultOK;
return oGCSendMessage(ecx, unMsgType, const_cast<void*>(pubData), cubData);
}

30
SpyCustom/protobuffs.hpp Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <windows.h>
#include <string>
#include "VMT.hpp"
#include "sdk/steam.h"
#include "intrin.h"
extern VMTHook* ProtoHook;
class Protobuffs
{
public:
static void WritePacket(std::string packet, void* thisPtr, void* oldEBP, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize);
void ReceiveMessage(void* thisPtr, void* oldEBP, uint32_t messageType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize);
bool PreSendMessage(uint32_t& unMsgType, void* pubData, uint32_t& cubData);
bool SendClientHello();
bool SendMatchmakingClient2GCHello();
bool SendClientGcRankUpdate();
bool EquipWeapon(int weaponid, int classid, int slotid);
};
extern Protobuffs ProtoFeatures;
EGCResult __fastcall hkGCRetrieveMessage(void* ecx, void*, uint32_t* punMsgType, void* pubDest, uint32_t cubDest, uint32_t* pcubMsgSize);
EGCResult __fastcall hkGCSendMessage(void* ecx, void*, uint32_t unMsgType, const void* pubData, uint32_t cubData);

195
SpyCustom/proxies.hpp Normal file
View File

@ -0,0 +1,195 @@
#pragma once
RecvVarProxyFn fnSequenceProxyFn = NULL;
void SetViewModelSequence(const CRecvProxyData* pDataConst, void* pStruct, void* pOut) {
CRecvProxyData* pData = const_cast<CRecvProxyData*>(pDataConst);
C_BaseViewModel* pViewModel = (C_BaseViewModel*)pStruct;
if (pViewModel) {
IClientEntity* pOwner = iff.g_pEntityList->GetClientEntityFromHandle(pViewModel->GetOwner());
if (pOwner && pOwner->GetIndex() == iff.g_pEngineClient->GetLocalPlayer()) {
const model_t* pModel = iff.g_pMdlInfo->GetModel(pViewModel->GetModelIndex());
const char* szModel = iff.g_pMdlInfo->GetModelName(pModel);
int m_nSequence = pData->m_Value.m_Int;
auto model = fnv2::hashRuntime(szModel);
static int defknifethash = fnv2::hash("models/weapons/v_knife_default_t.mdl");
static int defknifecthash = fnv2::hash("models/weapons/v_knife_default_ct.mdl");
if (model == defknifethash || model == defknifecthash) model = fnv2::hash(g_Options.weapons.value->arr[0].model);
for (int i = 2; i < g_Options.models.value->itemcount; i++) {
if (model == g_Options.models.value->arr[i].vmodel_hash)
{
if (g_Options.models.value->arr[i].seq_active)
m_nSequence = g_Options.models.value->arr[i].seqs[m_nSequence].seq_repl;
break;
}
if (model == fnv2::hash(g_Options.models.value->arr[i].vmodel_orig))
{
if (g_Options.models.value->arr[i].seq_active)
m_nSequence = g_Options.models.value->arr[i].seqs[m_nSequence].seq_repl;
break;
}
}
switch (model) {
case fnv2::hash("models/weapons/v_knife_butterfly.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_DRAW:
m_nSequence = random(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); break;
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = random(SEQUENCE_BUTTERFLY_LOOKAT01, SEQUENCE_BUTTERFLY_LOOKAT03); break;
default:
m_nSequence++;
}
break;
}
case fnv2::hash("models/weapons/v_knife_falchion_advanced.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_IDLE2:
m_nSequence = SEQUENCE_FALCHION_IDLE1; break;
case SEQUENCE_DEFAULT_HEAVY_MISS1:
m_nSequence = random(SEQUENCE_FALCHION_HEAVY_MISS1, SEQUENCE_FALCHION_HEAVY_MISS1_NOFLIP); break;
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = random(SEQUENCE_FALCHION_LOOKAT01, SEQUENCE_FALCHION_LOOKAT02); break;
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
m_nSequence = m_nSequence; break;
default:
m_nSequence--;
}
break;
}
case fnv2::hash("models/weapons/v_knife_push.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_IDLE2:
m_nSequence = SEQUENCE_DAGGERS_IDLE1; break;
case SEQUENCE_DEFAULT_LIGHT_MISS1:
case SEQUENCE_DEFAULT_LIGHT_MISS2:
m_nSequence = random(SEQUENCE_DAGGERS_LIGHT_MISS1, SEQUENCE_DAGGERS_LIGHT_MISS5); break;
case SEQUENCE_DEFAULT_HEAVY_MISS1:
m_nSequence = random(SEQUENCE_DAGGERS_HEAVY_MISS2, SEQUENCE_DAGGERS_HEAVY_MISS1); break;
case SEQUENCE_DEFAULT_HEAVY_HIT1:
case SEQUENCE_DEFAULT_HEAVY_BACKSTAB:
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = m_nSequence + 3; break;
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
m_nSequence = m_nSequence; break;
default:
m_nSequence = m_nSequence + 2;
}
break;
}
case fnv2::hash("models/weapons/v_knife_survival_bowie.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_DRAW:
case SEQUENCE_DEFAULT_IDLE1:
m_nSequence = m_nSequence; break;
case SEQUENCE_DEFAULT_IDLE2:
m_nSequence = SEQUENCE_BOWIE_IDLE1; break;
default:
m_nSequence = m_nSequence - 1;
}
break;
}
case fnv2::hash("models/weapons/v_knife_ursus.mdl"):
case fnv2::hash("models/weapons/v_knife_skeleton.mdl"):
case fnv2::hash("models/weapons/v_knife_outdoor.mdl"):
case fnv2::hash("models/weapons/v_knife_cord.mdl"):
case fnv2::hash("models/weapons/v_knife_canis.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_DRAW:
m_nSequence = random(SEQUENCE_BUTTERFLY_DRAW, SEQUENCE_BUTTERFLY_DRAW2); break;
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = random(SEQUENCE_BUTTERFLY_LOOKAT01, 14); break;
default:
m_nSequence = m_nSequence + 1;
}
break;
}
case fnv2::hash("models/weapons/v_knife_stiletto.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = random(12, 13); break;
}
break;
}
case fnv2::hash("models/weapons/v_knife_widowmaker.mdl"):
{
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_LOOKAT01:
m_nSequence = random(14, 15); break;
}
break;
}
case fnv2::hash("models/weapons/v_fists.mdl"):
case fnv2::hash("models/weapons/v_axe.mdl"):
case fnv2::hash("models/weapons/v_hammer.mdl"):
case fnv2::hash("models/weapons/v_spanner.mdl"):
{
static int lastpunch = 3;
switch (m_nSequence)
{
case SEQUENCE_DEFAULT_DRAW:
m_nSequence = 1; break;
case 1:
case 2:
case 12:
m_nSequence = 0; break;
default:
if (lastpunch == 3) lastpunch = 2; else lastpunch = 3;
m_nSequence = lastpunch;
}
break;
}
}
#ifdef DEBUG
cout << "activ " << (char*)pViewModel->GetSequenceActivity(m_nSequence);
printf(" new seq %d (%s)\n ", m_nSequence, szModel);
#endif
pData->m_Value.m_Int = m_nSequence;
}
}
fnSequenceProxyFn(pData, pStruct, pOut);
}

11
SpyCustom/resource.h Normal file
View File

@ -0,0 +1,11 @@
#define IDR_WAVE1 101
#define IDR_WAVE2 102
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -0,0 +1,31 @@
#ifndef ANALOGCODE_H
#define ANALOGCODE_H
#ifdef _WIN32
#pragma once
#endif
#include "InputEnums.h"
#define JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ( JOYSTICK_FIRST_AXIS + ((_joystick) * MAX_JOYSTICK_AXES) + (_axis) )
#define JOYSTICK_AXIS( _joystick, _axis ) ( (AnalogCode_t)JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) )
enum AnalogCode_t
{
ANALOG_CODE_INVALID = -1,
MOUSE_X = 0,
MOUSE_Y,
MOUSE_XY,
MOUSE_WHEEL,
JOYSTICK_FIRST_AXIS,
JOYSTICK_LAST_AXIS = JOYSTICK_AXIS_INTERNAL(MAX_JOYSTICKS - 1, MAX_JOYSTICK_AXES - 1),
ANALOG_CODE_LAST,
};
#endif

View File

@ -0,0 +1,231 @@
#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"
#include <string>
#include <vector>
extern ImFont* ifontmini;
extern ImFont* ifont;
namespace ImGui {
bool identical(const char* buf, const char* item) {
size_t buf_size = strlen(buf);
size_t item_size = strlen(item);
if (buf_size >= item_size) return false;
for (int i = 0; i < strlen(buf); ++i)
if (buf[i] != item[i]) return false;
return true;
};
int propose(ImGuiInputTextCallbackData* data) {
if (strlen(data->Buf) == 0) return 0;
const char** items = static_cast<std::pair<const char**, size_t>*> (data->UserData)->first;
size_t length = static_cast<std::pair<const char**, size_t>*> (data->UserData)->second;
if (IsKeyPressedMap(ImGuiKey_Backspace)) {
if (data->SelectionEnd != data->SelectionStart)
if (data->BufTextLen > 0)
if (data->CursorPos > 0)
data->DeleteChars(data->CursorPos - 1, 1);
return 0;
}
if (IsKeyPressedMap(ImGuiKey_Delete)) return 0;
for (int i = 0; i < length; i++) {
if (identical(data->Buf, items[i])) {
const int cursor = data->CursorPos;
data->DeleteChars(0, data->BufTextLen);
data->InsertChars(0, items[i]);
data->CursorPos = cursor;
data->SelectionStart = cursor;
data->SelectionEnd = data->BufTextLen;
break;
}
}
return 0;
}
bool TextInputComboBox(const char* id, char* buffer, size_t maxInputSize, const char* items[], size_t item_len, short showMaxItems) {
if (showMaxItems == 0)
showMaxItems = item_len;
ImGui::PushID(id);
std::pair<const char**, size_t> pass(items, item_len);
bool ret = ImGui::InputText("##in", buffer, maxInputSize, 0, 0, 0);
ImGui::OpenPopupOnItemClick("combobox");
ImVec2 pos = ImGui::GetItemRectMin();
ImVec2 size = ImGui::GetItemRectSize();
ImGui::SameLine(0, 0);
if (ImGui::ArrowButton("##openCombo", ImGuiDir_Down)) {
ImGui::OpenPopup("combobox");
}
ImGui::OpenPopupOnItemClick("combobox");
pos.y += size.y;
size.x += ImGui::GetItemRectSize().x;
size.y += 5 + (size.y * showMaxItems);
ImGui::SetNextWindowPos(pos);
ImGui::SetNextWindowSize(size);
ImGuiStyle* style = &ImGui::GetStyle();
ImGui::PushFont(ifontmini);
style->ItemSpacing = ImVec2(7.0f, 2.0f);
style->WindowPadding = ImVec2(5.0f, 5.0f);
if (ImGui::BeginPopup("combobox", ImGuiWindowFlags_::ImGuiWindowFlags_NoMove)) {
for (int i = 0; i < item_len; i++)
if (ImGui::Selectable(items[i]))
strcpy(buffer, items[i]);
ImGui::EndPopup();
}
style->WindowPadding = ImVec2(20.f, 20.0f);
style->ItemSpacing = ImVec2(7.0f, 15.0f);
ImGui::PushFont(ifont);
ImGui::PopID();
ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
return ret;
}
bool TextInputComboBox(const char* id, char* buffer, size_t maxInputSize, std::vector<std::string> items, short showMaxItems) {
const ImVec2 label_size = CalcTextSize(id, NULL, true);
if (label_size.x > 0) {
ImVec2 savecursor = ImGui::GetCursorPos();
ImVec2 newcursor = savecursor;
savecursor.y += 20.0f;
ImGui::SetCursorPos(newcursor);
ImGui::TextEx(id);
ImGui::SetCursorPos(savecursor);
}
size_t item_len = items.size();
if (showMaxItems == 0)
showMaxItems = item_len;
ImGui::PushID(id);
std::pair<std::vector<std::string>, size_t> pass(items, item_len);
ImGuiStyle* style = &ImGui::GetStyle();
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), CalcItemWidth(), label_size.y + style->FramePadding.y * 2.0f);
ImGui::SetNextItemWidth(frame_size.x - 19.0f);
bool ret = ImGui::InputText("##in", buffer, maxInputSize, 0, 0, 0);
ImGui::OpenPopupOnItemClick("combobox");
ImVec2 pos = ImGui::GetItemRectMin();
ImVec2 size = ImGui::GetItemRectSize();
ImGui::SameLine(0, 0);
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 5.0f);
if (ImGui::ArrowButton("##openCombo", ImGuiDir_Down)) {
ImGui::OpenPopup("combobox");
}
ImGui::OpenPopupOnItemClick("combobox");
pos.y += size.y;
ImGui::SetNextWindowPos(pos);
size.x += 15.0f;
ImGui::SetNextWindowSizeConstraints(size, ImVec2(400.0f, 200.0f));
ImGui::PushFont(ifontmini);
style->ItemSpacing = ImVec2(7.0f, 2.0f);
style->WindowPadding = ImVec2(5.0f, 5.0f);
if (ImGui::BeginPopup("combobox", ImGuiWindowFlags_::ImGuiWindowFlags_NoMove)) {
for (int i = 0; i < item_len; i++)
if (ImGui::Selectable(items[i].c_str()))
strcpy(buffer, items[i].c_str());
ImGui::EndPopup();
}
style->WindowPadding = ImVec2(20.f, 20.0f);
style->ItemSpacing = ImVec2(7.0f, 15.0f);
ImGui::PushFont(ifont);
ImGui::PopID();
return ret;
}
}

View File

@ -0,0 +1,156 @@
#pragma once
#include <cstring>
#include <cassert>
#include "Interfaces.hpp"
using proc_t = void(*)();
class vmt_base_hook
{
protected:
constexpr vmt_base_hook() = default;
public:
~vmt_base_hook()
{
if (m_new_vmt)
delete[](m_new_vmt - 1);
}
vmt_base_hook(const vmt_base_hook&) = delete;
vmt_base_hook(vmt_base_hook&&) = delete;
vmt_base_hook& operator=(const vmt_base_hook&) = delete;
vmt_base_hook& operator=(vmt_base_hook&&) = delete;
protected:
auto initialize(proc_t* original_table) -> void
{
m_old_vmt = original_table;
size_t size = 0;
while (m_old_vmt[size] && is_code_ptr(m_old_vmt[size]))
++size;
m_new_vmt = (new proc_t[size + 1]) + 1;
memcpy(m_new_vmt - 1, m_old_vmt - 1, sizeof(void*) * (size + 1));
}
constexpr auto leak_table() -> void
{
m_new_vmt = nullptr;
}
auto hook_instance(void* inst) const -> void
{
auto& vtbl = *reinterpret_cast<proc_t**>(inst);
assert(vtbl == m_old_vmt || vtbl == m_new_vmt);
vtbl = m_new_vmt;
}
auto unhook_instance(void* inst) const -> void
{
auto& vtbl = *reinterpret_cast<proc_t**>(inst);
assert(vtbl == m_old_vmt || vtbl == m_new_vmt);
vtbl = m_old_vmt;
}
auto initialize_and_hook_instance(void* inst) -> bool
{
auto& vtbl = *reinterpret_cast<proc_t**>(inst);
auto initialized = false;
if (!m_old_vmt)
{
initialized = true;
initialize(vtbl);
}
hook_instance(inst);
return initialized;
}
template <typename Fn>
auto hook_function(Fn hooked_fn, const std::size_t index) -> Fn
{
m_new_vmt[index] = (proc_t)(hooked_fn);
return (Fn)(m_old_vmt[index]);
}
template<typename T>
auto apply_hook(std::size_t idx) -> void
{
T::m_original = hook_function(&T::hooked, idx);
}
template <typename Fn = uintptr_t>
auto get_original_function(const int index) -> Fn
{
return (Fn)(m_old_vmt[index]);
}
private:
proc_t* m_new_vmt = nullptr;
proc_t* m_old_vmt = nullptr;
};
class vmt_smart_hook : vmt_base_hook
{
public:
vmt_smart_hook(void* class_base)
: m_class{ class_base }
{
initialize_and_hook_instance(class_base);
}
~vmt_smart_hook()
{
unhook_instance(m_class);
}
vmt_smart_hook(const vmt_smart_hook&) = delete;
vmt_smart_hook(vmt_smart_hook&&) = delete;
vmt_smart_hook& operator=(const vmt_smart_hook&) = delete;
vmt_smart_hook& operator=(vmt_smart_hook&&) = delete;
auto rehook() const -> void
{
hook_instance(m_class);
}
auto unhook() const -> void
{
unhook_instance(m_class);
}
using vmt_base_hook::apply_hook;
using vmt_base_hook::get_original_function;
using vmt_base_hook::hook_function;
private:
void* m_class = nullptr;
};
class vmt_multi_hook : vmt_base_hook
{
public:
constexpr vmt_multi_hook() = default;
~vmt_multi_hook()
{
leak_table();
}
vmt_multi_hook(const vmt_multi_hook&) = delete;
vmt_multi_hook(vmt_multi_hook&&) = delete;
vmt_multi_hook& operator=(const vmt_multi_hook&) = delete;
vmt_multi_hook& operator=(vmt_multi_hook&&) = delete;
using vmt_base_hook::apply_hook;
using vmt_base_hook::get_original_function;
using vmt_base_hook::hook_function;
using vmt_base_hook::hook_instance;
using vmt_base_hook::unhook_instance;
using vmt_base_hook::initialize;
using vmt_base_hook::initialize_and_hook_instance;
};

145
SpyCustom/vpkparser.h Normal file
View File

@ -0,0 +1,145 @@
#pragma once
#include <fstream>
#include <string>
#include <optional>
#include <unordered_map>
#pragma pack(push,1)
struct vpk_header_t
{
uint32_t signature;
uint32_t version;
uint32_t tree_size;
uint32_t file_data_section_size;
uint32_t archive_md5_section_size;
uint32_t other_md5_section_size;
uint32_t signature_section_size;
};
struct dir_entry_t
{
uint32_t crc;
uint16_t preload_bytes;
uint16_t archive_index;
uint32_t entry_offset;
uint32_t entry_length;
uint16_t terminator;
};
#pragma pack(pop)
class c_vpk_entry
{
public:
c_vpk_entry() = default;
c_vpk_entry(const std::string& base_file, const std::string& path, const dir_entry_t& entry) :_base_file(base_file), _path(path), _entry(entry) {}
std::optional<std::vector<uint8_t>> get_data()
{
size_t _dir_pos = _base_file.find("dir");
std::string old_number_string = std::to_string(_entry.archive_index);
std::string vpk_file = _base_file.replace(_base_file.begin() + _dir_pos, _base_file.begin() + _dir_pos + 3, std::string(3 - old_number_string.length(), '0') + old_number_string);
std::ifstream stream(vpk_file, std::ios::binary);
if (!stream.is_open())
return {};
uint8_t* data = new uint8_t[_entry.entry_length];
stream.seekg(_entry.entry_offset, stream.beg);
stream.read((char*)data, _entry.entry_length);
stream.close();
std::vector<uint8_t> data_vector(data, data + _entry.entry_length);
delete[] data;
return data_vector;
}
std::vector<uint8_t> preload_bytes = {};
std::string _base_file = {};
std::string _path = {};
dir_entry_t _entry = {};
};
class c_vpk_archive
{
public:
bool load(const std::string& name)
{
std::ifstream stream(name, std::ios::binary);
if (!stream.is_open())
return false;
try
{
vpk_header_t file_header = {};
stream.read((char*)&file_header, sizeof(file_header));
if (file_header.signature != 0x55aa1234)
{
stream.close();
return false;
}
if (file_header.version != 2)
{
stream.close();
return false;
}
while (true)
{
std::string extension;
std::getline(stream, extension, '\x00');
if (extension.empty())
break;
while (true)
{
std::string directory;
std::getline(stream, directory, '\x00');
if (directory.empty())
break;
while (true)
{
std::string file_name;
std::getline(stream, file_name, '\x00');
if (file_name.empty())
break;
std::string path = directory + '/' + file_name + '.' + extension;
dir_entry_t dir_entry;
stream.read((char*)&dir_entry, sizeof(dir_entry));
c_vpk_entry vpk_entry(name, path, dir_entry);
if (dir_entry.preload_bytes)
{
uint8_t* bytes = new uint8_t[dir_entry.preload_bytes];
stream.read((char*)bytes, dir_entry.preload_bytes);
vpk_entry.preload_bytes = std::vector<uint8_t>(bytes, bytes + dir_entry.preload_bytes);
delete[] bytes;
}
if (!files.count(path))
files[path] = vpk_entry;
}
}
}
}
catch (const std::exception& e) { return false; }
stream.close();
return true;
}
std::optional<c_vpk_entry> get_file(const std::string& name)
{
if (files.count(name))
return files[name];
return {};
}
std::unordered_map<std::string, c_vpk_entry> files = {};
};

View File

@ -0,0 +1,93 @@
#ifndef ZIP_UNCOMPRESSED_H
#define ZIP_UNCOMPRESSED_H
#ifdef _WIN32
#pragma once
#endif
#include "datamap.h"
#define PKID( a, b ) (((b)<<24)|((a)<<16)|('K'<<8)|'P')
#pragma pack(1)
struct ZIP_EndOfCentralDirRecord
{
DECLARE_BYTESWAP_DATADESC();
unsigned int signature;
unsigned short numberOfThisDisk;
unsigned short numberOfTheDiskWithStartOfCentralDirectory;
unsigned short nCentralDirectoryEntries_ThisDisk;
unsigned short nCentralDirectoryEntries_Total;
unsigned int centralDirectorySize;
unsigned int startOfCentralDirOffset;
unsigned short commentLength;
};
struct ZIP_FileHeader
{
DECLARE_BYTESWAP_DATADESC();
unsigned int signature;
unsigned short versionMadeBy;
unsigned short versionNeededToExtract;
unsigned short flags;
unsigned short compressionMethod;
unsigned short lastModifiedTime;
unsigned short lastModifiedDate;
unsigned int crc32;
unsigned int compressedSize;
unsigned int uncompressedSize;
unsigned short fileNameLength;
unsigned short extraFieldLength;
unsigned short fileCommentLength;
unsigned short diskNumberStart;
unsigned short internalFileAttribs;
unsigned int externalFileAttribs;
unsigned int relativeOffsetOfLocalHeader;
};
struct ZIP_LocalFileHeader
{
DECLARE_BYTESWAP_DATADESC();
unsigned int signature;
unsigned short versionNeededToExtract;
unsigned short flags;
unsigned short compressionMethod;
unsigned short lastModifiedTime;
unsigned short lastModifiedDate;
unsigned int crc32;
unsigned int compressedSize;
unsigned int uncompressedSize;
unsigned short fileNameLength;
unsigned short extraFieldLength;
};
#define PRELOAD_SECTION_NAME "__preload_section.pre"
#define PRELOAD_HDR_VERSION 3
#define XZIP_COMMENT_LENGTH 32
#define INVALID_PRELOAD_ENTRY ( (unsigned short)-1 )
struct ZIP_PreloadHeader
{
DECLARE_BYTESWAP_DATADESC();
unsigned int Version;
unsigned int DirectoryEntries;
unsigned int PreloadDirectoryEntries;
unsigned int Alignment;
};
struct ZIP_PreloadDirectoryEntry
{
DECLARE_BYTESWAP_DATADESC();
unsigned int Length;
unsigned int DataOffset;
};
struct ZIP_PreloadRemapTable
{
DECLARE_BYTESWAP_DATADESC();
unsigned short PreloadIndex;
};
#pragma pack()
#endif