Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added weapons support #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 196 additions & 155 deletions imCamAim/AdvancedAimingMod.cpp
Original file line number Diff line number Diff line change
@@ -1,171 +1,212 @@
#include "plugin.h"
#include "game_sa\common.h"
#include "game_sa\CCam.h"
#include "CRunningScript.h"

using namespace plugin;

class AdvancedAimingMod {
public:
enum eWeaponAimOffset {
AIM_OFFSET_WEAPON_DEFAULT,
AIM_OFFSET_WEAPON_COLT45,
AIM_OFFSET_WEAPON_SILENCED,
AIM_OFFSET_WEAPON_DESERTEAGLE,
AIM_OFFSET_WEAPON_CHROMEGUN,
AIM_OFFSET_WEAPON_SAWNOFF,
AIM_OFFSET_WEAPON_SHOTGSPA,
AIM_OFFSET_WEAPON_MICROUZI,
AIM_OFFSET_WEAPON_MP5,
AIM_OFFSET_WEAPON_TEC9,
AIM_OFFSET_WEAPON_AK47,
AIM_OFFSET_WEAPON_M4,
AIM_OFFSET_WEAPON_CUNTGUN,
AIM_OFFSET_WEAPON_ROCKETLA,
AIM_OFFSET_WEAPON_HEATSEEK,
AIM_OFFSET_WEAPON_FLAME
};

struct tAimingCamData {
float f0, f1, f2, f3, f4, f5, f6;
};

static tAimingCamData gData[4];
static CVector gOffsets[16];

static unsigned int updateSets;

static bool rightSide;

static void ReadSettings() {
char line[512];
char dummy[128];
float fVal;
FILE *file = fopen(PLUGIN_PATH("aimingSets.dat"), "r");
fgets(line, 512, file);
sscanf(line, "%s %d", dummy, &updateSets);
fgets(line, 512, file);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B4);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B8);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, &fVal);
patch::SetFloat(0x521632, fVal);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B0);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4AC);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4A8);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4A0);
fgets(line, 512, file);
for (int i = 0; i < 4; i++) {
fgets(line, 512, file);
sscanf(line, "%s %f %f %f %f %f %f %f", dummy, &gData[i].f0, &gData[i].f1, &gData[i].f2, &gData[i].f3, &gData[i].f4,
&gData[i].f5, &gData[i].f6);
}
memcpy((void *)0x8CC4C0, gData, 112);
fgets(line, 512, file);
for (int i = 0; i < 16; i++) {
fgets(line, 512, file);
sscanf(line, "%s %f %f %f", dummy, &gOffsets[i].x, &gOffsets[i].y, &gOffsets[i].z);
}
fclose(file);
}

static void _fastcall MyProcess_AimWeapon(CCam *cam, int, CVector const &vec, float arg3, float arg4, float arg5) {
CPed *playa = FindPlayerPed();
if (playa && !playa->m_nPedFlags.bInVehicle) {
int aimTypeId = -1;
switch (playa->m_aWeapons[playa->m_nActiveWeaponSlot].m_Type) {
case WEAPON_PISTOL:
aimTypeId = AIM_OFFSET_WEAPON_COLT45;
break;
case WEAPON_PISTOL_SILENCED:
aimTypeId = AIM_OFFSET_WEAPON_SILENCED;
break;
case WEAPON_DESERT_EAGLE:
aimTypeId = AIM_OFFSET_WEAPON_DESERTEAGLE;
break;
case WEAPON_SHOTGUN:
aimTypeId = AIM_OFFSET_WEAPON_CHROMEGUN;
break;
case WEAPON_SAWNOFF:
aimTypeId = AIM_OFFSET_WEAPON_SAWNOFF;
break;
case WEAPON_SPAS12:
aimTypeId = AIM_OFFSET_WEAPON_SHOTGSPA;
break;
case WEAPON_MICRO_UZI:
aimTypeId = AIM_OFFSET_WEAPON_MICROUZI;
break;
case WEAPON_MP5:
aimTypeId = AIM_OFFSET_WEAPON_MP5;
break;
case WEAPON_TEC9:
aimTypeId = AIM_OFFSET_WEAPON_TEC9;
break;
case WEAPON_AK47:
aimTypeId = AIM_OFFSET_WEAPON_AK47;
break;
case WEAPON_M4:
aimTypeId = AIM_OFFSET_WEAPON_M4;
break;
case WEAPON_COUNTRYRIFLE:
aimTypeId = AIM_OFFSET_WEAPON_CUNTGUN;
break;
case WEAPON_ROCKET:
aimTypeId = AIM_OFFSET_WEAPON_ROCKETLA;
break;
case WEAPON_ROCKET_HS:
aimTypeId = AIM_OFFSET_WEAPON_HEATSEEK;
break;
case WEAPON_FTHROWER:
aimTypeId = AIM_OFFSET_WEAPON_FLAME;
break;
}
if (aimTypeId != -1) {
CVector offset = gOffsets[aimTypeId];

// if rightSide flag enabled
if (rightSide)
offset.x *= -3.0f;

CallMethod<0x521500, CCam *, CVector const&>(cam, playa->TransformFromObjectSpace(offset), arg3, arg4, arg5);
}
else
CallMethod<0x521500, CCam *, CVector const&>(cam, vec, arg3, arg4, arg5);
}
else
CallMethod<0x521500, CCam *, CVector const&>(cam, vec, arg3, arg4, arg5);
}

