mirror of
https://github.com/0TheSpy/Seaside.git
synced 2025-09-19 04:06:03 +08:00
Add files via upload
This commit is contained in:
1295
SpyCustom/ConVars.cpp
Normal file
1295
SpyCustom/ConVars.cpp
Normal file
File diff suppressed because it is too large
Load Diff
107
SpyCustom/Config.hpp
Normal file
107
SpyCustom/Config.hpp
Normal 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
407
SpyCustom/EventListener.hpp
Normal 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
56
SpyCustom/GetVfunc.hpp
Normal 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
201
SpyCustom/Hooks.hpp
Normal 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
180
SpyCustom/Interfaces.cpp
Normal 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
326
SpyCustom/Interfaces.hpp
Normal 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
1830
SpyCustom/KeyValues.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1949
SpyCustom/Menu.hpp
Normal file
1949
SpyCustom/Menu.hpp
Normal file
File diff suppressed because it is too large
Load Diff
57
SpyCustom/NetVarManager.cpp
Normal file
57
SpyCustom/NetVarManager.cpp
Normal 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
217
SpyCustom/NetVarManager.hpp
Normal 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
1102
SpyCustom/Options.hpp
Normal file
File diff suppressed because it is too large
Load Diff
265
SpyCustom/Other.cpp
Normal file
265
SpyCustom/Other.cpp
Normal 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
15
SpyCustom/Other.hpp
Normal 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
76
SpyCustom/PatternScan.cpp
Normal 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
20
SpyCustom/PatternScan.hpp
Normal 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
|
||||
|
207
SpyCustom/PlayerInventory.cpp
Normal file
207
SpyCustom/PlayerInventory.cpp
Normal 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();
|
||||
}
|
138
SpyCustom/PlayerInventory.hpp
Normal file
138
SpyCustom/PlayerInventory.hpp
Normal 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
581
SpyCustom/ProtoParse.h
Normal 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
|
105
SpyCustom/ProtobuffMessages.h
Normal file
105
SpyCustom/ProtobuffMessages.h
Normal 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
28
SpyCustom/Singleton.hpp
Normal 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
427
SpyCustom/SkinChanger.hpp
Normal 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
678
SpyCustom/Skinchanger.cpp
Normal 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
BIN
SpyCustom/SpyCustom.aps
Normal file
Binary file not shown.
80
SpyCustom/SpyCustom.rc
Normal file
80
SpyCustom/SpyCustom.rc
Normal 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
560
SpyCustom/SpyCustom.vcxproj
Normal 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>
|
1225
SpyCustom/SpyCustom.vcxproj.filters
Normal file
1225
SpyCustom/SpyCustom.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
4
SpyCustom/SpyCustom.vcxproj.user
Normal file
4
SpyCustom/SpyCustom.vcxproj.user
Normal 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
75
SpyCustom/VMT.hpp
Normal 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
109
SpyCustom/XorStr.hpp
Normal 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
BIN
SpyCustom/cheat1.aps
Normal file
Binary file not shown.
BIN
SpyCustom/cod.wav
Normal file
BIN
SpyCustom/cod.wav
Normal file
Binary file not shown.
BIN
SpyCustom/crit.wav
Normal file
BIN
SpyCustom/crit.wav
Normal file
Binary file not shown.
55
SpyCustom/csgosdk.h
Normal file
55
SpyCustom/csgosdk.h
Normal 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
561
SpyCustom/detours.h
Normal 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 ⌖ \
|
||||
} \
|
||||
\
|
||||
__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
BIN
SpyCustom/detours.lib
Normal file
Binary file not shown.
389
SpyCustom/dllmain.cpp
Normal file
389
SpyCustom/dllmain.cpp
Normal 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
118
SpyCustom/imgui/imconfig.h
Normal 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
9268
SpyCustom/imgui/imgui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2036
SpyCustom/imgui/imgui.h
Normal file
2036
SpyCustom/imgui/imgui.h
Normal file
File diff suppressed because it is too large
Load Diff
6725
SpyCustom/imgui/imgui_demo.cpp
Normal file
6725
SpyCustom/imgui/imgui_demo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3568
SpyCustom/imgui/imgui_draw.cpp
Normal file
3568
SpyCustom/imgui/imgui_draw.cpp
Normal file
File diff suppressed because it is too large
Load Diff
232
SpyCustom/imgui/imgui_impl_dx9.cpp
Normal file
232
SpyCustom/imgui/imgui_impl_dx9.cpp
Normal 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();
|
||||
}
|
12
SpyCustom/imgui/imgui_impl_dx9.h
Normal file
12
SpyCustom/imgui/imgui_impl_dx9.h
Normal 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();
|
396
SpyCustom/imgui/imgui_impl_win32.cpp
Normal file
396
SpyCustom/imgui/imgui_impl_win32.cpp
Normal 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*)¤t_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);
|
||||
}
|
||||
|
14
SpyCustom/imgui/imgui_impl_win32.h
Normal file
14
SpyCustom/imgui/imgui_impl_win32.h
Normal 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);
|
2224
SpyCustom/imgui/imgui_internal.h
Normal file
2224
SpyCustom/imgui/imgui_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
3073
SpyCustom/imgui/imgui_tables.cpp
Normal file
3073
SpyCustom/imgui/imgui_tables.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7141
SpyCustom/imgui/imgui_widgets.cpp
Normal file
7141
SpyCustom/imgui/imgui_widgets.cpp
Normal file
File diff suppressed because it is too large
Load Diff
403
SpyCustom/imgui/imstb_rectpack.h
Normal file
403
SpyCustom/imgui/imstb_rectpack.h
Normal 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
|
||||
|
968
SpyCustom/imgui/imstb_textedit.h
Normal file
968
SpyCustom/imgui/imstb_textedit.h
Normal 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
|
||||
|
3861
SpyCustom/imgui/imstb_truetype.h
Normal file
3861
SpyCustom/imgui/imstb_truetype.h
Normal file
File diff suppressed because it is too large
Load Diff
397
SpyCustom/inventory_changer.h
Normal file
397
SpyCustom/inventory_changer.h
Normal 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
1785
SpyCustom/mathlib.h
Normal file
File diff suppressed because it is too large
Load Diff
36
SpyCustom/netchannel.hpp
Normal file
36
SpyCustom/netchannel.hpp
Normal 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
110
SpyCustom/netvars.cpp
Normal 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
37
SpyCustom/netvars.hpp
Normal 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
779
SpyCustom/pbwrap.hpp
Normal 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
1280
SpyCustom/platform.h
Normal file
File diff suppressed because it is too large
Load Diff
262
SpyCustom/protobuffs.cpp
Normal file
262
SpyCustom/protobuffs.cpp
Normal 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
30
SpyCustom/protobuffs.hpp
Normal 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
195
SpyCustom/proxies.hpp
Normal 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
11
SpyCustom/resource.h
Normal 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
|
31
SpyCustom/sdk/AnalogCode.h
Normal file
31
SpyCustom/sdk/AnalogCode.h
Normal 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
|
231
SpyCustom/textinputcombobox.cpp
Normal file
231
SpyCustom/textinputcombobox.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
156
SpyCustom/vmt_smart_hook.hpp
Normal file
156
SpyCustom/vmt_smart_hook.hpp
Normal 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
145
SpyCustom/vpkparser.h
Normal 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 = {};
|
||||
};
|
93
SpyCustom/zip_uncompressed.h
Normal file
93
SpyCustom/zip_uncompressed.h
Normal 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
|
Reference in New Issue
Block a user