Plugin: MQ2TributeManager

alt228

New member
Joined
Jan 27, 2006
Messages
12
Reaction score
0
Points
0
This original MQ2 plugin adds a /tribute command in game with automatic tribute status management capabilities.
Usage: /tribute < auto | manual | on | off | forceoff | enabledetrimental | disabledetrimental | show | savesettings >

Options:
Code:
auto:  Automatically turn tribute on/off as you go in and out of combat.  If you enter combat and tribute is not on, it is activated immediately.  If you are not in combat when the tribute timer is going to expire, tribute is deactivated.
manual: Do not automatically turn on/off tribute. (default)
on: Turn on tribute but do not change auto/manual state.
off: Turn off tribute when current time left is going to expire.  This option should not be combined with other options that change the operation mode.
forceoff: Turn off tribute immediately, ignoring any remainder of current time left.
enabledetrimental: Enable turning on tribute when casting a detrimental spell and in automatic mode.
enabledetrimental: Disables turning on tribute when casting a detrimental spell and in automatic mode. (default)
savesettings: Saves current settings to INI file (which will be loaded the next time the character logs in)
show: Show the current mode.

Multiple options can be passed as one command.  
Example: 
/tribute on auto 
would turn the tribute on immediately and would automatically manage the state from then on.  (ie, good before engaging a big named)

Code:
// MQ2TributeManager.cpp : Defines the entry point for the DLL application.
//

// MQ2TributeManager
// Manages tribute for you based on combat status
// Author: alt228, alt228@nerdshack.com

#include "../MQ2Plugin.h"

enum TributeMode
{
	TributeMode_Manual,
	TributeMode_Auto,
	TributeMode_OffWhenExpired,
	TributeMode_Unused
};

enum CombatState
{
	CombatState_COMBAT,
	CombatState_DEBUFFED,
	CombatState_COOLDOWN,
	CombatState_ACTIVE,
	CombatState_RESTING
};

PreSetup("MQ2TributeManager");
PLUGIN_VERSION(1.1);

//defaults
TributeMode mode = TributeMode_Manual;
bool tributeInitialized = false;
bool useDetrimentalSpell = false;
int tributeFudge = 2000;


VOID SetTributeStatus(bool tributeOn)
{
	if( tributeOn )
	{
		if( !(bool)*pTributeActive )
		{
			DebugSpewAlways("MQ2TributeManager :: Turning on tribute");
			SendWndClick("TributeBenefitWnd", "DowngradeButton", "leftmouseup");
		}
	}
	else
	{
		if( (bool)*pTributeActive )
		{
			DebugSpewAlways("MQ2TributeManager :: Turning off tribute");
			SendWndClick("TributeBenefitWnd", "DowngradeButton", "leftmouseup");
		}
	}
}

VOID LoadPreferences()
{
	WriteChatColor("MQ2TributeManager :: Reading settings from INI file.");

	CHAR iniSection[MAX_STRING];
	sprintf(iniSection,"%s_%s",EQADDR_SERVERNAME, GetCharInfo()->Name);
	CHAR iniMode[MAX_STRING];
	CHAR iniDetrimentalSpell[MAX_STRING];

	DebugSpewAlways("MQ2TributeManager :: Reading INI");
	GetPrivateProfileString(iniSection, "Mode", "Manual", iniMode, 30, INIFileName);
	GetPrivateProfileString(iniSection, "UseDetrimentalSpell", "0", iniDetrimentalSpell, 30, INIFileName);
	if( (stricmp(iniMode, "Manual") == 0) && (mode != TributeMode_Manual) )
	{
		mode = TributeMode_OffWhenExpired;
	}
	else if( stricmp(iniMode, "Auto") == 0 )
	{
		mode = TributeMode_Auto;
	}

	useDetrimentalSpell = (stricmp(iniDetrimentalSpell,"1") == 0);
}

