rendered paste body#pragma once#include "stdafx.h"#include <stdlib.h>//Globals//Stored team datau32 teamFlags; //Number of flags team hasu32 playersInTeam; //For drawing the amount of players in the teamconst char *lastTeam; //For comparing so you know whether to draw a new team headeru32 playerlist[512]; //The playerlist, for temporary storage so sorting is easychar playerBuffer[1024]; //For properly parsed nameu32 playerFlags; //Number of flags that the player hasu32 curStruct; //Current list entryu32 ListCapacity; //Number of entries in the listu32 NumPlayers; //Number of players in the arenau32 ListWidth; //The current parse constant for the entryu32 vertAlign; //The vertical alignment for the next entryu32 fontclass; //The pointer to the class used for drawing stuff u32 alignconst1; //Another alignment thingu32 entitiesdrawn; //Number of entities actually drawn to the screen (for use with ListCapacity)u32 index; //Index for the list (in player terms)u32 ofs; //Offset from the top of the list to start (due to scrollbar)u32 PixelWidth; //For the getpixelwidth functionu32 TeamNameAlign; //Alignment offset for the team name//These vars are to be able to select players and for the scrollbaru32 *numteams; //To calculate offsetsu32 *teamofs; //The number of teams up to the point where the teamlist is drawnu32 *numtotalteams; //The total number of teams present in the gamebool offsetlist[1024]; //List of where the teams are in the tableu32 oldindex; //For the declspec hckSelectu32 newindex; //For the declspec hckSelectu16 lasthighlight; //The playerid of the player last highlightedRECT selectRect; //For selected players//////////////////////////////////////////////////////////////////////// Helper asm functionsu32 GetPixelLength(u32 me, const char *thestring){ _asm { mov ecx, [me] mov [PixelWidth], 0 mov edi, [thestring] mov dl, byte ptr [edi] xor eax, eax xor esi, esi test dl, dl je endofloop mov ebx, dword ptr [ecx+8]startloop: movsx edx, dl sub edx, ebx js invalidchar mov ebp, dword ptr [ecx+4] movsx ebp, word ptr [ebp+0xA4] cmp edx, ebp jge invalidchar movsx edx, word ptr [ecx+edx*2+0x210] jmp skipinvalidcharinvalidchar: mov edx, 128 sub edx, ebx movsx edx, word ptr [ecx+edx*2]skipinvalidchar: add [PixelWidth], edx inc edi mov dl, byte ptr [edi] inc eax test dl, dl jnz startloopendofloop: } return PixelWidth;}//////////////////////////////////////////////////////////////////////// Helper c functionsu32 AlignString(const char *thestring, u32 lWidth, u32 me){ u32 Width = GetPixelLength(me, thestring); u32 Result = lWidth / 2; Result -= Width / 2; return Result;}//////////////////////////////////////////////////////////////////////// DrawPlayer - Draws a player entryvoid DrawPlayer(u32 me, char *buf, s32 colourbase){ _asm { mov esi, [me] } //Make string suitable for display (so it doesn't overlap stuff) _asm { push [ListWidth] mov ecx, dword ptr [esi+0x58] mov eax, [curStruct] add eax, 0x32 push eax mov eax, 0x4047E0 call eax inc eax push eax mov eax, [curStruct] add eax, 0x32 push eax mov eax, [buf] push eax mov eax, 0x476970 call eax add esp, 0xC } //Setup colour _asm { mov edi, [colourbase] neg edi sbb edi, edi and edi, 4 } //Check to see if player is selected _asm { mov eax, [index] mov ecx, 0x4BF838 mov ecx, [ecx] mov ecx, [ecx+0x586] mov eax, [ecx+eax*4] test eax, eax ;safety check jz skipselected movzx eax, word ptr [eax] movzx ecx, word ptr [lasthighlight] cmp eax, ecx ;dword ptr [esi+0x40] mov ebx, 0x13 jnz skipselected mov ecx, [ListWidth] lea eax, dword ptr [ebx-2] lea edx, dword ptr [eax+ecx+4] lea ebx, [selectRect] mov [ebx], eax mov eax, dword ptr [esi+0x4C] mov [ebx+8], edx push dword ptr [vertAlign] pop dword ptr [ebx+4] mov ecx, dword ptr [eax+4] movsx edx, word ptr [ecx+0xAA] mov eax, dword ptr [esi+0x38] add edx, [vertAlign] mov [ebx+12], edx mov eax, dword ptr [eax] push ebx mov ecx, 0x4BF838 mov ecx, [ecx] xor edx, edx mov dx, word ptr [ecx+edi*2+0x42] mov ecx, dword ptr [esi+0x38] push edx call dword ptr [eax+0x28] mov edi, 0xEskipselected: } //Draw it! _asm { mov edx, dword ptr [esi+0x38] mov ecx, dword ptr [esi+0x4C] push 3 push [vertAlign] push 0x13 push edx push edi mov eax, [buf] push eax mov eax, 0x404610 call eax } //NOTE: 0x13 is an alignment constant //See if player is carrying flags _asm { lea ecx, [playerlist] mov eax, [index] mov ecx, [ecx+eax*4] ;ecx <- Player structs mov eax, [ecx+0xDE] ;ecx <- # flags test eax, eax jz skipflagdraw push 10 push [buf] push eax call itoa add esp, 0xC mov edx, dword ptr [esi+0x38] mov ecx, dword ptr [esi+0x4C] push 3 mov eax, [vertAlign] add eax, [alignconst1] push eax push 10 push edx push 6 mov eax, [buf] push eax mov eax, 0x404610 call eaxskipflagdraw: } //See if the player has a crown _asm { lea ecx, [playerlist] mov eax, [index] mov ecx, [ecx+eax*4] ;ecx <- Player structs mov eax, [ecx+0xE6] ;ecx <- bool crown test eax, eax jz skipdrawcrown push 'k' ;Push character buffer onto stack mov edx, esp mov ecx, dword ptr [esi+0x4C] push 3 mov eax, [vertAlign] push eax push 9 push dword ptr [esi+0x38] push 2 push edx mov eax, 0x404610 call eax add esp, 4skipdrawcrown: } _asm { mov edi, [curStruct] mov ecx, edi mov eax, 0x44F510 call eax test eax, eax je skipspec mov ecx, [alignconst1] mov eax, dword ptr [esi+0x38] push 3 mov ebx, [vertAlign] lea edi, dword ptr [ecx+ebx] mov ecx, [fontclass] push edi ;lea edx, dword ptr [ebx-0x2] mov edx, 0x11 ;0x13(constant) - 0x2 push edx push eax push 5 push 0x48B37C mov eax, 0x404590 call eax mov ecx, [curStruct] mov eax, dword ptr [ecx+0xE6] test eax, eax je skipmedal mov edx, dword ptr [esi+0x38] push 3 push edi add ebx, -7 push ebx push edx jmp halfcallskipspec: mov eax, dword ptr [edi+0xE6] test eax, eax je skipmedal mov eax, [alignconst1] mov ecx, dword ptr [esi+0x38] push 3 add eax, ebp push eax add ebx, -2 push ebx push ecxhalfcall: mov ecx, [fontclass] push 2 push 0x48B39C mov eax, 0x404590 call eaxskipmedal: }}//////////////////////////////////////////////////////////////////////// DrawTeam - Draws a team entryvoid DrawTeam(u32 me, char* buf){ _asm { mov esi, [me] } //Convert to ASCII _asm { push 10 push [buf] push [playersInTeam] call itoa add esp, 0xC } //Draw the amount of players in the team _asm { ;Calculate position push [buf] push [esi+0x4C] call GetPixelLength add esp, 0x8 push eax mov ecx, [ListWidth] add ecx, 0x13 sub ecx, eax mov eax, ecx mov edx, dword ptr [esi+0x38] mov ecx, dword ptr [esi+0x4C] push 3 push [vertAlign] push eax push edx push 0x5 push [buf] mov eax, 0x404610 call eax } //Align the string _asm { push [esi+0x4C] push [ListWidth] mov eax, [curStruct] add eax, 0x6 push eax call AlignString add esp, 0xC add eax, 0x13 mov [TeamNameAlign], eax } //Make string suitable for display (so it doesn't overlap stuff) _asm { mov ecx, [ListWidth] sub ecx, eax pop eax push ecx mov ecx, dword ptr [esi+0x58] mov eax, [curStruct] add eax, 0x6 push eax mov eax, 0x4047E0 call eax inc eax push eax mov eax, [curStruct] add eax, 0x6 push eax mov eax, [buf] push eax mov eax, 0x476970 call eax add esp, 0xC } //Draw the teamname _asm { mov edx, dword ptr [esi+0x38] mov ecx, dword ptr [esi+0x4C] push 3 push [vertAlign] push [TeamNameAlign] push edx push 0x5 push [buf] mov eax, 0x404610 call eax } _asm { push 10 push [buf] push [teamFlags] call itoa add esp, 0xC } //Draw the number of flags team has _asm { mov eax, [teamFlags] test eax, eax jz skipdrawflags ;Calculate position push [buf] push [esi+0x4C] call GetPixelLength add esp, 0x8 mov ecx, [TeamNameAlign] sub ecx, eax sub ecx, 7 mov eax, ecx mov edx, dword ptr [esi+0x38] mov ecx, dword ptr [esi+0x4C] push 3 push [vertAlign] push eax push edx push 6 push [buf] mov eax, 0x404610 call eaxskipdrawflags: }}/////////////////////////////////////////////////////////////////////////////////////////////// This file handles the drawing of the playerlist (now teamlist :))void _declspec(naked) hckTeamList(){ //Initialize variables _asm { mov ecx, 0x4BF838 mov edi, [ecx] mov ecx, dword ptr [edi+0x586] mov eax, dword ptr [ecx+0x3E8] mov edx, dword ptr [esi+0x48] mov [ListCapacity], edx mov [NumPlayers], eax mov [ListWidth], 0x83 mov [vertAlign], 0x20 mov [alignconst1], 2 mov [lastTeam], 0 mov eax, [numteams] mov [eax], 0 mov eax, [teamofs] mov [eax], 0 ;Start according to the scrollbar mov eax, [edi+0x56E] test eax, eax jz noclass mov eax, [eax+0x44] ;eax <- amount scrolled bynoclass: mov [ofs], eax mov [index], 0 mov [entitiesdrawn], 0 ;Clear offsetlist lea edi, [offsetlist] xor eax, eax mov ecx, 1024 rep stosb ;Clear playerlist lea edi, [playerlist] xor eax, eax mov ecx, 512 rep stosd ;Clear rest of stored playerlist mov edi, 0x4bf838 mov edi, [edi] mov edi, dword ptr [edi+0x586] xor eax, eax mov ecx, 0xFA mov edx, dword ptr [edi+0x3E8] sub ecx, edx shl edx, 2 add edi, edx rep stosd ;Sort the stored playerlist push 0x444D30 push [NumPlayers] mov eax, 0x4bf838 mov eax, [eax] mov eax, dword ptr [eax+0x586] push eax mov eax, 0x407800 call eax add esp, 12 ;Initialize playerlist push esi mov esi, 0x4bf838 mov esi, [esi] mov esi, dword ptr [esi+0x586] lea edi, [playerlist] mov ecx, [NumPlayers] rep movsd pop esi } //Start of loop _asm {startloop: mov eax, 0x4bf838 mov edx, [eax] lea edi, dword ptr [playerlist] mov eax, [index] mov eax, dword ptr [edi+eax*4] mov ebx, dword ptr [edx+0xD9F0] mov [curStruct], eax test ebx, ebx je skipcolourbase xor edi, edi mov di, word ptr [eax+4] mov edx, dword ptr [edx+0xD9EC] sub di, word ptr [edx+4] neg di sbb edi, edi inc ediskipcolourbase: } //Update globals _asm { push [esp+0x18] pop [fontclass] } //Check to see if a new team is being drawn _asm { mov ecx, [curStruct] add ecx, 6 mov eax, [lastTeam] mov [lastTeam], ecx test eax, eax jz newteam push ecx push ecx push eax call dword ptr ds:[lstrcmpi] pop ecx test eax, eax jz drawThePlayer newteam: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Count teams, even if we skip them mov eax, [numteams] inc dword ptr [eax] ;Add team into offset list (even if it's skipped) push edi ;save colour flags lea edi, [offsetlist] mov eax, [numteams] mov eax, [eax] mov edx, [index] add eax, edx add edi, eax mov byte ptr [edi], 1 pop edi ;If we're scrolled up, don't need to draw this cmp [ofs], 0 jnz skippedateam ;New team, find the amount of players in the team mov [playersInTeam], 1 pushad lea edi, dword ptr [playerlist] mov esi, [index] inc esi mov ebx, ecx mov edx, dword ptr [edi+esi*4] ;edx <- curStruct, ebx <- lastTeam, esi <- index, onstack = numPlayersstartloop2: ;Check if we've any players left mov eax, [NumPlayers] cmp esi, eax jge endloop ;Compare add edx, 6 ; Get teamname push edx push ebx call dword ptr ds:[lstrcmpi] test eax, eax jnz endloop inc esi inc [playersInTeam] mov edx, dword ptr [edi+esi*4] jmp startloop2endloop: popad } //Get number of flags team has _asm { mov ecx, 0x4BF838 mov ecx, [ecx] mov ecx, dword ptr [ecx+0x5A2] mov eax, [curStruct] movsx eax, word ptr [eax+4] push eax mov eax, 0x43A290 call eax mov [teamFlags], eax } //Otherwise we draw the team first _asm { lea eax, [playerBuffer] push eax push esi call DrawTeam add esp, 0x8 inc [entitiesdrawn] ;Update the vertical alignment mov edx, dword ptr [esi+0x4C] mov eax, dword ptr [edx+0x4] movsx ecx, word ptr [eax+0xAA] add [vertAlign], ecx } //If going from Team -> Player, need to check if there's space _asm { mov eax, [ListCapacity] cmp eax, [entitiesdrawn] jle endloop2 } //Then draw the player _asm { jmp drawThePlayerskippedateam: ;We've skipped drawing a team, and want to draw a player now. ;Decrement the offset, and get on with it. dec [ofs] ;We also have to increase the team offset mov eax, [teamofs] inc dword ptr [eax]drawThePlayer: ;If we're scrolled up, don't need to draw this cmp [ofs], 0 jnz scrollbarskip push edi lea eax, [playerBuffer] push eax push esi call DrawPlayer add esp, 0xC inc [entitiesdrawn] ;Update the vertical alignment mov edx, dword ptr [esi+0x4C] mov eax, dword ptr [edx+0x4] movsx ecx, word ptr [eax+0xAA] add [vertAlign], ecx } _asm { jmp endscrollbarskipscrollbarskip: ;We've skipped an entry due to the offset, ;so decrement the offset and continue. dec [ofs]endscrollbarskip: ;Check to see if we've run out of players mov eax, [index] mov ecx, [NumPlayers] inc eax mov [index], eax cmp eax, ecx jge endloop2andindex ;Check to see if we've run out of space mov eax, [entitiesdrawn] cmp eax, [ListCapacity] jl startloopendloop2: ;Increase index since it wasn't done in the loop inc dword ptr [index]endloop2andindex: } //Now we need to find the total amount of teams, for statistical reference _asm { ;Initialize variables mov [lastTeam], 0 mov esi, [index] mov eax, [numteams] mov eax, [eax] mov edi, [numtotalteams] mov dword ptr [edi], eaxstartendloop: cmp esi, [NumPlayers] jge realendloop ;No more players -> no more teams ;Get the player's struct lea ecx, [playerlist] mov ecx, [ecx+esi*4] ;Is this player in a new team? add ecx, 6 mov eax, [lastTeam] mov [lastTeam], ecx test eax, eax jz anothernewteam push ecx push eax call dword ptr ds:[lstrcmpi] test eax, eax jz continueendloopanothernewteam: ;Add team into offset list lea ecx, [offsetlist] mov eax, [edi] ;num teams add eax, esi ;esi <- index add ecx, eax mov byte ptr [ecx], 1 ;Increase the amount of teams spotted inc dword ptr [edi]continueendloop: ;Increase the index inc esi ;Continue the loop jmp startendlooprealendloop: ;Return execution, after having drawn the list :) mov eax, 0x44D91F jmp eax }}/////////////////////////////////////////////////////////////////////////////// Left mouse button selection hookvoid __declspec(naked) hckSelect(){ _asm { ;eax <- player index mov [newindex], eax mov [oldindex], eax pushad } for (index=0 ; index <= oldindex ; index++) { if (offsetlist[index]) newindex--; } _asm { ;Obtain the new player's id mov eax, [newindex] mov edx, 0x4BF838 mov edx, [edx] mov ecx, [edx+0x586] mov eax, [ecx+eax*4] test eax, eax jz invalidguy movzx eax, word ptr [eax] mov [lasthighlight], axinvalidguy: ;Continue popad mov eax, [newindex] mov dword ptr [esi+0x3C], eax mov ecx, 0x4BF838 mov ecx, [ecx] push 0x44C870 retn }}/////////////////////////////////////////////////////////////////////////////// Hook to correct the credentials given for scrolling the scrollbar// (implemented due to 0 space)const u32 scrolljmp = 0x44BF0E;const u32 scrolljmp2 = 0x44D6AF;void __declspec(naked) hckScrollDown(){ _asm { ;This hook performs two functions, so check the return address add esp, 4 cmp dword ptr [esp-4], 0x44D6AA je checkhook cmp dword ptr [esp-4], 0x44C1D3 je pagescrollhookscrolldownhook: ;Perform the overwritten code mov eax, dword ptr [eax+0x3E8] ;eax <- number of players in list ;Add the total number of teams in the list mov edx, [numtotalteams] add eax, [edx] ;Use this to set the correct flags sub eax, dword ptr [ecx+0x40] ;Jump back to where we should be jmp [scrolljmp]pagescrollhook: sub esp, 4 ;Perform original instructions mov eax, 0x4BF838 mov eax, [eax] mov edx, [eax+0x586] ;Update the player id pushadrehandle: cmp ebp, 0xFA jge overflowedplayer test ebp, ebp ;The first highlight is always a team js incrementplayer ;We're below 0 mov eax, [edx+ebp*4] test eax, eax jz invalidplayer mov ax, word ptr [eax] mov [lasthighlight], ax jmp endhandleinvalidplayer: ;If the tick isn't above the top, we need to back track test ebp, ebp jns backtrackplayer ;Otherwise, we need to increase itincrementplayer: inc ebp jmp rehandlebacktrackplayer: dec ebp jmp rehandleendhandle: ;Keep the new ebp mov [esp+8], ebp popad ;Perform the overwritten code mov dword ptr [esi+0x3C], ebp mov eax, dword ptr [edx+0x3E8] ;eax <- number of players in list ;Add the total number of teams in the list mov ecx, [numtotalteams] add eax, [ecx] ;Jump back to where we should be retnoverflowedplayer: ;Set player to last player mov ebp, [edx+0x3E8] jmp rehandlecheckhook: ;Perform the overwritten code mov eax, dword ptr [edx+0x3E8] ;eax <- number of players in list ;Add the total number of teams in the list mov edx, [numtotalteams] add eax, [edx] ;Use this to set the correct flags mov edi, dword ptr [esi+0x48] ;Subtract to set the flags sub eax, edi ;Jump back to where we should be jmp [scrolljmp2] }}/////////////////////////////////////////////////////////////////////////////// Hook to find the currently selected player// (implemented due to 0 space)void __declspec(naked) hckGetSel(){ _asm { ;Setup stack push ebx push esi ;Prepare the loop mov esi, 0x4BF838 mov esi, [esi] mov esi, [esi+0x586] xor edx, edx mov bx, word ptr [lasthighlight] ;Begin searching for the associated playernextguy: ;Get the current player mov eax, [esi+edx*4] test eax, eax jz notfound ;Is this the guy? inc edx cmp word ptr [eax], bx jne nextguy ;Otherwise, we've got him jmp foundnotfound: xor eax, eaxfound: pop esi pop ebx retn }}