/* addresses 
1AA3D74 (1 for in game, 0 for not);
others 1AA8DC0, 1AA8DE0 all static


*/
#include <Windows.h>
#include <fstream>
#include <iostream>
#include <string.h>
//#include <gl\gl.h>								// Header File For The OpenGL32 Library/
//#include <gl\glu.h>								// Header File For The GLu32 Library
//#include <gl\glaux.h>								// Header File For The GLaux Library
//#include<d3d9.h>  //Direct3D header
//#include<d3dx9.h> //Direct3DX header (NEW)

#define WIN32_LEAN_AND_MEAN
#define InGame *(int*)0x1AA8F00
#define GoFarmBot (GetAsyncKeyState(VK_F11) != -32767)
#define F11Hit (GetAsyncKeyState(VK_F11) == -32767)
#define F12Hit (GetAsyncKeyState(VK_F12) == -32767)
#define TargetAlive (*(TData).Hp > 0)
#define TargetDead (*(TData).Hp < 0)
#define ToonAlive (*(PData).Hp > 0)
// if current window is open (sb) then we take commands 02802B51 or 028AD4CC
#define InWindow (*(BYTE*)0x02802B51)
// in window and hit left key
#define ExitKey (GetAsyncKeyState(VK_F12) < 0)
//#define TargetAlive
#define InstanceOne 0x400000

// current instance
int Instance = InstanceOne;

// pid and handles and stuff 
unsigned long dwID; //The thread ID
DWORD PID; // process id returned from getprocid
HWND SBwnd; // Shadobane window handle

// basic text stuff
char *WinTitle = "SBTools2 Beta zonemikel.com"; 
char *TestText = "Test"; // testing text to selection box

// int functions
long WINAPI HotKeys(long lParam); //Function declaration, for Hotkeys with WINAPI

// windows x pos(add 4 for y pos 8 for x size C for y size)
int WinXPosBase = 0x012C2128; // the base you add to the instance 
int XPosOffsets[] = {0x370,0x2E8,0x1C8,0x70,0x25C,0x08,777}; // x position of current window
int YPosOffsets[] = {0x370,0x2E8,0x1C8,0x70,0x25C,0x0C,777}; // y position of current window
int XSizeOffsets[] = {0x370,0x2E8,0x1C8,0x70,0x25C,0x10,777}; // x size of current window
int YSizeOffsets[] = {0x370,0x2E8,0x1C8,0x70,0x25C,0x14,777}; // y size of current window

// target stuff 
//const int TBase = 0x27934500; // base holder for target stats
//const int THpCurrent = (TBase + 0x5CC); //Target hit points current
//const int SBInGame = 0x1AA3D74; // 1 for in game
//const int SBAttack = 0x0054194D; // location in asm that starts attack ? 
// we will use *(BYTE*)0x1AA3D74) in the code instead

// struct with all ini stuff 
typedef struct{
        short AttackKey1;
        short AttackKey2;
        short AttackKey3;
		int KeyDelay;
		short TargetNPC;
		short SitKey;
		short InventoryKey;
        long HealHP;
        long HealMana;
        long HealStam;
        int UsePet;
        short SelectPet;
        short PetAttack;
        int Loot;
        short OpenKey;
        int AllItems;
		int DumpItems;
		int LootItemX;
		int LootItemY;
		int LootCloseX;
		int LootCloseY;
		int WaitTime;
		
       }INI;
INI config;
INI *con = &config;
// struct with all player stuff
typedef struct{
	float *Hp;
	float *MaxHp;
	float *Mana;
	float *MaxMana;
	float *Stam;
	float *MaxStam;
	float *Latitude;
	float *Longitude;
	int *Gold;
	int *InvWeight;
	int *XP;
	int Kills;
	int *LootOpen;
	int Type; // 0 for nothing, 1 for mob/npc, 2 for item pot/sword, 3 for wall etc
	int *Fname;
	int *Lname;
	int FnameLen; // lenght of name 
	int LnameLen;
	char FirstName[200];

}STATS;
STATS PData;
// this does never seem to work when i do Toon->hp or *Toon->hp maybe *(Toon)->hp but whats the point ? 
//STATS *Toon = &PData;
STATS TData;
//STATS *Target = &TData;

typedef struct{ // this is the keys stucture most of the keys are in a array of this type
short Key; // the key to hit 
int CastTime; // time to cast the key
int CoolDown; // the cooldown time (seconds)
int LastHit; // last time hit
}Keys; 
Keys AttackKeys[10];
Keys GeneralKeys[10];
Keys HealKeys[10];
Keys BuffKeys[10];

//functions here
class HackFunctions{ //HackFunctions class
public:
	//Function declarations
	void KeyHook(); // global keyboard hook
	void SBScreenPrint(char* text, int x, int y); // prints to screen 
	void SBNameOut(char* text1, char* text2);
	void SBTravOut(char* text1, char* text2, char* text3, char* text4);// sends text to trav stance stats
	void DumpItems(); // dump items out of the inventory
	void SelBoxPrint();// prints to select box, i hope
	void FarmBot();// farmbot duh
	void SendKey(short key); // sends key to sb
	void SendKeyArray(Keys KeyArray[]); //sends a whole array of keys with timers
	bool Startup(); // start up mem locations, ini read etc
	int UpdateTarget(int Target);
	int UpdatePlayer();
	int GetPointer(int base, int offsets[]);
	void LogFile(char *ToLog);
	void Window(int Action, int Number);
	
