Click without in foreground

Runes of Magic/Radiant Arcana (http://www.runesofmagic.com)
Post Reply
Message
Author
master121
Posts: 45
Joined: Mon Dec 29, 2008 10:40 am

Click without in foreground

#1 Post by master121 » Fri Aug 14, 2009 7:34 am

is it possible to use mouseclickL when the window is not in foreground ?

d003232
Posts: 1252
Joined: Wed Jun 03, 2009 4:27 pm

Re: Click without in foreground

#2 Post by d003232 » Fri Aug 14, 2009 7:37 am

master121 wrote:is it possible to use mouseclickL when the window is not in foreground ?
I don't think so. Perhaps Admin could say something about that? If there will come a new functionality for that? You can try to use the

Code: Select all

			local sfn = getExecutionPath() .. "/profiles/" .. player.Name .. ".bmp";
			saveScreenshot(getWin(), sfn);
to force the window to come to the foreground. I suppose that will work at least sometimes. I don't tested it by myselfe.
The RoM Bot Online Wiki needs your help!

User avatar
Administrator
Site Admin
Posts: 5306
Joined: Sat Jan 05, 2008 4:21 pm

Re: Click without in foreground

#3 Post by Administrator » Fri Aug 14, 2009 7:54 am

Not at this time, no. To force a window to the foreground (which will only work if it's paired MicroMacro window is already in the foreground), you can use this code:

Code: Select all

showWindow(getWin(), sw.show);

master121
Posts: 45
Joined: Mon Dec 29, 2008 10:40 am

Re: Click without in foreground

#4 Post by master121 » Fri Aug 14, 2009 7:56 am

Hm im trying to do autorepair without having the win in foreground but thanks anyway

User avatar
Rishijin
Posts: 49
Joined: Sat Jul 04, 2009 4:25 pm
Location: Kauai

Re: Click without in foreground

#5 Post by Rishijin » Fri Aug 14, 2009 7:52 pm

Can't you just write to the memory in game that turns true when you click the mouse (probably a value of 128 when clicking, 0 when not)?

d003232
Posts: 1252
Joined: Wed Jun 03, 2009 4:27 pm

Re: Click without in foreground

#6 Post by d003232 » Sat Aug 15, 2009 1:46 am

master121 wrote:Hm im trying to do autorepair without having the win in foreground but thanks anyway
There's a new function

Code: Select all

player:target_NPC( npc_name );
in SVN 152.

It will try to target the nearest NPC's and find the NPC by name. After that the bot will open the dialog windown. The RoM window don't have to be in the foreground for using that function.
The RoM Bot Online Wiki needs your help!

master121
Posts: 45
Joined: Mon Dec 29, 2008 10:40 am

Re: Click without in foreground

#7 Post by master121 » Sat Aug 15, 2009 10:36 am

Yep but then there is a conversion where you have to click an answer to open the shop :/

d003232
Posts: 1252
Joined: Wed Jun 03, 2009 4:27 pm

Re: Click without in foreground

#8 Post by d003232 » Sat Aug 15, 2009 1:20 pm

master121 wrote:Yep but then there is a conversion where you have to click an answer to open the shop :/
Just use the ingame addon streamline. That will autorepair after opening the dialog window/shop.
The RoM Bot Online Wiki needs your help!

User avatar
3cmSailorfuku
Posts: 354
Joined: Mon Jan 21, 2008 6:25 pm

Re: Click without in foreground

#9 Post by 3cmSailorfuku » Sun Aug 16, 2009 1:48 pm

Rishijin wrote:Can't you just write to the memory in game that turns true when you click the mouse (probably a value of 128 when clicking, 0 when not)?

Code: Select all

/* MouseControl.cpp
  Exports 2 functions:
  - void MouseClick(DWORD X,DWORD Y)
  - void MouseMove(DWORD X,DWORD Y)

  Credits to:
  -me(backtoreality) ;)
  -elverion
*/

//Header
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
//Detours 2.1
#include <detours.h>

#pragma comment(lib, "detours.lib" )

#define EXPORT extern "C" __declspec(dllexport)

//Logfile
#define LOGFILENAME "C:\\temp\\Log.txt"

//Adresses
#define PLAYERBASE_PTR 0x0088FF40
#define InjectAddress 0x00681D7A
#define InjectAddressJumpFrom (InjectAddress + 6)

//Offsets
#define OFF_MOUSE_X 0x03A4					//DWORD
#define OFF_MOUSE_Y 0x03A8                  //DWORD
#define OFF_INGAME_MOUSE_BUTTON_UP 0x03AC   //DWORD
#define OFF_INGAME_MOUSE_BUTTON_DOWN 0x03B0 //DWORD
#define OFF_BG_Flag 0x2C					//Byte

//Globale Variablen
DWORD BasePTR;
LPVOID MemSpace;
DWORD VarPTR;
bool Injected=false;
enum Events{No_Event,DoMouseClick,DoResetMouseButtons,DoMouseMove};

#pragma data_seg(".shared")

bool Inject = true;
int Event = No_Event;
DWORD Mouse_X = 0;
DWORD Mouse_Y = 0;

#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS") 

//Functions we need:
void CreateJump(DWORD JumpFrom,DWORD JumpTo,BYTE* buffer);
void InsertAdress(DWORD Addr,BYTE* buffer);
void AdjustCodeCave(DWORD VarPTR,BYTE* CodeCave);
void InsertCodeCave();
bool LogWriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress,LPCVOID lpBuffer,SIZE_T nSize);
void WriteLogFileLine(char * format,...);

//Exported Functions
//performs a mouse click at X,Y
EXPORT void MouseClick(DWORD X,DWORD Y){
		Mouse_X = X;
		Mouse_Y = Y;
		Event = DoMouseClick;
}

//moves the mouse to X,Y in memory
EXPORT void MouseMove(DWORD X,DWORD Y){
		Mouse_X = X;
		Mouse_Y = Y;
		Event = DoMouseMove;
}

//Hooked Functions
extern "C" { 
   //Runes of Magic uses ASCII
   static LRESULT (WINAPI *Real_DispatchMessageA)( const MSG* msg) = DispatchMessageA;
}

//DispatchMessage is very often called so we use this function to check if we have something to do
LRESULT WINAPI Mine_DispatchMessageA( const MSG* msg )
{
	if( Event == DoMouseClick ){
		BYTE BNull = 0x00;
		DWORD PerformClick = 0x00000001;
		DWORD NullWert = 0x00000000;
		DWORD error;

		WriteLogFileLine("Performing MouseClick at X: %i Y: %i",(int)Mouse_X,(int)Mouse_Y);

		//Set BG_Flag to 0
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_BG_Flag),(LPCVOID)&BNull,sizeof(BYTE));

		//Set MousePos_X
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_MOUSE_X),&Mouse_X,sizeof(DWORD));

		//Set MousePos_Y
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_MOUSE_Y),&Mouse_Y,sizeof(DWORD));

		//Set Ingame Mouse Button Down
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_INGAME_MOUSE_BUTTON_DOWN),&PerformClick,sizeof(DWORD));

		//And remove the up value
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_INGAME_MOUSE_BUTTON_UP),&NullWert,sizeof(DWORD));

		//Execute Click
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)VarPTR,(LPCVOID)&PerformClick,sizeof(DWORD));

		Event = DoResetMouseButtons;

		return Real_DispatchMessageA( msg );
	}
	else if(Event == DoResetMouseButtons){
		DWORD dEins = 0x00000001;
		DWORD dNull = 0x00000000;

		//Set Ingame Left Mouse Button Up
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_INGAME_MOUSE_BUTTON_DOWN),&dNull,sizeof(DWORD));

		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_INGAME_MOUSE_BUTTON_UP),&dEins,sizeof(DWORD));
	}
	else if(Event == DoMouseMove){
		BYTE BNull = 0x00;

		WriteLogFileLine("Performing MouseMove to X: %i Y: %i",(int)Mouse_X,(int)Mouse_Y);

		//Set BG_Flag to 0
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_BG_Flag),(LPCVOID)&BNull,sizeof(BYTE));

		//Set MousePos_X
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_MOUSE_X),&Mouse_X,sizeof(DWORD));

		//Set MousePos_Y
		LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)(BasePTR+OFF_MOUSE_Y),&Mouse_Y,sizeof(DWORD));
	}

   Event = No_Event;
   return Real_DispatchMessageA( msg );
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD dwReason, LPVOID lpReserved )
{
   int err = 0;

   switch( dwReason ) {
      case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls( hModule );
		 if(Inject == true){
			remove(LOGFILENAME);

			WriteLogFileLine("Attached...");

			//Avoid anew injection
			Inject = false;
			Injected = true;

			//Insert our CodeCave to enable MouseClick
			InsertCodeCave();

			//Read PlayerbasePTR, because we need it for BG_FLAG, Mouse X,Y Coord and Ingame MouseButton
			ReadProcessMemory(GetCurrentProcess(),(VOID*)PLAYERBASE_PTR,&BasePTR,sizeof(DWORD),NULL);

			WriteLogFileLine("PlayerBase: %X",BasePTR);

			DetourTransactionBegin();
			DetourUpdateThread( GetCurrentThread() );
			DetourAttach( &(PVOID&)Real_DispatchMessageA, Mine_DispatchMessageA );
			DetourTransactionCommit();
		 }
         break;
      case DLL_PROCESS_DETACH:
		  if(Injected){
			WriteLogFileLine("Detached...");

			DetourTransactionBegin();
			DetourUpdateThread( GetCurrentThread() );
			DetourDetach( &(PVOID&)Real_DispatchMessageA, Mine_DispatchMessageA );
			DetourTransactionCommit();
		 }
         break;
   }
   return TRUE;
}  

