1. Use the "for all players/actors" snippet
2. Get the 3d world position for each player
3. Convert it to 2d on screen position (0B55: convert_3D_coords 1@ 2@ 3@ to_screen 4@ 5@)
4. Get the 2d coordinates of the crosshair position (it's somewhere on this forum)
5. Check distance between the player and crosshair by using 0509: 4@ = distance_between_XY 0@ 1@ and_XY 2@ 3@
6. If distance is smaller than the distance of the previous player then copy his ID to a variable for future reference and overwrtite it every time you'll find the player closer to the crosshair
Edit: additionally use the following opcode for each of them to check whether they're in front of you 02CB: actor 31@ bounding_sphere_visible
Otherwise it may take into account players located behind you if I'm not mistaken
Edit_2: Just noticed it's C++... But the process is the same, it's just not as simple to convert the position and check the distance.
To convert the positions you could use function like this:
Code:
typedef bool (__cdecl *WorldCoords2ScreenCoords_t)(myVector*, myVector*, float * , float * , char, char);
WorldCoords2ScreenCoords_t WorldCoords2ScreenCoords = (WorldCoords2ScreenCoords_t)0x70CE30;
struct myVector
{
float pos[3];
};
tuple<float, float, bool> Convert3DposTo2Dscreen(myVector inPoint)
{
bool isOnScreen;
float x, y;
myVector outPoint;
WorldCoords2ScreenCoords(&inPoint, &outPoint, &x, &y, 0, 0);//gta internal function
outPoint.pos[0] /= x;
outPoint.pos[0] /= outPoint.pos[2];
outPoint.pos[1] /= y;
outPoint.pos[1] /= outPoint.pos[2];
outPoint.pos[0] *= resolutionX;
outPoint.pos[1] *= resolutionY;
if(x > 0.0 && y > 0.0)
{
isOnScreen = true;
}
else
{
isOnScreen = false;
}
return make_tuple(outPoint.pos[0], outPoint.pos[1], isOnScreen);
}
And then call it like this:
Code:
myVector inPoint = { position.x, position.y, position.z};
tuple<float, float, bool> result = Convert3DposTo2Dscreen(inPoint);
if(get<2>(result) == true)// if on screen
{
screenPos[0] = get<0>(result); // x pos
screenPos[1] = get<1>(result); // y pos
}
Then to check the distance between the player on screen pos and the crosshair you could use pythagorean theorem, the model below is not c++ but you'll get an idea what to do:
x_diff_abs = absolute_result(x_cross - x_player)
y_diff_abs = absolute_result(y_cross - y_player)
distance = square_root_of(x_diff_abs * x_diff_abs + y_diff_abs * y_diff_abs)
Btw here's an piece of code which involves getting the 3d world and 2d on screen position for each player, it's from the source of "supremeInfo" mod (2nd update), from the file called "triggerBot.cpp":
Code:
void AllPlayersCheck_GTA()
{
//ofstream log("logfile.txt", ios_base::app | ios_base::out);
int streamedPlayersNum=NULL;
float screenPosX = NULL;
float screenPosY = NULL;
XYZ pos;
XYZ myPos = player[1004].GetPos();
//AdjustCrosshairPos();
gtaActorBase = *(DWORD*)0xB74490;
byteMap = *(DWORD*)(gtaActorBase+4);
DWORD numberOfActiveActors = *(DWORD*)(gtaActorBase+12);
for(DWORD i = 0; i < 35584; i = i + 0x100)
{
BYTE inUse = *(BYTE*)byteMap;
byteMap += 0x1;
if(inUse > 0x00 && 0x80 > inUse)
{
//log << "1 "<<"\n";
DWORD offset = i;
offset = offset / 256;// The "byte map indicating which elements are in use" has 256 between each actor, by dividing the result by 256 we know what's the number of the player we're looking for
offset = offset * 1988;// Then multiply by the size of memory assigned per each actor
DWORD pActorStruct = *(DWORD*)*(DWORD*)0xB74490;
//pActorStruct = pActorStruct; //pointer to the first element in the pool
pActorStruct += offset; //add our offset for the active actor
//coords
if((*(unsigned short*)(pActorStruct + 0x530))!=1){continue;}//55 = wasted
pActorStruct += 0x14;
DWORD pActorCoords = *(DWORD*)pActorStruct;
pActorStruct -= 0x14;
/*
DWORD pActorStruct = (*(DWORD*)*(DWORD*)gtaActorBase) + ((i / 256) * 1988); //pointer to the first element in the pool
//coords
DWORD pActorCoords = *(DWORD*)(pActorStruct + 0x14);
*/
//log << "2 "<<"\n";
//streamedPlayerAddr[streamedPlayersNum] = pActorStruct - 0x14;
streamedPlayersNum++;
//if(streamedPlayersNum == numberOfActiveActors){break;}
//log<<"before reading pos"<<"\n";
pActorCoords += 0x30;
pos.x = *(float*)pActorCoords;
pActorCoords += 0x4;
pos.y = *(float*)pActorCoords;
pActorCoords += 0x4;
pos.z = *(float*)pActorCoords;
//log<<"after reading pos"<<"\n";
/*
pos.x = myPos.x+10.0f;
pos.y = myPos.y+10.0f;
pos.z = myPos.z+10.0f;
pos.x = 0.0f;
pos.y = 0.0f;
pos.z = 0.0f;
*/
//log << "3 "<<"\n";
if(_isnan((double)pos.x) || _isnan((double)pos.y) || _isnan((double)pos.z)){continue;}
if(IsPosOutOfRange(pos)){continue;}
//log <<"pos: " <<pos.x<<" "<<pos.y<<" "<<pos.z<<" myPos: "<<myPos.x<<" "<<myPos.y<<" "<<myPos.z<<"\n";
float dist = GetDistanceBetweenXYZ_XYZ(myPos,pos);
//log << "dist="<<dist<<"\n";
//to avoid bug
if(dist < 1.0f || dist > 150.0f)
{
//streamedPlayerAddr[streamedPlayersNum] = NULL;
//streamedPlayersNum--;
continue;
}
if(triggerBotPingModeOnOff)
{
int id = getSAMPPlayerIDFromGTAPed((actor_info*)pActorStruct);
if(id==1004){continue;}
float pingMult = (triggerBotPingModeStyle==PINGMODE_PROGRESSIVE?(float)player[id].GetPing():150.0f) / 45.0f;//300 is an example, could be higher or lower
pingMult *= triggerBotPingWeight;
XYZ spd = *(XYZ*)(pActorStruct+68);
pos.x += (spd.x * pingMult);
pos.y += (spd.y * pingMult);
pos.z += (spd.z * pingMult);
}
myVector inPoint = { pos.x, pos.y, pos.z};
tuple<float, float, bool> result = Convert3DposTo2Dscreen(inPoint);
if(get<2>(result) == true)
{
//is on screen
screenPosX = get<0>(result);
screenPosY = get<1>(result);
if(screenPosX > resolutionX || screenPosY > resolutionY || screenPosX < 0.0f || screenPosY < 0.0f){continue;}
//log <<"screenPos: "<< screenPosX<<" "<<screenPosY<<"\n";
float size = triggerBotRange/dist;
float xDiff = fabs(screenPosX - crosshairPosX);
float yDiff = fabs(screenPosY - crosshairPosY);
ManageTarget(streamedPlayersNum, screenPosX, screenPosY, size, (resolutionY/dist));
if(xDiff < size && yDiff < (resolutionY/dist))
{
MouseClick(&mouse);
triggerBotLength = size;
//if(!lockedTarget){lockedTarget = byteMap;}
lockedTarget = byteMap;
}
else
{
if(lockedTarget == byteMap && triggerBotTargetLock)
{
if(sqrtf((xDiff*xDiff) + (yDiff*yDiff)) < triggerBotAimThreshold)//500 is threshold
{
float x = (screenPosX - crosshairPosX) / triggerBotAimSpeed;
if(x>-1.0f&&x<0.0f){x=-1.0f;}if(x<1.0f&&x>0.0f){x=1.0f;}
float y = (screenPosY - crosshairPosY) / triggerBotAimSpeed;
//if(y>-1.0f&&y<0.0f){y=-1.0f;}if(y<1.0f&&y>0.0f){y=1.0f;}
if(timer.set(18, 0)){AimAtXY(x, y);}
//log << "after AimAtXY"<<"\n"<<"\n"<<"____________________"<<"\n";
}
}
}
}
}
}
ResetTargets();
OffCheck();
}