mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 06:21:28 +00:00
Merge remote-tracking branch 'remotes/origin/master' into blob_conversion
Conflicts: changelog.txt common/database.cpp world/client.cpp world/zoneserver.cpp zone/command.cpp
This commit is contained in:
commit
ad29fa9cfa
@ -1,6 +1,6 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 09/21/2014 ==
|
||||
== 09/21/2014 ==
|
||||
Akkadius: Player Profile Blob to Database Conversion
|
||||
- Summary: HUGE difference in database speeds reads/writes and 1:10 datasize difference
|
||||
- The new character storage engine unlike the character_ table before, is able to properly index data and make use of
|
||||
@ -94,6 +94,24 @@ Akkadius: Player Profile Blob to Database Conversion
|
||||
WHERE `table_name` LIKE 'character_%'
|
||||
ORDER BY DATA DESC;
|
||||
|
||||
== 09/20/2014 ==
|
||||
demonstar55: Fix crash in SendEnterWorld on illegally long names
|
||||
demonstar55: The client only lets you enter 15 characters for your name (UF at least)
|
||||
demonstar55: Add rule Spells:SHDProcIDOffByOne for pre-UF spell file, set to true, UF+ set to false
|
||||
KLS: #suspend and #ban now have required messages to record the reason for the ban/suspension.
|
||||
|
||||
== 09/19/2014 ==
|
||||
demonstar55: Added Client::Tell_StringID (used in tell queue messages)
|
||||
demonstar55: Tell queues (and offline) messages now show correctly
|
||||
demonstar55: Fix starting with capital check
|
||||
|
||||
== 09/18/2014==
|
||||
demonstar55: Implement tell queues
|
||||
Currently set to a limit of 20 by default (World:TellQueueSize) I was unable to hit the limit on live though (100+)
|
||||
The required SQL nukes the old tell queue table, which may or may not be in your DB
|
||||
Optional SQL adds the rule to the DB to allow easy of change
|
||||
Note: this does not play well with multiple sessions with the same name on (crash and relog and have multiple sessions) but normal tells don't play well either
|
||||
|
||||
== 09/16/2014 ==
|
||||
demonstar55: Implement spell formula 137 (BER AA Desperation)
|
||||
Uleat (NateDog): Fix for LoadBuffs() crash when a spell with a non-persistent Illusion effect was loaded.
|
||||
|
||||
@ -770,10 +770,20 @@ uint32 Database::GetCharacterID(const char *name) {
|
||||
the name "name" or zero if no character with that name was found
|
||||
Zero will also be returned if there is a database error.
|
||||
*/
|
||||
uint32 Database::GetAccountIDByChar(const char* charname) {
|
||||
uint32 accountId = 0;
|
||||
std::string query = StringFormat("SELECT `account_id`, `id` FROM `character_data` WHERE `name` = '%s' LIMIT 1", charname);
|
||||
auto results = QueryDatabase(query);
|
||||
uint32 Database::GetAccountIDByChar(const char* charname, uint32* oCharID) {
|
||||
std::string query = StringFormat("SELECT account_id, id FROM character_ WHERE name='%s'", EscapeString(charname).c_str());
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success())
|
||||
{
|
||||
std::cerr << "Error in GetAccountIDByChar query '" << query << "' " << results.ErrorMessage() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
if (row[0]){ accountId = atoi(row[0]); }
|
||||
return accountId;
|
||||
@ -2244,7 +2254,7 @@ bool Database::CheckNameFilter(const char* name, bool surname)
|
||||
else
|
||||
{
|
||||
// the minimum 4 is enforced by the client too
|
||||
if(!name || strlen(name) < 4 || strlen(name) > 64)
|
||||
if(!name || strlen(name) < 4 || strlen(name) > 15)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ MySQLRequestResult::MySQLRequestResult()
|
||||
MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, uint32 rowCount, uint32 columnCount, uint32 lastInsertedID, uint32 errorNumber, char *errorBuffer)
|
||||
: m_CurrentRow(result), m_OneBeyondRow()
|
||||
{
|
||||
m_Result = result;
|
||||
m_Result = result;
|
||||
m_RowsAffected = rowsAffected;
|
||||
m_RowCount = rowCount;
|
||||
m_ColumnCount = columnCount;
|
||||
@ -22,12 +22,12 @@ MySQLRequestResult::MySQLRequestResult(MYSQL_RES* result, uint32 rowsAffected, u
|
||||
m_ColumnLengths = nullptr;
|
||||
m_Fields = nullptr;
|
||||
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = true;
|
||||
if (errorBuffer != nullptr)
|
||||
m_Success = false;
|
||||
|
||||
m_Success = true;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
m_ErrorNumber = errorNumber;
|
||||
m_ErrorBuffer = errorBuffer;
|
||||
}
|
||||
|
||||
void MySQLRequestResult::FreeInternals()
|
||||
|
||||
@ -171,6 +171,7 @@ RULE_INT ( World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = R
|
||||
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
|
||||
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.
|
||||
RULE_BOOL (World, IPLimitDisconnectAll, false)
|
||||
RULE_INT (World, TellQueueSize, 20)
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY( Zone )
|
||||
@ -320,6 +321,7 @@ RULE_INT ( Spells, AI_PursueDetrimentalChance, 90) // Chance while chasing targe
|
||||
RULE_INT ( Spells, AI_IdleNoSpellMinRecast, 500) // AI spell recast time(MS) check when no spell is cast while idle. (min time in random)
|
||||
RULE_INT ( Spells, AI_IdleNoSpellMaxRecast, 2000) // AI spell recast time(MS) check when no spell is cast while chasing target. (max time in random)
|
||||
RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a beneficial spell on self or others.
|
||||
RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
|
||||
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
|
||||
@ -83,6 +83,7 @@
|
||||
#define ServerOP_QGlobalUpdate 0x0063
|
||||
#define ServerOP_QGlobalDelete 0x0064
|
||||
#define ServerOP_DepopPlayerCorpse 0x0065
|
||||
#define ServerOP_RequestTellQueue 0x0066 // client asks for it's tell queues
|
||||
|
||||
#define ServerOP_RaidAdd 0x0100 //in use
|
||||
#define ServerOP_RaidRemove 0x0101 //in use
|
||||
@ -348,6 +349,7 @@ struct ServerChannelMessage_Struct {
|
||||
uint16 chan_num;
|
||||
uint32 guilddbid;
|
||||
uint16 language;
|
||||
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
|
||||
char message[0];
|
||||
};
|
||||
|
||||
@ -1250,6 +1252,10 @@ struct ReloadWorld_Struct{
|
||||
uint32 Option;
|
||||
};
|
||||
|
||||
struct ServerRequestTellQueue_Struct {
|
||||
char name[64];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif
|
||||
|
||||
1
utils/sql/git/optional/2014_09_18_TellQueueRule.sql
Normal file
1
utils/sql/git/optional/2014_09_18_TellQueueRule.sql
Normal file
@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'World:TellQueueSize', '20', 'Maximum tell queue size.');
|
||||
1
utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql
Normal file
1
utils/sql/git/optional/2014_09_20_SHDProCIDOffByOne.sql
Normal file
@ -0,0 +1 @@
|
||||
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:SHDProcIDOffByOne', 'true', 'SHD procs are off by 1. Set true for pre-UF spell files, false for UF+.');
|
||||
1
utils/sql/git/required/2014_09_18_tellqueuesclean.sql
Normal file
1
utils/sql/git/required/2014_09_18_tellqueuesclean.sql
Normal file
@ -0,0 +1 @@
|
||||
DROP TABLE `tellque`;
|
||||
1
utils/sql/git/required/2014_09_20_ban_messages.sql
Normal file
1
utils/sql/git/required/2014_09_20_ban_messages.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `account` ADD COLUMN `ban_reason` TEXT NULL DEFAULT NULL AFTER `expansion`, ADD COLUMN `suspend_reason` TEXT NULL DEFAULT NULL AFTER `ban_reason`;
|
||||
@ -126,8 +126,9 @@ void Client::SendLogServer()
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::SendEnterWorld(std::string name) {
|
||||
char char_name[32]= { 0 };
|
||||
void Client::SendEnterWorld(std::string name)
|
||||
{
|
||||
char char_name[64] = { 0 };
|
||||
if (pZoning && database.GetLiveChar(GetAccountID(), char_name)) {
|
||||
if(database.GetAccountIDByChar(char_name) != GetAccountID()) {
|
||||
eqs->Close();
|
||||
@ -468,7 +469,8 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app)
|
||||
{
|
||||
if (GetAccountID() == 0) {
|
||||
clog(WORLD__CLIENT_ERR,"Name approval request with no logged in account");
|
||||
return false;
|
||||
@ -478,7 +480,7 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
uchar race = app->pBuffer[64];
|
||||
uchar clas = app->pBuffer[68];
|
||||
|
||||
clog(WORLD__CLIENT,"Name approval request. Name=%s, race=%s, class=%s",char_name,GetRaceName(race),GetEQClassName(clas));
|
||||
clog(WORLD__CLIENT, "Name approval request. Name=%s, race=%s, class=%s", char_name, GetRaceName(race), GetEQClassName(clas));
|
||||
|
||||
EQApplicationPacket *outapp;
|
||||
outapp = new EQApplicationPacket;
|
||||
@ -495,9 +497,8 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) {
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
if(!valid) {
|
||||
if (!valid)
|
||||
memset(char_name, 0, sizeof(char_name));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -93,6 +93,7 @@ ClientListEntry::~ClientListEntry() {
|
||||
Camp(); // updates zoneserver's numplayers
|
||||
client_list.RemoveCLEReferances(this);
|
||||
}
|
||||
tell_queue.clear();
|
||||
}
|
||||
|
||||
void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
|
||||
@ -233,6 +234,7 @@ void ClientListEntry::ClearVars(bool iAll) {
|
||||
pLFG = 0;
|
||||
gm = 0;
|
||||
pClientVersion = 0;
|
||||
tell_queue.clear();
|
||||
}
|
||||
|
||||
void ClientListEntry::Camp(ZoneServer* iZS) {
|
||||
@ -295,3 +297,21 @@ bool ClientListEntry::CheckAuth(uint32 id, const char* iKey, uint32 ip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientListEntry::ProcessTellQueue()
|
||||
{
|
||||
if (!Server())
|
||||
return;
|
||||
|
||||
ServerPacket *pack;
|
||||
auto it = tell_queue.begin();
|
||||
while (it != tell_queue.end()) {
|
||||
pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1);
|
||||
memcpy(pack->pBuffer, *it, pack->size);
|
||||
pack->Deflate();
|
||||
Server()->SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
it = tell_queue.erase(it);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include "../common/md5.h"
|
||||
//#include "../common/eq_packet_structs.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include <vector>
|
||||
|
||||
|
||||
#define CLE_Status_Never -1
|
||||
@ -80,6 +82,11 @@ public:
|
||||
inline const char* GetLFGComments() const { return pLFGComments; }
|
||||
inline uint8 GetClientVersion() { return pClientVersion; }
|
||||
|
||||
inline bool TellQueueFull() const { return tell_queue.size() >= RuleI(World, TellQueueSize); }
|
||||
inline bool TellQueueEmpty() const { return tell_queue.empty(); }
|
||||
inline void PushToTellQueue(ServerChannelMessage_Struct *scm) { tell_queue.push_back(scm); }
|
||||
void ProcessTellQueue();
|
||||
|
||||
private:
|
||||
void ClearVars(bool iAll = false);
|
||||
|
||||
@ -120,6 +127,9 @@ private:
|
||||
uint8 pLFGToLevel;
|
||||
bool pLFGMatchFilter;
|
||||
char pLFGComments[64];
|
||||
|
||||
// Tell Queue -- really a vector :D
|
||||
std::vector<ServerChannelMessage_Struct *> tell_queue;
|
||||
};
|
||||
|
||||
#endif /*CLIENTENTRY_H_*/
|
||||
|
||||
@ -437,45 +437,48 @@ bool ZoneServer::Process() {
|
||||
Console* con = 0;
|
||||
con = console_list.FindByAccountName(&scm->deliverto[1]);
|
||||
if (((!con) || (!con->SendChannelMessage(scm))) && (!scm->noreply))
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to);
|
||||
break;
|
||||
}
|
||||
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply)
|
||||
zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
}
|
||||
else if (cle->Online() == CLE_Status_Zoning) {
|
||||
if (!scm->noreply)
|
||||
{
|
||||
// time_t rawtime;
|
||||
// struct tm * timeinfo;
|
||||
// time ( &rawtime );
|
||||
// timeinfo = localtime ( &rawtime );
|
||||
// char *telldate=asctime(timeinfo);
|
||||
//
|
||||
// std::string query = StringFormat("SELECT name FROM `character_data` WHERE name = '%s'",scm->deliverto);
|
||||
// auto results = database.QueryDatabase(query);
|
||||
// if (!results.Success())
|
||||
// break;
|
||||
//
|
||||
// if (results.RowCount() == 0) {
|
||||
// zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// query = StringFormat("INSERT INTO tellque "
|
||||
// "(Date, Receiver, Sender, Message) "
|
||||
// "VALUES('%s', '%s', '%s', '%s')",
|
||||
// telldate, scm->deliverto, scm->from, scm->message);
|
||||
// results = database.QueryDatabase(query);
|
||||
// if (results.Success())
|
||||
// zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "Your message has been added to the %s's que.", scm->to);
|
||||
// else
|
||||
// zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
|
||||
if (cle == 0 || cle->Online() < CLE_Status_Zoning ||
|
||||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 3; // offline
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
// ideally this would be trimming off the message too, oh well
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
} else if (cle->Online() == CLE_Status_Zoning) {
|
||||
if (!scm->noreply) {
|
||||
ClientListEntry* sender = client_list.FindCharacter(scm->from);
|
||||
if (cle->TellQueueFull()) {
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 2; // queue full
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
sender->Server()->SendPacket(pack);
|
||||
} else {
|
||||
size_t struct_size = sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1;
|
||||
ServerChannelMessage_Struct *temp = (ServerChannelMessage_Struct *) new uchar[struct_size];
|
||||
memset(temp, 0, struct_size); // just in case, was seeing some corrupt messages, but it shouldn't happen
|
||||
memcpy(temp, scm, struct_size);
|
||||
temp->noreply = true;
|
||||
cle->PushToTellQueue(temp); // deallocation is handled in processing or deconstructor
|
||||
|
||||
if (!sender)
|
||||
break;
|
||||
scm->noreply = true;
|
||||
scm->queued = 1; // queued
|
||||
strcpy(scm->deliverto, scm->from);
|
||||
sender->Server()->SendPacket(pack);
|
||||
}
|
||||
}
|
||||
// zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "You told %s, '%s is not online at this time'", scm->to, scm->to);
|
||||
}
|
||||
else if (cle->Server() == 0) {
|
||||
if (!scm->noreply)
|
||||
@ -1285,6 +1288,16 @@ bool ZoneServer::Process() {
|
||||
zoneserver_list.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_RequestTellQueue:
|
||||
{
|
||||
ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer;
|
||||
ClientListEntry *cle = client_list.FindCharacter(rtq->name);
|
||||
if (!cle || cle->TellQueueEmpty())
|
||||
break;
|
||||
|
||||
cle->ProcessTellQueue();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
zlog(WORLD__ZONE_ERR,"Unknown ServerOPcode from zone 0x%04x, size %d",pack->opcode,pack->size);
|
||||
|
||||
@ -3077,6 +3077,14 @@ void Client::FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType fil
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
void Client::Tell_StringID(uint32 string_id, const char *who, const char *message)
|
||||
{
|
||||
char string_id_str[10];
|
||||
snprintf(string_id_str, 10, "%d", string_id);
|
||||
|
||||
Message_StringID(MT_TellEcho, TELL_QUEUED_MESSAGE, who, string_id_str, message);
|
||||
}
|
||||
|
||||
void Client::SetTint(int16 in_slot, uint32 color) {
|
||||
Color_Struct new_color;
|
||||
new_color.color = color;
|
||||
|
||||
@ -254,6 +254,7 @@ public:
|
||||
const char *message5 = nullptr, const char *message6 = nullptr,
|
||||
const char *message7 = nullptr, const char *message8 = nullptr,
|
||||
const char *message9 = nullptr);
|
||||
void Tell_StringID(uint32 string_id, const char *who, const char *message);
|
||||
void SendBazaarResults(uint32 trader_id,uint32 class_,uint32 race,uint32 stat,uint32 slot,uint32 type,char name[64],uint32 minprice,uint32 maxprice);
|
||||
void SendTraderItem(uint32 item_id,uint16 quantity);
|
||||
uint16 FindTraderItem(int32 SerialNumber,uint16 Quantity);
|
||||
|
||||
@ -9696,6 +9696,8 @@ void Client::CompleteConnect() {
|
||||
}
|
||||
|
||||
entity_list.RefreshClientXTargets(this);
|
||||
|
||||
worldserver.RequestTellQueue(GetName());
|
||||
}
|
||||
|
||||
void Client::Handle_OP_KeyRing(const EQApplicationPacket *app)
|
||||
|
||||
167
zone/command.cpp
167
zone/command.cpp
@ -331,8 +331,6 @@ int command_init(void) {
|
||||
command_add("guilds",nullptr,0,command_guild) ||
|
||||
command_add("zonestatus","- Show connected zoneservers, synonymous with /servers",150,command_zonestatus) ||
|
||||
command_add("manaburn","- Use AA Wizard class skill manaburn on target",10,command_manaburn) ||
|
||||
command_add("viewmessage","[id] - View messages in your tell queue",100,command_viewmessage) ||
|
||||
command_add("viewmessages",nullptr,0,command_viewmessage) ||
|
||||
command_add("doanim","[animnum] [type] - Send an EmoteAnim for you or your target",50,command_doanim) ||
|
||||
command_add("randomfeatures","- Temporarily randomizes the Facial Features of your target",80,command_randomfeatures) ||
|
||||
command_add("rf",nullptr,80,command_randomfeatures) ||
|
||||
@ -5191,53 +5189,6 @@ void command_manaburn(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_viewmessage(Client *c, const Seperator *sep)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
if(sep->arg[1][0]==0)
|
||||
{
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where receiver='%s'",c->GetName()), errbuf, &result))
|
||||
{
|
||||
if (mysql_num_rows(result)>0)
|
||||
{
|
||||
c->Message(0,"You have messages waiting for you to view.");
|
||||
c->Message(0,"Type #Viewmessage <Message ID> to view the message.");
|
||||
c->Message(0," ID , Message Sent Date, Message Sender");
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
c->Message(0,"ID: %s Sent Date: %s Sender: %s ",row[0],row[1],row[3]);
|
||||
}
|
||||
else
|
||||
c->Message(0,"You have no new messages");
|
||||
mysql_free_result(result);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (database.RunQuery(query, MakeAnyLenString(&query, "SELECT id,date,receiver,sender,message from tellque where id=%s",sep->argplus[1]), errbuf, &result))
|
||||
{
|
||||
if (mysql_num_rows(result)==1)
|
||||
{
|
||||
row = mysql_fetch_row(result);
|
||||
mysql_free_result(result);
|
||||
if (strcasecmp((const char *) c->GetName(), (const char *) row[2]) == 0)
|
||||
{
|
||||
c->Message(15,"ID: %s,Sent Date: %s,Sender: %s,Message: %s",row[0],row[1],row[3],row[4]);
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "Delete from tellque where id=%s",row[0]), errbuf);
|
||||
}
|
||||
else
|
||||
c->Message(13,"Invalid Message Number, check the number and try again.");
|
||||
}
|
||||
else
|
||||
c->Message(13,"Invalid Message Number, check the number and try again.");
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
}
|
||||
|
||||
void command_doanim(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!sep->IsNumber(1))
|
||||
@ -6204,36 +6155,49 @@ void command_stun(Client *c, const Seperator *sep)
|
||||
c->Message(0, "Usage: #stun [duration]");
|
||||
}
|
||||
|
||||
|
||||
void command_ban(Client *c, const Seperator *sep)
|
||||
{
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if(sep->arg[1][0] == 0)
|
||||
if(sep->arg[1][0] == 0 || sep->arg[2][0] == 0)
|
||||
{
|
||||
c->Message(0, "Usage: #ban [charname]");
|
||||
c->Message(0, "Usage: #ban <charname> <message>");
|
||||
}
|
||||
else
|
||||
{
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "SELECT account_id from `character_data` where name = '%s'", sep->arg[1]), errbuf, &result);
|
||||
if(query)
|
||||
{
|
||||
safe_delete_array(query);
|
||||
auto account_id = database.GetAccountIDByChar(sep->arg[1]);
|
||||
|
||||
std::string message;
|
||||
int i = 2;
|
||||
while(1) {
|
||||
if(sep->arg[i][0] == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(message.length() > 0) {
|
||||
message.push_back(' ');
|
||||
}
|
||||
|
||||
message += sep->arg[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
if(mysql_num_rows(result))
|
||||
{
|
||||
row = mysql_fetch_row(result);
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2 where id = %i", atoi(row[0])), errbuf, 0);
|
||||
c->Message(13,"Account number %i with the character %s has been banned.", atoi(row[0]), sep->arg[1]);
|
||||
if(message.length() == 0) {
|
||||
c->Message(0, "Usage: #ban <charname> <message>");
|
||||
return;
|
||||
}
|
||||
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_FlagUpdate, 6);
|
||||
*((uint32*) pack->pBuffer) = atoi(row[0]);
|
||||
*((int16*) &pack->pBuffer[4]) = -2;
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
if(account_id > 0)
|
||||
{
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE account set status = -2, ban_reason = '%s' where id = %i", EscapeString(message).c_str(), account_id), errbuf, 0);
|
||||
c->Message(13, "Account number %i with the character %s has been banned with message: \"%s\"", account_id, sep->arg[1], message.c_str());
|
||||
|
||||
ServerPacket pack(ServerOP_FlagUpdate, 6);
|
||||
*((uint32*)&pack.pBuffer[0]) = account_id;
|
||||
*((int16*)&pack.pBuffer[4]) = -2;
|
||||
worldserver.SendPacket(&pack);
|
||||
|
||||
Client *client = nullptr;
|
||||
client = entity_list.GetClientByName(sep->arg[1]);
|
||||
@ -6243,25 +6207,20 @@ void command_ban(Client *c, const Seperator *sep)
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
|
||||
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
|
||||
ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
|
||||
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack.pBuffer;
|
||||
strcpy(skp->adminname, c->GetName());
|
||||
strcpy(skp->name, sep->arg[1]);
|
||||
skp->adminrank = c->Admin();
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
worldserver.SendPacket(&pack);
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
c->Message(13,"Character does not exist.");
|
||||
}
|
||||
if(query)
|
||||
{
|
||||
safe_delete_array(query);
|
||||
c->Message(13, "Character does not exist.");
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6271,7 +6230,7 @@ void command_suspend(Client *c, const Seperator *sep)
|
||||
char *query = nullptr;
|
||||
|
||||
if((sep->arg[1][0] == 0) || (sep->arg[2][0] == 0))
|
||||
c->Message(0, "Usage: #suspend <charname> <days> (Specify 0 days to lift the suspension immediately)");
|
||||
c->Message(0, "Usage: #suspend <charname> <days>(Specify 0 days to lift the suspension immediately) <message>");
|
||||
else
|
||||
{
|
||||
int Duration = atoi(sep->arg[2]);
|
||||
@ -6279,22 +6238,40 @@ void command_suspend(Client *c, const Seperator *sep)
|
||||
if(Duration < 0)
|
||||
Duration = 0;
|
||||
|
||||
char *EscName = new char[strlen(sep->arg[1]) * 2 + 1];
|
||||
std::string message;
|
||||
if(Duration > 0) {
|
||||
int i = 3;
|
||||
while(1) {
|
||||
if(sep->arg[i][0] == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
database.DoEscapeString(EscName, sep->arg[1], strlen(sep->arg[1]));
|
||||
if(message.length() > 0) {
|
||||
message.push_back(' ');
|
||||
}
|
||||
|
||||
message += sep->arg[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
if(message.length() == 0) {
|
||||
c->Message(0, "Usage: #suspend <charname> <days>(Specify 0 days to lift the suspension immediately) <message>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int AccountID;
|
||||
|
||||
if((AccountID = database.GetAccountIDByChar(EscName)) > 0)
|
||||
if((AccountID = database.GetAccountIDByChar(sep->arg[1])) > 0)
|
||||
{
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY)"
|
||||
" WHERE `id` = %i", Duration, AccountID), errbuf, 0);
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "UPDATE `account` SET `suspendeduntil` = DATE_ADD(NOW(), INTERVAL %i DAY), "
|
||||
"suspend_reason = '%s' WHERE `id` = %i", Duration, EscapeString(message).c_str(), AccountID), errbuf, 0);
|
||||
|
||||
if(Duration)
|
||||
c->Message(13,"Account number %i with the character %s has been temporarily suspended for %i day(s).", AccountID, sep->arg[1],
|
||||
Duration);
|
||||
c->Message(13, "Account number %i with the character %s has been temporarily suspended for %i day(s) with the message: \"%s\"", AccountID, sep->arg[1],
|
||||
Duration, message.c_str());
|
||||
else
|
||||
c->Message(13,"Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]);
|
||||
c->Message(13, "Account number %i with the character %s is no longer suspended.", AccountID, sep->arg[1]);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
@ -6304,22 +6281,20 @@ void command_suspend(Client *c, const Seperator *sep)
|
||||
BannedClient->WorldKick();
|
||||
else
|
||||
{
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
|
||||
ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*) pack->pBuffer;
|
||||
ServerPacket pack(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
|
||||
ServerKickPlayer_Struct* sks = (ServerKickPlayer_Struct*)pack.pBuffer;
|
||||
|
||||
strn0cpy(sks->adminname, c->GetName(), sizeof(sks->adminname));
|
||||
strn0cpy(sks->name, sep->arg[1], sizeof(sks->name));
|
||||
sks->adminrank = c->Admin();
|
||||
|
||||
worldserver.SendPacket(pack);
|
||||
|
||||
safe_delete(pack);
|
||||
worldserver.SendPacket(&pack);
|
||||
}
|
||||
|
||||
} else
|
||||
c->Message(13,"Character does not exist.");
|
||||
|
||||
safe_delete_array(EscName);
|
||||
}
|
||||
else {
|
||||
c->Message(13, "Character does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -215,7 +215,6 @@ void command_guild(Client *c, const Seperator *sep);
|
||||
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
|
||||
void command_zonestatus(Client *c, const Seperator *sep);
|
||||
void command_manaburn(Client *c, const Seperator *sep);
|
||||
void command_viewmessage(Client *c, const Seperator *sep);
|
||||
void command_doanim(Client *c, const Seperator *sep);
|
||||
void command_randomfeatures(Client *c, const Seperator *sep);
|
||||
void command_face(Client *c, const Seperator *sep);
|
||||
|
||||
@ -5598,28 +5598,29 @@ void Mob::CheckNumHitsRemaining(uint8 type, uint32 buff_slot, uint16 spell_id)
|
||||
}
|
||||
|
||||
//for some stupid reason SK procs return theirs one base off...
|
||||
uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index) {
|
||||
uint16 Mob::GetProcID(uint16 spell_id, uint8 effect_index)
|
||||
{
|
||||
if (!RuleB(Spells, SHDProcIDOffByOne)) // UF+ spell files
|
||||
return spells[spell_id].base[effect_index];
|
||||
|
||||
// We should actually just be checking if the mob is SHD, but to not force
|
||||
// custom servers to create new spells, we will still do this
|
||||
bool sk = false;
|
||||
bool other = false;
|
||||
for(int x = 0; x < 16; x++)
|
||||
{
|
||||
if(x == 4){
|
||||
if(spells[spell_id].classes[4] < 255)
|
||||
for (int x = 0; x < 16; x++) {
|
||||
if (x == 4) {
|
||||
if (spells[spell_id].classes[4] < 255)
|
||||
sk = true;
|
||||
}
|
||||
else{
|
||||
if(spells[spell_id].classes[x] < 255)
|
||||
} else {
|
||||
if (spells[spell_id].classes[x] < 255)
|
||||
other = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(sk && !other)
|
||||
{
|
||||
return(spells[spell_id].base[effect_index] + 1);
|
||||
}
|
||||
else{
|
||||
return(spells[spell_id].base[effect_index]);
|
||||
}
|
||||
if (sk && !other)
|
||||
return spells[spell_id].base[effect_index] + 1;
|
||||
else
|
||||
return spells[spell_id].base[effect_index];
|
||||
}
|
||||
|
||||
bool Mob::TryDivineSave()
|
||||
|
||||
@ -249,6 +249,8 @@
|
||||
#define PLAYER_CHARMED 1461 //You lose control of yourself!
|
||||
#define TRADER_BUSY 1468 //That Trader is currently with a customer. Please wait until their transaction is finished.
|
||||
#define SENSE_CORPSE_DIRECTION 1563 //You sense a corpse in this direction.
|
||||
#define QUEUED_TELL 2458 //[queued]
|
||||
#define QUEUE_TELL_FULL 2459 //[zoing and queue is full]
|
||||
#define SUSPEND_MINION_UNSUSPEND 3267 //%1 tells you, 'I live again...'
|
||||
#define SUSPEND_MINION_SUSPEND 3268 //%1 tells you, 'By your command, master.'
|
||||
#define ONLY_SUMMONED_PETS 3269 //3269 This effect only works with summoned pets.
|
||||
@ -269,6 +271,8 @@
|
||||
#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse.
|
||||
#define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away.
|
||||
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
|
||||
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
|
||||
#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time.
|
||||
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
|
||||
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
|
||||
#define GAIN_RAIDEXP 5085 //You gained raid experience!
|
||||
|
||||
@ -168,18 +168,24 @@ void WorldServer::Process() {
|
||||
break;
|
||||
}
|
||||
case ServerOP_ChannelMessage: {
|
||||
if (!ZoneLoaded) break;
|
||||
if (!ZoneLoaded)
|
||||
break;
|
||||
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*) pack->pBuffer;
|
||||
if (scm->deliverto[0] == 0) {
|
||||
entity_list.ChannelMessageFromWorld(scm->from, scm->to, scm->chan_num, scm->guilddbid, scm->language, scm->message);
|
||||
}
|
||||
else {
|
||||
Client* client;
|
||||
client = entity_list.GetClientByName(scm->deliverto);
|
||||
if (client != 0) {
|
||||
} else {
|
||||
Client* client = entity_list.GetClientByName(scm->deliverto);
|
||||
if (client) {
|
||||
if (client->Connected()) {
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message);
|
||||
if (!scm->noreply && scm->chan_num!=2) { //dont echo on group chat
|
||||
if (scm->queued == 1) // tell was queued
|
||||
client->Tell_StringID(QUEUED_TELL, scm->to, scm->message);
|
||||
else if (scm->queued == 2) // tell queue was full
|
||||
client->Tell_StringID(QUEUE_TELL_FULL, scm->to, scm->message);
|
||||
else if (scm->queued == 3) // person was offline
|
||||
client->Message_StringID(MT_TellEcho, TOLD_NOT_ONLINE, scm->to);
|
||||
else // normal stuff
|
||||
client->ChannelMessageSend(scm->from, scm->to, scm->chan_num, scm->language, scm->message);
|
||||
if (!scm->noreply && scm->chan_num != 2) { //dont echo on group chat
|
||||
// if it's a tell, echo back so it shows up
|
||||
scm->noreply = true;
|
||||
scm->chan_num = 14;
|
||||
@ -1874,6 +1880,7 @@ bool WorldServer::SendChannelMessage(Client* from, const char* to, uint8 chan_nu
|
||||
scm->chan_num = chan_num;
|
||||
scm->guilddbid = guilddbid;
|
||||
scm->language = language;
|
||||
scm->queued = 0;
|
||||
strcpy(scm->message, buffer);
|
||||
|
||||
pack->Deflate();
|
||||
@ -2198,3 +2205,19 @@ void WorldServer::HandleLFPMatches(ServerPacket *pack) {
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldServer::RequestTellQueue(const char *who)
|
||||
{
|
||||
if (!who)
|
||||
return;
|
||||
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_RequestTellQueue, sizeof(ServerRequestTellQueue_Struct));
|
||||
ServerRequestTellQueue_Struct* rtq = (ServerRequestTellQueue_Struct*) pack->pBuffer;
|
||||
|
||||
strn0cpy(rtq->name, who, sizeof(rtq->name));
|
||||
|
||||
SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -57,6 +57,8 @@ public:
|
||||
void HandleLFGMatches(ServerPacket *pack);
|
||||
void HandleLFPMatches(ServerPacket *pack);
|
||||
|
||||
void RequestTellQueue(const char *who);
|
||||
|
||||
private:
|
||||
virtual void OnConnected();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user