AdvancedAimingMod() {
// inject our function
patch::RedirectCall(0x527A95, MyProcess_AimWeapon);
// read settings
ReadSettings();

Events::gameProcessEvent += []() {
// check for key-press
if (KeyPressed('Z'))
rightSide = false;
else if (KeyPressed('X'))
rightSide = true;

// update settings
if (updateSets)
ReadSettings();
};
}
enum eWeaponAimOffset {
AIM_OFFSET_WEAPON_DEFAULT,
AIM_OFFSET_WEAPON_COLT45,
AIM_OFFSET_WEAPON_SILENCED,
AIM_OFFSET_WEAPON_DESERTEAGLE,
AIM_OFFSET_WEAPON_CHROMEGUN,
AIM_OFFSET_WEAPON_SAWNOFF,
AIM_OFFSET_WEAPON_SHOTGSPA,
AIM_OFFSET_WEAPON_MICROUZI,
AIM_OFFSET_WEAPON_MP5,
AIM_OFFSET_WEAPON_TEC9,
AIM_OFFSET_WEAPON_AK47,
AIM_OFFSET_WEAPON_M4,
AIM_OFFSET_WEAPON_CUNTGUN,
AIM_OFFSET_WEAPON_ROCKETLA,
AIM_OFFSET_WEAPON_HEATSEEK,
AIM_OFFSET_WEAPON_FLAME
};

struct tAimingCamData {
float f0, f1, f2, f3, f4, f5, f6;
};

struct tAimingOffsetData {
int weaponId;
CVector offset;
};

static tAimingCamData gData[4];

static std::list<tAimingOffsetData*> offsets;

static unsigned int updateSets;

static bool holdingCommandLastFrame;
static bool holdingKeyLastFrame;

static unsigned int keyId1;
static unsigned int keyId2;
static unsigned int buttonId1;
static unsigned int buttonId2;

static bool rightSide;

static CVector defaultOffset;

static CVector GetAimingOffsetData(int weaponId) {
// Find weapon
for (auto data : offsets) {
if (data->weaponId == weaponId) return data->offset;
}
// Find default settings
for (auto data : offsets) {
if (data->weaponId == -1) return data->offset;
}
// Fall off
CVector offset;
offset.x = 0.0f; offset.y = 0.0f; offset.z = 0.0f;
return offset;
}

