|
|
|
@ -20,11 +20,19 @@
|
|
|
|
|
#include <client_class.h>
|
|
|
|
|
#include <cdll_int.h>
|
|
|
|
|
|
|
|
|
|
enum bot_state_t {
|
|
|
|
|
IDLE = 0,
|
|
|
|
|
FOLLOWING_TEAMMATE,
|
|
|
|
|
FOLLOWING_ENEMY,
|
|
|
|
|
PILOT_SEARCH,
|
|
|
|
|
TARGET_LOST
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
unsigned long g_nTick = 0;
|
|
|
|
|
int g_nTargetID = 0;
|
|
|
|
|
//IClientEntity* eTarget;
|
|
|
|
|
bool bFollowingTeammate;
|
|
|
|
|
unsigned long nPilotSearch = 0;
|
|
|
|
|
unsigned long SEARCH_TICKS = 250;
|
|
|
|
|
bot_state_t g_bState = IDLE;
|
|
|
|
|
|
|
|
|
|
void SetTarget(IClientEntity* ent) {
|
|
|
|
|
if (!ent) {
|
|
|
|
@ -43,34 +51,49 @@ void HPyroBot::ProcessEntity(IClientEntity* entity, bool enemy) {
|
|
|
|
|
IClientEntity* target = GetTarget();
|
|
|
|
|
|
|
|
|
|
if (!target) {
|
|
|
|
|
if (!enemy && v_iForceFollow->GetInt() != -1 && v_bForceFollowOnly->GetBool() && entity->entindex() != v_iForceFollow->GetInt()) return;
|
|
|
|
|
if (!enemy) {
|
|
|
|
|
if (v_iForceFollow->GetInt() != -1) {
|
|
|
|
|
if (v_bForceFollowOnly->GetBool() && (v_iForceFollow->GetInt() != entity->entindex())) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
target = entity;
|
|
|
|
|
bFollowingTeammate = !enemy;
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (enemy) {
|
|
|
|
|
if (!bFollowingTeammate) {
|
|
|
|
|
if (g_bState == bot_state_t::FOLLOWING_ENEMY) {
|
|
|
|
|
if (DistToSqr(entity) <= DistToSqr(target)) {
|
|
|
|
|
target = entity;
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
target = entity;
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
}
|
|
|
|
|
bFollowingTeammate = false;
|
|
|
|
|
g_bState = bot_state_t::FOLLOWING_ENEMY;
|
|
|
|
|
} else {
|
|
|
|
|
//if (nPilotSearch < 100) return;
|
|
|
|
|
//if (g_bState == bot_state_t::PILOT_SEARCH) {
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
if (g_bState == bot_state_t::FOLLOWING_ENEMY) return;
|
|
|
|
|
if (GetEntityValue<Vector>(entity, eoffsets.vVelocity).IsZero(1.0f)) return;
|
|
|
|
|
if (v_iForceFollow->GetInt() != -1) {
|
|
|
|
|
if (bFollowingTeammate && entity->entindex() == v_iForceFollow->GetInt()) {
|
|
|
|
|
if (entity->entindex() == v_iForceFollow->GetInt()) {
|
|
|
|
|
target = entity;
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
g_bState = bot_state_t::FOLLOWING_TEAMMATE;
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (GetEntityValue<Vector>(entity, eoffsets.vVelocity).IsZero(1.0f)) return;
|
|
|
|
|
if (bFollowingTeammate && DistToSqr(entity) < DistToSqr(target)) {
|
|
|
|
|
if (DistToSqr(entity) <= DistToSqr(target)) {
|
|
|
|
|
target = entity;
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
g_bState = bot_state_t::FOLLOWING_TEAMMATE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SetTarget(target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AimAt(IClientEntity* entity, CUserCmd* cmd) {
|
|
|
|
@ -97,7 +120,11 @@ bool HPyroBot::ShouldTarget(IClientEntity* ent) {
|
|
|
|
|
if (IsPlayerInvulnerable(ent)) return false;
|
|
|
|
|
}
|
|
|
|
|
if (DistToSqr(ent) > (v_iMaxDistance->GetInt() * v_iMaxDistance->GetInt())) return false;
|
|
|
|
|
if (!IsEntityVisible(ent, 4)) return false;
|
|
|
|
|
bool a = false;
|
|
|
|
|
for (int i = 0; i < 17; i++) {
|
|
|
|
|
if (IsEntityVisible(ent, i)) a = true;
|
|
|
|
|
}
|
|
|
|
|
if (!a) return false;
|
|
|
|
|
if (abs(ent->GetAbsOrigin().z - g_pLocalPlayer->v_Origin.z) > v_iMaxDeltaY->GetInt()) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -105,25 +132,37 @@ bool HPyroBot::ShouldTarget(IClientEntity* ent) {
|
|
|
|
|
void HPyroBot::Tick(CUserCmd* cmd) {
|
|
|
|
|
if (!g_pLocalPlayer->entity || g_pLocalPlayer->entity->IsDormant()) return;
|
|
|
|
|
if (g_pLocalPlayer->life_state) return;
|
|
|
|
|
|
|
|
|
|
IClientEntity* target = GetTarget();
|
|
|
|
|
IClientEntity* target_old = target;
|
|
|
|
|
if (!ShouldTarget(target) && !bFollowingTeammate) {
|
|
|
|
|
//logging::Info("Current target lost.");
|
|
|
|
|
|
|
|
|
|
bool target_lost = (!target || !ShouldTarget(target) || g_bState == bot_state_t::PILOT_SEARCH);
|
|
|
|
|
|
|
|
|
|
if (target_lost) logging::Info("Target lost! Target: %i, State: %i, ShouldTarget: %i", target, g_bState, ShouldTarget(target));
|
|
|
|
|
|
|
|
|
|
if (target_lost && g_bState == bot_state_t::FOLLOWING_ENEMY) {
|
|
|
|
|
g_bState = bot_state_t::PILOT_SEARCH;
|
|
|
|
|
nPilotSearch++;
|
|
|
|
|
SetTarget(0);
|
|
|
|
|
target = 0;
|
|
|
|
|
}
|
|
|
|
|
if (!ShouldTarget(target) && bFollowingTeammate) {
|
|
|
|
|
if (target_lost && (g_bState == bot_state_t::FOLLOWING_TEAMMATE || g_bState == bot_state_t::PILOT_SEARCH)) {
|
|
|
|
|
g_bState = bot_state_t::PILOT_SEARCH;
|
|
|
|
|
nPilotSearch++;
|
|
|
|
|
if (nPilotSearch >= 100) {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-forward");
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-attack");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nPilotSearch = 0;
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("+forward");
|
|
|
|
|
if ((g_nTick % 150 == 0) || !target) {
|
|
|
|
|
bFollowingTeammate = true;
|
|
|
|
|
//SetTarget(0);
|
|
|
|
|
|
|
|
|
|
if (!target_lost) {
|
|
|
|
|
nPilotSearch = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nPilotSearch < SEARCH_TICKS) {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("+forward");
|
|
|
|
|
} else {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-forward");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((g_nTick % 400 == 0) || target_lost) {
|
|
|
|
|
for (int i = 0; i < 64 && i < interfaces::entityList->GetMaxEntities(); i++) {
|
|
|
|
|
IClientEntity* ent = interfaces::entityList->GetClientEntity(i);
|
|
|
|
|
if (!ShouldTarget(ent)) continue;
|
|
|
|
@ -131,39 +170,51 @@ void HPyroBot::Tick(CUserCmd* cmd) {
|
|
|
|
|
ProcessEntity(ent, enemy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
target = GetTarget();
|
|
|
|
|
if (!target) {
|
|
|
|
|
target_lost = (!target || !ShouldTarget(target) || g_bState == bot_state_t::IDLE || g_bState == bot_state_t::PILOT_SEARCH || g_bState == bot_state_t::TARGET_LOST);
|
|
|
|
|
|
|
|
|
|
if (target_lost) {
|
|
|
|
|
if (target_old != 0) {
|
|
|
|
|
//logging::Info("Target lost!");
|
|
|
|
|
if (v_bChat->GetBool()) {
|
|
|
|
|
interfaces::engineClient->ServerCmd("say Target lost!");
|
|
|
|
|
//char* cmd = new char[256];
|
|
|
|
|
//sprintf(cmd, "say Target lost!", g_bState);
|
|
|
|
|
//interfaces::engineClient->ServerCmd(cmd);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
//logging::Info("Target lost! State: %i, %i", !!target, !!ShouldTarget(target));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (target != target_old) {
|
|
|
|
|
player_info_s info;
|
|
|
|
|
interfaces::engineClient->GetPlayerInfo(target->entindex(), &info);
|
|
|
|
|
logging::Info("Following %s", info.name);
|
|
|
|
|
if (v_bChat->GetBool()) {
|
|
|
|
|
char* cmd = new char[256];
|
|
|
|
|
if (bFollowingTeammate)
|
|
|
|
|
if (g_bState == bot_state_t::FOLLOWING_TEAMMATE)
|
|
|
|
|
sprintf(cmd, "say Following: %s", info.name);
|
|
|
|
|
else
|
|
|
|
|
sprintf(cmd, "say Attacking: %s", info.name);
|
|
|
|
|
interfaces::engineClient->ServerCmd(cmd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (GetEntityValue<Vector>(g_pLocalPlayer->entity, eoffsets.vVelocity).IsZero(10.0f)) {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("+jump");
|
|
|
|
|
} else {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-jump");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AimAt(target, cmd);
|
|
|
|
|
if (DistToSqr(target) < 200 * 200 && bFollowingTeammate) {
|
|
|
|
|
|
|
|
|
|
if (DistToSqr(target) < (200 * 200) && g_bState == bot_state_t::FOLLOWING_TEAMMATE) {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-forward");
|
|
|
|
|
}
|
|
|
|
|
if (DistToSqr(target) < (v_iShootDistance->GetInt() * v_iShootDistance->GetInt()) && !bFollowingTeammate) {
|
|
|
|
|
|
|
|
|
|
if (DistToSqr(target) < (v_iShootDistance->GetInt() * v_iShootDistance->GetInt()) && g_bState == bot_state_t::FOLLOWING_ENEMY) {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("+attack");
|
|
|
|
|
} else {
|
|
|
|
|
interfaces::engineClient->ExecuteClientCmd("-attack");
|
|
|
|
@ -177,6 +228,10 @@ bool HPyroBot::CreateMove(void*, float, CUserCmd* cmd) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CC_Status(const CCommand& args) {
|
|
|
|
|
logging::Info("W+M1 State: %i, ID: %i, Search: %i", g_bState, g_nTargetID, nPilotSearch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HPyroBot::Create() {
|
|
|
|
|
logging::Info("Creating PyroBot");
|
|
|
|
|
v_bEnabled = CreateConVar("u_pyrobot_enabled", "0", "Enables WM1 bot");
|
|
|
|
@ -186,6 +241,7 @@ void HPyroBot::Create() {
|
|
|
|
|
v_iMaxDistance = CreateConVar("u_pyrobot_aim_distance", "1300", "Distance");
|
|
|
|
|
v_iShootDistance = CreateConVar("u_pyrobot_shoot_distance", "800", "Shoot distance");
|
|
|
|
|
v_bChat = CreateConVar("u_pyrobot_chat", "0", "Enable chat");
|
|
|
|
|
cmd_Status = CreateConCommand("u_pyrobot_status", CC_Status, "Status");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HPyroBot::Destroy() {}
|
|
|
|
|