Samp Client Chat Translator (not server) -
JoshuaFoster - 07.12.2013
Hi, I made this
Autoit script which translate the chat messages from russian servers, actually it can translate from all languages(though I didn't test it). You only have to change these variables:
$mylang = "en"
$serverlang = "ru"
$codepage = 1251 ; Change this to the server language codepage(in this case
1251 is for ANSI Cyrillic)
And Run the script after starting GTA SA when chatbox is visible
Also press F10 to translate your message
Код:
#include <Array.au3>
#include <WinAPI.au3>
Opt("SendKeyDelay", 30)
$mylang = "en"
$serverlang = "ru"
$codepage = 1252 ; Latin(en,es)
$firstTime = True
$linesShifted = 1
$lastLineTrans = ""
$iRead = 0
$pID = WinGetProcess('GTA:SA:MP')
$hwnd = _WinAPI_OpenProcess(0x1F0FFF, False, $pID)
If (Not HotKeySet("{F10}", "TranslateMine")) Then
MsgBox(16, "Error", "Could not register the F10 hotkey.")
Exit
EndIf
;====CHANGE CODEPAGE TO SERVER LANG===
Switch $serverlang
case "ru"
$codepage = 1251
EndSwitch; TODO: try more codepages with servers
;====GET MEMORY ADDRESS====
$Modules = DllStructCreate("ptr[1024]")
$aCall = DllCall("psapi.dll", "int", "EnumProcessModules", "ptr", $hwnd, "ptr", DllStructGetPtr($Modules), "dword", DllStructGetSize($Modules), "dword*", 0)
If $aCall[4] > 0 Then
$iModnum = $aCall[4] / 4
Local $aTemp
For $i = 1 To $iModnum
$aTemp = DllCall("psapi.dll","dword","GetModuleBaseNameW","ptr",$hwnd,"ptr",Ptr(DllStructGetData($Modules,1,$i)), "wstr","","dword",260)
If $aTemp[3] = "samp.dll" Then
$addr = Ptr(DllStructGetData($Modules, 1, $i)); samp.dll base address :D
$Modules = 0
ExitLoop
EndIf
Next
EndIf
$s = DllStructCreate('dword')
$addr = $addr + 0x212A24 ; Pointer of Chatbox class for Samp 0.3x. This will change in future versions of SA-MP!!!
_WinAPI_ReadProcessMemory($hwnd,$addr,DllStructGetPtr($s),DllStructGetSize($s),$iRead)
$addr = DllStructGetData($s, 1)+0x62C6 ; the last line of chat messages (after the time)
$s = 0
;==========================
;==========MAIN============
While True
If $firstTime Then
$firstTime = False
Else
$linesShifted = GetLinesShifted($lastLineTrans)
EndIf
If $linesShifted > 0 Then
$r = ReadLines($addr, $linesShifted); save it to var $lines because
$r = Asc2Utf8($r)
$r = ******Translate($r, $serverlang, $mylang)
$lastLineTrans = WriteToMemory($addr, $r)
Send("{PGUP}{PGDN}") ;To refresh chatbox. With key F10 sometimes doesn't work
EndIf
If ProcessExists($pID) = 0 Then Exit
Sleep(2000)
WEnd
;==========================
;=======FUNCTIONS==========
Func TranslateMine()
Send("^a")
Send("^c")
$r = ******Translate(ClipGet(), $mylang, $serverlang)
$r = _WinAPI_WideCharToMultiByte($r[0], $codepage)
Send($r)
EndFunc
Func ReadLines($addr, $n)
$lines = ""
$s = DllStructCreate('char[128]')
For $i = 0 To $n - 1 Step 1
_WinAPI_ReadProcessMemory($hwnd, $addr, DllStructGetPtr($s), DllStructGetSize($s), $iRead)
$lines &= DllStructGetData($s, 1) & '%0A'
$addr -= 0xFC
Next
$s = 0
Return $lines
EndFunc
Func Asc2Utf8($str)
$r = _WinAPI_MultiByteToWideChar($str, $codepage)
$r = _WinAPI_WideCharToMultiByte($r, 65001)
Return $r
EndFunc
Func ******Translate($str, $from, $to)
If $str <> "" Then
$r = InetRead("http://translate.******.com/translate_a/t?client=p&text="&$str&"&sl="&$from&"&tl="&$to&"&ie=UTF-8&oe=UTF-8&multires=0", 16)
$r = BinaryToString($r, 4)
$r = StringRegExp($r, '(?:trans"\:")((?:[^"\\]|\\.)*)', 3)
$r = _ArrayToString($r, "")
$r = StringRegExpReplace($r, '\\"', '"')
$r = StringSplit($r, '\n', 3)
Return $r
EndIf
EndFunc
Func WriteToMemory($addr, $List)
For $i = 0 To UBound($List) - 1 Step 1
$s2 = DllStructCreate("char[" & StringLen($List[$i]) & "]")
DllStructSetData($s2, 1, $List[$i])
_WinAPI_WriteProcessMemory($hwnd, $addr, DllStructGetPtr($s2), DllStructGetSize($s2), $iRead)
$addr -= 0xFC
Next
Return $List[0]
EndFunc
Func GetLinesShifted($line)
$s = DllStructCreate('char[128]')
For $i = 0 To 8 Step 1
_WinAPI_ReadProcessMemory($hwnd, $addr, DllStructGetPtr($s), DllStructGetSize($s), $iRead)
If $line = DllStructGetData($s, 1) Then ExitLoop
Next
$s = 0
Return $i
EndFunc
;Notes: Get ****** translation takes around 1 sec. So in that time samp could get new msgs. I tried to add linesShifted in WriteToMemory, but it always messed the execution. I don't know why
This is what the script do:
1. Get the memory address of the chatbox
2. Read the messages(line by line) from the gta.exe memory
3. Get their ****** translation, parse the json response
4. Write the translated messages to the same memory address
5. Update the chatbox pressing PageUp and PageDown(you see a blink. If still the same, then press PgUp PgDwn manually)
6. On the Input Chatbox press F10 (after typed) and wait a sec, it will be translated to the server lang
Note: About Codepages I still didn't improved the code. You can look for it in
http://en.wikipedia.org/wiki/Windows_code_pages
Re: Samp Client Chat Translator (not server) -
Uberanwar - 11.12.2013
nice one