Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How Do You Get Entity Position? #4

Closed
ConnorMAD opened this issue Dec 29, 2023 · 11 comments
Closed

How Do You Get Entity Position? #4

ConnorMAD opened this issue Dec 29, 2023 · 11 comments
Labels
question Further information is requested

Comments

@ConnorMAD
Copy link

Hi, I'm learning and I'm analyzing your code, I've seen a lot of things in it, could you help me with just one thing? How to get the position of entities?

@IntelSDM
Copy link
Owner

Getting Player Position

void BasePlayer::UpdatePosition(VMMDLL_SCATTER_HANDLE handle)
{
	TargetProcess.QueueScatterReadEx(handle, PlayerModel + Position, reinterpret_cast<void*>(&TransformPosition), sizeof(Vector3));
}

Caching the playerlist, do this every 3-5 seconds.

void BasePlayer::CachePlayerList()
{
	if (VisiblePlayerList == 0)
		return;
	std::vector<std::shared_ptr<BasePlayer>> templayerlist;
	uint32_t size = TargetProcess.Read<uint32_t>(VisiblePlayerList + VisiblePlayerListSize);
	uint64_t buffer = TargetProcess.Read<uint64_t>(VisiblePlayerList + VisiblePlayerListBuffer);
	if (size == 0 || buffer == 0)
		return;
	std::vector<uint64_t> playerlist;
	playerlist.resize(size);
	auto handle = TargetProcess.CreateScatterHandle();
	for (int i = 0; i < size; i++)
	{
		TargetProcess.QueueScatterReadEx(handle, buffer + (0x20 + (i * 8)), reinterpret_cast<void*>(&playerlist[i]), sizeof(uint64_t));
	}
	TargetProcess.ExecuteScatterRead(handle);
	TargetProcess.CloseScatterHandle(handle);
	handle = TargetProcess.CreateScatterHandle();
	for (int i = 0; i < size; i++)
	{
		if (playerlist[i] == NULL)
			continue;
		templayerlist.push_back(std::make_shared<BasePlayer>(playerlist[i], handle));
	}
	TargetProcess.ExecuteScatterRead(handle);
	TargetProcess.CloseScatterHandle(handle);
	PlayerList = templayerlist;
}

Looping PlayerList

std::shared_ptr<CheatFunction> PlayerLoop = std::make_shared<CheatFunction>(0, []()
{
	if (!BaseLocalPlayer->IsPlayerValid())
		return;

	if (BaseLocalPlayer->PlayerList.size() == 0)
		return;
	auto handle = TargetProcess.CreateScatterHandle();
	int count = 0;
	std::vector<std::shared_ptr<BasePlayer>> templayerlist = BaseLocalPlayer.get()->PlayerList;
	for (int i = 0; i < templayerlist.size(); i++)
	{
		std::shared_ptr<BasePlayer> player = templayerlist[i];
		count += player->IntializeClasses(handle);
	}
	if (count != 0)
		TargetProcess.ExecuteScatterRead(handle);
	TargetProcess.CloseScatterHandle(handle);

	handle = TargetProcess.CreateScatterHandle();
	for (int i = 0; i < templayerlist.size(); i++)
	{
		std::shared_ptr<BasePlayer> player = templayerlist[i];
		if (!player->IsPlayerValid())
			continue;
		player->UpdatePosition(handle);
	}
	TargetProcess.ExecuteScatterRead(handle);
	TargetProcess.CloseScatterHandle(handle);
	json jsoned;
	CurrentMatrix = Camera->GetViewMatrix();
	for (int i = 0; i < templayerlist.size(); i++)
	{
		std::shared_ptr<BasePlayer> player = templayerlist[i];
		if (player->IsLocalPlayer() || !player->IsPlayerValid())
			continue;
		Vector3 position = player->GetPosition();
		if (position == Vector3(0, 0, 0))
			continue;
		Vector2 screenpos = WorldToScreen(position);
		if (screenpos.x == 0 && screenpos.y == 0)
			continue;
		TestObjectJson testobject;

		testobject.X = screenpos.x;
		testobject.Y = screenpos.y;
		testobject.Name = "Player";
		testobject.Type = 1;
		json entry;
		testobject.ToJson(entry);
		jsoned.push_back(entry);
	}
	std::lock_guard<std::mutex> lock(TCPClient->HandlerLock);
	{
		if (TCPClient->SendPackets && !jsoned.is_null())
		{
			TCPClient->SendText(jsoned.dump());
		}
	}
});