//write to log
void WriteLogFileLine(char * format,...){
	FILE* pLog = fopen(LOGFILENAME,"a");
	char buffer[512];
	va_list args;
	va_start (args, format);
	vsprintf (buffer,format, args);
	strcat(buffer,"\n");
	fputs(buffer,pLog);
	va_end (args);
	fclose(pLog);
}

//insert the codecave into memory
void InsertCodeCave(){
	//Patch and CodeCave
	/*
	CodeCave: 
			CMP BYTE PTR DS:[VAR],1
			JNE SHORT 0x0E
			MOV BYTE PTR DS:[ESI+100],1
			MOV BYTE PTR DS:[VAR],0
			CMP BYTE PTR DS:[ESI+100],AL
			JMP 00681D80

	*/
	BYTE CodeCave[] = {0x80,0x3D,0x00,0x00,0x00,0x00,0x01,0x75,0x0E,0xC6,0x86,0x00,0x01,0x00,0x00,0x01,0xC6,0x05,0x00,0x00,0x00,0x00,0x00,0x38,0x86,0x00,0x01,0x00,0x00,0xE9,0xFE,0x1D,0xC0,0x88};
	BYTE CallToCC[6];

	//CodeCave sizeof(CodeCave)
	//Variable 4 Byte
	MemSpace = VirtualAlloc(NULL,sizeof(CodeCave)+4,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
	VarPTR = (DWORD)((DWORD)MemSpace + sizeof(CodeCave));

	CallToCC[0] = 0x90; //NOP damit es passt
	CreateJump(InjectAddressJumpFrom,((DWORD)MemSpace),&CallToCC[1]);
	AdjustCodeCave((DWORD)MemSpace+sizeof(CodeCave),CodeCave);

	WriteLogFileLine("CodeCave at: %X",(DWORD)MemSpace);
		 
	//Write CodeCave first
	LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)((DWORD)MemSpace),CodeCave,sizeof(CodeCave));

	//Now write Call into Process
	LogWriteProcessMemory(GetCurrentProcess(),(LPVOID)InjectAddress,CallToCC,sizeof(CallToCC));
}

