在設計Bot之前,分析遊戲裡面的坐標系統是非常重要的,因為在尋路的過程我們需要坐標的轉換,以利我們在二維坐標的障礙物偵測,不過有些障礙物只能透過三維坐標來偵測障礙物,因此需要了解整個遊戲的坐標系統的轉換才能繼續開發我們的Bot程式。
一、二維坐標系統
在遊戲的右上角,會有小地圖顯示,我們可以抓取小地圖的Pixel值,分析地圖的邊界位置,不過我們也要知道遊戲中的三維坐標是如何轉換成小地圖的螢幕坐標。
另外我們在小地圖上,可以看見其餘的物件,這些都是遊戲將小地圖透過DrawPrimitiveUP繪製再螢幕上後,再將剩下的物件會制上去,物件包含Boss位址、人物位址、地圖資訊等等,這些都可能會影響我們抓取小地圖邊界的雜訊,因此我們需要將繪製物件的函式Nop掉。
去除小地圖上的物件雜訊後,就顯得乾淨許多,也可以比較準確的透過Pixel值來抓取小地圖上的邊界位址。
二、小地圖的二維坐標轉換
subs xmm0, [r9+4],其中xmm0是三維坐標的z坐標值,[r9+4]是worldScaleZ,那麼z坐標值減去worldScaleZ,是計算z坐標值轉換成小地圖的x坐標。
subs xmm1, [r9],其中xmm1是三維坐標的x坐標值,[r9]是worldScaleX,那麼x坐標值減去worldScaleX,是計算x坐標值轉換成小地圖的y坐標。
mulss xmm1, [rbx+4](乘法運算),其中xmm1是1 / 75,[rbx+4]是上一步計算的x坐標值。
mulss xmm0, [rbx] (乘法運算),其中xmm0也是1 / 75,[rbx]是上一步計算的z坐標值。
在上一步x和z都會乘上1 / 75,以利轉換成螢幕坐標,不過還並未轉換成小地圖上的坐標位置,因此在這步會進一步計算x和z值。
addss xmm0, [r9](加法運算),其中xmm0是小地圖x軸的差值計算值,[r9]是上一步計算後的z值。
subss xmm1, [r9+4] (減法運算),其中xmm1是小地圖y軸的差值計算值,[r9+4] 是上一步計算後的x值。
三、螢幕坐標轉換遊戲裡的三維坐標
在小地圖裡面,有些障礙物是不會顯示的,因此要仰賴之前的障礙物分析來躲避它,不過我們需要知道我們所檢測的螢幕坐標對應的三維坐標的數值,這樣才能準確的判斷這裡是否會碰撞到障礙物。
在遊戲裡我們滑鼠點擊左鍵,它會在我們點擊的位置出現類似驚嘆號的標示,並且人物會移動到此位置,因此這會是我們坐標轉換的切入點。
在遊戲裡會透過GetCursorPos來抓取滑鼠在螢幕上的位移坐標值,然後再利用ScreenToClient轉換成遊戲視窗裡的坐標位置。
mov r9d, [rsp+18C],其中[rsp+18C]是ScreenToClient回傳的y坐標值。
mov r9d, [rsp+18C],其中[rsp+188]是ScreenToClient回傳的x坐標值。
lea rdx, [rsp+50],它會在調用call 502AB00之後將三維坐標值的差值運算值存放到[rsp+50]裡面。
lea rcx, [rsp+98],它會在調用call 502AB00之後將一個三維坐標值存放到[rsp+98]裡面。
在三維坐標的差值運算後,會將結果存到[rsp+A8](x坐標)、[rsp+AC] (z坐標)、[rsp+B0] (y坐標)。
[rsp+50]是調用call 502AB00回傳的差值運算值,[rsp+98]也是調用call 502AB00回傳的三維坐標值,[rsp+A8]是前兩者運算後的結果值,上述這些參數都是為了從螢幕坐標轉換成三維坐標的前置作業,最後再調用call 5503790後的回傳值rax,其中rax+0x10是螢幕坐標轉換三維坐標的起始位址(x、z、y)。