static void ReadSettings() {
char line[512];
char dummy[128];
float fVal;
FILE *file = fopen(PLUGIN_PATH("aimingSets.dat"), "r");
fgets(line, 512, file);
sscanf(line, "%s %d", dummy, &updateSets);
fgets(line, 512, file);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B4);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B8);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, &fVal);
patch::SetFloat(0x521632, fVal);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4B0);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4AC);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4A8);
fgets(line, 512, file);
sscanf(line, "%s %f", dummy, (float *)0x8CC4A0);
fgets(line, 512, file);
fgets(line, 512, file);
sscanf(line, "%s %d %d", dummy, &keyId1, &keyId2);
fgets(line, 512, file);
sscanf(line, "%s %d %d", dummy, &buttonId1, &buttonId2);
fgets(line, 512, file);
for (int i = 0; i < 4; i++) {
fgets(line, 512, file);
sscanf(line, "%s %f %f %f %f %f %f %f", dummy, &gData[i].f0, &gData[i].f1, &gData[i].f2, &gData[i].f3, &gData[i].f4,
&gData[i].f5, &gData[i].f6);
}
memcpy((void *)0x8CC4C0, gData, 112);
fgets(line, 512, file);
for (auto offset : offsets) delete offset;
offsets.clear();
CVector offset;
int weaponId = 0;
for (int i = 0; i < 16; i++) {
fgets(line, 512, file);
if (sscanf(line, "%d %f %f %f", &weaponId, &offset.x, &offset.y, &offset.z) == 4) {
tAimingOffsetData *data = new tAimingOffsetData;
data->weaponId = weaponId;
data->offset = offset;
offsets.push_back(data);
}
}
fclose(file);
}

static void _fastcall MyProcess_AimWeapon(CCam *cam, int, CVector const &vec, float arg3, float arg4, float arg5) {

// check for commands

if (buttonId1 != buttonId2) {
if (buttonId2 != 0 && reinterpret_cast<CRunningScript*>(0)->GetPadState(0, buttonId2))
rightSide = false;
else if (buttonId1 != 0 && reinterpret_cast<CRunningScript*>(0)->GetPadState(0, buttonId1))
rightSide = true;
}
else {
if (buttonId1 != 0) {
if (reinterpret_cast<CRunningScript*>(0)->GetPadState(0, buttonId1)) {
if (!holdingCommandLastFrame) {
rightSide = !rightSide;
holdingCommandLastFrame = true;
}
}
else holdingCommandLastFrame = false;
}
}

if (keyId1 != keyId2) {
if (keyId2 != 0 && KeyPressed(keyId2))
rightSide = false;
else if (keyId1 != 0 && KeyPressed(keyId1))
rightSide = true;
}
else {
if (keyId1 != 0) {
if (KeyPressed(keyId1)) {
if (!holdingKeyLastFrame) {
rightSide = !rightSide;
holdingKeyLastFrame = true;
}
}
else holdingKeyLastFrame = false;
}
}

if (updateSets)
ReadSettings();

CPed *playa = FindPlayerPed();
if (playa && !playa->m_nPedFlags.bInVehicle) {

CVector offset = GetAimingOffsetData(playa->m_aWeapons[playa->m_nActiveWeaponSlot].m_nType);

if (offset.x != 0 || offset.y != 0 || offset.z != 0) {

// if rightSide flag enabled
if (rightSide)
offset.x *= -3.0f;

CallMethod<0x521500, CCam *, CVector const&>(cam, playa->TransformFromObjectSpace(offset), arg3, arg4, arg5);
}
else
CallMethod<0x521500, CCam *, CVector const&>(cam, vec, arg3, arg4, arg5);
}
else
CallMethod<0x521500, CCam *, CVector const&>(cam, vec, arg3, arg4, arg5);
}

AdvancedAimingMod() {
// inject our function
patch::RedirectCall(0x527A95, MyProcess_AimWeapon);
// read settings
ReadSettings();
}
};

AdvancedAimingMod::tAimingCamData AdvancedAimingMod::gData[4];
CVector AdvancedAimingMod::gOffsets[16];

std::list<AdvancedAimingMod::tAimingOffsetData*> AdvancedAimingMod::offsets;

CVector AdvancedAimingMod::defaultOffset;

unsigned int AdvancedAimingMod::updateSets;

bool AdvancedAimingMod::rightSide = false;

AdvancedAimingMod plg;
bool AdvancedAimingMod::holdingCommandLastFrame;
bool AdvancedAimingMod::holdingKeyLastFrame;

unsigned int AdvancedAimingMod::keyId1;
unsigned int AdvancedAimingMod::keyId2;
unsigned int AdvancedAimingMod::buttonId1;
unsigned int AdvancedAimingMod::buttonId2;

AdvancedAimingMod plg;