More offsets you need for baseplayer

	uint64_t VisiblePlayerList = 0x20; // 	private static ListDictionary<ulong, global::BasePlayer> visiblePlayerList;
	uint64_t VisiblePlayerListBuffer = 0x18; // list value 
	uint32_t VisiblePlayerListSize = 0x10; // list size

	uint64_t PlayerModel = 0x678; //public PlayerModel playerModel;
	uint64_t Position = 0x1B8; // PlayerModel -> internal Vector3 position;
	bool Initialized = false;
	Vector3 TransformPosition = Vector3(0, 0, 0);

I have missed the calls for getting playermodel address and all the typical reads to it but you can just read them in the baseplayer constructor. All the offsets you need are there and all the code is there to get all the player positions

@IntelSDM IntelSDM added help wanted Extra attention is needed question Further information is requested and removed help wanted Extra attention is needed labels Dec 29, 2023
@IntelSDM IntelSDM changed the title help How Do You Get Entity Position? Dec 29, 2023
@ConnorMAD
Copy link
Author

wow, thank you so much.
Another thing I was unsure about, these offsets:
uint64_t VisiblePlayerList = 0x20; // private static ListDictionary<ulong, global::BasePlayer> visiblePlayerList;
uint64_t VisiblePlayerListBuffer = 0x18; // list value
uint32_t VisiblePlayerListSize = 0x10; // list size

Where were they taken from?
because 0x20 is linked to VisiblePlayerList
Sorry for the questions, I believe they are silly, but I am learning and I am still new, I would like to learn more about reverse engineering.

@IntelSDM
Copy link
Owner

So 0x20 is from Baseplayer. Baseplayer + 0x20 is the address to the list datatype that contains the list of players. To explain the other values I need to say this, Whenever you store a list or an array it's just a class /struct(depending on C++ or C) so since we aren't just reading into the values, we are reading the C# List class. There are a few variables in The List class, but the ones we need for unity hacking are the size and the buffer. The size is the size of the list and the buffer is the actual datatypes in a raw array format. These values shouldn't ever change unless for some reason Microsoft updates the .NET framework's List class. So that's where and why we read 0x18 and 0x10 from any lists we want to read within Unity games or hell most games that don't just use a flat-out array.

@IntelSDM IntelSDM pinned this issue Dec 30, 2023
@ConnorMAD
Copy link
Author

ConnorMAD commented Dec 30, 2023

                            if "BasePlayer" or "NPCPlayer" in szName:
                                try:
                                    TEMPTEMP = self.mem.read_ulonglong((pObject + 0x18))
                                    temp_pObject = self.mem.read_ulonglong((TEMPTEMP + 0x28))
                                    print(temp_pObject)
                                    name = self.mem.read_ulonglong(temp_pObject + off_displayname)
                                    intname = self.mem.read_int(name + 0x10)
                                    name_ = ""

                                    for i in range(intname):
                                        name_ += str(self.mem.read_string(name + 0x14 + i))

                                    if temp_pObject == LocalPlayer:
                                        pass
                                    else:
                                        pos_ = self.mem.read_ulonglong(temp_pObject + off_playermodel)
                                        pos = self.read_vec3(pos_ + 0x1B8)
                                        health = int(self.mem.read_float(temp_pObject + 0x25C))
                                        self.entities.append(Entity(pos, "Player", health = health, playername = name_))
                                        continue

what i doing wrong?

@ConnorMAD
Copy link
Author

I can get the positions, but the names are not

@IntelSDM
Copy link
Owner

I haven't gotten around to working on my other version of this for ESP for a while as I have other projects to complete so i don't read the displayname but print out the values for each of your reads and put them in ReClass.net in a none EAC build of the game. You will see the addresses for everything in the class you are looking at and the contents of each byte and if it's heaped or not.
I am going to guess its this code though:

                                    for i in range(intname):
                                        name_ += str(self.mem.read_string(name + 0x14 + i))

That looks completely wrong and will not work, Look in consolecommands.cpp and you will see how I read strings. Do it the exact same way, read it as a char array, they should have them in python, something like this:

myArray = "\0" * 100

https://stackoverflow.com/questions/34675555/python-char-array-declaration
Just convert the char array back to a string.

@ConnorMAD
Copy link
Author

