Implemented server side #who

This commit is contained in:
Akkadius 2019-01-21 00:29:58 -06:00
parent 7b2c87c7ed
commit 48564a5789
5 changed files with 728 additions and 479 deletions

View File

@ -3,8 +3,21 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50)
== 1/20/2019 ==
Uleat: Added 'spells' entry to EQDictionary
Akkadius: Implement and extended #goto via #goto <player_name> - this will work cross zone, cross instance, in zone etc.
It works on top of the original #goto (target) and #goto x y z
Akkadius:
- [Command] Extended #goto via #goto <player_name> -
- This will work cross zone, cross instance, in zone etc.
- It works on top of the original #goto (target) and #goto x y z
- [Command] Implemented server side #who Example: https://bit.ly/2TZ2hvI
- Searches can be filtered by
- Account Name
- Base Class Name
- Guild Name
- IP
- Player Name
- Race Name
- Zone Short Name
- Features a clickable (Goto) saylink that will bring you directly to a player regardless of
whether or not they are in an instance
== 1/15/2019 ==
Uleat: Activated per-expansion support for active inventory slot addressing

View File

@ -18,230 +18,332 @@
#include "../common/global_define.h"
#include "../common/classes.h"
const char* GetClassIDName(uint8 class_id, uint8 level)
const char *GetClassIDName(uint8 class_id, uint8 level)
{
switch (class_id) {
case WARRIOR:
if (level >= 70)
if (level >= 70) {
return "Vanquisher";
else if (level >= 65)
}
else if (level >= 65) {
return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE.
else if (level >= 60)
}
else if (level >= 60) {
return "Warlord";
else if (level >= 55)
}
else if (level >= 55) {
return "Myrmidon";
else if (level >= 51)
}
else if (level >= 51) {
return "Champion";
else
}
else {
return "Warrior";
}
case CLERIC:
if (level >= 70)
if (level >= 70) {
return "Prelate";
else if (level >= 65)
}
else if (level >= 65) {
return "Archon";
else if (level >= 60)
}
else if (level >= 60) {
return "High Priest";
else if (level >= 55)
}
else if (level >= 55) {
return "Templar";
else if (level >= 51)
}
else if (level >= 51) {
return "Vicar";
else
}
else {
return "Cleric";
}
case PALADIN:
if (level >= 70)
if (level >= 70) {
return "Lord";
else if (level >= 65)
}
else if (level >= 65) {
return "Lord Protector";
else if (level >= 60)
}
else if (level >= 60) {
return "Crusader";
else if (level >= 55)
}
else if (level >= 55) {
return "Knight";
else if (level >= 51)
}
else if (level >= 51) {
return "Cavalier";
else
}
else {
return "Paladin";
}
case RANGER:
if (level >= 70)
if (level >= 70) {
return "Plainswalker";
else if (level >= 65)
}
else if (level >= 65) {
return "Forest Stalker";
else if (level >= 60)
}
else if (level >= 60) {
return "Warder";
else if (level >= 55)
}
else if (level >= 55) {
return "Outrider";
else if (level >= 51)
}
else if (level >= 51) {
return "Pathfinder";
else
}
else {
return "Ranger";
}
case SHADOWKNIGHT:
if (level >= 70)
if (level >= 70) {
return "Scourge Knight";
else if (level >= 65)
}
else if (level >= 65) {
return "Dread Lord";
else if (level >= 60)
}
else if (level >= 60) {
return "Grave Lord";
else if (level >= 55)
}
else if (level >= 55) {
return "Revenant";
else if (level >= 51)
}
else if (level >= 51) {
return "Reaver";
else
}
else {
return "Shadowknight";
}
case DRUID:
if (level >= 70)
if (level >= 70) {
return "Natureguard";
else if (level >= 65)
}
else if (level >= 65) {
return "Storm Warden";
else if (level >= 60)
}
else if (level >= 60) {
return "Hierophant";
else if (level >= 55)
}
else if (level >= 55) {
return "Preserver";
else if (level >= 51)
}
else if (level >= 51) {
return "Wanderer";
else
}
else {
return "Druid";
}
case MONK:
if (level >= 70)
if (level >= 70) {
return "Stone Fist";
else if (level >= 65)
}
else if (level >= 65) {
return "Transcendent";
else if (level >= 60)
}
else if (level >= 60) {
return "Grandmaster";
else if (level >= 55)
}
else if (level >= 55) {
return "Master";
else if (level >= 51)
}
else if (level >= 51) {
return "Disciple";
else
}
else {
return "Monk";
}
case BARD:
if (level >= 70)
if (level >= 70) {
return "Performer";
else if (level >= 65)
}
else if (level >= 65) {
return "Maestro";
else if (level >= 60)
}
else if (level >= 60) {
return "Virtuoso";
else if (level >= 55)
}
else if (level >= 55) {
return "Troubadour";
else if (level >= 51)
}
else if (level >= 51) {
return "Minstrel";
else
}
else {
return "Bard";
}
case ROGUE:
if (level >= 70)
if (level >= 70) {
return "Nemesis";
else if (level >= 65)
}
else if (level >= 65) {
return "Deceiver";
else if (level >= 60)
}
else if (level >= 60) {
return "Assassin";
else if (level >= 55)
}
else if (level >= 55) {
return "Blackguard";
else if (level >= 51)
}
else if (level >= 51) {
return "Rake";
else
}
else {
return "Rogue";
}
case SHAMAN:
if (level >= 70)
if (level >= 70) {
return "Soothsayer";
else if (level >= 65)
}
else if (level >= 65) {
return "Prophet";
else if (level >= 60)
}
else if (level >= 60) {
return "Oracle";
else if (level >= 55)
}
else if (level >= 55) {
return "Luminary";
else if (level >= 51)
}
else if (level >= 51) {
return "Mystic";
else
}
else {
return "Shaman";
}
case NECROMANCER:
if (level >= 70)
if (level >= 70) {
return "Wraith";
else if (level >= 65)
}
else if (level >= 65) {
return "Arch Lich";
else if (level >= 60)
}
else if (level >= 60) {
return "Warlock";
else if (level >= 55)
}
else if (level >= 55) {
return "Defiler";
else if (level >= 51)
}
else if (level >= 51) {
return "Heretic";
else
}
else {
return "Necromancer";
}
case WIZARD:
if (level >= 70)
if (level >= 70) {
return "Grand Arcanist";
else if (level >= 65)
}
else if (level >= 65) {
return "Arcanist";
else if (level >= 60)
}
else if (level >= 60) {
return "Sorcerer";
else if (level >= 55)
}
else if (level >= 55) {
return "Evoker";
else if (level >= 51)
}
else if (level >= 51) {
return "Channeler";
else
}
else {
return "Wizard";
}
case MAGICIAN:
if (level >= 70)
if (level >= 70) {
return "Arch Magus";
else if (level >= 65)
}
else if (level >= 65) {
return "Arch Convoker";
else if (level >= 60)
}
else if (level >= 60) {
return "Arch Mage";
else if (level >= 55)
}
else if (level >= 55) {
return "Conjurer";
if (level >= 51)
}
if (level >= 51) {
return "Elementalist";
else
}
else {
return "Magician";
}
case ENCHANTER:
if (level >= 70)
if (level >= 70) {
return "Bedazzler";
else if (level >= 65)
}
else if (level >= 65) {
return "Coercer";
else if (level >= 60)
}
else if (level >= 60) {
return "Phantasmist";
else if (level >= 55)
}
else if (level >= 55) {
return "Beguiler";
else if (level >= 51)
}
else if (level >= 51) {
return "Illusionist";
else
}
else {
return "Enchanter";
}
case BEASTLORD:
if (level >= 70)
if (level >= 70) {
return "Wildblood";
else if (level >= 65)
}
else if (level >= 65) {
return "Feral Lord";
else if (level >= 60)
}
else if (level >= 60) {
return "Savage Lord";
else if (level >= 55)
}
else if (level >= 55) {
return "Animist";
else if (level >= 51)
}
else if (level >= 51) {
return "Primalist";
else
}
else {
return "Beastlord";
}
case BERSERKER:
if (level >= 70)
if (level >= 70) {
return "Ravager";
else if (level >= 65)
}
else if (level >= 65) {
return "Fury";
else if (level >= 60)
}
else if (level >= 60) {
return "Rager";
else if (level >= 55)
}
else if (level >= 55) {
return "Vehement";
else if (level >= 51)
}
else if (level >= 51) {
return "Brawler";
else
}
else {
return "Berserker";
}
case BANKER:
if (level >= 70)
if (level >= 70) {
return "Master Banker";
else if (level >= 65)
}
else if (level >= 65) {
return "Elder Banker";
else if (level >= 60)
}
else if (level >= 60) {
return "Oldest Banker";
else if (level >= 55)
}
else if (level >= 55) {
return "Older Banker";
else if (level >= 51)
}
else if (level >= 51) {
return "Old Banker";
else
}
else {
return "Banker";
}
case WARRIORGM:
return "Warrior Guildmaster";
case CLERICGM:
@ -291,7 +393,7 @@ const char* GetClassIDName(uint8 class_id, uint8 level)
}
}
const char* GetPlayerClassName(uint32 player_class_value, uint8 level)
const char *GetPlayerClassName(uint32 player_class_value, uint8 level)
{
return GetClassIDName(GetClassIDFromPlayerClassValue(player_class_value), level);
}

