Ok so for some time now I've been working on walking with @Kasi;. We came up with quite a lot of ideas on how to approach it. One was to intercept socket events but that required decrypting the EOC client and injecting into it to get the right fields. Another was to get the Camera Position so that it gives the "Tile" the user is on. This tile is the exact equivalent to that of reflection/injection tiles. However, we do not see the camera position ever being passed to the graphics card directly. Our next idea was to create something like SPS but with 100% accuracy and this one sorta worked out. Well it did work out but we want to know if there are better/easier ways for any of you mathematicians out there.
Thus our first task was to write a runescape emulator in OpenGL/C++ to emulate how runescape loads the map in both RS2 and RS3. What we came up with was quite weird and tricky at the same time but it worked. The emulator's source is located at: http://www.mediafire.com/download/82...y/Emulator.zip
Our first code and theories are as follows:
Non-Rotated Maps:
Let us say that this is our Map information retrieved from the game:
C++ Code:ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -240.11853, 356.74777);
glVertex2f(309.88147, -144.74777); //Top Left
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -244.00943, -177.2381);
glVertex2f(305.99057, 389.2381); //Bottom Left
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 289.97644, -181.129);
glVertex2f(839.97644, 393.129); //Bottom Right
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 293.86731, 352.85684);
glVertex2f(843.86731, -140.85684); //Top Right
OpenGL coordinates are as follows:
http://i.imgur.com/PruG6n9.png
So every glMultiTexCoord2fARB that has: GL_TEXTURE1 as a parameter represents the Minimap circle and the coordinates represent its position relative to the MAP.
MMCircle: http://i.imgur.com/zsdkVW4.png
Every glVertex2f is Map coordinates and represents where the map is drawn within the current Window.
So in the above, it looks like:
http://i.imgur.com/Pq7Ikv9.png
Where the MMCircle's bottom left is at: 550, 212 and the center is at 627, 135.
Now how did we figure that out? Well see the numbers are hidden. The math goes like this:
Compass Width = 154.
Compass Height = 154.
Thus:
839.97644 + 240.11853 = 550;
550 + (154/2) = 627. Since the compass is relative to whatever map coordinate is at the top left of the screen.
-144.74777 + 356.74777 = 212;
212 - 77 = 135. Since the compass is relative to the top left map coordinate and Y increases downwards in window coordinates.
This is true for all coordinates above. No matter which pair you choose, you will always get 627, 135 if the quadrants are taken into account as well. It is also true no matter which way the map is turned. The minimap circle is never rotated. It is simply moved up and down relative to the MAP! And the Map is relative to the Window.
Each map is ALWAYS 512x512. In the above, you will notice that the map is stretched but still a square/rhombus. It's new dimensions is calculated using the distance formula like so:
C++ Code:
To find out the ratio of the stretched map to the regular unstretched, unrotated map, we do:
Ratio-X = Width / 512;
Ratio-Y = Height / 512;
We then get:
Ratio-X = 1.042969;
Ratio-Y = 1.042969;
Knowing the compass is relative to the Map, we can thus find the player's location within the current Map using the following formula assuming that the map is not rotated too much:
Player-X = (MMX / Ratio) + (154 / 2); + because X increases going right in window coordinates.
Player-Y = (MMY / Ratio) - (154 / 2); - because Y decreases going up in window coordinates.
Where MMX = 240 and MMY = 356 as shown above. The results are thus:
http://i.imgur.com/6dXDp43.png
That is our EXACT player position. The emulator figures that out and draws it to the screen. As you can see the map is only slightly rotated and it is only part of the map. The top part is cut off. I also had to stretch the window to show the right side because the Original Window size is 0, 0, 765, 553. And we know that some of those coords definitely do NOT fit into the window.
This was our first theory for calculating position and it worked FLAWLESSLY!
Rotated Maps:
http://i.imgur.com/9o34eK6.png
Our first theory worked perfectly fine! Until one day.. we decided to rotate the map and the algorithm broke :l Why did it break? Well because the MMCircle is always relative to whatever the top-left corner of the map is. If the map is rotated 180 degrees, the bottom right of the map will be drawn at the top left and coordinates would be upside down. Inverting it doesn't help either. I tried all mathematical formulas. Until day two, Kasi figured something out with his magical theoretical brain. Take notes of the coordinates in the map above using our first theory.
He said.. Why don't we try and rotate the map back to 0, 0 or as straight as it can get. So we tried all possible formulas we knew for rotating but we all know rotating an image is just crazy and ridiculously inaccurate. At first we used these formulas for distance and rotation:
C++ Code:float Distance(Point P, Point Q)
{
return std::sqrt(std::pow(Q.X - P.X, 2) + std::pow(Q.Y - P.Y, 2));
}
Point RotatePoint(Point P, float cx, float cy, float AngleRadians)
{
P.X = cos(AngleRadians) * (P.X-cx) - sin(AngleRadians) * (P.Y-cy) + cx;
P.Y = sin(AngleRadians) * (P.X-cx) + cos(AngleRadians) * (P.Y-cy) + cy;
return P;
}
And what happened was the map shrunk as it rotated. Sometimes it flipped and sometimes it got large. Very weird since we rotated it around its center-point.
Then somehow he came up with the following algorithm.. You'll notice that the algorithm still uses the 550, 212 and 627, 135 relativity numbers. It also uses the Map Ratio and thus 77 is what we also call a magic number. For us, these 5 numbers are magical. They don't even change in RS3 :l
C++ Code:float Rot = (360 - 146.95) * ((atan(1) * 4) / 180); //Knowing that a map is rotated at 146.95 degrees..
glColor3f(1, 1, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 317.67151, -52.51767);
Points[0] = RotatePoint({867.67151, 264.51767}, 627, 135, Rot);
glVertex2f(Points[0].X, Points[0].Y);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 0, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, 36.11798, 379.89832);
Points[1] = RotatePoint({586.11798, -167.89832}, 627, 135, Rot);
glVertex2f(Points[1].X, Points[1].Y);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 0);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -396.29797, 98.344757);
Points[2] = RotatePoint({153.70203, 113.344757}, 627, 135, Rot);
glVertex2f(Points[2].X, Points[2].Y);
ptr_glMultiTexCoord2fARB(GL_TEXTURE0, 1, 1);
ptr_glMultiTexCoord2fARB(GL_TEXTURE1, -114.74445, -334.07123);
Points[3] = RotatePoint({435.25555, 546.07123}, 627, 135, Rot);
glVertex2f(Points[3].X, Points[3].Y);
glEnd();
for (int I = 0; I < 4; I++)
Dists[I] = Distance({0, 0}, Points[I]);
float Smallest = Dists[0];
int Element = 0;
for (int I = 0; I < 4; I++)
{
if (Smallest > Dists[I])
{
Smallest = Dists[I];
Element = I;
}
}
And the above Un-rotates the map. Using our ratio theory being applied to the now un-rotated map, calculates all our player coordinates perfectly accurate just like the before. However, the above does NOT work for maps that are aligned straight already. In other words, applying a rotation of 0//360 with the above algorithm, it does NOT work.
After running his algorithm on the map, it turned out like:
http://i.imgur.com/zdxFQoG.png
Now notice the difference in the two sets of coordinates? The first set which you were to take note of; and this set which is 100% accurate and exactly where we stand. They are completely different! If you notice, the emulator does not SEE the difference at all. All it knows is that the mini-map circle is X, Y relative to the Map which is relative to the screen. Thus our position within the map is still the same. However, the formula generated the wrong coordinates. The second formula worked and generated the right coordinates.
In other words, when mine works, his does not. When mine fails, his works. Mine seems to work for anything between 270 < 0 < 90.
His works for anything between 45 < 180 < 315.
I know runescape 3 does not have a minimap circle. It's a rectangle/square but it makes no difference. The same formula will apply since the MMCircle is also a square with a transparent circle inside.
What we want from you:
So we want to know if you guys have any other ideas for calculating player position given the above info or if we really have to implement both algorithms given the compass angle. Another problem we have is making these into global coordinates not local. We were most likely going to load a bunch of maps just like SPS does and figure out our location within the local maps. Figure out which local map we're standing in within the global(world) map and that would be our global position but I'm not so sure :S