	//ini stuff also made by me
	short getkey(char* section, char* key);
	long getint(char* section, char* key);
	int SetupKeys(char* section, char* key, Keys KeyArray[]); // for mulitple keys like attack and buff keys
	// stuff in order
	void Click(int xPos, int yPos, int side);
protected:
	//Variables only accessible to the class member functions
	//Variables, with pointer declarations, and regular variables with int
}Hack; //Declare the HackFunctions type, with MinHack

// float goal = *reinterpret_cast<float *>( * reinterpret_cast<int *>(0x1AA3DCC) + 0x5CC);
//(*((DWORD *)0x1AA3DCC)+0x5CC)
// (DWORD)(*((BYTE *)(0x1AA3DCC) + 0x5CC)));
int pBaseAddr = *(int *) 0x1AA4058; // player stats base addr
int tBaseAddr = *(int *) 0x1AA4064; // target stats base addr
int TravStanceAddr;

// functions in Hackfunctions Class
void HackFunctions::LogFile(char *ToLog) // sends text to log file with a timestamp so we can see what happened
{
  SYSTEMTIME LogTime; 
  GetSystemTime(&LogTime);
  char PreMessage[300];
  std::ofstream LogFile ( "SBTools.log", std::ios::app);
  sprintf(PreMessage,"\n[%d-%d %d:%d] ",LogTime.wMonth,LogTime.wDay,LogTime.wHour,LogTime.wMinute);
  LogFile << PreMessage << ToLog;
  LogFile.close();
}

// make these so they are only set once they are giving me a headache
// thes are all set to 0 on farmbot start so it only checks once every time farmbot starts
int Xpos, Ypos, Xsize, Ysize;
void HackFunctions::Window(int Action, int Number)
{
	// 0 = close window
	// 1 = get item "Number"
	// 2 = Click Number = 1 Yes else click no
	// 3 = click ok
	//char test[200];
	/* Window Sizes 
	   local map 210x210
	   button(power etc) 28x28
	   hotbar 105x252 (with 2col 8 rows of buttons)
	   chat 304x102 (varies !)
	   selection small 246x60
	   status bar 246x60 	
	*/

	//if(Number == 8 && (*(PData).LootOpen != 1)){return;} // loot window is not open stop ! while dumping items
	if(ExitKey){return;}
	Hack.UpdateTarget(0);
	Sleep(200);
	//if(Number == 1 && (*(TData).LootOpen != 1))
	//{return;} // they are looting but target is not selected!
	int i=0;
	int row = 0;
	int col = 0;
	if (Xpos == 0)
	{
		Xpos = *(int *)(Hack.GetPointer((Instance + WinXPosBase),XPosOffsets));
		Ypos = *(int *)(Hack.GetPointer((Instance + WinXPosBase),YPosOffsets));
		Xsize = *(int *)(Hack.GetPointer((Instance + WinXPosBase),XSizeOffsets));
		Ysize = *(int *)(Hack.GetPointer((Instance + WinXPosBase),YSizeOffsets));
	}
	if(Xpos == 0){return;}
	int Rows = (int)((Xsize - Xpos) / 50); // items in row
	int Colums = (int)((Ysize - Ypos) / 50); // items in colums
	int ItemsSeen = (Rows*Colums); // number of items u can see 
	int ItemX = (Xpos + 25);
	int ItemY = (Ypos + 35);
	int Width = (Xsize - Xpos);
	int Height = (Ysize - Ypos);
	//sprintf(Message,"X:%d,Y:%d,W:%d,L:%d",Xpos,Ypos,Xsize,Ysize);
	//MessageBox (0, Message, WinTitle, MB_ICONINFORMATION);
	switch(Action)
	{
	case 0:
		Hack.Click((Xsize-5),(Ypos+5),1);
		break;
	case 1: // get item: (number)
		// if its the local map or a power stop !
		//if((Width == Height) && ((Width == 210) || (Width == 28))){break;} no longer needed
		if(Number < ItemsSeen)
		{
			for(i=0;i<Number;i++) // get the row
			{	
				row++;
				if(row>=Rows)
				{
					col++;
					row = 0;
				}
				
			}
		Hack.Click(((ItemX)+(row*50)),((ItemY)+(col*50)),1);
		//sprintf(test,"items: %d col:%d,row:%d,x:%d,y:%d",ItemsSeen,col,row,((ItemX)+(row*50)),((ItemY)+(col*50)));
		//MessageBox (0, test, WinTitle, MB_ICONINFORMATION);
		}else{
			Hack.SBScreenPrint("Cant See Item",0,0);
		}
		break;
	default: // shouldnt be here !
	break;
	}

}

