Page 1 of 1

Click without in foreground

Posted: Fri Aug 14, 2009 7:34 am
by master121
is it possible to use mouseclickL when the window is not in foreground ?

Re: Click without in foreground

Posted: Fri Aug 14, 2009 7:37 am
by d003232
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.

Re: Click without in foreground

Posted: Fri Aug 14, 2009 7:54 am
by Administrator
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);

Re: Click without in foreground

Posted: Fri Aug 14, 2009 7:56 am
by master121
Hm im trying to do autorepair without having the win in foreground but thanks anyway

Re: Click without in foreground

Posted: Fri Aug 14, 2009 7:52 pm
by Rishijin
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)?

Re: Click without in foreground

Posted: Sat Aug 15, 2009 1:46 am
by d003232
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.

Re: Click without in foreground

Posted: Sat Aug 15, 2009 10:36 am
by master121
Yep but then there is a conversion where you have to click an answer to open the shop :/

Re: Click without in foreground

Posted: Sat Aug 15, 2009 1:20 pm
by d003232
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.

Re: Click without in foreground

Posted: Sun Aug 16, 2009 1:48 pm
by 3cmSailorfuku
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.

Re: Click without in foreground

Posted: Tue Aug 18, 2009 8:33 am
by master121
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