rendered paste body// GPL License - see http://opensource.org/licenses/gpl-license.php
// Copyright 2006 *nixCoders team - don't forget to credit us
/*
==============================
All aimbot related funtions
==============================
*/
#include "eth.h"
#include "offsets.h"
void aimAt(vec3_t target) {
#ifdef ETH_DEBUG
if (seth.value[VAR_AIM_POINT] == AIM_POINT_2D) {
#define POINT_SIZE 4
int x, y;
if (worldToScreen(target, &x, &y))
drawFillRect(x - (POINT_SIZE / 2), y - (POINT_SIZE / 2), POINT_SIZE, POINT_SIZE, colorYellow);
} else if (seth.value[VAR_AIM_POINT] == AIM_POINT_3D) {
crossRailTrail(target);
}
#endif
vec3_t org, ang;
// Self Prediction
if (seth.value[VAR_SELFPREDICT]) {
vec3_t pVieworg;
if (seth.value[VAR_SELFPREDICT]) {
VectorMA(eth.cg_refdef.vieworg, (float)(eth.cg_frametime) / 1000.0f, eth.cg_entities[eth.cg_clientNum].currentState->pos.trDelta, pVieworg);
} else {
ethLog("error: invalid aim prediction type: %i", seth.value[VAR_SELFPREDICT]);
VectorCopy(eth.cg_refdef.vieworg, pVieworg);
}
VectorSubtract(target, pVieworg, org);
} else {
VectorSubtract(target, eth.cg_refdef.vieworg, org);
}
vectoangles(org, ang);
ang[PITCH] -= eth.cg_refdefViewAngles[PITCH];
ang[YAW] -= eth.cg_refdefViewAngles[YAW];
// Simple human aim for now - will try to make it cg_time based, not framebased like now
if (seth.value[VAR_HUMAN]) {
while (ang[PITCH] < -360.0f)
ang[PITCH] += 360.0f;
while (ang[PITCH] > 360.0f)
ang[PITCH] -= 360.0f;
while (ang[YAW] < -360.0f)
ang[YAW] += 360.0f;
while (ang[YAW] > 360.0f)
ang[YAW] -= 360.0f;
if (ang[PITCH] > 180.0f)
ang[PITCH] -= 360.0f;
if (ang[PITCH] < -180.0f)
ang[PITCH] += 360.0f;
if (ang[YAW] > 180.0f)
ang[YAW] -= 360.0f;
if (ang[YAW] < -180.0f)
ang[YAW] += 360.0f;
ang[PITCH] *= seth.value[VAR_HUMANVALUE]*0.9;
ang[YAW] *= seth.value[VAR_HUMANVALUE];
if(ang[PITCH] <0) ang[PITCH]*=0.05;
}
*(float *)sethET->cl_mouseDx += ang[PITCH];
*(float *)sethET->cl_mouseDy += ang[YAW];
// *(float *)CL_MOUSEDX_ADDR += AngleDelta(ang[PITCH], seth.refdefViewAngles[PITCH]);
// *(float *)CL_MOUSEDY_ADDR += AngleDelta(ang[YAW], seth.refdefViewAngles[YAW]);
}
void riffleAimAt(vec3_t target) {
vec3_t org, ang;
VectorSubtract(target, eth.cg_refdef.vieworg, org);
vectoangles(org, ang);
// Calculate y distance
vec3_t me, enemy;
VectorCopy(eth.cg_refdef.vieworg, me);
VectorCopy(target, enemy);
me[ROLL] = 0;
enemy[ROLL] = 0;
float y = target[ROLL] - eth.cg_refdef.vieworg[ROLL];
float v = 2000; // Riffle speed
float g = DEFAULT_GRAVITY;
float x = VectorDistance(me, enemy);
float angle = atan((pow(v, 2) - (sqrt(pow(v, 4) + (g * ((g * pow(x, 2)) + (2.0f * y * pow(v, 2))))))) / (g * x));
angle = RAD2DEG(angle);
ang[PITCH] = angle;
ang[PITCH] -= eth.cg_refdefViewAngles[PITCH];
ang[YAW] -= eth.cg_refdefViewAngles[YAW];
*(float *)sethET->cl_mouseDx += ang[PITCH];
*(float *)sethET->cl_mouseDy += ang[YAW];
}
// This tag are in priority order. The first tags are near the center of the
// models, the last tag are at edge of the models
static char *modelBodyTags[] = {
"tag_chest",
"tag_torso",
"tag_bright",
"tag_lbelt",
"tag_bleft",
"tag_ubelt",
"tag_back",
"tag_armleft",
"tag_weapon",
"tag_armright",
"tag_weapon2",
"tag_legright",
"tag_legleft",
"tag_footleft",
"tag_footright"
};
qboolean getVisibleModelBodyTag(const int player, vec3_t *origin) {
int count = 0;
for (; count < (sizeof(modelBodyTags) / sizeof(char *)); count++) {
char *tagText = modelBodyTags[count];
orientation_t tagOrientation;
if (!eth_CG_GetTag(player, tagText, &tagOrientation))
ethLog("error: can't find tag %i[%s] for player: %i", count, tagText, player);
if (isVisible(tagOrientation.origin)) {
VectorCopy(tagOrientation.origin, *origin);
#ifdef ETH_DEBUG
ethDebug("found visible tag: %s for player: %i", tagText, player);
#endif
return qtrue;
}
}
return qfalse;
}
void doAutoShoot(qboolean shoot) {
// We don't want autoshoot
if (!seth.value[VAR_AUTOSHOOT])
return;
// Don't shoot if we're specing/following a player
if (eth.cg_clientNum != eth.cg_snap->ps.clientNum)
return;
qboolean trigger;
// *----------------------------------------------------------------------*
static int anylastShootTime = 0;
if ((eth.cg_time - anylastShootTime) >= (seth.value[VAR_SNIPERDELAY])) {
anylastShootTime = eth.cg_time;
setAction(ACTION_ATTACK, 0); // u can remove it for testing so leave return only;
return;
}
// *----------------------------------------------------------------------*
if (seth.value[VAR_AUTOSHOOT_TYPE] == AUTOSHOOT_TYPE_TRIGGER) {
// Set a far away end point
vec3_t aheadPos;
VectorMA(eth.cg_refdef.vieworg, 8192, eth.cg_refdef.viewaxis[0], aheadPos);
// Get trace for this point
trace_t trace;
eth.CG_Trace(&trace, eth.cg_refdef.vieworg, NULL, NULL, aheadPos, eth.cg_snap->ps.clientNum, CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_ITEM);
trigger = IS_PLAYER_ENEMY(trace.entityNum);
// Don't use trigger
} else {
trigger = qtrue;
}
// For tce
if (eth.mod->type == MOD_TCE) {
if (shoot && trigger && (syscall_CG_Key_IsDown(K_MOUSE1) || (seth.value[VAR_AUTOSHOOT] == AUTOSHOOT_ON))) {
static qboolean lastFrameAttack = qfalse;
if (!lastFrameAttack) {
setAction(ACTION_ATTACK, 1);
lastFrameAttack = qtrue;
} else {
setAction(ACTION_ATTACK, 0);
lastFrameAttack = qfalse;
}
} else {
setAction(ACTION_ATTACK, 0);
}
// For all others mod
} else {
if (shoot && trigger && (syscall_CG_Key_IsDown(K_MOUSE1) || (seth.value[VAR_AUTOSHOOT] == AUTOSHOOT_ON))) {
// Check for sniper weapon delay
if (((eth.cg_entities[eth.cg_clientNum].currentState->weapon == WP_K43_SCOPE)
|| (eth.cg_entities[eth.cg_clientNum].currentState->weapon == WP_GARAND_SCOPE)) && !BG_PlayerMounted(eth.cg_snap->ps.eFlags)) {
static int lastShootTime = 0;
if ((eth.cg_time - lastShootTime) >= (seth.value[VAR_SNIPERDELAY])) {
setAction(ACTION_ATTACK, 1);
lastShootTime = eth.cg_time;
} else {
setAction(ACTION_ATTACK, 0);
}
// Check for weapon overheating
#define OVERHEATING_LIMIT 200
} else if (seth.value[VAR_OVERHEAT] && (eth.cg_snap->ps.curWeapHeat > OVERHEATING_LIMIT)) {
setAction(ACTION_ATTACK, 0);
} else {
setAction(ACTION_ATTACK, 1);
#ifdef ETH_DEBUG
ethDebug("autoshoot: shoot on");
#endif
}
} else {
setAction(ACTION_ATTACK, 0);
#ifdef ETH_DEBUG
ethDebug("autoshoot: shoot off");
#endif
}
}
}
void doSatchelAutoShoot() {
int satchelEntityNum = findSatchel();
// If don't find satchel
if (satchelEntityNum == -1) {
#ifdef ETH_DEBUG
ethDebug("autoshoot: don't find satchel for %i", eth.cg_snap->ps.clientNum);
#endif
setAction(ACTION_ATTACK, 0);
return;
}
// Find an enemy near the satchel
#define SATCHEL_SHOOT_DISTANCE 100
int entityNum = 0;
for (; entityNum < MAX_CLIENTS; entityNum++) {
ethEntity_t *entity = ð.entities[entityNum];
if (entity->isValid
&& IS_PLAYER_ENEMY(entityNum)
&& (VectorDistance(entity->origin, eth.entities[satchelEntityNum].origin) < SATCHEL_SHOOT_DISTANCE)) {
setAction(ACTION_ATTACK, 1);
return;
}
}
// TODO: find a breakable object near the satchel
setAction(ACTION_ATTACK, 0);
}
int findTarget(int targetFlag) {
int nearest = -1;
int maxEntities = MAX_GENTITIES;
// Get max entities
if (targetFlag & TARGET_PLAYER)
maxEntities = MAX_CLIENTS;
int entityNum = 0;
if( (seth.value[VAR_TARGET_PRIO] == TARGET_ATTACKER ) ){
int ent = eth.cg_snap->ps.persistant[PERS_ATTACKER];
if( ent && ent <= MAX_CLIENTS ){
// Jaymod 2.1.x aimbot workaround
if( eth.mod->crc32 == 0x5f24fa23 || eth.mod->crc32 == 0x8352a951 )
eth.cg_entities[ent].currentState->eType = ET_PLAYER;
if( ((targetFlag & TARGET_ENEMY) && (targetFlag & TARGET_PLAYER) && IS_PLAYER_ENEMY(entityNum))
&& eth.entities[ent].isVisible && !IS_PLAYER_DEAD(ent) )
return ent;
}
}
for (; entityNum < maxEntities; entityNum++) {
ethEntity_t* entity = ð.entities[entityNum];
if (!*eth.cg_entities[entityNum].currentValid || (entityNum == eth.cg_snap->ps.clientNum))
continue;
// Jaymod 2.1.x aimbot workaround
if( entityNum < MAX_CLIENTS && (eth.mod->crc32 == 0x5f24fa23 || eth.mod->crc32 == 0x8352a951) )
eth.cg_entities[entityNum].currentState->eType = ET_PLAYER;
// Player
if ((targetFlag & TARGET_PLAYER) && !IS_PLAYER_VALID(entityNum))
continue;
if ((targetFlag & TARGET_PLAYER_VULN) && !IS_PLAYER_VULNERABLE(entityNum))
continue;
if ((targetFlag & TARGET_PLAYER_ALIVE) && IS_PLAYER_DEAD(entityNum))
continue;
if ((targetFlag & TARGET_PLAYER_DEAD) && !IS_PLAYER_DEAD(entityNum))
continue;
// Target
if ((targetFlag & TARGET_PLAYER_HEAD) && !entity->isHeadVisible)
continue;
if ((targetFlag & TARGET_PLAYER_BODY) && VectorCompare(entity->bodyPart, vec3_origin))
continue;
// Targeting specific player has priority over other settings
if ( (targetFlag & TARGET_VISIBLE) && entity->isVisible &&
(seth.value[VAR_TARGET_PRIO]==TARGET_PERSON) && eth.clAttack[entityNum] )
return entityNum;
// Common
if ((targetFlag & TARGET_ENEMY) && (targetFlag & TARGET_PLAYER) && !IS_PLAYER_ENEMY(entityNum))
continue;
if ((targetFlag & TARGET_ENEMY) && (targetFlag & TARGET_MISSILE) && !IS_MISSILE_ENEMY(entityNum))
continue;
if ((targetFlag & TARGET_FRIEND) && (targetFlag & TARGET_PLAYER) && IS_PLAYER_ENEMY(entityNum))
continue;
if ((targetFlag & TARGET_FRIEND) && (targetFlag & TARGET_MISSILE) && IS_MISSILE_ENEMY(entityNum))
continue;
if ((targetFlag & TARGET_VISIBLE) && !entity->isVisible)
continue;
if ((targetFlag & TARGET_NOTVISIBLE) && entity->isVisible)
continue;
// Missile
if ((targetFlag & TARGET_MISSILE) && !IS_MISSILE(entityNum))
continue;
if ((targetFlag & TARGET_MISSILE_ARMED) && !IS_MISSILE_ARMED(entityNum))
continue;
if ((targetFlag & TARGET_MISSILE_NOTARMED) && IS_MISSILE_ARMED(entityNum))
continue;
if ((targetFlag & TARGET_MISSILE_DYNAMITE) && !IS_DYNAMITE(entityNum))
continue;
if( (seth.value[VAR_TARGET_PRIO] == TARGET_NOOBTUBE) && IS_PANZER(entityNum) )
return entityNum;
if( (seth.value[VAR_TARGET_PRIO] == TARGET_MG42) && IS_MG42(entityNum) )
return entityNum;
if( (seth.value[VAR_TARGET_PRIO] == TARGET_HEAVY) && (IS_HEAVYWP(entityNum) ))
return entityNum;
if (seth.value[VAR_AIMFOV] != 360.00f) {
vec3_t aimPoint, ang, org;
if (eth.entities[entityNum].isHeadVisible)
VectorCopy(eth.entities[entityNum].head, aimPoint);
else if (seth.value[VAR_AIM_PRIO] != AIM_PRIO_HEAD_ONLY)
VectorCopy(eth.entities[entityNum].bodyPart, aimPoint);
else {
ethLog("findTarget: can't find a point to aim");
return -1;
}
VectorSubtract(aimPoint, eth.cg_refdef.vieworg, org);
vectoangles(org, ang);
ang[PITCH] -= eth.cg_refdefViewAngles[PITCH];
ang[YAW] -= eth.cg_refdefViewAngles[YAW];
if (ang[PITCH] < 0.0)
ang[PITCH] *= -1.0;
if (ang[YAW] < 0.0)
ang[YAW] *= -1.0;
if (ang[PITCH] > 360.0f)
ang[PITCH] -= 360.0f;
if (ang[YAW] > 360.0f)
ang[YAW] -= 360.0f;
float aimFov[2];
aimFov[0] = (ang[PITCH] - 360.0) * -1.0;
aimFov[1] = (ang[YAW] - 360.0) * -1.0;
if (ang[PITCH] > aimFov[0])
ang[PITCH] = aimFov[0];
if (ang[YAW] > aimFov[1])
ang[YAW] = aimFov[1];
if ((ang[PITCH] > seth.value[VAR_AIMFOV]) || (ang[YAW] > seth.value[VAR_AIMFOV]))
continue;
}
if ((entity->distance != 0)
&& (nearest == -1 || (entity->distance < eth.entities[nearest].distance))) {
nearest = entityNum;
}
}
#ifdef ETH_DEBUG
if (nearest != -1)
ethDebug("findTarget: target found for flags 0x%x", targetFlag);
else
ethDebug("findTarget: target not found for flags 0x%x", targetFlag);
#endif
return nearest;
}
void blockMouse(qboolean state) {
if (!seth.value[VAR_BLOCK_MOUSE])
return;
#define SENSITIVITY_STR "sensitivity"
static float sensitivity = 0; // For backup user sensitivity
static qboolean mouseBlocked = qfalse; // Current state
char buffer[32];
// Set sensitivity
if (state && !mouseBlocked) {
syscall_CG_Cvar_VariableStringBuffer(SENSITIVITY_STR, buffer, sizeof(buffer));
sensitivity = atof(buffer);
syscall_CG_SendConsoleCommand(SENSITIVITY_STR " 0\n");
mouseBlocked = qtrue;
#ifdef ETH_DEBUG
ethDebug("blockMouse: mouse off");
#endif
} else if (!state && mouseBlocked) {
snprintf(buffer, sizeof(buffer), SENSITIVITY_STR " %f\n", sensitivity);
syscall_CG_SendConsoleCommand(buffer);
mouseBlocked = qfalse;
#ifdef ETH_DEBUG
ethDebug("blockMouse: mouse on");
#endif
}
}
void doAimbot() {
qboolean autoShootWeapon = qfalse;
int targetFlag[2] = { -1, -1 }; // If a targetFlag failed try the next one
// For tce
if (eth.mod->type == MOD_TCE) {
int clips = eth.cg_snap->ps.ammoclip[eth.cg_snap->ps.weapon];
int ammo = eth.cg_snap->ps.ammo[eth.cg_snap->ps.weapon];
static qboolean lastframeReload = qfalse;
if(clips == 0 && ammo > 0) {
if(eth.cg_snap->ps.weapon != WP_KNIFE)
if(!lastframeReload) {
setAction(ACTION_RELOAD, 1);
lastframeReload = qtrue;
return;
}
}
if(lastframeReload) {
setAction(ACTION_RELOAD, 0);
lastframeReload = qfalse;
}
autoShootWeapon = qtrue;
targetFlag[0] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_ALIVE;
// Aim priority
if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD_BODY) {
targetFlag[0] |= TARGET_PLAYER_HEAD_BODY;
} else if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD_ONLY) {
targetFlag[0] |= TARGET_PLAYER_HEAD;
} else if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD) {
targetFlag[1] = targetFlag[0] | TARGET_PLAYER_BODY;
targetFlag[0] |= TARGET_PLAYER_HEAD;
}
// For all others mod
} else {
// if player is mounted (tank mg, mobile mg42, static mg42) aim for body
if (BG_PlayerMounted(eth.cg_snap->ps.eFlags) || (eth.cg_snap->ps.weapon == WP_MOBILE_MG42) || (eth.cg_snap->ps.weapon == WP_MOBILE_MG42_SET)) {
autoShootWeapon = qtrue;
targetFlag[0] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_BODY;
if (!seth.value[VAR_AIM_DEAD])
targetFlag[0] |= TARGET_PLAYER_ALIVE;
targetFlag[1] = targetFlag[0] | TARGET_PLAYER_HEAD;
} else {
// different targets for differents weapons
switch (eth.cg_snap->ps.weapon) {
case WP_LUGER:
case WP_SILENCER:
case WP_AKIMBO_LUGER:
case WP_AKIMBO_SILENCEDLUGER:
case WP_COLT:
case WP_SILENCED_COLT:
case WP_AKIMBO_COLT:
case WP_AKIMBO_SILENCEDCOLT:
case WP_MP40:
case WP_THOMPSON:
case WP_GARAND:
case WP_K43:
case WP_FG42:
case WP_STEN:
case WP_CARBINE:
case WP_KAR98:
autoShootWeapon = qtrue;
targetFlag[0] = TARGET_PLAYER_ENEMY;
// Aim at dead player
if (!seth.value[VAR_AIM_DEAD])
targetFlag[0] |= TARGET_PLAYER_ALIVE;
// Aim priority
if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD_BODY) {
targetFlag[0] |= TARGET_PLAYER_HEAD_BODY;
} else if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD_ONLY) {
targetFlag[0] |= TARGET_PLAYER_HEAD;
} else if (seth.value[VAR_AIM_PRIO] == AIM_PRIO_HEAD) {
targetFlag[1] = targetFlag[0] | TARGET_PLAYER_BODY;
targetFlag[0] |= TARGET_PLAYER_HEAD;
}
break;
case WP_GPG40:
case WP_M7:
autoShootWeapon = qtrue;
targetFlag[0] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_ALIVE | TARGET_PLAYER_BODY;
break;
case WP_GARAND_SCOPE:
case WP_K43_SCOPE:
case WP_FG42SCOPE:
autoShootWeapon = qtrue;
targetFlag[0] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_ALIVE | TARGET_PLAYER_HEAD;
break;
case WP_KNIFE:
targetFlag[0] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_ALIVE | TARGET_PLAYER_HEAD;
targetFlag[1] = TARGET_PLAYER_ENEMY | TARGET_PLAYER_DEAD | TARGET_PLAYER_HEAD;
break;
case WP_MEDIC_SYRINGE:
targetFlag[0] = TARGET_PLAYER | TARGET_FRIEND | TARGET_PLAYER_DEAD | TARGET_PLAYER_BODY;
break;
case WP_PLIERS:
targetFlag[0] = TARGET_MISSILE | TARGET_MISSILE_DYNAMITE | TARGET_ENEMY | TARGET_MISSILE_ARMED;
targetFlag[1] = TARGET_MISSILE | TARGET_MISSILE_DYNAMITE | TARGET_FRIEND | TARGET_MISSILE_NOTARMED;
default:
break;
}
}
}
// Check if we want aimbot
if ((syscall_CG_Key_IsDown(K_MOUSE1) || seth.value[VAR_AIM_AUTO])
&& (targetFlag[0] != -1) && seth.value[VAR_AIM_PRIO] &&
(eth.cg_snap->ps.clientNum == eth.cg_clientNum) ) {
// Find target aim point
int count = 0;
int target;
for (; count < (sizeof(targetFlag) / sizeof(int)); count++) {
if (targetFlag[count] != -1) {
vec3_t aimPoint;
VectorCopy(vec3_origin, aimPoint);
target = findTarget(targetFlag[count]);
// No target found
if (target == -1)
continue;
// Target found
if (targetFlag[count] & TARGET_PLAYER) {
if (targetFlag[count] & TARGET_PLAYER_HEAD) {
VectorCopy(eth.entities[target].head, aimPoint);
#ifdef ETH_DEBUG
ethDebug("aimbot: found head player: %s", eth.clientInfo[target].name);
#endif
} else if (targetFlag[count] & TARGET_PLAYER_BODY) {
VectorCopy(eth.entities[target].bodyPart, aimPoint);
#ifdef ETH_DEBUG
ethDebug("aimbot: found body player: %s", eth.clientInfo[target].name);
#endif
} else if (targetFlag[count] & TARGET_PLAYER_HEAD_BODY) {
// Head or body ?
if (eth.entities[target].isHeadVisible)
VectorCopy(eth.entities[target].head, aimPoint);
else
VectorCopy(eth.entities[target].bodyPart, aimPoint);
#ifdef ETH_DEBUG
ethDebug("aimbot: found head/body player: %s", eth.clientInfo[target].name);
#endif
} else {
ethLog("error: target found but no aimpoint set in target flags");
}
} else if (targetFlag[count] & TARGET_MISSILE) {
VectorCopy(eth.entities[target].origin, aimPoint);
#ifdef ETH_DEBUG
ethDebug("aimbot: found missile: %i", target);
#endif
} else {
ethLog("error: target found but it's not a player/missile");
}
// If aim point is set, aim and shoot
if (!VectorCompare(aimPoint, vec3_origin)) {
if (!seth.value[VAR_HUMAN])
doAutoShoot(qtrue);
if ((eth.cg_snap->ps.weapon == WP_GPG40) || (eth.cg_snap->ps.weapon == WP_M7))
riffleAimAt(aimPoint);
else
aimAt(aimPoint);
blockMouse(qtrue);
return;
}
}
}
#ifdef ETH_DEBUG
ethDebug("aimbot: no target found");
#endif
}
blockMouse(qfalse);
// For satchel
if (seth.value[VAR_SATCHEL_AUTOSHOOT]
&& (eth.cg_entities[eth.cg_clientNum].currentState->weapon == WP_SATCHEL_DET)
&& (eth.mod->type != MOD_TCE)) {
doSatchelAutoShoot();
// All others weapons
} else {
doAutoShoot(!autoShootWeapon);
}
}
void doVecZ(int player) {
ethEntity_t *entity = ð.entities[player];
// No need if not an enemy
if (!IS_PLAYER_ENEMY(player))
return;
// For tce
if (eth.mod->type == MOD_TCE) {
VectorMA(entity->head, seth.value[VAR_VECZ], entity->headAxis[2], entity->head);
// For all others mod
} else {
// Set different vecz for different weapon
switch (eth.cg_snap->ps.weapon) {
case WP_LUGER:
case WP_SILENCER:
case WP_AKIMBO_LUGER:
case WP_AKIMBO_SILENCEDLUGER:
case WP_COLT:
case WP_SILENCED_COLT:
case WP_AKIMBO_COLT:
case WP_AKIMBO_SILENCEDCOLT:
case WP_MP40:
case WP_THOMPSON:
case WP_MOBILE_MG42:
case WP_GARAND:
case WP_K43:
case WP_FG42:
case WP_STEN:
case WP_CARBINE:
case WP_KAR98:
case WP_GARAND_SCOPE:
case WP_K43_SCOPE:
case WP_FG42SCOPE:
if (seth.value[VAR_AIMVECZ_TYPE] == VECZ_HITBOX) {
vec3_t rmin;
vec3_t rmax;
VectorCopy(entity->rmin,rmin);
VectorCopy(entity->rmax,rmax);
// -> u can test it SnapVector(entity->head);//simple
entity->head[0]=entity->head[0]+(rmin[0]+rmax[0])*0.5f;
entity->head[1]=entity->head[1]+(rmin[1]+rmax[1])*0.5f;
entity->head[2]=entity->head[2]+(rmin[2]+rmax[2])*0.5f;
#ifdef ETH_DEBUG
//Debugstuph - use functions from: http://www.nixcoders.org/forum/index.php?showtopic=538
// if (seth.value[VAR_HITBOX] && syscall_CG_Key_IsDown(K_MOUSE1)) {
// drawHeadBox(rmin,rmax,entity->head);
// }
#endif
} else if (seth.value[VAR_AIMVECZ_TYPE] == VECZ_MANUAL) {
// Simple vecz correction
switch (eth.cg_snap->ps.weapon) {
case WP_STEN:
VectorMA(entity->head, seth.value[VAR_VECZ_STEN], entity->headAxis[2], entity->head);
break ;
case WP_K43_SCOPE:
case WP_GARAND_SCOPE:
case WP_FG42SCOPE:
VectorMA(entity->head, seth.value[VAR_VECZ_SCOPE], entity->headAxis[2], entity->head);
break;
default:
VectorMA(entity->head, seth.value[VAR_VECZ], entity->headAxis[2], entity->head);
break;
} // Auto vecz
} else if (seth.value[VAR_AIMVECZ_TYPE] == VECZ_AUTO) {
#define NEAR_TARGET_VECZ 5.0f
// Scoped weapons always aim at the middle of head
if (eth.cg_snap->ps.weapon == WP_GARAND_SCOPE || eth.cg_snap->ps.weapon == WP_K43_SCOPE || eth.cg_snap->ps.weapon == WP_FG42SCOPE) {
VectorMA(entity->head, 5.0f, entity->headAxis[2], entity->head);
return;
}
// Different 'near distance' for sten
int nearTarget;
if (eth.cg_snap->ps.weapon == WP_STEN)
nearTarget = 700.0f;
else
nearTarget = 500.0f;
if (entity->distance <= nearTarget)
VectorMA(entity->head, NEAR_TARGET_VECZ, entity->headAxis[2], entity->head);
else if ((entity->distance > nearTarget) && (entity->distance < 2000.0f))
VectorMA(entity->head, (NEAR_TARGET_VECZ * (100.0f - ((entity->distance - nearTarget) / 15.0f))) / 100.0f, entity->headAxis[2], entity->head);
}
break;
default:
break;
}
}
}
void doPrediction(int player) {
// No predicton
if (!seth.value[VAR_AIMPREDICT])
return;
ethEntity_t *entity = ð.entities[player];
//eth.BG_EvaluateTrajectory(ð.cg_entities[player].currentState->pos, *eth.cg.time + eth.cg_frametime, entity->origin, qfalse, 0);
//eth.BG_EvaluateTrajectory(ð.cg_entities[player].currentState->pos, *eth.cg.time + (seth.value[VAR_AIMPREDICT_VALUE] * 100.0f), entity->origin, qfalse, 0);
// Frametime prediction based
if (seth.value[VAR_AIMPREDICT] == AIMPREDICT_AUTO_1) {
VectorMA(entity->origin, (float)(eth.cg_frametime) / 1000.0f, eth.cg_entities[player].currentState->pos.trDelta, entity->origin);
//VectorMA(entity->head, (float)(eth.cg_frametime) / 1000.0f, eth.cg_entities[player].currentState->pos.trDelta, entity->head);
VectorMA (entity->head, eth.cg_snap->ping / 800, eth.cg_entities[player].currentState->pos.trDelta, entity->head);
} else if (seth.value[VAR_AIMPREDICT] == AIMPREDICT_AUTO_2) {
vec3_t velocity;
VectorScale(eth.cg_entities[player].currentState->pos.trDelta, 1000.0f / ((float)(eth.cg_frametime) - eth.cg_entities[player].currentState->pos.trTime) , velocity);
VectorMA(entity->origin, (float)(eth.cg_frametime) / 1000.0f, velocity, entity->origin);
VectorMA(entity->head, (float)(eth.cg_frametime) / 1000.0f, velocity, entity->head);
} else
ethLog("error: invalid aim prediction type: %i", seth.value[VAR_AIMPREDICT]);
}
#ifdef ETH_DEBUG
void doPredictionStats() {
static int lastTarget = -1;
int target = -1;
// Find the nearest moving player
int count;
int targetDistance = -1;
static vec3_t lastPosition[MAX_CLIENTS];
for (count = 0; count < MAX_CLIENTS; count++) {
// If valid and moving
if (IS_PLAYER_VALID(count) && !VectorCompare(lastPosition[count], eth.entities[count].origin)) {
// If nearest
if ((targetDistance == -1) || (eth.entities[count].distance < targetDistance)) {
target = count;
targetDistance = eth.entities[count].distance;
}
}
}
// Backup for next frame
lastTarget = target;
// Store all players positions for next frame
for (count = 0; count < MAX_CLIENTS; count++) {
if (IS_PLAYER_VALID(count))
VectorCopy(eth.entities[count].origin, lastPosition[count]);
}
// If no target found or not the same target
if ((target == -1) || (lastTarget != target))
return;
// Init prediction stats
ethEntity_t *entity = ð.entities[target];
static vec3_t lastOrigin;
static vec3_t lastPredictOrigin;
// Draw stats
drawPredictStats(lastOrigin, entity->origin, lastPredictOrigin);
printf("---------\n");
printf("origin : %.1f %.1f %.1f\n", lastOrigin[0], lastOrigin[1], lastOrigin[2]);
printf("real : %.1f %.1f %.1f\n", entity->origin[0], entity->origin[1], entity->origin[2]);
printf("predict: %.1f %.1f %.1f\n", lastPredictOrigin[0], lastPredictOrigin[1], lastPredictOrigin[2]);
// Backup var for next frame
VectorCopy(entity->origin, lastOrigin);
doPrediction(target);
// Backup var for next frame
VectorCopy(entity->origin, lastPredictOrigin);
}
#endif // ETH_DEBUG