Browse Source

Initial code commit.

master
atom0s 8 years ago
parent
commit
c3ae049e9c
  1. 22
      WatchEXP.sln
  2. 94
      WatchEXP/CommandParse.h
  3. 966
      WatchEXP/WatchEXP.cpp
  4. 85
      WatchEXP/WatchEXP.h
  5. 111
      WatchEXP/WatchEXP.vcxproj
  6. 35
      WatchEXP/WatchEXP.vcxproj.filters
  7. 5
      WatchEXP/exports.def

22
WatchEXP.sln

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30501.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WatchEXP", "WatchEXP\WatchEXP.vcxproj", "{25DAD057-C948-487D-A69C-6540DCD565DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{25DAD057-C948-487D-A69C-6540DCD565DA}.Debug|Win32.ActiveCfg = Debug|Win32
{25DAD057-C948-487D-A69C-6540DCD565DA}.Debug|Win32.Build.0 = Debug|Win32
{25DAD057-C948-487D-A69C-6540DCD565DA}.Release|Win32.ActiveCfg = Release|Win32
{25DAD057-C948-487D-A69C-6540DCD565DA}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

94
WatchEXP/CommandParse.h

@ -0,0 +1,94 @@
#pragma once
#ifndef __COMMANDPARSE_H_INCLUDED__
#define __COMMANDPARSE_H_INCLUDED__
#include <Windows.h>
#include <string>
#define VALIDATE_COMMAND( s, c ) \
if (_strnicmp( s + 1, c, strlen( c ) ) != 0) \
return false;
#define HANDLE_ARGUMENT( a, b ) \
if (a[1] == b)
/**
* GetCommandArgs
* @param1 : The command to parse for arguments.
* @param2 : Array of strings to store the found arguments.
* @returns : Number of arguments found within the command.
*
* This function mimics the *nix command 'strsep' to locate and
* parse strings with inline-quotes.
*
* Thanks to:
* http://stackoverflow.com/questions/9659697/parse-string-into-array-based-on-spaces-or-double-quotes-strings
*
* Modified for Ashita needs with plugin commands.
*
*/
int __stdcall GetCommandArgs( const char* pszCommand, std::string* args )
{
enum {
NONE,
IN_WORD,
IN_STRING,
} state = NONE;
char szCurrentArgument[ 255 ] = { 0 };
char szCurrentChar = 0;
char *pszStart = 0;
int nArgCount = 0;
for (const char* p = pszCommand; *p != '\0' || state != NONE; ++p)
{
szCurrentChar = (unsigned char)*p;
switch (state)
{
case NONE:
{
if (isspace( szCurrentChar ))
continue;
if (szCurrentChar == '"')
{
state = IN_STRING;
pszStart = (char*)( p + 1 );
continue;
}
state = IN_WORD;
pszStart = (char*)p;
continue;
}
case IN_STRING:
if (szCurrentChar == '"')
{
strncpy_s( szCurrentArgument, pszStart, p - pszStart );
args[nArgCount] = std::string( szCurrentArgument );
nArgCount++;
state = NONE;
}
continue;
case IN_WORD:
if (isspace( szCurrentChar ) || *++p == '\0')
{
strncpy_s( szCurrentArgument, pszStart, p - pszStart );
args[nArgCount] = std::string( szCurrentArgument );
nArgCount++;
state = NONE;
}
*--p;
continue;
}
}
return nArgCount;
}
#endif // __COMMANDPARSE_H_INCLUDED__

966
WatchEXP/WatchEXP.cpp

@ -0,0 +1,966 @@
#include "WatchEXP.h"
#include "CommandParse.h"
WatchEXP::WatchEXP(void)
: m_AshitaCore(nullptr)
, m_PluginId(0)
, m_Direct3DDevice(nullptr)
, m_ExpObj(nullptr)
, m_AbyTimeStart(0)
, m_DynTimeStart(0)
, m_BaseTimeEXP(0)
, m_BaseTimeCR(0)
, m_resetTime(NULL)
, font_size(0)
, m_reset_min(0)
, m_CurrentZoneID(0)
, m_LastZoneRecorded(0)
, m_Dyna_Crm('X')
, m_Dyna_Azr('X')
, m_Dyna_Amb('X')
, m_Dyna_Alab('X')
, m_Dyna_Obs('X')
, m_vTime(0)
, m_DynaTime(0)
, m_xpKill(0)
, m_xpTotal(0)
, m_xpTest(0)
, m_crKill(0)
, m_crTotal(0)
, m_prl(0)
, m_gld(0)
, m_slv(0)
, m_ebn(0)
, m_azr(0)
, m_rby(0)
, m_amb(0)
, backTrans(0)
, m_IsInAbyssea(false)
, m_IsInDynamis(false)
, show_XP_M_always(false)
, m_autoreset(false)
{ }
WatchEXP::~WatchEXP(void)
{ }
plugininfo_t WatchEXP::GetPluginInfo(void)
{
return *g_PluginInformation;
}
bool WatchEXP::Initialize(IAshitaCore* core, ILogManager* log, uint32_t id)
{
// Store the variables we are passed..
this->m_AshitaCore = core;
this->m_PluginId = id;
this->GetConfig();
return true;
}
void WatchEXP::Release(void)
{
}
bool WatchEXP::HandleCommand(const char* pszCommand, int nCommandType)
{
if (pszCommand == nullptr)
return false;
if (_strnicmp(pszCommand, "/wexp", 4) == 0)
{
std::vector<std::string> args;
Ashita::Commands::GetCommandArgs(pszCommand, &args);
if (args[1] == "reset")
{
m_crTotal = 0, m_xpTotal = 0, m_xpKill = 0, m_crKill = 0;
m_BaseTimeEXP = time(nullptr), m_BaseTimeCR = time(nullptr);
m_AshitaCore->GetChatManager()->Write("WatchEXP was reset!");
return true;
}
if (args[1] == "config")
{
this->GetConfig();
m_ExpObj->SetFontFamily(font_name);
m_ExpObj->SetFontHeight(font_size);
return true;
}
}
return false;
}
//bool WatchEXP::HandleNewChatLine(short sMode, char* pszChatLine)
bool WatchEXP::HandleIncomingText(int16_t sMode, const char* pszChatLine, int16_t* modifiedMode, char* modifiedMessage, bool blocked)
{
std::string data;
std::vector< std::string > temp;
data = ScrubChat(pszChatLine);
//Holds matches
std::smatch m;
#pragma region Search Pattern
//Regex Searches
std::regex xp_inc("gains\\s\\d+\\s(experience|limit)\\spoints");
std::regex xp_chain("EXP\\schain\\s\\d+\\s\\w+\\sgains\\s\\d+\\sexperience\\spoints");
std::regex cru_inc("obtained\\s\\d+\\scruor", std::regex_constants::icase);
std::regex vis_wear("Your\\svisitant\\sstatus\\swill\\swear\\soff\\sin\\s\\d+\\sminutes");
std::regex vis_inc("Your\\svisitant\\sstatus\\shas\\sbeen\\sextended\\sby\\s\\d+\\sminutes");
std::regex vis_exit("Exiting\\sin\\s\\d+\\sminutes");
std::regex vis_pegs("Visitant\\sLight\\sIntensity\\sPearlescent\\s\\d+\\sEbon\\s\\d+\\sGolden\\s\\d+\\sSilvery\\s\\d+");
std::regex vis_azram("Azure\\s\\d+\\sRuby\\s\\d+\\sAmber\\s\\d+");
std::regex light_pearl("body\\semits\\sa\\sfaint\\spearlescent\\slight");
std::regex light_azure("body\\semits\\sa\\sfeeble\\sazure\\slight");
std::regex light_ruby("body\\semits\\sa\\sfeeble\\sruby\\slight");
std::regex light_amber("body\\semits\\sa\\sfeeble\\samber\\slight");
std::regex light_gold("body\\semits\\sa\\sfaint\\sgolden\\slight");
std::regex light_silver("body\\semits\\sa\\sfaint\\ssilvery\\slight");
std::regex light_ebon("body\\semits\\sa\\sfaint\\sebon\\slight");
std::regex dyn_start("sands");
std::regex dyn_start2("hourglass");
std::regex dyn_extend("Dynamis");
std::regex dyn_extend2("extended");
std::regex dyn_expelled("expelled");
//Used to get all the numbers
std::regex get_number("\\d+");
if (sMode == 121)
{
if (std::regex_search(data, xp_chain))
{
std::sregex_token_iterator start(data.begin(), data.end(), get_number, 0), end;
while (start != end)
{
temp.push_back(*start);
++start;
}
if (temp.size() >= 1)
m_xpKill = std::stoi(temp[temp.size() - 1]);
else
m_xpKill = 0;
m_xpTotal += m_xpKill;
}
}
if (sMode == 131)
{
if (std::regex_search(data, xp_inc))
{
std::sregex_token_iterator start(data.begin(), data.end(), get_number, 0), end;
temp.clear();
while (start != end)
{
temp.push_back(*start);
++start;
}
if (temp.size() >= 1)
m_xpKill = std::stoi(temp[temp.size() - 1]);
else
m_xpKill = 0;
m_xpTotal += m_xpKill;
}
}
else if (sMode == 633)
{
if (std::regex_search(data, cru_inc))
{
std::sregex_token_iterator start(data.begin(), data.end(), get_number, 0), end;
temp.clear();
while (start != end)
{
temp.push_back(*start);
++start;
}
if (temp.size() >= 1)
m_crKill = std::stoi(temp[temp.size() - 1]);
else
m_crKill = 0;
m_crTotal += m_crKill;
}
else if (std::regex_search(data, vis_inc))
{
m_vTime += 10;
}
}
else if (sMode == 653)
{
if ((std::regex_search(data, dyn_expelled)) && (std::regex_search(data, dyn_extend)))
{
std::regex_search(data, m, get_number);
m_DynaTime = std::stoi(m.str());
m_DynTimeStart = time(nullptr);
}
}
else if (sMode == 658)
{
if ((std::regex_search(data, dyn_extend)) && (std::regex_search(data, dyn_extend2)))
{
std::regex_search(data, m, get_number);
m_DynaTime += std::stoi(m.str());
m_DynTimeStart = time(nullptr);
}
}
else if (sMode == 660)
{
if ((std::regex_search(data, dyn_start)) && (std::regex_search(data, dyn_start2)))
{
std::regex_search(data, m, get_number);
m_DynaTime = std::stoi(m.str());
}
if (std::regex_search(data, vis_exit))
{
std::regex_search(data, m, get_number);
m_vTime = std::stoi(m.str());
}
else if (std::regex_search(data, cru_inc))
{
std::regex_search(data, m, get_number);
m_crKill = std::stoi(m.str());
m_crTotal += m_crKill;
}
else if (std::regex_search(data, vis_wear))
{
std::regex_search(data, m, get_number);
m_vTime = std::stoi(m.str());
m_AbyTimeStart = time(nullptr);
}
else if (std::regex_search(data, vis_pegs))
{
std::sregex_token_iterator start(data.begin(), data.end(), get_number, 0), end;
while (start != end)
{
temp.push_back(*start);
++start;
}
//Corrects Pearlescent Values
m_prl = std::stoi(temp[0]);
//Corrects Ebon Values
m_ebn = std::stoi(temp[1]);
//Corrects Gold Values
m_gld = std::stoi(temp[2]);
//Corrects Silvery Values
m_slv = std::stoi(temp[3]);
}
else if (std::regex_search(data, vis_azram))
{
std::sregex_token_iterator start(data.begin(), data.end(), get_number, 0), end;
while (start != end)
{
temp.push_back(*start);
++start;
}
//Corrects Azure Values
m_azr = std::stoi(temp[0]);
//Corrects Ruby Values
m_rby = std::stoi(temp[1]);
//Corrects Amber Values
m_amb = std::stoi(temp[2]);
}
else if (std::regex_search(data, light_pearl))
{
//checks to ensure value does not exceed 230
if (m_prl + 5 > 230)
{
m_prl = 230;
}
else
{
m_prl += 5;
}
}
else if (std::regex_search(data, light_gold))
{
//checks to ensure value does not exceed 200
if (m_gld + 5 > 200)
{
m_gld = 200;
}
else
{
m_gld += 5;
}
}
else if (std::regex_search(data, light_silver))
{
//checks to ensure value does not exceed 200
if (m_slv + 5 > 200)
{
m_slv = 200;
}
else
{
m_slv += 5;
}
}
else if (std::regex_search(data, light_ebon))
{
//checks to ensure value does not exceed 200
if (m_ebn + 1 > 200)
{
m_ebn = 200;
}
else
{
m_ebn += 1;
}
}
else if (std::regex_search(data, light_azure))
{
//checks to ensure value does not exceed 255
if (m_azr + 8 > 255)
{
m_azr = 255;
}
else
{
m_azr += 8;
}
}
else if (std::regex_search(data, light_ruby))
{
//checks to ensure value does not exceed 255
if (m_rby + 8 > 255)
{
m_rby = 255;
}
else
{
m_rby += 8;
}
}
else if (std::regex_search(data, light_amber))
{
//checks to ensure value does not exceed 255
if (m_amb + 8 > 255)
{
m_amb = 255;
}
else
{
m_amb += 8;
}
}
}
#pragma endregion
return false;
}
bool WatchEXP::Direct3DInitialize(IDirect3DDevice8* lpDevice)
{
this->m_Direct3DDevice = lpDevice;
m_ExpObj = m_AshitaCore->GetFontManager()->Create("EXP_ID");
m_ExpObj->SetText("0/0");
m_ExpObj->SetFontFamily(font_name);
m_ExpObj->SetFontHeight(font_size);
m_ExpObj->SetColor(0xFFFFFFFF);
m_ExpObj->SetBold(false);
m_ExpObj->SetVisibility(true);
m_ExpObj->SetPositionX(100);
m_ExpObj->SetPositionY(100);
m_ExpObj->SetVisibility(false);
m_ExpObj->GetBackground()->SetVisibility(true);
m_ExpObj->GetBackground()->SetColor(0x80000000);
m_BaseTimeEXP = time(nullptr);
m_BaseTimeCR = time(nullptr);
return true;
}
void WatchEXP::Direct3DRelease(void)
{
m_AshitaCore->GetFontManager()->Delete("EXP_ID");
}
void WatchEXP::Direct3DRender(void)
{
doEXPCalculations();
doAbysseaZoneTimings();
doDynamisZoneTimings();
checkResetTime();
}
__declspec(dllexport) double __stdcall GetInterfaceVersion(void)
{
return ASHITA_INTERFACE_VERSION;
}
__declspec(dllexport) void __stdcall CreatePluginInfo(plugininfo_t* info)
{
g_PluginInformation = info;
strcpy_s(info->Author, sizeof(info->Author), "Praenuntiae (ported by Vicrelant)");
strcpy_s(info->Name, sizeof(info->Name), "WatchEXP");
info->InterfaceVersion = ASHITA_INTERFACE_VERSION;
info->PluginVersion = 3.0f;
info->Priority = 0;
}
__declspec(dllexport) IPlugin* __stdcall CreatePlugin(void)
{
return (IPlugin*)new WatchEXP();
}
#pragma region GetConfig
void WatchEXP::GetConfig()
{
auto iConfigResult = false;
auto iTemp = 0;
iConfigResult = m_AshitaCore->GetConfigurationManager()->Load("WatchEXP", "WatchEXP");
if (iConfigResult != 0)
{
auto szBuffer = m_AshitaCore->GetConfigurationManager()->get_string("WatchEXP", "font_name");
strcpy_s(font_name, szBuffer);
font_size = m_AshitaCore->GetConfigurationManager()->get_int32("WatchEXP", "font_size", 11);
show_XP_M_always = m_AshitaCore->GetConfigurationManager()->get_bool("WatchEXP", "show_both_xp_and_merits_when_capped", false);
m_reset_min = m_AshitaCore->GetConfigurationManager()->get_int32("WatchEXP", "auto_reset_time", 45);
m_autoreset = m_AshitaCore->GetConfigurationManager()->get_bool("WatchEXP", "auto_reset_enabled", false);
}
else if (iConfigResult == 0)
{
m_AshitaCore->GetConfigurationManager()->set_value("WatchEXP", "font_name", "Arial");
m_AshitaCore->GetConfigurationManager()->set_value("WatchEXP", "font_size", "11");
m_AshitaCore->GetConfigurationManager()->set_value("WatchEXP", "show_both_xp_and_merits_when_capped", "true");
m_AshitaCore->GetConfigurationManager()->set_value("WatchEXP", "auto_reset_time", "45");
m_AshitaCore->GetConfigurationManager()->set_value("WatchEXP", "auto_reset_enabled", "false");
m_AshitaCore->GetConfigurationManager()->Save("WatchEXP", "WatchEXP");
strcpy_s(font_name, "Arial");
font_size = 11;
show_XP_M_always = false;
m_reset_min = 45;
m_autoreset = false;
}
}
#pragma endregion
#pragma region doEXPCalculations
void WatchEXP::doEXPCalculations()
{
char *p;
char expIntoLVL[10] = "", expForLVL[10] = "", expTillLVL[10] = "", lmtIntoLVL[10] = "", lmtTillLVL[10] = "", xpTotal[40] = "", crTotal[40] = "";
m_IsInAbyssea = isInAbyssea(m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0));
m_IsInDynamis = isInDynamis(m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0));
// get the EXP info
unsigned short expIN = m_AshitaCore->GetDataManager()->GetPlayer()->GetExpCurrent();
unsigned short expMAX = m_AshitaCore->GetDataManager()->GetPlayer()->GetExpNeeded();
unsigned short expLEFT = expMAX - expIN;
// get the Merit info
unsigned short lmtIN = m_AshitaCore->GetDataManager()->GetPlayer()->GetLimitPoints();
unsigned short lmtMAX = 10000;
unsigned short lmtLEFT = lmtMAX - lmtIN;
p = expIntoLVL;
makeComma(expIN, p, 0);
_strrev(expIntoLVL);
p = expForLVL;
makeComma(expMAX, p, 0);
_strrev(expForLVL);
p = expTillLVL;
makeComma(expLEFT, p, 0);
_strrev(expTillLVL);
p = lmtIntoLVL;
makeComma(lmtIN, p, 0);
_strrev(lmtIntoLVL);
p = lmtTillLVL;
makeComma(lmtLEFT, p, 0);
_strrev(lmtTillLVL);
p = xpTotal;
makeComma(m_xpTotal, p, 0);
_strrev(xpTotal);
p = crTotal;
makeComma(m_crTotal, p, 0);
_strrev(crTotal);
if (m_AshitaCore->GetDataManager()->GetPlayer()->GetMainJobLevel() < 75)
{
if (m_IsInDynamis)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr Alb:%c Amb:%c Azr:%c Crm:%c Obn:%c Time Remaining: %d ", expIntoLVL, expForLVL, expTillLVL,
xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), m_Dyna_Alab, m_Dyna_Amb, m_Dyna_Azr, m_Dyna_Crm, m_Dyna_Obs, m_DynaTime);
}
else if (m_IsInAbyssea)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr Cruor:%s(%u) %.1fk/hr Prl:%u Gld:%u Slv:%u Ebn:%u Azr:%u Rby:%u Amb:%u V.Time: %d ",
expIntoLVL, expForLVL, expTillLVL, xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), crTotal, m_crKill, returnProjectedCRUORperHour(m_crTotal),
m_prl, m_gld, m_slv, m_ebn, m_azr, m_rby, m_amb, m_vTime);
}
else
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr ", expIntoLVL, expForLVL, expTillLVL,
xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal));
}
}
if ((!show_XP_M_always) && (m_AshitaCore->GetDataManager()->GetPlayer()->GetMainJobLevel() >= 75))
{
unsigned char isMeritMode = m_AshitaCore->GetDataManager()->GetPlayer()->GetLimitMode();
if ((expLEFT == 1) || (isMeritMode == 224))
{
if (m_IsInDynamis)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr Alb:%c Amb:%c Azr:%c Crm:%c Obn:%c Time Remaining: %d ", lmtIntoLVL, lmtTillLVL,
(int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), m_Dyna_Alab, m_Dyna_Amb, m_Dyna_Azr, m_Dyna_Crm,
m_Dyna_Obs, m_DynaTime);
}
else if (m_IsInAbyssea)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr Cruor:%s(%u) %.1fk/hr Prl:%u Gld:%u Slv:%u Ebn:%u Azr:%u Rby:%u Amb:%u V.Time: %d ", lmtIntoLVL, lmtTillLVL,
(int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), crTotal, m_crKill, returnProjectedCRUORperHour(m_crTotal),
m_prl, m_gld, m_slv, m_ebn, m_azr, m_rby, m_amb, m_vTime);
}
else
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr ",
lmtIntoLVL, lmtTillLVL, (int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal,
m_xpKill, returnProjectedEXPperHour(m_xpTotal));
}
}
else
{
if (m_IsInDynamis)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr Alb:%c Amb:%c Azr:%c Crm:%c Obn:%c Time Remaining: %d ", expIntoLVL, expForLVL, expTillLVL,
xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), m_Dyna_Alab, m_Dyna_Amb, m_Dyna_Azr, m_Dyna_Crm, m_Dyna_Obs, m_DynaTime);
}
else if (m_IsInAbyssea)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr Cruor:%s(%u) %.1fk/hr Prl:%u Gld:%u Slv:%u Ebn:%u Azr:%u Rby:%u Amb:%u V.Time: %d ",
expIntoLVL, expForLVL, expTillLVL, xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), crTotal, m_crKill, returnProjectedCRUORperHour(m_crTotal), m_prl,
m_gld, m_slv, m_ebn, m_azr, m_rby, m_amb, m_vTime);
}
else
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) XP:%s(%u) %.1fk/hr ", expIntoLVL, expForLVL, expTillLVL, xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal));
}
}
}
if ((show_XP_M_always) && (m_AshitaCore->GetDataManager()->GetPlayer()->GetMainJobLevel() >= 75))
{
if (m_IsInDynamis)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr Alb:%c Amb:%c Azr:%c Crm:%c Obn:%c Time Remaining: %d ", expIntoLVL, expForLVL, expTillLVL,
lmtIntoLVL, lmtTillLVL, (int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal), m_Dyna_Alab, m_Dyna_Amb,
m_Dyna_Azr, m_Dyna_Crm, m_Dyna_Obs, m_DynaTime);
}
else if (m_IsInAbyssea)
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr Cruor:%s(%u) %.1fk/hr Prl:%u Gld:%u Slv:%u Ebn:%u Azr:%u Rby:%u Amb:%u V.Time: %d ",
expIntoLVL, expForLVL, expTillLVL, lmtIntoLVL, lmtTillLVL, (int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal),
crTotal, m_crKill, returnProjectedCRUORperHour(m_crTotal), m_prl, m_gld, m_slv, m_ebn, m_azr, m_rby, m_amb, m_vTime);
}
else
{
sprintf_s(TextObjectBuffer, MAX_PATH, " %s/%s(%s) %s/10,000(%s)[%i] XP:%s(%u) %.1fk/hr ", expIntoLVL, expForLVL, expTillLVL,
lmtIntoLVL, lmtTillLVL, (int)m_AshitaCore->GetDataManager()->GetPlayer()->GetMeritPoints(), xpTotal, m_xpKill, returnProjectedEXPperHour(m_xpTotal));
}
}
// double check the size of the text
if (m_ExpObjSize.cy == 0)
{
int window_y = m_AshitaCore->GetConfigurationManager()->get_int32("boot_config", "window_y", 600);
m_ExpObj->GetTextSize(&m_ExpObjSize);
m_ExpObj->SetPositionX(15.0f);
m_ExpObj->SetPositionY((float)(window_y - m_ExpObjSize.cy));
}
// set the object information
m_ExpObj->SetText(TextObjectBuffer);
m_ExpObj->SetVisibility(true);
}
#pragma endregion
#pragma region returnProjectedEXPperHour
float WatchEXP::returnProjectedEXPperHour(unsigned int expIntoLevel)
{
float changeInTime = (float(time(nullptr) - m_BaseTimeEXP));
float changeInTimeHR = ((changeInTime / 60) / 60);
if (expIntoLevel == 0)
{
m_BaseTimeEXP = time(nullptr);
}
// just in case we don't do a divide by zero
if (changeInTime == 0.0f)
{
return 0;
}
return ((((float)expIntoLevel) / changeInTimeHR) / 1000);
}
#pragma endregion
#pragma region returnProjectedCRUORperHour
float WatchEXP::returnProjectedCRUORperHour(unsigned int cruorLVL)
{
float changeInTime = (float(time(nullptr) - m_BaseTimeCR));
float changeInTimeHR = ((changeInTime / 60) / 60);
if (cruorLVL == 0)
{
m_BaseTimeCR = time(nullptr);
}
// just in case we don't do a divide by zero
if (changeInTime == 0.0f)
{
return 0;
}
return ((((float)cruorLVL) / changeInTimeHR) / 1000);
}
#pragma endregion
#pragma region isInAbyssea
bool WatchEXP::isInAbyssea(int zoneID)
{
// look for it
for (auto& x : AbysseaZoneIDs)
{
// Yes!
if (x == zoneID)
return true;
}
m_prl = 0, m_gld = 0, m_amb = 0, m_slv = 0, m_azr = 0, m_ebn = 0, m_rby = 0, m_vTime = 0;
return false;
}
#pragma endregion
#pragma region isInDynamis
bool WatchEXP::isInDynamis(int zoneID)
{
// look for it
for (auto& x : DynamisZoneIDs)
{
// Yes!
if (x == zoneID)
return true;
}
m_Dyna_Crm = 'X', m_Dyna_Azr = 'X', m_Dyna_Alab = 'X', m_Dyna_Amb = 'X', m_Dyna_Obs = 'X';
// Nope
return false;
}
#pragma endregion
#pragma region doAbysseaZoneTimings
void WatchEXP::doAbysseaZoneTimings()
{
// check to see if we are in Abyssea
m_IsInAbyssea = isInAbyssea(m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0));
if (m_IsInAbyssea && (time(nullptr) - m_AbyTimeStart) > 60)
{
m_AbyTimeStart = time(nullptr);
if (m_vTime != 0)
{
m_vTime -= 1;
}
}
}
#pragma endregion
#pragma region doDynamisZoneTimings
void WatchEXP::doDynamisZoneTimings()
{
// check to see if we are in Abyssea
m_IsInDynamis = isInDynamis(m_AshitaCore->GetDataManager()->GetParty()->GetMemberZone(0));
doDynamisKItemCheck();
if (m_IsInDynamis && (time(nullptr) - m_DynTimeStart) > 60)
{
m_DynTimeStart = time(nullptr);
if (m_DynaTime != 0)
{
m_DynaTime -= 1;
}
}
}
#pragma endregion
#pragma region doDynamisKItemCheck
void WatchEXP::doDynamisKItemCheck()
{
//Checks for Crimson Granule of Time
if (m_AshitaCore->GetDataManager()->GetPlayer()->HasKeyItem(1545))
{
m_Dyna_Crm = 'O';
}
//Checks for Azure Granule of Time
if (m_AshitaCore->GetDataManager()->GetPlayer()->HasKeyItem(1546))
{
m_Dyna_Azr = 'O';
}
//Checks for Amber Granule of Time
if (m_AshitaCore->GetDataManager()->GetPlayer()->HasKeyItem(1547))
{
m_Dyna_Amb = 'O';
}
//Checks for Alabaster Granule of Time
if (m_AshitaCore->GetDataManager()->GetPlayer()->HasKeyItem(1548))
{
m_Dyna_Alab = 'O';
}
//Checks for Obsidian Granule of Time
if (m_AshitaCore->GetDataManager()->GetPlayer()->HasKeyItem(1549))
{
m_Dyna_Obs = 'O';
}
}
#pragma endregion
#pragma region makeComma
void WatchEXP::makeComma(int n, char *p, int count)
{
int d;
// Get least significant digit
d = n % 10;
// Convert to ascii character and store
*p++ = d + '0';
// Remove least significant digit
// Test for finished
if (n /= 10)
{
// Not finished, increase digit count,
// test for comma position
count++;
if (count >= 3)
{
// Add the comma and reset the count
*p++ = ',';
count = 0;
}
// Call this procedure to work on
// remaining part of number
makeComma(n, p, count);
}
return;
}
#pragma endregion
#pragma region convertFromHex
int WatchEXP::convertFromHex(std::string hex)
{
int value = 0;
int a = 0;
int b = hex.length() - 1;
for (; b >= 0; a++, b--)
{
if (hex[b] >= '0' && hex[b] <= '9')
{
value += (hex[b] - '0') * (1 << (a * 4));
}
else
{
switch (hex[b])
{
case 'A':
case 'a':
value += 10 * (1 << (a * 4));
break;
case 'B':
case 'b':
value += 11 * (1 << (a * 4));
break;
case 'C':
case 'c':
value += 12 * (1 << (a * 4));
break;
case 'D':
case 'd':
value += 13 * (1 << (a * 4));
break;
case 'E':
case 'e':
value += 14 * (1 << (a * 4));
break;
case 'F':
case 'f':
value += 15 * (1 << (a * 4));
break;
default:
break;
}
}
}
return value;
}
#pragma endregion
#pragma region hextodec
void WatchEXP::hextodec(std::string hex, std::vector<unsigned char>& rgb)
{
std::string redString, greenString, blueString;
if (hex.compare(0, 1, "#") == 0)
{
//If the prefix # was attached to hex, use the following code
redString = hex.substr(1, 2);
greenString = hex.substr(3, 2);
blueString = hex.substr(5, 2);
}
else if (hex.compare(0, 2, "0x") == 0)
{
//If the prefix 0x was attached to hex, use the following code
redString = hex.substr(2, 2);
greenString = hex.substr(4, 2);
blueString = hex.substr(6, 2);
}
else
{
//If there is no prefix attached to hex, use this code
redString = hex.substr(0, 2);
greenString = hex.substr(2, 2);
blueString = hex.substr(4, 2);
}
unsigned char red = (unsigned char)(convertFromHex(redString));
unsigned char green = (unsigned char)(convertFromHex(greenString));
unsigned char blue = (unsigned char)(convertFromHex(blueString));
rgb[0] = red;
rgb[1] = green;
rgb[2] = blue;
}
#pragma endregion
#pragma region convertTrans
void WatchEXP::convertTrans(unsigned char& trans)
{
float temp1, temp2;
temp1 = (float)trans;
temp2 = temp1 * (float)2.55;
if (temp2 > 255)
{
trans = (unsigned char)255;
}
else
{
trans = (unsigned char)temp2;
}
}
#pragma endregion
#pragma region checkResetTime
void WatchEXP::checkResetTime()
{
if (time(nullptr) - m_resetTime > 60)
{
if (m_xpTest != m_xpTotal)
{
m_xpTest = m_xpTotal;
m_resetTime = time(nullptr);
}
else if ((m_xpTest == m_xpTotal) && (m_autoreset))
{
if (((time(nullptr) - m_resetTime) / 60) >= m_reset_min)
{
m_resetTime = time(nullptr);
m_crTotal = 0, m_xpTotal = 0, m_xpKill = 0, m_crKill = 0;
}
}
}
}
#pragma endregion
#pragma region ScrubChat
std::string WatchEXP::ScrubChat(const char* chat_line)
{
//strings to hold the chat data through the various scrubbing stages
std::string chat_raw;
std::string clean_chat_pass1;
std::string clean_chat_pass2;
std::string clean_chat_pass3;
std::string clean_chat_final;
char szClean[1024];
//regex expressions for parsing the raw chat until it's clean
std::regex parse1("\\x1E\\x05|\\x1E(\\x03|\\x02|\\x01)|\\x7F\\x31|\\x1F(\\x79|\\x7F|\\x7B|\\W)");
std::regex parse2("[[:cntrl:]]|\\W\\W");
std::regex time_stamp("\\x1E\\x03((\\[\\d+(:|/)\\d+(:|/)\\d+(\\]| [AMP]+\\]))|\\[\\d+(:|/)\\d+(:|/)\\d+ - \\d+:\\d+:\\d+(\\]| [AMP]+\\]))\\x1E\\x01\\s+");
std::regex multi_space("\\s+");
memset(szClean, 0, 1024);
//Cleans up any auto translate data so it can be properly parsed
m_AshitaCore->GetChatManager()->ParseAutoTranslate(chat_line, szClean, 1024, false);
chat_raw = chat_line;
//Removes TimeStamp data from beginning of line
std::regex_replace(std::back_inserter(clean_chat_pass1), chat_raw.begin(), chat_raw.end(), time_stamp, "");
//Removes some control characters from the beginning and end of the string that print as garbage
std::regex_replace(std::back_inserter(clean_chat_pass2), clean_chat_pass1.begin(), clean_chat_pass1.end(), parse1, "");
//Removes any remaining control characters and replaces them with spaces
std::regex_replace(std::back_inserter(clean_chat_pass3), clean_chat_pass2.begin(), clean_chat_pass2.end(), parse2, " ");
//Changes any multi space areas to single spaces
std::regex_replace(std::back_inserter(clean_chat_final), clean_chat_pass3.begin(), clean_chat_pass3.end(), multi_space, " ");
return clean_chat_final;
}
#pragma endregion