VOID SavePreferences()
{
	CHAR iniSection[MAX_STRING];
	CHAR valueTemp[MAX_STRING];

	sprintf(iniSection,"%s_%s",EQADDR_SERVERNAME, GetCharInfo()->Name);
	if( mode == TributeMode_Auto )
	{
		WritePrivateProfileString(iniSection, "Mode", "Auto", INIFileName);
	}
	else if( (mode == TributeMode_Manual) || (mode == TributeMode_OffWhenExpired) )
	{
		WritePrivateProfileString(iniSection, "Mode", "Manual", INIFileName);
	}

	sprintf(valueTemp,"%d",useDetrimentalSpell);
	WritePrivateProfileString(iniSection, "UseDetrimentalSpell", valueTemp, INIFileName);

	WriteChatColor("MQ2TributeManager :: Preferences Saved");
	
}

VOID TributeManagerCmd(PSPAWNINFO characterSpawn, PCHAR line)
{
	bool syntaxError = false;
	if (line[0]==0)
	{
		syntaxError = true;
	}
	
	bool setMode = false;
	TributeMode newMode = TributeMode_Unused;

	bool setStatus = false;
	bool newStatus = true;

	bool showStatus = false;
	bool saveSettings = false;

    CHAR thisArg[MAX_STRING] = {0};
	int argNumber = 1;
	bool moreArgs = true;

	while(moreArgs && argNumber<10 )
	{
		DebugSpewAlways("MQ2TributeManager :: GetArg(%i)", argNumber);
		GetArg(thisArg,line,argNumber);
		argNumber++;

	
		if( !thisArg || (strlen(thisArg)==0) )
		{
			moreArgs = false;
		}
		else if(stricmp(thisArg,"on") == 0)
		{
			setStatus = true;
			newStatus = true;
		}
		else if(stricmp(thisArg,"off") == 0)
		{
			setMode = true;
			newMode = TributeMode_OffWhenExpired;
		}
		else if(stricmp(thisArg,"forceoff") == 0)
		{
			setStatus = true;
			newStatus = false;
			setMode = true;
			newMode = TributeMode_Manual;
		}
		else if(stricmp(thisArg,"auto") == 0)
		{
			setMode = true;
			newMode = TributeMode_Auto;
		}
		else if(stricmp(thisArg,"manual") == 0)
		{
			setMode = true;
			newMode = TributeMode_Manual;
		}
		else if(stricmp(thisArg,"show") == 0)
		{
			showStatus = true;
		}
		else if(stricmp(thisArg,"savesettings") == 0)
		{
			saveSettings = true;
		}
		else if(stricmp(thisArg,"enabledetrimental") == 0)
		{
			useDetrimentalSpell = true;
		}
		else if(stricmp(thisArg,"disabledetrimental") == 0)
		{
			useDetrimentalSpell = false;
		}
		else
		{
			syntaxError = true;
		}
	}

	if( syntaxError )
	{
		SyntaxError("Usage: /tribute < auto | manual | on | off | forceoff | enabledetrimental | disabledetrimental | show | savesettings >");
		return;
	}

	if( setStatus )
	{
		SetTributeStatus(newStatus);
	}

	if( setMode )
	{
		mode = newMode;
	}

	if( showStatus )
	{
		CHAR buffer[MAX_STRING];

		WriteChatColor("--------------------------------");
		if( mode == TributeMode_Manual )
		{
			WriteChatColor("MQ2TributeManager :: Tribute mode: manual");
		}
		else if( mode == TributeMode_Auto )
		{
			WriteChatColor("MQ2TributeManager :: Tribute mode: automatic");
		}
		else if( mode == TributeMode_OffWhenExpired )
		{
			WriteChatColor("MQ2TributeManager :: Tribute mode: off when expired");
		}

		sprintf(buffer,"MQ2TributeManager :: Detrimental Spell Activation: %i", useDetrimentalSpell);
		WriteChatColor(buffer);

		if( gGameState == GAMESTATE_INGAME )
		{
			sprintf(buffer,"MQ2TributeManager :: Active Favor Cost: %i", pEQMisc->GetActiveFavorCost());
			WriteChatColor(buffer);
			sprintf(buffer,"MQ2TributeManager :: Combat State: %i", (CombatState)((PCPLAYERWND)pPlayerWnd)->CombatState);
			WriteChatColor(buffer);
			sprintf(buffer,"MQ2TributeManager :: Tribute Active: %i", *pTributeActive);
			WriteChatColor(buffer);
			sprintf(buffer,"MQ2TributeManager :: Current Favor: %i", GetCharInfo()->CurrFavor);
			WriteChatColor(buffer);
			sprintf(buffer,"MQ2TributeManager :: Tribute Timer: %i ms", GetCharInfo()->TributeTimer);
			WriteChatColor(buffer);
		}
		WriteChatColor("--------------------------------");

	}

	if( saveSettings )
	{
		SavePreferences();
	}

}

// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
	DebugSpewAlways("MQ2TributeManager :: Initializing");
	AddCommand("/tribute",TributeManagerCmd);
}

// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
	DebugSpewAlways("MQ2TributeManager :: Shutting down");
	RemoveCommand("/tribute");
}


// This is called every time MQ pulses
PLUGIN_API VOID OnPulse(VOID)
{
	if( gGameState != GAMESTATE_INGAME )
	{
		return;
	}

	if( mode == TributeMode_Auto )
	{
		PCHARINFO myCharInfo = GetCharInfo();
		DWORD castingID = myCharInfo->pSpawn->CastingSpellID;
		CombatState combatState = (CombatState)((PCPLAYERWND)pPlayerWnd)->CombatState;
		int activeFavorCost = pEQMisc->GetActiveFavorCost();

		bool inCombat = false;

		if( combatState == CombatState_COMBAT )
		{
			inCombat = true;
		}
		
		if( (!inCombat) && (castingID != -1) && (useDetrimentalSpell) )
		{
			PSPELL casting = GetSpellByID(castingID);
			if( casting->SpellType == 0 )
			{
				//detrimental spell
				inCombat = true;
			}
		}


		if( (inCombat) && (!*pTributeActive) && (activeFavorCost <= myCharInfo->CurrFavor) && (pEQMisc->GetActiveFavorCost() > 0) )
		{
			//activate tribute
			SetTributeStatus(true);
		}
		else if( (!inCombat) && (*pTributeActive) && (myCharInfo->TributeTimer < tributeFudge) )
		{
			//deactivate tribute
			SetTributeStatus(false);
		}
	}
	else if( mode == TributeMode_OffWhenExpired )
	{
		if( (bool)*pTributeActive == false )
		{
			mode = TributeMode_Manual;
			return;
		}

		if( GetCharInfo()->TributeTimer < tributeFudge )
		{
			mode = TributeMode_Manual;
			SetTributeStatus(false);
		}

	}

}


PLUGIN_API VOID SetGameState(DWORD GameState)
{
	if( GameState == GAMESTATE_INGAME )
	{
		if( !tributeInitialized )
		{
			DebugSpewAlways("MQ2TributeManager :: Making sure that TributeBenefitWnd has been opened at least once.");
			DoCommand( (PSPAWNINFO)pCharSpawn, "/keypress TOGGLE_TRIBUTEBENEFITWIN" );
			DoCommand( (PSPAWNINFO)pCharSpawn, "/keypress TOGGLE_TRIBUTEBENEFITWIN" );

			LoadPreferences();

			tributeInitialized = true;
		}
	}
	else if( GameState == GAMESTATE_CHARSELECT )
	{
		tributeInitialized = false;
	}
}

Compiled DLL attached.

alt228
alt228@nerdshack.com
 

Attachments

  • MQ2TributeManager.dll
    128 KB · Views: 32
Last edited:
Does this automatically toggle tribute if you're phisically attacking/being attacked, os is it based on your combat state, ie: crossed swords?

