07.12.2013, 03:37
(
Последний раз редактировалось JoshuaFoster; 07.12.2013 в 07:55.
Причина: Improved code
)
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
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
$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
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