View File

@ -809,6 +809,16 @@ void Client::CompleteConnect()
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
}
/**
* Update last login since this doesn't get updated until a late save later so we can update online status
*/
database.QueryDatabase(
StringFormat(
"UPDATE `character_data` SET `last_login` = UNIX_TIMESTAMP() WHERE id = %u",
this->CharacterID()
)
);
}
if (zone) {

View File

@ -413,6 +413,7 @@ int command_init(void)
command_add("viewpetition", "[petition number] - View a petition", 20, command_viewpetition) ||
command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", 200, command_wc) ||
command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", 80, command_weather) ||
command_add("who", "[search]", 20, command_who) ||
command_add("worldshutdown", "- Shut down world and all zones", 200, command_worldshutdown) ||
command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) ||
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) ||
@ -2262,10 +2263,12 @@ void command_sendzonespawns(Client *c, const Seperator *sep)
void command_zsave(Client *c, const Seperator *sep)
{
if(zone->SaveZoneCFG())
if (zone->SaveZoneCFG()) {
c->Message(13, "Zone header saved successfully.");
else
}
else {
c->Message(13, "ERROR: Zone header data was NOT saved.");
}
}
void command_dbspawn2(Client *c, const Seperator *sep)
@ -11837,6 +11840,126 @@ void command_scale(Client *c, const Seperator *sep)
}
}
void command_who(Client *c, const Seperator *sep)
{
std::string query =
"SELECT\n"
" character_data.account_id,\n"
" character_data.name,\n"
" character_data.zone_id,\n"
" COALESCE((select zone.short_name from zone where zoneidnumber = character_data.zone_id LIMIT 1), \"Not Found\") as zone_name,\n"
" character_data.zone_instance,\n"
" COALESCE((select guilds.name from guilds where id = ((select guild_id from guild_members where char_id = character_data.id))), \"\") as guild_name,\n"
" character_data.level,\n"
" character_data.race,\n"
" character_data.class,\n"
" COALESCE((select account.status from account where account.id = character_data.account_id LIMIT 1), 0) as account_status,\n"
" COALESCE((select account.name from account where account.id = character_data.account_id LIMIT 1), \"\") as account_name,\n"
" COALESCE((select account_ip.ip from account_ip where account_ip.accid = character_data.account_id ORDER BY account_ip.lastused DESC LIMIT 1), \"\") as account_ip\n"
"FROM\n"
" character_data\n"
"WHERE\n"
" last_login > (UNIX_TIMESTAMP() - 600)\n"
"ORDER BY character_data.name;";
auto results = database.QueryDatabase(query);
if (!results.Success())
return;
if (results.RowCount() == 0) {
c->Message(15, "No results found");
return;
}
std::string search_string;
if (sep->arg[1]) {
search_string = str_tolower(sep->arg[1]);
}
int found_count = 0;
c->Message(5, "Players in EverQuest");
c->Message(5, "--------------------");
for (auto row = results.begin(); row != results.end(); ++row) {
auto account_id = static_cast<uint32>(atoi(row[0]));
std::string player_name = row[1];
auto zone_id = static_cast<uint32>(atoi(row[2]));
std::string zone_short_name = row[3];
auto zone_instance = static_cast<uint32>(atoi(row[4]));
std::string guild_name = row[5];
auto player_level = static_cast<uint32>(atoi(row[6]));
auto player_race = static_cast<uint32>(atoi(row[7]));
auto player_class = static_cast<uint32>(atoi(row[8]));
auto account_status = static_cast<uint32>(atoi(row[9]));
std::string account_name = row[10];
std::string account_ip = row[11];
std::string base_class_name = GetClassIDName(static_cast<uint8>(player_class), 1);
std::string displayed_race_name = GetRaceIDName(static_cast<uint16>(player_race));
if (search_string.length() > 0) {
bool found_search_term =
(
str_tolower(player_name).find(search_string) != std::string::npos ||
str_tolower(zone_short_name).find(search_string) != std::string::npos ||
str_tolower(displayed_race_name).find(search_string) != std::string::npos ||
str_tolower(base_class_name).find(search_string) != std::string::npos ||
str_tolower(guild_name).find(search_string) != std::string::npos ||
str_tolower(account_name).find(search_string) != std::string::npos ||
str_tolower(account_ip).find(search_string) != std::string::npos
);
if (!found_search_term) {
continue;
}
}
std::string displayed_guild_name;
if (guild_name.length() > 0) {
displayed_guild_name = EQEmu::SayLinkEngine::GenerateQuestSaylink(
StringFormat(
"#who \"%s\"",
guild_name.c_str()),
false,
StringFormat("<%s>", guild_name.c_str())
);
}
std::string goto_saylink = EQEmu::SayLinkEngine::GenerateQuestSaylink(
StringFormat("#goto %s", player_name.c_str()), false, "Goto"
);
std::string display_class_name = GetClassIDName(static_cast<uint8>(player_class), static_cast<uint8>(player_level));
c->Message(
5, "%s[%u %s] %s (%s) %s ZONE: %s (%u) (%s) (%s) (%s)",
(account_status > 0 ? "* GM * " : ""),
player_level,
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", base_class_name.c_str()), false, display_class_name).c_str(),
player_name.c_str(),
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", displayed_race_name.c_str()), false, displayed_race_name).c_str(),
displayed_guild_name.c_str(),
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", zone_short_name.c_str()), false, zone_short_name).c_str(),
zone_instance,
goto_saylink.c_str(),
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_name.c_str()), false, account_name).c_str(),
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_ip.c_str()), false, account_ip).c_str()
);
found_count++;
}
std::string message = (
found_count > 0 ?
StringFormat("There is %i player(s) in EverQuest", found_count).c_str() :
"There are no players in EverQuest that match those who filters."
);
c->Message(5, message.c_str());
}
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
#ifdef BOTS
#include "bot_command.h"

View File

@ -325,6 +325,7 @@ void command_viewnpctype(Client *c, const Seperator *sep);
void command_viewpetition(Client *c, const Seperator *sep);
void command_wc(Client *c, const Seperator *sep);
void command_weather(Client *c, const Seperator *sep);
void command_who(Client *c, const Seperator *sep);
void command_worldshutdown(Client *c, const Seperator *sep);
void command_wp(Client *c, const Seperator *sep);
void command_wpadd(Client *c, const Seperator *sep);