Samp Client Chat Translator (not server)
#1

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
Reply
#2

nice one
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)