add versions of clubman and tokyo
@@ -0,0 +1,497 @@
|
||||
|
||||
; https://github.com/berban/Gdip
|
||||
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#NoEnv
|
||||
#Persistent
|
||||
#SingleInstance Force
|
||||
#Include Lib\Gdip.ahk
|
||||
|
||||
CoordMode, Pixel, Client
|
||||
CoordMode, ToolTip, Client
|
||||
DetectHiddenWindows, On
|
||||
ListLines Off
|
||||
Process, priority, , High
|
||||
SendMode Input
|
||||
SetBatchLines, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SetFormat, Float, 0.2
|
||||
; SetFormat, IntegerFast, Hex
|
||||
SetKeyDelay, 50
|
||||
SetMouseDelay, -1
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
|
||||
; Variables
|
||||
races_clean := 0
|
||||
races_clean_percent := 0
|
||||
races_completed := 0
|
||||
races_completed_check := 0
|
||||
credits_total := 0
|
||||
credits_average := 0
|
||||
|
||||
time_start := A_TickCount
|
||||
time_current := A_TickCount
|
||||
|
||||
window_width := 640
|
||||
window_height := 360
|
||||
|
||||
; GUI
|
||||
Gui, New, -MaximizeBox -Resize, ClubmanPlus 0.2
|
||||
Gui, Font, S10
|
||||
Gui, Add, Button, w150 h40 Default gStart, Start
|
||||
Gui, Add, Button, w150 h40 x+10 gReset, Reset
|
||||
Gui, Show
|
||||
return
|
||||
|
||||
; GUI events
|
||||
GuiClose:
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
OutputDebug % "Clubman> Terminated"
|
||||
ExitApp
|
||||
|
||||
; GUI buttons
|
||||
Start:
|
||||
hwnd := 0
|
||||
|
||||
Gosub, Release_All
|
||||
Gosub, GrabWindow
|
||||
|
||||
if (hwnd = 0) {
|
||||
MsgBox, % "PS Remote Play not found"
|
||||
return
|
||||
}
|
||||
|
||||
SetTimer, Health, 600000
|
||||
SetTimer, Summary, 3600000
|
||||
time_start := A_TickCount
|
||||
|
||||
; ** AFK Loop
|
||||
Loop {
|
||||
|
||||
; ** RACE
|
||||
OutputDebug % "Clubman> Race: Waiting for position GUI to show"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(90), TuneCoordinateY(90), 4, 75)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Starting race"
|
||||
Gosub, Hold_X
|
||||
Gosub, Hold_Down
|
||||
OutputDebug % "Clubman> Race: Racing until position GUI disappears"
|
||||
while (IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(90), TuneCoordinateY(90), 4, 75)) {
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Race ended, releasing all buttons"
|
||||
Gosub, Release_All
|
||||
|
||||
; ** GO TO LEADERBOARDS
|
||||
OutputDebug % "Clubman> End race: Waiting for continue X icon to show"
|
||||
while (!IsColor(hwnd, 0xDEDCDA, TuneCoordinateX(475), TuneCoordinateY(563), 4, 10)) {
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Press X to continue"
|
||||
while (IsColor(hwnd, 0xDEDCDA, TuneCoordinateX(475), TuneCoordinateY(563), 4, 10)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 1000
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Transitioning to leaderboard"
|
||||
|
||||
; ** LEADERBOARD
|
||||
Loop {
|
||||
OutputDebug % "Clubman> Leaderboard: Checking positions"
|
||||
|
||||
if (IsColor(hwnd, 0xBADD3E, TuneCoordinateX(675), TuneCoordinateY(169), 10, 10)) {
|
||||
OutputDebug % "Clubman> Leaderboard: 1st position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, TuneCoordinateX(675), TuneCoordinateY(198), 10, 10)) {
|
||||
OutputDebug % "Clubman> Leaderboard: 2nd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, TuneCoordinateX(675), TuneCoordinateY(227), 10, 10)) {
|
||||
OutputDebug % "Clubman> Leaderboard: 3rd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, TuneCoordinateX(675), TuneCoordinateY(256), 10, 10)) {
|
||||
OutputDebug % "Clubman> Leaderboard: 4th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, TuneCoordinateX(675), TuneCoordinateY(285), 10, 10)) {
|
||||
OutputDebug % "Clubman> Leaderboard: 5th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else {
|
||||
Sleep, 500
|
||||
}
|
||||
}
|
||||
|
||||
; ** REWARDS
|
||||
OutputDebug % "Clubman> Rewards: Waiting for Rewards screen to load (checking money earnt)"
|
||||
while (!IsColor(hwnd, 0xBE140F, TuneCoordinateX(850), TuneCoordinateY(236), 10, 50)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Rewards: Found Rewards screen"
|
||||
races_completed++
|
||||
|
||||
Loop 100 {
|
||||
if (IsColor(hwnd, 0x5C90FB, TuneCoordinateX(486), TuneCoordinateY(311), 4, 20)) {
|
||||
OutputDebug % "Clubman> Rewards: Clean bonus"
|
||||
races_clean++
|
||||
PixelSearch(TuneCoordinateX(486), TuneCoordinateY(311), 1, hwnd, "clean")
|
||||
break
|
||||
}
|
||||
|
||||
if (A_Index == 100) {
|
||||
OutputDebug % "Clubman> Rewards: No clean bonus"
|
||||
PixelSearch(TuneCoordinateX(486), TuneCoordinateY(311), 1, hwnd, "no-clean")
|
||||
}
|
||||
}
|
||||
|
||||
; ** REPLAY
|
||||
OutputDebug % "Clubman> Replay: Waiting for Replay screen to load (checking exit button)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(920), TuneCoordinateY(555), 4, 10)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Pressing the Exit button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(920), TuneCoordinateY(555), 4, 10)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Leaving the Replay screen"
|
||||
|
||||
; ** RACE RESULTS
|
||||
OutputDebug % "Clubman> Race Result: Waiting for Race Result screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xBB1C1A, TuneCoordinateX(664), TuneCoordinateY(540), 5, 10)) {
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Moving cursor to the Retry button"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(525), TuneCoordinateY(550), 4, 10)) {
|
||||
Gosub, Press_Right
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Pressing the Retry button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(525), TuneCoordinateY(550), 4, 10)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
; ** RACE START
|
||||
OutputDebug % "Clubman> Race Start: Waiting for Race Start screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(300), TuneCoordinateY(550), 4, 10)) {
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Start: Pressing the Start button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, TuneCoordinateX(300), TuneCoordinateY(550), 4, 10)) {
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
OutputDebug % "--- Summary ---"
|
||||
credits_total := (races_completed * 0.07 + races_clean * 0.035)
|
||||
races_clean_percent := (races_clean / races_completed) * 100
|
||||
time_current := A_TickCount
|
||||
credits_average := credits_total / (time_current - time_start) * 3600000
|
||||
|
||||
OutputDebug % "Clubman> Summary: Races " races_completed
|
||||
OutputDebug % "Clubman> Summary: Races Clean " races_clean
|
||||
OutputDebug % "Clubman> Summary: Races Clean Rate " races_clean_percent "%"
|
||||
OutputDebug % "Clubman> Summary: Earnings " credits_total "M"
|
||||
OutputDebug % "Clubman> Summary: Earnings Rate " credits_average "M/Hr"
|
||||
OutputDebug % "---------------"
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Coordinate tuning
|
||||
; -------------------
|
||||
TuneCoordinateX(coord) {
|
||||
; 3840 because I used a 4K 16:9 monitor to get the values
|
||||
Return Round((A_ScreenWidth * coord) / 3840)
|
||||
}
|
||||
|
||||
TuneCoordinateY(coord) {
|
||||
; 2160 because I used a 4K 16:9 monitor to get the values
|
||||
Return Round((A_ScreenHeight * coord) / 2160)
|
||||
}
|
||||
|
||||
Reset:
|
||||
; Gosub, GrabWindow
|
||||
|
||||
; ; PixelSearch(TuneCoordinateX(850), TuneCoordinateY(236), 10, WinExist("PS Remote Play"), "test1")
|
||||
; bolas := IsColor(hwnd, 0xBE140F, TuneCoordinateX(850), TuneCoordinateY(236), 10, 50)
|
||||
; OutputDebug % "Clubman> is color " bolas
|
||||
|
||||
; OutputDebug % "Clubman> d1 " ColorDistance(0xBE140F, 0x87281D)
|
||||
; OutputDebug % "Clubman> d2 " ColorDistance(0xBE140F, 0x6C1F16)
|
||||
; OutputDebug % "Clubman> d2 " ColorDistance(0xBE140F, 0x862A1F)
|
||||
|
||||
; Gosub, GrabWindow
|
||||
|
||||
; X := (A_ScreenWidth / 2) + 1 ; X = 677 (On 1024) or 805 (On 1280)
|
||||
; Y := A_ScreenHeight - 25 ; Y = 743 (On 768) or 999 (On 1024)
|
||||
|
||||
; OutputDebug % "Clubman> X " TuneCoordinateX(90)
|
||||
; OutputDebug % "Clubman> Y " TuneCoordinateY(90)
|
||||
|
||||
; PixelSearch(90, 90, 10, WinExist("PS Remote Play"), "test1")
|
||||
; PixelSearch(675, 256, 10, WinExist("PS Remote Play"), "l4")
|
||||
; PixelSearch(675, 227, 10, WinExist("PS Remote Play"), "l3")
|
||||
; PixelSearch(675, 198, 10, WinExist("PS Remote Play"), "l2")
|
||||
; PixelSearch(675, 169, 10, WinExist("PS Remote Play"), "l1")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Health Check
|
||||
; -------------------
|
||||
Health:
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
OutputDebug % "Clubman> Health: Checking health at " current_date
|
||||
OutputDebug % "Clubman> Health: Races completed " races_completed
|
||||
OutputDebug % "Clubman> Health: Races completed last time " races_completed_check
|
||||
|
||||
if (races_completed_check >= races_completed) {
|
||||
OutputDebug % "Clubman> Health: Error dectected, sending notification"
|
||||
SendNotification("ClubmanPlus", "Something went wrong", 2, "persistent")
|
||||
} else {
|
||||
OutputDebug % "Clubman> Health: Running healthy"
|
||||
races_completed_check := races_completed
|
||||
}
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Summary Check
|
||||
; -------------------
|
||||
Summary:
|
||||
OutputDebug % "Clubman> Summary: Sending summary notification"
|
||||
message := ""
|
||||
message := message "Races " races_clean " / " races_completed " (" races_clean_percent ")`n"
|
||||
message := message "Earnings " credits_total "M (" credits_average "M/Hr)"
|
||||
SendNotification("ClubmanPlus", message, 0, "cashregister")
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Send Notification
|
||||
; -------------------
|
||||
SendNotification(title, message, level, sound) {
|
||||
|
||||
IniRead, token, %A_ScriptDir%\clubman.ini, pushover, token
|
||||
IniRead, user, %A_ScriptDir%\clubman.ini, pushover, user_key
|
||||
|
||||
retries := 60
|
||||
expires := 3600
|
||||
|
||||
url := "https://api.pushover.net/1/messages.json"
|
||||
param := "token=" token "&user=" user "&title=" title "&message=" message "&sound=" sound "&priority=" level
|
||||
|
||||
if (level == 2) {
|
||||
param := param "&retry=" retries "&expire=" expires
|
||||
}
|
||||
|
||||
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
WebRequest.Open("POST", url)
|
||||
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
WebRequest.Send(param)
|
||||
Return
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Grab Window
|
||||
; -------------------
|
||||
GrabWindow:
|
||||
OutputDebug % "Clubman> Looking for window"
|
||||
hwnd := WinExist("PS Remote Play")
|
||||
|
||||
if (hwnd > 0) {
|
||||
OutputDebug % "Clubman> Window found: " hwnd
|
||||
WinMove, ahk_id %hwnd%,, 0, 0, %window_width%, %window_height%
|
||||
WinActivate, ahk_id %hwnd%
|
||||
ControlFocus,, ahk_id %hwnd%
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Is Color
|
||||
; -------------------
|
||||
IsColor(hwnd, target_color, x, y, b, tolerance) {
|
||||
for i, c in PixelSearch(x, y, b, hwnd) {
|
||||
if (ColorDistance(c, target_color) <= tolerance) {
|
||||
Return True
|
||||
}
|
||||
}
|
||||
Return False
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Color Distance
|
||||
; -------------------
|
||||
ColorDistance( c1, c2 ) {
|
||||
r1 := c1 >> 16
|
||||
g1 := c1 >> 8 & 255
|
||||
b1 := c1 & 255
|
||||
r2 := c2 >> 16
|
||||
g2 := c2 >> 8 & 255
|
||||
b2 := c2 & 255
|
||||
return Sqrt( (r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2 )
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Pixel Search
|
||||
; -------------------
|
||||
PixelSearch(x, y, b, hwnd, debugsave := "") {
|
||||
WinGetPos,,, width, height, ahk_id %hwnd%
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
hbm := CreateDIBSection(width, height),
|
||||
hdc := CreateCompatibleDC(),
|
||||
obm := SelectObject(hdc, hbm)
|
||||
|
||||
RegExMatch(A_OsVersion, "\d+", version)
|
||||
PrintWindow(hwnd, hdc, version >= 8 ? 2 : 0)
|
||||
|
||||
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
SelectObject(hdc, obm),
|
||||
DeleteObject(hbm),
|
||||
DeleteDC(hdc)
|
||||
|
||||
pixs := []
|
||||
Loop % b*2 + 1 {
|
||||
i := (-1 * b) + (A_Index - 1)
|
||||
Loop % b*2 + 1 {
|
||||
j := (-1 * b) + (A_Index - 1)
|
||||
pixs.Push(Gdip_GetPixel(pBitmap, x+i, y+j) & 0x00FFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
if (debugsave != "") {
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
filename := A_ScriptDir . "\" . current_date . "-" . debugsave . ".bmp"
|
||||
|
||||
; debugbitmap:=Gdip_CloneBitmapArea(pBitmap, x-b, y-b, b*2, b*2)
|
||||
; Gdip_SaveBitmapToFile(debugbitmap, filename)
|
||||
Gdip_SaveBitmapToFile(pBitmap, filename)
|
||||
Gdip_DisposeImage(debugbitmap)
|
||||
; Run % filename
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Release All
|
||||
; -------------------
|
||||
Release_All:
|
||||
Gosub, Release_X
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press x
|
||||
; -------------------
|
||||
Press_X:
|
||||
Gosub, Hold_X
|
||||
Gosub, Release_x
|
||||
return
|
||||
|
||||
Hold_X:
|
||||
ControlSend,, {Enter down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_X:
|
||||
ControlSend,, {Enter up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press O
|
||||
; -------------------
|
||||
Press_O:
|
||||
Gosub, Hold_O
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
Hold_O:
|
||||
ControlSend,, {Esc down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_O:
|
||||
ControlSend,, {Esc up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Right
|
||||
; -------------------
|
||||
Press_Right:
|
||||
Gosub, Hold_Right
|
||||
Gosub, Release_Right
|
||||
return
|
||||
|
||||
Hold_Right:
|
||||
ControlSend,, {Right down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Right:
|
||||
ControlSend,, {Right up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Left
|
||||
; -------------------
|
||||
Press_Left:
|
||||
Gosub, Hold_Left
|
||||
Gosub, Release_Left
|
||||
return
|
||||
|
||||
Hold_Left:
|
||||
ControlSend,, {Left down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Left:
|
||||
ControlSend,, {Left up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Up
|
||||
; -------------------
|
||||
Press_Up:
|
||||
Gosub, Hold_Up
|
||||
Gosub, Release_Up
|
||||
return
|
||||
|
||||
Hold_Up:
|
||||
ControlSend,, {Up down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Up:
|
||||
ControlSend,, {Up up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Down
|
||||
; -------------------
|
||||
Press_Down:
|
||||
Gosub, Hold_Down
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
Hold_Down:
|
||||
ControlSend,, {Down down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Down:
|
||||
ControlSend,, {Down up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; Hotkeys
|
||||
^Esc::ExitApp
|
||||
@@ -0,0 +1,3 @@
|
||||
[pushover]
|
||||
user_key=your_key
|
||||
token=your_token
|
||||
@@ -0,0 +1,490 @@
|
||||
|
||||
; https://github.com/berban/Gdip
|
||||
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#NoEnv
|
||||
#Persistent
|
||||
#SingleInstance Force
|
||||
#Include Lib\Gdip.ahk
|
||||
|
||||
CoordMode, Pixel, Client
|
||||
CoordMode, ToolTip, Client
|
||||
DetectHiddenWindows, On
|
||||
ListLines Off
|
||||
Process, priority, , High
|
||||
SendMode Input
|
||||
SetBatchLines, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SetFormat, Float, 0.2
|
||||
; SetFormat, IntegerFast, Hex
|
||||
SetKeyDelay, 50
|
||||
SetMouseDelay, -1
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
|
||||
; Variables
|
||||
races_clean := 0
|
||||
races_clean_percent := 0
|
||||
races_completed := 0
|
||||
races_completed_check := 0
|
||||
credits_total := 0
|
||||
credits_average := 0
|
||||
|
||||
time_start := A_TickCount
|
||||
time_current := A_TickCount
|
||||
|
||||
window_width := 640
|
||||
window_height := 360
|
||||
|
||||
; GUI
|
||||
Gui, New, -MaximizeBox -Resize, ClubmanPlus 0.3
|
||||
Gui, Font, S10
|
||||
Gui, Add, Button, w150 h40 Default gStart, Start
|
||||
Gui, Add, Button, w150 h40 x+10 gReset, Reset
|
||||
Gui, Show
|
||||
return
|
||||
|
||||
; GUI events
|
||||
GuiClose:
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
OutputDebug % "Clubman> Terminated"
|
||||
ExitApp
|
||||
|
||||
; GUI buttons
|
||||
Start:
|
||||
hwnd := 0
|
||||
|
||||
Gosub, Release_All
|
||||
Gosub, GrabWindow
|
||||
|
||||
if (hwnd = 0) {
|
||||
MsgBox, % "PS Remote Play not found"
|
||||
return
|
||||
}
|
||||
|
||||
SetTimer, Health, 600000
|
||||
SetTimer, Summary, 3600000
|
||||
time_start := A_TickCount
|
||||
|
||||
; ** AFK Loop
|
||||
Gosub, Press_X
|
||||
|
||||
Loop {
|
||||
|
||||
; ** RACE
|
||||
OutputDebug % "Clubman> Race: Waiting for position GUI to show"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Starting race"
|
||||
Gosub, Hold_X
|
||||
Gosub, Hold_Down
|
||||
OutputDebug % "Clubman> Race: Racing until position GUI disappears"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Race ended, releasing all buttons"
|
||||
Gosub, Release_All
|
||||
Sleep, 5000
|
||||
|
||||
; ** GO TO LEADERBOARDS
|
||||
OutputDebug % "Clubman> End race: Waiting for continue X icon to show"
|
||||
while (!IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Press X to continue"
|
||||
while (IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Gosub, Press_X
|
||||
Sleep, 100
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Transitioning to leaderboard"
|
||||
|
||||
; ** LEADERBOARD
|
||||
Loop {
|
||||
OutputDebug % "Clubman> Leaderboard: Checking positions"
|
||||
|
||||
if (IsColor(hwnd, 0xBADD3E, 671, 124, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 1st position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 153, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 2nd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 182, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 3rd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 211, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 4th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 240, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 5th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else {
|
||||
Sleep, 500
|
||||
}
|
||||
}
|
||||
|
||||
; ** REWARDS
|
||||
OutputDebug % "Clubman> Rewards: Waiting for Rewards screen to load (checking money earnt)"
|
||||
while (!IsColor(hwnd, 0xBE140F, 848, 192, 6, 100)) { ; money earn, the red text
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Rewards: Found Rewards screen"
|
||||
races_completed++
|
||||
|
||||
Loop 100 {
|
||||
if (IsColor(hwnd, 0x5C90FB, 451, 260, 10, 20)) { ; the 'R' in Clean Race Bonus
|
||||
OutputDebug % "Clubman> Rewards: Clean bonus"
|
||||
races_clean++
|
||||
PixelSearch(486, 311, 1, hwnd, "clean", "")
|
||||
break
|
||||
}
|
||||
|
||||
if (A_Index == 100) {
|
||||
OutputDebug % "Clubman> Rewards: No clean bonus"
|
||||
PixelSearch(486, 311, 1, hwnd, "no-clean", "")
|
||||
}
|
||||
}
|
||||
|
||||
; ** REPLAY
|
||||
OutputDebug % "Clubman> Replay: Waiting for Replay screen to load"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Pressing the Exit button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Leaving the Replay screen"
|
||||
|
||||
; ** RACE RESULTS
|
||||
OutputDebug % "Clubman> Race Result: Waiting for Race Result screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xBE1E1C, 651, 497, 4, 20)) { ; the exit button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Moving cursor to the Retry button"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_Right
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Pressing the Retry button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
; ** RACE START
|
||||
OutputDebug % "Clubman> Race Start: Waiting for Race Start screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Start: Pressing the Start button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
OutputDebug % "--- Summary ---"
|
||||
credits_total := (races_completed * 0.07 + races_clean * 0.035)
|
||||
races_clean_percent := (races_clean / races_completed) * 100
|
||||
time_current := A_TickCount
|
||||
credits_average := credits_total / (time_current - time_start) * 3600000
|
||||
|
||||
OutputDebug % "Clubman> Summary: Races " races_completed
|
||||
OutputDebug % "Clubman> Summary: Races Clean " races_clean
|
||||
OutputDebug % "Clubman> Summary: Races Clean Rate " races_clean_percent "%"
|
||||
OutputDebug % "Clubman> Summary: Earnings " credits_total "M"
|
||||
OutputDebug % "Clubman> Summary: Earnings Rate " credits_average "M/Hr"
|
||||
OutputDebug % "---------------"
|
||||
}
|
||||
return
|
||||
|
||||
Reset:
|
||||
Gosub, GrabWindow
|
||||
; PixelSearch(465, 519, 6, hwnd, "", "2")
|
||||
; OutputDebug % "Clubman> has grey " IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Health Check
|
||||
; -------------------
|
||||
Health:
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
OutputDebug % "Clubman> Health: Checking health at " current_date
|
||||
OutputDebug % "Clubman> Health: Races completed " races_completed
|
||||
OutputDebug % "Clubman> Health: Races completed last time " races_completed_check
|
||||
|
||||
if (races_completed_check >= races_completed) {
|
||||
OutputDebug % "Clubman> Health: Error dectected, sending notification"
|
||||
SendNotification("ClubmanPlus", "Something went wrong", 2, "persistent")
|
||||
} else {
|
||||
OutputDebug % "Clubman> Health: Running healthy"
|
||||
races_completed_check := races_completed
|
||||
}
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Summary Check
|
||||
; -------------------
|
||||
Summary:
|
||||
OutputDebug % "Clubman> Summary: Sending summary notification"
|
||||
message := ""
|
||||
message := message "Races " races_clean " / " races_completed " (" races_clean_percent ")`n"
|
||||
message := message "Earnings " credits_total "M (" credits_average "M/Hr)"
|
||||
SendNotification("ClubmanPlus", message, 0, "cashregister")
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Send Notification
|
||||
; -------------------
|
||||
SendNotification(title, message, level, sound) {
|
||||
|
||||
IniRead, token, %A_ScriptDir%\clubman.ini, pushover, token
|
||||
IniRead, user, %A_ScriptDir%\clubman.ini, pushover, user_key
|
||||
|
||||
retries := 60
|
||||
expires := 3600
|
||||
|
||||
url := "https://api.pushover.net/1/messages.json"
|
||||
param := "token=" token "&user=" user "&title=" title "&message=" message "&sound=" sound "&priority=" level
|
||||
|
||||
if (level == 2) {
|
||||
param := param "&retry=" retries "&expire=" expires
|
||||
}
|
||||
|
||||
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
WebRequest.Open("POST", url)
|
||||
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
WebRequest.Send(param)
|
||||
Return
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Grab Window
|
||||
; -------------------
|
||||
GrabWindow:
|
||||
OutputDebug % "Clubman> Looking for window"
|
||||
hwnd := WinExist("PS Remote Play")
|
||||
|
||||
if (hwnd > 0) {
|
||||
OutputDebug % "Clubman> Window found: " hwnd
|
||||
WinMove, ahk_id %hwnd%,, 0, 0, %window_width%, %window_height%
|
||||
WinActivate, ahk_id %hwnd%
|
||||
ControlFocus,, ahk_id %hwnd%
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Is Color
|
||||
; -------------------
|
||||
IsColor(hwnd, target_color, x, y, b, tolerance) {
|
||||
for i, c in PixelSearch(x, y, b, hwnd) {
|
||||
if (ColorDistance(c, target_color) <= tolerance) {
|
||||
Return True
|
||||
}
|
||||
}
|
||||
Return False
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Color Distance
|
||||
; -------------------
|
||||
ColorDistance( c1, c2 ) {
|
||||
r1 := c1 >> 16
|
||||
g1 := c1 >> 8 & 255
|
||||
b1 := c1 & 255
|
||||
r2 := c2 >> 16
|
||||
g2 := c2 >> 8 & 255
|
||||
b2 := c2 & 255
|
||||
return Sqrt( (r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2 )
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Pixel Search
|
||||
; -------------------
|
||||
PixelSearch(x, y, b, hwnd, debugsave := "", debugsavecropped := "") {
|
||||
; Find out client area
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hwnd, "ptr", &rect)
|
||||
client_width := NumGet(rect, 8, "int")
|
||||
client_height := NumGet(rect, 12, "int")
|
||||
|
||||
; Recalculate the area desired to the current system scaling; values were taken using 150% scale
|
||||
b := Floor((b * client_width) / 960)
|
||||
|
||||
; Convert x and y to currrent system; values were taken using 4K resolution
|
||||
x := Floor((A_ScreenWidth * x) / 3840)
|
||||
y := Floor((A_ScreenHeight * y) / 2160)
|
||||
|
||||
; Convert client to screen coordinates
|
||||
VarSetCapacity(POINT, 8)
|
||||
NumPut(x, &POINT, 0, "Int")
|
||||
NumPut(y, &POINT, 4, "Int")
|
||||
DllCall("user32\ClientToScreen", Ptr,hWnd, Ptr,&POINT)
|
||||
x := NumGet(&POINT, 0, "Int")
|
||||
y := NumGet(&POINT, 4, "Int")
|
||||
|
||||
WinGetPos,,, width, height, ahk_id %hwnd%
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
hbm := CreateDIBSection(width, height),
|
||||
hdc := CreateCompatibleDC(),
|
||||
obm := SelectObject(hdc, hbm)
|
||||
|
||||
RegExMatch(A_OsVersion, "\d+", version)
|
||||
PrintWindow(hwnd, hdc, version >= 8 ? 2 : 0)
|
||||
|
||||
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
SelectObject(hdc, obm),
|
||||
DeleteObject(hbm),
|
||||
DeleteDC(hdc)
|
||||
|
||||
pixs := []
|
||||
Loop % b*2 + 1 {
|
||||
i := (-1 * b) + (A_Index - 1)
|
||||
Loop % b*2 + 1 {
|
||||
j := (-1 * b) + (A_Index - 1)
|
||||
pixs.Push(Gdip_GetPixel(pBitmap, x+i, y+j) & 0x00FFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
|
||||
if (debugsave != "") {
|
||||
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . current_date . "-" . debugsave . ".bmp")
|
||||
; Run % filename
|
||||
}
|
||||
if (debugsavecropped != "") {
|
||||
debugbitmap:=Gdip_CloneBitmapArea(pBitmap, x-b, y-b, b*2, b*2)
|
||||
Gdip_SaveBitmapToFile(debugbitmap, A_ScriptDir . "\" . current_date . "-" . debugsavecropped . ".bmp")
|
||||
Gdip_DisposeImage(debugbitmap)
|
||||
; Run % filename
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Release All
|
||||
; -------------------
|
||||
Release_All:
|
||||
Gosub, Release_X
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press x
|
||||
; -------------------
|
||||
Press_X:
|
||||
Gosub, Hold_X
|
||||
Gosub, Release_x
|
||||
return
|
||||
|
||||
Hold_X:
|
||||
ControlSend,, {Enter down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_X:
|
||||
ControlSend,, {Enter up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press O
|
||||
; -------------------
|
||||
Press_O:
|
||||
Gosub, Hold_O
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
Hold_O:
|
||||
ControlSend,, {Esc down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_O:
|
||||
ControlSend,, {Esc up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Right
|
||||
; -------------------
|
||||
Press_Right:
|
||||
Gosub, Hold_Right
|
||||
Gosub, Release_Right
|
||||
return
|
||||
|
||||
Hold_Right:
|
||||
ControlSend,, {Right down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Right:
|
||||
ControlSend,, {Right up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Left
|
||||
; -------------------
|
||||
Press_Left:
|
||||
Gosub, Hold_Left
|
||||
Gosub, Release_Left
|
||||
return
|
||||
|
||||
Hold_Left:
|
||||
ControlSend,, {Left down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Left:
|
||||
ControlSend,, {Left up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Up
|
||||
; -------------------
|
||||
Press_Up:
|
||||
Gosub, Hold_Up
|
||||
Gosub, Release_Up
|
||||
return
|
||||
|
||||
Hold_Up:
|
||||
ControlSend,, {Up down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Up:
|
||||
ControlSend,, {Up up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Down
|
||||
; -------------------
|
||||
Press_Down:
|
||||
Gosub, Hold_Down
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
Hold_Down:
|
||||
ControlSend,, {Down down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Down:
|
||||
ControlSend,, {Down up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; Hotkeys
|
||||
^Esc::ExitApp
|
||||
@@ -0,0 +1,3 @@
|
||||
[pushover]
|
||||
user_key=your_key
|
||||
token=your_token
|
||||
@@ -0,0 +1,521 @@
|
||||
|
||||
; https://github.com/berban/Gdip
|
||||
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#NoEnv
|
||||
#Persistent
|
||||
#SingleInstance Force
|
||||
#Include Lib\Gdip.ahk
|
||||
|
||||
CoordMode, Pixel, Client
|
||||
CoordMode, ToolTip, Client
|
||||
DetectHiddenWindows, On
|
||||
ListLines Off
|
||||
Process, priority, , High
|
||||
SendMode Input
|
||||
SetBatchLines, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SetFormat, Float, 0.2
|
||||
; SetFormat, IntegerFast, Hex
|
||||
SetKeyDelay, 50
|
||||
SetMouseDelay, -1
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
|
||||
; Variables
|
||||
races_clean := 0
|
||||
races_clean_percent := 0
|
||||
races_completed := 0
|
||||
races_completed_check := 0
|
||||
credits_total := 0
|
||||
credits_average := 0
|
||||
|
||||
time_start := A_TickCount
|
||||
time_current := A_TickCount
|
||||
|
||||
window_width := 640
|
||||
window_height := 360
|
||||
|
||||
; GUI
|
||||
Gui, New, -MaximizeBox -Resize, ClubmanPlus 0.4
|
||||
Gui, Font, S10
|
||||
Gui, Add, Button, w150 h40 Default gStart, Start
|
||||
Gui, Add, Button, w150 h40 x+10 gReset, Reset
|
||||
Gui, Show
|
||||
return
|
||||
|
||||
; GUI events
|
||||
GuiClose:
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
OutputDebug % "Clubman> Terminated"
|
||||
ExitApp
|
||||
|
||||
; GUI buttons
|
||||
Start:
|
||||
hwnd := 0
|
||||
|
||||
Gosub, Release_All
|
||||
Gosub, GrabWindow
|
||||
|
||||
if (hwnd = 0) {
|
||||
MsgBox, % "PS Remote Play not found"
|
||||
return
|
||||
}
|
||||
|
||||
SetTimer, Health, 600000
|
||||
SetTimer, Summary, 3600000
|
||||
time_start := A_TickCount
|
||||
|
||||
; ** AFK Loop
|
||||
Gosub, Press_X
|
||||
|
||||
Loop {
|
||||
|
||||
; ** RACE
|
||||
OutputDebug % "Clubman> Race: Waiting for position GUI to show"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Starting race"
|
||||
Gosub, Hold_X
|
||||
; Gosub, Hold_Down
|
||||
OutputDebug % "Clubman> Race: Racing until position GUI disappears"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Race ended, releasing all buttons"
|
||||
Gosub, Release_All
|
||||
; Sleep, 5000
|
||||
|
||||
; ** GO TO LEADERBOARDS
|
||||
OutputDebug % "Clubman> End race: Waiting for continue X icon to show"
|
||||
while (!IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Press X to continue"
|
||||
while (IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Gosub, Press_X
|
||||
Sleep, 100
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Transitioning to leaderboard"
|
||||
|
||||
; ** LEADERBOARD
|
||||
Loop {
|
||||
OutputDebug % "Clubman> Leaderboard: Checking positions"
|
||||
|
||||
if (IsColor(hwnd, 0xBADD3E, 671, 124, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 1st position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 153, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 2nd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 182, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 3rd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 211, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 4th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 240, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 5th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else {
|
||||
Sleep, 500
|
||||
}
|
||||
}
|
||||
|
||||
; ** REWARDS
|
||||
OutputDebug % "Clubman> Rewards: Waiting for Rewards screen to load (checking money earnt)"
|
||||
while (!IsColor(hwnd, 0xBE140F, 848, 192, 6, 100)) { ; money earn, the red text
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Rewards: Found Rewards screen"
|
||||
races_completed++
|
||||
|
||||
Loop 100 {
|
||||
if (IsColor(hwnd, 0x5C90FB, 451, 260, 10, 20)) { ; the 'R' in Clean Race Bonus
|
||||
OutputDebug % "Clubman> Rewards: Clean bonus"
|
||||
races_clean++
|
||||
PixelSearch(486, 311, 1, hwnd, "clean", "")
|
||||
break
|
||||
}
|
||||
|
||||
if (A_Index == 100) {
|
||||
OutputDebug % "Clubman> Rewards: No clean bonus"
|
||||
PixelSearch(486, 311, 1, hwnd, "no-clean", "")
|
||||
}
|
||||
}
|
||||
|
||||
; ** REPLAY
|
||||
OutputDebug % "Clubman> Replay: Waiting for Replay screen to load"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Pressing the Exit button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Leaving the Replay screen"
|
||||
|
||||
; ** RACE RESULTS
|
||||
OutputDebug % "Clubman> Race Result: Waiting for Race Result screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xBE1E1C, 651, 497, 4, 20)) { ; the exit button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Moving cursor to the Retry button"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_Right
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Pressing the Retry button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
; ** RACE START
|
||||
OutputDebug % "Clubman> Race Start: Waiting for Race Start screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Start: Pressing the Start button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
OutputDebug % "--- Summary ---"
|
||||
credits_total := (races_completed * 0.07 + races_clean * 0.035)
|
||||
races_clean_percent := (races_clean / races_completed) * 100
|
||||
time_current := A_TickCount
|
||||
credits_average := credits_total / (time_current - time_start) * 3600000
|
||||
|
||||
OutputDebug % "Clubman> Summary: Races " races_completed
|
||||
OutputDebug % "Clubman> Summary: Races Clean " races_clean
|
||||
OutputDebug % "Clubman> Summary: Races Clean Rate " races_clean_percent "%"
|
||||
OutputDebug % "Clubman> Summary: Earnings " credits_total "M"
|
||||
OutputDebug % "Clubman> Summary: Earnings Rate " credits_average "M/Hr"
|
||||
OutputDebug % "---------------"
|
||||
}
|
||||
return
|
||||
|
||||
Reset:
|
||||
Gosub, GrabWindow
|
||||
; PixelSearch(465, 519, 6, hwnd, "", "2")
|
||||
; OutputDebug % "Clubman> has grey " IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)
|
||||
|
||||
; 960 / 296
|
||||
; 540 / 134
|
||||
; PixelSearch(3.243243, 4.029851, 20, hwnd, "", "test")
|
||||
|
||||
; pToken := Gdip_Startup()
|
||||
; pBitmap := Gdip_BitmapFromScreen("hwnd:" hwnd)
|
||||
; Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\bolas.bmp")
|
||||
; Gdip_DisposeImage(pBitmap)
|
||||
; Gdip_Shutdown(pToken)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Health Check
|
||||
; -------------------
|
||||
Health:
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
OutputDebug % "Clubman> Health: Checking health at " current_date
|
||||
OutputDebug % "Clubman> Health: Races completed " races_completed
|
||||
OutputDebug % "Clubman> Health: Races completed last time " races_completed_check
|
||||
|
||||
if (races_completed_check >= races_completed) {
|
||||
OutputDebug % "Clubman> Health: Error dectected, sending notification"
|
||||
SendNotification("ClubmanPlus", "Something went wrong", 2, "persistent")
|
||||
} else {
|
||||
OutputDebug % "Clubman> Health: Running healthy"
|
||||
races_completed_check := races_completed
|
||||
}
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Summary Check
|
||||
; -------------------
|
||||
Summary:
|
||||
OutputDebug % "Clubman> Summary: Sending summary notification"
|
||||
message := ""
|
||||
message := message "Races " races_clean " / " races_completed " (" races_clean_percent ")`n"
|
||||
message := message "Earnings " credits_total "M (" credits_average "M/Hr)"
|
||||
SendNotification("ClubmanPlus", message, 0, "cashregister")
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Send Notification
|
||||
; -------------------
|
||||
SendNotification(title, message, level, sound) {
|
||||
|
||||
IniRead, token, %A_ScriptDir%\clubman.ini, pushover, token
|
||||
IniRead, user, %A_ScriptDir%\clubman.ini, pushover, user_key
|
||||
|
||||
retries := 60
|
||||
expires := 3600
|
||||
|
||||
url := "https://api.pushover.net/1/messages.json"
|
||||
param := "token=" token "&user=" user "&title=" title "&message=" message "&sound=" sound "&priority=" level
|
||||
|
||||
if (level == 2) {
|
||||
param := param "&retry=" retries "&expire=" expires
|
||||
}
|
||||
|
||||
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
WebRequest.Open("POST", url)
|
||||
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
WebRequest.Send(param)
|
||||
Return
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Grab Window
|
||||
; -------------------
|
||||
GrabWindow:
|
||||
OutputDebug % "Clubman> Looking for window"
|
||||
hwnd := WinExist("PS Remote Play")
|
||||
|
||||
if (hwnd > 0) {
|
||||
OutputDebug % "Clubman> Window found: " hwnd
|
||||
WinMove, ahk_id %hwnd%,, 0, 0, %window_width%, %window_height%
|
||||
WinActivate, ahk_id %hwnd%
|
||||
ControlFocus,, ahk_id %hwnd%
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Is Color
|
||||
; -------------------
|
||||
IsColor(hwnd, target_color, x, y, b, tolerance) {
|
||||
for i, c in PixelSearch(x, y, b, hwnd) {
|
||||
if (ColorDistance(c, target_color) <= tolerance) {
|
||||
Return True
|
||||
}
|
||||
}
|
||||
Return False
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Color Distance
|
||||
; -------------------
|
||||
ColorDistance( c1, c2 ) {
|
||||
r1 := c1 >> 16
|
||||
g1 := c1 >> 8 & 255
|
||||
b1 := c1 & 255
|
||||
r2 := c2 >> 16
|
||||
g2 := c2 >> 8 & 255
|
||||
b2 := c2 & 255
|
||||
return Sqrt( (r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2 )
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Pixel Search
|
||||
; -------------------
|
||||
PixelSearch(x, y, b, hwnd, debugsave := "", debugsavecropped := "") {
|
||||
; ; Find out client area
|
||||
; VarSetCapacity(rect, 16)
|
||||
; DllCall("GetClientRect", "ptr", hwnd, "ptr", &rect)
|
||||
; client_width := NumGet(rect, 8, "int")
|
||||
; client_height := NumGet(rect, 12, "int")
|
||||
|
||||
; ; Recalculate the area desired to the current system scaling; values were taken using 150% scale
|
||||
; b := Floor((b * client_width) / 960)
|
||||
|
||||
; ; Convert x and y to currrent system; values were taken using 4K resolution
|
||||
; x := Floor((A_ScreenWidth * x) / 3840)
|
||||
; y := Floor((A_ScreenHeight * y) / 2160)
|
||||
|
||||
; ; Convert client to screen coordinates
|
||||
; VarSetCapacity(POINT, 8)
|
||||
; NumPut(x, &POINT, 0, "Int")
|
||||
; NumPut(y, &POINT, 4, "Int")
|
||||
; DllCall("user32\ClientToScreen", Ptr,hWnd, Ptr,&POINT)
|
||||
; x := NumGet(&POINT, 0, "Int")
|
||||
; y := NumGet(&POINT, 4, "Int")
|
||||
|
||||
x := (960 / x)
|
||||
y := (540 / y)
|
||||
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hwnd, "ptr", &rect)
|
||||
x := floor(NumGet(rect, 8, "int") // x)
|
||||
y := floor(NumGet(rect, 12, "int") // y)
|
||||
b := floor((b * NumGet(rect, 8, "int")) / 960)
|
||||
|
||||
VarSetCapacity(POINT, 8)
|
||||
NumPut(x, &POINT, 0, "Int")
|
||||
NumPut(y, &POINT, 4, "Int")
|
||||
DllCall("user32\ClientToScreen", Ptr, hwnd, Ptr,&POINT)
|
||||
x := NumGet(&POINT, 0, "Int")
|
||||
y := NumGet(&POINT, 4, "Int")
|
||||
|
||||
; OutputDebug % "Clubman> Reading screen at " x "x" y
|
||||
|
||||
; WinGetPos,,, width, height, ahk_id %hwnd%
|
||||
|
||||
; pToken := Gdip_Startup()
|
||||
; hbm := CreateDIBSection(width, height),
|
||||
; hdc := CreateCompatibleDC(),
|
||||
; obm := SelectObject(hdc, hbm)
|
||||
|
||||
; RegExMatch(A_OsVersion, "\d+", version)
|
||||
; PrintWindow(hwnd, hdc, version >= 8 ? 2 : 0)
|
||||
|
||||
; pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
; SelectObject(hdc, obm),
|
||||
; DeleteObject(hbm),
|
||||
; DeleteDC(hdc)
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromScreen("hwnd:" hwnd)
|
||||
|
||||
pixs := []
|
||||
Loop % b*2 + 1 {
|
||||
i := (-1 * b) + (A_Index - 1)
|
||||
Loop % b*2 + 1 {
|
||||
j := (-1 * b) + (A_Index - 1)
|
||||
pixs.Push(Gdip_GetPixel(pBitmap, x+i, y+j) & 0x00FFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
|
||||
if (debugsave != "") {
|
||||
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . current_date . "-" . debugsave . ".bmp")
|
||||
; Run % filename
|
||||
}
|
||||
if (debugsavecropped != "") {
|
||||
debugbitmap:=Gdip_CloneBitmapArea(pBitmap, x-b, y-b, b*2, b*2)
|
||||
Gdip_SaveBitmapToFile(debugbitmap, A_ScriptDir . "\" . current_date . "-" . debugsavecropped . ".bmp")
|
||||
Gdip_DisposeImage(debugbitmap)
|
||||
; Run % filename
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Release All
|
||||
; -------------------
|
||||
Release_All:
|
||||
Gosub, Release_X
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press x
|
||||
; -------------------
|
||||
Press_X:
|
||||
Gosub, Hold_X
|
||||
Gosub, Release_x
|
||||
return
|
||||
|
||||
Hold_X:
|
||||
ControlSend,, {Enter down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_X:
|
||||
ControlSend,, {Enter up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press O
|
||||
; -------------------
|
||||
Press_O:
|
||||
Gosub, Hold_O
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
Hold_O:
|
||||
ControlSend,, {Esc down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_O:
|
||||
ControlSend,, {Esc up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Right
|
||||
; -------------------
|
||||
Press_Right:
|
||||
Gosub, Hold_Right
|
||||
Gosub, Release_Right
|
||||
return
|
||||
|
||||
Hold_Right:
|
||||
ControlSend,, {Right down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Right:
|
||||
ControlSend,, {Right up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Left
|
||||
; -------------------
|
||||
Press_Left:
|
||||
Gosub, Hold_Left
|
||||
Gosub, Release_Left
|
||||
return
|
||||
|
||||
Hold_Left:
|
||||
ControlSend,, {Left down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Left:
|
||||
ControlSend,, {Left up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Up
|
||||
; -------------------
|
||||
Press_Up:
|
||||
Gosub, Hold_Up
|
||||
Gosub, Release_Up
|
||||
return
|
||||
|
||||
Hold_Up:
|
||||
ControlSend,, {Up down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Up:
|
||||
ControlSend,, {Up up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Down
|
||||
; -------------------
|
||||
Press_Down:
|
||||
Gosub, Hold_Down
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
Hold_Down:
|
||||
ControlSend,, {Down down}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
Release_Down:
|
||||
ControlSend,, {Down up}, ahk_id %hwnd%
|
||||
return
|
||||
|
||||
; Hotkeys
|
||||
^Esc::ExitApp
|
||||
@@ -0,0 +1,3 @@
|
||||
[pushover]
|
||||
user_key=your_key
|
||||
token=your_token
|
||||
@@ -0,0 +1,211 @@
|
||||
#include %A_LineFile%\..\CLR.ahk
|
||||
|
||||
; Static class, holds ViGEm Client instance
|
||||
class ViGEmWrapper {
|
||||
static asm := 0
|
||||
static client := 0
|
||||
|
||||
Init(){
|
||||
if (this.client == 0){
|
||||
this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
}
|
||||
}
|
||||
|
||||
CreateInstance(cls){
|
||||
return this.asm.CreateInstance(cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
; Base class for ViGEm "Targets" (Controller types - eg xb360 / ds4) to inherit from
|
||||
class ViGEmTarget {
|
||||
target := 0
|
||||
helperClass := ""
|
||||
controllerClass := ""
|
||||
|
||||
__New(){
|
||||
;~ this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
ViGEmWrapper.Init()
|
||||
this.Instance := ViGEmWrapper.CreateInstance(this.helperClass)
|
||||
|
||||
if (this.Instance.OkCheck() != "OK"){
|
||||
msgbox ViGEmWrapper.dll failed to load!
|
||||
ExitApp
|
||||
}
|
||||
}
|
||||
|
||||
SendReport(){
|
||||
this.Instance.SendReport()
|
||||
}
|
||||
|
||||
SubscribeFeedback(callback){
|
||||
this.Instance.SubscribeFeedback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
; DS4 (DualShock 4 for Playstation 4)
|
||||
class ViGEmDS4 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Ds4"
|
||||
__New(){
|
||||
static buttons := {Square: 16, Cross: 32, Circle: 64, Triangle: 128, L1: 256, R1: 512, L2: 1024, R2: 2048
|
||||
, Share: 4096, Options: 8192, LS: 16384, RS: 32768 }
|
||||
static specialButtons := {Ps: 1, TouchPad: 2}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
for name, id in specialButtons {
|
||||
this.Buttons[name] := new this._SpecialButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _SpecialButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetSpecialButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
return round(state * 2.55)
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dPadDirections := {Up: 0, UpRight: 1, Right: 2, DownRight: 3, Down: 4, DownLeft: 5, Left: 6, UpLeft: 7, None: 8}
|
||||
this._Parent.Instance.SetDpadState(dPadDirections[state])
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Xb360
|
||||
class ViGEmXb360 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Xb360"
|
||||
__New(){
|
||||
static buttons := {A: 4096, B: 8192, X: 16384, Y: 32768, LB: 256, RB: 512, LS: 64, RS: 128, Back: 32, Start: 16, Xbox: 1024}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
value := round((state * 655.36) - 32768)
|
||||
if (value == 32768)
|
||||
return 32767
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
_DpadStates := {1:0, 8:0, 2:0, 4:0} ; Up, Right, Down, Left
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dpadDirections := { None: {1:0, 8:0, 2:0, 4:0}
|
||||
, Up: {1:1, 8:0, 2:0, 4:0}
|
||||
, UpRight: {1:1, 8:1, 2:0, 4:0}
|
||||
, Right: {1:0, 8:1, 2:0, 4:0}
|
||||
, DownRight: {1:0, 8:1, 2:1, 4:0}
|
||||
, Down: {1:0, 8:0, 2:1, 4:0}
|
||||
, DownLeft: {1:0, 8:0, 2:1, 4:1}
|
||||
, Left: {1:0, 8:0, 2:0, 4:1}
|
||||
, UpLeft: {1:1, 8:0, 2:0, 4:1}}
|
||||
newStates := dpadDirections[state]
|
||||
for id, newState in newStates {
|
||||
oldState := this._DpadStates[id]
|
||||
if (oldState != newState){
|
||||
this._DpadStates[id] := newState
|
||||
this._Parent.Instance.SetButtonState(id, newState)
|
||||
}
|
||||
this._Parent.SendReport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
; ==========================================================
|
||||
; .NET Framework Interop
|
||||
; https://autohotkey.com/boards/viewtopic.php?t=4633
|
||||
; ==========================================================
|
||||
;
|
||||
; Author: Lexikos
|
||||
; Version: 1.2
|
||||
; Requires: AutoHotkey_L v1.0.96+
|
||||
;
|
||||
|
||||
CLR_LoadLibrary(AssemblyName, AppDomain=0)
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
e := ComObjError(0)
|
||||
Loop 1 {
|
||||
if assembly := AppDomain.Load_2(AssemblyName)
|
||||
break
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 1), args[0] := AssemblyName
|
||||
typeofAssembly := AppDomain.GetType().Assembly.GetType()
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, null, null, args)
|
||||
break
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)
|
||||
break
|
||||
}
|
||||
ComObjError(e)
|
||||
return assembly
|
||||
}
|
||||
|
||||
CLR_CreateObject(Assembly, TypeName, Args*)
|
||||
{
|
||||
if !(argCount := Args.MaxIndex())
|
||||
return Assembly.CreateInstance_2(TypeName, true)
|
||||
|
||||
vargs := ComObjArray(0xC, argCount)
|
||||
Loop % argCount
|
||||
vargs[A_Index-1] := Args[A_Index]
|
||||
|
||||
static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0)
|
||||
|
||||
return Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
|
||||
}
|
||||
|
||||
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
|
||||
{
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
|
||||
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, null, null, args)
|
||||
return A_LastError >= 0
|
||||
}
|
||||
|
||||
CLR_StopDomain(ByRef AppDomain)
|
||||
{ ; ICorRuntimeHost::UnloadDomain
|
||||
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
|
||||
CLR_Start(Version="") ; returns ICorRuntimeHost*
|
||||
{
|
||||
static RtHst := 0
|
||||
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
|
||||
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
|
||||
if RtHst
|
||||
return RtHst
|
||||
EnvGet SystemRoot, SystemRoot
|
||||
if Version =
|
||||
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
|
||||
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
|
||||
Version := A_LoopFileName
|
||||
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
|
||||
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr*", RtHst) >= 0
|
||||
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
|
||||
return RtHst
|
||||
}
|
||||
|
||||
;
|
||||
; INTERNAL FUNCTIONS
|
||||
;
|
||||
|
||||
CLR_GetDefaultDomain()
|
||||
{
|
||||
static defaultDomain := 0
|
||||
if !defaultDomain
|
||||
{ ; ICorRuntimeHost::GetDefaultDomain
|
||||
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
|
||||
defaultDomain := ComObject(p), ObjRelease(p)
|
||||
}
|
||||
return defaultDomain
|
||||
}
|
||||
|
||||
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
|
||||
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|
||||
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|
||||
|| !(codeCompiler := codeProvider.CreateCompiler())
|
||||
return 0
|
||||
|
||||
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
|
||||
return 0
|
||||
|
||||
; Convert | delimited list of references into an array.
|
||||
StringSplit, Refs, References, |, %A_Space%%A_Tab%
|
||||
aRefs := ComObjArray(8, Refs0)
|
||||
Loop % Refs0
|
||||
aRefs[A_Index-1] := Refs%A_Index%
|
||||
|
||||
; Set parameters for compiler.
|
||||
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
|
||||
, prms.OutputAssembly := FileName
|
||||
, prms.GenerateInMemory := FileName=""
|
||||
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
|
||||
, prms.CompilerOptions := CompilerOptions
|
||||
, prms.IncludeDebugInformation := true
|
||||
|
||||
; Compile!
|
||||
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
|
||||
|
||||
if error_count := (errors := compilerRes.Errors).Count
|
||||
{
|
||||
error_text := ""
|
||||
Loop % error_count
|
||||
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
|
||||
MsgBox, 16, Compilation Failed, %error_text%
|
||||
return 0
|
||||
}
|
||||
; Success. Return Assembly object or path.
|
||||
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
|
||||
}
|
||||
|
||||
CLR_GUID(ByRef GUID, sGUID)
|
||||
{
|
||||
VarSetCapacity(GUID, 16, 0)
|
||||
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
|
||||
; https://github.com/berban/Gdip
|
||||
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#NoEnv
|
||||
#Persistent
|
||||
#SingleInstance Force
|
||||
#Include Lib\Gdip.ahk
|
||||
#Include Lib\AHK-ViGEm-Bus.ahk
|
||||
|
||||
CoordMode, Pixel, Client
|
||||
CoordMode, ToolTip, Client
|
||||
DetectHiddenWindows, On
|
||||
ListLines Off
|
||||
Process, priority, , High
|
||||
SendMode Input
|
||||
SetBatchLines, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SetFormat, Float, 0.2
|
||||
; SetFormat, IntegerFast, Hex
|
||||
SetKeyDelay, 50
|
||||
SetMouseDelay, -1
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
|
||||
; Variables
|
||||
races_clean := 0
|
||||
races_clean_percent := 0
|
||||
races_completed := 0
|
||||
races_completed_check := 0
|
||||
credits_total := 0
|
||||
credits_average := 0
|
||||
|
||||
time_start := A_TickCount
|
||||
time_current := A_TickCount
|
||||
|
||||
window_width := 640
|
||||
window_height := 360
|
||||
|
||||
; Create a new controller controller
|
||||
controller := new ViGEmDS4()
|
||||
|
||||
; GUI
|
||||
Gui, New, -MaximizeBox -Resize, ClubmanPlus 0.5.1
|
||||
Gui, Font, S10
|
||||
Gui, Add, Text, w300 vStatRace, Race Counts: %races_completed%
|
||||
Gui, Add, Text, y+0 w300 vCleanRace, Clean Races: %races_clean%
|
||||
Gui, Add, Text, y+0 w300 vCleanRate, Average Clean Runs: %races_clean_percent%`%
|
||||
Gui, Add, Text, y+0 w300 vEarnings, Earnings: %credits_total%M
|
||||
Gui, Add, Text, y+0 w300 vEarningsRate, Earnings Rate: %credits_average%M/hr
|
||||
Gui, Add, Button, w150 h40 Default gStart, Start
|
||||
Gui, Add, Button, w150 h40 x+10 gReset, Reset
|
||||
Gui, Show
|
||||
return
|
||||
|
||||
; GUI events
|
||||
GuiClose:
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
OutputDebug % "Clubman> Terminated"
|
||||
ExitApp
|
||||
|
||||
; GUI controls
|
||||
Stats:
|
||||
format_avg_clean_race := Format("{1:0.2f}", races_clean_percent)
|
||||
format_earnings := Format("{1:0.2f}", credits_total)
|
||||
format_earnings_rate := Format("{1:0.2f}", credits_average)
|
||||
|
||||
GuiControl,,StatRace, Race Counts: %races_completed%
|
||||
GuiControl,,CleanRace, Clean Races: %races_clean%
|
||||
GuiControl,,CleanRate, Average Clean Runs: %format_avg_clean_race%`%
|
||||
GuiControl,,Earnings, Earnings: %format_earnings%M
|
||||
GuiControl,,EarningsRate, Earnings Rate: %format_earnings_rate%M/hr
|
||||
Return
|
||||
|
||||
Start:
|
||||
hwnd := 0
|
||||
|
||||
Gosub, Release_All
|
||||
Gosub, GrabWindow
|
||||
|
||||
if (hwnd = 0) {
|
||||
MsgBox, % "PS Remote Play not found"
|
||||
return
|
||||
}
|
||||
|
||||
SetTimer, Health, 600000
|
||||
SetTimer, Summary, 3600000
|
||||
time_start := A_TickCount
|
||||
|
||||
; ** AFK Loop
|
||||
Gosub, Press_X
|
||||
|
||||
Loop {
|
||||
|
||||
; ** RACE
|
||||
OutputDebug % "Clubman> Race: Waiting for position GUI to show"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Starting race"
|
||||
Gosub, Hold_X
|
||||
; Gosub, Hold_Down
|
||||
OutputDebug % "Clubman> Race: Racing until position GUI disappears"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Race ended, releasing all buttons"
|
||||
Gosub, Release_All
|
||||
; Sleep, 5000
|
||||
|
||||
; ** GO TO LEADERBOARDS
|
||||
OutputDebug % "Clubman> End race: Waiting for continue X icon to show"
|
||||
while (!IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Press X to continue"
|
||||
while (IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Gosub, Press_X
|
||||
Sleep, 100
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Transitioning to leaderboard"
|
||||
|
||||
; ** LEADERBOARD
|
||||
Loop {
|
||||
OutputDebug % "Clubman> Leaderboard: Checking positions"
|
||||
|
||||
if (IsColor(hwnd, 0xBADD3E, 671, 124, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 1st position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 153, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 2nd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 182, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 3rd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 211, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 4th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 240, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 5th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else {
|
||||
Sleep, 500
|
||||
}
|
||||
}
|
||||
|
||||
; ** REWARDS
|
||||
OutputDebug % "Clubman> Rewards: Waiting for Rewards screen to load (checking money earnt)"
|
||||
while (!IsColor(hwnd, 0xBE140F, 848, 192, 6, 100)) { ; money earn, the red text
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Rewards: Found Rewards screen"
|
||||
races_completed++
|
||||
|
||||
Loop 100 {
|
||||
if (IsColor(hwnd, 0x5C90FB, 451, 260, 10, 20)) { ; the 'R' in Clean Race Bonus
|
||||
OutputDebug % "Clubman> Rewards: Clean bonus"
|
||||
races_clean++
|
||||
PixelSearch(486, 311, 1, hwnd, "clean", "")
|
||||
break
|
||||
}
|
||||
|
||||
if (A_Index == 100) {
|
||||
OutputDebug % "Clubman> Rewards: No clean bonus"
|
||||
PixelSearch(486, 311, 1, hwnd, "no-clean", "")
|
||||
}
|
||||
}
|
||||
|
||||
; ** REPLAY
|
||||
OutputDebug % "Clubman> Replay: Waiting for Replay screen to load"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Pressing the Exit button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Leaving the Replay screen"
|
||||
|
||||
; ** RACE RESULTS
|
||||
OutputDebug % "Clubman> Race Result: Waiting for Race Result screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xBE1E1C, 651, 497, 4, 20)) { ; the exit button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Moving cursor to the Retry button"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_Right
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Pressing the Retry button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
; ** RACE START
|
||||
OutputDebug % "Clubman> Race Start: Waiting for Race Start screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Start: Pressing the Start button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
OutputDebug % "--- Summary ---"
|
||||
credits_total := (races_completed * 0.07 + races_clean * 0.035)
|
||||
races_clean_percent := (races_clean / races_completed) * 100
|
||||
time_current := A_TickCount
|
||||
credits_average := credits_total / (time_current - time_start) * 3600000
|
||||
|
||||
Gosub, Stats
|
||||
|
||||
OutputDebug % "Clubman> Summary: Races " races_completed
|
||||
OutputDebug % "Clubman> Summary: Races Clean " races_clean
|
||||
OutputDebug % "Clubman> Summary: Races Clean Rate " races_clean_percent "%"
|
||||
OutputDebug % "Clubman> Summary: Earnings " credits_total "M"
|
||||
OutputDebug % "Clubman> Summary: Earnings Rate " credits_average "M/Hr"
|
||||
OutputDebug % "---------------"
|
||||
}
|
||||
return
|
||||
|
||||
Reset:
|
||||
OutputDebug % "Clubman> Reloading"
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
Reload
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Health Check
|
||||
; -------------------
|
||||
Health:
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
OutputDebug % "Clubman> Health: Checking health at " current_date
|
||||
OutputDebug % "Clubman> Health: Races completed " races_completed
|
||||
OutputDebug % "Clubman> Health: Races completed last time " races_completed_check
|
||||
|
||||
if (races_completed_check >= races_completed) {
|
||||
OutputDebug % "Clubman> Health: Error dectected, sending notification"
|
||||
SendNotification("ClubmanPlus", "Something went wrong", 2, "persistent")
|
||||
} else {
|
||||
OutputDebug % "Clubman> Health: Running healthy"
|
||||
races_completed_check := races_completed
|
||||
}
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Summary Check
|
||||
; -------------------
|
||||
Summary:
|
||||
OutputDebug % "Clubman> Summary: Sending summary notification"
|
||||
message := ""
|
||||
message := message "Races " races_clean " / " races_completed " (" races_clean_percent ")`n"
|
||||
message := message "Earnings " credits_total "M (" credits_average "M/Hr)"
|
||||
SendNotification("ClubmanPlus", message, 0, "cashregister")
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Send Notification
|
||||
; -------------------
|
||||
SendNotification(title, message, level, sound) {
|
||||
|
||||
IniRead, token, %A_ScriptDir%\clubman.ini, pushover, token
|
||||
IniRead, user, %A_ScriptDir%\clubman.ini, pushover, user_key
|
||||
|
||||
retries := 60
|
||||
expires := 3600
|
||||
|
||||
url := "https://api.pushover.net/1/messages.json"
|
||||
param := "token=" token "&user=" user "&title=" title "&message=" message "&sound=" sound "&priority=" level
|
||||
|
||||
if (level == 2) {
|
||||
param := param "&retry=" retries "&expire=" expires
|
||||
}
|
||||
|
||||
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
WebRequest.Open("POST", url)
|
||||
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
WebRequest.Send(param)
|
||||
Return
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Grab Window
|
||||
; -------------------
|
||||
GrabWindow:
|
||||
OutputDebug % "Clubman> Looking for window"
|
||||
hwnd := WinExist("PS Remote Play")
|
||||
|
||||
if (hwnd > 0) {
|
||||
OutputDebug % "Clubman> Window found: " hwnd
|
||||
WinMove, ahk_id %hwnd%,, 0, 0, %window_width%, %window_height%
|
||||
WinActivate, ahk_id %hwnd%
|
||||
ControlFocus,, ahk_id %hwnd%
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Is Color
|
||||
; -------------------
|
||||
IsColor(hwnd, target_color, x, y, b, tolerance) {
|
||||
for i, c in PixelSearch(x, y, b, hwnd) {
|
||||
if (ColorDistance(c, target_color) <= tolerance) {
|
||||
Return True
|
||||
}
|
||||
}
|
||||
Return False
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Color Distance
|
||||
; -------------------
|
||||
ColorDistance( c1, c2 ) {
|
||||
r1 := c1 >> 16
|
||||
g1 := c1 >> 8 & 255
|
||||
b1 := c1 & 255
|
||||
r2 := c2 >> 16
|
||||
g2 := c2 >> 8 & 255
|
||||
b2 := c2 & 255
|
||||
return Sqrt( (r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2 )
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Pixel Search
|
||||
; -------------------
|
||||
PixelSearch(x, y, b, hwnd, debugsave := "", debugsavecropped := "") {
|
||||
x := (960 / x)
|
||||
y := (540 / y)
|
||||
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hwnd, "ptr", &rect)
|
||||
x := floor(NumGet(rect, 8, "int") // x)
|
||||
y := floor(NumGet(rect, 12, "int") // y)
|
||||
b := floor((b * NumGet(rect, 8, "int")) / 960)
|
||||
|
||||
VarSetCapacity(POINT, 8)
|
||||
NumPut(x, &POINT, 0, "Int")
|
||||
NumPut(y, &POINT, 4, "Int")
|
||||
DllCall("user32\ClientToScreen", Ptr, hwnd, Ptr,&POINT)
|
||||
x := NumGet(&POINT, 0, "Int")
|
||||
y := NumGet(&POINT, 4, "Int")
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromScreen("hwnd:" hwnd)
|
||||
|
||||
pixs := []
|
||||
Loop % b*2 + 1 {
|
||||
i := (-1 * b) + (A_Index - 1)
|
||||
Loop % b*2 + 1 {
|
||||
j := (-1 * b) + (A_Index - 1)
|
||||
pixs.Push(Gdip_GetPixel(pBitmap, x+i, y+j) & 0x00FFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
|
||||
if (debugsave != "") {
|
||||
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . current_date . "-" . debugsave . ".bmp")
|
||||
}
|
||||
if (debugsavecropped != "") {
|
||||
debugbitmap:=Gdip_CloneBitmapArea(pBitmap, x-b, y-b, b*2, b*2)
|
||||
Gdip_SaveBitmapToFile(debugbitmap, A_ScriptDir . "\" . current_date . "-" . debugsavecropped . ".bmp")
|
||||
Gdip_DisposeImage(debugbitmap)
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Release All
|
||||
; -------------------
|
||||
Release_All:
|
||||
Gosub, Release_X
|
||||
Gosub, Release_O
|
||||
Gosub, Release_Right
|
||||
Gosub, Release_Left
|
||||
Gosub, Release_Up
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press x
|
||||
; -------------------
|
||||
Press_X:
|
||||
Gosub, Hold_X
|
||||
Sleep, 50
|
||||
Gosub, Release_x
|
||||
return
|
||||
|
||||
Hold_X:
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
return
|
||||
|
||||
Release_X:
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press O
|
||||
; -------------------
|
||||
Press_O:
|
||||
Gosub, Hold_O
|
||||
Sleep, 50
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
Hold_O:
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
return
|
||||
|
||||
Release_O:
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Right
|
||||
; -------------------
|
||||
Press_Right:
|
||||
Gosub, Hold_Right
|
||||
Sleep, 50
|
||||
Gosub, Release_Right
|
||||
return
|
||||
|
||||
Hold_Right:
|
||||
controller.Dpad.SetState("Right")
|
||||
return
|
||||
|
||||
Release_Right:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Left
|
||||
; -------------------
|
||||
Press_Left:
|
||||
Gosub, Hold_Left
|
||||
Sleep, 50
|
||||
Gosub, Release_Left
|
||||
return
|
||||
|
||||
Hold_Left:
|
||||
controller.Dpad.SetState("Left")
|
||||
return
|
||||
|
||||
Release_Left:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Up
|
||||
; -------------------
|
||||
Press_Up:
|
||||
Gosub, Hold_Up
|
||||
Sleep, 50
|
||||
Gosub, Release_Up
|
||||
return
|
||||
|
||||
Hold_Up:
|
||||
controller.Dpad.SetState("Up")
|
||||
return
|
||||
|
||||
Release_Up:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Down
|
||||
; -------------------
|
||||
Press_Down:
|
||||
Gosub, Hold_Down
|
||||
Sleep, 50
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
Hold_Down:
|
||||
controller.Dpad.SetState("Down")
|
||||
return
|
||||
|
||||
Release_Down:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; Hotkeys
|
||||
^Esc::ExitApp
|
||||
@@ -0,0 +1,3 @@
|
||||
[pushover]
|
||||
user_key=your_key
|
||||
token=your_token
|
||||
@@ -0,0 +1,211 @@
|
||||
#include %A_LineFile%\..\CLR.ahk
|
||||
|
||||
; Static class, holds ViGEm Client instance
|
||||
class ViGEmWrapper {
|
||||
static asm := 0
|
||||
static client := 0
|
||||
|
||||
Init(){
|
||||
if (this.client == 0){
|
||||
this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
}
|
||||
}
|
||||
|
||||
CreateInstance(cls){
|
||||
return this.asm.CreateInstance(cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
; Base class for ViGEm "Targets" (Controller types - eg xb360 / ds4) to inherit from
|
||||
class ViGEmTarget {
|
||||
target := 0
|
||||
helperClass := ""
|
||||
controllerClass := ""
|
||||
|
||||
__New(){
|
||||
;~ this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
ViGEmWrapper.Init()
|
||||
this.Instance := ViGEmWrapper.CreateInstance(this.helperClass)
|
||||
|
||||
if (this.Instance.OkCheck() != "OK"){
|
||||
msgbox ViGEmWrapper.dll failed to load!
|
||||
ExitApp
|
||||
}
|
||||
}
|
||||
|
||||
SendReport(){
|
||||
this.Instance.SendReport()
|
||||
}
|
||||
|
||||
SubscribeFeedback(callback){
|
||||
this.Instance.SubscribeFeedback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
; DS4 (DualShock 4 for Playstation 4)
|
||||
class ViGEmDS4 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Ds4"
|
||||
__New(){
|
||||
static buttons := {Square: 16, Cross: 32, Circle: 64, Triangle: 128, L1: 256, R1: 512, L2: 1024, R2: 2048
|
||||
, Share: 4096, Options: 8192, LS: 16384, RS: 32768 }
|
||||
static specialButtons := {Ps: 1, TouchPad: 2}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
for name, id in specialButtons {
|
||||
this.Buttons[name] := new this._SpecialButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _SpecialButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetSpecialButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
return round(state * 2.55)
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dPadDirections := {Up: 0, UpRight: 1, Right: 2, DownRight: 3, Down: 4, DownLeft: 5, Left: 6, UpLeft: 7, None: 8}
|
||||
this._Parent.Instance.SetDpadState(dPadDirections[state])
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Xb360
|
||||
class ViGEmXb360 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Xb360"
|
||||
__New(){
|
||||
static buttons := {A: 4096, B: 8192, X: 16384, Y: 32768, LB: 256, RB: 512, LS: 64, RS: 128, Back: 32, Start: 16, Xbox: 1024}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
value := round((state * 655.36) - 32768)
|
||||
if (value == 32768)
|
||||
return 32767
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
_DpadStates := {1:0, 8:0, 2:0, 4:0} ; Up, Right, Down, Left
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dpadDirections := { None: {1:0, 8:0, 2:0, 4:0}
|
||||
, Up: {1:1, 8:0, 2:0, 4:0}
|
||||
, UpRight: {1:1, 8:1, 2:0, 4:0}
|
||||
, Right: {1:0, 8:1, 2:0, 4:0}
|
||||
, DownRight: {1:0, 8:1, 2:1, 4:0}
|
||||
, Down: {1:0, 8:0, 2:1, 4:0}
|
||||
, DownLeft: {1:0, 8:0, 2:1, 4:1}
|
||||
, Left: {1:0, 8:0, 2:0, 4:1}
|
||||
, UpLeft: {1:1, 8:0, 2:0, 4:1}}
|
||||
newStates := dpadDirections[state]
|
||||
for id, newState in newStates {
|
||||
oldState := this._DpadStates[id]
|
||||
if (oldState != newState){
|
||||
this._DpadStates[id] := newState
|
||||
this._Parent.Instance.SetButtonState(id, newState)
|
||||
}
|
||||
this._Parent.SendReport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
; ==========================================================
|
||||
; .NET Framework Interop
|
||||
; https://autohotkey.com/boards/viewtopic.php?t=4633
|
||||
; ==========================================================
|
||||
;
|
||||
; Author: Lexikos
|
||||
; Version: 1.2
|
||||
; Requires: AutoHotkey_L v1.0.96+
|
||||
;
|
||||
|
||||
CLR_LoadLibrary(AssemblyName, AppDomain=0)
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
e := ComObjError(0)
|
||||
Loop 1 {
|
||||
if assembly := AppDomain.Load_2(AssemblyName)
|
||||
break
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 1), args[0] := AssemblyName
|
||||
typeofAssembly := AppDomain.GetType().Assembly.GetType()
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, null, null, args)
|
||||
break
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)
|
||||
break
|
||||
}
|
||||
ComObjError(e)
|
||||
return assembly
|
||||
}
|
||||
|
||||
CLR_CreateObject(Assembly, TypeName, Args*)
|
||||
{
|
||||
if !(argCount := Args.MaxIndex())
|
||||
return Assembly.CreateInstance_2(TypeName, true)
|
||||
|
||||
vargs := ComObjArray(0xC, argCount)
|
||||
Loop % argCount
|
||||
vargs[A_Index-1] := Args[A_Index]
|
||||
|
||||
static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0)
|
||||
|
||||
return Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
|
||||
}
|
||||
|
||||
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
|
||||
{
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
|
||||
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, null, null, args)
|
||||
return A_LastError >= 0
|
||||
}
|
||||
|
||||
CLR_StopDomain(ByRef AppDomain)
|
||||
{ ; ICorRuntimeHost::UnloadDomain
|
||||
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
|
||||
CLR_Start(Version="") ; returns ICorRuntimeHost*
|
||||
{
|
||||
static RtHst := 0
|
||||
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
|
||||
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
|
||||
if RtHst
|
||||
return RtHst
|
||||
EnvGet SystemRoot, SystemRoot
|
||||
if Version =
|
||||
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
|
||||
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
|
||||
Version := A_LoopFileName
|
||||
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
|
||||
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr*", RtHst) >= 0
|
||||
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
|
||||
return RtHst
|
||||
}
|
||||
|
||||
;
|
||||
; INTERNAL FUNCTIONS
|
||||
;
|
||||
|
||||
CLR_GetDefaultDomain()
|
||||
{
|
||||
static defaultDomain := 0
|
||||
if !defaultDomain
|
||||
{ ; ICorRuntimeHost::GetDefaultDomain
|
||||
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
|
||||
defaultDomain := ComObject(p), ObjRelease(p)
|
||||
}
|
||||
return defaultDomain
|
||||
}
|
||||
|
||||
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
|
||||
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|
||||
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|
||||
|| !(codeCompiler := codeProvider.CreateCompiler())
|
||||
return 0
|
||||
|
||||
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
|
||||
return 0
|
||||
|
||||
; Convert | delimited list of references into an array.
|
||||
StringSplit, Refs, References, |, %A_Space%%A_Tab%
|
||||
aRefs := ComObjArray(8, Refs0)
|
||||
Loop % Refs0
|
||||
aRefs[A_Index-1] := Refs%A_Index%
|
||||
|
||||
; Set parameters for compiler.
|
||||
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
|
||||
, prms.OutputAssembly := FileName
|
||||
, prms.GenerateInMemory := FileName=""
|
||||
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
|
||||
, prms.CompilerOptions := CompilerOptions
|
||||
, prms.IncludeDebugInformation := true
|
||||
|
||||
; Compile!
|
||||
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
|
||||
|
||||
if error_count := (errors := compilerRes.Errors).Count
|
||||
{
|
||||
error_text := ""
|
||||
Loop % error_count
|
||||
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
|
||||
MsgBox, 16, Compilation Failed, %error_text%
|
||||
return 0
|
||||
}
|
||||
; Success. Return Assembly object or path.
|
||||
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
|
||||
}
|
||||
|
||||
CLR_GUID(ByRef GUID, sGUID)
|
||||
{
|
||||
VarSetCapacity(GUID, 16, 0)
|
||||
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
|
||||
}
|
||||
@@ -0,0 +1,502 @@
|
||||
|
||||
; https://github.com/berban/Gdip
|
||||
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#NoEnv
|
||||
#Persistent
|
||||
#SingleInstance Force
|
||||
#Include Lib\Gdip.ahk
|
||||
#Include Lib\AHK-ViGEm-Bus.ahk
|
||||
|
||||
CoordMode, Pixel, Client
|
||||
CoordMode, ToolTip, Client
|
||||
DetectHiddenWindows, On
|
||||
ListLines Off
|
||||
Process, priority, , High
|
||||
SendMode Input
|
||||
SetBatchLines, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SetFormat, Float, 0.2
|
||||
; SetFormat, IntegerFast, Hex
|
||||
SetKeyDelay, 50
|
||||
SetMouseDelay, -1
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
|
||||
; Variables
|
||||
races_clean := 0
|
||||
races_clean_percent := 0
|
||||
races_completed := 0
|
||||
races_completed_check := 0
|
||||
credits_total := 0
|
||||
credits_average := 0
|
||||
|
||||
time_start := A_TickCount
|
||||
time_current := A_TickCount
|
||||
|
||||
window_width := 640
|
||||
window_height := 360
|
||||
|
||||
; Create a new controller controller
|
||||
controller := new ViGEmDS4()
|
||||
|
||||
; GUI
|
||||
Gui, New, -MaximizeBox -Resize, ClubmanPlus 0.5
|
||||
Gui, Font, S10
|
||||
Gui, Add, Text, vStatRace, Race Counts: %races_completed%
|
||||
Gui, Add, Text, vCleanRace, Clean Races: %races_clean%
|
||||
Gui, Add, Text, vCleanRate, Average Clean Runs: %races_clean_percent%`%
|
||||
Gui, Add, Text, vEarnings, Earnings: %credits_total%M
|
||||
Gui, Add, Text, vEarningsRate, Earnings Rate: %credits_average%M/hr
|
||||
Gui, Add, Button, w150 h40 Default gStart, Start
|
||||
Gui, Add, Button, w150 h40 x+10 gReset, Reset
|
||||
Gui, Show
|
||||
return
|
||||
|
||||
; GUI events
|
||||
GuiClose:
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
OutputDebug % "Clubman> Terminated"
|
||||
ExitApp
|
||||
|
||||
; GUI buttons
|
||||
Stats:
|
||||
GuiControl,,StatRace, Race Counts: %races_completed%
|
||||
GuiControl,,CleanRace, Clean Races: %races_clean%
|
||||
GuiControl,,CleanRate, Average Clean Runs: %races_clean_percent%`%
|
||||
GuiControl,,Earnings, Earnings: %credits_total%M
|
||||
GuiControl,,EarningsRate, Earnings Rate: %credits_average%M/hr
|
||||
Return
|
||||
|
||||
Start:
|
||||
hwnd := 0
|
||||
|
||||
Gosub, Release_All
|
||||
Gosub, GrabWindow
|
||||
|
||||
if (hwnd = 0) {
|
||||
MsgBox, % "PS Remote Play not found"
|
||||
return
|
||||
}
|
||||
|
||||
SetTimer, Health, 600000
|
||||
SetTimer, Summary, 3600000
|
||||
time_start := A_TickCount
|
||||
|
||||
; ** AFK Loop
|
||||
Gosub, Press_X
|
||||
|
||||
Loop {
|
||||
|
||||
; ** RACE
|
||||
OutputDebug % "Clubman> Race: Waiting for position GUI to show"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Starting race"
|
||||
Gosub, Hold_X
|
||||
; Gosub, Hold_Down
|
||||
OutputDebug % "Clubman> Race: Racing until position GUI disappears"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 218, 490, 6, 20)) { ; top-right tire wear indicator
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race: Race ended, releasing all buttons"
|
||||
Gosub, Release_All
|
||||
; Sleep, 5000
|
||||
|
||||
; ** GO TO LEADERBOARDS
|
||||
OutputDebug % "Clubman> End race: Waiting for continue X icon to show"
|
||||
while (!IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Press X to continue"
|
||||
while (IsColor(hwnd, 0xC9C9C9, 465, 519, 6, 20)) { ; X icon
|
||||
Gosub, Press_X
|
||||
Sleep, 100
|
||||
}
|
||||
OutputDebug % "Clubman> End race: Transitioning to leaderboard"
|
||||
|
||||
; ** LEADERBOARD
|
||||
Loop {
|
||||
OutputDebug % "Clubman> Leaderboard: Checking positions"
|
||||
|
||||
if (IsColor(hwnd, 0xBADD3E, 671, 124, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 1st position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 153, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 2nd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 182, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 3rd position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 211, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 4th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else if (IsColor(hwnd, 0xBADD3E, 671, 240, 10, 20)) { ; venom green on the leaderboard
|
||||
OutputDebug % "Clubman> Leaderboard: 5th position"
|
||||
Gosub, Press_X
|
||||
break
|
||||
}
|
||||
else {
|
||||
Sleep, 500
|
||||
}
|
||||
}
|
||||
|
||||
; ** REWARDS
|
||||
OutputDebug % "Clubman> Rewards: Waiting for Rewards screen to load (checking money earnt)"
|
||||
while (!IsColor(hwnd, 0xBE140F, 848, 192, 6, 100)) { ; money earn, the red text
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Rewards: Found Rewards screen"
|
||||
races_completed++
|
||||
|
||||
Loop 100 {
|
||||
if (IsColor(hwnd, 0x5C90FB, 451, 260, 10, 20)) { ; the 'R' in Clean Race Bonus
|
||||
OutputDebug % "Clubman> Rewards: Clean bonus"
|
||||
races_clean++
|
||||
PixelSearch(486, 311, 1, hwnd, "clean", "")
|
||||
break
|
||||
}
|
||||
|
||||
if (A_Index == 100) {
|
||||
OutputDebug % "Clubman> Rewards: No clean bonus"
|
||||
PixelSearch(486, 311, 1, hwnd, "no-clean", "")
|
||||
}
|
||||
}
|
||||
|
||||
; ** REPLAY
|
||||
OutputDebug % "Clubman> Replay: Waiting for Replay screen to load"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Pressing the Exit button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 911, 510, 4, 20)) { ; the cursor on top the exit button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Replay: Leaving the Replay screen"
|
||||
|
||||
; ** RACE RESULTS
|
||||
OutputDebug % "Clubman> Race Result: Waiting for Race Result screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xBE1E1C, 651, 497, 4, 20)) { ; the exit button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Moving cursor to the Retry button"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_Right
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Result: Pressing the Retry button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 514, 504, 4, 20)) { ; cursor on top the retry button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
; ** RACE START
|
||||
OutputDebug % "Clubman> Race Start: Waiting for Race Start screen to load (checking cursor)"
|
||||
while (!IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Sleep, 500
|
||||
}
|
||||
OutputDebug % "Clubman> Race Start: Pressing the Start button"
|
||||
while (IsColor(hwnd, 0xFFFFFF, 287, 504, 4, 20)) { ; cursor on top the start button
|
||||
Gosub, Press_X
|
||||
Sleep, 500
|
||||
}
|
||||
|
||||
OutputDebug % "--- Summary ---"
|
||||
credits_total := (races_completed * 0.07 + races_clean * 0.035)
|
||||
races_clean_percent := (races_clean / races_completed) * 100
|
||||
time_current := A_TickCount
|
||||
credits_average := credits_total / (time_current - time_start) * 3600000
|
||||
|
||||
Gosub, Stats
|
||||
|
||||
OutputDebug % "Clubman> Summary: Races " races_completed
|
||||
OutputDebug % "Clubman> Summary: Races Clean " races_clean
|
||||
OutputDebug % "Clubman> Summary: Races Clean Rate " races_clean_percent "%"
|
||||
OutputDebug % "Clubman> Summary: Earnings " credits_total "M"
|
||||
OutputDebug % "Clubman> Summary: Earnings Rate " credits_average "M/Hr"
|
||||
OutputDebug % "---------------"
|
||||
}
|
||||
return
|
||||
|
||||
Reset:
|
||||
OutputDebug % "Clubman> Reloading"
|
||||
Gosub, Release_All
|
||||
SetTimer, Health, Off
|
||||
SetTimer, Summary, Off
|
||||
Reload
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Health Check
|
||||
; -------------------
|
||||
Health:
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
OutputDebug % "Clubman> Health: Checking health at " current_date
|
||||
OutputDebug % "Clubman> Health: Races completed " races_completed
|
||||
OutputDebug % "Clubman> Health: Races completed last time " races_completed_check
|
||||
|
||||
if (races_completed_check >= races_completed) {
|
||||
OutputDebug % "Clubman> Health: Error dectected, sending notification"
|
||||
SendNotification("ClubmanPlus", "Something went wrong", 2, "persistent")
|
||||
} else {
|
||||
OutputDebug % "Clubman> Health: Running healthy"
|
||||
races_completed_check := races_completed
|
||||
}
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Summary Check
|
||||
; -------------------
|
||||
Summary:
|
||||
OutputDebug % "Clubman> Summary: Sending summary notification"
|
||||
message := ""
|
||||
message := message "Races " races_clean " / " races_completed " (" races_clean_percent ")`n"
|
||||
message := message "Earnings " credits_total "M (" credits_average "M/Hr)"
|
||||
SendNotification("ClubmanPlus", message, 0, "cashregister")
|
||||
Return
|
||||
|
||||
; -------------------
|
||||
; Send Notification
|
||||
; -------------------
|
||||
SendNotification(title, message, level, sound) {
|
||||
|
||||
IniRead, token, %A_ScriptDir%\clubman.ini, pushover, token
|
||||
IniRead, user, %A_ScriptDir%\clubman.ini, pushover, user_key
|
||||
|
||||
retries := 60
|
||||
expires := 3600
|
||||
|
||||
url := "https://api.pushover.net/1/messages.json"
|
||||
param := "token=" token "&user=" user "&title=" title "&message=" message "&sound=" sound "&priority=" level
|
||||
|
||||
if (level == 2) {
|
||||
param := param "&retry=" retries "&expire=" expires
|
||||
}
|
||||
|
||||
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
WebRequest.Open("POST", url)
|
||||
WebRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
WebRequest.Send(param)
|
||||
Return
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Grab Window
|
||||
; -------------------
|
||||
GrabWindow:
|
||||
OutputDebug % "Clubman> Looking for window"
|
||||
hwnd := WinExist("PS Remote Play")
|
||||
|
||||
if (hwnd > 0) {
|
||||
OutputDebug % "Clubman> Window found: " hwnd
|
||||
WinMove, ahk_id %hwnd%,, 0, 0, %window_width%, %window_height%
|
||||
WinActivate, ahk_id %hwnd%
|
||||
ControlFocus,, ahk_id %hwnd%
|
||||
}
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Is Color
|
||||
; -------------------
|
||||
IsColor(hwnd, target_color, x, y, b, tolerance) {
|
||||
for i, c in PixelSearch(x, y, b, hwnd) {
|
||||
if (ColorDistance(c, target_color) <= tolerance) {
|
||||
Return True
|
||||
}
|
||||
}
|
||||
Return False
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Color Distance
|
||||
; -------------------
|
||||
ColorDistance( c1, c2 ) {
|
||||
r1 := c1 >> 16
|
||||
g1 := c1 >> 8 & 255
|
||||
b1 := c1 & 255
|
||||
r2 := c2 >> 16
|
||||
g2 := c2 >> 8 & 255
|
||||
b2 := c2 & 255
|
||||
return Sqrt( (r1-r2)**2 + (g1-g2)**2 + (b1-b2)**2 )
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Pixel Search
|
||||
; -------------------
|
||||
PixelSearch(x, y, b, hwnd, debugsave := "", debugsavecropped := "") {
|
||||
x := (960 / x)
|
||||
y := (540 / y)
|
||||
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hwnd, "ptr", &rect)
|
||||
x := floor(NumGet(rect, 8, "int") // x)
|
||||
y := floor(NumGet(rect, 12, "int") // y)
|
||||
b := floor((b * NumGet(rect, 8, "int")) / 960)
|
||||
|
||||
VarSetCapacity(POINT, 8)
|
||||
NumPut(x, &POINT, 0, "Int")
|
||||
NumPut(y, &POINT, 4, "Int")
|
||||
DllCall("user32\ClientToScreen", Ptr, hwnd, Ptr,&POINT)
|
||||
x := NumGet(&POINT, 0, "Int")
|
||||
y := NumGet(&POINT, 4, "Int")
|
||||
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromScreen("hwnd:" hwnd)
|
||||
|
||||
pixs := []
|
||||
Loop % b*2 + 1 {
|
||||
i := (-1 * b) + (A_Index - 1)
|
||||
Loop % b*2 + 1 {
|
||||
j := (-1 * b) + (A_Index - 1)
|
||||
pixs.Push(Gdip_GetPixel(pBitmap, x+i, y+j) & 0x00FFFFFF)
|
||||
}
|
||||
}
|
||||
|
||||
FormatTime, current_date,, % "yyMMdd-HHmm-ss"
|
||||
|
||||
if (debugsave != "") {
|
||||
Gdip_SaveBitmapToFile(pBitmap, A_ScriptDir . "\" . current_date . "-" . debugsave . ".bmp")
|
||||
}
|
||||
if (debugsavecropped != "") {
|
||||
debugbitmap:=Gdip_CloneBitmapArea(pBitmap, x-b, y-b, b*2, b*2)
|
||||
Gdip_SaveBitmapToFile(debugbitmap, A_ScriptDir . "\" . current_date . "-" . debugsavecropped . ".bmp")
|
||||
Gdip_DisposeImage(debugbitmap)
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
; -------------------
|
||||
; Release All
|
||||
; -------------------
|
||||
Release_All:
|
||||
Gosub, Release_X
|
||||
Gosub, Release_O
|
||||
Gosub, Release_Right
|
||||
Gosub, Release_Left
|
||||
Gosub, Release_Up
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press x
|
||||
; -------------------
|
||||
Press_X:
|
||||
Gosub, Hold_X
|
||||
Sleep, 50
|
||||
Gosub, Release_x
|
||||
return
|
||||
|
||||
Hold_X:
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
return
|
||||
|
||||
Release_X:
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press O
|
||||
; -------------------
|
||||
Press_O:
|
||||
Gosub, Hold_O
|
||||
Sleep, 50
|
||||
Gosub, Release_O
|
||||
return
|
||||
|
||||
Hold_O:
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
return
|
||||
|
||||
Release_O:
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Right
|
||||
; -------------------
|
||||
Press_Right:
|
||||
Gosub, Hold_Right
|
||||
Sleep, 50
|
||||
Gosub, Release_Right
|
||||
return
|
||||
|
||||
Hold_Right:
|
||||
controller.Dpad.SetState("Right")
|
||||
return
|
||||
|
||||
Release_Right:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Left
|
||||
; -------------------
|
||||
Press_Left:
|
||||
Gosub, Hold_Left
|
||||
Sleep, 50
|
||||
Gosub, Release_Left
|
||||
return
|
||||
|
||||
Hold_Left:
|
||||
controller.Dpad.SetState("Left")
|
||||
return
|
||||
|
||||
Release_Left:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Up
|
||||
; -------------------
|
||||
Press_Up:
|
||||
Gosub, Hold_Up
|
||||
Sleep, 50
|
||||
Gosub, Release_Up
|
||||
return
|
||||
|
||||
Hold_Up:
|
||||
controller.Dpad.SetState("Up")
|
||||
return
|
||||
|
||||
Release_Up:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; -------------------
|
||||
; Press Down
|
||||
; -------------------
|
||||
Press_Down:
|
||||
Gosub, Hold_Down
|
||||
Sleep, 50
|
||||
Gosub, Release_Down
|
||||
return
|
||||
|
||||
Hold_Down:
|
||||
controller.Dpad.SetState("Down")
|
||||
return
|
||||
|
||||
Release_Down:
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
; Hotkeys
|
||||
^Esc::ExitApp
|
||||
@@ -0,0 +1,3 @@
|
||||
[pushover]
|
||||
user_key=your_key
|
||||
token=your_token
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,313 @@
|
||||
#Persistent
|
||||
#NoEnv
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#Include Lib\Gdip.ahk
|
||||
#Include Lib\AHK-ViGEm-Bus.ahk
|
||||
#Include Lib\__utility__.ahk
|
||||
#Include Lib\__controller_functions__.ahk
|
||||
#Include Mod\TokyoDetections.ahk
|
||||
#Include Races\Tokyo.ahk
|
||||
|
||||
hModule := DllCall("LoadLibrary", "Str", A_LineFile "\..\Lib\SuperSleep.dll", "Ptr")
|
||||
SuperSleep := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", A_LineFile "\..\Lib\SuperSleep.dll", "Ptr"), "AStr", "super_sleep", "Ptr")
|
||||
|
||||
ListLines Off
|
||||
Process, Priority, , A
|
||||
SetBatchLines, -1
|
||||
SetKeyDelay, -1, -1
|
||||
SetMouseDelay, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SendMode Input
|
||||
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
DetectHiddenWindows, On
|
||||
#Persistent
|
||||
|
||||
Global script_start := A_TickCount
|
||||
Global remote_play_offsetY := 71
|
||||
Global racecounter := 0
|
||||
Global resetcounter := 0
|
||||
Global color_pitstop1 := 0xFFFFFF
|
||||
Global color_restart := 0x6D5223
|
||||
Global hairpin_delay := 0
|
||||
|
||||
Global TelegramBotToken := ""
|
||||
Global TelegramChatID := ""
|
||||
Global location := ""
|
||||
Global TokyoLapCount := 1
|
||||
|
||||
|
||||
|
||||
SetFormat, integerfast, d
|
||||
ps_win_width := 640
|
||||
ps_win_height := 360
|
||||
IniRead, hairpin_delay, config.ini, Vars, hairpin_delay, 0
|
||||
IniRead, color_pitstop1, config.ini, Vars, color_pitstop1, 0
|
||||
IniRead, RaceCounterTotal, config.ini, Stats, racecountertotal, 0
|
||||
IniRead, ResetCounterTotal, config.ini, Stats, resetcountertotal, 0
|
||||
IniRead, TelegramBotToken, config.ini, API, TelegramBotToken, 0
|
||||
IniRead, TelegramChatID, config.ini, API, TelegramChatID, 0
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountertotal := 835000*racecountertotal/1000000
|
||||
|
||||
Global controller := new ViGEmDS4()
|
||||
controller.SubscribeFeedback(Func("OnFeedback"))
|
||||
OnFeedback(largeMotor, smallMotor, lightbarColor){
|
||||
}
|
||||
|
||||
;- GUI 1 (MAIN) -------------------------------------------------------------------------------------------------
|
||||
Icon = Assets\GT7_Tokyo.ico
|
||||
Menu, Tray, Icon, %Icon%
|
||||
Gui, -Caption
|
||||
Gui, Add, Picture, x0 y0 w650 h207 , Assets\tokyo_gui.png
|
||||
Gui, Add, Button, x222 y82 w410 h80 default gButtonStart, START
|
||||
Gui, Add, Progress, x0 y54 w641 h12 RaceProgress vRaceProgress -Smooth, 0
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x440 y3 w160 h20 RaceCounterTotal +BackgroundTrans, // ALL TIME
|
||||
Gui, Font, ,
|
||||
Gui, Add, Text, x440 y23 w160 h20 RaceCounterTotal vracecountertotal +BackgroundTrans, Races completed: %racecountertotal%
|
||||
Gui, Add, Text, x440 y38 w160 h20 ResetCounterTotal vresetcountertotal +BackgroundTrans, Races failed: %resetcountertotal%
|
||||
Gui, Add, Text, x550 y38 w160 h20 CreditCounterTotal vcreditcountertotal +BackgroundTrans, Credits: %creditcountertotal% M
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x220 y3 w300 h20 RaceSession vracesession +BackgroundTrans, // SESSION
|
||||
Gui, Font, ,
|
||||
Gui, Add, Text, x220 y23 w160 h20 RaceCounterSession vracecountersession +BackgroundTrans, Races completed: 0
|
||||
Gui, Add, Text, x220 y38 w160 h20 ResetCounterSession vresetcountersession +BackgroundTrans, Races failed: 0
|
||||
Gui, Add, Text, x330 y23 w160 h20 CreditCounterSession vcreditcountersession +BackgroundTrans, Credits: 0
|
||||
Gui, Add, Text, x330 y38 w160 h20 CreditAVG vcreditavg +BackgroundTrans, Avg./h: 0
|
||||
Gui, Add, Text, x10 y38 w150 h20 CounterLap vcurrentlap +BackgroundTrans, Current Lap: 0/12
|
||||
Gui, Add, Text, x10 y23 w150 h20 CurrentLoop vcurrentloop +BackgroundTrans, Current Location: -
|
||||
Gui, Add, Button, x222 y172 w300 h20 default gGUIReset, Reset
|
||||
Gui, Add, Button, x531 y172 w101 h20 default gGUIClose, Exit
|
||||
Gui, Add, Button, x12 y82 w200 h20 default gMachineSettingsWindow, Settings: Machine/Setup
|
||||
Gui, Add, Button, x12 y112 w200 h20 default gIngameSettingsWindow, Settings: Ingame (wip)
|
||||
Gui, Add, Button, x12 y142 w200 h20 default gRiskRewardWindow, Settings: Risk/Reward (wip)
|
||||
Gui, Add, Button, x12 y172 w200 h20 default gNotificationsWindow, Settings: Notifications/API
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x10 y3 w620 h20 +BackgroundTrans, // TOKYO CONTROL CENTER
|
||||
Gui, Add, Statusbar, -Theme Backgroundeeeeee ;#eeeeee, no typo
|
||||
SB_SetParts(80,270,190)
|
||||
SB_SetText(" beta 9.2 ",1)
|
||||
SB_SetText(" by problemz.",4)
|
||||
Gui, Show, x8 y532 h225 w640, GT7 Tokyo // by problemz
|
||||
guicontrol,, CurrentLoop, Press START, go go!
|
||||
;- GUI 2 (MACHINE/SETUP) ----------------------------------------------------------------------------------------
|
||||
Gui, 2: Add, Picture, x0 y0 w650 h210 , Assets\tokyo_gui.png
|
||||
Gui, 2: Add, Text, x10 y14 w200 h20 +BackgroundTrans , Hairpin Turn Delay:
|
||||
Gui, 2: Font, ,
|
||||
Gui, 2: Add, Text, x170 y14 w200 h20 +BackgroundTrans , (ms)
|
||||
Gui, 2: Add, Slider, x220 y10 w300 h51 vsliderhairpindelay Range0-800 Thick40 +ToolTip TickInterval50 gSliderMove,%hairpin_delay%
|
||||
Gui, 2: Add, Edit, x106 y11 w60 vtxthairpindelay gtextchanged, %hairpin_delay%
|
||||
Gui, 2: Add, Text, x10 y40 w200 h20 +BackgroundTrans , Lower = slower PC // Higher = faster PC
|
||||
Gui, 2: Add, Button, x530 y11 w100 h51 +BackgroundTrans gSaveToIni, Save
|
||||
|
||||
Gui, 2: Add, Button, x10 y80 w200 h40 gPit1Color, Stuck in pit `n(Only click when at tire selection menu)
|
||||
;- GUI 3 (INGAME) -----------------------------------------------------------------------------------------------
|
||||
Gui, 3: Add, Picture, x0 y0 w650 h177 , Assets\tokyo_gui.png
|
||||
;- GUI 4 (RISK/REWARD) ------------------------------------------------------------------------------------------
|
||||
Gui, 4: Add, Picture, x0 y0 w650 h177 , Assets\tokyo_gui.png
|
||||
;- GUI 5 (NOTIFICATIONS/API) ------------------------------------------------------------------------------------
|
||||
Gui, 5: Add, Picture, x0 y0 w650 h400 , Assets\tokyo_gui.png
|
||||
Gui, 5: Add, Text, x10 y14 w205 h20 +BackgroundTrans , Telegram Bot Token:
|
||||
Gui, 5: Add, Edit, x116 y11 w400 vTelegramBotToken Password, %TelegramBotToken%
|
||||
Gui, 5: Add, Text, x10 y44 w205 h20 +BackgroundTrans , Telegram Chat ID:
|
||||
Gui, 5: Add, Edit, x116 y41 w400 vTelegramChatID Password, %TelegramChatID%
|
||||
Gui, 5: Add, Button, x530 y11 w100 h51 +BackgroundTrans gSaveToIni, Save
|
||||
Return
|
||||
|
||||
MachineSettingsWindow:
|
||||
|
||||
if (GetKeyState("LShift", "P") AND GetKeyState("LAlt", "P")){
|
||||
goto, MouseColor
|
||||
}
|
||||
else{
|
||||
Gui, 2: Show, x6 y757 w639 h133, Settings: Machine/Setup
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
IngameSettingsWindow:
|
||||
Gui, 3: Show, x6 y757 w639 h35, Settings: Ingame
|
||||
return
|
||||
|
||||
RiskRewardWindow:
|
||||
Gui, 4: Show, x6 y757 w639 h35, Settings: Risk/Reward
|
||||
return
|
||||
|
||||
NotificationsWindow:
|
||||
Gui, 5: Show, x6 y757 w639 h70, Settings: Notifications/API
|
||||
return
|
||||
|
||||
SliderMove:
|
||||
Gui, Submit, nohide
|
||||
GuiControl,, txthairpindelay, %sliderhairpindelay%
|
||||
Return
|
||||
|
||||
SaveToIni:
|
||||
Gui, Submit, Hide
|
||||
IniWrite, %txthairpindelay%, config.ini,Vars, hairpin_delay
|
||||
IniWrite, %TelegramBotToken%, config.ini,API, TelegramBotToken
|
||||
IniWrite, %TelegramChatID%, config.ini,API, TelegramChatID
|
||||
return
|
||||
|
||||
TextChanged:
|
||||
guiControlGet, txtvar,, txthairpindelay
|
||||
if (txtvar > 800)
|
||||
{
|
||||
GuiControl,, txthairpindelay, 800
|
||||
}
|
||||
|
||||
GuiControl,, sliderhairpindelay, %txtvar%
|
||||
return
|
||||
|
||||
Pit1Color:
|
||||
MsgBox, 4,, Do you really wanna set a new Pitstop color?
|
||||
IfMsgBox Yes
|
||||
{
|
||||
gosub, GrabRemotePlay
|
||||
color_pitstop1 := PixelColorSimple(199, 315+remote_play_offsetY)
|
||||
IniWrite, %color_pitstop1%, config.ini,Vars, color_pitstop1
|
||||
}
|
||||
return
|
||||
|
||||
ButtonStart:
|
||||
SetTimer, UpdateTimer, 1000
|
||||
Gui, Submit, NoHide
|
||||
id := ""
|
||||
SetKeyDelay, 10
|
||||
Process, priority, , High
|
||||
gosub, GrabRemotePlay
|
||||
if (id = "")
|
||||
return
|
||||
gosub, PauseLoop
|
||||
CoordMode, Pixel, Screen
|
||||
CoordMode, ToolTip, Screen
|
||||
loop {
|
||||
Press_X()
|
||||
Race_Tokyo()
|
||||
}
|
||||
|
||||
PixelTuning:
|
||||
x_ratio := ps_win_width/640
|
||||
y_ratio := ps_win_height/360
|
||||
return
|
||||
|
||||
GrabRemotePlay:
|
||||
WinGet, remotePlay_id, List, ahk_exe RemotePlay.exe
|
||||
if (remotePlay_id = 0)
|
||||
{
|
||||
MsgBox, PS4 Remote Play not found
|
||||
return
|
||||
}
|
||||
Loop, %remotePlay_id%
|
||||
{
|
||||
id := remotePlay_id%A_Index%
|
||||
WinGetTitle, title, % "ahk_id " id
|
||||
If InStr(title, "PS Remote Play")
|
||||
break
|
||||
}
|
||||
WinMove, ahk_id %id%,, 0, 0, 640, 540
|
||||
|
||||
ControlFocus,, ahk_class %remotePlay_class%
|
||||
WinActivate, ahk_id %id%
|
||||
GetClientSize(remotePlay_id5, ps_win_width, ps_win_height)
|
||||
gosub, PixelTuning
|
||||
return
|
||||
|
||||
PauseLoop:
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
controller.Buttons.Square.SetState(false)
|
||||
controller.Buttons.Triangle.SetState(false)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
controller.Buttons.L1.SetState(false)
|
||||
controller.Buttons.L2.SetState(false)
|
||||
controller.Axes.L2.SetState(0)
|
||||
controller.Buttons.R1.SetState(false)
|
||||
controller.Buttons.R2.SetState(false)
|
||||
controller.Axes.R2.SetState(0)
|
||||
controller.Buttons.RS.SetState(false)
|
||||
controller.Axes.RX.SetState(50)
|
||||
controller.Axes.RY.SetState(50)
|
||||
controller.Buttons.LS.SetState(false)
|
||||
controller.Axes.LX.SetState(50)
|
||||
controller.Axes.LY.SetState(50)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
ResetRace:
|
||||
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime%: Race failed - Lap %TokyoLapCount% - %location%.`n, log.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race failed - Lap " TokyoLapCount " - " location ".&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
|
||||
SB_SetText(" - RESET INITIATED -",2)
|
||||
guicontrol,, CurrentLoop, Something went wrong, reseting.
|
||||
controller.Axes.LX.SetState(50)
|
||||
Press_Options()
|
||||
Sleep(1000)
|
||||
Press_Right()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
controller.Axes.LX.SetState(65)
|
||||
IniRead, ResetCounterTotal, config.ini, Stats, resetcountertotal, 0
|
||||
SetFormat, integerfast, d
|
||||
resetcounter++
|
||||
resetcountertotal++
|
||||
IniWrite, %resetcountertotal%, config.ini,Stats, ResetCounterTotal
|
||||
guicontrol,, ResetCounterTotal, Races failed: %resetcountertotal%
|
||||
guicontrol,, ResetCounterSession, Races failed: %resetcounter%
|
||||
guicontrol,, RaceProgress, 0
|
||||
Race_Tokyo()
|
||||
return
|
||||
|
||||
|
||||
MouseHelp:
|
||||
|
||||
coord=relative
|
||||
sleep, 1000
|
||||
CoordMode, ToolTip, %coord%
|
||||
CoordMode, Pixel, %coord%
|
||||
CoordMode, Mouse, %coord%
|
||||
CoordMode, Caret, %coord%
|
||||
CoordMode, Menu, %coord%
|
||||
return
|
||||
|
||||
Refresh:
|
||||
MouseGetPos, x, y
|
||||
PixelGetColor, cBGR, %x%, %y%,, Alt RGB
|
||||
WinGetPos,,, w, h, A
|
||||
ToolTip,Location: %x% x %y%`nRGB: %cBGR%`nWindow Size: %w% x %h%
|
||||
return
|
||||
|
||||
MouseColor:
|
||||
gosub, MouseHelp
|
||||
SetTimer, Refresh, 75
|
||||
return
|
||||
|
||||
GuiClose:
|
||||
gosub, PauseLoop
|
||||
ExitApp
|
||||
^Esc::ExitApp
|
||||
|
||||
GUIReset:
|
||||
if (GetKeyState("LShift", "P") AND GetKeyState("LAlt", "P")){
|
||||
MsgBox, 4,, Reset all data?
|
||||
IfMsgBox Yes
|
||||
{
|
||||
IniWrite, 0, config.ini,Stats, RaceCounterTotal
|
||||
IniWrite, 0, config.ini,Stats, ResetCounterTotal
|
||||
}
|
||||
}
|
||||
Sleep(500)
|
||||
gosub, PauseLoop
|
||||
Reload
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
#include %A_LineFile%\..\CLR.ahk
|
||||
|
||||
; Static class, holds ViGEm Client instance
|
||||
class ViGEmWrapper {
|
||||
static asm := 0
|
||||
static client := 0
|
||||
|
||||
Init(){
|
||||
if (this.client == 0){
|
||||
this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
}
|
||||
}
|
||||
|
||||
CreateInstance(cls){
|
||||
return this.asm.CreateInstance(cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
; Base class for ViGEm "Targets" (Controller types - eg xb360 / ds4) to inherit from
|
||||
class ViGEmTarget {
|
||||
target := 0
|
||||
helperClass := ""
|
||||
controllerClass := ""
|
||||
|
||||
__New(){
|
||||
;~ this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
ViGEmWrapper.Init()
|
||||
this.Instance := ViGEmWrapper.CreateInstance(this.helperClass)
|
||||
|
||||
if (this.Instance.OkCheck() != "OK"){
|
||||
msgbox ViGEmWrapper.dll failed to load!
|
||||
ExitApp
|
||||
}
|
||||
}
|
||||
|
||||
SendReport(){
|
||||
this.Instance.SendReport()
|
||||
}
|
||||
|
||||
SubscribeFeedback(callback){
|
||||
this.Instance.SubscribeFeedback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
; DS4 (DualShock 4 for Playstation 4)
|
||||
class ViGEmDS4 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Ds4"
|
||||
__New(){
|
||||
static buttons := {Square: 16, Cross: 32, Circle: 64, Triangle: 128, L1: 256, R1: 512, L2: 1024, R2: 2048
|
||||
, Share: 4096, Options: 8192, LS: 16384, RS: 32768 }
|
||||
static specialButtons := {Ps: 1, TouchPad: 2}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
for name, id in specialButtons {
|
||||
this.Buttons[name] := new this._SpecialButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _SpecialButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetSpecialButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
return round(state * 2.55)
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dPadDirections := {Up: 0, UpRight: 1, Right: 2, DownRight: 3, Down: 4, DownLeft: 5, Left: 6, UpLeft: 7, None: 8}
|
||||
this._Parent.Instance.SetDpadState(dPadDirections[state])
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Xb360
|
||||
class ViGEmXb360 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Xb360"
|
||||
__New(){
|
||||
static buttons := {A: 4096, B: 8192, X: 16384, Y: 32768, LB: 256, RB: 512, LS: 64, RS: 128, Back: 32, Start: 16, Xbox: 1024}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
value := round((state * 655.36) - 32768)
|
||||
if (value == 32768)
|
||||
return 32767
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
_DpadStates := {1:0, 8:0, 2:0, 4:0} ; Up, Right, Down, Left
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dpadDirections := { None: {1:0, 8:0, 2:0, 4:0}
|
||||
, Up: {1:1, 8:0, 2:0, 4:0}
|
||||
, UpRight: {1:1, 8:1, 2:0, 4:0}
|
||||
, Right: {1:0, 8:1, 2:0, 4:0}
|
||||
, DownRight: {1:0, 8:1, 2:1, 4:0}
|
||||
, Down: {1:0, 8:0, 2:1, 4:0}
|
||||
, DownLeft: {1:0, 8:0, 2:1, 4:1}
|
||||
, Left: {1:0, 8:0, 2:0, 4:1}
|
||||
, UpLeft: {1:1, 8:0, 2:0, 4:1}}
|
||||
newStates := dpadDirections[state]
|
||||
for id, newState in newStates {
|
||||
oldState := this._DpadStates[id]
|
||||
if (oldState != newState){
|
||||
this._DpadStates[id] := newState
|
||||
this._Parent.Instance.SetButtonState(id, newState)
|
||||
}
|
||||
this._Parent.SendReport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
; ==========================================================
|
||||
; .NET Framework Interop
|
||||
; https://autohotkey.com/boards/viewtopic.php?t=4633
|
||||
; ==========================================================
|
||||
;
|
||||
; Author: Lexikos
|
||||
; Version: 1.2
|
||||
; Requires: AutoHotkey_L v1.0.96+
|
||||
;
|
||||
|
||||
CLR_LoadLibrary(AssemblyName, AppDomain=0)
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
e := ComObjError(0)
|
||||
Loop 1 {
|
||||
if assembly := AppDomain.Load_2(AssemblyName)
|
||||
break
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 1), args[0] := AssemblyName
|
||||
typeofAssembly := AppDomain.GetType().Assembly.GetType()
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, null, null, args)
|
||||
break
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)
|
||||
break
|
||||
}
|
||||
ComObjError(e)
|
||||
return assembly
|
||||
}
|
||||
|
||||
CLR_CreateObject(Assembly, TypeName, Args*)
|
||||
{
|
||||
if !(argCount := Args.MaxIndex())
|
||||
return Assembly.CreateInstance_2(TypeName, true)
|
||||
|
||||
vargs := ComObjArray(0xC, argCount)
|
||||
Loop % argCount
|
||||
vargs[A_Index-1] := Args[A_Index]
|
||||
|
||||
static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0)
|
||||
|
||||
return Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
|
||||
}
|
||||
|
||||
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
|
||||
{
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
|
||||
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, null, null, args)
|
||||
return A_LastError >= 0
|
||||
}
|
||||
|
||||
CLR_StopDomain(ByRef AppDomain)
|
||||
{ ; ICorRuntimeHost::UnloadDomain
|
||||
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
|
||||
CLR_Start(Version="") ; returns ICorRuntimeHost*
|
||||
{
|
||||
static RtHst := 0
|
||||
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
|
||||
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
|
||||
if RtHst
|
||||
return RtHst
|
||||
EnvGet SystemRoot, SystemRoot
|
||||
if Version =
|
||||
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
|
||||
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
|
||||
Version := A_LoopFileName
|
||||
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
|
||||
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr*", RtHst) >= 0
|
||||
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
|
||||
return RtHst
|
||||
}
|
||||
|
||||
;
|
||||
; INTERNAL FUNCTIONS
|
||||
;
|
||||
|
||||
CLR_GetDefaultDomain()
|
||||
{
|
||||
static defaultDomain := 0
|
||||
if !defaultDomain
|
||||
{ ; ICorRuntimeHost::GetDefaultDomain
|
||||
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
|
||||
defaultDomain := ComObject(p), ObjRelease(p)
|
||||
}
|
||||
return defaultDomain
|
||||
}
|
||||
|
||||
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
|
||||
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|
||||
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|
||||
|| !(codeCompiler := codeProvider.CreateCompiler())
|
||||
return 0
|
||||
|
||||
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
|
||||
return 0
|
||||
|
||||
; Convert | delimited list of references into an array.
|
||||
StringSplit, Refs, References, |, %A_Space%%A_Tab%
|
||||
aRefs := ComObjArray(8, Refs0)
|
||||
Loop % Refs0
|
||||
aRefs[A_Index-1] := Refs%A_Index%
|
||||
|
||||
; Set parameters for compiler.
|
||||
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
|
||||
, prms.OutputAssembly := FileName
|
||||
, prms.GenerateInMemory := FileName=""
|
||||
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
|
||||
, prms.CompilerOptions := CompilerOptions
|
||||
, prms.IncludeDebugInformation := true
|
||||
|
||||
; Compile!
|
||||
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
|
||||
|
||||
if error_count := (errors := compilerRes.Errors).Count
|
||||
{
|
||||
error_text := ""
|
||||
Loop % error_count
|
||||
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
|
||||
MsgBox, 16, Compilation Failed, %error_text%
|
||||
return 0
|
||||
}
|
||||
; Success. Return Assembly object or path.
|
||||
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
|
||||
}
|
||||
|
||||
CLR_GUID(ByRef GUID, sGUID)
|
||||
{
|
||||
VarSetCapacity(GUID, 16, 0)
|
||||
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
|
||||
/**********************************************
|
||||
* Controller methods for simplicity *
|
||||
***********************************************/
|
||||
*/
|
||||
|
||||
GoTo EndControllerFunctionsDef
|
||||
|
||||
;;;;;;;;;;;; Turning functions
|
||||
;;;;;;;;;;;; For holding the stick in a specific position for a period of time
|
||||
;;;;;;;;;;;; Note no other button may be pressed or released when these functions are ran
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (50, 100), 100 being the most, 50 being neutral
|
||||
Turn_Right(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (0, 50), 0 being the most
|
||||
Turn_Left(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
;;;;;;;;;;;; Simple button press functions
|
||||
;;;;;;;;;;;; You can pass a delay amount or leave it blank
|
||||
;;;;;;;;;;;; Longer delays hold the button longer
|
||||
|
||||
; Press X button
|
||||
Press_X(delay:=200){
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press O button
|
||||
Press_O(delay:=200){
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Triangle button
|
||||
Press_Triangle(delay:=200){
|
||||
controller.Buttons.Triangle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Triangle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Square button
|
||||
Press_Square(delay:=200){
|
||||
controller.Buttons.Square.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Square.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_L1(delay:=200){
|
||||
controller.Buttons.L1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.L1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_R1(delay:=200){
|
||||
controller.Buttons.R1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.R1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Right on D-pad
|
||||
Press_Right(delay:=200){
|
||||
controller.Dpad.SetState("Right")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Left on D-pad
|
||||
Press_Left(delay:=200){
|
||||
controller.Dpad.SetState("Left")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Up on D-pad
|
||||
Press_Up(delay:=200){
|
||||
controller.Dpad.SetState("Up")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Down on D-pad
|
||||
Press_Down(delay:=200){
|
||||
controller.Dpad.SetState("Down")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
;;;;;;;;;;; Other functions specific to GT7
|
||||
|
||||
; Turn on nitrous
|
||||
Nitrous_On(){
|
||||
controller.Buttons.RS.SetState(true)
|
||||
}
|
||||
|
||||
; Turn off nitrous
|
||||
Nitrous_Off(){
|
||||
controller.Buttons.RS.SetState(false)
|
||||
}
|
||||
|
||||
Accel_On(control:=100){
|
||||
controller.Buttons.R2.SetState(true)
|
||||
controller.Axes.RT.SetState(control)
|
||||
}
|
||||
|
||||
Accel_Off(){
|
||||
controller.Buttons.R2.SetState(false)
|
||||
controller.Axes.RT.SetState(0)
|
||||
}
|
||||
|
||||
Brake_On(control:=100){
|
||||
controller.Buttons.L2.SetState(true)
|
||||
controller.Axes.LT.SetState(control)
|
||||
}
|
||||
|
||||
Brake_Off(){
|
||||
controller.Buttons.L2.SetState(false)
|
||||
controller.Axes.LT.SetState(0)
|
||||
}
|
||||
; given time t in miliseconds, turn right for that long, with intensity being how much the turn button is held for
|
||||
Turn:
|
||||
t0 := A_TickCount
|
||||
tf := t0+t
|
||||
loop {
|
||||
Sleep(100)
|
||||
} until A_TickCount > tf
|
||||
return
|
||||
|
||||
|
||||
Press_Options(){
|
||||
controller.Buttons.Options.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Options.SetState(false)
|
||||
}
|
||||
|
||||
|
||||
PressX:
|
||||
; Just for menuing, does not hold X down
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
|
||||
PressO:
|
||||
; Just for menuing, does not hold O down
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
|
||||
PressRight:
|
||||
; For turning
|
||||
controller.Dpad.SetState("Right")
|
||||
Sleep, 50
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
PressShare:
|
||||
controller.Buttons.Share.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Share.SetState(false)
|
||||
return
|
||||
|
||||
EndControllerFunctionsDef:
|
||||
@@ -0,0 +1,136 @@
|
||||
/**********************************************
|
||||
* Only place functions here, no sub routines *
|
||||
***********************************************/
|
||||
|
||||
|
||||
; Grabs the colors of the pixels (x-b, y-b) to (x+b, y+b)
|
||||
; returns the array of colors
|
||||
*/
|
||||
|
||||
BitGrab(x, y, b)
|
||||
{
|
||||
HWND := WinExist("PS Remote Play")
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromHWND2(hwnd)
|
||||
|
||||
pixs := []
|
||||
for i in range(-1*b, b+1){
|
||||
for j in range(-1*b, b+1){
|
||||
pixel := Gdip_GetPixel(pBitmap,x+i,y+j)
|
||||
rgb := ConvertARGB( pixel )
|
||||
pixs.Push(rgb)
|
||||
}
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
Gdip_BitmapFromHWND2(hwnd)
|
||||
{
|
||||
WinGetPos,,, Width, Height, ahk_id %hwnd%
|
||||
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
|
||||
RegExMatch(A_OsVersion, "\d+", Version)
|
||||
PrintWindow(hwnd, hdc, Version >= 8 ? 2 : 0)
|
||||
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
|
||||
return pBitmap
|
||||
}
|
||||
|
||||
range(start, stop:="", step:=1) {
|
||||
static range := { _NewEnum: Func("_RangeNewEnum") }
|
||||
if !step
|
||||
throw "range(): Parameter 'step' must not be 0 or blank"
|
||||
if (stop == "")
|
||||
stop := start, start := 0
|
||||
; Formula: r[i] := start + step*i ; r = range object, i = 0-based index
|
||||
; For a postive 'step', the constraints are i >= 0 and r[i] < stop
|
||||
; For a negative 'step', the constraints are i >= 0 and r[i] > stop
|
||||
; No result is returned if r[0] does not meet the value constraint
|
||||
if (step > 0 ? start < stop : start > stop) ;// start == start + step*0
|
||||
return { base: range, start: start, stop: stop, step: step }
|
||||
}
|
||||
|
||||
_RangeNewEnum(r) {
|
||||
static enum := { "Next": Func("_RangeEnumNext") }
|
||||
return { base: enum, r: r, i: 0 }
|
||||
}
|
||||
|
||||
_RangeEnumNext(enum, ByRef k, ByRef v:="") {
|
||||
stop := enum.r.stop, step := enum.r.step
|
||||
, k := enum.r.start + step*enum.i
|
||||
if (ret := step > 0 ? k < stop : k > stop)
|
||||
enum.i += 1
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
Sleep(ms=1)
|
||||
{
|
||||
global timeBeginPeriodHasAlreadyBeenCalled
|
||||
if (timeBeginPeriodHasAlreadyBeenCalled != 1)
|
||||
{
|
||||
DllCall("Winmm.dll\timeBeginPeriod", UInt, 1)
|
||||
timeBeginPeriodHasAlreadyBeenCalled := 1
|
||||
}
|
||||
|
||||
DllCall("Sleep", UInt, ms)
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixelColorSimple(pc_x, pc_y)
|
||||
{
|
||||
WinGet, remotePlay_id, List, ahk_exe RemotePlay.exe
|
||||
if (remotePlay_id = 0)
|
||||
{
|
||||
MsgBox, PS4 Remote Play not found
|
||||
return
|
||||
}
|
||||
if remotePlay_id
|
||||
{
|
||||
pc_wID := remotePlay_id[0]
|
||||
pc_hDC := DllCall("GetDC", "UInt", pc_wID)
|
||||
pc_fmtI := A_FormatInteger
|
||||
SetFormat, IntegerFast, Hex
|
||||
pc_c := DllCall("GetPixel", "UInt", pc_hDC, "Int", pc_x, "Int", pc_y, "UInt")
|
||||
pc_c := pc_c >> 16 & 0xff | pc_c & 0xff00 | (pc_c & 0xff) << 16
|
||||
pc_c .= ""
|
||||
SetFormat, IntegerFast, %pc_fmtI%
|
||||
DllCall("ReleaseDC", "UInt", pc_wID, "UInt", pc_hDC)
|
||||
return pc_c
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GetClientSize(hWnd, ByRef w := "", ByRef h := "")
|
||||
{
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hWnd, "ptr", &rect)
|
||||
w := NumGet(rect, 8, "int")
|
||||
h := NumGet(rect, 12, "int")
|
||||
}
|
||||
|
||||
Distance(c1, c2)
|
||||
{ ; function by [VxE], return value range = [0, 441.67295593006372]
|
||||
return Sqrt((((c1>>16)-(c2>>16))**2)+(((c1>>8&255)-(c2>>8&255))**2)+(((c1&255)-(c1&255))**2))
|
||||
}
|
||||
|
||||
ConvertARGB(ARGB, Convert := 0)
|
||||
{
|
||||
SetFormat, IntegerFast, Hex
|
||||
RGB += ARGB
|
||||
RGB := RGB & 0x00FFFFFF
|
||||
if (Convert)
|
||||
RGB := (RGB & 0xFF000000) | ((RGB & 0xFF0000) >> 16) | (RGB & 0x00FF00) | ((RGB & 0x0000FF) << 16)
|
||||
|
||||
return RGB
|
||||
}
|
||||
|
||||
ToolTipper(msg, x := 100, y := 100)
|
||||
{
|
||||
if (debug_mode = 1)
|
||||
ToolTip, %msg%, x, y, Screen
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
__enableTokyoDetections_mod__ := 1
|
||||
IniRead, color_pitstop1, config.ini, Vars, color_pitstop1, 0
|
||||
IniRead, color_pitstop2, config.ini, Vars, color_pitstop2, 0
|
||||
|
||||
class TokyoTurnContainer
|
||||
{
|
||||
__New(startX, startY, endX := 0, endY := 0)
|
||||
{
|
||||
this.startX := startX
|
||||
this.startY := startY
|
||||
this.endX := endX
|
||||
this.endY := endY
|
||||
}
|
||||
}
|
||||
|
||||
GoTo EndTokyoDetectionsDef
|
||||
|
||||
CheckTokyoMFD(x,y, b_size := 1)
|
||||
{
|
||||
color_dot := 0xD3D2D0
|
||||
TokyoMFD := false
|
||||
tries := 1000 ; we shouldn't need more than 6 tries, but I have seen it loop passed
|
||||
loop {
|
||||
|
||||
tc := BitGrab(x, y, b_size)
|
||||
SB_SetText(" Searching... " td " < 5",2)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_dot)
|
||||
|
||||
if (td < 5){
|
||||
SB_SetText(" Found: " td " < 5",2)
|
||||
TokyoMFD := true
|
||||
break
|
||||
}
|
||||
else {
|
||||
; Gonna try to automate the mfd checker, why not right?
|
||||
if (tries > 0){
|
||||
SB_SetText(" Searching Track/Course Map MFD " td " < 5",2)
|
||||
Press_Left()
|
||||
Sleep(200)
|
||||
tries--
|
||||
break
|
||||
}
|
||||
tries := 1000
|
||||
TokyoMFD := true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
} until TokyoMFD = true
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
CheckTokyoTurn(x,y, b_size := 1)
|
||||
{
|
||||
turnStart := A_TickCount
|
||||
color_player := 0xDE6E70
|
||||
TokyoTurnComplete := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 50",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_player)
|
||||
|
||||
if (td < 50 ){
|
||||
SB_SetText(" Found: " td " < 50",2)
|
||||
TokyoTurnComplete := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run looking for turn. Gonna start with a high number, can adjust lower later.
|
||||
; added some press down, x's and waits just in case we are in the pit stop
|
||||
if (A_TickCount - turnStart > 90000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoTurnComplete = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPen1(x,y, b_size := 1)
|
||||
{
|
||||
pen1Start := A_TickCount
|
||||
|
||||
color_pen := 0xFFC10B
|
||||
TokyoPen1 := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 50",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pen)
|
||||
|
||||
if (td < 50 ){
|
||||
SB_SetText(" Found: " td " < 50",2)
|
||||
TokyoPen1 := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run looking for Pen1. Gonna start with a high number, can adjust lower later.
|
||||
; started with 1.5 mins, i had these set to 3:33 on other file and still won.
|
||||
if (A_TickCount - pen1Start > 90000) {
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoPen1 = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoHairpinTurn(x,y, b_size := 1)
|
||||
{
|
||||
hairpinStart := A_TickCount
|
||||
|
||||
color_hairpinturn := 0xB3B1B2
|
||||
TokyoHairpinTurn := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 5",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_hairpinturn)
|
||||
|
||||
if (td < 5){
|
||||
SB_SetText(" Found: " td " < 5",2)
|
||||
TokyoHairpinTurn := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in hairpin
|
||||
; set to 1 minute to start, I had this at 3:33 (200000) on my other file and still won.
|
||||
if (A_TickCount - hairpinStart > 90000) {
|
||||
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoHairpinTurn = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPen2(x,y, b_size := 1)
|
||||
{
|
||||
start := A_TickCount
|
||||
color_pen := 0xFFC10B
|
||||
RecoveryTried := false
|
||||
TokyoPen2 := false
|
||||
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 60",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pen)
|
||||
|
||||
if (td > 60 ){
|
||||
SB_SetText(" Found: " td " > 60",2)
|
||||
TokyoPen2 := true
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
if (A_TickCount - start > 25000 AND RecoveryTried = false) {
|
||||
SB_SetText(" We stuck? Starting recovery try.",2)
|
||||
Accel_off()
|
||||
controller.Axes.LX.SetState(50)
|
||||
loop 7 {
|
||||
Press_Square(delay:=50)
|
||||
Sleep(100)
|
||||
}
|
||||
Accel_on(80)
|
||||
Sleep(500)
|
||||
loop 9 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(100)
|
||||
}
|
||||
controller.Axes.LX.SetState(30)
|
||||
RecoveryTried := true
|
||||
}
|
||||
|
||||
if (A_TickCount - start > 60000) {
|
||||
gosub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoPen2 = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPenServed(x,y, b_size := 1)
|
||||
{
|
||||
color_penserved := 0xAE1B1E
|
||||
TokyoPenServed := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 60",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_penserved)
|
||||
|
||||
if (td > 60 ){
|
||||
SB_SetText(" Found: " td " > 60",2)
|
||||
TokyoPenServed := true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
} until TokyoPenServed = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPenReceived(x,y, b_size := 1)
|
||||
{
|
||||
start := A_TickCount
|
||||
color_penreceived := 0xAE1B1E
|
||||
TokyoPenReceived := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 40",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_penreceived)
|
||||
|
||||
if (td < 40 ){
|
||||
SB_SetText(" Found: " td " < 40",2)
|
||||
guicontrol,, CurrentLoop, Pen received
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
if (TokyoLapCount != 6 AND A_TickCount - start > 36000)
|
||||
{
|
||||
SB_SetText(" Not found in time. Shifting up.",2)
|
||||
loop 6 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
if (TokyoLapCount = 6 AND A_TickCount - start > 46000)
|
||||
{
|
||||
SB_SetText(" Not found in time. Shifting up.",2)
|
||||
loop 20 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
} until TokyoPenReceived = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPitstopDone(x,y, b_size := 1)
|
||||
{
|
||||
pitstopDoneStart := A_TickCount
|
||||
|
||||
color_pitstopdone := 0xFFFFFF
|
||||
TokyoPitstopDone := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 10",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pitstopdone)
|
||||
|
||||
if (td > 10 ){
|
||||
SB_SetText(" Found: " td " > 10",2)
|
||||
TokyoPitstopDone := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in pit, havent tested if press down works to get us out
|
||||
if (A_TickCount - pitstopDoneStart > 60000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
}
|
||||
} until TokyoPitstopDone = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
{
|
||||
if ( A_TickCount - loopStartTime > maxTime AND TokyoLapCount <= 10) {
|
||||
gosub, ResetRace
|
||||
}
|
||||
else if (A_TickCount - loopStartTime > maxTime+90000 AND TokyoLapCount > 10)
|
||||
{
|
||||
gosub, ResetRace
|
||||
}
|
||||
}
|
||||
|
||||
CheckTokyoPitstop1(x,y, b_size := 1)
|
||||
{
|
||||
pitstop1Start := A_TickCount
|
||||
|
||||
;color_pitstop1 := 0xFFFFFF
|
||||
;color_pitstop1 := 0x818002
|
||||
;color_pitstop1 := 0xFBFB00 ; old color
|
||||
TokyoPitstop := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 10",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pitstop1)
|
||||
|
||||
if (td < 10 ){
|
||||
SB_SetText(" Found: " td " < 10",2)
|
||||
TokyoPitstop := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in pit, havent tested if press down works to get us out
|
||||
if (A_TickCount - pitstop1Start > 60000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
}
|
||||
guicontrol,, CurrentLoop, Stuck in pit? Press GUI Button.
|
||||
|
||||
} until TokyoPitstop = true
|
||||
return
|
||||
}
|
||||
UpdateAVG(racecounter, script_start)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
creditcountersession := (835000*racecounter)/1000000
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditavg := creditcountersession/(A_TickCount-script_start)*3600000
|
||||
guicontrol,, CreditAVG, Avg./h: ~%creditavg% M
|
||||
return
|
||||
}
|
||||
|
||||
UpdateTimer()
|
||||
{
|
||||
ElapsedTime := A_TickCount - script_start
|
||||
VarSetCapacity(t,256),DllCall("GetDurationFormat","uint",2048,"uint",0,"ptr",0,"int64",ElapsedTime*10000,"wstr","d' day(s) 'h':'mm':'ss","wstr",t,"int",256)
|
||||
SB_SetText("Runtime: " t,3)
|
||||
return
|
||||
}
|
||||
|
||||
EndTokyoDetectionsDef:
|
||||
@@ -0,0 +1,86 @@
|
||||
#Include Races\PanAm.ahk
|
||||
#Include Races\Tokyo.ahk
|
||||
|
||||
GoTo EndRaceDef
|
||||
|
||||
Race:
|
||||
|
||||
Switch RaceChoice
|
||||
{
|
||||
case "PanAm":
|
||||
Race_PANAM()
|
||||
return
|
||||
case "Tokyo":
|
||||
Race_Tokyo()
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
SettingsSheet:
|
||||
|
||||
Gui, 4: Show, AutoSize, Settings Sheet
|
||||
;/////////////////////////////////////////////////////////
|
||||
; Add images to your setup here and in the Src folder
|
||||
;
|
||||
;/////////////////////////////////////////////////////////
|
||||
Switch RaceChoice
|
||||
{
|
||||
case "PanAm":
|
||||
|
||||
assist_1 = %A_ScriptDir%\Src\PanAm\Assist1.jpg
|
||||
assist_2 = %A_ScriptDir%\Src\PanAm\Assist2.jpg
|
||||
tune_1 = %A_ScriptDir%\Src\PanAm\CarSetup.jpg
|
||||
tune_2 = %A_ScriptDir%\Src\PanAm\CarGearRatio.jpg
|
||||
controls = %A_ScriptDir%\Src\PanAm\Controller.jpg
|
||||
return
|
||||
case "Tokyo":
|
||||
|
||||
assist_1 = %A_ScriptDir%\Src\Tokyo\Assist_Settings.png
|
||||
assist_2 = %A_ScriptDir%\Src\Tokyo\Misc_Settings.png
|
||||
controls = %A_ScriptDir%\Src\Tokyo\Controller_Settings.png
|
||||
tune_1 = %A_ScriptDir%\Src\Tokyo\Settings_Car1.png
|
||||
tune_2 = %A_ScriptDir%\Src\Tokyo\Settings_Car2.png
|
||||
tune_3 = %A_ScriptDir%\Src\Tokyo\Settings_Car3.png
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
|
||||
Assists1:
|
||||
GuiControl, 4:, CurrentPic, %assist_1%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Assists2:
|
||||
GuiControl, 4:, CurrentPic, %assist_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune1:
|
||||
GuiControl, 4:, CurrentPic, %tune_1%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune2:
|
||||
GuiControl, 4:, CurrentPic, %tune_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune3:
|
||||
GuiControl, 4:, CurrentPic, %tune_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
ControllerSetting:
|
||||
GuiControl, 4:, CurrentPic, %controls%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Guisizer:
|
||||
GuiControl, 4: Move, CurrentPic, % "x" 10 "y" 40 "w" 1200 . " h" . 800
|
||||
Gui, 4: Show, AutoSize, Settings Sheet
|
||||
return
|
||||
|
||||
EndRaceDef:
|
||||
@@ -0,0 +1,494 @@
|
||||
GoTo EndRace_Tokyo_Def
|
||||
|
||||
Race_Tokyo()
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
TokyoStart:
|
||||
;- VARIABLES -----------------------------------------------------------------------------
|
||||
SetFormat, integerfast, d
|
||||
TokyoLapCount := 1
|
||||
maxTime := 200000
|
||||
;- COORDINATES: TURNS --------------------------------------------------------------------
|
||||
TokyoTurn1 := new TokyoTurnContainer(611, 59+remote_play_offsetY, 622, 69+remote_play_offsetY)
|
||||
TokyoTurn2 := new TokyoTurnContainer(618, 70+remote_play_offsetY, 601, 76+remote_play_offsetY)
|
||||
TokyoTurn3 := new TokyoTurnContainer(599, 79+remote_play_offsetY, 591, 87+remote_play_offsetY)
|
||||
TokyoTurn4 := new TokyoTurnContainer(589, 88+remote_play_offsetY, 571, 96+remote_play_offsetY)
|
||||
TokyoTurn5 := new TokyoTurnContainer(567, 96+remote_play_offsetY, 556, 90+remote_play_offsetY)
|
||||
TokyoTurn6 := new TokyoTurnContainer(554, 86+remote_play_offsetY, 543, 82+remote_play_offsetY)
|
||||
TokyoTurn7 := new TokyoTurnContainer(538, 81+remote_play_offsetY, 530, 75+remote_play_offsetY)
|
||||
TokyoTurn8 := new TokyoTurnContainer(530, 75+remote_play_offsetY, 510, 72+remote_play_offsetY)
|
||||
;- COORDINATES: PENALTY WARNINGS ---------------------------------------------------------
|
||||
TokyoPenWarning := new TokyoTurnContainer(360, 154+remote_play_offsetY, 408, 154+remote_play_offsetY)
|
||||
TokyoPenIndicator := new TokyoTurnContainer(366, 132+remote_play_offsetY)
|
||||
;- COORDINATES: HAIRPIN TURN -------------------------------------------------------------
|
||||
TokyoHairpinTurn := new TokyoTurnContainer(606, 334+remote_play_offsetY)
|
||||
;- COORDINATES: PENALTY WARNINGS ---------------------------------------------------------
|
||||
TokyoPen := new TokyoTurnContainer(360, 154+remote_play_offsetY, 408, 154+remote_play_offsetY)
|
||||
TokyoPenServed := new TokyoTurnContainer(366, 132+remote_play_offsetY)
|
||||
;- COORDINATES: HAIRPIN TURN--------------------------------------------------------------
|
||||
TokyoHairpinTurn := new TokyoTurnContainer(606, 334+remote_play_offsetY)
|
||||
;- MISC ----------------------------------------------------------------------------------
|
||||
TokyoPitstop := new TokyoTurnContainer(191, 316+remote_play_offsetY, 580, 383+remote_play_offsetY)
|
||||
TokyoPitstopEnter := new TokyoTurnContainer(530, 70+remote_play_offsetY)
|
||||
TokyoPitstopDone := new TokyoTurnContainer(57, 329+remote_play_offsetY)
|
||||
TokyoRestartRace := new TokyoTurnContainer(405,465+remote_play_offsetY)
|
||||
;- RACE START ----------------------------------------------------------------------------
|
||||
controller.Axes.LX.SetState(65)
|
||||
Sleep(7400)
|
||||
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime%: Race started.`n, logs.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race started.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
|
||||
guicontrol,, CurrentLoop, Race started. Good luck!
|
||||
guicontrol,, CurrentLap, Current Lap: %TokyoLapCount% /12
|
||||
Accel_On(100)
|
||||
loop 3 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
}
|
||||
Sleep(800)
|
||||
controller.Axes.LX.SetState(65)
|
||||
;- 12 LAP LOOP ---------------------------------------------------------------------------
|
||||
loop 12
|
||||
{
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
loopStartTime := A_TickCount
|
||||
; Turn 1
|
||||
location := "T1 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn1.startX, TokyoTurn1.startY)
|
||||
loop 3 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
}
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(36)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
Sleep(1000)
|
||||
location := "T1 End"
|
||||
CheckTokyoTurn(TokyoTurn1.endX, TokyoTurn1.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(35)
|
||||
Sleep(1000)
|
||||
; Turn 2
|
||||
location := "T2 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn2.startX, TokyoTurn2.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(52)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
Sleep(1000)
|
||||
location := "T2 End"
|
||||
CheckTokyoTurn(TokyoTurn2.endX, TokyoTurn2.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Turn 3
|
||||
location := "T3 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn3.startX, TokyoTurn3.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
controller.Axes.LX.SetState(40)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn3.endX, TokyoTurn3.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
; Turn 4
|
||||
location := "T4 Start"
|
||||
Accel_On(85)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn4.startX, TokyoTurn4.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
controller.Axes.LX.SetState(68)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn4.endX, TokyoTurn4.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(60)
|
||||
Accel_On(70)
|
||||
Sleep(1000)
|
||||
; Turn 5
|
||||
location := "T5 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn5.startX, TokyoTurn5.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(42)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn5.endX, TokyoTurn5.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(63)
|
||||
Sleep(1000)
|
||||
; Turn 6
|
||||
location := "T6 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn6.startX, TokyoTurn6.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
Accel_on(75)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn6.endX, TokyoTurn6.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Turn 7
|
||||
location := "T7 Start"
|
||||
Accel_On(100)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn7.startX, TokyoTurn7.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn7.endX, TokyoTurn7.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
; Turn 8
|
||||
location := "T8 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn8.startX, TokyoTurn8.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(65)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn8.endX, TokyoTurn8.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(30)
|
||||
Sleep(2000)
|
||||
Brake_on(100)
|
||||
Sleep(2200)
|
||||
Brake_off()
|
||||
Accel_On(35)
|
||||
; Penalty Warning 1
|
||||
location := "Hairpin Entrance"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPen1(TokyoPenWarning.startX, TokyoPenWarning.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Accel_On(32)
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Hairpin Turn
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
location := "Hairpin Turn"
|
||||
CheckTokyoHairpinTurn(TokyoHairpinTurn.startX, TokyoHairpinTurn.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(hairpin_delay)
|
||||
controller.Axes.LX.SetState(100)
|
||||
Sleep(200)
|
||||
Accel_Off()
|
||||
Sleep(4200)
|
||||
Accel_On(45) ;was 40
|
||||
controller.Axes.LX.SetState(60)
|
||||
Accel_Off()
|
||||
Sleep(800)
|
||||
controller.Axes.LX.SetState(40)
|
||||
Accel_On(50)
|
||||
Sleep(5000)
|
||||
controller.Axes.LX.SetState(30)
|
||||
Sleep(5500)
|
||||
Accel_On(80)
|
||||
loop 30 { ; failsafe, if we ever get a reset caused by a cone under the car
|
||||
Press_Triangle(delay:=100)
|
||||
Sleep(200)
|
||||
}
|
||||
; Penalty Warning 2
|
||||
location := "Hairpin exit"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPen2(TokyoPen.endX, TokyoPen.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
if (TokyoLapCount <= 11)
|
||||
{
|
||||
|
||||
location := "Pit entrance"
|
||||
Accel_On(53)
|
||||
controller.Axes.LX.SetState(30)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoPitstopEnter.startX, TokyoPitstopEnter.startY)
|
||||
controller.Axes.LX.SetState(0)
|
||||
Accel_On(55)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPitstop1(TokyoPitstop.startX, TokyoPitstop.startY)
|
||||
location := "In pit"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(50)
|
||||
|
||||
if (TokyoLapCount = 1)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap01timing := 0
|
||||
location := "In pit: Waiting " lap01timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap01timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 2)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap02timing := 0
|
||||
location := "In pit: Waiting " lap02timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap02timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 3)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap03timing := 0
|
||||
location := "In pit: Waiting " lap03timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap03timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 4)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap04timing := 0
|
||||
location := "In pit: Waiting " lap04timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap04timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 5)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap05timing := 20000
|
||||
location := "In pit: Waiting " lap05timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap05timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 6)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap06timing := 0
|
||||
location := "In pit: Waiting " lap06timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap06timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 7)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap07timing := 0
|
||||
location := "In pit: Waiting " lap07timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap07timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 8)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap08timing := 0
|
||||
location := "In pit: Waiting " lap08timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap08timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 9)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap09timing := 12000
|
||||
location := "In pit: Waiting " lap09timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap09timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 10)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap10timing := 20000
|
||||
location := "In pit: Waiting " lap10timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap10timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 11)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap11timing := 0
|
||||
location := "In pit: Waiting " lap11timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap11timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 12)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
lap12timing := 0
|
||||
location := "In pit: Waiting " lap12timing " Seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (lap12timing)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
controller.Axes.LX.SetState(20)
|
||||
Accel_On(100)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPenReceived(TokyoPenServed.startX, TokyoPenServed.startY)
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(38)
|
||||
Sleep (500)
|
||||
loop 10 {
|
||||
Press_Triangle(delay:=200)
|
||||
sleep, 200
|
||||
}
|
||||
}
|
||||
else {
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Accel_On(100)
|
||||
controller.Axes.LX.SetState(60)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPenServed(TokyoPenServed.startX, TokyoPenServed.startY)
|
||||
}
|
||||
SetFormat, integerfast, d
|
||||
TokyoLapCount++
|
||||
guicontrol,, CurrentLap, Current Lap: %TokyoLapCount% /12
|
||||
ProgressRace := (100/13)*TokyoLapCount
|
||||
guicontrol,, RaceProgress, %ProgressRace%
|
||||
|
||||
if(TokyoLapCount = "13")
|
||||
{
|
||||
location := "Finish line"
|
||||
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime% Race finished.`n, logs.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race finished.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
guicontrol,, CurrentLap, GG!
|
||||
controller.Axes.LX.SetState(50)
|
||||
SetFormat, integerfast, d
|
||||
racecounter++
|
||||
SetFormat, integerfast, d
|
||||
racecountertotal++
|
||||
|
||||
; // THIS SESSION
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountersession := (835000*racecounter)/1000000
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditavg := creditcountersession/(A_TickCount-script_start)*3600000
|
||||
guicontrol,, RaceCounterSession, Races completed: %racecounter%
|
||||
guicontrol,, ResetCounterSession, Races failed: %resetcounter%
|
||||
guicontrol,, CreditCounterSession, Credits: %creditcountersession% M
|
||||
guicontrol,, CreditAVGSession, Avg./h: %creditavg% M
|
||||
|
||||
; // ALL TIME
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountertotal := (835000*racecountertotal)/1000000
|
||||
IniWrite, %racecountertotal%, config.ini,Stats, RaceCounterTotal
|
||||
IniWrite, %resetcountertotal%, config.ini,Stats, ResetCounterTotal
|
||||
guicontrol,, RaceCounterTotal, Races completed: %racecountertotal%
|
||||
guicontrol,, ResetCounterTotal, Races failed: %resetcountertotal%
|
||||
guicontrol,, CreditCounterTotal, Credits: %creditcountertotal% M
|
||||
UpdateAVG(racecounter, script_start)
|
||||
lapcounter =
|
||||
ProgressRace =
|
||||
guicontrol,, RaceProgress, %ProgressRace%
|
||||
loop
|
||||
{
|
||||
restart_found := false
|
||||
c2 := BitGrab(162, 43+remote_play_offsetY, 2)
|
||||
for i, c in c2
|
||||
{
|
||||
d2 := Distance(c, color_restart)
|
||||
SB_SetText(" Searching... " d2 " < 50",2)
|
||||
if (d2 < 10 )
|
||||
{
|
||||
SB_SetText(" Found: Restart Color",2)
|
||||
restart_found := true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (restart_found)
|
||||
break
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
|
||||
}
|
||||
SB_SetText("Found: Restart Color",2)
|
||||
Sleep(260)
|
||||
Press_O()
|
||||
Sleep(200)
|
||||
Press_Right()
|
||||
Sleep(3000)
|
||||
Press_X()
|
||||
Sleep(4000)
|
||||
Press_X()
|
||||
Sleep(4000)
|
||||
guicontrol,, CurrentLoop, Setting up next race.
|
||||
Press_Options()
|
||||
Sleep(1000)
|
||||
Press_Right()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
controller.Axes.LX.SetState(50)
|
||||
UpdateAVG(racecounter, script_start)
|
||||
Goto, TokyoStart
|
||||
}
|
||||
}
|
||||
}
|
||||
EndRace_Tokyo_Def:
|
||||
|
After Width: | Height: | Size: 744 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,498 @@
|
||||
#Persistent
|
||||
#NoEnv
|
||||
#MaxHotkeysPerInterval 99000000
|
||||
#HotkeyInterval 99000000
|
||||
#KeyHistory 0
|
||||
#Include Lib\Gdip.ahk
|
||||
#Include Lib\AHK-ViGEm-Bus.ahk
|
||||
#Include Lib\__utility__.ahk
|
||||
#Include Lib\__controller_functions__.ahk
|
||||
#Include Mod\TokyoDetections.ahk
|
||||
#Include Races\Tokyo.ahk
|
||||
|
||||
hModule := DllCall("LoadLibrary", "Str", A_LineFile "\..\Lib\SuperSleep.dll", "Ptr")
|
||||
SuperSleep := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", A_LineFile "\..\Lib\SuperSleep.dll", "Ptr"), "AStr", "super_sleep", "Ptr")
|
||||
|
||||
ListLines Off
|
||||
Process, Priority, , A
|
||||
SetBatchLines, -1
|
||||
SetKeyDelay, -1, -1
|
||||
SetMouseDelay, -1
|
||||
SetDefaultMouseSpeed, 0
|
||||
SendMode Input
|
||||
|
||||
SetWorkingDir %A_ScriptDir%
|
||||
DetectHiddenWindows, On
|
||||
#Persistent
|
||||
|
||||
Global script_start := A_TickCount
|
||||
Global remote_play_offsetY := 71
|
||||
Global racecounter := 0
|
||||
Global resetcounter := 0
|
||||
Global color_pitstop1 := 0xFFFFFF
|
||||
Global color_restart := 0x6D5223
|
||||
Global hairpin_delay := 0
|
||||
Global PitstopTimings := 0
|
||||
Global TelegramBotToken := ""
|
||||
Global TelegramChatID := ""
|
||||
Global location := ""
|
||||
Global TokyoLapCount := 1
|
||||
Global PitstopTimingsArray :=
|
||||
Global DynTurnDelay := 0
|
||||
Global SaveResetClip := 0
|
||||
SetFormat, integerfast, d
|
||||
ps_win_width := 640
|
||||
ps_win_height := 360
|
||||
IniRead, hairpin_delay, config.ini, Vars, hairpin_delay, 0
|
||||
IniRead, color_pitstop1, config.ini, Vars, color_pitstop1, 0
|
||||
IniRead, RaceCounterTotal, config.ini, Stats, racecountertotal, 0
|
||||
IniRead, ResetCounterTotal, config.ini, Stats, resetcountertotal, 0
|
||||
IniRead, TelegramBotToken, config.ini, API, TelegramBotToken, 0
|
||||
IniRead, TelegramChatID, config.ini, API, TelegramChatID, 0
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings0, 0
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
|
||||
IniRead, DynTurnDelay, config.ini, Vars, DynTurnDelay, 0
|
||||
IniRead, SaveResetClip, config.ini, Vars, SaveResetClip, 0
|
||||
|
||||
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountertotal := 835000*racecountertotal/1000000
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
|
||||
Global controller := new ViGEmDS4()
|
||||
controller.SubscribeFeedback(Func("OnFeedback"))
|
||||
OnFeedback(largeMotor, smallMotor, lightbarColor){
|
||||
}
|
||||
|
||||
;- GUI 1 (MAIN) -------------------------------------------------------------------------------------------------
|
||||
Icon = Assets\GT7_Tokyo.ico
|
||||
Menu, Tray, Icon, %Icon%
|
||||
Gui, -Caption
|
||||
Gui, Add, Picture, x0 y0 w650 h207 , Assets\tokyo_gui.png
|
||||
Gui, Add, Button, x222 y82 w410 h80 default gButtonStart, START
|
||||
Gui, Add, Progress, x0 y54 w641 h12 RaceProgress vRaceProgress -Smooth, 0
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x440 y3 w160 h20 RaceCounterTotal +BackgroundTrans, // ALL TIME
|
||||
Gui, Font, ,
|
||||
Gui, Add, Text, x440 y23 w160 h20 RaceCounterTotal vracecountertotal +BackgroundTrans, Races completed: %racecountertotal%
|
||||
Gui, Add, Text, x440 y38 w160 h20 ResetCounterTotal vresetcountertotal +BackgroundTrans, Races failed: %resetcountertotal%
|
||||
Gui, Add, Text, x550 y38 w160 h20 CreditCounterTotal vcreditcountertotal +BackgroundTrans, Credits: %creditcountertotal% M
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x220 y3 w300 h20 RaceSession vracesession +BackgroundTrans, // SESSION
|
||||
Gui, Font, ,
|
||||
Gui, Add, Text, x220 y23 w160 h20 RaceCounterSession vracecountersession +BackgroundTrans, Races completed: 0
|
||||
Gui, Add, Text, x220 y38 w160 h20 ResetCounterSession vresetcountersession +BackgroundTrans, Races failed: 0
|
||||
Gui, Add, Text, x330 y23 w160 h20 CreditCounterSession vcreditcountersession +BackgroundTrans, Credits: 0
|
||||
Gui, Add, Text, x330 y38 w160 h20 CreditAVG vcreditavg +BackgroundTrans, Avg./h: 0
|
||||
Gui, Add, Text, x10 y38 w150 h20 CounterLap vcurrentlap +BackgroundTrans, Current Lap: 0/12
|
||||
Gui, Add, Text, x10 y23 w220 h20 CurrentLoop vcurrentloop +BackgroundTrans, Current Location: -
|
||||
Gui, Add, Button, x222 y172 w300 h20 default gGUIReset, Reset
|
||||
Gui, Add, Button, x531 y172 w101 h20 default gGUIClose, Exit
|
||||
Gui, Add, Button, x12 y82 w200 h20 default gRaceSettingsWindow, Settings: Race
|
||||
Gui, Add, Button, x12 y112 w200 h20 default gMachineSettingsWindow, Settings: Machine/Setup
|
||||
Gui, Add, Button, x12 y142 w200 h20 default gIngameSettingsWindow, Settings: Ingame (wip)
|
||||
Gui, Add, Button, x12 y172 w200 h20 default gNotificationsWindow, Settings: Notifications/API
|
||||
Gui, Font, S8 CDefault Bold, Verdana
|
||||
Gui, Add, Text, x10 y3 w620 h20 +BackgroundTrans, // TOKYO CONTROL CENTER
|
||||
Gui, Add, Statusbar, -Theme Backgroundeeeeee ;#eeeeee, no typo
|
||||
SB_SetParts(80,270,190)
|
||||
SB_SetText(" beta 9.4 ",1)
|
||||
SB_SetText(" by problemz.",4)
|
||||
Gui, Show, x8 y532 h225 w640, GT7 Tokyo // by problemz
|
||||
guicontrol,, CurrentLoop, Press START, go go!
|
||||
;- GUI 2 (MACHINE/SETUP) ----------------------------------------------------------------------------------------
|
||||
;Gui, 2: Add, Picture, x0 y0 w650 h500 , Assets\tokyo_gui.png
|
||||
Gui, 2: Add, Text, x10 y14 w200 h20 +BackgroundTrans , Hairpin Turn Delay:
|
||||
Gui, 2: Add, Text, x170 y14 w200 h20 +BackgroundTrans , (ms)
|
||||
Gui, 2: Add, Slider, x220 y10 w300 h51 vsliderhairpindelay Range0-800 Thick40 +ToolTip TickInterval50 gSliderMove,%hairpin_delay%
|
||||
Gui, 2: Add, Edit, x106 y11 w60 vtxthairpindelay gtextchanged, %hairpin_delay%
|
||||
Gui, 2: Add, Text, x10 y40 w200 h20 +BackgroundTrans , Lower = slower PC // Higher = faster PC
|
||||
Gui, 2: Add, Button, x530 y11 w100 h73 +BackgroundTrans gSaveToIni, Save
|
||||
Gui, 2: Add, Button, x10 y103 w200 h40 gPit1Color, Stuck in pit `n(Only click when at tire selection menu)
|
||||
Gui, 2: Add, Checkbox, x320 y110 w300 gDynTurnDelay vDynTurnDelay +BackgroundTrans Checkbox Checked%DynTurnDelay%, Experimental: Use dynamic hairpin turn delays.
|
||||
Gui, 2: Add, Checkbox, x320 y130 w300 gSaveResetClip vSaveResetClip +BackgroundTrans Checkbox Checked%SaveResetClip%, Experimental: Save clip (past 3 minutes) after a reset.
|
||||
|
||||
;- GUI 3 (INGAME) -----------------------------------------------------------------------------------------------
|
||||
;Gui, 3: Add, Picture, x0 y0 w650 h177 , Assets\tokyo_gui.png
|
||||
;- GUI 4 (RACE SETTINGS) ----------------------------------------------------------------------------------------
|
||||
;Gui, 4: Add, Picture, x0 y0 w650 h450 , Assets\tokyo_gui.png
|
||||
Gui, 4: Font, S8 CDefault Bold, Verdana
|
||||
Gui, 4: Add, Text, x220 y20 w200 h20 vFightme +gFightMe +BackgroundTrans , ლ(`ー´ლ)
|
||||
Gui, 4: Add, Text, x30 y10 w200 h50 +BackgroundTrans vPitstopText , Pit stop wait timers in ms`n(Read-only):
|
||||
Gui, 4: Font, ,
|
||||
Gui, 4: Add, Text, xp yp+40 w100 h20 +BackgroundTrans , Lap 1:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray1, %PitstopTimingsArray1%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 2:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray2, %PitstopTimingsArray2%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 3:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray3, %PitstopTimingsArray3%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 4:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray4, %PitstopTimingsArray4%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 5:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray5, %PitstopTimingsArray5%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 6:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray6, %PitstopTimingsArray6%
|
||||
Gui, 4: Add, Text, xp-540 yp+30 w100 h20 +BackgroundTrans , Lap 7:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray7, %PitstopTimingsArray7%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 8:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray8, %PitstopTimingsArray8%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 9:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray9, %PitstopTimingsArray9%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 10:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray10, %PitstopTimingsArray10%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 11:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
Gui, 4: Add, Text, xp+60 yp+3 w100 h20 +BackgroundTrans , Lap 12:
|
||||
Gui, 4: Add, Edit, +ReadOnly xp+40 yp-3 w50 vNewPitstopTimingsArray12, %PitstopTimingsArray12%
|
||||
Gui, 4: Add, Button, +hidden xp-540 yp+30 w590 h25 vNewPitstopTimingsButton gSaveNewTimings, Save pit stop timings
|
||||
Gui, 4: Font, S8 CDefault Bold, Verdana
|
||||
Gui, 4: Add, Text, x370 y10 w120 h20 +BackgroundTrans , Select Race pace:
|
||||
Gui, 4: Font, ,
|
||||
Gui, 4: Add, DropDownList, xp+125 yp-3 w125 vRacePaceChoice gRacePaceChoice, Select to change||Safe (slower)|Risky (faster)
|
||||
Gui, 4: Add, Button, +hidden x230 yp+10 w120 h25 vLoadDevTimings gLoadDevTimings, Load last dev timings
|
||||
|
||||
;- GUI 5 (NOTIFICATIONS/API) ------------------------------------------------------------------------------------
|
||||
;Gui, 5: Add, Picture, x0 y0 w650 h400 , Assets\tokyo_gui.png
|
||||
Gui, 5: Add, Text, x10 y14 w205 h20 +BackgroundTrans , Telegram Bot Token:
|
||||
Gui, 5: Add, Edit, x116 y11 w400 vTelegramBotToken Password, %TelegramBotToken%
|
||||
Gui, 5: Add, Text, x10 y44 w205 h20 +BackgroundTrans , Telegram Chat ID:
|
||||
Gui, 5: Add, Edit, x116 y41 w400 vTelegramChatID Password, %TelegramChatID%
|
||||
Gui, 5: Add, Button, x530 y11 w100 h51 +BackgroundTrans gSaveToIni, Save
|
||||
Return
|
||||
|
||||
DynTurnDelay:
|
||||
return
|
||||
|
||||
SaveResetClip:
|
||||
return
|
||||
|
||||
MachineSettingsWindow:
|
||||
|
||||
if (GetKeyState("LShift", "P") AND GetKeyState("LAlt", "P")){
|
||||
goto, MouseColor
|
||||
}
|
||||
else{
|
||||
Gui, 2: Show, x6 y757 w639 h150, Settings: Machine/Setup
|
||||
}
|
||||
return
|
||||
|
||||
IngameSettingsWindow:
|
||||
Gui, 3: Show, x6 y757 w639 h35, Settings: Ingame
|
||||
return
|
||||
|
||||
RaceSettingsWindow:
|
||||
Gui, 4: Show, x6 y757 w639 h140, Settings: Race
|
||||
return
|
||||
|
||||
NotificationsWindow:
|
||||
Gui, 5: Show, x6 y757 w639 h70, Settings: Notifications/API
|
||||
return
|
||||
|
||||
SliderMove:
|
||||
Gui, Submit, nohide
|
||||
GuiControl,, txthairpindelay, %sliderhairpindelay%
|
||||
Return
|
||||
|
||||
SaveToIni:
|
||||
Gui, Submit, Hide
|
||||
IniWrite, %txthairpindelay%, config.ini,Vars, hairpin_delay
|
||||
IniWrite, %TelegramBotToken%, config.ini,API, TelegramBotToken
|
||||
IniWrite, %TelegramChatID%, config.ini,API, TelegramChatID
|
||||
GuiControlGet, DynTurnDelay,,DynTurnDelay
|
||||
IniWrite, %DynTurnDelay%, config.ini,VARS, DynTurnDelay
|
||||
GuiControlGet, SaveResetClip,,SaveResetClip
|
||||
IniWrite, %SaveResetClip%, config.ini,VARS, SaveResetClip
|
||||
return
|
||||
|
||||
SaveNewTimings:
|
||||
MsgBox, 4,, Do you really wanna save new pitstop timings?
|
||||
IfMsgBox Yes
|
||||
{
|
||||
Gui, Submit, NoHide
|
||||
NewPitStopTimings = %NewPitstopTimingsArray1%`,%NewPitstopTimingsArray2%`,%NewPitstopTimingsArray3%`,%NewPitstopTimingsArray4%`,%NewPitstopTimingsArray5%`,%NewPitstopTimingsArray6%`,%NewPitstopTimingsArray7%`,%NewPitstopTimingsArray8%`,%NewPitstopTimingsArray9%`,%NewPitstopTimingsArray10%`,%NewPitstopTimingsArray11%`,%NewPitstopTimingsArray12%
|
||||
IniWrite, %NewPitStopTimings%, config.ini,VARS, PitStopTimings0
|
||||
IniWrite, %NewPitStopTimings%, config.ini,VARS, PitStopTimings99
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings0, 0
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
}
|
||||
return
|
||||
|
||||
|
||||
RacePaceChoice:
|
||||
Gui, Submit, NoHide
|
||||
If (RacePaceChoice = "Safe (slower)")
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings1, 0
|
||||
IniWrite, %PitstopTimings%, config.ini,VARS, PitStopTimings0
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings0, 0
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
guicontrol,, NewPitstopTimingsArray1, %PitstopTimingsArray1%
|
||||
guicontrol,, NewPitstopTimingsArray2, %PitstopTimingsArray2%
|
||||
guicontrol,, NewPitstopTimingsArray3, %PitstopTimingsArray3%
|
||||
guicontrol,, NewPitstopTimingsArray4, %PitstopTimingsArray4%
|
||||
guicontrol,, NewPitstopTimingsArray5, %PitstopTimingsArray5%
|
||||
guicontrol,, NewPitstopTimingsArray6, %PitstopTimingsArray6%
|
||||
guicontrol,, NewPitstopTimingsArray7, %PitstopTimingsArray7%
|
||||
guicontrol,, NewPitstopTimingsArray8, %PitstopTimingsArray8%
|
||||
guicontrol,, NewPitstopTimingsArray9, %PitstopTimingsArray9%
|
||||
guicontrol,, NewPitstopTimingsArray10, %PitstopTimingsArray10%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
|
||||
If (RacePaceChoice = "Risky (faster)")
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings2, 0
|
||||
IniWrite, %PitstopTimings%, config.ini,VARS, PitStopTimings0
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings0, 0
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
guicontrol,, NewPitstopTimingsArray1, %PitstopTimingsArray1%
|
||||
guicontrol,, NewPitstopTimingsArray2, %PitstopTimingsArray2%
|
||||
guicontrol,, NewPitstopTimingsArray3, %PitstopTimingsArray3%
|
||||
guicontrol,, NewPitstopTimingsArray4, %PitstopTimingsArray4%
|
||||
guicontrol,, NewPitstopTimingsArray5, %PitstopTimingsArray5%
|
||||
guicontrol,, NewPitstopTimingsArray6, %PitstopTimingsArray6%
|
||||
guicontrol,, NewPitstopTimingsArray7, %PitstopTimingsArray7%
|
||||
guicontrol,, NewPitstopTimingsArray8, %PitstopTimingsArray8%
|
||||
guicontrol,, NewPitstopTimingsArray9, %PitstopTimingsArray9%
|
||||
guicontrol,, NewPitstopTimingsArray10, %PitstopTimingsArray10%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
return
|
||||
|
||||
TextChanged:
|
||||
guiControlGet, txtvar,, txthairpindelay
|
||||
if (txtvar > 800)
|
||||
{
|
||||
GuiControl,, txthairpindelay, 800
|
||||
}
|
||||
|
||||
GuiControl,, sliderhairpindelay, %txtvar%
|
||||
return
|
||||
|
||||
Pit1Color:
|
||||
MsgBox, 4,, Do you really wanna set a new Pitstop color?
|
||||
IfMsgBox Yes
|
||||
{
|
||||
gosub, GrabRemotePlay
|
||||
color_pitstop1 := PixelColorSimple(199, 315+remote_play_offsetY)
|
||||
IniWrite, %color_pitstop1%, config.ini,Vars, color_pitstop1
|
||||
}
|
||||
return
|
||||
|
||||
ButtonStart:
|
||||
SetTimer, UpdateTimer, 1000
|
||||
Gui, Submit, NoHide
|
||||
id := ""
|
||||
SetKeyDelay, 10
|
||||
Process, priority, , High
|
||||
gosub, GrabRemotePlay
|
||||
if (id = "")
|
||||
return
|
||||
gosub, PauseLoop
|
||||
CoordMode, Pixel, Screen
|
||||
CoordMode, ToolTip, Screen
|
||||
loop {
|
||||
Press_X()
|
||||
Race_Tokyo()
|
||||
}
|
||||
|
||||
PixelTuning:
|
||||
x_ratio := ps_win_width/640
|
||||
y_ratio := ps_win_height/360
|
||||
return
|
||||
|
||||
GrabRemotePlay:
|
||||
WinGet, remotePlay_id, List, ahk_exe RemotePlay.exe
|
||||
if (remotePlay_id = 0)
|
||||
{
|
||||
MsgBox, PS4 Remote Play not found
|
||||
return
|
||||
}
|
||||
Loop, %remotePlay_id%
|
||||
{
|
||||
id := remotePlay_id%A_Index%
|
||||
WinGetTitle, title, % "ahk_id " id
|
||||
If InStr(title, "PS Remote Play")
|
||||
break
|
||||
}
|
||||
WinMove, ahk_id %id%,, 0, 0, 640, 540
|
||||
|
||||
ControlFocus,, ahk_class %remotePlay_class%
|
||||
WinActivate, ahk_id %id%
|
||||
GetClientSize(remotePlay_id5, ps_win_width, ps_win_height)
|
||||
gosub, PixelTuning
|
||||
return
|
||||
|
||||
FightMe:
|
||||
if (A_GuiEvent = "DoubleClick")
|
||||
{
|
||||
guicontrol, -readonly, NewPitstopTimingsArray1
|
||||
guicontrol, -readonly, NewPitstopTimingsArray2
|
||||
guicontrol, -readonly, NewPitstopTimingsArray3
|
||||
guicontrol, -readonly, NewPitstopTimingsArray4
|
||||
guicontrol, -readonly, NewPitstopTimingsArray5
|
||||
guicontrol, -readonly, NewPitstopTimingsArray6
|
||||
guicontrol, -readonly, NewPitstopTimingsArray7
|
||||
guicontrol, -readonly, NewPitstopTimingsArray8
|
||||
guicontrol, -readonly, NewPitstopTimingsArray9
|
||||
guicontrol, -readonly, NewPitstopTimingsArray10
|
||||
guicontrol, -readonly, NewPitstopTimingsArray11
|
||||
guicontrol, -readonly, NewPitstopTimingsArray12
|
||||
guicontrol, -hidden, NewPitstopTimingsButton
|
||||
guicontrol, -hidden, LoadDevTimings
|
||||
guicontrol,, PitstopText, Pit stop wait timers in ms`ndevmode unlocked ლ(`ー´ლ):
|
||||
guicontrol, +hidden, FightMe
|
||||
}
|
||||
return
|
||||
|
||||
LoadDevTimings:
|
||||
IniRead, PitstopTimings, config.ini, Vars, PitStopTimings99, 0
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
guicontrol,, NewPitstopTimingsArray1, %PitstopTimingsArray1%
|
||||
guicontrol,, NewPitstopTimingsArray2, %PitstopTimingsArray2%
|
||||
guicontrol,, NewPitstopTimingsArray3, %PitstopTimingsArray3%
|
||||
guicontrol,, NewPitstopTimingsArray4, %PitstopTimingsArray4%
|
||||
guicontrol,, NewPitstopTimingsArray5, %PitstopTimingsArray5%
|
||||
guicontrol,, NewPitstopTimingsArray6, %PitstopTimingsArray6%
|
||||
guicontrol,, NewPitstopTimingsArray7, %PitstopTimingsArray7%
|
||||
guicontrol,, NewPitstopTimingsArray8, %PitstopTimingsArray8%
|
||||
guicontrol,, NewPitstopTimingsArray9, %PitstopTimingsArray9%
|
||||
guicontrol,, NewPitstopTimingsArray10, %PitstopTimingsArray10%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
guicontrol,, NewPitstopTimingsArray11, %PitstopTimingsArray11%
|
||||
return
|
||||
|
||||
PauseLoop:
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
controller.Buttons.Square.SetState(false)
|
||||
controller.Buttons.Triangle.SetState(false)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
controller.Buttons.L1.SetState(false)
|
||||
controller.Buttons.L2.SetState(false)
|
||||
controller.Axes.L2.SetState(0)
|
||||
controller.Buttons.R1.SetState(false)
|
||||
controller.Buttons.R2.SetState(false)
|
||||
controller.Axes.R2.SetState(0)
|
||||
controller.Buttons.RS.SetState(false)
|
||||
controller.Axes.RX.SetState(50)
|
||||
controller.Axes.RY.SetState(50)
|
||||
controller.Buttons.LS.SetState(false)
|
||||
controller.Axes.LX.SetState(50)
|
||||
controller.Axes.LY.SetState(50)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
|
||||
ResetRace:
|
||||
|
||||
|
||||
|
||||
SB_SetText(" - RESET INITIATED -",2)
|
||||
guicontrol,, CurrentLoop, Something went wrong, reseting.
|
||||
controller.Axes.LX.SetState(50)
|
||||
|
||||
if(SaveResetClip)
|
||||
{
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime%: Race failed - Lap %TokyoLapCount% - %location% - Clip saved.`n, log.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race failed - Lap " TokyoLapCount " - " location ". Clip saved.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
SB_SetText(" Saving clip (past 3 minutes)...",2)
|
||||
Sleep(500)
|
||||
PressShare()
|
||||
Sleep(1000)
|
||||
Press_Left()
|
||||
Sleep(200)
|
||||
Press_X()
|
||||
Sleep(200)
|
||||
Press_X()
|
||||
Sleep(200)
|
||||
Press_Down()
|
||||
Sleep(200)
|
||||
Press_Down()
|
||||
Sleep(200)
|
||||
Press_Down()
|
||||
Sleep(200)
|
||||
Press_X()
|
||||
Sleep(1000)
|
||||
PressShare()
|
||||
Sleep(1000)
|
||||
Press_O()
|
||||
Sleep(200)
|
||||
Press_Right()
|
||||
Sleep(200)
|
||||
Press_X()
|
||||
}
|
||||
else {
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime%: Race failed - Lap %TokyoLapCount% - %location%.`n, log.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race failed - Lap " TokyoLapCount " - " location ". Clip saved.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
SB_SetText(" Saving clip (past 3 minutes)...",2)
|
||||
Sleep(500)
|
||||
Press_Options()
|
||||
Sleep(1000)
|
||||
Press_Right()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
}
|
||||
controller.Axes.LX.SetState(65)
|
||||
IniRead, ResetCounterTotal, config.ini, Stats, resetcountertotal, 0
|
||||
SetFormat, integerfast, d
|
||||
resetcounter++
|
||||
resetcountertotal++
|
||||
IniWrite, %resetcountertotal%, config.ini,Stats, ResetCounterTotal
|
||||
guicontrol,, ResetCounterTotal, Races failed: %resetcountertotal%
|
||||
guicontrol,, ResetCounterSession, Races failed: %resetcounter%
|
||||
guicontrol,, RaceProgress, 0
|
||||
Race_Tokyo()
|
||||
return
|
||||
|
||||
|
||||
MouseHelp:
|
||||
|
||||
coord=relative
|
||||
sleep, 1000
|
||||
CoordMode, ToolTip, %coord%
|
||||
CoordMode, Pixel, %coord%
|
||||
CoordMode, Mouse, %coord%
|
||||
CoordMode, Caret, %coord%
|
||||
CoordMode, Menu, %coord%
|
||||
return
|
||||
|
||||
Refresh:
|
||||
MouseGetPos, x, y
|
||||
PixelGetColor, cBGR, %x%, %y%,, Alt RGB
|
||||
WinGetPos,,, w, h, A
|
||||
ToolTip,Location: %x% x %y%`nRGB: %cBGR%`nWindow Size: %w% x %h%
|
||||
return
|
||||
|
||||
MouseColor:
|
||||
gosub, MouseHelp
|
||||
SetTimer, Refresh, 75
|
||||
return
|
||||
|
||||
GuiClose:
|
||||
gosub, PauseLoop
|
||||
ExitApp
|
||||
^Esc::ExitApp
|
||||
|
||||
GUIReset:
|
||||
if (GetKeyState("LShift", "P") AND GetKeyState("LAlt", "P")){
|
||||
MsgBox, 4,, Reset all data?
|
||||
IfMsgBox Yes
|
||||
{
|
||||
IniWrite, 0, config.ini,Stats, RaceCounterTotal
|
||||
IniWrite, 0, config.ini,Stats, ResetCounterTotal
|
||||
}
|
||||
}
|
||||
Sleep(500)
|
||||
gosub, PauseLoop
|
||||
Reload
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
#include %A_LineFile%\..\CLR.ahk
|
||||
|
||||
; Static class, holds ViGEm Client instance
|
||||
class ViGEmWrapper {
|
||||
static asm := 0
|
||||
static client := 0
|
||||
|
||||
Init(){
|
||||
if (this.client == 0){
|
||||
this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
}
|
||||
}
|
||||
|
||||
CreateInstance(cls){
|
||||
return this.asm.CreateInstance(cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
; Base class for ViGEm "Targets" (Controller types - eg xb360 / ds4) to inherit from
|
||||
class ViGEmTarget {
|
||||
target := 0
|
||||
helperClass := ""
|
||||
controllerClass := ""
|
||||
|
||||
__New(){
|
||||
;~ this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
ViGEmWrapper.Init()
|
||||
this.Instance := ViGEmWrapper.CreateInstance(this.helperClass)
|
||||
|
||||
if (this.Instance.OkCheck() != "OK"){
|
||||
msgbox ViGEmWrapper.dll failed to load!
|
||||
ExitApp
|
||||
}
|
||||
}
|
||||
|
||||
SendReport(){
|
||||
this.Instance.SendReport()
|
||||
}
|
||||
|
||||
SubscribeFeedback(callback){
|
||||
this.Instance.SubscribeFeedback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
; DS4 (DualShock 4 for Playstation 4)
|
||||
class ViGEmDS4 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Ds4"
|
||||
__New(){
|
||||
static buttons := {Square: 16, Cross: 32, Circle: 64, Triangle: 128, L1: 256, R1: 512, L2: 1024, R2: 2048
|
||||
, Share: 4096, Options: 8192, LS: 16384, RS: 32768 }
|
||||
static specialButtons := {Ps: 1, TouchPad: 2}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
for name, id in specialButtons {
|
||||
this.Buttons[name] := new this._SpecialButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _SpecialButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetSpecialButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
return round(state * 2.55)
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dPadDirections := {Up: 0, UpRight: 1, Right: 2, DownRight: 3, Down: 4, DownLeft: 5, Left: 6, UpLeft: 7, None: 8}
|
||||
this._Parent.Instance.SetDpadState(dPadDirections[state])
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Xb360
|
||||
class ViGEmXb360 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Xb360"
|
||||
__New(){
|
||||
static buttons := {A: 4096, B: 8192, X: 16384, Y: 32768, LB: 256, RB: 512, LS: 64, RS: 128, Back: 32, Start: 16, Xbox: 1024}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
value := round((state * 655.36) - 32768)
|
||||
if (value == 32768)
|
||||
return 32767
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
_DpadStates := {1:0, 8:0, 2:0, 4:0} ; Up, Right, Down, Left
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dpadDirections := { None: {1:0, 8:0, 2:0, 4:0}
|
||||
, Up: {1:1, 8:0, 2:0, 4:0}
|
||||
, UpRight: {1:1, 8:1, 2:0, 4:0}
|
||||
, Right: {1:0, 8:1, 2:0, 4:0}
|
||||
, DownRight: {1:0, 8:1, 2:1, 4:0}
|
||||
, Down: {1:0, 8:0, 2:1, 4:0}
|
||||
, DownLeft: {1:0, 8:0, 2:1, 4:1}
|
||||
, Left: {1:0, 8:0, 2:0, 4:1}
|
||||
, UpLeft: {1:1, 8:0, 2:0, 4:1}}
|
||||
newStates := dpadDirections[state]
|
||||
for id, newState in newStates {
|
||||
oldState := this._DpadStates[id]
|
||||
if (oldState != newState){
|
||||
this._DpadStates[id] := newState
|
||||
this._Parent.Instance.SetButtonState(id, newState)
|
||||
}
|
||||
this._Parent.SendReport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
; ==========================================================
|
||||
; .NET Framework Interop
|
||||
; https://autohotkey.com/boards/viewtopic.php?t=4633
|
||||
; ==========================================================
|
||||
;
|
||||
; Author: Lexikos
|
||||
; Version: 1.2
|
||||
; Requires: AutoHotkey_L v1.0.96+
|
||||
;
|
||||
|
||||
CLR_LoadLibrary(AssemblyName, AppDomain=0)
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
e := ComObjError(0)
|
||||
Loop 1 {
|
||||
if assembly := AppDomain.Load_2(AssemblyName)
|
||||
break
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 1), args[0] := AssemblyName
|
||||
typeofAssembly := AppDomain.GetType().Assembly.GetType()
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, null, null, args)
|
||||
break
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)
|
||||
break
|
||||
}
|
||||
ComObjError(e)
|
||||
return assembly
|
||||
}
|
||||
|
||||
CLR_CreateObject(Assembly, TypeName, Args*)
|
||||
{
|
||||
if !(argCount := Args.MaxIndex())
|
||||
return Assembly.CreateInstance_2(TypeName, true)
|
||||
|
||||
vargs := ComObjArray(0xC, argCount)
|
||||
Loop % argCount
|
||||
vargs[A_Index-1] := Args[A_Index]
|
||||
|
||||
static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0)
|
||||
|
||||
return Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
|
||||
}
|
||||
|
||||
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
|
||||
{
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
|
||||
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, null, null, args)
|
||||
return A_LastError >= 0
|
||||
}
|
||||
|
||||
CLR_StopDomain(ByRef AppDomain)
|
||||
{ ; ICorRuntimeHost::UnloadDomain
|
||||
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
|
||||
CLR_Start(Version="") ; returns ICorRuntimeHost*
|
||||
{
|
||||
static RtHst := 0
|
||||
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
|
||||
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
|
||||
if RtHst
|
||||
return RtHst
|
||||
EnvGet SystemRoot, SystemRoot
|
||||
if Version =
|
||||
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
|
||||
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
|
||||
Version := A_LoopFileName
|
||||
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
|
||||
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr*", RtHst) >= 0
|
||||
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
|
||||
return RtHst
|
||||
}
|
||||
|
||||
;
|
||||
; INTERNAL FUNCTIONS
|
||||
;
|
||||
|
||||
CLR_GetDefaultDomain()
|
||||
{
|
||||
static defaultDomain := 0
|
||||
if !defaultDomain
|
||||
{ ; ICorRuntimeHost::GetDefaultDomain
|
||||
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
|
||||
defaultDomain := ComObject(p), ObjRelease(p)
|
||||
}
|
||||
return defaultDomain
|
||||
}
|
||||
|
||||
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
|
||||
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|
||||
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|
||||
|| !(codeCompiler := codeProvider.CreateCompiler())
|
||||
return 0
|
||||
|
||||
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
|
||||
return 0
|
||||
|
||||
; Convert | delimited list of references into an array.
|
||||
StringSplit, Refs, References, |, %A_Space%%A_Tab%
|
||||
aRefs := ComObjArray(8, Refs0)
|
||||
Loop % Refs0
|
||||
aRefs[A_Index-1] := Refs%A_Index%
|
||||
|
||||
; Set parameters for compiler.
|
||||
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
|
||||
, prms.OutputAssembly := FileName
|
||||
, prms.GenerateInMemory := FileName=""
|
||||
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
|
||||
, prms.CompilerOptions := CompilerOptions
|
||||
, prms.IncludeDebugInformation := true
|
||||
|
||||
; Compile!
|
||||
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
|
||||
|
||||
if error_count := (errors := compilerRes.Errors).Count
|
||||
{
|
||||
error_text := ""
|
||||
Loop % error_count
|
||||
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
|
||||
MsgBox, 16, Compilation Failed, %error_text%
|
||||
return 0
|
||||
}
|
||||
; Success. Return Assembly object or path.
|
||||
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
|
||||
}
|
||||
|
||||
CLR_GUID(ByRef GUID, sGUID)
|
||||
{
|
||||
VarSetCapacity(GUID, 16, 0)
|
||||
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
|
||||
/**********************************************
|
||||
* Controller methods for simplicity *
|
||||
***********************************************/
|
||||
*/
|
||||
|
||||
GoTo EndControllerFunctionsDef
|
||||
|
||||
;;;;;;;;;;;; Turning functions
|
||||
;;;;;;;;;;;; For holding the stick in a specific position for a period of time
|
||||
;;;;;;;;;;;; Note no other button may be pressed or released when these functions are ran
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (50, 100), 100 being the most, 50 being neutral
|
||||
Turn_Right(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (0, 50), 0 being the most
|
||||
Turn_Left(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
;;;;;;;;;;;; Simple button press functions
|
||||
;;;;;;;;;;;; You can pass a delay amount or leave it blank
|
||||
;;;;;;;;;;;; Longer delays hold the button longer
|
||||
|
||||
; Press X button
|
||||
Press_X(delay:=200){
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press O button
|
||||
Press_O(delay:=200){
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Triangle button
|
||||
Press_Triangle(delay:=200){
|
||||
controller.Buttons.Triangle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Triangle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Square button
|
||||
Press_Square(delay:=200){
|
||||
controller.Buttons.Square.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Square.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_L1(delay:=200){
|
||||
controller.Buttons.L1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.L1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_R1(delay:=200){
|
||||
controller.Buttons.R1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.R1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Right on D-pad
|
||||
Press_Right(delay:=200){
|
||||
controller.Dpad.SetState("Right")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Left on D-pad
|
||||
Press_Left(delay:=200){
|
||||
controller.Dpad.SetState("Left")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Up on D-pad
|
||||
Press_Up(delay:=200){
|
||||
controller.Dpad.SetState("Up")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Down on D-pad
|
||||
Press_Down(delay:=200){
|
||||
controller.Dpad.SetState("Down")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
;;;;;;;;;;; Other functions specific to GT7
|
||||
|
||||
; Turn on nitrous
|
||||
Nitrous_On(){
|
||||
controller.Buttons.RS.SetState(true)
|
||||
}
|
||||
|
||||
; Turn off nitrous
|
||||
Nitrous_Off(){
|
||||
controller.Buttons.RS.SetState(false)
|
||||
}
|
||||
|
||||
Accel_On(control:=100){
|
||||
controller.Buttons.R2.SetState(true)
|
||||
controller.Axes.RT.SetState(control)
|
||||
}
|
||||
|
||||
Accel_Off(){
|
||||
controller.Buttons.R2.SetState(false)
|
||||
controller.Axes.RT.SetState(0)
|
||||
}
|
||||
|
||||
Brake_On(control:=100){
|
||||
controller.Buttons.L2.SetState(true)
|
||||
controller.Axes.LT.SetState(control)
|
||||
}
|
||||
|
||||
Brake_Off(){
|
||||
controller.Buttons.L2.SetState(false)
|
||||
controller.Axes.LT.SetState(0)
|
||||
}
|
||||
; given time t in miliseconds, turn right for that long, with intensity being how much the turn button is held for
|
||||
Turn:
|
||||
t0 := A_TickCount
|
||||
tf := t0+t
|
||||
loop {
|
||||
Sleep(100)
|
||||
} until A_TickCount > tf
|
||||
return
|
||||
|
||||
|
||||
Press_Options(){
|
||||
controller.Buttons.Options.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Options.SetState(false)
|
||||
}
|
||||
|
||||
PressShare(){
|
||||
controller.Buttons.Share.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Share.SetState(false)
|
||||
}
|
||||
|
||||
PressX:
|
||||
; Just for menuing, does not hold X down
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
|
||||
PressO:
|
||||
; Just for menuing, does not hold O down
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
|
||||
PressRight:
|
||||
; For turning
|
||||
controller.Dpad.SetState("Right")
|
||||
Sleep, 50
|
||||
controller.Dpad.SetState("None")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
EndControllerFunctionsDef:
|
||||
@@ -0,0 +1,136 @@
|
||||
/**********************************************
|
||||
* Only place functions here, no sub routines *
|
||||
***********************************************/
|
||||
|
||||
|
||||
; Grabs the colors of the pixels (x-b, y-b) to (x+b, y+b)
|
||||
; returns the array of colors
|
||||
*/
|
||||
|
||||
BitGrab(x, y, b)
|
||||
{
|
||||
HWND := WinExist("PS Remote Play")
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromHWND2(hwnd)
|
||||
|
||||
pixs := []
|
||||
for i in range(-1*b, b+1){
|
||||
for j in range(-1*b, b+1){
|
||||
pixel := Gdip_GetPixel(pBitmap,x+i,y+j)
|
||||
rgb := ConvertARGB( pixel )
|
||||
pixs.Push(rgb)
|
||||
}
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
Gdip_BitmapFromHWND2(hwnd)
|
||||
{
|
||||
WinGetPos,,, Width, Height, ahk_id %hwnd%
|
||||
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
|
||||
RegExMatch(A_OsVersion, "\d+", Version)
|
||||
PrintWindow(hwnd, hdc, Version >= 8 ? 2 : 0)
|
||||
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
|
||||
return pBitmap
|
||||
}
|
||||
|
||||
range(start, stop:="", step:=1) {
|
||||
static range := { _NewEnum: Func("_RangeNewEnum") }
|
||||
if !step
|
||||
throw "range(): Parameter 'step' must not be 0 or blank"
|
||||
if (stop == "")
|
||||
stop := start, start := 0
|
||||
; Formula: r[i] := start + step*i ; r = range object, i = 0-based index
|
||||
; For a postive 'step', the constraints are i >= 0 and r[i] < stop
|
||||
; For a negative 'step', the constraints are i >= 0 and r[i] > stop
|
||||
; No result is returned if r[0] does not meet the value constraint
|
||||
if (step > 0 ? start < stop : start > stop) ;// start == start + step*0
|
||||
return { base: range, start: start, stop: stop, step: step }
|
||||
}
|
||||
|
||||
_RangeNewEnum(r) {
|
||||
static enum := { "Next": Func("_RangeEnumNext") }
|
||||
return { base: enum, r: r, i: 0 }
|
||||
}
|
||||
|
||||
_RangeEnumNext(enum, ByRef k, ByRef v:="") {
|
||||
stop := enum.r.stop, step := enum.r.step
|
||||
, k := enum.r.start + step*enum.i
|
||||
if (ret := step > 0 ? k < stop : k > stop)
|
||||
enum.i += 1
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
Sleep(ms=1)
|
||||
{
|
||||
global timeBeginPeriodHasAlreadyBeenCalled
|
||||
if (timeBeginPeriodHasAlreadyBeenCalled != 1)
|
||||
{
|
||||
DllCall("Winmm.dll\timeBeginPeriod", UInt, 1)
|
||||
timeBeginPeriodHasAlreadyBeenCalled := 1
|
||||
}
|
||||
|
||||
DllCall("Sleep", UInt, ms)
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixelColorSimple(pc_x, pc_y)
|
||||
{
|
||||
WinGet, remotePlay_id, List, ahk_exe RemotePlay.exe
|
||||
if (remotePlay_id = 0)
|
||||
{
|
||||
MsgBox, PS4 Remote Play not found
|
||||
return
|
||||
}
|
||||
if remotePlay_id
|
||||
{
|
||||
pc_wID := remotePlay_id[0]
|
||||
pc_hDC := DllCall("GetDC", "UInt", pc_wID)
|
||||
pc_fmtI := A_FormatInteger
|
||||
SetFormat, IntegerFast, Hex
|
||||
pc_c := DllCall("GetPixel", "UInt", pc_hDC, "Int", pc_x, "Int", pc_y, "UInt")
|
||||
pc_c := pc_c >> 16 & 0xff | pc_c & 0xff00 | (pc_c & 0xff) << 16
|
||||
pc_c .= ""
|
||||
SetFormat, IntegerFast, %pc_fmtI%
|
||||
DllCall("ReleaseDC", "UInt", pc_wID, "UInt", pc_hDC)
|
||||
return pc_c
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GetClientSize(hWnd, ByRef w := "", ByRef h := "")
|
||||
{
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hWnd, "ptr", &rect)
|
||||
w := NumGet(rect, 8, "int")
|
||||
h := NumGet(rect, 12, "int")
|
||||
}
|
||||
|
||||
Distance(c1, c2)
|
||||
{ ; function by [VxE], return value range = [0, 441.67295593006372]
|
||||
return Sqrt((((c1>>16)-(c2>>16))**2)+(((c1>>8&255)-(c2>>8&255))**2)+(((c1&255)-(c1&255))**2))
|
||||
}
|
||||
|
||||
ConvertARGB(ARGB, Convert := 0)
|
||||
{
|
||||
SetFormat, IntegerFast, Hex
|
||||
RGB += ARGB
|
||||
RGB := RGB & 0x00FFFFFF
|
||||
if (Convert)
|
||||
RGB := (RGB & 0xFF000000) | ((RGB & 0xFF0000) >> 16) | (RGB & 0x00FF00) | ((RGB & 0x0000FF) << 16)
|
||||
|
||||
return RGB
|
||||
}
|
||||
|
||||
ToolTipper(msg, x := 100, y := 100)
|
||||
{
|
||||
if (debug_mode = 1)
|
||||
ToolTip, %msg%, x, y, Screen
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
__enableTokyoDetections_mod__ := 1
|
||||
IniRead, color_pitstop1, config.ini, Vars, color_pitstop1, 0
|
||||
IniRead, color_pitstop2, config.ini, Vars, color_pitstop2, 0
|
||||
|
||||
class TokyoTurnContainer
|
||||
{
|
||||
__New(startX, startY, endX := 0, endY := 0)
|
||||
{
|
||||
this.startX := startX
|
||||
this.startY := startY
|
||||
this.endX := endX
|
||||
this.endY := endY
|
||||
}
|
||||
}
|
||||
|
||||
GoTo EndTokyoDetectionsDef
|
||||
|
||||
CheckTokyoMFD(x,y, b_size := 1)
|
||||
{
|
||||
color_dot := 0x8D8B8C
|
||||
TokyoMFD := false
|
||||
tries := 1000 ; we shouldn't need more than 6 tries, but I have seen it loop passed
|
||||
loop {
|
||||
|
||||
tc := BitGrab(x, y, b_size)
|
||||
SB_SetText(" Searching... " td " < 120",2)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_dot)
|
||||
|
||||
if (td < 120){
|
||||
SB_SetText(" Found: " td " < 120",2)
|
||||
TokyoMFD := true
|
||||
break
|
||||
}
|
||||
else {
|
||||
; Gonna try to automate the mfd checker, why not right?
|
||||
if (tries > 0){
|
||||
SB_SetText(" Searching MFD " td " < 110",2)
|
||||
Press_Left()
|
||||
Sleep(100)
|
||||
tries--
|
||||
break
|
||||
}
|
||||
tries := 1000
|
||||
TokyoMFD := true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
} until TokyoMFD = true
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
CheckTokyoTurn(x,y, b_size := 1)
|
||||
{
|
||||
turnStart := A_TickCount
|
||||
color_player := 0xDE6E70
|
||||
TokyoTurnComplete := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 50",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_player)
|
||||
|
||||
if (td < 50 ){
|
||||
SB_SetText(" Found: " td " < 50",2)
|
||||
TokyoTurnComplete := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run looking for turn. Gonna start with a high number, can adjust lower later.
|
||||
; added some press down, x's and waits just in case we are in the pit stop
|
||||
if (A_TickCount - turnStart > 90000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoTurnComplete = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPen1(x,y, b_size := 1)
|
||||
{
|
||||
pen1Start := A_TickCount
|
||||
|
||||
color_pen := 0xFFC10B
|
||||
TokyoPen1 := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 50",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pen)
|
||||
|
||||
if (td < 50 ){
|
||||
SB_SetText(" Found: " td " < 50",2)
|
||||
TokyoPen1 := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run looking for Pen1. Gonna start with a high number, can adjust lower later.
|
||||
; started with 1.5 mins, i had these set to 3:33 on other file and still won.
|
||||
if (A_TickCount - pen1Start > 90000) {
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoPen1 = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoHairpinTurn(x,y, b_size := 1)
|
||||
{
|
||||
hairpinStart := A_TickCount
|
||||
|
||||
color_hairpinturn := 0xB3B1B2
|
||||
TokyoHairpinTurn := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 5",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_hairpinturn)
|
||||
|
||||
if (td < 5){
|
||||
SB_SetText(" Found: " td " < 5",2)
|
||||
TokyoHairpinTurn := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in hairpin
|
||||
; set to 1 minute to start, I had this at 3:33 (200000) on my other file and still won.
|
||||
if (A_TickCount - hairpinStart > 90000) {
|
||||
|
||||
GoSub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoHairpinTurn = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPen2(x,y, b_size := 1)
|
||||
{
|
||||
start := A_TickCount
|
||||
color_pen := 0xFFC10B
|
||||
RecoveryTried := false
|
||||
TokyoPen2 := false
|
||||
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 60",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pen)
|
||||
|
||||
if (td > 60 ){
|
||||
SB_SetText(" Found: " td " > 60",2)
|
||||
TokyoPen2 := true
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
if (A_TickCount - start > 35000 AND RecoveryTried = false) {
|
||||
SB_SetText(" We stuck? Starting recovery try.",2)
|
||||
Accel_off()
|
||||
controller.Axes.LX.SetState(50)
|
||||
loop 7 {
|
||||
Press_Square(delay:=50)
|
||||
Sleep(100)
|
||||
}
|
||||
Accel_on(80)
|
||||
Sleep(500)
|
||||
loop 9 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(100)
|
||||
}
|
||||
controller.Axes.LX.SetState(30)
|
||||
RecoveryTried := true
|
||||
}
|
||||
|
||||
if (A_TickCount - start > 60000) {
|
||||
gosub, ResetRace
|
||||
break
|
||||
}
|
||||
|
||||
} until TokyoPen2 = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPenServed(x,y, b_size := 1)
|
||||
{
|
||||
color_penserved := 0xAE1B1E
|
||||
TokyoPenServed := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 60",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_penserved)
|
||||
|
||||
if (td > 60 ){
|
||||
SB_SetText(" Found: " td " > 60",2)
|
||||
TokyoPenServed := true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
} until TokyoPenServed = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPenReceived(x,y, b_size := 1)
|
||||
{
|
||||
start := A_TickCount
|
||||
color_penreceived := 0xAE1B1E
|
||||
TokyoPenReceived := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 40",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_penreceived)
|
||||
|
||||
if (td < 40 ){
|
||||
SB_SetText(" Found: " td " < 40",2)
|
||||
guicontrol,, CurrentLoop, Pen received
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
if (TokyoLapCount != 6 AND A_TickCount - start > 36000)
|
||||
{
|
||||
SB_SetText(" Not found in time. Shifting up.",2)
|
||||
loop 6 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
if (TokyoLapCount = 6 AND A_TickCount - start > 46000)
|
||||
{
|
||||
SB_SetText(" Not found in time. Shifting up.",2)
|
||||
loop 20 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
TokyoPenReceived := true
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
} until TokyoPenReceived = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckTokyoPitstopDone(x,y, b_size := 1)
|
||||
{
|
||||
pitstopDoneStart := A_TickCount
|
||||
|
||||
color_pitstopdone := 0xFFFFFF
|
||||
TokyoPitstopDone := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " > 10",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pitstopdone)
|
||||
|
||||
if (td > 10 ){
|
||||
SB_SetText(" Found: " td " > 10",2)
|
||||
TokyoPitstopDone := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in pit, havent tested if press down works to get us out
|
||||
if (A_TickCount - pitstopDoneStart > 60000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
}
|
||||
} until TokyoPitstopDone = true
|
||||
return
|
||||
}
|
||||
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
{
|
||||
if ( A_TickCount - loopStartTime > maxTime AND TokyoLapCount <= 10) {
|
||||
gosub, ResetRace
|
||||
}
|
||||
else if (A_TickCount - loopStartTime > maxTime+90000 AND TokyoLapCount > 10)
|
||||
{
|
||||
gosub, ResetRace
|
||||
}
|
||||
}
|
||||
|
||||
CheckTokyoPitstop1(x,y, b_size := 1)
|
||||
{
|
||||
pitstop1Start := A_TickCount
|
||||
|
||||
;color_pitstop1 := 0xFFFFFF
|
||||
;color_pitstop1 := 0x818002
|
||||
;color_pitstop1 := 0xFBFB00 ; old color
|
||||
TokyoPitstop := false
|
||||
loop {
|
||||
SB_SetText(" Searching... " td " < 10",2)
|
||||
tc := BitGrab(x, y, b_size)
|
||||
for i, c in tc
|
||||
{
|
||||
td := Distance(c, color_pitstop1)
|
||||
|
||||
if (td < 10 ){
|
||||
SB_SetText(" Found: " td " < 10",2)
|
||||
TokyoPitstop := true
|
||||
break
|
||||
}
|
||||
}
|
||||
; add recovery so we don't kill run sitting in pit, havent tested if press down works to get us out
|
||||
if (A_TickCount - pitstop1Start > 60000) {
|
||||
Press_Down()
|
||||
Sleep(300)
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
Sleep(7000)
|
||||
GoSub, ResetRace
|
||||
}
|
||||
guicontrol,, CurrentLoop, Stuck in pit? Press GUI Button.
|
||||
|
||||
} until TokyoPitstop = true
|
||||
return
|
||||
}
|
||||
UpdateAVG(racecounter, script_start)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
creditcountersession := (835000*racecounter)/1000000
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditavg := creditcountersession/(A_TickCount-script_start)*3600000
|
||||
guicontrol,, CreditAVG, Avg./h: ~%creditavg% M
|
||||
return
|
||||
}
|
||||
|
||||
UpdateTimer()
|
||||
{
|
||||
ElapsedTime := A_TickCount - script_start
|
||||
VarSetCapacity(t,256),DllCall("GetDurationFormat","uint",2048,"uint",0,"ptr",0,"int64",ElapsedTime*10000,"wstr","d' day(s) 'h':'mm':'ss","wstr",t,"int",256)
|
||||
SB_SetText("Runtime: " t,3)
|
||||
return
|
||||
}
|
||||
|
||||
HexToDec(hex)
|
||||
{
|
||||
VarSetCapacity(dec, 66, 0)
|
||||
, val := DllCall("msvcrt.dll\_wcstoui64", "Str", hex, "UInt", 0, "UInt", 16, "CDECL Int64")
|
||||
, DllCall("msvcrt.dll\_i64tow", "Int64", val, "Str", dec, "UInt", 10, "CDECL")
|
||||
return dec
|
||||
}
|
||||
|
||||
|
||||
EndTokyoDetectionsDef:
|
||||
@@ -0,0 +1,86 @@
|
||||
#Include Races\PanAm.ahk
|
||||
#Include Races\Tokyo.ahk
|
||||
|
||||
GoTo EndRaceDef
|
||||
|
||||
Race:
|
||||
|
||||
Switch RaceChoice
|
||||
{
|
||||
case "PanAm":
|
||||
Race_PANAM()
|
||||
return
|
||||
case "Tokyo":
|
||||
Race_Tokyo()
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
SettingsSheet:
|
||||
|
||||
Gui, 4: Show, AutoSize, Settings Sheet
|
||||
;/////////////////////////////////////////////////////////
|
||||
; Add images to your setup here and in the Src folder
|
||||
;
|
||||
;/////////////////////////////////////////////////////////
|
||||
Switch RaceChoice
|
||||
{
|
||||
case "PanAm":
|
||||
|
||||
assist_1 = %A_ScriptDir%\Src\PanAm\Assist1.jpg
|
||||
assist_2 = %A_ScriptDir%\Src\PanAm\Assist2.jpg
|
||||
tune_1 = %A_ScriptDir%\Src\PanAm\CarSetup.jpg
|
||||
tune_2 = %A_ScriptDir%\Src\PanAm\CarGearRatio.jpg
|
||||
controls = %A_ScriptDir%\Src\PanAm\Controller.jpg
|
||||
return
|
||||
case "Tokyo":
|
||||
|
||||
assist_1 = %A_ScriptDir%\Src\Tokyo\Assist_Settings.png
|
||||
assist_2 = %A_ScriptDir%\Src\Tokyo\Misc_Settings.png
|
||||
controls = %A_ScriptDir%\Src\Tokyo\Controller_Settings.png
|
||||
tune_1 = %A_ScriptDir%\Src\Tokyo\Settings_Car1.png
|
||||
tune_2 = %A_ScriptDir%\Src\Tokyo\Settings_Car2.png
|
||||
tune_3 = %A_ScriptDir%\Src\Tokyo\Settings_Car3.png
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
return
|
||||
|
||||
Assists1:
|
||||
GuiControl, 4:, CurrentPic, %assist_1%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Assists2:
|
||||
GuiControl, 4:, CurrentPic, %assist_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune1:
|
||||
GuiControl, 4:, CurrentPic, %tune_1%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune2:
|
||||
GuiControl, 4:, CurrentPic, %tune_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Tune3:
|
||||
GuiControl, 4:, CurrentPic, %tune_2%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
ControllerSetting:
|
||||
GuiControl, 4:, CurrentPic, %controls%
|
||||
gosub, Guisizer
|
||||
return
|
||||
|
||||
Guisizer:
|
||||
GuiControl, 4: Move, CurrentPic, % "x" 10 "y" 40 "w" 1200 . " h" . 800
|
||||
Gui, 4: Show, AutoSize, Settings Sheet
|
||||
return
|
||||
|
||||
EndRaceDef:
|
||||
@@ -0,0 +1,509 @@
|
||||
GoTo EndRace_Tokyo_Def
|
||||
|
||||
Race_Tokyo()
|
||||
{
|
||||
IniRead, hairpin_delay, config.ini, Vars, hairpin_delay, 0
|
||||
IniRead, RaceCounterTotal, config.ini, Stats, racecountertotal, 0
|
||||
IniRead, ResetCounterTotal, config.ini, Stats, resetcountertotal, 0
|
||||
SetFormat, integerfast, d
|
||||
TokyoStart:
|
||||
;- VARIABLES -----------------------------------------------------------------------------
|
||||
SetFormat, integerfast, d
|
||||
TokyoLapCount := 1
|
||||
maxTime := 200000
|
||||
StringSplit, PitstopTimingsArray, PitstopTimings, `,
|
||||
;- COORDINATES: TURNS --------------------------------------------------------------------
|
||||
TokyoTurn1 := new TokyoTurnContainer(611, 59+remote_play_offsetY, 622, 69+remote_play_offsetY)
|
||||
TokyoTurn2 := new TokyoTurnContainer(618, 70+remote_play_offsetY, 601, 76+remote_play_offsetY)
|
||||
TokyoTurn3 := new TokyoTurnContainer(599, 79+remote_play_offsetY, 591, 87+remote_play_offsetY)
|
||||
TokyoTurn4 := new TokyoTurnContainer(589, 88+remote_play_offsetY, 571, 96+remote_play_offsetY)
|
||||
TokyoTurn5 := new TokyoTurnContainer(567, 96+remote_play_offsetY, 556, 90+remote_play_offsetY)
|
||||
TokyoTurn6 := new TokyoTurnContainer(554, 86+remote_play_offsetY, 543, 82+remote_play_offsetY)
|
||||
TokyoTurn7 := new TokyoTurnContainer(538, 81+remote_play_offsetY, 530, 75+remote_play_offsetY)
|
||||
TokyoTurn8 := new TokyoTurnContainer(530, 75+remote_play_offsetY, 510, 72+remote_play_offsetY)
|
||||
;- COORDINATES: PENALTY WARNINGS ---------------------------------------------------------
|
||||
TokyoPenWarning := new TokyoTurnContainer(360, 154+remote_play_offsetY, 408, 154+remote_play_offsetY)
|
||||
TokyoPenIndicator := new TokyoTurnContainer(366, 132+remote_play_offsetY)
|
||||
;- COORDINATES: HAIRPIN TURN -------------------------------------------------------------
|
||||
TokyoHairpinTurn := new TokyoTurnContainer(606, 334+remote_play_offsetY)
|
||||
;- COORDINATES: PENALTY WARNINGS ---------------------------------------------------------
|
||||
TokyoPen := new TokyoTurnContainer(360, 154+remote_play_offsetY, 408, 154+remote_play_offsetY)
|
||||
TokyoPenServed := new TokyoTurnContainer(366, 132+remote_play_offsetY)
|
||||
;- COORDINATES: HAIRPIN TURN--------------------------------------------------------------
|
||||
TokyoHairpinTurn := new TokyoTurnContainer(606, 334+remote_play_offsetY)
|
||||
;- MISC ----------------------------------------------------------------------------------
|
||||
TokyoPitstop := new TokyoTurnContainer(191, 316+remote_play_offsetY, 580, 383+remote_play_offsetY)
|
||||
TokyoPitstopEnter := new TokyoTurnContainer(530, 70+remote_play_offsetY)
|
||||
TokyoPitstopDone := new TokyoTurnContainer(57, 329+remote_play_offsetY)
|
||||
TokyoRestartRace := new TokyoTurnContainer(405,465+remote_play_offsetY)
|
||||
TokyoMFD := new TokyoTurnContainer(557, 382+remote_play_offsetY)
|
||||
;- RACE START ----------------------------------------------------------------------------
|
||||
controller.Axes.LX.SetState(65)
|
||||
Sleep(7400)
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime%: Race started.`n, log.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race started.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
guicontrol,, CurrentLoop, Race started. Good luck!
|
||||
guicontrol,, CurrentLap, Current Lap: %TokyoLapCount% /12
|
||||
Accel_On(100)
|
||||
loop 3 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
}
|
||||
Sleep(800)
|
||||
controller.Axes.LX.SetState(65)
|
||||
CheckTokyoMFD(TokyoMFD.startX, TokyoMFD.startY)
|
||||
;- 12 LAP LOOP ---------------------------------------------------------------------------
|
||||
loop 12
|
||||
{
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
loopStartTime := A_TickCount
|
||||
; Turn 1
|
||||
location := "T1 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn1.startX, TokyoTurn1.startY)
|
||||
loop 3 {
|
||||
Press_Triangle(delay:=50)
|
||||
Sleep(200)
|
||||
}
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(36)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
Sleep(1000)
|
||||
location := "T1 End"
|
||||
CheckTokyoTurn(TokyoTurn1.endX, TokyoTurn1.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(35)
|
||||
Sleep(1000)
|
||||
; Turn 2
|
||||
location := "T2 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn2.startX, TokyoTurn2.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(52)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
Sleep(1000)
|
||||
location := "T2 End"
|
||||
CheckTokyoTurn(TokyoTurn2.endX, TokyoTurn2.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Turn 3
|
||||
location := "T3 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn3.startX, TokyoTurn3.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
controller.Axes.LX.SetState(40)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn3.endX, TokyoTurn3.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
; Turn 4
|
||||
location := "T4 Start"
|
||||
Accel_On(85)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn4.startX, TokyoTurn4.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
controller.Axes.LX.SetState(68)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn4.endX, TokyoTurn4.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(60)
|
||||
Accel_On(70)
|
||||
Sleep(1000)
|
||||
; Turn 5
|
||||
location := "T5 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn5.startX, TokyoTurn5.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(42)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn5.endX, TokyoTurn5.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(63)
|
||||
Sleep(1000)
|
||||
; Turn 6
|
||||
location := "T6 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn6.startX, TokyoTurn6.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
Accel_on(75)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn6.endX, TokyoTurn6.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Turn 7
|
||||
location := "T7 Start"
|
||||
Accel_On(100)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn7.startX, TokyoTurn7.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn7.endX, TokyoTurn7.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(70)
|
||||
Sleep(1000)
|
||||
; Turn 8
|
||||
location := "T8 Start"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn8.startX, TokyoTurn8.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(65)
|
||||
Sleep(1000)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoTurn8.endX, TokyoTurn8.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(30)
|
||||
Sleep(2000)
|
||||
Brake_on(100)
|
||||
Sleep(2200)
|
||||
Brake_off()
|
||||
Accel_On(35)
|
||||
; Penalty Warning 1
|
||||
location := "Hairpin Entrance"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPen1(TokyoPenWarning.startX, TokyoPenWarning.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Accel_On(32)
|
||||
if (TokyoLapCount=12) {
|
||||
Accel_On(34)
|
||||
}
|
||||
controller.Axes.LX.SetState(40)
|
||||
Sleep(1000)
|
||||
; Hairpin Turn
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
location := "Hairpin Turn"
|
||||
CheckTokyoHairpinTurn(TokyoHairpinTurn.startX, TokyoHairpinTurn.startY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
|
||||
if (DynTurnDelay)
|
||||
{
|
||||
if ((ThairpinS - 6000) > 0) {
|
||||
hairpin_delayn := HexToDec(hairpin_delay - 20 - ( 50 * Floor((ThairpinS - 6000)/1000)))
|
||||
If ( hairpin_delayn <0 ){
|
||||
hairpin_delayn := 0
|
||||
}
|
||||
guicontrol,, CurrentLoop, Turn delay: %hairpin_delayn% (Dynamic)
|
||||
}
|
||||
if ((ThairpinS - 5000) < 0) {
|
||||
hairpin_delayn := HexToDec(hairpin_delay + 50 + ( 20 * Floor((5000 - ThairpinS)/1000) ))
|
||||
guicontrol,, CurrentLoop, Turn delay: %hairpin_delayn% (Dynamic)
|
||||
}
|
||||
if (6000<=ThairpinS>=5000) {
|
||||
hairpin_delayn := HexToDec(hairpin_delay)
|
||||
guicontrol,, CurrentLoop, Turn delay: %hairpin_delayn% (Default)
|
||||
}
|
||||
Sleep(hairpin_delayn)
|
||||
}
|
||||
else
|
||||
{
|
||||
Sleep(hairpin_delay)
|
||||
}
|
||||
controller.Axes.LX.SetState(100)
|
||||
Sleep(200)
|
||||
Accel_Off()
|
||||
Sleep(4200)
|
||||
Accel_On(45) ;was 40
|
||||
controller.Axes.LX.SetState(60)
|
||||
Accel_Off()
|
||||
Sleep(800)
|
||||
controller.Axes.LX.SetState(40)
|
||||
Accel_On(50)
|
||||
Sleep(5000)
|
||||
controller.Axes.LX.SetState(30)
|
||||
Sleep(5500)
|
||||
Accel_On(80)
|
||||
loop 30 { ; failsafe, if we ever get a reset caused by a cone under the car
|
||||
Press_Triangle(delay:=100)
|
||||
Sleep(200)
|
||||
}
|
||||
; Penalty Warning 2
|
||||
location := "Hairpin exit"
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPen2(TokyoPen.endX, TokyoPen.endY)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Sleep(1000)
|
||||
if (TokyoLapCount <= 11)
|
||||
{
|
||||
location := "Pit entrance"
|
||||
Accel_On(53)
|
||||
controller.Axes.LX.SetState(30)
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoTurn(TokyoPitstopEnter.startX, TokyoPitstopEnter.startY)
|
||||
controller.Axes.LX.SetState(0)
|
||||
Accel_On(55)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPitstop1(TokyoPitstop.startX, TokyoPitstop.startY)
|
||||
location := "In pit"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(50)
|
||||
|
||||
if (TokyoLapCount = 1)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray1/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray1)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 2)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray2/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray2)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 3)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray3/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray3)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 4)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray4/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray4)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 5)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray5/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray5)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 6)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray6/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray6)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 7)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray7/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray7)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 8)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray8/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray8)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 9)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray9/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray9)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 10)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray10/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray10)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 11)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray11/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray11)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
if (TokyoLapCount = 12)
|
||||
{
|
||||
SetFormat, integerfast, d
|
||||
location := "In pit: Waiting " Round(PitstopTimingsArray12/1000) " seconds."
|
||||
guicontrol,, CurrentLoop, %location%
|
||||
Sleep (PitstopTimingsArray12)
|
||||
Press_Up()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
Sleep (100)
|
||||
Press_X()
|
||||
}
|
||||
controller.Axes.LX.SetState(20)
|
||||
Accel_On(100)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPenReceived(TokyoPenServed.startX, TokyoPenServed.startY)
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
controller.Axes.LX.SetState(38)
|
||||
Sleep (500)
|
||||
loop 10 {
|
||||
Press_Triangle(delay:=200)
|
||||
sleep, 200
|
||||
}
|
||||
}
|
||||
else {
|
||||
location := "Start/Finish"
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
Accel_On(100)
|
||||
controller.Axes.LX.SetState(60)
|
||||
CheckMaxTime(maxTime, loopStartTime, TokyoLapCount)
|
||||
CheckTokyoPenServed(TokyoPenServed.startX, TokyoPenServed.startY)
|
||||
}
|
||||
SetFormat, integerfast, d
|
||||
TokyoLapCount++
|
||||
guicontrol,, CurrentLap, Current Lap: %TokyoLapCount% /12
|
||||
ProgressRace := (100/13)*TokyoLapCount
|
||||
guicontrol,, RaceProgress, %ProgressRace%
|
||||
|
||||
if(TokyoLapCount = "13")
|
||||
{
|
||||
location := "Finish line"
|
||||
|
||||
FormatTime, TGTime,, MM/dd hh:mm:ss
|
||||
FileAppend, %TGTime% Race finished.`n, log.txt
|
||||
url := "https://api.telegram.org/bot" TelegramBotToken "/sendMessage?text=" TGTime ": Race finished.&chat_id=" TelegramChatID
|
||||
hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1")
|
||||
hObject.Open("GET",url)
|
||||
hObject.Send()
|
||||
|
||||
guicontrol,, CurrentLoop, Current Location: %location%
|
||||
guicontrol,, CurrentLap, GG!
|
||||
controller.Axes.LX.SetState(50)
|
||||
SetFormat, integerfast, d
|
||||
racecounter++
|
||||
SetFormat, integerfast, d
|
||||
racecountertotal++
|
||||
|
||||
; // THIS SESSION
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountersession := (835000*racecounter)/1000000
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditavg := creditcountersession/(A_TickCount-script_start)*3600000
|
||||
guicontrol,, RaceCounterSession, Races completed: %racecounter%
|
||||
guicontrol,, ResetCounterSession, Races failed: %resetcounter%
|
||||
guicontrol,, CreditCounterSession, Credits: %creditcountersession% M
|
||||
guicontrol,, CreditAVGSession, Avg./h: %creditavg% M
|
||||
|
||||
; // ALL TIME
|
||||
SetFormat, integerfast, d
|
||||
SetFormat, FloatFast, 0.2
|
||||
creditcountertotal := (835000*racecountertotal)/1000000
|
||||
IniWrite, %racecountertotal%, config.ini,Stats, RaceCounterTotal
|
||||
IniWrite, %resetcountertotal%, config.ini,Stats, ResetCounterTotal
|
||||
guicontrol,, RaceCounterTotal, Races completed: %racecountertotal%
|
||||
guicontrol,, ResetCounterTotal, Races failed: %resetcountertotal%
|
||||
guicontrol,, CreditCounterTotal, Credits: %creditcountertotal% M
|
||||
UpdateAVG(racecounter, script_start)
|
||||
lapcounter =
|
||||
ProgressRace =
|
||||
guicontrol,, RaceProgress, %ProgressRace%
|
||||
loop
|
||||
{
|
||||
restart_found := false
|
||||
c2 := BitGrab(162, 43+remote_play_offsetY, 2)
|
||||
for i, c in c2
|
||||
{
|
||||
d2 := Distance(c, color_restart)
|
||||
SB_SetText(" Searching... " d2 " < 50",2)
|
||||
if (d2 < 10 )
|
||||
{
|
||||
SB_SetText(" Found: Restart Color " d2 " < 50",2)
|
||||
restart_found := true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (restart_found)
|
||||
break
|
||||
Press_X()
|
||||
Sleep(500)
|
||||
}
|
||||
Sleep(400)
|
||||
Press_O()
|
||||
Sleep(500)
|
||||
Press_Right()
|
||||
Sleep(3000)
|
||||
Press_X()
|
||||
Sleep(4000)
|
||||
Press_X()
|
||||
Sleep(4000)
|
||||
guicontrol,, CurrentLoop, Setting up next race.
|
||||
Press_Options()
|
||||
Sleep(1000)
|
||||
Press_Right()
|
||||
Sleep(500)
|
||||
Press_X()
|
||||
controller.Axes.LX.SetState(50)
|
||||
UpdateAVG(racecounter, script_start)
|
||||
Goto, TokyoStart
|
||||
}
|
||||
}
|
||||
}
|
||||
EndRace_Tokyo_Def:
|
||||
|
After Width: | Height: | Size: 744 KiB |
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,336 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>GT7 - Tokyo X by problemz.</title>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800,900" rel="stylesheet">
|
||||
<link rel="stylesheet" href="scribbler-global.css">
|
||||
<link rel="stylesheet" href="scribbler-doc.css">
|
||||
<link rel="author" href="humans.txt">
|
||||
</head>
|
||||
<body>
|
||||
<div class="doc__bg"></div>
|
||||
<nav class="header">
|
||||
|
||||
|
||||
<h1 class="logo">Tokyo X <span class="logo__thin">Doc</br>by problemz.</span></h1>
|
||||
|
||||
<ul class="menu">
|
||||
<div class="menu__item toggle"><span></span></div>
|
||||
<li class="menu__item"><a href="https://discord.gg/CfppVp7VXV" target="_blank" class="link link--dark"><i class="fa-brands fa-discord"></i> Join our Discord server</a></li>
|
||||
</ul>
|
||||
</br>
|
||||
<div class="position-relative marquee-container d-none d-sm-block">
|
||||
<div class="marquee d-flex justify-content-around">
|
||||
<span>Shoutout (alphabetic order) to all these <b>AMAZING PEOPLE</b> from the Discord Tokyo Beta Channel. Thank you for helping me bringing the <b>TOKYO X</b> script to life - it was a great time!</span>
|
||||
</br>
|
||||
<span><shadow2>andow</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Atoms4Piece</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>BeefSupreme</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>BobGT</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>CarapauCorrida</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Chester</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>🐐 </shadow2>(you know)</span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>GTMaster</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>heidi</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>hitomi</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>j0shjones</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>JordanD123</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Krazyy</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>NavS</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Rossey</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Scany</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Septomor</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Sevencuts</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Solisu</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>TheScythed</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>x34uvc</shadow2></span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
</nav>
|
||||
|
||||
<div class="wrapper">
|
||||
<aside class="doc__nav">
|
||||
|
||||
<ul>
|
||||
<li class="js-btn selected">Welcome to Tokyo</li>
|
||||
<li class="js-btn">The Masterplan</li>
|
||||
<li class="js-btn">Setting everything up</li>
|
||||
<li class="js-btn">FAQ/Changelog</li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<article class="doc__content">
|
||||
<section class="js-section">
|
||||
<h3 class="section__title">Konnichiwa friend o/</h3>
|
||||
<p>In this documentation you learn how the Tokyo WTC 600 race works and how to set up the <b>Tokyo X</b> AHK script to farm GT7 credits when you are away from your computer or busy doing other tasks.</br></br>Please <b><u>read carefully and double-check</u></b> everything in this documentation if something isn't working as described. The PSNProfiles Discord has many helpful members that will assist you in getting the script running for your configuration, provided you have read and followed the directions below first.</p></br>
|
||||
<div class="callout">
|
||||
<a href="https://discord.gg/CfppVp7VXV" target="_blank" class="button--primary"><i class="fa-brands fa-discord"></i> Join our Discord server</a></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="js-section">
|
||||
<h3 class="section__title">Problemz, what is happening and why does it all work? </h3>
|
||||
<p>Some time ago i started to look for the race with the best credits per hour ratio. <i class="fa-solid fa-arrow-trend-up"></i></br>After an update, the WTC 600 - Tokyo Race became the clear winner and i started writing the script.</p><h4>For this race we have different obstacles:</h4>
|
||||
<table id="obstacles">
|
||||
<tr>
|
||||
<th>Obstacle</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PP restriction</td>
|
||||
<td>We are only allowed to enter a car with a maximum of 600 PP.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tire/fuel consumption</td>
|
||||
<td>Tire (9x) and fuel (3x) consumption is active. That means we must find the best way to finish the race with the least RNG possible. (Worn tires can lead to spinouts, we must not not run out of fuel, etc.)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Track condition</td>
|
||||
<td>Track conditions There are 12 laps total, and the race starts with a very wet track. The track dries throughout the race and and we must react accordingly in order to not spin out or run into obstacles that we can’t recover from (mainly barrels in the hairpin turn).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AI/Opponents</td>
|
||||
<td>You start the race with 15 other opponents. We try to avoid them as much as possible in order to not spin out or miss set detection pixels (explained later).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Hairpin turn</td>
|
||||
<td>There is a hairpin in this track. And it is here to make our scripting lives horrible.</br>The inner side is blocked by big cones, hindering us from just grinding the inner part of the turn.</br>On the outer side we have small cones and 90° walls. The walls are hindering us from just grinding the outside, the small cones often resets our car (when stuck under the car), spawning us back in the first gear.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2> Let's start explaining how we mastered this race to earn some good credits:</h2>
|
||||
<div class="obstacles">
|
||||
<h3 class="section__title">Overcoming the obstacles. 1 by 1.</h3>
|
||||
</br>
|
||||
<div class="tab__container">
|
||||
<ul class="tab__menu">
|
||||
<li class="tab active" data-tab="pp">PP restriction</li>
|
||||
<li class="tab" data-tab="track">Track condition</li>
|
||||
<li class="tab" data-tab="consumption">Tire/fuel consumptions</li>
|
||||
<li class="tab" data-tab="ai">AI/Opponents</li>
|
||||
<li class="tab" data-tab="hairpin">Final boss: Hairpin</li>
|
||||
</ul>
|
||||
<pre class="nohighlight code">
|
||||
<code class="tab__pane active pp">We use a bug in the code to jump below the allowed PP, but still having the fastest car (<i class="fa-solid fa-car"></i> Dodge SRT Tomahawk X VGT). </br></br>We manipulate the gear ratios to a point, where the PP calculation shows <i class="fa-solid fa-triangle-exclamation"></i> PP.</br>From there we fiddle with values until the PP calculation is under 600 PP.</br></br>This still works after the PP-Patch. <i class="fa-solid fa-square-check"></i> </code>
|
||||
<code class="tab__pane track"><i class="fa-solid fa-water"></i> The race starts with a very wet track. We have to start with <b>intermediates.</b></br></br>After a few laps, the track starts to get dryer, but we can't just switch to Hards. We are not driving the ideal line. <br>We hit some wet spots here and there, therefore we stay on <b>intermediates</b> for the whole race.</br></br> <i class="fa-solid fa-circle-exclamation"></i> Otherwise we would risk to RNG-Spin at many different spots, which endangers ours <b>consistency</b>.</code>
|
||||
<code class="tab__pane pen"><i class="fa-solid fa-clock-rotate-left"></i> I found out, that there is an internal cooldown for the penalty counter.</br></br>If you receive a penalty and hit or grind a wall/part of the track within 6 seconds, the internal cooldown gets reset.</br>You still collect penalties in a internal penalty storage.</br></br>The first time you're not hitting something for 6 seconds, the penalty gets triggered and is added to your current penalty.</br></br>I also found out, that if you keep grinding the wall while serving a penalty, your penalty storage gets reset. <i class="fa-solid fa-square-check"></i></br></br>If we just keep collecting penalties and finish the race without ever triggering/serving them, we end in a blackscreen and have to close the game and never receive credits.<b></br></br>We use all of this to our advantage:</b></br>We only trigger and serve a 5 second penalty every lap and reset our internal penalty storage, even if we are grinding walls 90% of the time, filling our internal storage.</br></code>
|
||||
<code class="tab__pane consumption"><b><i class="fa-regular fa-circle"></i> The tires consumption rate is at 9x.</b></br>We already know that we keep the Intermediates. We use the pit stop to always, <b>consistently</b>, trigger a new 5 second penalty</br>We're switching tires every lap - to always have the same behaviour on track, with our set timings/speeds.</br></br><i class="fa-solid fa-gas-pump"></i><b> The fuel consumtion rate is at 3x.</b></br>Because of our frequent pit visits, we can drive with the fuel map setting 1 (Power).</br>We fill up completely in Lap 6 and continiue driving until the race is finish, after lap 12.</code>
|
||||
<code class="tab__pane ai">We mainly use the pit stops to control our distance to the AI cars.</br>We are using set wait times, depending on our current lap and AI position at this time of the race. There are 2 timings at the momement.</br></br><i class="fa-solid fa-shield"></i> <b>Safest:</b> This one always stays behind AI, therefore its slower but we never see AI.</br></br><i class="fa-solid fa-shield-halved"></i> <b>Risky:</b> With this timings, we overtake AI on different parts of the track, but never in the hairpin turn.</code>
|
||||
<code class="tab__pane hairpin"><i class="fa-solid fa-radiation"></i> Welcome to the run/consisteny killer #1, the hairpin. <i class="fa-solid fa-skull-crossbones"></i></br></br>After many hours and iterations, our current most consistent way to handle the hairpin is this:</br></br>We place our car on the left wall, controlling our speed, when reaching the turn detection point. We then steer to the right, release acceleration and reach the other side's left wall. This reads so simple, but it's really much more complicated.</br></br>You will see why, pretty soon, running the script. <i class="fa-solid fa-person-harassing"></i></code>
|
||||
</pre>
|
||||
</div>
|
||||
<h4>About pixel detection:</h4>This script relies on the detection of specific color pixels at given coordinates to determine the position of the car relative to the racetrack, also some UI elements and respond accordingly. Pixel detection can be affected by a number of factors such as PlayStation version, PC performance, and network throughput, latency and stability.</br></br>
|
||||
There is also a degree of variance that happens with every race. Although we have tried to remove as much of this as possible by pitting every lap and avoiding AI in the hairpin, there is still randomness in AI behavior or in things like how the cones in the hairpin react when hit.</br></br>
|
||||
As such, although we have included a number of variables that allow you to fine tune the script for your specific setup (hairpin turn delay/pit timings), but do not expect to see a 100% completion/win rate. A 75%-90% success is achievable for most people when the correct hairpin turn delay was found.
|
||||
|
||||
<hr>
|
||||
</section>
|
||||
<section class="js-section">
|
||||
<h3 class="section__title">Requirements & Informations</h3>
|
||||
<h3>Hardware:</h3>
|
||||
<li>A computer running <i class="fa-brands fa-windows"></i> Microsoft Windows (must be X86 processor, ARM is not supported!)</li>
|
||||
<li>Do <b>NOT</b> connect a <i class="fa-solid fa-gamepad"></i> Controller to your <i class="fa-brands fa-playstation"></i> Playstation or <i class="fa-solid fa-computer"></i> Computer</li>
|
||||
<li><i class="fa-solid fa-network-wired"></i> Wired internet connection for stable operation of the script. If you do not have both, <i class="fa-solid fa-computer"></i> PC and <i class="fa-brands fa-playstation"></i> Playstation connected by <i class="fa-solid fa-network-wired"></i> wired internet, you may experience all kinds of different problems. If you use <i class="fa-solid fa-wifi"></i> WiFi, we cannot guarantee good operation.</li>
|
||||
<hr>
|
||||
<h3>Software:</h3>
|
||||
<h4><i class="fa-solid fa-download"></i> Download and install:</h4>
|
||||
<li><a href="https://remoteplay.dl.playstation.net/remoteplay/" target:"_blank"><i class="fa-brands fa-playstation"></i> PS Remote Play</a></br></li>
|
||||
<li><a href="https://www.autohotkey.com/" target:"_blank"><i class="fa-regular fa-keyboard"></i> AutoHotkey</a></br></li>
|
||||
<li><a href="https://github.com/ViGEm/ViGEmBus" target:"_blank"><i class="fa-solid fa-gamepad"></i> ViGEmBus Driver (including dependencies)</a></br></li></br>
|
||||
<h4><i class="fa-brands fa-windows"></i> Windows Settings:</h4>
|
||||
<li><i class="fa-brands fa-windows"></i> Windows scaling set to <b>100%</b> </li>
|
||||
<li><i class="fa-solid fa-toggle-off"></i> HDR <b>off</b></li>
|
||||
<li> Run <b>GT7-TokyoX.exe</b> as <i class="fa-solid fa-person-arrow-up-from-line"></i> Administrator</li>
|
||||
<li><b>Do NOT</b> minimize <i class="fa-brands fa-playstation"></i> Remote Play. Having other windows or programs on top of it is okay, minimizing is <b>NOT</b>. </li>
|
||||
<hr>
|
||||
<h4><i class="fa-brands fa-playstation"></i> Playstation settings:</h4>
|
||||
<li><b><i class="fa-solid fa-toggle-off"></i> Turn off <i class="fa-brands fa-playstation"></i> Playstation system notifications (these can cover the track map, causing issues with our detections)</br>[Example: "Your friend had come online"]</li></br>
|
||||
<b><i class="fa-solid fa-triangle-exclamation"></i> <u>IMPORTANT FOR YOUR OWN SAFETY:</b></u></br>
|
||||
<li><b>Turn ON</b> a password requirement for making any purchases on <i class="fa-brands fa-playstation"></i> PlayStation.</br>This way, when the script has any problems, it will not be possible to buy any MTX by accident.</li></br></br><b><i class="fa-solid fa-circle-exclamation"></i> THEREFORE, WE ARE NOT RESPONSIBLE FOR ACCIDENTAL PURCHASES IF YOU DON’T TURN THIS ON AS A PRECAUTION. <i class="fa-solid fa-circle-exclamation"></i></b>
|
||||
<hr>
|
||||
<h3>Ingame:</h3>
|
||||
<li>Player must have finished all Café Menu Books and the final championship (the one with 5 races). </br> This makes sure you have the <b>Tokyo WTC600 championship unlocked. <i class="fa-solid fa-lock-open"></i></b></li>
|
||||
<li>Player has the <i class="fa-solid fa-car"></i> Dodge SRT Tomahawk X VGT. ($1.000.000)</li>
|
||||
<li>Player has <i class="fa-solid fa-wrench"></i> tuning parts for the <i class="fa-solid fa-car"></i> Dodge SRT Tomahawk X VGT: </br>Ballast, customisable racing transmission, fully adjustable LSD, Racing Hard tires, Intermediate tires. (~$150.000)</li>
|
||||
<hr>
|
||||
<h2>GT7 Settings:</h2>
|
||||
<h3>_car build:</h3>
|
||||
<img class="enlarge-image" src="tokyo_car1.png" alt="Tokyo Car 1" /></br><b>//car settings - 1</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_car2.png" alt="Tokyo Car 2" /></br><b>// car settings - 2</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_car3.png" alt="Tokyo Car 2" /></br><b>// car settings - 3</b>
|
||||
</section>
|
||||
<h3>_misc settings:</h3>
|
||||
<img class="enlarge-image" src="tokyo_difficulty.png" alt="Tokyo Difficulty" /></br><b>// difficulty Setting</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_display.png" alt="Tokyo Display" /></br><b>// display settings</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_drivinggear.png" alt="Tokyo Driving Gear" /></br><b>// driving gear</b>
|
||||
</br></br>
|
||||
<h3>_after race start:</h3>
|
||||
<h4>_-controller settings:</h4>
|
||||
<img class="enlarge-image" src="tokyo_controller1.png" alt="Tokyo Controller 1" /></br><b>// controller - 1</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_controller2.png" alt="Tokyo Controller 2" /></br><b>// controller - 2</b>
|
||||
</br></br>
|
||||
<h4>_-assists settings:</h4>
|
||||
<img class="enlarge-image" src="tokyo_assists1.png" alt="Tokyo Assists 1" /></br><b>// assists - 1</b>
|
||||
</br></br>
|
||||
<img class="enlarge-image" src="tokyo_assists2.png" alt="Tokyo Assists 2" /></br><b>// assists - 2</b>
|
||||
</br></br>
|
||||
<h4>_-cockpit:</h4>
|
||||
<img class="enlarge-image" src="tokyo_cockpitview.png" alt="Tokyo Cockpit" /></br><b>// cockpit - 1</b>
|
||||
</br></br>
|
||||
<hr>
|
||||
<h2>Tokyo X features:</h2>
|
||||
<h3>The script offers you following features:</h3>
|
||||
</br>
|
||||
<div class="tab__container">
|
||||
<ul class="tab__menu">
|
||||
<li class="tab active" data-tab="main">Main GUI</li>
|
||||
<li class="tab" data-tab="race">Settings: Race</li>
|
||||
<li class="tab" data-tab="machine">Settings: Machine/Setup</li>
|
||||
<li class="tab" data-tab="notifications">Settings: Notification</li>
|
||||
<li class="tab" data-tab="endafter">End after X wins</li>
|
||||
</ul>
|
||||
<pre class="nohighlight code">
|
||||
<code class="tab__pane active main">
|
||||
<img class="enlarge-image" src="tokyo_script1.png" alt="Tokyo Script 1" /></br>You <b>start</b> after entering the WTC 600 Tokyo race, pause and hover over "Retry".</br>Tokyo WTC600 championship can be found in Asia, it is (currently) the last race option at the Tokyo Expressway track.</br><p>In the main GUI you can see your current location on the track, in which lap you are (also visualized by a progress bar) and check out your session/all time stats.</br></br></p></code>
|
||||
<code class="tab__pane race"><img class="enlarge-image" src="tokyo_script2.png" alt="Tokyo Script 2" /></br>Select between 2 different pit stop timings.</br></br><img class="enlarge-image" src="tokyo_script3.png" alt="Tokyo Script 3" /></br>Safe (slower): You always stay behind the AI cars after you are in first place.</br>
|
||||
</br></br><img class="enlarge-image" src="tokyo_script4.png" alt="Tokyo Script 4" /></br>Risky (faster): You overtake AI cars, exception: hairpin turn.</br></br><p>Select an option from the dropdown menu, the values are instantly saved and active.</br>You can check out both timings and decide whats suits you better.</p>
|
||||
<p align = "right">...myths says there is even a 3rd option <i class="fa-solid fa-hand-fist"></i></p></code>
|
||||
<code class="tab__pane machine"><img class="enlarge-image" src="tokyo_script5.png" alt="Tokyo Script 5" /></br><p><i class="fa-solid fa-u"></i> <b>Hairpin settings:</br></b></br>The <b>hairpin turn delay</b> in ms dictates how fast the script reacts and turns right after fining the pixel we defined. Start with default settings and watch how your hairpin turns look. In the first lap, the hairpin turn can be pretty wide, they will then be good/perfect for the remaining laps.</br></br>You can try out the option <b>"Dynamic Turn Delay"</b> and find your perfect setup. It measures the time between two detection points and increases/decreases the delay depending on your speed.</p></br><p><i class="fa-solid fa-eye-dropper"></i> <b>Set detection colors:</b></br></br><b>Grab: Pit stop Color</b> - here you can grab the current color when you are <b>stuck in the pit menu </b>(tire selection).</br>You can also manually enter the Hex-Color code when double-clicking on the colored rectangle.</br></br><b>Grab: Restart color</b> - here you can grab the current color when you are <b>stuck in the replay window.</b></br>You can also manually enter the Hex-Color code when double-clicking on the colored rectangle.</p></br><p><i class="fa-solid fa-video"></i> <b>Other Features:</b></br></br><b>Save clip after reset</b> - use the <i class="fa-brands fa-playstation"></i> Playstation feature to record a 3 minutes clip after a reset is triggered.</p></code>
|
||||
<code class="tab__pane notifications"><img class="enlarge-image" src="tokyo_script6.png" alt="Tokyo Script 6" /><p>You can send race reports to your <i class="fa-brands fa-telegram"></i> Telegram Account.</br></br>Here is a <i class="fa-solid fa-book"></i> <b>quick guide</b> how to set it up:</br></br>
|
||||
<ol><li>Open Telegram, and start a conversation with @BotFather</li>
|
||||
<li>In the conversation with @BotFather, type ‘/newbot’.</li>
|
||||
<li>Give your bot a nickname, like BotFather instructs you.</li>
|
||||
<li>Pick a username for the bot as BotFather instructs you.</li>
|
||||
<li>BotFather congratulates you and gives you the HTTP API token. This is what you plug into ‘Telegram Bot Token’ inside the Notifications/API settings in the script.</li>
|
||||
<li>Create a new group chat in Telegram, where you invite your bot and @RawDataBot</li>
|
||||
<li>Type ‘/start’ and the Raw Data Bot will spit out some data. Look for “chat” and specifically “id”. This is what you plug into ‘Telegram Chat ID’. Caution: the ID is not just a number, it also has a special character before the number that you <b>MUST include!</b></li></ol>
|
||||
</p></code>
|
||||
<code class="tab__pane endafter"><img class="enlarge-image" src="tokyo_script1.png" alt="Tokyo Script 1" /><p>You can set the number of wins until the script stops. Default value is 0 (infinite). </br></br>To activate this feature, enter your wanted number with the Up-Down control and HIT the button below. It is changing its text, depending on how many wins you set.</p></code>
|
||||
</pre>
|
||||
</div>
|
||||
<hr>
|
||||
<section class="js-section">
|
||||
<h3 class="section__title">FAQ</h3>
|
||||
<p><i class="fa-solid fa-question"></i> Can i change the pit stop timings while the script is running?</br><i class="fa-solid fa-exclamation"></i> Yes, you can do it and the script will pull the correct timing for the coming pit stop.</p>
|
||||
<p><i class="fa-solid fa-question"></i> My race failed. Is something wrong?</br><i class="fa-solid fa-exclamation"></i> No. Failures will happen due to Randomness. Script is designed to work most of the time, but failures are inevitable.</p>
|
||||
<p><i class="fa-solid fa-question"></i> I can't get my PP to match yours! Help?!</br><i class="fa-solid fa-exclamation"></i> CHECK THE TOE!!!!!</p>
|
||||
<p><i class="fa-solid fa-question"></i> Why do I pit every lap? Wouldn't it be faster to not pit so much?</br><i class="fa-solid fa-exclamation"></i> Faster, yes. But slow is more reliable and the benefit doesn't outweigh the risk.</p>
|
||||
<p><i class="fa-solid fa-question"></i> How long can I safely keep my Playstation running?</br><i class="fa-solid fa-exclamation"></i> That's not up to us. Your mileage may vary. Be responsible.</p>
|
||||
<p><i class="fa-solid fa-question"></i> What do I do with all these credits?</br><i class="fa-solid fa-exclamation"></i> You do you, pikachu.</p>
|
||||
<p><i class="fa-solid fa-question"></i> How long do I have before this gets fixed?</br><i class="fa-solid fa-exclamation"></i> Probably best to think of a patch coming immediately.</p>
|
||||
<p><i class="fa-solid fa-question"></i> Why are you doing this?</br><i class="fa-solid fa-exclamation"></i> To show that we can.</p>
|
||||
<p><i class="fa-solid fa-question"></i> Can I get a beta version of whatever you are working on next?</br><i class="fa-solid fa-exclamation"></i> If this lives long enough for updates to be made, they will be released as they are finished.</p>
|
||||
<p><i class="fa-solid fa-question"></i> Do starting grids matter?</br><i class="fa-solid fa-exclamation"></i> No.</p>
|
||||
<p><i class="fa-solid fa-question"></i> How fast are the laps?</br><i class="fa-solid fa-exclamation"></i> Anywhere between 2:00 and 3:00 depending on pit delay timings and if you happen to get stuck on something for a moment. Before you @ us... slow is reliable. Reliable is enriching.</p>
|
||||
<p><i class="fa-solid fa-question"></i> What should I do if I can't get it to work?</br><i class="fa-solid fa-exclamation"></i> Clubman is great. Panam still works. Ask in the Discord, but know you have options.</p>
|
||||
<hr>
|
||||
<h3>Changelog</h3>
|
||||
<div class="changelog__item">
|
||||
<div class="changelog__meta">
|
||||
<h4 class="changelog__title">Tokyo X</h4>
|
||||
<small class="changelog__date"></small>
|
||||
</div>
|
||||
<div class="changelog__detail">
|
||||
<ul>
|
||||
<li>Initial public release</li>
|
||||
Please provide as much information as possible when asking for help (last status text, lap, location - optimally with a video clip).
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</article>
|
||||
</div>
|
||||
</br>
|
||||
<div class="position-relative marquee-container d-none d-sm-block">
|
||||
<div class="marquee d-flex justify-content-around">
|
||||
<span>Shoutout (alphabetic order) to all these <b>AMAZING PEOPLE</b> from the Discord Tokyo Beta Channel. Thank you for helping me bringing the <b>TOKYO X</b> script to life - it was a great time!</span>
|
||||
</br>
|
||||
<span><shadow2>andow</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Atoms4Piece</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>BeefSupreme</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>BobGT</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>CarapauCorrida</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Chester</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>🐐 </shadow2>(you know)</span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>GTMaster</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>heidi</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>hitomi</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>j0shjones</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>JordanD123</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Krazyy</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>NavS</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Rossey</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Scany</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Septomor</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Sevencuts</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>Solisu</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>TheScythed</shadow2></span>
|
||||
<span><shadow>//</shadow></span>
|
||||
<span><shadow2>x34uvc</shadow2></span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<hr>
|
||||
<footer class="footer">GG! - Tokyo X by problemz
|
||||
|
||||
</footer>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
<script src="scribbler.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,115 @@
|
||||
html, body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* layout */
|
||||
.header {
|
||||
border-bottom: 1px solid var(--code-bg-color);
|
||||
grid-template-columns: 1fr 150px 60% 1fr;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
/* logo */
|
||||
.logo {
|
||||
font-weight: 900;
|
||||
color: var(--primary-color);
|
||||
font-size: 1.4em;
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.logo__thin {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/* menu */
|
||||
.menu {
|
||||
grid-template-columns: 1fr 180px 60% 1fr;
|
||||
}
|
||||
|
||||
.menu__item {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
/* doc */
|
||||
.doc__bg {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 28%;
|
||||
background-color: var(--bg-color);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.doc__nav {
|
||||
flex-basis: 20%;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.doc__nav ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.doc__nav ul.fixed {
|
||||
position: fixed;
|
||||
top: 2rem;
|
||||
}
|
||||
|
||||
.doc__nav li:hover {
|
||||
color: var(--primary-color-light);
|
||||
cursor: pointer;
|
||||
transition: color .3s ease-in-out;
|
||||
}
|
||||
|
||||
.doc__nav .selected {
|
||||
color: var(--accent-color);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.doc__nav .selected:after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: var(--accent-color);
|
||||
left: -1.5rem;
|
||||
top: 0.3rem;
|
||||
}
|
||||
|
||||
.doc__content {
|
||||
flex-basis: 80%;
|
||||
padding: 0 0 5rem 1rem;
|
||||
}
|
||||
|
||||
@media (max-width: 750px) {
|
||||
.wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
.doc__content {
|
||||
padding-left: 0;
|
||||
}
|
||||
.doc__nav ul {
|
||||
border-bottom: 1px solid var(--code-bg-color);
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
.doc__nav ul.fixed {
|
||||
/* nutralized the fixed menu for mobile*/
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
.doc__nav li {
|
||||
display: inline-block;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
.doc__nav .selected:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
/* css variables*/
|
||||
:root {
|
||||
--primary-color: #432E30;
|
||||
--primary-color-light: #8E7474;
|
||||
--accent-color: #FE6A6B;
|
||||
--accent-color-light: #FFE4E4;
|
||||
--accent-color-dark: #B94B4C;
|
||||
--white-color: #FAFBFC;
|
||||
--light-gray-color: #C6CBD1;
|
||||
--medium-gray-color: #959DA5;
|
||||
--dark-gray-color: #444D56;
|
||||
--bg-color: #F8F8FA;
|
||||
--code-bg-color: #F0E8E8;
|
||||
}
|
||||
|
||||
/* normalized */
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: 'Nunito Sans', sans-serif;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
p {
|
||||
font-weight: 300;
|
||||
color: #4A4A4A;
|
||||
}
|
||||
|
||||
a, a:hover {
|
||||
text-decoration: none;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
hr {
|
||||
padding: 1rem 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--bg-color);
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* global components */
|
||||
|
||||
/* typography */
|
||||
.section__title {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.tab__container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab__container > ul {
|
||||
position: absolute;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
right: 1rem;
|
||||
top: -2rem;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tab__container .code {
|
||||
white-space: normal;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: inline-block;
|
||||
padding: 0.3rem 0.5rem;
|
||||
font-weight: 200;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
border-bottom: 1px solid var(--primary-color);
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tab__pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab__pane.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* code */
|
||||
.code {
|
||||
border-radius: 3px;
|
||||
font-family: Space Mono, SFMono-Regular, Menlo,Monaco, Consolas, Liberation Mono, Courier New, monospace;
|
||||
background: var(--bg-color);
|
||||
border: 1px solid var(--code-bg-color);
|
||||
color: var(--primary-color-light);
|
||||
}
|
||||
|
||||
.code--block {
|
||||
white-space: pre-line;
|
||||
padding: 0 1.5rem;
|
||||
}
|
||||
|
||||
.code--inline {
|
||||
padding: 3px 6px;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
.button--primary {
|
||||
padding: 10px 22px;
|
||||
background-color: var(--accent-color);
|
||||
color: white;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
border: 0;
|
||||
transition: all .3s ease-out;
|
||||
}
|
||||
|
||||
.button--primary:after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: var(--accent-color-light);
|
||||
right: -0.4rem;
|
||||
top: -0.4rem;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.button--primary:hover {
|
||||
text-shadow: 0px 1px 1px var(--accent-color-dark);
|
||||
color: white;
|
||||
transform: translate3D(0, -3px, 0);
|
||||
}
|
||||
|
||||
.button--primary:hover::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.button--secondary {
|
||||
padding: 10px 22px;
|
||||
border: 2px solid var(--primary-color);
|
||||
transition: all 0.5s ease-out;
|
||||
}
|
||||
|
||||
.button--secondary:hover {
|
||||
border-color: var(--accent-color);
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
/* links */
|
||||
.link {
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.link--dark {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.link--light {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
/* menu */
|
||||
nav {
|
||||
display: grid;
|
||||
grid-template-columns: 70px auto;
|
||||
}
|
||||
|
||||
.menu {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.toggle span,
|
||||
.toggle span:before,
|
||||
.toggle span:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
width: 18px;
|
||||
border-radius: 2px;
|
||||
background: var(--primary-color);
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease-in-out;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.toggle span:before {
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
.toggle span:after {
|
||||
bottom: -6px;
|
||||
}
|
||||
|
||||
.toggle.open span{
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.toggle.open span:before,
|
||||
.toggle.open span:after {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.toggle.open span:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.toggle.open span:after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.menu__item {
|
||||
padding: 1rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.menu__item.toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* table */
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
transition: color .3s ease-out;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
table td, table th {
|
||||
border: 1px solid var(--code-bg-color);
|
||||
padding: 0.8rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
background-color: white;
|
||||
border-color: white;
|
||||
border-bottom-color: var(--code-bg-color);
|
||||
}
|
||||
|
||||
table td:first-child {
|
||||
background-color: var(--bg-color);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
nav {
|
||||
grid-template-columns: 70px auto;
|
||||
}
|
||||
|
||||
.menu__item{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu__item.toggle {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.menu {
|
||||
text-align: right;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu.responsive .menu__item:not(:first-child) {
|
||||
display: block;
|
||||
padding: 0 0 0.5rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* layout */
|
||||
.wrapper {
|
||||
margin: 0 auto;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
background-color: var(--primary-color);
|
||||
padding: 2rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@keyframes fadeUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0,30px,0);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.enlarge-image {
|
||||
margin-top: 0px;
|
||||
width: 32%;
|
||||
float: center;
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
}
|
||||
.enlarge-image:hover {
|
||||
-webkit-transition: all 0.5s ease-in-out;
|
||||
-moz-transition: all 0.5s ease-in-out;
|
||||
transition: all 0.5s ease-in-out;
|
||||
-moz-transform: scale(3);
|
||||
-webkit-transform: scale(3);
|
||||
-o-transform: scale(3);
|
||||
-ms-transform: scale(3);
|
||||
transform: scale(3);
|
||||
|
||||
}
|
||||
|
||||
.marquee-container {
|
||||
height: 20px;
|
||||
overflow: hidden;
|
||||
line-height: 20px;
|
||||
}
|
||||
.marquee-container .marquee {
|
||||
left: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
animation: marquee 25s linear infinite;
|
||||
}
|
||||
.marquee-container .marquee2 {
|
||||
animation-delay: 20s;
|
||||
}
|
||||
.marquee-container shadow {
|
||||
color: #ffffff;
|
||||
color: #616161;
|
||||
text-shadow: #e0e0e0 1px 1px 0;
|
||||
font-size: 1em;
|
||||
vertical-align: middle;
|
||||
|
||||
}
|
||||
.marquee-container shadow2 {
|
||||
color: #fe6a6b;
|
||||
font-size: 1em;
|
||||
text-shadow: rgba(255,255,255,.1) -1px -1px 1px,rgba(0,0,0,.5) 1px 1px 1px;
|
||||
vertical-align: middle;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@keyframes marquee {
|
||||
0% {
|
||||
left: 100%;
|
||||
}
|
||||
100% {
|
||||
left: -100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// utilities
|
||||
var get = function (selector, scope) {
|
||||
scope = scope ? scope : document;
|
||||
return scope.querySelector(selector);
|
||||
};
|
||||
|
||||
var getAll = function (selector, scope) {
|
||||
scope = scope ? scope : document;
|
||||
return scope.querySelectorAll(selector);
|
||||
};
|
||||
|
||||
// setup typewriter effect in the terminal demo
|
||||
if (document.getElementsByClassName('demo').length > 0) {
|
||||
var i = 0;
|
||||
var txt = `scribbler
|
||||
[Entry mode; press Ctrl+D to save and quit; press Ctrl+C to quit without saving]
|
||||
|
||||
###todo for new year dinner party
|
||||
|
||||
- milk
|
||||
- butter
|
||||
- green onion
|
||||
- lots and lots of kiwis 🥝`;
|
||||
var speed = 60;
|
||||
|
||||
function typeItOut () {
|
||||
if (i < txt.length) {
|
||||
document.getElementsByClassName('demo')[0].innerHTML += txt.charAt(i);
|
||||
i++;
|
||||
setTimeout(typeItOut, speed);
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(typeItOut, 1800);
|
||||
}
|
||||
|
||||
// toggle tabs on codeblock
|
||||
window.addEventListener("load", function() {
|
||||
// get all tab_containers in the document
|
||||
var tabContainers = getAll(".tab__container");
|
||||
|
||||
// bind click event to each tab container
|
||||
for (var i = 0; i < tabContainers.length; i++) {
|
||||
get('.tab__menu', tabContainers[i]).addEventListener("click", tabClick);
|
||||
}
|
||||
|
||||
// each click event is scoped to the tab_container
|
||||
function tabClick (event) {
|
||||
var scope = event.currentTarget.parentNode;
|
||||
var clickedTab = event.target;
|
||||
var tabs = getAll('.tab', scope);
|
||||
var panes = getAll('.tab__pane', scope);
|
||||
var activePane = get(`.${clickedTab.getAttribute('data-tab')}`, scope);
|
||||
|
||||
// remove all active tab classes
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
tabs[i].classList.remove('active');
|
||||
}
|
||||
|
||||
// remove all active pane classes
|
||||
for (var i = 0; i < panes.length; i++) {
|
||||
panes[i].classList.remove('active');
|
||||
}
|
||||
|
||||
// apply active classes on desired tab and pane
|
||||
clickedTab.classList.add('active');
|
||||
activePane.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
//in page scrolling for documentaiton page
|
||||
var btns = getAll('.js-btn');
|
||||
var sections = getAll('.js-section');
|
||||
|
||||
function setActiveLink(event) {
|
||||
// remove all active tab classes
|
||||
for (var i = 0; i < btns.length; i++) {
|
||||
btns[i].classList.remove('selected');
|
||||
}
|
||||
|
||||
event.target.classList.add('selected');
|
||||
}
|
||||
|
||||
function smoothScrollTo(element, event) {
|
||||
setActiveLink(event);
|
||||
|
||||
window.scrollTo({
|
||||
'behavior': 'smooth',
|
||||
'top': element.offsetTop - 20,
|
||||
'left': 0
|
||||
});
|
||||
}
|
||||
|
||||
if (btns.length && sections.length > 0) {
|
||||
// for (var i = 0; i<btns.length; i++) {
|
||||
// btns[i].addEventListener('click', function(event) {
|
||||
// smoothScrollTo(sections[i], event);
|
||||
// });
|
||||
// }
|
||||
btns[0].addEventListener('click', function (event) {
|
||||
smoothScrollTo(sections[0], event);
|
||||
});
|
||||
|
||||
btns[1].addEventListener('click', function (event) {
|
||||
smoothScrollTo(sections[1], event);
|
||||
});
|
||||
|
||||
btns[2].addEventListener('click', function (event) {
|
||||
smoothScrollTo(sections[2], event);
|
||||
});
|
||||
|
||||
btns[3].addEventListener('click', function (event) {
|
||||
smoothScrollTo(sections[3], event);
|
||||
});
|
||||
}
|
||||
|
||||
// fix menu to page-top once user starts scrolling
|
||||
window.addEventListener('scroll', function () {
|
||||
var docNav = get('.doc__nav > ul');
|
||||
|
||||
if( docNav) {
|
||||
if (window.pageYOffset > 63) {
|
||||
docNav.classList.add('fixed');
|
||||
} else {
|
||||
docNav.classList.remove('fixed');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// responsive navigation
|
||||
var topNav = get('.menu');
|
||||
var icon = get('.toggle');
|
||||
|
||||
window.addEventListener('load', function(){
|
||||
function showNav() {
|
||||
if (topNav.className === 'menu') {
|
||||
topNav.className += ' responsive';
|
||||
icon.className += ' open';
|
||||
} else {
|
||||
topNav.className = 'menu';
|
||||
icon.classList.remove('open');
|
||||
}
|
||||
}
|
||||
icon.addEventListener('click', showNav);
|
||||
});
|
||||
|
After Width: | Height: | Size: 462 KiB |
|
After Width: | Height: | Size: 412 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 276 KiB |
|
After Width: | Height: | Size: 513 KiB |
|
After Width: | Height: | Size: 430 KiB |
|
After Width: | Height: | Size: 266 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 292 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,211 @@
|
||||
#include %A_LineFile%\..\CLR.ahk
|
||||
|
||||
; Static class, holds ViGEm Client instance
|
||||
class ViGEmWrapper {
|
||||
static asm := 0
|
||||
static client := 0
|
||||
|
||||
Init(){
|
||||
if (this.client == 0){
|
||||
this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
}
|
||||
}
|
||||
|
||||
CreateInstance(cls){
|
||||
return this.asm.CreateInstance(cls)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
; Base class for ViGEm "Targets" (Controller types - eg xb360 / ds4) to inherit from
|
||||
class ViGEmTarget {
|
||||
target := 0
|
||||
helperClass := ""
|
||||
controllerClass := ""
|
||||
|
||||
__New(){
|
||||
;~ this.asm := CLR_LoadLibrary(A_LineFile "\..\ViGEmWrapper.dll")
|
||||
ViGEmWrapper.Init()
|
||||
this.Instance := ViGEmWrapper.CreateInstance(this.helperClass)
|
||||
|
||||
if (this.Instance.OkCheck() != "OK"){
|
||||
msgbox ViGEmWrapper.dll failed to load!
|
||||
ExitApp
|
||||
}
|
||||
}
|
||||
|
||||
SendReport(){
|
||||
this.Instance.SendReport()
|
||||
}
|
||||
|
||||
SubscribeFeedback(callback){
|
||||
this.Instance.SubscribeFeedback(callback)
|
||||
}
|
||||
}
|
||||
|
||||
; DS4 (DualShock 4 for Playstation 4)
|
||||
class ViGEmDS4 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Ds4"
|
||||
__New(){
|
||||
static buttons := {Square: 16, Cross: 32, Circle: 64, Triangle: 128, L1: 256, R1: 512, L2: 1024, R2: 2048
|
||||
, Share: 4096, Options: 8192, LS: 16384, RS: 32768 }
|
||||
static specialButtons := {Ps: 1, TouchPad: 2}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
for name, id in specialButtons {
|
||||
this.Buttons[name] := new this._SpecialButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _SpecialButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetSpecialButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
return round(state * 2.55)
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dPadDirections := {Up: 0, UpRight: 1, Right: 2, DownRight: 3, Down: 4, DownLeft: 5, Left: 6, UpLeft: 7, None: 8}
|
||||
this._Parent.Instance.SetDpadState(dPadDirections[state])
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; Xb360
|
||||
class ViGEmXb360 extends ViGEmTarget {
|
||||
helperClass := "ViGEmWrapper.Xb360"
|
||||
__New(){
|
||||
static buttons := {A: 4096, B: 8192, X: 16384, Y: 32768, LB: 256, RB: 512, LS: 64, RS: 128, Back: 32, Start: 16, Xbox: 1024}
|
||||
static axes := {LX: 2, LY: 3, RX: 4, RY: 5, LT: 0, RT: 1}
|
||||
|
||||
this.Buttons := {}
|
||||
for name, id in buttons {
|
||||
this.Buttons[name] := new this._ButtonHelper(this, id)
|
||||
}
|
||||
|
||||
this.Axes := {}
|
||||
for name, id in axes {
|
||||
this.Axes[name] := new this._AxisHelper(this, id)
|
||||
}
|
||||
|
||||
this.Dpad := new this._DpadHelper(this)
|
||||
|
||||
base.__New()
|
||||
}
|
||||
|
||||
class _ButtonHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._Id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetButtonState(this._Id, state)
|
||||
this._Parent.Instance.SendReport()
|
||||
return this._Parent
|
||||
}
|
||||
}
|
||||
|
||||
class _AxisHelper {
|
||||
__New(parent, id){
|
||||
this._Parent := parent
|
||||
this._id := id
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
this._Parent.Instance.SetAxisState(this._Id, this.ConvertAxis(state))
|
||||
this._Parent.Instance.SendReport()
|
||||
}
|
||||
|
||||
ConvertAxis(state){
|
||||
value := round((state * 655.36) - 32768)
|
||||
if (value == 32768)
|
||||
return 32767
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
class _DpadHelper {
|
||||
_DpadStates := {1:0, 8:0, 2:0, 4:0} ; Up, Right, Down, Left
|
||||
__New(parent){
|
||||
this._Parent := parent
|
||||
}
|
||||
|
||||
SetState(state){
|
||||
static dpadDirections := { None: {1:0, 8:0, 2:0, 4:0}
|
||||
, Up: {1:1, 8:0, 2:0, 4:0}
|
||||
, UpRight: {1:1, 8:1, 2:0, 4:0}
|
||||
, Right: {1:0, 8:1, 2:0, 4:0}
|
||||
, DownRight: {1:0, 8:1, 2:1, 4:0}
|
||||
, Down: {1:0, 8:0, 2:1, 4:0}
|
||||
, DownLeft: {1:0, 8:0, 2:1, 4:1}
|
||||
, Left: {1:0, 8:0, 2:0, 4:1}
|
||||
, UpLeft: {1:1, 8:0, 2:0, 4:1}}
|
||||
newStates := dpadDirections[state]
|
||||
for id, newState in newStates {
|
||||
oldState := this._DpadStates[id]
|
||||
if (oldState != newState){
|
||||
this._DpadStates[id] := newState
|
||||
this._Parent.Instance.SetButtonState(id, newState)
|
||||
}
|
||||
this._Parent.SendReport()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
; ==========================================================
|
||||
; .NET Framework Interop
|
||||
; https://autohotkey.com/boards/viewtopic.php?t=4633
|
||||
; ==========================================================
|
||||
;
|
||||
; Author: Lexikos
|
||||
; Version: 1.2
|
||||
; Requires: AutoHotkey_L v1.0.96+
|
||||
;
|
||||
|
||||
CLR_LoadLibrary(AssemblyName, AppDomain=0)
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
e := ComObjError(0)
|
||||
Loop 1 {
|
||||
if assembly := AppDomain.Load_2(AssemblyName)
|
||||
break
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 1), args[0] := AssemblyName
|
||||
typeofAssembly := AppDomain.GetType().Assembly.GetType()
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadWithPartialName", 0x158, null, null, args)
|
||||
break
|
||||
if assembly := typeofAssembly.InvokeMember_3("LoadFrom", 0x158, null, null, args)
|
||||
break
|
||||
}
|
||||
ComObjError(e)
|
||||
return assembly
|
||||
}
|
||||
|
||||
CLR_CreateObject(Assembly, TypeName, Args*)
|
||||
{
|
||||
if !(argCount := Args.MaxIndex())
|
||||
return Assembly.CreateInstance_2(TypeName, true)
|
||||
|
||||
vargs := ComObjArray(0xC, argCount)
|
||||
Loop % argCount
|
||||
vargs[A_Index-1] := Args[A_Index]
|
||||
|
||||
static Array_Empty := ComObjArray(0xC,0), null := ComObject(13,0)
|
||||
|
||||
return Assembly.CreateInstance_3(TypeName, true, 0, null, vargs, null, Array_Empty)
|
||||
}
|
||||
|
||||
CLR_CompileC#(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.CSharp.CSharpCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_CompileVB(Code, References="", AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
return CLR_CompileAssembly(Code, References, "System", "Microsoft.VisualBasic.VBCodeProvider", AppDomain, FileName, CompilerOptions)
|
||||
}
|
||||
|
||||
CLR_StartDomain(ByRef AppDomain, BaseDirectory="")
|
||||
{
|
||||
static null := ComObject(13,0)
|
||||
args := ComObjArray(0xC, 5), args[0] := "", args[2] := BaseDirectory, args[4] := ComObject(0xB,false)
|
||||
AppDomain := CLR_GetDefaultDomain().GetType().InvokeMember_3("CreateDomain", 0x158, null, null, args)
|
||||
return A_LastError >= 0
|
||||
}
|
||||
|
||||
CLR_StopDomain(ByRef AppDomain)
|
||||
{ ; ICorRuntimeHost::UnloadDomain
|
||||
DllCall("SetLastError", "uint", hr := DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+20*A_PtrSize), "ptr", RtHst, "ptr", ComObjValue(AppDomain))), AppDomain := ""
|
||||
return hr >= 0
|
||||
}
|
||||
|
||||
; NOTE: IT IS NOT NECESSARY TO CALL THIS FUNCTION unless you need to load a specific version.
|
||||
CLR_Start(Version="") ; returns ICorRuntimeHost*
|
||||
{
|
||||
static RtHst := 0
|
||||
; The simple method gives no control over versioning, and seems to load .NET v2 even when v4 is present:
|
||||
; return RtHst ? RtHst : (RtHst:=COM_CreateObject("CLRMetaData.CorRuntimeHost","{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}"), DllCall(NumGet(NumGet(RtHst+0)+40),"uint",RtHst))
|
||||
if RtHst
|
||||
return RtHst
|
||||
EnvGet SystemRoot, SystemRoot
|
||||
if Version =
|
||||
Loop % SystemRoot "\Microsoft.NET\Framework" (A_PtrSize=8?"64":"") "\*", 2
|
||||
if (FileExist(A_LoopFileFullPath "\mscorlib.dll") && A_LoopFileName > Version)
|
||||
Version := A_LoopFileName
|
||||
if DllCall("mscoree\CorBindToRuntimeEx", "wstr", Version, "ptr", 0, "uint", 0
|
||||
, "ptr", CLR_GUID(CLSID_CorRuntimeHost, "{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr", CLR_GUID(IID_ICorRuntimeHost, "{CB2F6722-AB3A-11D2-9C40-00C04FA30A3E}")
|
||||
, "ptr*", RtHst) >= 0
|
||||
DllCall(NumGet(NumGet(RtHst+0)+10*A_PtrSize), "ptr", RtHst) ; Start
|
||||
return RtHst
|
||||
}
|
||||
|
||||
;
|
||||
; INTERNAL FUNCTIONS
|
||||
;
|
||||
|
||||
CLR_GetDefaultDomain()
|
||||
{
|
||||
static defaultDomain := 0
|
||||
if !defaultDomain
|
||||
{ ; ICorRuntimeHost::GetDefaultDomain
|
||||
if DllCall(NumGet(NumGet(0+RtHst:=CLR_Start())+13*A_PtrSize), "ptr", RtHst, "ptr*", p:=0) >= 0
|
||||
defaultDomain := ComObject(p), ObjRelease(p)
|
||||
}
|
||||
return defaultDomain
|
||||
}
|
||||
|
||||
CLR_CompileAssembly(Code, References, ProviderAssembly, ProviderType, AppDomain=0, FileName="", CompilerOptions="")
|
||||
{
|
||||
if !AppDomain
|
||||
AppDomain := CLR_GetDefaultDomain()
|
||||
|
||||
if !(asmProvider := CLR_LoadLibrary(ProviderAssembly, AppDomain))
|
||||
|| !(codeProvider := asmProvider.CreateInstance(ProviderType))
|
||||
|| !(codeCompiler := codeProvider.CreateCompiler())
|
||||
return 0
|
||||
|
||||
if !(asmSystem := (ProviderAssembly="System") ? asmProvider : CLR_LoadLibrary("System", AppDomain))
|
||||
return 0
|
||||
|
||||
; Convert | delimited list of references into an array.
|
||||
StringSplit, Refs, References, |, %A_Space%%A_Tab%
|
||||
aRefs := ComObjArray(8, Refs0)
|
||||
Loop % Refs0
|
||||
aRefs[A_Index-1] := Refs%A_Index%
|
||||
|
||||
; Set parameters for compiler.
|
||||
prms := CLR_CreateObject(asmSystem, "System.CodeDom.Compiler.CompilerParameters", aRefs)
|
||||
, prms.OutputAssembly := FileName
|
||||
, prms.GenerateInMemory := FileName=""
|
||||
, prms.GenerateExecutable := SubStr(FileName,-3)=".exe"
|
||||
, prms.CompilerOptions := CompilerOptions
|
||||
, prms.IncludeDebugInformation := true
|
||||
|
||||
; Compile!
|
||||
compilerRes := codeCompiler.CompileAssemblyFromSource(prms, Code)
|
||||
|
||||
if error_count := (errors := compilerRes.Errors).Count
|
||||
{
|
||||
error_text := ""
|
||||
Loop % error_count
|
||||
error_text .= ((e := errors.Item[A_Index-1]).IsWarning ? "Warning " : "Error ") . e.ErrorNumber " on line " e.Line ": " e.ErrorText "`n`n"
|
||||
MsgBox, 16, Compilation Failed, %error_text%
|
||||
return 0
|
||||
}
|
||||
; Success. Return Assembly object or path.
|
||||
return compilerRes[FileName="" ? "CompiledAssembly" : "PathToAssembly"]
|
||||
}
|
||||
|
||||
CLR_GUID(ByRef GUID, sGUID)
|
||||
{
|
||||
VarSetCapacity(GUID, 16, 0)
|
||||
return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
|
||||
/**********************************************
|
||||
* Controller methods for simplicity *
|
||||
***********************************************/
|
||||
*/
|
||||
|
||||
GoTo EndControllerFunctionsDef
|
||||
|
||||
;;;;;;;;;;;; Turning functions
|
||||
;;;;;;;;;;;; For holding the stick in a specific position for a period of time
|
||||
;;;;;;;;;;;; Note no other button may be pressed or released when these functions are ran
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (50, 100), 100 being the most, 50 being neutral
|
||||
Turn_Right(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
; Set the time you want to turn for in miliseconds and how hard (0, 50), 0 being the most
|
||||
Turn_Left(sleept, inten){
|
||||
t := sleept
|
||||
controller.Axes.LX.SetState(inten)
|
||||
gosub, Turn
|
||||
controller.Axes.LX.SetState(50)
|
||||
}
|
||||
|
||||
;;;;;;;;;;;; Simple button press functions
|
||||
;;;;;;;;;;;; You can pass a delay amount or leave it blank
|
||||
;;;;;;;;;;;; Longer delays hold the button longer
|
||||
|
||||
; Press X button
|
||||
Press_X(delay:=200){
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press O button
|
||||
Press_O(delay:=200){
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Triangle button
|
||||
Press_Triangle(delay:=200){
|
||||
controller.Buttons.Triangle.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Triangle.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Square button
|
||||
Press_Square(delay:=200){
|
||||
controller.Buttons.Square.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.Square.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_L1(delay:=200){
|
||||
controller.Buttons.L1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.L1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press R1 button
|
||||
Press_R1(delay:=200){
|
||||
controller.Buttons.R1.SetState(true)
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Buttons.R1.SetState(false)
|
||||
return
|
||||
}
|
||||
|
||||
; Press Right on D-pad
|
||||
Press_Right(delay:=200){
|
||||
controller.Dpad.SetState("Right")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Left on D-pad
|
||||
Press_Left(delay:=200){
|
||||
controller.Dpad.SetState("Left")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Up on D-pad
|
||||
Press_Up(delay:=200){
|
||||
controller.Dpad.SetState("Up")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
; Press Down on D-pad
|
||||
Press_Down(delay:=200){
|
||||
controller.Dpad.SetState("Down")
|
||||
DllCall("Sleep", "UInt", delay)
|
||||
controller.Dpad.SetState("None")
|
||||
return
|
||||
}
|
||||
|
||||
;;;;;;;;;;; Other functions specific to GT7
|
||||
|
||||
; Turn on nitrous
|
||||
Nitrous_On(){
|
||||
controller.Buttons.RS.SetState(true)
|
||||
}
|
||||
|
||||
; Turn off nitrous
|
||||
Nitrous_Off(){
|
||||
controller.Buttons.RS.SetState(false)
|
||||
}
|
||||
|
||||
Accel_On(control:=100){
|
||||
controller.Buttons.R2.SetState(true)
|
||||
controller.Axes.RT.SetState(control)
|
||||
}
|
||||
|
||||
Accel_Off(){
|
||||
controller.Buttons.R2.SetState(false)
|
||||
controller.Axes.RT.SetState(0)
|
||||
}
|
||||
|
||||
Brake_On(control:=100){
|
||||
controller.Buttons.L2.SetState(true)
|
||||
controller.Axes.LT.SetState(control)
|
||||
}
|
||||
|
||||
Brake_Off(){
|
||||
controller.Buttons.L2.SetState(false)
|
||||
controller.Axes.LT.SetState(0)
|
||||
}
|
||||
; given time t in miliseconds, turn right for that long, with intensity being how much the turn button is held for
|
||||
Turn:
|
||||
t0 := A_TickCount
|
||||
tf := t0+t
|
||||
loop {
|
||||
Sleep(100)
|
||||
} until A_TickCount > tf
|
||||
return
|
||||
|
||||
|
||||
Press_Options(){
|
||||
controller.Buttons.Options.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Options.SetState(false)
|
||||
}
|
||||
|
||||
PressShare(){
|
||||
controller.Buttons.Share.SetState(true)
|
||||
Sleep, 50
|
||||
controller.Buttons.Share.SetState(false)
|
||||
}
|
||||
|
||||
PressX:
|
||||
; Just for menuing, does not hold X down
|
||||
controller.Buttons.Cross.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Cross.SetState(false)
|
||||
return
|
||||
|
||||
PressO:
|
||||
; Just for menuing, does not hold O down
|
||||
controller.Buttons.Circle.SetState(true)
|
||||
DllCall("Sleep", "UInt", 200)
|
||||
controller.Buttons.Circle.SetState(false)
|
||||
return
|
||||
|
||||
PressRight:
|
||||
; For turning
|
||||
controller.Dpad.SetState("Right")
|
||||
Sleep, 50
|
||||
controller.Dpad.SetState("None")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
EndControllerFunctionsDef:
|
||||
@@ -0,0 +1,136 @@
|
||||
/**********************************************
|
||||
* Only place functions here, no sub routines *
|
||||
***********************************************/
|
||||
|
||||
|
||||
; Grabs the colors of the pixels (x-b, y-b) to (x+b, y+b)
|
||||
; returns the array of colors
|
||||
*/
|
||||
|
||||
BitGrab(x, y, b)
|
||||
{
|
||||
HWND := WinExist("PS Remote Play")
|
||||
pToken := Gdip_Startup()
|
||||
pBitmap := Gdip_BitmapFromHWND2(hwnd)
|
||||
|
||||
pixs := []
|
||||
for i in range(-1*b, b+1){
|
||||
for j in range(-1*b, b+1){
|
||||
pixel := Gdip_GetPixel(pBitmap,x+i,y+j)
|
||||
rgb := ConvertARGB( pixel )
|
||||
pixs.Push(rgb)
|
||||
}
|
||||
}
|
||||
|
||||
Gdip_DisposeImage(pBitmap)
|
||||
Gdip_Shutdown(pToken)
|
||||
return pixs
|
||||
}
|
||||
|
||||
Gdip_BitmapFromHWND2(hwnd)
|
||||
{
|
||||
WinGetPos,,, Width, Height, ahk_id %hwnd%
|
||||
hbm := CreateDIBSection(Width, Height), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
|
||||
RegExMatch(A_OsVersion, "\d+", Version)
|
||||
PrintWindow(hwnd, hdc, Version >= 8 ? 2 : 0)
|
||||
pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
|
||||
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc)
|
||||
return pBitmap
|
||||
}
|
||||
|
||||
range(start, stop:="", step:=1) {
|
||||
static range := { _NewEnum: Func("_RangeNewEnum") }
|
||||
if !step
|
||||
throw "range(): Parameter 'step' must not be 0 or blank"
|
||||
if (stop == "")
|
||||
stop := start, start := 0
|
||||
; Formula: r[i] := start + step*i ; r = range object, i = 0-based index
|
||||
; For a postive 'step', the constraints are i >= 0 and r[i] < stop
|
||||
; For a negative 'step', the constraints are i >= 0 and r[i] > stop
|
||||
; No result is returned if r[0] does not meet the value constraint
|
||||
if (step > 0 ? start < stop : start > stop) ;// start == start + step*0
|
||||
return { base: range, start: start, stop: stop, step: step }
|
||||
}
|
||||
|
||||
_RangeNewEnum(r) {
|
||||
static enum := { "Next": Func("_RangeEnumNext") }
|
||||
return { base: enum, r: r, i: 0 }
|
||||
}
|
||||
|
||||
_RangeEnumNext(enum, ByRef k, ByRef v:="") {
|
||||
stop := enum.r.stop, step := enum.r.step
|
||||
, k := enum.r.start + step*enum.i
|
||||
if (ret := step > 0 ? k < stop : k > stop)
|
||||
enum.i += 1
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
Sleep(ms=1)
|
||||
{
|
||||
global timeBeginPeriodHasAlreadyBeenCalled
|
||||
if (timeBeginPeriodHasAlreadyBeenCalled != 1)
|
||||
{
|
||||
DllCall("Winmm.dll\timeBeginPeriod", UInt, 1)
|
||||
timeBeginPeriodHasAlreadyBeenCalled := 1
|
||||
}
|
||||
|
||||
DllCall("Sleep", UInt, ms)
|
||||
}
|
||||
|
||||
|
||||
|
||||
PixelColorSimple(pc_x, pc_y)
|
||||
{
|
||||
WinGet, remotePlay_id, List, ahk_exe RemotePlay.exe
|
||||
if (remotePlay_id = 0)
|
||||
{
|
||||
MsgBox, PS4 Remote Play not found
|
||||
return
|
||||
}
|
||||
if remotePlay_id
|
||||
{
|
||||
pc_wID := remotePlay_id[0]
|
||||
pc_hDC := DllCall("GetDC", "UInt", pc_wID)
|
||||
pc_fmtI := A_FormatInteger
|
||||
SetFormat, IntegerFast, Hex
|
||||
pc_c := DllCall("GetPixel", "UInt", pc_hDC, "Int", pc_x, "Int", pc_y, "UInt")
|
||||
pc_c := pc_c >> 16 & 0xff | pc_c & 0xff00 | (pc_c & 0xff) << 16
|
||||
pc_c .= ""
|
||||
SetFormat, IntegerFast, %pc_fmtI%
|
||||
DllCall("ReleaseDC", "UInt", pc_wID, "UInt", pc_hDC)
|
||||
return pc_c
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GetClientSize(hWnd, ByRef w := "", ByRef h := "")
|
||||
{
|
||||
VarSetCapacity(rect, 16)
|
||||
DllCall("GetClientRect", "ptr", hWnd, "ptr", &rect)
|
||||
w := NumGet(rect, 8, "int")
|
||||
h := NumGet(rect, 12, "int")
|
||||
}
|
||||
|
||||
Distance(c1, c2)
|
||||
{ ; function by [VxE], return value range = [0, 441.67295593006372]
|
||||
return Sqrt((((c1>>16)-(c2>>16))**2)+(((c1>>8&255)-(c2>>8&255))**2)+(((c1&255)-(c1&255))**2))
|
||||
}
|
||||
|
||||
ConvertARGB(ARGB, Convert := 0)
|
||||
{
|
||||
SetFormat, IntegerFast, Hex
|
||||
RGB += ARGB
|
||||
RGB := RGB & 0x00FFFFFF
|
||||
if (Convert)
|
||||
RGB := (RGB & 0xFF000000) | ((RGB & 0xFF0000) >> 16) | (RGB & 0x00FF00) | ((RGB & 0x0000FF) << 16)
|
||||
|
||||
return RGB
|
||||
}
|
||||
|
||||
ToolTipper(msg, x := 100, y := 100)
|
||||
{
|
||||
if (debug_mode = 1)
|
||||
ToolTip, %msg%, x, y, Screen
|
||||
return
|
||||
}
|
||||