i got it, thanks.
Last thing, I promise, it has helped me a lot

                        if overlay.esp:
                            if i % 100 == 0:
                                camera = self.mem.read_ulonglong(self.gameassembly_base + 0x3417CD8)
                                matrix4x4 = []
                                print(matrix4x4)
                                for j in range(16):
                                    matrix4x4.append(self.mem.read_float(self.mem.read_ulonglong(camera + 0x18) + 0xDC + 0x4 * j))
                                overlay.matrix4x4 = matrix4x4

I'm using a matrix to store and then send to my wts, but I'm having difficulty reading the data to send

@IntelSDM
Copy link
Owner

Firstly, Don't read the camera constantly, It also appears you are reading from the camera manager which is honestly just a mess. Read from MainCamera.

MainCamera::MainCamera()
{
	printf("[MainCamera] Initialized\n");
	uint64_t maincamera = TargetProcess.Read<uint64_t>(TargetProcess.GetModuleAddress(L"GameAssembly.dll") + Class); // Get Class Start Address
	printf("[MainCamera] MainCamera: 0x%llX\n", maincamera);
	this->StaticField = TargetProcess.Read<uint64_t>(maincamera + StaticField); // Set Static Padding
	printf("[MainCamera] Static Fields: 0x%llX\n", StaticField);
	this->Camera = TargetProcess.Read<uint64_t>(StaticField + Camera); // Current MainCamera
	printf("[MainCamera] Camera: 0x%llX\n", Camera);
	this->CameraGamoObject = TargetProcess.Read<uint64_t>(Camera + CameraGamoObject); // get the native gameobject
	printf("[MainCamera] CameraGamoObject: 0x%llX\n", CameraGamoObject);


}
bool MainCamera::IsValid()
{
	return Camera != 0;
}
ViewMatrix MainCamera::GetViewMatrix()
{
	ViewMatrix viewmatrix;
	viewmatrix = TargetProcess.Read<ViewMatrix>(CameraGamoObject + ViewMatrixOffset);
	return viewmatrix;
}
class MainCamera
{
	/*
	Script.json
	"Address": 55074032,
	  "Name": "MainCamera_TypeInfo",
	  "Signature": "MainCamera_c*"
	*/
	uint64_t Class = 0x3485CF0;
	//Dump.cs / DummyDLL
	uint64_t StaticField = 0xB8;// Static Padding To Access Static Fields
	uint64_t Camera = 0x0;// public static Camera mainCamera
	uint64_t CameraGamoObject = 0x10;
	uint64_t ViewMatrixOffset = 0x2E4;
	ViewMatrix CacheMatrix;
public:
	MainCamera();
	bool IsValid();
	ViewMatrix GetViewMatrix();
};
struct ViewMatrix
{
public:
	float matrix[4][4];

	Vector3 Transform(const Vector3 vector) const;
};

@ConnorMAD
Copy link
Author

you are amazing, really thank you for your help!

@ConnorMAD
Copy link
Author

                        if overlay.esp:
                            if i % 100 == 0:
                                camera = self.mem.read_ulonglong(self.gameassembly_base + 0x3485CF0)
                                matrix4x4 = []

                                for j in range(16):
                                    # Correção aqui: Use self.read_chain
                                    camera_manager = read_chain(self, camera, [0xB8, 0x0, 0x10])
                                    camera_managerr = self.mem.read_float(camera_manager) + 0x2E4
                                    matrix4x4.append(camera_managerr * j)
                                print(overlay.matrix4x4)
def read_chain(self, address, offsets):
    current = address
    for offset in offsets[:-1]:
        current = self.mem.read_ulonglong(current + offset)
        if current == 0:
            return None
    return self.mem.read_ulonglong(current + offsets[-1])

what am i doing wrong?

@ConnorMAD
Copy link
Author

i got it:

                        if i % 100 == 0:
                            camera = self.mem.read_ulonglong(self.gameassembly_base + 0x3485CF0)
                            matrix4x4 = []

                            for j in range(16):
                                # Correção aqui: Use self.read_chain
                                camera_manager = read_chain(self, camera, [0xB8, 0x0, 0x10])
                                camera_managerr = camera_manager + 0x2E4
                                camera_managerrr = self.mem.read_float(camera_managerr + (j * 4))

                                matrix4x4.append(camera_managerrr)
                                overlay.matrix4x4 = matrix4x4
                            print(overlay.matrix4x4)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants