• You've discovered RedGuides 📕 an EverQuest multi-boxing community 🛡️🧙🗡️. We want you to play several EQ characters at once, come join us and say hello! 👋
  • IS THIS SITE UGLY? Change the look. To dismiss this notice, click the X --->
  • There is a suspension/ban wave happening, we're still gathering information. Please keep regular discussion to Suspension MegaThread and please consider submitting a Suspension report to RG.
Resource icon

Plugin - MQ2FPS (1 Viewer)

Machiavelli

New member
Joined
Nov 14, 2004
RedCents
10¢
This plugin was removed from the main release of MQ2 quite some time ago. I still have the code however.

Requires latest version of MQ2, no changes or offsets needed.
Rich (BB code):
// MQ2FPS.cpp : Defines the entry point for the DLL application. 
// 

// PLUGIN_API is only to be used for callbacks.  All existing callbacks at this time 
// are shown below. Remove the ones your plugin does not use.  Always use Initialize 
// and Shutdown for setup and cleanup, do NOT do it in DllMain. 


//#define DEBUG_TRY 1 
#include "../MQ2Plugin.h" 
#include "MQ2FPS.h" 

PreSetup("MQ2FPS"); 

#define FPS_ABSOLUTE  0 
#define FPS_CALCULATE 1 

DWORD MaxFPSMode=FPS_CALCULATE; 

DWORD FPSIndicatorX=5; 
DWORD FPSIndicatorY=25; 
BOOL FPSIndicator=TRUE; 

bool InForeground=false; 

DWORD gFG_Rate=1; 
DWORD gBG_Rate=0; 
BOOL  ReverseFG_Rate=true;// skip every nth frame vs show every nth frame 
BOOL  ReverseBG_Rate=false; 

DWORD CurrentRate=1; 
BOOL CurrentReverse=false; 

DWORD PreDetour=0; 

BOOL InMacro=false; 

char *szFPSModes[]= 
{ 
   "Absolute", 
   "Calculate" 
}; 

HMODULE EQWhMod=0; 
typedef HWND   (__stdcall *fEQW_GetDisplayWindow)(VOID); 
fEQW_GetDisplayWindow EQW_GetDisplayWindow=0; 

BOOL dataFPS(PCHAR szIndex, MQ2TYPEVAR &Ret); 
BOOL dataMaxFPS(PCHAR szIndex, MQ2TYPEVAR &Ret); 
BOOL dataForeground(PCHAR szIndex, MQ2TYPEVAR &Ret); 
VOID RenderCommand(PSPAWNINFO pChar, PCHAR szLine); 

void SetVTable(DWORD index, DWORD value) 
{ 
   DWORD oldperm=0; 
   DWORD Address=(DWORD)&(*((DWORD**)g_pDrawHandler))[index]; 
   DebugSpewAlways("SetVTable writing at address %X to %X",Address,value); 
  VirtualProtectEx(GetCurrentProcess(), (LPVOID)Address, 4,PAGE_EXECUTE_READWRITE, &oldperm); 
 WriteProcessMemory( 
  GetCurrentProcess(), 
  (LPVOID)Address, 
  (LPVOID)&value, 
  4, 
  NULL); 
 VirtualProtectEx(GetCurrentProcess(), (LPVOID)Address, 4, oldperm, &oldperm); 
} 

DWORD GetVTable(DWORD index) 
{ 
   DWORD Ret=(*((DWORD**)g_pDrawHandler))[index]; 
   DebugSpewAlways("GetVTable(%d)=%X",index,Ret); 
   return Ret; 
} 

class CMyDisplay 
{ 
public: 
   VOID Void(VOID) 
   { 
      static DWORD nRender=0; 
      if (++nRender>CurrentRate-1) 
      { 
         nRender=0; 
         if (!CurrentReverse) 
         { 
            Render(); 
         } 
      } 
      else if (CurrentReverse) 
         Render(); 
   } 
   VOID Render(VOID); 
}; 
FUNCTION_AT_VARIABLE_ADDRESS(VOID CMyDisplay::Render(VOID),PreDetour); 

// Called once, when the plugin is to initialize 
PLUGIN_API VOID InitializePlugin(VOID) 
{ 
   DebugSpewAlways("Initializing MQ2FPS"); 
   if (EQWhMod=GetModuleHandle("eqw.dll")) 
   { 
      EQW_GetDisplayWindow=(fEQW_GetDisplayWindow)GetProcAddress(EQWhMod,"EQW_GetDisplayWindow"); 
   } 
    
   // Add commands, macro parameters, hooks, etc. 
   // INI Settings 
    DWORD Temp=0; 
    Temp = GetPrivateProfileInt("MQ2FPS","ForegroundMaxFPS",50,INIFileName); 
    SetForegroundMaxFPS(Temp); 
    Temp = GetPrivateProfileInt("MQ2FPS","BackgroundMaxFPS",30,INIFileName); 
    SetBackgroundMaxFPS(Temp); 
    MaxFPSMode = GetPrivateProfileInt("MQ2FPS","Mode",FPS_CALCULATE,INIFileName); 
    FPSIndicatorX = GetPrivateProfileInt("MQ2FPS","IndicatorX",5,INIFileName); 
    FPSIndicatorY = GetPrivateProfileInt("MQ2FPS","IndicatorY",25,INIFileName); 
   FPSIndicator = GetPrivateProfileInt("MQ2FPS","Indicator",TRUE,INIFileName); 

   gBG_Rate = GetPrivateProfileInt("Rendering","BGRate",30,INIFileName); 
   ReverseBG_Rate = GetPrivateProfileInt("Rendering","ReverseBGRate",0,INIFileName); 
   gFG_Rate = GetPrivateProfileInt("Rendering","FGRate",1,INIFileName); 
   ReverseFG_Rate = GetPrivateProfileInt("Rendering","ReverseFGRate",0,INIFileName); 

   // Commands 
   AddCommand("/maxfps",MaxFPS,0,1); 
   AddCommand("/fps",FPSCommand,0,1); 
   AddCommand("/render",RenderCommand,0,1); 

   AddMQ2Data("FPS",dataFPS); 
   AddMQ2Data("MaxFPS",dataMaxFPS); 
   AddMQ2Data("Foreground",dataForeground); 

} 

PLUGIN_API VOID SetGameState(DWORD GameState) 
{ 
   if (GameState==GAMESTATE_INGAME || GameState==GAMESTATE_CHARSELECT) 
   { 
      if (!PreDetour) 
         PreDetour=GetVTable(36); 
      VOID (CMyDisplay::*pfDetour)(VOID) = CMyDisplay::Void; 
      SetVTable(36,*(DWORD*)&pfDetour); 
   } 
} 


// Called once, when the plugin is to shutdown 
PLUGIN_API VOID ShutdownPlugin(VOID) 
{ 
   DebugSpewAlways("Shutting down MQ2FPS"); 
   // Remove commands, macro parameters, hooks, etc. 
   RemoveCommand("/maxfps"); 
   RemoveCommand("/fps"); 
   RemoveCommand("/render"); 
   RemoveMQ2Data("FPS"); 
   RemoveMQ2Data("MaxFPS"); 
   RemoveMQ2Data("Foreground"); 

   if (PreDetour) 
   { 
      SetVTable(36,PreDetour); 
      PreDetour=0; 
   } 
} 