int HackFunctions::UpdatePlayer()
{
	int i = 0;
	int k = 0;
	char info[100];
	pBaseAddr = *(int *) 0x1AA4058; // player stats base addr
	if(pBaseAddr == 0){return (0);} // if nothing is selected dont try and read it, unneeded !
	PData.Hp = (float*)(pBaseAddr + 0x5CC);
	PData.MaxHp = (float*)(pBaseAddr + 0x5D0);
	PData.Mana = (float*)(pBaseAddr + 0xCD4);
	PData.MaxMana = (float*)(pBaseAddr + 0xCD0);
	PData.Stam = (float*)(pBaseAddr + 0xCDC);
	PData.MaxStam = (float*)(pBaseAddr + 0xCD8);
	PData.LootOpen = (int*)(pBaseAddr + 0x6A8);
	PData.InvWeight = (int*)(pBaseAddr + 0x6D8);
	PData.Fname = (int*)(pBaseAddr + 0xC4C);
	PData.Lname = (int*)(pBaseAddr + 0xC64);

	char* a = reinterpret_cast<char*>(*(PData.Fname));
	for(i=0;i<50;i+=2)// check up to 50 chars
	{
		if(a[i] == '\0'){break;}
		PData.FnameLen++;
	}
	char* b = reinterpret_cast<char*>(*(PData.Lname));
	for(i=0;i<50;i+=2)// check up to 50 chars
	{
		if(b[i] == '\0'){break;}
		PData.LnameLen++;
	}
	//sprintf(info, "Fname: %d Lname: %d",PData.FnameLen,PData.LnameLen);
	//MessageBox (0, info, WinTitle, MB_ICONINFORMATION);

	return (1);
}
int HackFunctions::UpdateTarget(int Target)
{
	// we found out the base addr is different for every target so 
	// we either need pointer to pointer or this no come to think
	// of it we need this because if tbaseaddr=0 and we try and
	// get the other values it will crash so ptr to ptr would crash
	
	// holder for first part of targeted things array
	//if(Target == 0)// get target
	//{
	char TargetStats[200];
	int i = 0;
	int k = 0;
	int tBaseAddr = *(int *) 0x1AA4064; // target stats base addr
	if(tBaseAddr == 0){return(tBaseAddr);}// nothing selected no point in continuing
	//}
	/* no time ill fix this in a sec
	if(Target == 1) // target nothing
	{
	int *NewTarget = (int *) 0x1AA3F24; // set target address to NewTarget
	*NewTarget = 0;// set target to 0 (nothing selected)
	return(0);
	}
	if(Target != 0 && Target != 1)
	{// set current target
	int *NewTarget = *(int *) 0x1AA3F24; // set target address to NewTarget
	*NewTarget = Target;// set target to Target
	}
	*/
	// update the values
	TData.Hp = (float*)(tBaseAddr + 0x5CC);
	TData.MaxHp = (float*)(tBaseAddr + 0x5D0);
	TData.Mana = (float*)(tBaseAddr + 0xCD4);
	TData.MaxMana = (float*)(tBaseAddr + 0xCD0);
	TData.Stam = (float*)(tBaseAddr + 0xCDC);
	TData.MaxStam = (float*)(tBaseAddr + 0xCD8);
	TData.InvWeight = (int*)(tBaseAddr + 0x6D8);
	TData.LootOpen = (int*)(tBaseAddr + 0x6A8);
	TData.Fname = (int*)(tBaseAddr + 0xC4C);
	TData.Lname = (int*)(pBaseAddr + 0xC64);
	// if the int at tbaseaddr = 22292060 = person/npc/mob22292060 grave
	// if the int at tbaseaddr = 22296392 then its a item
	// 22514684 = tree/bldg/wall/fire/etc
	// found 22300700 is oasis 
	// found 22299256 is rune
	if(*((int*) tBaseAddr) == 22292060){ // targeted mob/npc/person 
		TData.Type = 1;
		/* this dont work worth a shit, it was supposed to get the name
		char* a = reinterpret_cast<char*>(*(TData.Fname));
		for(i=0;i<40;i+=2)// get the name 
		{
			if(a[i] == '\0'){break;}
			TData.FirstName[k] = a[i];
			k++;
			TData.FnameLen++;
		}
		TData.FirstName[i+1] = '\0';
		*/
	} // mob banker or npc
	if(*((int*) tBaseAddr) == 22296392){TData.Type = 2;Hack.SBScreenPrint("Item Selcted",0,0);} // item like in your inventory
	if(*((int*) tBaseAddr) == 22514684){TData.Type = 3;Hack.SBScreenPrint("Building Selcted",0,0);} // tree/bldg/rock etc
	if(*((int*) tBaseAddr) == 22300700){TData.Type = 4;Hack.SBScreenPrint("Oasis Selected ?",0,0);}
	if(*((int*) tBaseAddr) == 22299256){TData.Type = 5;Hack.SBScreenPrint("Rune Selected",0,0);}

	return(tBaseAddr);

}
int HackFunctions::GetPointer(int base, int offsets[])
{
	char Testing[200];
	int Address0 = 0;
	int Address1 = 0;
	int i = 0;

	Address0 = *(int *)(base) + offsets[0];
	//sprintf(Testing, "Number %d: %X",i,Address0);
	//MessageBox (0, Testing, WinTitle, MB_ICONINFORMATION);
	for(i=1; i < 10; i++)
	{
		if (offsets[i] == 777){break;}
		Address1 = *(int *)(Address0) + offsets[i];
		Address0 = Address1;
		// for testing output
		//sprintf(Testing, "Number %d: %X",i,Address0);
		//MessageBox (0, Testing, WinTitle, MB_ICONINFORMATION);
	}
	return(Address0);

}
bool HackFunctions::Startup()
{
	char settings[200];
	// get all keys/settings from ini
	Hack.SetupKeys("FarmBot","AttackKeys",AttackKeys);
	Hack.SetupKeys("FarmBot","GeneralKeys",GeneralKeys);
	Hack.SetupKeys("FarmBot","HealKeys",HealKeys);
	Hack.SetupKeys("FarmBot","BuffKeys",BuffKeys);
	// start ini read
	con->TargetNPC = getkey("FarmBot","TargetNPC");
	con->SitKey = getkey("FarmBot","SitKey");
	con->InventoryKey = getkey("FarmBot","InventoryKey");
	// these need more attention since they are ints getint returns int from ini
	con->KeyDelay = getint("FarmBot","KeyDelay");
	con->HealHP = getint("FarmBot","HealHP");
	con->HealMana = getint("FarmBot","HealMana");
	con->HealStam = getint("FarmBot","HealStam");
	con->Loot = getint("FarmBot","Loot");
	con->OpenKey = getkey("FarmBot","OpenKey");
	con->AllItems = getint("FarmBot","AllItems");
	con->DumpItems = getint("FarmBot","DumpItems");
	con->WaitTime = getint("FarmBot","WaitTime");
	// are they in game if not we will crash past this point
	while(!(InGame))
	{
	Hack.SBScreenPrint(WinTitle, 50, 50);
	Hack.SBScreenPrint("Waiting To Be In Game", 50, 70);
	Sleep(1);
	}
	Sleep(2000); // allow game to start
	
	pBaseAddr = *(int *) 0x1AA4058; // player stats base addr
	if(pBaseAddr == 0){MessageBox (0, "Player stats not found", WinTitle, MB_ICONINFORMATION);}
	Hack.SBScreenPrint("SBTools2 Loading . . .", 0, 0);



	// toon stats struct setup
	Hack.UpdatePlayer();

	Hack.SBScreenPrint("Ini Loaded", 0, 0);
	Hack.LogFile("--SBtools Loaded/Reloaded Sucessfully--");
	return true;
}
void HackFunctions::SBScreenPrint(char* text,int x, int y)
{
	int i = 0;
	
	if(x==0 && y==0)
	{
	RECT r;
	GetClientRect(SBwnd, &r);
	x = (r.right/2);
	y = (r.bottom/2);
	i = 10;
	}
	do {
	HDC hdc = GetDC(SBwnd);
	SetBkColor(hdc,RGB(255,255,255));                   //WHITE BACKGROUND
	SetBkMode(hdc, TRANSPARENT);                        //MAKES BACKGROUND TRANSPARENT
                                                        //SO ALL YOU SEE IS THE TEXT
	//MAKE SHADOW FOR TEXT (BLACK) and offset it by 1 pixel
	SetTextColor(hdc,RGB(0,0,0));     
    TextOut(hdc,x+1,y+1, text,strlen(text)*sizeof(char));
	//MAKE SECOND SHADOW FOR TEXT (BLACK) and offset it by 2 pixels
    TextOut(hdc,x+2,y+2, text,strlen(text)*sizeof(char));
	//PRINTS MY TEXT OVER THE BLACK TEXT IN RED, GIVES IT A DROP SHADOW APPEARANCE.
	SetTextColor(hdc,RGB(255,0,0));   
    TextOut(hdc,x,y, text,strlen(text)*sizeof(char));
	UpdateWindow(SBwnd);
	ReleaseDC(SBwnd,hdc);
	if(i !=0){Sleep(10);} // so we can at least see it
	i--;
	}while(i>0);
}
void HackFunctions::SBNameOut(char* text1, char* text2)
{
	int i,k = 0;
	if(InGame)
	{
	char* a = reinterpret_cast<char*>(*(PData.Fname)); 
	for(i=0;i<(PData.FnameLen * 2);i+=2){ // convert ascii to unicode (high byte char low byte 0)
	if(k<strlen(text1))
	{
	a[i] = text1[k];
	}else{a[i] = 0;}
	a[i+1] = 0;
	k++;
	}
	k=0; //reset k 
	// second text goes into last name part
	char* b = reinterpret_cast<char*>(*(PData.Lname)); 
	for(i=0;i<(PData.LnameLen * 2);i+=2){// convert ascii to unicode
	if(k<strlen(text2))
	{
	b[i] = text2[k];
	}else{b[i] = 0;}
	b[i+1] = 0;
	k++;
	}
	}else{
		Hack.SBScreenPrint("Not In Game", 0, 0);
		Hack.SBScreenPrint(text1,0,0);
	}
}
void HackFunctions::SBTravOut(char* text1, char* text2, char* text3, char* text4)
{
	int i,k = 0;
	if(InGame)
	{
		Hack.SBNameOut(text1,text2);
		//Hack.SBScreenPrint(text1,0,0);
		/*
		char* a = reinterpret_cast<char*>(TravStanceAddr); 
		for(i=0;i<32;i+=2){ // convert ascii to unicode (high byte char low byte 0)
			if(k<strlen(text1))
			{
			a[i] = text1[k];
			}else{a[i] = 0;}
			a[i+1] = 0;
			k++;
		}
		*/
		/*
		k=0; //reset k 
		char* b = reinterpret_cast<char*>(0x053EC950); 
		for(i=0;i<46;i+=2){// convert ascii to unicode
			if(k<strlen(text2))
			{
			b[i] = text2[k];
			}else{b[i] = 0;}
			b[i+1] = 0;
			k++;
		}
		k=0; //reset k 
		char* c = reinterpret_cast<char*>(0x04BB5738); 
		for(i=0;i<116;i+=2){// convert ascii to unicode
			if(k<strlen(text3))
			{
			c[i] = text3[k];
			}else{c[i] = 0;}
			c[i+1] = 0;
			k++;
		}
		k=0; //reset k 
		char* d = reinterpret_cast<char*>(0x053EABD0); 
		for(i=0;i<50;i+=2){// convert ascii to unicode
			if(k<strlen(text4))
			{
			d[i] = text4[k];
			}else{d[i] = 0;}
			d[i+1] = 0;
			k++;
		}
		*/
	}else{
		Hack.SBScreenPrint("Not In Game", 0, 0);
		Hack.SBScreenPrint(text1,0,0);
	}
}
void HackFunctions::DumpItems()
{
	int i,k=0;// some toys
	char DumpStats[200];
	Hack.SendKey(con->InventoryKey); // open inv window
	Sleep(500);
	//k = (*(PData).InvWeight - 7); // all but seven items
	k=25;
	Hack.SBScreenPrint("Dumping Items", 0, 0); 
	//send the clicks                 
	for(i=0;i<k;i++) // i did not want a while in here it could get stuck etc.
	{     
	if(ExitKey){break;}
	Hack.Window(1,8);
	Sleep(200);
	if(UpdateTarget(0) == 0){break;}
	if(TData.Type == 2)
		{
		Hack.SendKey(VK_DELETE);
		Sleep(400);
		Hack.SendKey(VK_RETURN);
		Sleep(400);
		}
		
	}
	sprintf(DumpStats, "Dumped %d Items", i);
	Hack.LogFile(DumpStats);
	Sleep(500);
	Hack.SendKey(con->InventoryKey); // close inv window
	Hack.SBScreenPrint("Finished", 0, 0); 
}
void HackFunctions::SendKey(short key)
{
	SendMessage(SBwnd, WM_KEYDOWN, key, 0);
    SendMessage(SBwnd, WM_CHAR, key, 0);
}
void HackFunctions::SendKeyArray(Keys KeyArray[])
{
	int i = 0;
	char KeyStat[50];
	for(i=0; i<10; i++)
	{
		//sprintf(KeyStat,"%d",i);
		if(ExitKey){break;}
		// if the key is null stop 
		if(KeyArray[i].Key == '\0' && KeyArray[i].CastTime == 0 && KeyArray[i].CoolDown == 0)
		{
			//Hack.SBTravOut("","","Done","");
		Sleep(con->KeyDelay);
		break;
		}// no more keys
		if(KeyArray[i].LastHit < (((int)(GetTickCount()/1000)) - KeyArray[i].CoolDown))
		{
			sprintf(KeyStat,"Sending Key:%d",i);
			//Hack.SBTravOut("","",KeyStat,"");
			SendKey(KeyArray[i].Key);
			KeyArray[i].LastHit = (int)(GetTickCount()/1000);
			sprintf(KeyStat,"Waiting CastTimer (sec):%d",KeyArray[i].CastTime);
						//Hack.SBTravOut("","",KeyStat,"");
			if(ExitKey){break;}
			if(UpdateTarget(0) != 0) // is something selected ? 
			{
			if(TargetDead){break;} // we are hitting keys on a dead target ! 
			}
			
			Sleep((KeyArray[i].CastTime * 1000));
		}
		if(UpdateTarget(0) != 0) // is something selected ? 
			{
			if(TargetDead){break;} // we are hitting keys on a dead target ! 
			}
		Sleep(con->KeyDelay);

	}// end for 

}
void HackFunctions::FarmBot()
{
	int i,k,j = 0;
	char BotStats[200];
	float oldhp = 0;
	int TestObject = 0;
	int NewTarget=0;
	sprintf(BotStats,"Kills: %d",PData.Kills);
	int TargetAddress = Hack.UpdateTarget(0);
	if((TargetAddress == 0) || TargetDead || (TData.Type != 1) || (TargetAddress == pBaseAddr))
	{
		Hack.SendKey(con->TargetNPC);}// send select next npc
		//Hack.SBScreenPrint("Targeting Next Mob", 0, 0);
		Hack.SBTravOut("Farming Bot",
						"Targeting Next Mob",
						BotStats,
						"Hold F12 To Stop");
	Sleep(500); // small delay
	// while you have not selected another target and you and mob are alive
	while((TargetAddress == Hack.UpdateTarget(0)) && TargetAlive && ToonAlive)
	{
		if(TData.Type != 1){break;}
		//if(*(TData).InvWeight == 256){break;} // target killed by another
		if(!InGame){break;} // they dropped out of game
		if(Hack.UpdateTarget(0) == 0){break;} // nothing is selected
		if(j>20){
			//Hack.SBScreenPrint("Cant Kill", 0, 0);
			Hack.SendKey(con->TargetNPC);// send select next npc
			break;}
		if(oldhp == *(TData).Hp){j++;}
		NewTarget=1;
				Hack.SBTravOut("Farming Bot",
						"Sending Attack Keys",
						BotStats,
						"Hold F12 To Stop");
		PData.Hp = (float*)(pBaseAddr + 0x5CC);
		Hack.SendKeyArray(AttackKeys);
		if(ExitKey){break;}
		/*
		if(F12Hit){
		sprintf(BotStats,"Selected Npc Hp: %f\n Your Hp: %f Kills: %d",*(TData).Hp,*(PData).Hp,PData.Kills);
		MessageBox (0, BotStats, "Zonemikel", MB_ICONINFORMATION);
		}
		*/
		if(j==0){oldhp = *(TData).Hp;}
	}
	/*
	we added something to store old target address and only increment dead if it changed.
	*/
	if(TargetDead && (NewTarget == 1)){ // if its not the same dead target and if its dead
		PData.Kills = PData.Kills + 1; // how many did they kill ? 
				Hack.SBTravOut("Farming Bot",
						"Killed!",
						BotStats,
						"Hold F12 To Stop");
				sprintf(BotStats, "Killed Mob Kills: %d",PData.Kills);
				Hack.LogFile(BotStats);
		NewTarget = 0;
		}
	if(ExitKey){return;} // if the hit f11 get out
	/*
	code to loot here
	potential win open address A23EACA and A23EA3E (maybe loot win structure?)
	*/ 
	if((con->Loot != 0) && TargetDead && (Hack.UpdateTarget(0) != 0))
	{
		Hack.SendKey(con->OpenKey);
		//sprintf(BotStats,"Looting: %S", TData.FirstName);
		Hack.SBTravOut("Farming Bot",
						"Open Loot Window",
						"If This Dont Work Use Setup Windows To Configure Coords",
						"Hold F12 To Stop");
		Hack.LogFile("Looting Mob");
		i=0;
		int maxtime = (con->WaitTime*2);
		while(*(TData).LootOpen == 0)
		{
			
			//Hack.SBScreenPrint("Waiting for Loot Window", 0, 0);
			Hack.SBTravOut("Farming Bot",
						"Waiting ",
						"Waiting Till The Loot Window Opens",
						"Hold F12 To Stop");
			Sleep(500);
			TargetAddress = Hack.UpdateTarget(0);
			if((TargetAddress == 0))
			{
				sprintf(BotStats, "Waited for loot win to open: %d milliseconds",i*500);
				Hack.LogFile(BotStats);
				Hack.LogFile("Mob Dissapeared");
				break;
			}
			if(i>maxtime)
			{
				sprintf(BotStats, "Waited for loot win to open: %d milliseconds",i*500);
				Hack.LogFile(BotStats);
				Hack.LogFile("Time expired");
				break;
			}
			if(i%5 == 0) // every 2.5 seconds
			{
			Hack.SendKey(con->OpenKey);
			}
			i++;
			
		}
		k=con->Loot;
		Sleep(500);
		for(i=0; i<k; i++)
		{
					Hack.SBTravOut("Farming Bot",
						"Getting Items",
						"If This Dont Work Use Setup Windows To Configure Coords",
						"Hold F12 To Stop");

		Hack.Window(1,0); // get item one
		Sleep(800);
		}
		Sleep(400);
		Hack.SBTravOut("Farming Bot",
						"Close Window",
						"If This Dont Work Use Setup Windows To Configure Coords",
						"Hold F12 To Stop");
		Hack.Window(0,0); // close window
		//Hack.SBScreenPrint("Looted", 0, 0);
		Hack.SBTravOut("Farming Bot",
						"Finished",
						"If This Dont Work Use Setup Windows To Configure Coords",
						"Hold F12 To Stop");
		Hack.UpdateTarget(1); // target nothing
	}
	// start dump inventory part 
	if(*(PData).InvWeight > con->DumpItems){
				Hack.SBTravOut("Farming Bot",
						"Dumping Items",
						"If This Dont Work Use Setup Windows To Configure Coords",
						"Hold F12 To Stop");
				Hack.LogFile("Dumping Items From Inventory");
		Hack.DumpItems();}
			Hack.SBTravOut("Farming Bot",
						"Sending Keys",
						"Sending the General Keys",
						"Hold F12 To Stop");
	Hack.SendKeyArray(GeneralKeys);
	// start heal part 
	if((*(PData).Hp < con->HealHP) || (*(PData).Mana < con->HealMana) || (*(PData).Stam < con->HealStam))
	{
				Hack.SBTravOut("Farming Bot",
						"Sending Keys",
						"Sending the Heal Keys",
						"Hold F12 To Stop");
	Hack.SendKeyArray(HealKeys);
	//Hack.UpdateTarget(1); // target nothing
	//Hack.SBScreenPrint("Sitting Down", 0, 0);
			Hack.SBTravOut("Farming Bot",
						"Sitting and Healing",
						"I Will Now Sit Till 100% Health",
						"Hold F12 To Stop");
			Hack.LogFile("Sitting and Healing");
	Hack.SendKey(con->SitKey);// sit down
	while((*(PData).Hp < *(PData).MaxHp) || (*(PData).Mana < *(PData).MaxMana) || (*(PData).Stam < *(PData).MaxStam))
		{
			if(ExitKey){return;} // if the hit f11 get out
			if(!InGame){return;} // they dropped out of game

			sprintf(BotStats, "HP: %8.2f/%8.2f Mana: %8.2f/%8.2f Stam: %8.2f/%8.2f",*(PData).Hp,*(PData).MaxHp,*(PData).Mana,*(PData).MaxMana,*(PData).Stam,*(PData).MaxStam);
			Hack.SBTravOut("Farming Bot",
						"Healing",
						BotStats,
						"Hold F12 To Stop");
			Sleep(100);
			if(!(ToonAlive)){break;}// if we die while healing
		}
	//Hack.SBScreenPrint("Standing Up", 0, 0);
		Hack.SBTravOut("Farming Bot",
						"Standing",
						"I Will Now Stand And Resume",
						"Hold F12 To Stop");
	Hack.SendKey(con->SitKey);// Stand Up
	// send buff keys
	//Hack.UpdateTarget(pBaseAddr); // target self
		Hack.SBTravOut("Farming Bot",
						"Sending Keys",
						"Sending The Buff Keys Now",
						"Hold F12 To Stop");
	Hack.SendKeyArray(BuffKeys);
	//Hack.UpdateTarget(1); // target nothing
	}
}
void HackFunctions::KeyHook() //Function header
{
	if(!(SBwnd = FindWindow(NULL, "Shadowbane"))) // get window handle
	{MessageBox (0, "Cant Find Program Window ?\n", WinTitle, MB_ICONINFORMATION);}
	PID = GetWindowThreadProcessId(SBwnd, &dwID);//get process id
	
	CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)HotKeys,NULL,0,&dwID); // hotkey hook 
}