Also when set to auto, does it automatically shut off tribute as soon as you're out of combat, or does it wait till the timer is expiring?

If this works as I want it to, and Fry still doesn't give you any access I'll buy ya month!
 
hmm looks ok, will test it tonight
but i do see some things in there that look suspect
 
Does this automatically toggle tribute if you're phisically attacking/being attacked, os is it based on your combat state, ie: crossed swords?
It's based on your combat state, ie crossed swords.

Also when set to auto, does it automatically shut off tribute as soon as you're out of combat, or does it wait till the timer is expiring?
It waits until the timer has less than 2 seconds on it.
 
Tested Auto mode.. works like a charm. Thanks!

I must of burned through well over 100k tribute now by forgetting to switch it off!
 
I must of burned through well over 100k tribute now by forgetting to switch it off!

Ha ha, I hear ya! That's why I wrote the plugin. I'm also forgetful and don't remember to turn on my tribute until just after I needed it.
 
Excellent. I use tribute on my warrior for haste, so this is a very welcome plugin.
 
When set to auto mode it turns off fine, but it wont turn back on when I go into combat. /tribute auto is the command right?
 
When set to auto mode it turns off fine, but it wont turn back on when I go into combat. /tribute auto is the command right?

What build of MQ2 are you using? I'll look to see if I can duplicate this. /tribute auto is correct.
 
Still working perfectly for me with the 17th compile.
 
I'm using the 17th compile too and it hasn't failed me yet.

Athough, with how simple this thing is I don't know if the compile would really make a difference.

I tested it for 4 hours off & on last night, but couldn't get it to break. Of course, maybe since the plugin was written by a U of M grad, it won't work for any buckeyes fans. *shrug* When you let me know what compile (and UI actually) you are using I'll take a deeper look into this.

(Go Blue!)
 
What'd really be the win with this is .ini support to store different settings per character (I play other people's toons frequently and don't like to burn their tribute), but it's still pretty damn nice just as is.
 
Im using the 17th compile myself. My UI is a bunch of parts and pieces to keep it as small as I can. Basicly it doesnt do anything for me at all. Its not turning off or on. Ive unloaded it, and reloaded it. Im gonna take the plugin from the newest compile see what happens.Im sure its the same one /shrug
You know I would never say that folks from that state up north cant write plugins :D Go Bucks :eek:
 
Ok, I've noticed something interesting the night before last while raiding. If I heal a person that is engaged on a mob, my state does not immediately become "In Combat" but it does go out of the resting state. Are you by chance a healing class, Mr. OSU?

This should be a relatively straightforward fix once I can test all the transitions. Unfortunately I'll be out of town this weekend so don't expect it until probably Monday.

Also, until I can get the INI support going, please remember that you should be able to put a /tribute auto or a /tribute manual into your servername_charactername.cfg files.
 
Im a warrior. It just doesnt work at all. It wont turn off or on at this point. Ive sat totally out of combat and it wont shut off, and if I turn it off it wont turn it back on. Even though I use parts of different UIs, my tribute window is no different, its still default. Now my player window is one I downloaded from eqinterface that shows my tribute timer. Im not sure if that has anything to do with it or not. Ive downloaded the newest compile and it does nothing. All my other plugins work great, so Im thinking there is something up with just this one.
 
I've found that it does not work until I have brought up the tribute window once. At least it appears that way.
 
1Now my player window is one I downloaded from eqinterface that shows my tribute timer. Im not sure if that has anything to do with it or not.

It probably has a lot to do with it. The combat state is really being scraped from that window, so if it isn't on that custom UI then it can't find it to determine your combat state. If you upload your EQUI_PlayerWindow.xml I can modify it to make sure it's on there and named appropriately. If you don't want it visible on there, I can just add it and shove it out of the viewable area of that window.
 
I've found that it does not work until I have brought up the tribute window once. At least it appears that way.

I haven't seen that behavior, but I usually look at my current tribute at the beginning of my play session. I'll see if I can verify (and fix) this once I'm back from my trip.