85
WatchEXP/WatchEXP.h

@ -0,0 +1,85 @@
#ifndef __ASHITA_WATCHEXP_H_INCLUDED__
#define __ASHITA_WATCHEXP_H_INCLUDED__
#if defined (_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
#include "G:\Code\git.ashita.atom0s.com\Ashita v3\Ashita-src\build\plugins\ADK\Ashita.h"
#include <tuple>
#include <stdint.h>
#include <regex>
#include <time.h>
#include <string>
#include <sstream>
#include <vector>
plugininfo_t* g_PluginInformation = nullptr;
int AbysseaZoneIDs[] = { 15,45,132,215,216,217,218,253,254,255 };
int DynamisZoneIDs[] = { 39,40,41,42,134,135,185,186,187,188 };
class WatchEXP : IPlugin
{
WatchEXP(const WatchEXP & cpy);
WatchEXP & operator=(WatchEXP & rhs);
IAshitaCore* m_AshitaCore;
DWORD m_PluginId;
IDirect3DDevice8* m_Direct3DDevice;
public:
WatchEXP(void);
virtual ~WatchEXP(void);
public:
plugininfo_t GetPluginInfo(void) override;
private:
IFontObject* m_ExpObj;
char TextObjectBuffer[MAX_PATH];
time_t m_AbyTimeStart, m_DynTimeStart, m_BaseTimeEXP, m_BaseTimeCR, m_resetTime;
SIZE m_ExpObjSize;
int font_size, m_reset_min;
int m_CurrentZoneID, m_LastZoneRecorded;
char font_name[128];
char m_Dyna_Crm, m_Dyna_Azr, m_Dyna_Amb, m_Dyna_Alab, m_Dyna_Obs;
std::string hexColor;
unsigned int m_vTime;
unsigned int m_DynaTime;
unsigned int m_xpKill, m_xpTotal, m_xpTest;
unsigned int m_crKill, m_crTotal;
unsigned int m_prl, m_gld, m_slv, m_ebn, m_azr, m_rby, m_amb;
unsigned char backTrans;
bool m_IsInAbyssea, m_IsInDynamis, show_XP_M_always, m_autoreset;
public:
bool Initialize(IAshitaCore* core, ILogManager* log, uint32_t id) override;
void Release(void) override;
bool HandleCommand(const char* pszCommand, int nCommandType) override;
bool HandleIncomingText(int16_t mode, const char* message, int16_t* modifiedMode, char* modifiedMessage, bool blocked) override;
bool Direct3DInitialize(IDirect3DDevice8* lpDevice) override;
void Direct3DRelease(void) override;
void Direct3DRender(void) override;
void GetConfig(void);
float returnProjectedEXPperHour(unsigned int expIntoLevel);
float returnProjectedCRUORperHour(unsigned int expIntoLevel);
void doAbysseaZoneTimings();
void doDynamisZoneTimings();
void doDynamisKItemCheck();
void doEXPCalculations();
bool isInAbyssea(int zoneID);
bool isInDynamis(int zoneID);
void makeComma(int n, char *p, int count);
int convertFromHex(std::string hex);
void hextodec(std::string hex, std::vector<unsigned char>& rgb);
void convertTrans(unsigned char& trans);
void checkResetTime();
std::string ScrubChat(const char* chat_line);
};
#endif

111
WatchEXP/WatchEXP.vcxproj

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{25DAD057-C948-487D-A69C-6540DCD565DA}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WatchEXP</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Configuration)\Plugins\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WATCHEXP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<ExceptionHandling>Async</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>Full</Optimization>
<FunctionLevelLinking>false</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WATCHEXP_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<StringPooling>true</StringPooling>
<ExceptionHandling>Async</ExceptionHandling>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<PostBuildEvent>
<Command>
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CommandParse.h" />
<ClInclude Include="WatchEXP.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="WatchEXP.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

35
WatchEXP/WatchEXP.vcxproj.filters

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="WatchEXP.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CommandParse.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WatchEXP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="exports.def">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

5
WatchEXP/exports.def

@ -0,0 +1,5 @@
LIBRARY "WatchEXP"
EXPORTS
GetInterfaceVersion
CreatePluginInfo
CreatePlugin
Loading…
Cancel
Save