// normal functions
long WINAPI HotKeys(long lParam) //Function header
{
	/*
	VK_LEFT (25)
	VK_UP (26)
	VK_RIGHT (27)
	VK_DOWN (28)
	*/
	Hack.Startup();
	SYSTEMTIME StartTime; 
	SYSTEMTIME Time; 
	int TimePlayed;
	int Choice = 0;
	int i = 0;
	char Message[200];
	char TargetStats[200];
	int finished = 0; // for loot window config
	//int *AbPoints = (int*)(pBaseAddr + 0xCAC); // Ability points
	int *AbPoints;
	while(1)
	{
		Sleep(10); // so it dont lag !

		if(GetAsyncKeyState(VK_F12) == -32767)
		{  
			for(i=0;i<10;i++){Hack.Window(1,i);} // 
		}

		if(GetAsyncKeyState(VK_UP) == -32767)
		{  
			if(pBaseAddr != *(int *) 0x1AA4058)// if player is not current
			{Hack.UpdatePlayer();} // get current player stuff 
			Choice++;
		}
		if(GetAsyncKeyState(VK_DOWN) == -32767)
		{   
			Choice--;
		}
		if(GetAsyncKeyState(VK_RIGHT) == -32767)
		{   
			switch(Choice)
			{
				case 0:
					Hack.SBTravOut("Ready",
						"SBHack.com",
						"UP/Down Cycles menu, Right Arrow Start, F12 Stop/MainMenu",
						"- Please Make Selection -");
				
					break;
				case 1:
					Hack.SBTravOut("FarmBot",
						"Start",
						"This Farms Mobs, To Configure Edit the SBTools2.ini file",
						"Hold F12 To Stop");
					Sleep(500);
					Hack.LogFile("FarmBot Started");
					if(InGame) // if ingame this should be 1 else tell them
					{
					Hack.SBTravOut("Farming Bot",
						"Started",
						"Sending Buff Keys",
						"Hold F12 To Stop");
					Hack.SBNameOut("Menu:","Start");
					GetSystemTime(&StartTime);
					Hack.SendKeyArray(BuffKeys);
					}else{
					Hack.SBScreenPrint("You Are Not in Game", 0, 0);
					}
					Xpos = 0;
					Ypos = 0;
					Xsize = 0;
					Ysize = 0;
					while(ToonAlive) // while he is alive
					{
						if(!(InGame)){
							GetSystemTime(&Time);
							sprintf(Message,"You Dropped out of game after  %d:%d H:M Kills: %d",(Time.wHour-StartTime.wHour),(Time.wMinute-StartTime.wMinute),PData.Kills);
							Hack.LogFile(Message);
							//MessageBox (0, Message, "Zonemikel", MB_ICONINFORMATION);
							break;
						} // they arent in game
						if(!(ToonAlive)){
							GetSystemTime(&Time);
							sprintf(Message,"You Died after %d:%d H:M Kills: %d , bummer",(Time.wHour-StartTime.wHour),(Time.wMinute-StartTime.wMinute),PData.Kills);
							Hack.LogFile(Message);
							//MessageBox (0, Message, "Zonemikel", MB_ICONINFORMATION);
							break;
						}// if they die
					if(ExitKey){break;}
					Hack.FarmBot();
					}
					Hack.LogFile("Farmbot Turned Off");
					Hack.SBTravOut("Turn",
						"Off",
						"You Will Now Return To Main Menu",
						"Happy Looting");
					Sleep(1000);
					Choice = 0;
					break;
				case 2:
					AbPoints = (int*)(pBaseAddr + 0xCAC);
					Hack.SBTravOut("+100 Abilty Pts",
						"Adding 100 Points",
						"When You Restart SB Your Points Will Be Normal Again",
						"For Testing Builds !");
					
					*AbPoints = 100;
					Hack.SendKey(VkKeyScan('s'));
					Choice = 0;
					break;
				case 3:
					Hack.SBTravOut("Dump",
						"Items",
						"Hold F12 To Stop",
						"Try it !");
					Hack.DumpItems();
					break;
				case 4:
					Hack.SBTravOut("Reload",
						"ini",
						"This Will Reload The SBTools2.ini And Other Stuff",
						"Make A .ini For Each Toon");
					if(!Hack.Startup())
					{MessageBox (0, "Reset Problem\n", "Zonemikel", MB_ICONINFORMATION);}
					Choice = 0;
					break;

				default:
					Choice = 0;
					break;
				}


		}
		if(InGame)
		{
			switch(Choice)
			{
				case 0:
					Hack.SBTravOut("Ready",
						"SBHack.com",
						"UP/Down Cycles menu, Right Arrow Start, F12 Stop/MainMenu",
						"- Please Make Selection -");
					break;
				case 1:
					Hack.SBTravOut("Farm",
						"Bot",
						"This Farms Mobs, To Configure Edit the SBTools2.ini file",
						"Once Started F12 To Stop");
					break;
				case 2:
					Hack.SBTravOut("+100 Abilty Pts",
						"Right arrow to start",
						"Will Give You 100 Ability Points (client side only)",
						"For Testing Builds !");
					break;
				case 3:
					Hack.SBTravOut("Dump",
						"Items",
						"This Dumps Everything Out of Inventory Except Top 3 Rows",
						"Try it !");
					break;
				case 4:
					Hack.SBTravOut("Reload",
						"INI",
						"This Will Reload The SBTools2.ini And Other Stuff",
						"Make A .ini For Each Toon");
					break;
				default:
					Choice = 0;
					break;
			}// end switch(choice)
		}// end if ingame

	}
	return 0;
}
/* 
this function takes the key out of the ini then if it is only one char 
(second char in array is '\0' null char) then it returns the scan code, 
which is the hex code that needs to be fed into sendmessage, else if its
f1-f12 it returns the hex for that seems to return 32 if its really nothing?
returns a 0 if no key is in the key returns a 1 if something was wrong ie. to 
many chars or a unrecognized char etc. 
*/ 
short HackFunctions::getkey(char* section, char* key)
{
     char buf[10];
     char *szFileName = ".\\SBTools2.ini";
     GetPrivateProfileString (section, 
                        key, 
                        TEXT("ERR"), 
                        buf, 
                        10, 
                        szFileName); 
     if(!buf[0])// if the entry is blank
     {return(0);}
     if(buf[1] == '\0')// if its just one key
     {
               if(VkKeyScan(buf[0]) != 32)
               return(VkKeyScan(buf[0]));
     }
     // for f1-f8 keys 
       if(buf[1] == '1')
       return(VK_F1);
       if(buf[1] == '2')
       return(VK_F2);
       if(buf[1] == '3')
       return(VK_F3);
       if(buf[1] == '4')
       return(VK_F4);
       if(buf[1] == '5')
       return(VK_F5);
       if(buf[1] == '6')
       return(VK_F6);
       if(buf[1] == '7')
       return(VK_F7);
       if(buf[1] == '8')
       return(VK_F8);  
     /*If it hasnt returned yet something is very wrong
	  at least its a key that i havent anticipated */
	   char error[50];
	   strcat(error, "ini error around:");
	   strcat(error, key);
	MessageBox (0, error, "Zonemikel", MB_ICONINFORMATION);
     return(1);          
}
long HackFunctions::getint(char* section, char* key)
{
     char buf[10];
	 //char crap[10];// should not be used
	 char* crap;
	 int thereturn;
     char *szFileName = ".\\SBTools2.ini";
     GetPrivateProfileString (section, 
                        key, 
                        TEXT("ERR"), 
                        buf, 
                        10, 
                        szFileName); 
	 thereturn = strtol(buf,&crap,0);
	 return(thereturn);

}
void HackFunctions::Click(int xPos, int yPos, int side)
    {
                        
                       POINT pt;      
                       DWORD aw;
					   int i=0;
                       pt.x = xPos;
                       pt.y = yPos;
                       //send close inv click
                       aw = MAKELPARAM(pt.x, pt.y);
                       Sleep(500);
                       if (side == 1) // 1 for left click 
                       {
                       SendMessage(SBwnd, WM_LBUTTONDOWN, MK_LBUTTON, aw);
                       SendMessage(SBwnd, WM_LBUTTONUP, MK_LBUTTON, aw);
					   for(i=0; i<5; i++)
					   {Hack.SBScreenPrint("L", pt.x, pt.y);}
                       }
					   
                       if (side == 2) // 2 for right click :)
                       {
                       SendMessage(SBwnd, WM_RBUTTONDOWN, MK_RBUTTON, aw);
                       SendMessage(SBwnd, WM_RBUTTONUP, MK_RBUTTON, aw);
					   for(i=0; i<5; i++)
					   {Hack.SBScreenPrint("R", pt.x, pt.y);}
                       }
					   // show where we clicked 5 times
					   
    }

int HackFunctions::SetupKeys(char* section, char* key, Keys KeyArray[])
{
     int i=0;
     int j=0;
     char* crap;
	 char info[100];
     char buf[200];
     char *szFileName = ".\\SBTools2.ini";
     GetPrivateProfileString (section, 
                        key, 
                        TEXT("ERR"), 
                        buf, 
                        200, 
                        szFileName);
     //printf("FromINI: %s\n", buf); 
     char *result = NULL;
     result = strtok( buf, "," );
     while( result != NULL ) 
     {
                 if(result[1] == '\0')// if its just one key the next char will be ','
                 {   
				  //sprintf(info, "Key: %d String: %s Hex: %c",i,result,VkKeyScan(result[0]));
				  //MessageBox (0, info, WinTitle, MB_ICONINFORMATION);
                  KeyArray[i].Key = VkKeyScan(result[0]);
                 }else{
                 
                 if(!(strcmp(result,"f1"))){KeyArray[i].Key = VK_F1;}
                 if(!(strcmp(result,"f2"))){KeyArray[i].Key = VK_F2;}
                 if(!(strcmp(result,"f3"))){KeyArray[i].Key = VK_F3;}
                 if(!(strcmp(result,"f4"))){KeyArray[i].Key = VK_F4;}
                 if(!(strcmp(result,"f5"))){KeyArray[i].Key = VK_F5;}
                 if(!(strcmp(result,"f6"))){KeyArray[i].Key = VK_F6;}
                 if(!(strcmp(result,"f7"))){KeyArray[i].Key = VK_F7;}
                 if(!(strcmp(result,"f8"))){KeyArray[i].Key = VK_F8;}
                 if(!(strcmp(result,"f9"))){KeyArray[i].Key = VK_F9;}
                 if(!(strcmp(result,"f10"))){KeyArray[i].Key = VK_F10;}
                 if(!(strcmp(result,"f11"))){KeyArray[i].Key = VK_F11;}
                 if(!(strcmp(result,"f12"))){KeyArray[i].Key = VK_F12;}
				 if(!(strcmp(result,"end"))){KeyArray[i].Key = VK_END;}
                 
                 }
            result = strtok( NULL, ",");
			KeyArray[i].CastTime = strtol(result,&crap,0);
			result = strtok( NULL, ",");
            KeyArray[i].CoolDown = strtol(result,&crap,0);
            result = strtok( NULL, ",");
            i++;
     }
	 for(i=i; i<10; i++)
     {
        KeyArray[i].Key = '\0';
        KeyArray[i].CoolDown = 0;
		KeyArray[i].CastTime = 0;
     }
     return(1);     
          
}
