AutoHeal update
This commit is contained in:
parent
7957563e1c
commit
b4995eca71
@ -12,18 +12,52 @@
|
||||
|
||||
namespace hacks { namespace tf { namespace autoheal {
|
||||
|
||||
extern CatVar enabled(CV_SWITCH, "autoheal_enabled", "0", "AutoHeal", "Automatically heals nearby teammates");
|
||||
extern CatVar silent(CV_SWITCH, "autoheal_silent", "1", "Silent AutoHeal", "Silent AutoHeal. Disable this to make ghetto followbot");
|
||||
CatVar enabled(CV_SWITCH, "autoheal_enabled", "0", "AutoHeal", "Automatically heals nearby teammates");
|
||||
CatVar silent(CV_SWITCH, "autoheal_silent", "1", "Silent AutoHeal", "Silent AutoHeal. Disable this to make ghetto followbot");
|
||||
//extern CatVar target_only;
|
||||
|
||||
int m_iCurrentHealingTarget { -1 };
|
||||
int m_iNewTarget { 0 };
|
||||
|
||||
static CatVar pop_uber(CV_FLOAT, "autoheal_uber_health", "20", "Pop uber if health% <");
|
||||
static CatVar pop_uber_auto(CV_SWITCH, "autoheal_uber", "1", "AutoUber");
|
||||
static CatVar pop_uber_percent(CV_FLOAT, "autoheal_uber_health", "30", "Pop uber if health% <");
|
||||
static CatVar share_uber(CV_SWITCH, "autoheal_share_uber", "1", "Share ubercharge");
|
||||
|
||||
bool IsPopped() {
|
||||
CachedEntity* weapon = g_pLocalPlayer->weapon();
|
||||
if (CE_BAD(weapon) || weapon->m_iClassID != g_pClassID->CWeaponMedigun) return false;
|
||||
return CE_BYTE(weapon, netvar.bChargeRelease);
|
||||
}
|
||||
|
||||
bool ShouldChargePlayer(int idx) {
|
||||
CachedEntity* target = ENTITY(idx);
|
||||
const float damage_accum_duration = g_GlobalVars->curtime - data[idx].accum_damage_start;
|
||||
const int health = target->m_iHealth;
|
||||
if (!data[idx].accum_damage_start) return false;
|
||||
if (health > 30 && data[idx].accum_damage < 45) return false;
|
||||
const float dd = ((float)data[idx].accum_damage / damage_accum_duration);
|
||||
if (dd > 40) {
|
||||
return true;
|
||||
}
|
||||
if (health < 30 && data[idx].accum_damage > 10) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShouldPop() {
|
||||
if (IsPopped()) return false;
|
||||
if (m_iCurrentHealingTarget != -1) {
|
||||
CachedEntity* target = ENTITY(m_iCurrentHealingTarget);
|
||||
if (CE_GOOD(target)) {
|
||||
if (ShouldChargePlayer(m_iCurrentHealingTarget)) return true;
|
||||
}
|
||||
}
|
||||
return ShouldChargePlayer(LOCAL_E->m_IDX);
|
||||
}
|
||||
|
||||
void CreateMove() {
|
||||
if (!enabled) return;
|
||||
if (GetWeaponMode(g_pLocalPlayer->entity) != weapon_medigun) return;
|
||||
UpdateData();
|
||||
int old_target = m_iCurrentHealingTarget;
|
||||
m_iCurrentHealingTarget = BestTarget();
|
||||
if (m_iNewTarget > 0 && m_iNewTarget < 10) m_iNewTarget++;
|
||||
@ -38,13 +72,37 @@ void CreateMove() {
|
||||
GetHitbox(target, 7, out);
|
||||
AimAt(g_pLocalPlayer->v_Eye, out, g_pUserCmd);
|
||||
if (silent) g_pLocalPlayer->bUseSilentAngles = true;
|
||||
if (!m_iNewTarget && (g_GlobalVars->tickcount % 60)) g_pUserCmd->buttons |= IN_ATTACK;
|
||||
if (((float)target->m_iHealth / (float)target->m_iMaxHealth) * 100 < (float)pop_uber) {
|
||||
g_pUserCmd->buttons |= IN_ATTACK2;
|
||||
}
|
||||
if (!m_iNewTarget && (g_GlobalVars->tickcount % 300)) g_pUserCmd->buttons |= IN_ATTACK;
|
||||
if (ShouldPop()) g_pUserCmd->buttons |= IN_ATTACK2;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<patient_data_s> data(32);
|
||||
void UpdateData() {
|
||||
for (int i = 1; i < 32; i++) {
|
||||
CachedEntity* ent = ENTITY(i);
|
||||
if (CE_GOOD(ent)) {
|
||||
int health = ent->m_iHealth;
|
||||
if (data[i].last_damage > g_GlobalVars->curtime) {
|
||||
data[i].last_damage = 0.0f;
|
||||
}
|
||||
if (g_GlobalVars->curtime - data[i].last_damage > 5.0f) {
|
||||
data[i].accum_damage = 0;
|
||||
data[i].accum_damage_start = 0.0f;
|
||||
}
|
||||
const int last_health = data[i].last_health;
|
||||
if (health != last_health) {
|
||||
data[i].last_health = health;
|
||||
if (health < last_health) {
|
||||
data[i].accum_damage += (last_health - health);
|
||||
if (!data[i].accum_damage_start) data[i].accum_damage_start = g_GlobalVars->curtime;
|
||||
data[i].last_damage = g_GlobalVars->curtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BestTarget() {
|
||||
int best = -1;
|
||||
int best_score = -65536;
|
||||
@ -61,6 +119,10 @@ int BestTarget() {
|
||||
int HealingPriority(int idx) {
|
||||
if (!CanHeal(idx)) return -1;
|
||||
CachedEntity* ent = ENTITY(idx);
|
||||
if (share_uber && IsPopped()) {
|
||||
return !HasCondition(ent, TFCond_Ubercharged);
|
||||
}
|
||||
|
||||
int priority = 0;
|
||||
int health = CE_INT(ent, netvar.iHealth);
|
||||
int maxhealth = g_pPlayerResource->GetMaxHealth(ent);
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "IHack.h"
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
namespace hacks { namespace tf { namespace autoheal {
|
||||
|
||||
extern CatVar enabled;
|
||||
@ -17,6 +19,16 @@ extern CatVar silent;
|
||||
// TODO extern CatVar target_only;
|
||||
void CreateMove();
|
||||
|
||||
struct patient_data_s {
|
||||
float last_damage { 0.0f };
|
||||
int last_health { 0 };
|
||||
int accum_damage { 0 }; // accumulated damage over X seconds (data stored for AT least 5 seconds)
|
||||
float accum_damage_start { 0.0f };
|
||||
};
|
||||
|
||||
extern std::vector<patient_data_s> data;
|
||||
|
||||
void UpdateData();
|
||||
int BestTarget();
|
||||
int HealingPriority(int idx);
|
||||
bool CanHeal(int idx);
|
||||
|
@ -127,6 +127,7 @@ bool DispatchUserMessage_hook(void* thisptr, int type, bf_read& buf) {
|
||||
buf.Seek(0);
|
||||
}
|
||||
}
|
||||
//if (type != net_Tick) logging::Info("Got message: %s", type);
|
||||
return ((DispatchUserMessage_t*)hooks::hkClient->GetMethod(hooks::offFrameStageNotify + 1))(thisptr, type, buf);
|
||||
SEGV_END; return false;
|
||||
}
|
||||
|
15
src/ipc.cpp
15
src/ipc.cpp
@ -54,9 +54,24 @@ CatCommand connect("ipc_connect", "Connect to IPC server", []() {
|
||||
pthread_create(&listener_thread, nullptr, listen, nullptr);
|
||||
} catch (std::exception& error) {
|
||||
logging::Info("Runtime error: %s", error.what());
|
||||
delete peer;
|
||||
peer = nullptr;
|
||||
}
|
||||
|
||||
});
|
||||
CatCommand lobby("ipc_lobby", "Join a lobby", [](const CCommand& args) {
|
||||
std::string input(args.ArgS());
|
||||
std::size_t lobby_id_start = input.find("[L:1:");
|
||||
if (lobby_id_start == std::string::npos) {
|
||||
logging::Info("couldn't find lobby ID!");
|
||||
return;
|
||||
}
|
||||
input = input.substr(lobby_id_start + 5);
|
||||
unsigned long lobby32 = strtoul(input.c_str(), nullptr, 10);
|
||||
unsigned long long lobby64 = ((25559040ull << 32) | lobby32);
|
||||
logging::Info("lobby64 ID: %llu", lobby64);
|
||||
peer->SendMessage(format("connect_lobby ", lobby64).c_str(), 0, ipc::commands::execute_client_cmd, 0, 0);
|
||||
});
|
||||
CatCommand disconnect("ipc_disconnect", "Disconnect from IPC server", []() {
|
||||
thread_running = false;
|
||||
pthread_join(listener_thread, nullptr);
|
||||
|
@ -33,6 +33,7 @@ extern CatCommand connect;
|
||||
extern CatCommand disconnect;
|
||||
extern CatCommand exec;
|
||||
extern CatCommand exec_all;
|
||||
extern CatCommand lobby;
|
||||
extern CatVar server_name;
|
||||
|
||||
extern pthread_t listener_thread;
|
||||
|
@ -54,6 +54,8 @@ void NetVars::Init() {
|
||||
this->iPlayerClass = gNetvars.get_offset("DT_TFPlayerResource", "m_iPlayerClass");
|
||||
this->angEyeAngles = gNetvars.get_offset("DT_TFPlayer", "tfnonlocaldata", "m_angEyeAngles[0]");
|
||||
this->iWeaponState = gNetvars.get_offset("DT_WeaponMinigun", "m_iWeaponState");
|
||||
this->flChargeLevel = gNetvars.get_offset("DT_WeaponMedigun", "NonLocalTFWeaponMedigunData", "m_flChargeLevel");
|
||||
this->bChargeRelease = gNetvars.get_offset("DT_WeaponMedigun", "m_bChargeRelease");
|
||||
}
|
||||
if (TF2C) this->iCritMult = gNetvars.get_offset("DT_TFPlayer", "m_Shared", "m_iCritMult");
|
||||
if (TF2C) {
|
||||
|
@ -113,6 +113,9 @@ public:
|
||||
offset_t hOwner;
|
||||
offset_t iWeaponState;
|
||||
offset_t iCritMult; // TF2C
|
||||
|
||||
offset_t flChargeLevel;
|
||||
offset_t bChargeRelease;
|
||||
};
|
||||
|
||||
extern NetVars netvar;
|
||||
|
Reference in New Issue
Block a user