DWORD gFG_MAX=0; 
DWORD gBG_MAX=0; 
DWORD CurMax=0; 
#define FRAME_COUNT 64 
DWORD FrameArray[FRAME_COUNT+1]={0}; 
DWORD CurrentFrame=0; 
DWORD FrameTime=0; 
DWORD LastSleep=0; 
BOOL bFrameArrayFilled=0; 
float FPS=0.0f; 

VOID SetMode(DWORD Mode) 
{ 
   if (Mode<2) 
   { 
      MaxFPSMode=Mode; 
      if (Mode==FPS_ABSOLUTE) // i dont really want to use sprintf here, suck it 
      { 
         WriteChatColor("FPS Limiter mode now absolute"); 
         WritePrivateProfileString("MQ2FPS","Mode","0",INIFileName); 
      } 
      else 
      { 
         WriteChatColor("FPS Limiter mode now calculate"); 
         WritePrivateProfileString("MQ2FPS","Mode","1",INIFileName); 
      } 
   } 
} 

VOID SetForegroundMaxFPS(DWORD MaxFPS) 
{ 
   gFG_MAX=MaxFPS; 
   /* 
    if (MaxFPS==0) 
        gFG_SLEEP=0; 
    else 
        gFG_SLEEP=1000/MaxFPS; 
   /**/ 
} 

VOID SetBackgroundMaxFPS(DWORD MaxFPS) 
{ 
   gBG_MAX=MaxFPS; 
   /* 
    if (MaxFPS==0) 
        gBG_SLEEP=0; 
    else 
        gBG_SLEEP=1000/MaxFPS; 
   /**/ 
} 

VOID ProcessFrame() 
{ 
   // Update frame array 
   DWORD Now=FrameArray[CurrentFrame]=GetTickCount(); 

   DWORD FirstFrame=0; 
   DWORD Frames=CurrentFrame; 
   if (bFrameArrayFilled) 
   { 
      FirstFrame=CurrentFrame+1; 
      if (FirstFrame>FRAME_COUNT) 
      { 
         FirstFrame=FRAME_COUNT; 
      } 
      Frames=FRAME_COUNT; 
   } 
   // Calculate time this frame 
   DWORD LastFrame=CurrentFrame-1; 
   if (LastFrame>FRAME_COUNT) 
   { 
      if (bFrameArrayFilled) 
      { 
         LastFrame=FRAME_COUNT; 
         FrameTime=Now-FrameArray[LastFrame]; 
      } 
      else 
         FrameTime=0; 
   } 
   else 
      FrameTime=Now-FrameArray[LastFrame]; 

   // Calculate FPS 
   // Get amount of time between first frame and now 
   DWORD Elapsed=Now-FrameArray[FirstFrame]; 


   if (Elapsed) 
   { 
      // less than one second? 
      if (Elapsed<1000) 
      { 
         // elapsed 150 ms 
         // extrapolate. how many frame arrays would fit in one second? 
         FPS=(float)(1000.0f/(float)Elapsed); 
         // 6.66667=1000/150 
         // now multiply by the number of frames we've gone through 
         // Frames 10 
         FPS*=(float)Frames; 
         // 66.6667= FPS * 10 
   //      FPS= 
      } 
      else 
      { 
         // Frames = 100 
         // Elapsed = 2000ms 
         // FPS = 100 / (2000/1000) = 50 

         // interpolate. how many seconds did it take for our frame array? 
         FPS=(float)Frames/(float)((float)Elapsed/1000.0f); // Frames / number of seconds 
      } 
   } 
   else 
      FPS=999.0f; 
   // advance frame count 
   if (++CurrentFrame>FRAME_COUNT) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=1; 
   } 
} 

