AutoHeal update

This commit is contained in:
nullifiedcat 2017-03-25 14:38:39 +03:00
parent 7957563e1c
commit b4995eca71
7 changed files with 103 additions and 7 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -113,6 +113,9 @@ public:
offset_t hOwner;
offset_t iWeaponState;
offset_t iCritMult; // TF2C
offset_t flChargeLevel;
offset_t bChargeRelease;
};
extern NetVars netvar;