//adjust códecave with VarPTR and adjust jump at the end
void AdjustCodeCave(DWORD VarPTR,BYTE* CodeCave){
	/*Anzupassende Adressen:
		- 2 VarPTR
		- 18 VarPTR
		- 30 InjectAddressJumpFrom
	*/
	InsertAdress(VarPTR,&CodeCave[2]);
	InsertAdress(VarPTR,&CodeCave[18]);
	CreateJump(VarPTR,InjectAddressJumpFrom,&CodeCave[29]);
}

//Insert an adress into an array of bytes
void InsertAdress(DWORD Addr,BYTE* buffer){
	buffer[0] = Addr;
    buffer[1] = Addr>>8;
    buffer[2] = Addr>>16;
    buffer[3] = Addr>>24;
}

//Creates an Jump from JumpFrom to JumpTo which needs 5 Bytes
void CreateJump(DWORD JumpFrom,DWORD JumpTo,BYTE* buffer){
    DWORD diff = JumpTo-JumpFrom;
    
    buffer[0] = 0xE9; //JMP
    buffer[1] = diff;
    buffer[2] = diff>>8;
    buffer[3] = diff>>16;
    buffer[4] = diff>>24;    
}

bool LogWriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress,LPCVOID lpBuffer,SIZE_T nSize){
	unsigned long BytesWritten=0,error=0;
	DWORD Address;

	if( WriteProcessMemory(hProcess,lpBaseAddress,lpBuffer,nSize,&BytesWritten) == NULL ){
		error = GetLastError();
		Address = (DWORD)lpBaseAddress;
		WriteLogFileLine("Error: %i. Fail to write at Address: %X. ",error,Address);
		return false;
	} else {
		WriteLogFileLine("Success writing at: %X. %i Bytes written.",(DWORD)lpBaseAddress,BytesWritten);
		return true;
	}
}
If you want to use this in newest version you only have to edit:
#define PLAYERBASE_PTR 0x0088FF40
#define InjectAddress 0x00681D7A
to get the InjectAddress you only need to scan client.exe for 8B 74 24 14 8A 91 00 09 00 00 32 C0 38 86 00 01 00 00.
The Exports which can be used from the bot are documentated at the top.

master121
Posts: 45
Joined: Mon Dec 29, 2008 10:40 am

Re: Click without in foreground

#10 Post by master121 » Tue Aug 18, 2009 8:33 am

Huu i don´t know anything about that language :(
But like with lua i´ll manage all allright when you say how to compile that :D

Post Reply

Who is online

Users browsing this forum: No registered users and 34 guests