// This is called every time MQ pulses 
PLUGIN_API VOID OnPulse(VOID) 
{ 
   // DONT leave in this debugspew, even if you leave in all the others 
//   DebugSpewAlways("MQ2FPS::OnPulse()"); 
   DebugTry(ProcessFrame()); 
   if (IsMouseWaiting()) 
      return; 


//   if (!gDelay && !gMacroPause && (!gMQPauseOnChat || *EQADDR_NOTINCHATMODE) && 
//        gMacroBlock && gMacroStack) { 
//      InMacro=true; 
//      Sleep(0); 
//    } 
//   else 
   { 
      InMacro=false; 
      HWND EQhWnd=*(HWND*)EQADDR_HWND; 
      if (EQW_GetDisplayWindow) 
         EQhWnd=EQW_GetDisplayWindow(); 
       
      if (GetForegroundWindow()==EQhWnd) 
      { 
         InForeground=true; 
         CurMax=gFG_MAX; 
         CurrentRate=gFG_Rate; 
         CurrentReverse=ReverseFG_Rate; 
         if (gFG_MAX) 
         { 
            int SleepTime=(int)(1000.0f/(float)gFG_MAX); 
            if (MaxFPSMode==FPS_CALCULATE) 
            { 
               // assume last frame time is constant, so a 30ms frame = 33 fps 
               // 
                
               SleepTime-=(FrameTime-LastSleep); 
               /**/ 
               if (SleepTime<0) 
                  SleepTime=0; 
               else if (SleepTime>300) 
                  SleepTime=300; 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
            else 
            { 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
         } 
         else 
            Sleep(0); 
      } 
      else 
      { 
         if (InForeground) 
         { 
            // just switched to background, release ctrl/alt/shift 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]=0; 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]=0; 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]=0; 
         } 
         InForeground=false; 
         CurMax=gBG_MAX; 
         CurrentRate=gBG_Rate; 
         CurrentReverse=ReverseBG_Rate; 
         if (gBG_MAX) 
         { 
            int SleepTime=(int)(1000.0f/(float)gBG_MAX); 
            if (MaxFPSMode==FPS_CALCULATE) 
            { 
               SleepTime-=(FrameTime-LastSleep); 
               /**/ 
               if (SleepTime<0) 
                  SleepTime=0; 
               else if (SleepTime>300) 
                  SleepTime=300; 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
            else 
            { 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
         } 
         else 
            Sleep(0); 
      } 
   } 

} 



// Called every frame that the "HUD" is drawn -- e.g. net status / packet loss bar 
PLUGIN_API VOID OnDrawHUD(VOID) 
{ 
   if (!pDisplay || !FPSIndicator) 
      return; 
   CHAR szBuffer[MAX_STRING]; 

    
   // Display 
   DWORD SX=0; 
   DWORD SY=0; 
   if (pScreenX && pScreenY) 
   { 
      SX=ScreenX; 
      SY=ScreenY; 
   } 
    
   if (InMacro) 
      sprintf(szBuffer,"%d/MACRO FPS",(DWORD)FPS); 
   else 
   { 
      if (MaxFPSMode==FPS_ABSOLUTE) 
      { 
         sprintf(szBuffer,"%d/%d* FPS",(DWORD)FPS,CurMax); 
      } 
      else 
      { 
         sprintf(szBuffer,"%d/%d FPS",(DWORD)FPS,CurMax); 
      } 
   } 



   DebugTry(pDisplay->WriteTextHD2(szBuffer,SX+FPSIndicatorX,SY+FPSIndicatorY,0x0d)); 

} 

VOID FPSCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
   if (Arg1[0]==0) { 
        SyntaxError("Usage: /fps <mode|absolute|calculate|x,y|on|off>"); 
        return; 
   } 

   if (!strnicmp(Arg1,"absolute",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(FPS_ABSOLUTE); 
      return; 
   } 
   else 
   if (!strnicmp(Arg1,"calculate",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(FPS_CALCULATE); 
      return; 
   } 
   else 
   if (!strnicmp(Arg1,"mode",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(MaxFPSMode==0); 
      return; 
   } 
   else 
    if (!strnicmp(Arg1,"on",strlen(Arg1))) 
    { 
       FPSIndicator=TRUE; 
       WritePrivateProfileString("MQ2FPS","Indicator","1",INIFileName); 
       return; 
    } 
    else 
    if (!strnicmp(Arg1,"off",strlen(Arg1))) 
    { 
       FPSIndicator=FALSE; 
       WritePrivateProfileString("MQ2FPS","Indicator","0",INIFileName); 
       return; 
    } 

   if (strchr(szLine,',')) 
   { 
      sscanf(szLine,"%d,%d",&FPSIndicatorX,&FPSIndicatorY); 
//      itoa(FPSIndicatorX,szCmd,10); 
      WritePrivateProfileString("MQ2FPS","IndicatorX",itoa(FPSIndicatorX,szCmd,10),INIFileName); 
      WritePrivateProfileString("MQ2FPS","IndicatorY",itoa(FPSIndicatorY,szCmd,10),INIFileName); 
      return; 
   } 
        SyntaxError("Usage: /fps <mode|absolute|calculate|x,y|on|off>"); 
} 


// *************************************************************************** 
// Function:      MaxFPS 
// Description:   Our /MaxFPS command. Sets or displays the max fps setting for 
//                foreground or background 
// 2003-11-01     Lax 
// *************************************************************************** 
VOID MaxFPS(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    CHAR Arg2[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
    GetArg(Arg2,szLine,2); 


   if (Arg1[0]==0 || Arg2[0]==0) { 
       sprintf(szCmd,"\aw\ayMaxFPS\ax\a-u:\ax \a-u[\ax\at%d\ax Foreground\a-u]\ax \a-u[\ax\at%d\ax Background\a-u]\ax \a-u[\ax%s Mode\a-u]\ax",gFG_MAX,gBG_MAX,szFPSModes[MaxFPSMode]); 
        WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
        WriteChatColor("Usage: /maxfps <fg|bg> <#>",CONCOLOR_YELLOW); 
        return; 
   } 
   DWORD NewMax=atoi(Arg2); 
   if (NewMax>200) 
   { 
       MacroError("MaxFPS: Please use a number between 0 and 200, 0 being absolute fastest, 1-200 being that many frames per second."); 
       return; 
   } 

   if (!stricmp(Arg1,"fg")) 
   { 
     SetForegroundMaxFPS(NewMax); 
       WritePrivateProfileString("MQ2FPS","ForegroundMaxFPS",Arg2,INIFileName); 
   } 
   else if (!stricmp(Arg1,"bg")) 
   { 
       SetBackgroundMaxFPS(NewMax); 
       WritePrivateProfileString("MQ2FPS","BackgroundMaxFPS",Arg2,INIFileName); 
   } 
    sprintf(szCmd,"\aw\ayMaxFPS\ax\a-u:\ax \a-u[\ax\at%d\ax Foreground\a-u]\ax \a-u[\ax\at%d\ax Background\a-u]\ax \a-u[\ax%s Mode\a-u]\ax",gFG_MAX,gBG_MAX,szFPSModes[MaxFPSMode]); 
    WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
} 

VOID RenderCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    CHAR Arg2[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
    GetArg(Arg2,szLine,2); 
   CHAR szFore[MAX_STRING]={0}; 
   CHAR szBack[MAX_STRING]={0}; 


   if (Arg1[0]==0 || Arg2[0]==0) { 
      if (ReverseFG_Rate) 
         sprintf(szFore,"%d/",gFG_Rate-1); 
      else 
         strcpy(szFore,"1/"); 
      if (ReverseBG_Rate) 
         sprintf(szBack,"%d/",gBG_Rate-1); 
      else 
         strcpy(szBack,"1/"); 
      sprintf(szCmd,"\aw\ayRender Rate\ax\a-u:\ax \a-u[\ax\at%s%d\ax Foreground\a-u]\ax \a-u[\ax\at%s%d\ax Background\a-u]\ax",szFore,gFG_Rate,szBack,gBG_Rate); 
        WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
      WriteChatColor("Usage: /render <fg|bg> <#|~#>",CONCOLOR_YELLOW); 
        return; 
   } 
   DWORD NewRate; 
   BOOL Reverse=false; 
   if (Arg2[0]=='~') 
   { 
      NewRate=atoi(&Arg2[1]); 
      Reverse=true; 
      memcpy(&Arg2[0],&Arg2[1],MAX_STRING-1); 
   } 
   else 
      NewRate=atoi(&Arg2[0]); 
   if (NewRate>200) 
   { 
       MacroError("Render: Please use a number between 0 and 200, 0 being absolute fastest, 1-200 being that many frames per second.",USERCOLOR_DEFAULT); 
       return; 
   } 

   if (!stricmp(Arg1,"fg")) 
   { 
      gFG_Rate=NewRate; 
      ReverseFG_Rate=Reverse; 
       WritePrivateProfileString("Rendering","FGRate",Arg2,INIFileName); 
      WritePrivateProfileString("Rendering","ReverseFGRate",ReverseFG_Rate?"1":"0",INIFileName); 
   } 
   else if (!stricmp(Arg1,"bg")) 
   { 
      gBG_Rate=NewRate; 
      ReverseBG_Rate=Reverse; 
       WritePrivateProfileString("Rendering","BGRate",Arg2,INIFileName); 
       WritePrivateProfileString("Rendering","ReverseBGRate",ReverseBG_Rate?"1":"0",INIFileName); 
   } 

   if (ReverseFG_Rate) 
      sprintf(szFore,"%d/",gFG_Rate-1); 
   else 
      strcpy(szFore,"1/"); 
   if (ReverseBG_Rate) 
      sprintf(szBack,"%d/",gBG_Rate-1); 
   else 
      strcpy(szBack,"1/"); 
   sprintf(szCmd,"\aw\ayRender Rate\ax\a-u:\ax \a-u[\ax\at%s%d\ax Foreground\a-u]\ax \a-u[\ax\at%s%d\ax Background\a-u]\ax",szFore,gFG_Rate,szBack,gBG_Rate); 
    WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
} 

BOOL dataFPS(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.Float=FPS; 
   Ret.Type=pFloatType; 
   return true; 
} 

BOOL dataMaxFPS(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.DWord=CurMax; 
   Ret.Type=pIntType; 
   return true; 
} 

BOOL dataForeground(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.DWord=InForeground; 
   Ret.Type=pBoolType; 
   return true; 
}
 
MQ2FPS

Changes the frames per second of the Everquest screen when it is in focus and when it is in the background.

This frees CPU processing time for other tasks. The default setting is foreground: 50 background:20.

MQ2FPS now releases the CTRL ALT and SHIFT keys as soon as EQ goes to the background.

/maxfps fg|bg #

Sets the foreground or background framerate

/fps mode [absolute|calculate]

Changes the mode used by /maxfps to absolute or calculate. You can specify the mode, or use /fps mode to toggle between the two.

/fps on|off

Enables or disables the framerate display

/render fg|bg #|~#

Sets the foreground or background rendering rate. This is how many out of n frames MQ2FPS will allow to be drawn. You keep moving full speed, the client responds to mouse or keys, the UI is still drawn... but, the world itself will not be drawn as often.

· The use of # will cause MQ2FPS to draw 1 of # frames.
· The use of ~# will cause MQ2FPS to draw n - 1 frames, where n is #.

Examples:
/render bg 3
Draws 1 out of 3 frames

/render bg ~3
Draws 2 out of 3 frames
 
here's the new one. no .h for you!!!
Rich (BB code):
// MQ2FPS.cpp : Defines the entry point for the DLL application. 
// 

// PLUGIN_API is only to be used for callbacks.  All existing callbacks at this time 
// are shown below. Remove the ones your plugin does not use.  Always use Initialize 
// and Shutdown for setup and cleanup, do NOT do it in DllMain. 

#pragma warning(disable:4786) 
//#define DEBUG_TRY 1 
#include "../MQ2Plugin.h" 

PreSetup("MQ2FPS"); 


VOID MaxFPS(PSPAWNINFO pChar, PCHAR szLine); 
VOID SetForegroundMaxFPS(DWORD MaxFPS); 
VOID SetBackgroundMaxFPS(DWORD MaxFPS); 
VOID FPSCommand(PSPAWNINFO pChar, PCHAR szLine); 

#define FPS_ABSOLUTE  0 
#define FPS_CALCULATE 1 

DWORD MaxFPSMode=FPS_CALCULATE; 

DWORD FPSIndicatorX=5; 
DWORD FPSIndicatorY=25; 
BOOL FPSIndicator=TRUE; 

bool InForeground=false; 

DWORD gFG_Rate=1; 
DWORD gBG_Rate=0; 
BOOL  ReverseFG_Rate=true;// skip every nth frame vs show every nth frame 
BOOL  ReverseBG_Rate=false; 

DWORD CurrentRate=1; 
BOOL CurrentReverse=false; 

DWORD PreDetour=0; 

BOOL InMacro=false; 

char *szFPSModes[]= 
{ 
   "Absolute", 
   "Calculate" 
}; 

HMODULE EQWhMod=0; 
typedef HWND   (__stdcall *fEQW_GetDisplayWindow)(VOID); 
fEQW_GetDisplayWindow EQW_GetDisplayWindow=0; 

BOOL dataFPS(PCHAR szIndex, MQ2TYPEVAR &Ret); 
BOOL dataMaxFPS(PCHAR szIndex, MQ2TYPEVAR &Ret); 
BOOL dataForeground(PCHAR szIndex, MQ2TYPEVAR &Ret); 
VOID RenderCommand(PSPAWNINFO pChar, PCHAR szLine); 

void SetVTable(DWORD index, DWORD value) 
{ 
   DWORD oldperm=0; 
   DWORD Address=(DWORD)&(*((DWORD**)g_pDrawHandler))[index]; 
   DebugSpewAlways("SetVTable writing at address %X to %X",Address,value); 
  VirtualProtectEx(GetCurrentProcess(), (LPVOID)Address, 4,PAGE_EXECUTE_READWRITE, &oldperm); 
 WriteProcessMemory( 
  GetCurrentProcess(), 
  (LPVOID)Address, 
  (LPVOID)&value, 
  4, 
  NULL); 
 VirtualProtectEx(GetCurrentProcess(), (LPVOID)Address, 4, oldperm, &oldperm); 
} 

DWORD GetVTable(DWORD index) 
{ 
   DWORD Ret=(*((DWORD**)g_pDrawHandler))[index]; 
   DebugSpewAlways("GetVTable(%d)=%X",index,Ret); 
   return Ret; 
} 

class CMyDisplay 
{ 
public: 
   VOID Void(VOID) 
   { 
      static DWORD nRender=0; 
      if (++nRender>CurrentRate-1) 
      { 
         nRender=0; 
         if (!CurrentReverse) 
         { 
            Render(); 
         } 
      } 
      else if (CurrentReverse) 
         Render(); 
   } 
   VOID Render(VOID); 
}; 
FUNCTION_AT_VARIABLE_ADDRESS(VOID CMyDisplay::Render(VOID),PreDetour); 

// Called once, when the plugin is to initialize 
PLUGIN_API VOID InitializePlugin(VOID) 
{ 
   DebugSpewAlways("Initializing MQ2FPS"); 
   if (EQWhMod=GetModuleHandle("eqw.dll")) 
   { 
      EQW_GetDisplayWindow=(fEQW_GetDisplayWindow)GetProcAddress(EQWhMod,"EQW_GetDisplayWindow"); 
   } 
    
   // Add commands, macro parameters, hooks, etc. 
   // INI Settings 
    DWORD Temp=0; 
    Temp = GetPrivateProfileInt("MQ2FPS","ForegroundMaxFPS",50,INIFileName); 
    SetForegroundMaxFPS(Temp); 
    Temp = GetPrivateProfileInt("MQ2FPS","BackgroundMaxFPS",30,INIFileName); 
    SetBackgroundMaxFPS(Temp); 
    MaxFPSMode = GetPrivateProfileInt("MQ2FPS","Mode",FPS_CALCULATE,INIFileName); 
    FPSIndicatorX = GetPrivateProfileInt("MQ2FPS","IndicatorX",5,INIFileName); 
    FPSIndicatorY = GetPrivateProfileInt("MQ2FPS","IndicatorY",25,INIFileName); 
   FPSIndicator = GetPrivateProfileInt("MQ2FPS","Indicator",TRUE,INIFileName); 

   gBG_Rate = GetPrivateProfileInt("Rendering","BGRate",30,INIFileName); 
   ReverseBG_Rate = GetPrivateProfileInt("Rendering","ReverseBGRate",0,INIFileName); 
   gFG_Rate = GetPrivateProfileInt("Rendering","FGRate",1,INIFileName); 
   ReverseFG_Rate = GetPrivateProfileInt("Rendering","ReverseFGRate",0,INIFileName); 

   // Commands 
   AddCommand("/maxfps",MaxFPS,0,1); 
   AddCommand("/fps",FPSCommand,0,1); 
   AddCommand("/render",RenderCommand,0,1); 

   AddMQ2Data("FPS",dataFPS); 
   AddMQ2Data("MaxFPS",dataMaxFPS); 
   AddMQ2Data("Foreground",dataForeground); 

} 

PLUGIN_API VOID SetGameState(DWORD GameState) 
{ 
   if (GameState==GAMESTATE_INGAME || GameState==GAMESTATE_CHARSELECT) 
   { 
      if (!PreDetour) 
         PreDetour=GetVTable(36); 
      VOID (CMyDisplay::*pfDetour)(VOID) = CMyDisplay::Void; 
      SetVTable(36,*(DWORD*)&pfDetour); 
   } 
} 


// Called once, when the plugin is to shutdown 
PLUGIN_API VOID ShutdownPlugin(VOID) 
{ 
   DebugSpewAlways("Shutting down MQ2FPS"); 
   // Remove commands, macro parameters, hooks, etc. 
   RemoveCommand("/maxfps"); 
   RemoveCommand("/fps"); 
   RemoveCommand("/render"); 
   RemoveMQ2Data("FPS"); 
   RemoveMQ2Data("MaxFPS"); 
   RemoveMQ2Data("Foreground"); 

   if (PreDetour) 
   { 
      SetVTable(36,PreDetour); 
      PreDetour=0; 
   } 
} 

DWORD gFG_MAX=0; 
DWORD gBG_MAX=0; 
DWORD CurMax=0; 
#define FRAME_COUNT 64 
DWORD FrameArray[FRAME_COUNT+1]={0}; 
DWORD CurrentFrame=0; 
DWORD FrameTime=0; 
DWORD LastSleep=0; 
BOOL bFrameArrayFilled=0; 
float FPS=0.0f; 

VOID SetMode(DWORD Mode) 
{ 
   if (Mode<2) 
   { 
      MaxFPSMode=Mode; 
      if (Mode==FPS_ABSOLUTE) // i dont really want to use sprintf here, suck it 
      { 
         WriteChatColor("FPS Limiter mode now absolute"); 
         WritePrivateProfileString("MQ2FPS","Mode","0",INIFileName); 
      } 
      else 
      { 
         WriteChatColor("FPS Limiter mode now calculate"); 
         WritePrivateProfileString("MQ2FPS","Mode","1",INIFileName); 
      } 
   } 
} 

VOID SetForegroundMaxFPS(DWORD MaxFPS) 
{ 
   gFG_MAX=MaxFPS; 
   /* 
    if (MaxFPS==0) 
        gFG_SLEEP=0; 
    else 
        gFG_SLEEP=1000/MaxFPS; 
   /**/ 
} 

VOID SetBackgroundMaxFPS(DWORD MaxFPS) 
{ 
   gBG_MAX=MaxFPS; 
   /* 
    if (MaxFPS==0) 
        gBG_SLEEP=0; 
    else 
        gBG_SLEEP=1000/MaxFPS; 
   /**/ 
} 

VOID ProcessFrame() 
{ 
   // Update frame array 
   DWORD Now=FrameArray[CurrentFrame]=GetTickCount(); 

   DWORD FirstFrame=0; 
   DWORD Frames=CurrentFrame; 
   if (bFrameArrayFilled) 
   { 
      FirstFrame=CurrentFrame+1; 
      if (FirstFrame>FRAME_COUNT) 
      { 
         FirstFrame=FRAME_COUNT; 
      } 
      Frames=FRAME_COUNT; 
   } 
   // Calculate time this frame 
   DWORD LastFrame=CurrentFrame-1; 
   if (LastFrame>FRAME_COUNT) 
   { 
      if (bFrameArrayFilled) 
      { 
         LastFrame=FRAME_COUNT; 
         FrameTime=Now-FrameArray[LastFrame]; 
      } 
      else 
         FrameTime=0; 
   } 
   else 
      FrameTime=Now-FrameArray[LastFrame]; 

   // Calculate FPS 
   // Get amount of time between first frame and now 
   DWORD Elapsed=Now-FrameArray[FirstFrame]; 


   if (Elapsed) 
   { 
      // less than one second? 
      if (Elapsed<1000) 
      { 
         // elapsed 150 ms 
         // extrapolate. how many frame arrays would fit in one second? 
         FPS=(float)(1000.0f/(float)Elapsed); 
         // 6.66667=1000/150 
         // now multiply by the number of frames we've gone through 
         // Frames 10 
         FPS*=(float)Frames; 
         // 66.6667= FPS * 10 
   //      FPS= 
      } 
      else 
      { 
         // Frames = 100 
         // Elapsed = 2000ms 
         // FPS = 100 / (2000/1000) = 50 

         // interpolate. how many seconds did it take for our frame array? 
         FPS=(float)Frames/(float)((float)Elapsed/1000.0f); // Frames / number of seconds 
      } 
   } 
   else 
      FPS=999.0f; 
   // advance frame count 
   if (++CurrentFrame>FRAME_COUNT) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=1; 
   } 
} 

// This is called every time MQ pulses 
PLUGIN_API VOID OnPulse(VOID) 
{ 
   // DONT leave in this debugspew, even if you leave in all the others 
//   DebugSpewAlways("MQ2FPS::OnPulse()"); 
   DebugTry(ProcessFrame()); 
   if (IsMouseWaiting()) 
      return; 


//   if (!gDelay && !gMacroPause && (!gMQPauseOnChat || *EQADDR_NOTINCHATMODE) && 
//        gMacroBlock && gMacroStack) { 
//      InMacro=true; 
//      Sleep(0); 
//    } 
//   else 
   { 
      InMacro=false; 
      HWND EQhWnd=*(HWND*)EQADDR_HWND; 
      if (EQW_GetDisplayWindow) 
         EQhWnd=EQW_GetDisplayWindow(); 
       
      if (GetForegroundWindow()==EQhWnd) 
      { 
         InForeground=true; 
         CurMax=gFG_MAX; 
         CurrentRate=gFG_Rate; 
         CurrentReverse=ReverseFG_Rate; 
         if (gFG_MAX) 
         { 
            int SleepTime=(int)(1000.0f/(float)gFG_MAX); 
            if (MaxFPSMode==FPS_CALCULATE) 
            { 
               // assume last frame time is constant, so a 30ms frame = 33 fps 
               // 
                
               SleepTime-=(FrameTime-LastSleep); 
               /**/ 
               if (SleepTime<0) 
                  SleepTime=0; 
               else if (SleepTime>300) 
                  SleepTime=300; 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
            else 
            { 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
         } 
         else 
            Sleep(0); 
      } 
      else 
      { 
         if (InForeground) 
         { 
            // just switched to background, release ctrl/alt/shift 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[0]=0; 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[1]=0; 
            ((PCXWNDMGR)pWndMgr)->KeyboardFlags[2]=0; 
         } 
         InForeground=false; 
         CurMax=gBG_MAX; 
         CurrentRate=gBG_Rate; 
         CurrentReverse=ReverseBG_Rate; 
         if (gBG_MAX) 
         { 
            int SleepTime=(int)(1000.0f/(float)gBG_MAX); 
            if (MaxFPSMode==FPS_CALCULATE) 
            { 
               SleepTime-=(FrameTime-LastSleep); 
               /**/ 
               if (SleepTime<0) 
                  SleepTime=0; 
               else if (SleepTime>300) 
                  SleepTime=300; 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
            else 
            { 
               Sleep(SleepTime); 
               LastSleep=SleepTime; 
            } 
         } 
         else 
            Sleep(0); 
      } 
   } 

} 



// Called every frame that the "HUD" is drawn -- e.g. net status / packet loss bar 
PLUGIN_API VOID OnDrawHUD(VOID) 
{ 
   if (!pDisplay || !FPSIndicator) 
      return; 
   CHAR szBuffer[MAX_STRING]; 

    
   // Display 
   DWORD SX=0; 
   DWORD SY=0; 
   if (pScreenX && pScreenY) 
   { 
      SX=ScreenX; 
      SY=ScreenY; 
   } 
    
   if (InMacro) 
      sprintf(szBuffer,"%d/MACRO FPS",(DWORD)FPS); 
   else 
   { 
      if (MaxFPSMode==FPS_ABSOLUTE) 
      { 
         sprintf(szBuffer,"%d/%d* FPS",(DWORD)FPS,CurMax); 
      } 
      else 
      { 
         sprintf(szBuffer,"%d/%d FPS",(DWORD)FPS,CurMax); 
      } 
   } 



   DebugTry(pDisplay->WriteTextHD2(szBuffer,SX+FPSIndicatorX,SY+FPSIndicatorY,0x0d)); 

} 

VOID FPSCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
   if (Arg1[0]==0) { 
        SyntaxError("Usage: /fps <mode|absolute|calculate|x,y|on|off>"); 
        return; 
   } 

   if (!strnicmp(Arg1,"absolute",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(FPS_ABSOLUTE); 
      return; 
   } 
   else 
   if (!strnicmp(Arg1,"calculate",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(FPS_CALCULATE); 
      return; 
   } 
   else 
   if (!strnicmp(Arg1,"mode",strlen(Arg1))) 
   { 
      CurrentFrame=0; 
      bFrameArrayFilled=0; 
      SetMode(MaxFPSMode==0); 
      return; 
   } 
   else 
    if (!strnicmp(Arg1,"on",strlen(Arg1))) 
    { 
       FPSIndicator=TRUE; 
       WritePrivateProfileString("MQ2FPS","Indicator","1",INIFileName); 
       return; 
    } 
    else 
    if (!strnicmp(Arg1,"off",strlen(Arg1))) 
    { 
       FPSIndicator=FALSE; 
       WritePrivateProfileString("MQ2FPS","Indicator","0",INIFileName); 
       return; 
    } 

   if (strchr(szLine,',')) 
   { 
      sscanf(szLine,"%d,%d",&FPSIndicatorX,&FPSIndicatorY); 
//      itoa(FPSIndicatorX,szCmd,10); 
      WritePrivateProfileString("MQ2FPS","IndicatorX",itoa(FPSIndicatorX,szCmd,10),INIFileName); 
      WritePrivateProfileString("MQ2FPS","IndicatorY",itoa(FPSIndicatorY,szCmd,10),INIFileName); 
      return; 
   } 
        SyntaxError("Usage: /fps <mode|absolute|calculate|x,y|on|off>"); 
} 


// *************************************************************************** 
// Function:      MaxFPS 
// Description:   Our /MaxFPS command. Sets or displays the max fps setting for 
//                foreground or background 
// 2003-11-01     Lax 
// *************************************************************************** 
VOID MaxFPS(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    CHAR Arg2[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
    GetArg(Arg2,szLine,2); 


   if (Arg1[0]==0 || Arg2[0]==0) { 
       sprintf(szCmd,"\aw\ayMaxFPS\ax\a-u:\ax \a-u[\ax\at%d\ax Foreground\a-u]\ax \a-u[\ax\at%d\ax Background\a-u]\ax \a-u[\ax%s Mode\a-u]\ax",gFG_MAX,gBG_MAX,szFPSModes[MaxFPSMode]); 
        WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
        WriteChatColor("Usage: /maxfps <fg|bg> <#>",CONCOLOR_YELLOW); 
        return; 
   } 
   DWORD NewMax=atoi(Arg2); 
   if (NewMax>200) 
   { 
       MacroError("MaxFPS: Please use a number between 0 and 200, 0 being absolute fastest, 1-200 being that many frames per second."); 
       return; 
   } 

   if (!stricmp(Arg1,"fg")) 
   { 
     SetForegroundMaxFPS(NewMax); 
       WritePrivateProfileString("MQ2FPS","ForegroundMaxFPS",Arg2,INIFileName); 
   } 
   else if (!stricmp(Arg1,"bg")) 
   { 
       SetBackgroundMaxFPS(NewMax); 
       WritePrivateProfileString("MQ2FPS","BackgroundMaxFPS",Arg2,INIFileName); 
   } 
    sprintf(szCmd,"\aw\ayMaxFPS\ax\a-u:\ax \a-u[\ax\at%d\ax Foreground\a-u]\ax \a-u[\ax\at%d\ax Background\a-u]\ax \a-u[\ax%s Mode\a-u]\ax",gFG_MAX,gBG_MAX,szFPSModes[MaxFPSMode]); 
    WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
} 

VOID RenderCommand(PSPAWNINFO pChar, PCHAR szLine) 
{ 
   bRunNextCommand = TRUE; 
   CHAR szCmd[MAX_STRING] = {0}; 
    CHAR Arg1[MAX_STRING] = {0}; 
    CHAR Arg2[MAX_STRING] = {0}; 
    GetArg(Arg1,szLine,1); 
    GetArg(Arg2,szLine,2); 
   CHAR szFore[MAX_STRING]={0}; 
   CHAR szBack[MAX_STRING]={0}; 


   if (Arg1[0]==0 || Arg2[0]==0) { 
      if (ReverseFG_Rate) 
         sprintf(szFore,"%d/",gFG_Rate-1); 
      else 
         strcpy(szFore,"1/"); 
      if (ReverseBG_Rate) 
         sprintf(szBack,"%d/",gBG_Rate-1); 
      else 
         strcpy(szBack,"1/"); 
      sprintf(szCmd,"\aw\ayRender Rate\ax\a-u:\ax \a-u[\ax\at%s%d\ax Foreground\a-u]\ax \a-u[\ax\at%s%d\ax Background\a-u]\ax",szFore,gFG_Rate,szBack,gBG_Rate); 
        WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
      WriteChatColor("Usage: /render <fg|bg> <#|~#>",CONCOLOR_YELLOW); 
        return; 
   } 
   DWORD NewRate; 
   BOOL Reverse=false; 
   if (Arg2[0]=='~') 
   { 
      NewRate=atoi(&Arg2[1]); 
      Reverse=true; 
      memcpy(&Arg2[0],&Arg2[1],MAX_STRING-1); 
   } 
   else 
      NewRate=atoi(&Arg2[0]); 
   if (NewRate>200) 
   { 
       MacroError("Render: Please use a number between 0 and 200, 0 being absolute fastest, 1-200 being that many frames per second.",USERCOLOR_DEFAULT); 
       return; 
   } 

   if (!stricmp(Arg1,"fg")) 
   { 
      gFG_Rate=NewRate; 
      ReverseFG_Rate=Reverse; 
       WritePrivateProfileString("Rendering","FGRate",Arg2,INIFileName); 
      WritePrivateProfileString("Rendering","ReverseFGRate",ReverseFG_Rate?"1":"0",INIFileName); 
   } 
   else if (!stricmp(Arg1,"bg")) 
   { 
      gBG_Rate=NewRate; 
      ReverseBG_Rate=Reverse; 
       WritePrivateProfileString("Rendering","BGRate",Arg2,INIFileName); 
       WritePrivateProfileString("Rendering","ReverseBGRate",ReverseBG_Rate?"1":"0",INIFileName); 
   } 

   if (ReverseFG_Rate) 
      sprintf(szFore,"%d/",gFG_Rate-1); 
   else 
      strcpy(szFore,"1/"); 
   if (ReverseBG_Rate) 
      sprintf(szBack,"%d/",gBG_Rate-1); 
   else 
      strcpy(szBack,"1/"); 
   sprintf(szCmd,"\aw\ayRender Rate\ax\a-u:\ax \a-u[\ax\at%s%d\ax Foreground\a-u]\ax \a-u[\ax\at%s%d\ax Background\a-u]\ax",szFore,gFG_Rate,szBack,gBG_Rate); 
    WriteChatColor(szCmd,USERCOLOR_DEFAULT); 
} 

BOOL dataFPS(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.Float=FPS; 
   Ret.Type=pFloatType; 
   return true; 
} 

BOOL dataMaxFPS(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.DWord=CurMax; 
   Ret.Type=pIntType; 
   return true; 
} 

BOOL dataForeground(PCHAR szIndex, MQ2TYPEVAR &Ret) 
{ 
   Ret.DWord=InForeground; 
   Ret.Type=pBoolType; 
   return true; 
}
 
--------------------Configuration: MQ2FPS - Win32 Release--------------------
Compiling...
MQ2FPS.cpp
EQLIB_IMPORTS
C:\mq2\MQ2FPS\MQ2FPS.h(108) : error C2065: 'GetPro' : undeclared identifier
C:\mq2\MQ2FPS\MQ2FPS.h(108) : error C2146: syntax error : missing ';' before identifier 'cAddress'
C:\mq2\MQ2FPS\MQ2FPS.h(108) : error C2065: 'cAddress' : undeclared identifier
C:\mq2\MQ2FPS\MQ2FPS.h(421) : error C2065: 'FPSIndic' : undeclared identifier
C:\mq2\MQ2FPS\MQ2FPS.h(421) : error C2146: syntax error : missing ')' before identifier 'atorY'
C:\mq2\MQ2FPS\MQ2FPS.h(421) : error C2660: 'WriteTextHD2' : function does not take 3 parameters
C:\mq2\MQ2FPS\MQ2FPS.h(421) : error C2059: syntax error : ')'
C:\mq2\MQ2FPS\MQ2FPS.cpp(13) : error C2374: 'INIFileName' : redefinition; multiple initialization
C:\mq2\MQ2FPS\../MQ2Plugin.h(39) : see declaration of 'INIFileName'
C:\mq2\MQ2FPS\MQ2FPS.cpp(13) : error C2084: function 'int __stdcall DllMain(void *,unsigned long,void *)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(18) : error C2374: 'MaxFPSMode' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(24) : see declaration of 'MaxFPSMode'
C:\mq2\MQ2FPS\MQ2FPS.cpp(20) : error C2374: 'FPSIndicatorX' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(26) : see declaration of 'FPSIndicatorX'
C:\mq2\MQ2FPS\MQ2FPS.cpp(21) : error C2374: 'FPSIndicatorY' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(27) : see declaration of 'FPSIndicatorY'
C:\mq2\MQ2FPS\MQ2FPS.cpp(22) : error C2374: 'FPSIndicator' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(28) : see declaration of 'FPSIndicator'
C:\mq2\MQ2FPS\MQ2FPS.cpp(24) : error C2374: 'InForeground' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(30) : see declaration of 'InForeground'
C:\mq2\MQ2FPS\MQ2FPS.cpp(26) : error C2374: 'gFG_Rate' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(32) : see declaration of 'gFG_Rate'
C:\mq2\MQ2FPS\MQ2FPS.cpp(27) : error C2374: 'gBG_Rate' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(33) : see declaration of 'gBG_Rate'
C:\mq2\MQ2FPS\MQ2FPS.cpp(28) : error C2374: 'ReverseFG_Rate' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(34) : see declaration of 'ReverseFG_Rate'
C:\mq2\MQ2FPS\MQ2FPS.cpp(29) : error C2374: 'ReverseBG_Rate' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(35) : see declaration of 'ReverseBG_Rate'
C:\mq2\MQ2FPS\MQ2FPS.cpp(31) : error C2374: 'CurrentRate' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(37) : see declaration of 'CurrentRate'
C:\mq2\MQ2FPS\MQ2FPS.cpp(32) : error C2374: 'CurrentReverse' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(38) : see declaration of 'CurrentReverse'
C:\mq2\MQ2FPS\MQ2FPS.cpp(34) : error C2374: 'PreDetour' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(40) : see declaration of 'PreDetour'
C:\mq2\MQ2FPS\MQ2FPS.cpp(36) : error C2374: 'InMacro' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(42) : see declaration of 'InMacro'
C:\mq2\MQ2FPS\MQ2FPS.cpp(38) : error C2374: 'szFPSModes' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(44) : see declaration of 'szFPSModes'
C:\mq2\MQ2FPS\MQ2FPS.cpp(44) : error C2374: 'EQWhMod' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(50) : see declaration of 'EQWhMod'
C:\mq2\MQ2FPS\MQ2FPS.cpp(46) : error C2374: 'EQW_GetDisplayWindow' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(52) : see declaration of 'EQW_GetDisplayWindow'
C:\mq2\MQ2FPS\MQ2FPS.cpp(54) : error C2084: function 'void __cdecl SetVTable(unsigned long,unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(69) : error C2084: function 'unsigned long __cdecl GetVTable(unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(76) : error C2011: 'CMyDisplay' : 'class' type redefinition
C:\mq2\MQ2FPS\MQ2FPS.cpp(94) : error C2084: function 'void __thiscall CMyDisplay::Render(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(98) : error C2084: function 'void __cdecl InitializePlugin(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(102) : error C2146: syntax error : missing ';' before identifier 'cAddress'
C:\mq2\MQ2FPS\MQ2FPS.cpp(134) : error C2084: function 'void __cdecl SetGameState(unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(138) : error C2440: '=' : cannot convert from 'unsigned long (__cdecl *)(unsigned long)' to 'unsigned long'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
C:\mq2\MQ2FPS\MQ2FPS.cpp(147) : error C2084: function 'void __cdecl ShutdownPlugin(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(164) : error C2374: 'gFG_MAX' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(170) : see declaration of 'gFG_MAX'
C:\mq2\MQ2FPS\MQ2FPS.cpp(165) : error C2374: 'gBG_MAX' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(171) : see declaration of 'gBG_MAX'
C:\mq2\MQ2FPS\MQ2FPS.cpp(166) : error C2374: 'CurMax' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(172) : see declaration of 'CurMax'
C:\mq2\MQ2FPS\MQ2FPS.cpp(168) : error C2374: 'FrameArray' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(174) : see declaration of 'FrameArray'
C:\mq2\MQ2FPS\MQ2FPS.cpp(169) : error C2374: 'CurrentFrame' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(175) : see declaration of 'CurrentFrame'
C:\mq2\MQ2FPS\MQ2FPS.cpp(170) : error C2374: 'FrameTime' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(176) : see declaration of 'FrameTime'
C:\mq2\MQ2FPS\MQ2FPS.cpp(171) : error C2374: 'LastSleep' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(177) : see declaration of 'LastSleep'
C:\mq2\MQ2FPS\MQ2FPS.cpp(172) : error C2374: 'bFrameArrayFilled' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(178) : see declaration of 'bFrameArrayFilled'
C:\mq2\MQ2FPS\MQ2FPS.cpp(173) : error C2374: 'FPS' : redefinition; multiple initialization
C:\mq2\MQ2FPS\MQ2FPS.h(179) : see declaration of 'FPS'
C:\mq2\MQ2FPS\MQ2FPS.cpp(176) : error C2084: function 'void __cdecl SetMode(unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(194) : error C2084: function 'void __cdecl SetForegroundMaxFPS(unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(205) : error C2084: function 'void __cdecl SetBackgroundMaxFPS(unsigned long)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(216) : error C2084: function 'void __cdecl ProcessFrame(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(288) : error C2084: function 'void __cdecl OnPulse(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(306) : error C2440: '=' : cannot convert from 'struct HWND__ *(__stdcall *)(void)' to 'struct HWND__ *'
There is no context in which this conversion is possible
C:\mq2\MQ2FPS\MQ2FPS.cpp(384) : error C2084: function 'void __cdecl OnDrawHUD(void)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(415) : error C2146: syntax error : missing ')' before identifier 'atorY'
C:\mq2\MQ2FPS\MQ2FPS.cpp(415) : error C2660: 'WriteTextHD2' : function does not take 3 parameters
C:\mq2\MQ2FPS\MQ2FPS.cpp(415) : error C2059: syntax error : ')'
C:\mq2\MQ2FPS\MQ2FPS.cpp(420) : error C2084: function 'void __cdecl FPSCommand(struct EQData::_SPAWNINFO *,char *)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(487) : error C2084: function 'void __cdecl MaxFPS(struct EQData::_SPAWNINFO *,char *)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(524) : error C2084: function 'void __cdecl RenderCommand(struct EQData::_SPAWNINFO *,char *)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(593) : error C2084: function 'int __cdecl dataFPS(char *,struct MQ2Internal::_MQ2TypeVar &)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(600) : error C2084: function 'int __cdecl dataMaxFPS(char *,struct MQ2Internal::_MQ2TypeVar &)' already has a body
C:\mq2\MQ2FPS\MQ2FPS.cpp(607) : error C2084: function 'int __cdecl dataForeground(char *,struct MQ2Internal::_MQ2TypeVar &)' already has a body
Error executing cl.exe.

MQ2FPS.dll - 59 error(s), 0 warning(s)



im thinking maybe i put header file in wrong directory?
 
Would this plugin still be beneficial with the new features in-game that let you make certain changes to the display? If not, what might be some of the advantages of this plugin, in what situations, etc.
 
this plugin can still help, in game features let you set an over all FPS rate but it stays at that same rate even while EQ is in the background.

This plugin allows you to set a foreground and background rate. Helps alot on resorces for machines that need every drop.
 
MQ2FPS - This plugin changes the frames per second of the Everquest screen when it is in focus and when it is in the background. This is the same as EQPlayNice, only more macro friendly.

Commands:

/fps [on|off] - On/Off enables or disables the FPS display.
/fps [x|y] - Use x and y to control the location of the FPS display on the screen.
/fps mode [absolute|calculate] - With mode you can change the FPS limiter mode to the one specified (absolute or calculate) or toggle between the two if no mode is specified.

Example
Rich (BB code):
 /fps on
 /fps mode absolute
 /fps 10,25
/render [bg|fg] #|~# - This sets the foreground or background rendering rate (ie. how many frames will be drawn). Setting the rendering rate does not slow down the game at all.
The client still responds to the mouse and keyboard the same, the UI is still drawn, but the world itself is not drawn as often.

With #, MQ2FPS will drawn 1 out of # frames.
The use of ~# will cause MQ2FPS to draw #-1 out of # frames.

Example

Rich (BB code):
 /render bg 3              Draws 1 out of 3 frames
 /render bg ~3             Draws 2 out of 3 frames
 /render bg 1~1            Draw every frame
/maxfps [bg|fg] # - Sets the foreground or background framerate.

Examples
Rich (BB code):
 /maxfps fg 25
 /maxfps bg 25
Sample INI File
Rich (BB code):
ForegroundMaxFPS=25
BackgroundMaxFPS=25
Indicator=1
Mode=1
IndicatorX=10
IndicatorY=25
[Rendering]
FGRate=1
ReverseFGRate=0
BGRate=75
ReverseBGRate=0
 
Last edited by a moderator:
It seems since the last 1-2 patches, where eqmule did something regarding to fps, this plugin dont work anymore for /maxfps bg

Whatever i do, my background dps drops to like 5-10, while i like it at 60 since i play with multiple monitors.

Anyone got an idea how to fix that ?

Edit: seems it's not because of mq2ic. /maxfps bg just dont seem to work anymore. :-(
 
Last edited:
MQ2FPS works fine for me. At the end of the day you should only have ONE thing managing FPS. So pick one and turn the others off :P (built-in set to unlimited for both to turn it off) But the things that can manage FPS are MQ2FPS, built-in, WinEQ2/EQPlayNice, ISBoxer (or w/e part of ISBoxer, I'm not 100% sure which :P)

But if multiple things are doing FPS limiting, you're gonna have a bad time.
 
Since we're on the topic of this plugin... anyone have a really good INI setting for it? I've tinkered around with it but figure someone has found the optimum setup :p
 
Here's what I run on a Lenovo W500... 2.53 ghz core 2 duo, 4 gig ram, 512mb ATI Radeon HD 3650...

Rich (BB code):
[MQ2FPS]
Indicator=1
ForegroundMaxFPS=35
BackgroundMaxFPS=35
Indicator=1
Mode=1
[Rendering]
FGRate=1
ReverseFGRate=0
BGRate=50
ReverseBGRate=0

it seems (i emphasize seems) to start stuttering if the window stays in the background too long... It acts like it doesn't recognize it's been moved to the front and picking up items from bags gets laggy...

but I haven't done any serious testing to see if it's just heat / time or the plugin that's the variable.
 
I think so - it helps you control it on the command line, so you can "up" it when you need to. Both the client and mq2fps work by slowing your client down - and MQ2, which limits CPU usage. Sometimes this isn't great - for example on your healer during a tough named. However, if you have a ton of boxes just farming easymode etc mq2fps+mq2viewport is a really good option.
 
About all it adds is the command line option. There's no advantage over the built in FPS limiter for background/foreground clients. If you haven't looked into it, I highly recommend checking out MQ2EQWire. It's an annual fee to mule, but it's well worth it's cost. MQ2FPS and viewport just can't measure up to the monster that is MQ2EQWire
 
About all it adds is the command line option. There's no advantage over the built in FPS limiter for background/foreground clients. If you haven't looked into it, I highly recommend checking out MQ2EQWire. It's an annual fee to mule, but it's well worth it's cost. MQ2FPS and viewport just can't measure up to the monster that is MQ2EQWire

I'll have to find out what configs people are using then.

Mq2fps+mq2viewport have a much greater effect on CPU usage at the expense of responsiveness. However , I only ever noticed that being an issue in TBL when I was under geared.

That said, paying 10 bucks to eqmule and getting a plug in is really no different to donating to him to help fund mq2 development as a whole anyway.
 
Plugin - MQ2FPS

Users who are viewing this thread

Back
Top