mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server into shutdown_crash
Conflicts: changelog.txt
This commit is contained in:
commit
6a4f7466f0
@ -3,6 +3,51 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
== 08/24/2014 ==
|
||||
Uleat: Fix (attempted) for zone crashes related to zone shut-down. This change disables all Mob AI and disables/deletes all Mob timers once Zone::ShutDown() is called. More areas will be addressed as reports come in.
|
||||
Note: Perl and Lua quests tested to work..please post any aberrant behavior. (I finally set my spell-check to US English...)
|
||||
Akkadius: Character creation process crash fix and query cleanup
|
||||
Akkadius: Created `character_lookup` table for applications that mirrors all `character_` table fields minus blob fields for application lookups
|
||||
- A 2.4GB character_ table will take 7 seconds to query on a SSD versus .1s on the character_lookup table
|
||||
- This also causes applications like Magelo to burst reads of the entire character table because of the blob fields that come with the reads, as much as 500-600MB/s even if a indexed id filter is provided
|
||||
- This field is synchronized on player save and has 0.001s DB hit
|
||||
- When we split out from the blob, ideally this table can be removed
|
||||
- Required SQL: utils\sql\git\required\2014_08_24_character_lookup.sql
|
||||
|
||||
== 08/23/2014 ==
|
||||
Akkadius: Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
|
||||
Akkadius: Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
|
||||
intensive or metric based logging to a remote server process that could exist on another server entirely
|
||||
Akkadius: Implemented Player Event Logging Types (Go to table `qs_player_events`):
|
||||
1 = Player_Log_Quest,
|
||||
2 = Player_Log_Zoning,
|
||||
3 = Player_Log_Deaths,
|
||||
4 = Player_Log_Connect_State,
|
||||
5 = Player_Log_Levels,
|
||||
6 = Player_Log_Keyring_Addition,
|
||||
7 = Player_Log_QGlobal_Update,
|
||||
8 = Player_Log_Task_Updates,
|
||||
9 = Player_Log_AA_Purchases,
|
||||
10 = Player_Log_Trade_Skill_Events,
|
||||
11 = Player_Log_Issued_Commands,
|
||||
12 = Player_Log_Money_Transactions,
|
||||
13 = Player_Log_Alternate_Currency_Transactions,
|
||||
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
|
||||
- Architecture page: http://wiki.eqemulator.org/p?QueryServ_Architecture
|
||||
Akkadius: Changed all QS Error related logging to 'QUERYSERV__ERROR'
|
||||
Akkadius: (Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
|
||||
Akkadius: Implemented Perl Quest objects (LUA still needed to be exported):
|
||||
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
|
||||
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
|
||||
Akkadius: Added MySQL Tables
|
||||
- `qs_player_aa_rate_hourly`
|
||||
- `qs_player_events`
|
||||
- Source table structures from:
|
||||
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
|
||||
To get the complete QueryServ schema, source from here:
|
||||
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
|
||||
Akkadius: Added rules for each logging type, source rules here with them enabled by default:
|
||||
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
|
||||
Akkadius: Spawn related logging cleanup
|
||||
Akkadius: General code cleanup
|
||||
Akkadius: More to come for QueryServ
|
||||
|
||||
== 08/20/2014 ==
|
||||
Uleat: Rework of Trade::AddEntity() - function used to move items into the trade window. Now accepts argument for 'stack_size' and updates client properly.
|
||||
|
||||
@ -608,10 +608,11 @@ bool Database::StoreCharacter(uint32 account_id, PlayerProfile_Struct* pp, Inven
|
||||
for (int16 i=EmuConstants::EQUIPMENT_BEGIN; i<=EmuConstants::BANK_BAGS_END;)
|
||||
{
|
||||
const ItemInst* newinv = inv->GetItem(i);
|
||||
if (!newinv)
|
||||
if (newinv)
|
||||
{
|
||||
invquery = StringFormat("INSERT INTO inventory SET charid=%0u, slotid=%0d, itemid=%0u, charges=%0d, color=%0u",
|
||||
invquery = StringFormat("INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)",
|
||||
charid, i, newinv->GetItem()->ID, newinv->GetCharges(), newinv->GetColor());
|
||||
|
||||
auto results = QueryDatabase(invquery);
|
||||
|
||||
if (!results.RowsAffected())
|
||||
|
||||
@ -108,6 +108,7 @@ LOG_CATEGORY( FACTION )
|
||||
|
||||
LOG_CATEGORY( ZONE )
|
||||
LOG_TYPE( ZONE, GROUND_SPAWNS, DISABLED )
|
||||
LOG_TYPE( ZONE, SPAWNS, ENABLED)
|
||||
LOG_TYPE( ZONE, INIT, ENABLED )
|
||||
LOG_TYPE( ZONE, INIT_ERR, ENABLED )
|
||||
LOG_TYPE( ZONE, WORLD, ENABLED )
|
||||
|
||||
@ -558,14 +558,28 @@ RULE_INT ( Console, SessionTimeOut, 600000 ) // Amount of time in ms for the con
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY( QueryServ )
|
||||
RULE_BOOL( QueryServ, PlayerChatLogging, false) // Logs Player Chat
|
||||
RULE_BOOL( QueryServ, PlayerLogChat, false) // Logs Player Chat
|
||||
RULE_BOOL( QueryServ, PlayerLogTrades, false) // Logs Player Trades
|
||||
RULE_BOOL( QueryServ, PlayerLogHandins, false) // Logs Player Handins
|
||||
RULE_BOOL( QueryServ, PlayerLogNPCKills, false) // Logs Player NPC Kills
|
||||
RULE_BOOL( QueryServ, PlayerLogDeletes, false) // Logs Player Deletes
|
||||
RULE_BOOL( QueryServ, PlayerLogMoves, false) // Logs Player Moves
|
||||
RULE_BOOL( QueryServ, MerchantLogTransactions, false) // Logs Merchant Transactions
|
||||
RULE_BOOL( QueryServ, PlayerLogMerchantTransactions, false) // Logs Merchant Transactions
|
||||
RULE_BOOL( QueryServ, PlayerLogPCCoordinates, false) // Logs Player Coordinates with certain events
|
||||
RULE_BOOL( QueryServ, PlayerLogDropItem, false) // Logs Player Drop Item
|
||||
RULE_BOOL( QueryServ, PlayerLogZone, false) // Logs Player Zone Events
|
||||
RULE_BOOL( QueryServ, PlayerLogDeaths, false) // Logs Player Deaths
|
||||
RULE_BOOL( QueryServ, PlayerLogConnectDisconnect, false) // Logs Player Connect Disconnect State
|
||||
RULE_BOOL( QueryServ, PlayerLogLevels, false) // Logs Player Leveling/Deleveling
|
||||
RULE_BOOL( QueryServ, PlayerLogAARate, false) // Logs Player AA Experience Rates
|
||||
RULE_BOOL( QueryServ, PlayerLogQGlobalUpdate, false) // Logs Player QGlobal Updates
|
||||
RULE_BOOL( QueryServ, PlayerLogTaskUpdates, false) // Logs Player Task Updates
|
||||
RULE_BOOL( QueryServ, PlayerLogKeyringAddition, false) // Log PLayer Keyring additions
|
||||
RULE_BOOL( QueryServ, PlayerLogAAPurchases, false) // Log Player AA Purchases
|
||||
RULE_BOOL( QueryServ, PlayerLogTradeSkillEvents, false) // Log Player Tradeskill Transactions
|
||||
RULE_BOOL( QueryServ, PlayerLogIssuedCommandes, false ) // Log Player Issued Commands
|
||||
RULE_BOOL( QueryServ, PlayerLogMoneyTransactions, false) // Log Player Money Transaction/Splits
|
||||
RULE_BOOL( QueryServ, PlayerLogAlternateCurrencyTransactions, false) // Log Ploayer Alternate Currency Transactions
|
||||
RULE_CATEGORY_END()
|
||||
|
||||
RULE_CATEGORY( Inventory )
|
||||
|
||||
@ -184,8 +184,10 @@
|
||||
#define ServerOP_QSPlayerLogNPCKills 0x4012
|
||||
#define ServerOP_QSPlayerLogDeletes 0x4013
|
||||
#define ServerOP_QSPlayerLogMoves 0x4014
|
||||
#define ServerOP_QSMerchantLogTransactions 0x4015
|
||||
#define ServerOP_QSPlayerLogMerchantTransactions 0x4015
|
||||
#define ServerOP_QSSendQuery 0x4016
|
||||
|
||||
/* Query Serv Generic Packet Flag/Type Enumeration */
|
||||
enum { QSG_LFGuild = 0 };
|
||||
enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_RequestPlayerInfo, QSG_LFGuild_UpdateGuildInfo, QSG_LFGuild_GuildMatches,
|
||||
QSG_LFGuild_RequestGuildInfo };
|
||||
@ -1219,6 +1221,10 @@ struct QSMerchantLogTransaction_Struct {
|
||||
QSTransactionItems_Struct items[0];
|
||||
};
|
||||
|
||||
struct QSGeneralQuery_Struct {
|
||||
char QueryString[0];
|
||||
};
|
||||
|
||||
struct CZMessagePlayer_Struct {
|
||||
uint32 Type;
|
||||
char CharName[64];
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
// Disgrace: for windows compile
|
||||
#ifdef _WINDOWS
|
||||
@ -96,41 +97,6 @@ Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
bool Database::GetVariable(const char* varname, char* varvalue, uint16 varvalue_len) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!RunQuery(query,MakeAnyLenString(&query, "select `value` from `variables` where `varname`='%s'", varname), errbuf, &result)) {
|
||||
|
||||
_log(UCS__ERROR, "Unable to get message count from database. %s %s", query, errbuf);
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
|
||||
if (mysql_num_rows(result) != 1) {
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(result);
|
||||
|
||||
snprintf(varvalue, varvalue_len, "%s", row[0]);
|
||||
|
||||
mysql_free_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Database::AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
@ -143,8 +109,8 @@ void Database::AddSpeech(const char* from, const char* to, const char* message,
|
||||
DoEscapeString(S3, message, strlen(message));
|
||||
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_speech` SET `from`='%s', `to`='%s', `message`='%s', `minstatus`='%i', `guilddbid`='%i', `type`='%i'", S1, S2, S3, minstatus, guilddbid, type), errbuf, 0, 0)) {
|
||||
_log(NET__WORLD, "Failed Speech Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Speech Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
safe_delete_array(query);
|
||||
@ -164,8 +130,8 @@ void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 Items) {
|
||||
QS->char1_id, QS->char1_money.platinum, QS->char1_money.gold, QS->char1_money.silver, QS->char1_money.copper, QS->char1_count,
|
||||
QS->char2_id, QS->char2_money.platinum, QS->char2_money.gold, QS->char2_money.silver, QS->char2_money.copper, QS->char2_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed Trade Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
@ -176,15 +142,14 @@ void Database::LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 Items) {
|
||||
lastid, QS->items[i].from_id, QS->items[i].from_slot, QS->items[i].to_id, QS->items[i].to_slot, QS->items[i].item_id,
|
||||
QS->items[i].charges, QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed Trade Log Record Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Trade Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 Items) {
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
@ -194,8 +159,8 @@ void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 Items) {
|
||||
QS->quest_id, QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count,
|
||||
QS->npc_id, QS->npc_money.platinum, QS->npc_money.gold, QS->npc_money.silver, QS->npc_money.copper, QS->npc_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed Handin Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
@ -206,8 +171,8 @@ void Database::LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 Items) {
|
||||
lastid, QS->items[i].action_type, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed Handin Log Record Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Handin Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,15 +183,15 @@ void Database::LogPlayerNPCKill(QSPlayerLogNPCKill_Struct* QS, uint32 Members){
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record` SET `npc_id`='%i', `type`='%i', `zone_id`='%i', `time`=NOW()", QS->s1.NPCID, QS->s1.Type, QS->s1.ZoneID), errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed NPC Kill Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Members > 0){
|
||||
for (int i = 0; i < Members; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_npc_kill_record_entries` SET `event_id`='%i', `char_id`='%i'", lastid, QS->Chars[i].char_id, errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed NPC Kill Log Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed NPC Kill Log Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -241,8 +206,8 @@ void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) {
|
||||
"`char_id`='%i', `stack_size`='%i', `char_items`='%i'",
|
||||
QS->char_id, QS->stack_size, QS->char_count, QS->char_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed Delete Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
@ -253,15 +218,15 @@ void Database::LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items) {
|
||||
lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed Delete Log Record Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) {
|
||||
|
||||
/* These are item moves */
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
@ -269,10 +234,9 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) {
|
||||
"`char_id`='%i', `from_slot`='%i', `to_slot`='%i', `stack_size`='%i', `char_items`='%i', `postaction`='%i'",
|
||||
QS->char_id, QS->from_slot, QS->to_slot, QS->stack_size, QS->char_count, QS->postaction),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed Move Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
for(int i = 0; i < Items; i++) {
|
||||
if(!RunQuery(query, MakeAnyLenString(&query, "INSERT INTO `qs_player_move_record_entries` SET `event_id`='%i', "
|
||||
@ -281,16 +245,15 @@ void Database::LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items) {
|
||||
QS->items[i].from_slot, QS->items[i].to_slot, QS->items[i].item_id, QS->items[i].charges,
|
||||
QS->items[i].aug_1, QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed Move Log Record Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Move Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items) {
|
||||
// Merchant transactions are from the perspective of the merchant, not the player -U
|
||||
|
||||
/* Merchant transactions are from the perspective of the merchant, not the player -U */
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
@ -300,8 +263,8 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3
|
||||
QS->zone_id, QS->merchant_id, QS->merchant_money.platinum, QS->merchant_money.gold, QS->merchant_money.silver, QS->merchant_money.copper, QS->merchant_count,
|
||||
QS->char_id, QS->char_money.platinum, QS->char_money.gold, QS->char_money.silver, QS->char_money.copper, QS->char_count),
|
||||
errbuf, 0, 0, &lastid)) {
|
||||
_log(NET__WORLD, "Failed Transaction Log Record Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
|
||||
if(Items > 0) {
|
||||
@ -312,10 +275,29 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3
|
||||
lastid, QS->items[i].char_slot, QS->items[i].item_id, QS->items[i].charges, QS->items[i].aug_1,
|
||||
QS->items[i].aug_2, QS->items[i].aug_3, QS->items[i].aug_4, QS->items[i].aug_5,
|
||||
errbuf, 0, 0))) {
|
||||
_log(NET__WORLD, "Failed Transaction Log Record Entry Insert: %s", errbuf);
|
||||
_log(NET__WORLD, "%s", query);
|
||||
_log(QUERYSERV__ERROR, "Failed Transaction Log Record Entry Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
}
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
|
||||
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||
/*
|
||||
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
|
||||
*/
|
||||
char *Query = nullptr;
|
||||
Query = new char[pack->ReadUInt32() + 1];
|
||||
pack->ReadString(Query);
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
uint32 lastid = 0;
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, Query), errbuf, 0, 0, &lastid)) {
|
||||
_log(QUERYSERV__ERROR, "Failed Delete Log Record Insert: %s", errbuf);
|
||||
_log(QUERYSERV__ERROR, "%s", query);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
safe_delete(pack);
|
||||
safe_delete(Query);
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ public:
|
||||
bool Connect(const char* host, const char* user, const char* passwd, const char* database,uint32 port);
|
||||
~Database();
|
||||
|
||||
bool GetVariable(const char* varname, char* varvalue, uint16 varvalue_len);
|
||||
void AddSpeech(const char* from, const char* to, const char* message, uint16 minstatus, uint32 guilddbid, uint8 type);
|
||||
void LogPlayerTrade(QSPlayerLogTrade_Struct* QS, uint32 Items);
|
||||
void LogPlayerHandin(QSPlayerLogHandin_Struct* QS, uint32 Items);
|
||||
@ -50,6 +49,7 @@ public:
|
||||
void LogPlayerDelete(QSPlayerLogDelete_Struct* QS, uint32 Items);
|
||||
void LogPlayerMove(QSPlayerLogMove_Struct* QS, uint32 Items);
|
||||
void LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint32 Items);
|
||||
void GeneralQueryReceive(ServerPacket *pack);
|
||||
protected:
|
||||
void HandleMysqlError(uint32 errnum);
|
||||
private:
|
||||
|
||||
@ -33,24 +33,15 @@
|
||||
|
||||
volatile bool RunLoops = true;
|
||||
|
||||
uint32 MailMessagesSent = 0;
|
||||
uint32 ChatMessagesSent = 0;
|
||||
|
||||
TimeoutManager timeout_manager;
|
||||
|
||||
Database database;
|
||||
LFGuildManager lfguildmanager;
|
||||
std::string WorldShortName;
|
||||
|
||||
const queryservconfig *Config;
|
||||
|
||||
WorldServer *worldserver = 0;
|
||||
|
||||
|
||||
void CatchSignal(int sig_num) {
|
||||
|
||||
RunLoops = false;
|
||||
|
||||
if(worldserver)
|
||||
worldserver->Disconnect();
|
||||
}
|
||||
@ -58,31 +49,31 @@ void CatchSignal(int sig_num) {
|
||||
int main() {
|
||||
RegisterExecutablePlatform(ExePlatformQueryServ);
|
||||
set_exception_handler();
|
||||
|
||||
Timer LFGuildExpireTimer(60000);
|
||||
|
||||
Timer InterserverTimer(INTERSERVER_TIMER); // does auto-reconnect
|
||||
|
||||
/* Load XML from eqemu_config.xml
|
||||
<qsdatabase>
|
||||
<host>127.0.0.1</host>
|
||||
<port>3306</port>
|
||||
<username>user</username>
|
||||
<password>password</password>
|
||||
<db>dbname</db>
|
||||
</qsdatabase>
|
||||
*/
|
||||
|
||||
_log(QUERYSERV__INIT, "Starting EQEmu QueryServ.");
|
||||
|
||||
if (!queryservconfig::LoadConfig()) {
|
||||
|
||||
_log(QUERYSERV__INIT, "Loading server configuration failed.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
Config = queryservconfig::get();
|
||||
|
||||
if(!load_log_settings(Config->LogSettingsFile.c_str()))
|
||||
_log(QUERYSERV__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
|
||||
else
|
||||
_log(QUERYSERV__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
|
||||
|
||||
WorldShortName = Config->ShortName;
|
||||
|
||||
_log(QUERYSERV__INIT, "Connecting to MySQL...");
|
||||
|
||||
/* MySQL Connection */
|
||||
if (!database.Connect(
|
||||
Config->QSDatabaseHost.c_str(),
|
||||
Config->QSDatabaseUsername.c_str(),
|
||||
@ -93,6 +84,12 @@ int main() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize Logging */
|
||||
if (!load_log_settings(Config->LogSettingsFile.c_str()))
|
||||
_log(QUERYSERV__INIT, "Warning: Unable to read %s", Config->LogSettingsFile.c_str());
|
||||
else
|
||||
_log(QUERYSERV__INIT, "Log settings loaded from %s", Config->LogSettingsFile.c_str());
|
||||
|
||||
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
|
||||
_log(QUERYSERV__ERROR, "Could not set signal handler");
|
||||
return 1;
|
||||
@ -102,16 +99,15 @@ int main() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initial Connection to Worldserver */
|
||||
worldserver = new WorldServer;
|
||||
|
||||
worldserver->Connect();
|
||||
|
||||
/* Load Looking For Guild Manager */
|
||||
lfguildmanager.LoadDatabase();
|
||||
|
||||
while(RunLoops) {
|
||||
|
||||
Timer::SetCurrentTime();
|
||||
|
||||
if(LFGuildExpireTimer.Check())
|
||||
lfguildmanager.ExpireEntries();
|
||||
|
||||
@ -120,9 +116,7 @@ int main() {
|
||||
worldserver->AsyncConnect();
|
||||
}
|
||||
worldserver->Process();
|
||||
|
||||
timeout_manager.CheckTimeouts();
|
||||
|
||||
Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,121 +57,108 @@ void WorldServer::OnConnected()
|
||||
void WorldServer::Process()
|
||||
{
|
||||
WorldConnection::Process();
|
||||
|
||||
if (!Connected())
|
||||
return;
|
||||
|
||||
ServerPacket *pack = 0;
|
||||
|
||||
while((pack = tcpc.PopPacket()))
|
||||
{
|
||||
_log(QUERYSERV__TRACE, "Received Opcode: %4X", pack->opcode);
|
||||
|
||||
switch(pack->opcode)
|
||||
{
|
||||
switch(pack->opcode) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case ServerOP_KeepAlive:
|
||||
{
|
||||
case ServerOP_KeepAlive: {
|
||||
break;
|
||||
}
|
||||
case ServerOP_Speech:
|
||||
{
|
||||
case ServerOP_Speech: {
|
||||
Server_Speech_Struct *SSS = (Server_Speech_Struct*)pack->pBuffer;
|
||||
|
||||
std::string tmp1 = SSS->from;
|
||||
std::string tmp2 = SSS->to;
|
||||
|
||||
database.AddSpeech(tmp1.c_str(), tmp2.c_str(), SSS->message, SSS->minstatus, SSS->guilddbid, SSS->type);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogTrades:
|
||||
{
|
||||
case ServerOP_QSPlayerLogTrades: {
|
||||
QSPlayerLogTrade_Struct *QS = (QSPlayerLogTrade_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char1_count + QS->char2_count;
|
||||
database.LogPlayerTrade(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogHandins:
|
||||
{
|
||||
case ServerOP_QSPlayerLogHandins: {
|
||||
QSPlayerLogHandin_Struct *QS = (QSPlayerLogHandin_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count + QS->npc_count;
|
||||
database.LogPlayerHandin(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogNPCKills:
|
||||
{
|
||||
case ServerOP_QSPlayerLogNPCKills: {
|
||||
QSPlayerLogNPCKill_Struct *QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer;
|
||||
uint32 Members = pack->size - sizeof(QSPlayerLogNPCKill_Struct);
|
||||
if (Members > 0) Members = Members / sizeof(QSPlayerLogNPCKillsPlayers_Struct);
|
||||
database.LogPlayerNPCKill(QS, Members);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogDeletes:
|
||||
{
|
||||
case ServerOP_QSPlayerLogDeletes: {
|
||||
QSPlayerLogDelete_Struct *QS = (QSPlayerLogDelete_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count;
|
||||
database.LogPlayerDelete(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSPlayerLogMoves:
|
||||
{
|
||||
case ServerOP_QSPlayerLogMoves: {
|
||||
QSPlayerLogMove_Struct *QS = (QSPlayerLogMove_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count;
|
||||
database.LogPlayerMove(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSMerchantLogTransactions:
|
||||
{
|
||||
case ServerOP_QSPlayerLogMerchantTransactions: {
|
||||
QSMerchantLogTransaction_Struct *QS = (QSMerchantLogTransaction_Struct*)pack->pBuffer;
|
||||
uint32 Items = QS->char_count + QS->merchant_count;
|
||||
database.LogMerchantTransaction(QS, Items);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QueryServGeneric:
|
||||
{
|
||||
// The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets
|
||||
// each time we add functionality to queryserv.
|
||||
//
|
||||
// A ServerOP_QueryServGeneric packet has the following format:
|
||||
//
|
||||
// uint32 SourceZoneID
|
||||
// uint32 SourceInstanceID
|
||||
// char OriginatingCharacterName[0] // Null terminated name of the character this packet came from. This could be just
|
||||
// // an empty string if it has no meaning in the context of a particular packet.
|
||||
// uint32 Type
|
||||
//
|
||||
// The 'Type' field is a 'sub-opcode'. A value of 0 is used for the LFGuild packets. The next feature to be added
|
||||
// to queryserv would use 1, etc.
|
||||
//
|
||||
// Obviously, any fields in the packet following the 'Type' will be unique to the particular type of packet. The
|
||||
// 'Generic' in the name of this ServerOP code relates to the four header fields.
|
||||
case ServerOP_QueryServGeneric: {
|
||||
/*
|
||||
The purpose of ServerOP_QueryServerGeneric is so that we don't have to add code to world just to relay packets
|
||||
each time we add functionality to queryserv.
|
||||
|
||||
A ServerOP_QueryServGeneric packet has the following format:
|
||||
|
||||
uint32 SourceZoneID
|
||||
uint32 SourceInstanceID
|
||||
char OriginatingCharacterName[0]
|
||||
- Null terminated name of the character this packet came from. This could be just
|
||||
- an empty string if it has no meaning in the context of a particular packet.
|
||||
uint32 Type
|
||||
|
||||
The 'Type' field is a 'sub-opcode'. A value of 0 is used for the LFGuild packets. The next feature to be added
|
||||
to queryserv would use 1, etc.
|
||||
|
||||
Obviously, any fields in the packet following the 'Type' will be unique to the particular type of packet. The
|
||||
'Generic' in the name of this ServerOP code relates to the four header fields.
|
||||
*/
|
||||
|
||||
char From[64];
|
||||
pack->SetReadPosition(8);
|
||||
pack->ReadString(From);
|
||||
uint32 Type = pack->ReadUInt32();
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
case QSG_LFGuild:
|
||||
{
|
||||
switch(Type) {
|
||||
case QSG_LFGuild:{
|
||||
lfguildmanager.HandlePacket(pack);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
_log(QUERYSERV__ERROR, "Received unhandled ServerOP_QueryServGeneric", Type);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ServerOP_QSSendQuery: {
|
||||
/* Process all packets here */
|
||||
database.GeneralQueryReceive(pack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete(pack);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_events
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_events`;
|
||||
CREATE TABLE `qs_player_events` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`event` int(11) unsigned DEFAULT '0',
|
||||
`event_desc` varchar(255) DEFAULT NULL,
|
||||
`time` int(11) unsigned DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_aa_rate_hourly
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_aa_rate_hourly`;
|
||||
CREATE TABLE `qs_player_aa_rate_hourly` (
|
||||
`char_id` int(11) NOT NULL DEFAULT '0',
|
||||
`hour_time` int(11) NOT NULL,
|
||||
`aa_count` varchar(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`char_id`,`hour_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
@ -0,0 +1,45 @@
|
||||
-- Disable Player Logging for All --
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogPCCoordinates', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogNPCKills', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTrades', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMerchantTransactions', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDeletes', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogHandins', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMoves', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogChat', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogKeyringAddition', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAAPurchases', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogIssuedCommandes', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMoneyTransactions', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAlternateCurrencyTransactions', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTradeSkillEvents', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogPCCoordinates', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDropItem', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMerchantTransactions', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDeletes', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogHandins', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMoves', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogNPCKills', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTrades', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogQGlobalUpdate', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTaskUpdates', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDeaths', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogZone', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogConnectDisconnect', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogLevels', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAARate', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogChat', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDropItem', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogZone', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDeaths', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogLevels', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogEXPRate', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAARate', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogQGlobalUpdate', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTaskUpdates', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogKeyringAddition', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAAPurchases', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTradeSkillEvents', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogIssuedCommandes', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMoneyTransactions', 'false', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAlternateCurrencyTransactions', 'false', '');
|
||||
@ -0,0 +1,45 @@
|
||||
-- Enable Player Logging for All --
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogPCCoordinates', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogNPCKills', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTrades', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMerchantTransactions', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDeletes', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogHandins', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMoves', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogChat', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogKeyringAddition', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAAPurchases', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogIssuedCommandes', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMoneyTransactions', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAlternateCurrencyTransactions', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTradeSkillEvents', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogPCCoordinates', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDropItem', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMerchantTransactions', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDeletes', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogHandins', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogMoves', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogNPCKills', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTrades', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogQGlobalUpdate', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogTaskUpdates', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogDeaths', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogZone', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogConnectDisconnect', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogLevels', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (9, 'QueryServ:PlayerLogAARate', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogChat', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDropItem', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogZone', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogDeaths', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogLevels', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogEXPRate', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAARate', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogQGlobalUpdate', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTaskUpdates', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogKeyringAddition', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAAPurchases', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogTradeSkillEvents', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogIssuedCommandes', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogMoneyTransactions', 'true', '');
|
||||
REPLACE INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (0, 'QueryServ:PlayerLogAlternateCurrencyTransactions', 'true', '');
|
||||
@ -0,0 +1,247 @@
|
||||
-- QS Table Structures --
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_merchant_transaction_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_merchant_transaction_record`;
|
||||
CREATE TABLE `qs_merchant_transaction_record` (
|
||||
`transaction_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`zone_id` int(11) DEFAULT '0',
|
||||
`merchant_id` int(11) DEFAULT '0',
|
||||
`merchant_pp` int(11) DEFAULT '0',
|
||||
`merchant_gp` int(11) DEFAULT '0',
|
||||
`merchant_sp` int(11) DEFAULT '0',
|
||||
`merchant_cp` int(11) DEFAULT '0',
|
||||
`merchant_items` mediumint(7) DEFAULT '0',
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`char_pp` int(11) DEFAULT '0',
|
||||
`char_gp` int(11) DEFAULT '0',
|
||||
`char_sp` int(11) DEFAULT '0',
|
||||
`char_cp` int(11) DEFAULT '0',
|
||||
`char_items` mediumint(7) DEFAULT '0',
|
||||
PRIMARY KEY (`transaction_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_merchant_transaction_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_merchant_transaction_record_entries`;
|
||||
CREATE TABLE `qs_merchant_transaction_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`char_slot` mediumint(7) DEFAULT '0',
|
||||
`item_id` int(11) DEFAULT '0',
|
||||
`charges` mediumint(7) DEFAULT '0',
|
||||
`aug_1` int(11) DEFAULT '0',
|
||||
`aug_2` int(11) DEFAULT '0',
|
||||
`aug_3` int(11) DEFAULT '0',
|
||||
`aug_4` int(11) DEFAULT '0',
|
||||
`aug_5` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_aa_rate_hourly
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_aa_rate_hourly`;
|
||||
CREATE TABLE `qs_player_aa_rate_hourly` (
|
||||
`char_id` int(11) NOT NULL DEFAULT '0',
|
||||
`hour_time` int(11) NOT NULL,
|
||||
`aa_count` varchar(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`char_id`,`hour_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_delete_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_delete_record`;
|
||||
CREATE TABLE `qs_player_delete_record` (
|
||||
`delete_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`stack_size` mediumint(7) DEFAULT '0',
|
||||
`char_items` mediumint(7) DEFAULT '0',
|
||||
PRIMARY KEY (`delete_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_delete_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_delete_record_entries`;
|
||||
CREATE TABLE `qs_player_delete_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`char_slot` mediumint(7) DEFAULT '0',
|
||||
`item_id` int(11) DEFAULT '0',
|
||||
`charges` mediumint(7) DEFAULT '0',
|
||||
`aug_1` int(11) DEFAULT '0',
|
||||
`aug_2` int(11) DEFAULT '0',
|
||||
`aug_3` int(11) DEFAULT '0',
|
||||
`aug_4` int(11) DEFAULT '0',
|
||||
`aug_5` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_events
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_events`;
|
||||
CREATE TABLE `qs_player_events` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`event` int(11) unsigned DEFAULT '0',
|
||||
`event_desc` varchar(255) DEFAULT NULL,
|
||||
`time` int(11) unsigned DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_handin_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_handin_record`;
|
||||
CREATE TABLE `qs_player_handin_record` (
|
||||
`handin_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`quest_id` int(11) DEFAULT '0',
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`char_pp` int(11) DEFAULT '0',
|
||||
`char_gp` int(11) DEFAULT '0',
|
||||
`char_sp` int(11) DEFAULT '0',
|
||||
`char_cp` int(11) DEFAULT '0',
|
||||
`char_items` mediumint(7) DEFAULT '0',
|
||||
`npc_id` int(11) DEFAULT '0',
|
||||
`npc_pp` int(11) DEFAULT '0',
|
||||
`npc_gp` int(11) DEFAULT '0',
|
||||
`npc_sp` int(11) DEFAULT '0',
|
||||
`npc_cp` int(11) DEFAULT '0',
|
||||
`npc_items` mediumint(7) DEFAULT '0',
|
||||
PRIMARY KEY (`handin_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_handin_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_handin_record_entries`;
|
||||
CREATE TABLE `qs_player_handin_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`action_type` char(6) DEFAULT 'action',
|
||||
`char_slot` mediumint(7) DEFAULT '0',
|
||||
`item_id` int(11) DEFAULT '0',
|
||||
`charges` mediumint(7) DEFAULT '0',
|
||||
`aug_1` int(11) DEFAULT '0',
|
||||
`aug_2` int(11) DEFAULT '0',
|
||||
`aug_3` int(11) DEFAULT '0',
|
||||
`aug_4` int(11) DEFAULT '0',
|
||||
`aug_5` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_move_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_move_record`;
|
||||
CREATE TABLE `qs_player_move_record` (
|
||||
`move_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`char_id` int(11) DEFAULT '0',
|
||||
`from_slot` mediumint(7) DEFAULT '0',
|
||||
`to_slot` mediumint(7) DEFAULT '0',
|
||||
`stack_size` mediumint(7) DEFAULT '0',
|
||||
`char_items` mediumint(7) DEFAULT '0',
|
||||
`postaction` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`move_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_move_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_move_record_entries`;
|
||||
CREATE TABLE `qs_player_move_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`from_slot` mediumint(7) DEFAULT '0',
|
||||
`to_slot` mediumint(7) DEFAULT '0',
|
||||
`item_id` int(11) DEFAULT '0',
|
||||
`charges` mediumint(7) DEFAULT '0',
|
||||
`aug_1` int(11) DEFAULT '0',
|
||||
`aug_2` int(11) DEFAULT '0',
|
||||
`aug_3` int(11) DEFAULT '0',
|
||||
`aug_4` int(11) DEFAULT '0',
|
||||
`aug_5` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_npc_kill_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_npc_kill_record`;
|
||||
CREATE TABLE `qs_player_npc_kill_record` (
|
||||
`fight_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`npc_id` int(11) DEFAULT NULL,
|
||||
`type` int(11) DEFAULT NULL,
|
||||
`zone_id` int(11) DEFAULT NULL,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`fight_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_npc_kill_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_npc_kill_record_entries`;
|
||||
CREATE TABLE `qs_player_npc_kill_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`char_id` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_speech
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_speech`;
|
||||
CREATE TABLE `qs_player_speech` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`from` varchar(64) NOT NULL,
|
||||
`to` varchar(64) NOT NULL,
|
||||
`message` varchar(256) NOT NULL,
|
||||
`minstatus` smallint(5) NOT NULL,
|
||||
`guilddbid` int(11) NOT NULL,
|
||||
`type` tinyint(3) NOT NULL,
|
||||
`timerecorded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_trade_record
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_trade_record`;
|
||||
CREATE TABLE `qs_player_trade_record` (
|
||||
`trade_id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`char1_id` int(11) DEFAULT '0',
|
||||
`char1_pp` int(11) DEFAULT '0',
|
||||
`char1_gp` int(11) DEFAULT '0',
|
||||
`char1_sp` int(11) DEFAULT '0',
|
||||
`char1_cp` int(11) DEFAULT '0',
|
||||
`char1_items` mediumint(7) DEFAULT '0',
|
||||
`char2_id` int(11) DEFAULT '0',
|
||||
`char2_pp` int(11) DEFAULT '0',
|
||||
`char2_gp` int(11) DEFAULT '0',
|
||||
`char2_sp` int(11) DEFAULT '0',
|
||||
`char2_cp` int(11) DEFAULT '0',
|
||||
`char2_items` mediumint(7) DEFAULT '0',
|
||||
PRIMARY KEY (`trade_id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for qs_player_trade_record_entries
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `qs_player_trade_record_entries`;
|
||||
CREATE TABLE `qs_player_trade_record_entries` (
|
||||
`event_id` int(11) DEFAULT '0',
|
||||
`from_id` int(11) DEFAULT '0',
|
||||
`from_slot` mediumint(7) DEFAULT '0',
|
||||
`to_id` int(11) DEFAULT '0',
|
||||
`to_slot` mediumint(7) DEFAULT '0',
|
||||
`item_id` int(11) DEFAULT '0',
|
||||
`charges` mediumint(7) DEFAULT '0',
|
||||
`aug_1` int(11) DEFAULT '0',
|
||||
`aug_2` int(11) DEFAULT '0',
|
||||
`aug_3` int(11) DEFAULT '0',
|
||||
`aug_4` int(11) DEFAULT '0',
|
||||
`aug_5` int(11) DEFAULT '0'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
33
utils/sql/git/required/2014_08_24_character_lookup.sql
Normal file
33
utils/sql/git/required/2014_08_24_character_lookup.sql
Normal file
@ -0,0 +1,33 @@
|
||||
-- chracter_lookup table structure --
|
||||
|
||||
CREATE TABLE `character_lookup` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`account_id` int(11) NOT NULL DEFAULT '0',
|
||||
`name` varchar(64) NOT NULL DEFAULT '',
|
||||
`timelaston` int(11) unsigned DEFAULT '0',
|
||||
`x` float NOT NULL DEFAULT '0',
|
||||
`y` float NOT NULL DEFAULT '0',
|
||||
`z` float NOT NULL DEFAULT '0',
|
||||
`zonename` varchar(30) NOT NULL DEFAULT '',
|
||||
`zoneid` smallint(6) NOT NULL DEFAULT '0',
|
||||
`instanceid` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
`pktime` int(8) NOT NULL DEFAULT '0',
|
||||
`groupid` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`class` tinyint(4) NOT NULL DEFAULT '0',
|
||||
`level` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`lfp` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
`lfg` tinyint(1) unsigned NOT NULL DEFAULT '0',
|
||||
`mailkey` char(16) NOT NULL,
|
||||
`xtargets` tinyint(3) unsigned NOT NULL DEFAULT '5',
|
||||
`firstlogon` tinyint(3) NOT NULL DEFAULT '0',
|
||||
`inspectmessage` varchar(256) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`),
|
||||
KEY `account_id` (`account_id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
|
||||
|
||||
-- Initial population of the character_lookup table --
|
||||
|
||||
INSERT INTO `character_lookup` (id, account_id, `name`, timelaston, x, y, z, zonename, zoneid, instanceid, pktime, groupid, class, `level`, lfp, lfg, mailkey, xtargets, firstlogon, inspectmessage)
|
||||
SELECT id, account_id, `name`, timelaston, x, y, z, zonename, zoneid, instanceid, pktime, groupid, class, `level`, lfp, lfg, mailkey, xtargets, firstlogon, inspectmessage
|
||||
FROM `character_`;
|
||||
@ -1268,7 +1268,7 @@ bool ZoneServer::Process() {
|
||||
UCSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
|
||||
case ServerOP_QSSendQuery:
|
||||
case ServerOP_QueryServGeneric:
|
||||
case ServerOP_Speech:
|
||||
case ServerOP_QSPlayerLogTrades:
|
||||
@ -1296,7 +1296,7 @@ bool ZoneServer::Process() {
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
}
|
||||
case ServerOP_QSMerchantLogTransactions:
|
||||
case ServerOP_QSPlayerLogMerchantTransactions:
|
||||
{
|
||||
QSLink.SendPacket(pack);
|
||||
break;
|
||||
|
||||
@ -93,6 +93,7 @@ SET(zone_sources
|
||||
petitions.cpp
|
||||
pets.cpp
|
||||
qglobals.cpp
|
||||
queryserv.cpp
|
||||
questmgr.cpp
|
||||
quest_parser_collection.cpp
|
||||
raids.cpp
|
||||
@ -184,6 +185,8 @@ SET(zone_headers
|
||||
pets.h
|
||||
qglobals.h
|
||||
quest_interface.h
|
||||
queryserv.h
|
||||
quest_interface.h
|
||||
questmgr.h
|
||||
quest_parser_collection.h
|
||||
raid.h
|
||||
|
||||
25
zone/aa.cpp
25
zone/aa.cpp
@ -38,6 +38,9 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net)
|
||||
#include "../common/logsys.h"
|
||||
#include "zonedb.h"
|
||||
#include "string_ids.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
|
||||
//static data arrays, really not big enough to warrant shared mem.
|
||||
AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
|
||||
@ -1059,11 +1062,29 @@ void Client::BuyAA(AA_Action* action)
|
||||
|
||||
//we are building these messages ourself instead of using the stringID to work around patch discrepencies
|
||||
//these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2
|
||||
if(cur_level<1)
|
||||
|
||||
/* Initial purchase of an AA ability */
|
||||
if (cur_level < 1){
|
||||
Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point");
|
||||
else
|
||||
|
||||
/* QS: Player_Log_AA_Purchases */
|
||||
if (RuleB(QueryServ, PlayerLogAAPurchases)){
|
||||
std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
/* Ranked purchase of an AA ability */
|
||||
else{
|
||||
Message(15, "You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level + 1, real_cost, (real_cost > 1) ? "points" : "point");
|
||||
|
||||
/* QS: Player_Log_AA_Purchases */
|
||||
if (RuleB(QueryServ, PlayerLogAAPurchases)){
|
||||
std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SendAAStats();
|
||||
|
||||
|
||||
@ -873,7 +873,30 @@ bool Mob::CombatRange(Mob* other)
|
||||
if (size_mod > 10000)
|
||||
size_mod = size_mod / 7;
|
||||
|
||||
if (DistNoRoot(*other) <= size_mod)
|
||||
float _DistNoRoot = DistNoRoot(*other);
|
||||
|
||||
if (GetSpecialAbility(NPC_CHASE_DISTANCE)){
|
||||
|
||||
float max_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 0));
|
||||
float min_dist = static_cast<float>(GetSpecialAbilityParam(NPC_CHASE_DISTANCE, 1));
|
||||
|
||||
if (max_dist == 1)
|
||||
max_dist = 250.0f; //Default it to 250 if you forget to put a value
|
||||
|
||||
max_dist = max_dist * max_dist;
|
||||
|
||||
if (!min_dist)
|
||||
min_dist = size_mod; //Default to melee range
|
||||
else
|
||||
min_dist = min_dist * min_dist;
|
||||
|
||||
if (CheckLastLosState() && (_DistNoRoot >= min_dist && _DistNoRoot <= max_dist))
|
||||
SetPseudoRoot(true);
|
||||
else
|
||||
SetPseudoRoot(false);
|
||||
}
|
||||
|
||||
if (_DistNoRoot <= size_mod)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -887,6 +910,8 @@ bool Mob::CheckLosFN(Mob* other) {
|
||||
if(other)
|
||||
Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize());
|
||||
|
||||
SetLastLosState(Result);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +42,9 @@
|
||||
#include "quest_parser_collection.h"
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern WorldServer worldserver;
|
||||
|
||||
#ifdef _WINDOWS
|
||||
@ -1455,14 +1458,14 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
int exploss = 0;
|
||||
mlog(COMBAT__HITS, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killerMob ? killerMob->GetName() : "Unknown", damage, spell, attack_skill);
|
||||
|
||||
//
|
||||
// #1: Send death packet to everyone
|
||||
//
|
||||
/*
|
||||
#1: Send death packet to everyone
|
||||
*/
|
||||
uint8 killed_level = GetLevel();
|
||||
|
||||
SendLogoutPackets();
|
||||
|
||||
//make our become corpse packet, and queue to ourself before OP_Death.
|
||||
/* Make self become corpse packet */
|
||||
EQApplicationPacket app2(OP_BecomeCorpse, sizeof(BecomeCorpse_Struct));
|
||||
BecomeCorpse_Struct* bc = (BecomeCorpse_Struct*)app2.pBuffer;
|
||||
bc->spawn_id = GetID();
|
||||
@ -1471,7 +1474,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
bc->z = GetZ();
|
||||
QueuePacket(&app2);
|
||||
|
||||
// make death packet
|
||||
/* Make Death Packet */
|
||||
EQApplicationPacket app(OP_Death, sizeof(Death_Struct));
|
||||
Death_Struct* d = (Death_Struct*)app.pBuffer;
|
||||
d->spawn_id = GetID();
|
||||
@ -1484,9 +1487,9 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
app.priority = 6;
|
||||
entity_list.QueueClients(this, &app);
|
||||
|
||||
//
|
||||
// #2: figure out things that affect the player dying and mark them dead
|
||||
//
|
||||
/*
|
||||
#2: figure out things that affect the player dying and mark them dead
|
||||
*/
|
||||
|
||||
InterruptSpell();
|
||||
SetPet(0);
|
||||
@ -1541,9 +1544,9 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
//remove ourself from all proximities
|
||||
ClearAllProximities();
|
||||
|
||||
//
|
||||
// #3: exp loss and corpse generation
|
||||
//
|
||||
/*
|
||||
#3: exp loss and corpse generation
|
||||
*/
|
||||
|
||||
// figure out if they should lose exp
|
||||
if(RuleB(Character, UseDeathExpLossMult)){
|
||||
@ -1659,27 +1662,21 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
|
||||
LeftCorpse = true;
|
||||
}
|
||||
|
||||
// if(!IsLD())//Todo: make it so an LDed client leaves corpse if its enabled
|
||||
// MakeCorpse(exploss);
|
||||
} else {
|
||||
BuffFadeDetrimental();
|
||||
}
|
||||
|
||||
//
|
||||
// Finally, send em home
|
||||
//
|
||||
/*
|
||||
Finally, send em home
|
||||
|
||||
// we change the mob variables, not pp directly, because Save() will copy
|
||||
// from these and overwrite what we set in pp anyway
|
||||
//
|
||||
We change the mob variables, not pp directly, because Save() will copy
|
||||
from these and overwrite what we set in pp anyway
|
||||
*/
|
||||
|
||||
if(LeftCorpse && (GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
|
||||
{
|
||||
ClearDraggedCorpses();
|
||||
|
||||
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
|
||||
|
||||
SendRespawnBinds();
|
||||
}
|
||||
else
|
||||
@ -1697,16 +1694,21 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
|
||||
r->MemberZoned(this);
|
||||
|
||||
dead_timer.Start(5000, true);
|
||||
|
||||
m_pp.zone_id = m_pp.binds[0].zoneId;
|
||||
m_pp.zoneInstance = 0;
|
||||
database.MoveCharacterToZone(this->CharacterID(), database.GetZoneName(m_pp.zone_id));
|
||||
|
||||
Save();
|
||||
|
||||
GoToDeath();
|
||||
}
|
||||
|
||||
/* QS: PlayerLogDeaths */
|
||||
if (RuleB(QueryServ, PlayerLogDeaths)){
|
||||
const char * killer_name = "";
|
||||
if (killerMob && killerMob->GetCleanName()){ killer_name = killerMob->GetCleanName(); }
|
||||
std::string event_desc = StringFormat("Died in zoneid:%i instid:%i by '%s', spellid:%i, damage:%i", this->GetZoneID(), this->GetInstanceID(), killer_name, spell, damage);
|
||||
QServ->PlayerLogEvent(Player_Log_Deaths, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
parse->EventPlayer(EVENT_DEATH_COMPLETE, this, buffer, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -62,8 +62,9 @@ extern volatile bool RunLoops;
|
||||
#include "client_logs.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern EntityList entity_list;
|
||||
extern Zone* zone;
|
||||
extern volatile bool ZoneLoaded;
|
||||
@ -629,6 +630,9 @@ bool Client::Save(uint8 iCommitNow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Mirror Character Data */
|
||||
database.StoreCharacterLookup(this->CharacterID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -805,8 +809,8 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(RuleB(QueryServ, PlayerChatLogging)) {
|
||||
/* Logs Player Chat */
|
||||
if (RuleB(QueryServ, PlayerLogChat)) {
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_Speech, sizeof(Server_Speech_Struct) + strlen(message) + 1);
|
||||
Server_Speech_Struct* sem = (Server_Speech_Struct*) pack->pBuffer;
|
||||
|
||||
@ -841,7 +845,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
|
||||
switch(chan_num)
|
||||
{
|
||||
case 0: { // GuildChat
|
||||
case 0: { /* Guild Chat */
|
||||
if (!IsInAGuild())
|
||||
Message_StringID(MT_DefaultText, GUILD_NOT_MEMBER2); //You are not a member of any guild.
|
||||
else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_SPEAK))
|
||||
@ -850,7 +854,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 2: { // GroupChat
|
||||
case 2: { /* Group Chat */
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if(raid) {
|
||||
raid->RaidGroupSay((const char*) message, this);
|
||||
@ -863,14 +867,14 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 15: { //raid say
|
||||
case 15: { /* Raid Say */
|
||||
Raid* raid = entity_list.GetRaidByClient(this);
|
||||
if(raid){
|
||||
raid->RaidSay((const char*) message, this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: { // Shout
|
||||
case 3: { /* Shout */
|
||||
Mob *sender = this;
|
||||
if (GetPet() && GetPet()->FindType(SE_VoiceGraft))
|
||||
sender = GetPet();
|
||||
@ -878,7 +882,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
entity_list.ChannelMessage(sender, chan_num, language, lang_skill, message);
|
||||
break;
|
||||
}
|
||||
case 4: { // Auction
|
||||
case 4: { /* Auction */
|
||||
if(RuleB(Chat, ServerWideAuction))
|
||||
{
|
||||
if(!global_channel_timer.Check())
|
||||
@ -917,7 +921,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: { // OOC
|
||||
case 5: { /* OOC */
|
||||
if(RuleB(Chat, ServerWideOOC))
|
||||
{
|
||||
if(!global_channel_timer.Check())
|
||||
@ -964,15 +968,15 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: // Broadcast
|
||||
case 11: { // GMSay
|
||||
case 6: /* Broadcast */
|
||||
case 11: { /* GM Say */
|
||||
if (!(admin >= 80))
|
||||
Message(0, "Error: Only GMs can use this channel");
|
||||
else if (!worldserver.SendChannelMessage(this, targetname, chan_num, 0, language, message))
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 7: { // Tell
|
||||
case 7: { /* Tell */
|
||||
if(!global_channel_timer.Check())
|
||||
{
|
||||
if(strlen(targetname) == 0)
|
||||
@ -1020,7 +1024,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
Message(0, "Error: World server disconnected");
|
||||
break;
|
||||
}
|
||||
case 8: { // /say
|
||||
case 8: { /* Say */
|
||||
if(message[0] == COMMAND_CHAR) {
|
||||
if(command_dispatch(this, message) == -2) {
|
||||
if(parse->PlayerHasQuestSub(EVENT_COMMAND)) {
|
||||
@ -4029,13 +4033,17 @@ void Client::KeyRingAdd(uint32 item_id)
|
||||
bool bFound = KeyRingCheck(item_id);
|
||||
if(!bFound){
|
||||
sprintf(query, "INSERT INTO keyring(char_id,item_id) VALUES(%i,%i)",character_id,item_id);
|
||||
if(database.RunQuery(query, strlen(query), errbuf, 0, &affected_rows))
|
||||
{
|
||||
if(database.RunQuery(query, strlen(query), errbuf, 0, &affected_rows)) {
|
||||
Message(4,"Added to keyring.");
|
||||
|
||||
/* QS: PlayerLogKeyringAddition */
|
||||
if (RuleB(QueryServ, PlayerLogKeyringAddition)){
|
||||
std::string event_desc = StringFormat("itemid:%i in zoneid:%i instid:%i", item_id, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Keyring_Addition, this->CharacterID(), event_desc);
|
||||
}
|
||||
safe_delete_array(query);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
std::cerr << "Error in Doors::HandleClick query '" << query << "' " << errbuf << std::endl;
|
||||
safe_delete_array(query);
|
||||
return;
|
||||
@ -6933,8 +6941,18 @@ void Client::SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount)
|
||||
SendAlternateCurrencyValue(currency_id);
|
||||
}
|
||||
|
||||
void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount)
|
||||
void Client::AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method)
|
||||
{
|
||||
|
||||
/* Added via Quest, rest of the logging methods may be done inline due to information available in that area of the code */
|
||||
if (method == 1){
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Added via Quest :: Cursor to Item :: alt_currency_id:%i amount:%i in zoneid:%i instid:%i", currency_id, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
if(amount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1097,7 +1097,7 @@ public:
|
||||
inline void ClearDraggedCorpses() { DraggedCorpses.clear(); }
|
||||
void SendAltCurrencies();
|
||||
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
||||
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount);
|
||||
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
|
||||
void SendAlternateCurrencyValues();
|
||||
void SendAlternateCurrencyValue(uint32 currency_id, bool send_if_null = true);
|
||||
uint32 GetAlternateCurrencyValue(uint32 currency_id) const;
|
||||
|
||||
@ -16,16 +16,16 @@
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <zlib.h>
|
||||
#include <assert.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define snprintf _snprintf
|
||||
@ -38,8 +38,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "masterentity.h"
|
||||
#include "zonedb.h"
|
||||
#include "../common/packet_functions.h"
|
||||
#include "../common/packet_dump.h"
|
||||
#include "worldserver.h"
|
||||
@ -59,17 +57,21 @@
|
||||
#include "../common/faction.h"
|
||||
#include "../common/crc32.h"
|
||||
#include "string_ids.h"
|
||||
#include "map.h"
|
||||
#include "titles.h"
|
||||
#include "pets.h"
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "zone.h"
|
||||
#include "zone_config.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "pathing.h"
|
||||
#include "water_map.h"
|
||||
#include "merc.h"
|
||||
#include "pets.h"
|
||||
#include "../common/zone_numbers.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern Zone* zone;
|
||||
extern volatile bool ZoneLoaded;
|
||||
extern WorldServer worldserver;
|
||||
@ -5687,8 +5689,8 @@ void Client::Handle_OP_ShopPlayerBuy(const EQApplicationPacket *app)
|
||||
safe_delete(outapp);
|
||||
|
||||
// start QS code
|
||||
if(RuleB(QueryServ, MerchantLogTransactions)) {
|
||||
ServerPacket* qspack = new ServerPacket(ServerOP_QSMerchantLogTransactions, sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct));
|
||||
if(RuleB(QueryServ, PlayerLogMerchantTransactions)) {
|
||||
ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct));
|
||||
QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer;
|
||||
|
||||
qsaudit->zone_id = zone->GetZoneID();
|
||||
@ -5823,8 +5825,8 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
// start QS code
|
||||
if(RuleB(QueryServ, MerchantLogTransactions)) {
|
||||
ServerPacket* qspack = new ServerPacket(ServerOP_QSMerchantLogTransactions, sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct));
|
||||
if(RuleB(QueryServ, PlayerLogMerchantTransactions)) {
|
||||
ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogMerchantTransactions, sizeof(QSMerchantLogTransaction_Struct) + sizeof(QSTransactionItems_Struct));
|
||||
QSMerchantLogTransaction_Struct* qsaudit = (QSMerchantLogTransaction_Struct*)qspack->pBuffer;
|
||||
|
||||
qsaudit->zone_id = zone->GetZoneID();
|
||||
@ -9180,8 +9182,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
if(!GetAA(aaPersistentMinion))
|
||||
memset(&m_suspendedminion, 0, sizeof(PetInfo));
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Server Zone Entry Packet
|
||||
/* Server Zone Entry Packet */
|
||||
outapp = new EQApplicationPacket(OP_ZoneEntry, sizeof(ServerZoneEntry_Struct));
|
||||
ServerZoneEntry_Struct* sze = (ServerZoneEntry_Struct*)outapp->pBuffer;
|
||||
|
||||
@ -9191,42 +9192,30 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
sze->player.spawn.z += 6; //arbitrary lift, seems to help spawning under zone.
|
||||
outapp->priority = 6;
|
||||
FastQueuePacket(&outapp);
|
||||
//safe_delete(outapp);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Zone Spawns Packet
|
||||
/* Zone Spawns Packet */
|
||||
entity_list.SendZoneSpawnsBulk(this);
|
||||
entity_list.SendZoneCorpsesBulk(this);
|
||||
entity_list.SendZonePVPUpdates(this); //hack until spawn struct is fixed.
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Time of Day packet
|
||||
/* Time of Day packet */
|
||||
outapp = new EQApplicationPacket(OP_TimeOfDay, sizeof(TimeOfDay_Struct));
|
||||
TimeOfDay_Struct* tod = (TimeOfDay_Struct*)outapp->pBuffer;
|
||||
zone->zone_time.getEQTimeOfDay(time(0), tod);
|
||||
outapp->priority = 6;
|
||||
FastQueuePacket(&outapp);
|
||||
//safe_delete(outapp);
|
||||
|
||||
//I think this should happen earlier, not sure
|
||||
/* if(GetHideMe())
|
||||
SetHideMe(true); */
|
||||
// Moved to Handle_Connect_OP_SendExpZonein();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Tribute Packets
|
||||
/* Tribute Packets */
|
||||
DoTributeUpdate();
|
||||
if(m_pp.tribute_active) {
|
||||
//restart the tribute timer where we left off
|
||||
tribute_timer.Start(m_pp.tribute_time_remaining);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Character Inventory Packet
|
||||
//this is not quite where live sends inventory, they do it after tribute
|
||||
/*
|
||||
Character Inventory Packet
|
||||
this is not quite where live sends inventory, they do it after tribute
|
||||
*/
|
||||
if (loaditems) { //dont load if a length error occurs
|
||||
BulkSendInventoryItems();
|
||||
|
||||
@ -9241,9 +9230,7 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Task Packets
|
||||
/* Task Packets */
|
||||
LoadClientTaskState();
|
||||
|
||||
if (GetClientVersion() >= EQClientRoF)
|
||||
@ -9261,10 +9248,11 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Weather Packet
|
||||
// This shouldent be moved, this seems to be what the client
|
||||
// uses to advance to the next state (sending ReqNewZone)
|
||||
/*
|
||||
Weather Packet
|
||||
This shouldent be moved, this seems to be what the client
|
||||
uses to advance to the next state (sending ReqNewZone)
|
||||
*/
|
||||
outapp = new EQApplicationPacket(OP_Weather, 12);
|
||||
Weather_Struct *ws = (Weather_Struct *) outapp->pBuffer;
|
||||
ws->val1 = 0x000000FF;
|
||||
@ -9279,16 +9267,6 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
|
||||
//////////////////////////////////////
|
||||
// Group Roles
|
||||
//
|
||||
//////////////////////////////////////
|
||||
/*if(group){
|
||||
group->NotifyMainTank(this, 1);
|
||||
group->NotifyMainAssist(this, 1);
|
||||
group->NotifyPuller(this, 1);
|
||||
}*/
|
||||
|
||||
SetAttackTimer();
|
||||
|
||||
conn_state = ZoneInfoSent;
|
||||
@ -9296,9 +9274,8 @@ bool Client::FinishConnState2(DBAsyncWork* dbaw) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finish client connecting state
|
||||
void Client::CompleteConnect()
|
||||
{
|
||||
/* Finish client connecting state */
|
||||
void Client::CompleteConnect() {
|
||||
UpdateWho();
|
||||
client_state = CLIENT_CONNECTED;
|
||||
|
||||
@ -9311,7 +9288,7 @@ void Client::CompleteConnect()
|
||||
EnteringMessages(this);
|
||||
LoadZoneFlags();
|
||||
|
||||
// Sets GM Flag if needed & Sends Petition Queue
|
||||
/* Sets GM Flag if needed & Sends Petition Queue */
|
||||
UpdateAdmin(false);
|
||||
|
||||
if (IsInAGuild()){
|
||||
@ -9344,9 +9321,11 @@ void Client::CompleteConnect()
|
||||
raid->LearnMembers();
|
||||
raid->VerifyRaid();
|
||||
raid->GetRaidDetails();
|
||||
//only leader should get this; send to all for now till
|
||||
//I figure out correct creation; can probably also send a no longer leader packet for non leaders
|
||||
//but not important for now.
|
||||
/*
|
||||
Only leader should get this; send to all for now till
|
||||
I figure out correct creation; can probably also send a no longer leader packet for non leaders
|
||||
but not important for now.
|
||||
*/
|
||||
raid->SendRaidCreate(this);
|
||||
raid->SendMakeLeaderPacketTo(raid->leadername, this);
|
||||
raid->SendRaidAdd(GetName(), this);
|
||||
@ -9463,7 +9442,8 @@ void Client::CompleteConnect()
|
||||
BuffFadeByEffect(SE_Levitate);
|
||||
Message(13, "You can't levitate in this zone.");
|
||||
}
|
||||
}else{
|
||||
}
|
||||
else{
|
||||
SendAppearancePacket(AT_Levitate, 2);
|
||||
}
|
||||
break;
|
||||
@ -9499,10 +9479,10 @@ void Client::CompleteConnect()
|
||||
}
|
||||
}
|
||||
|
||||
//sends appearances for all mobs not doing anim_stand aka sitting, looting, playing dead
|
||||
/* Sends appearances for all mobs not doing anim_stand aka sitting, looting, playing dead */
|
||||
entity_list.SendZoneAppearance(this);
|
||||
|
||||
//sends the Nimbus particle effects (up to 3) for any mob using them
|
||||
/* Sends the Nimbus particle effects (up to 3) for any mob using them */
|
||||
entity_list.SendNimbusEffects(this);
|
||||
|
||||
entity_list.SendUntargetable(this);
|
||||
@ -9546,41 +9526,40 @@ void Client::CompleteConnect()
|
||||
zone->weatherSend();
|
||||
|
||||
TotalKarma = database.GetKarma(AccountID());
|
||||
|
||||
SendDisciplineTimers();
|
||||
|
||||
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
|
||||
|
||||
//This sub event is for if a player logs in for the first time since entering world.
|
||||
if(firstlogon == 1)
|
||||
/* This sub event is for if a player logs in for the first time since entering world. */
|
||||
if (firstlogon == 1){
|
||||
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
|
||||
/* QS: PlayerLogConnectDisconnect */
|
||||
if (RuleB(QueryServ, PlayerLogConnectDisconnect)){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if(zone)
|
||||
{
|
||||
if(zone->GetInstanceTimer())
|
||||
{
|
||||
if(zone) {
|
||||
if(zone->GetInstanceTimer()) {
|
||||
uint32 ttime = zone->GetInstanceTimer()->GetRemainingTime();
|
||||
uint32 day = (ttime/86400000);
|
||||
uint32 hour = (ttime/3600000)%24;
|
||||
uint32 minute = (ttime/60000)%60;
|
||||
uint32 second = (ttime/1000)%60;
|
||||
if(day)
|
||||
{
|
||||
if(day) {
|
||||
Message(15, "%s(%u) will expire in %u days, %u hours, %u minutes, and %u seconds.",
|
||||
zone->GetLongName(), zone->GetInstanceID(), day, hour, minute, second);
|
||||
}
|
||||
else if(hour)
|
||||
{
|
||||
else if(hour) {
|
||||
Message(15, "%s(%u) will expire in %u hours, %u minutes, and %u seconds.",
|
||||
zone->GetLongName(), zone->GetInstanceID(), hour, minute, second);
|
||||
}
|
||||
else if(minute)
|
||||
{
|
||||
else if(minute) {
|
||||
Message(15, "%s(%u) will expire in %u minutes, and %u seconds.",
|
||||
zone->GetLongName(), zone->GetInstanceID(), minute, second);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
Message(15, "%s(%u) will expire in in %u seconds.",
|
||||
zone->GetLongName(), zone->GetInstanceID(), second);
|
||||
}
|
||||
@ -9603,8 +9582,7 @@ void Client::CompleteConnect()
|
||||
if(GetClientVersion() >= EQClientSoD)
|
||||
entity_list.SendFindableNPCList(this);
|
||||
|
||||
if(IsInAGuild())
|
||||
{
|
||||
if(IsInAGuild()) {
|
||||
SendGuildRanks();
|
||||
guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), zone->GetZoneID(), time(nullptr));
|
||||
guild_mgr.RequestOnlineGuildMembers(this->CharacterID(), this->GuildID());
|
||||
@ -9616,8 +9594,7 @@ void Client::CompleteConnect()
|
||||
worldserver.SendPacket(pack);
|
||||
delete pack;
|
||||
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater)
|
||||
{
|
||||
if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_UnderfootAndLater) {
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
}
|
||||
@ -12749,6 +12726,12 @@ void Client::Handle_OP_AltCurrencyPurchase(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Merchant Purchase */
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Merchant Purchase :: Spent alt_currency_id:%i cost:%i for itemid:%i in zoneid:%i instid:%i", alt_cur_id, cost, item->ID, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
AddAlternateCurrencyValue(alt_cur_id, -((int32)cost));
|
||||
int16 charges = 1;
|
||||
if(item->MaxCharges != 0)
|
||||
@ -12780,20 +12763,37 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(reclaim->reclaim_flag == 1) { //item -> altcur
|
||||
/* Item to Currency Storage */
|
||||
if(reclaim->reclaim_flag == 1) {
|
||||
uint32 removed = NukeItem(item_id, invWhereWorn | invWherePersonal | invWhereCursor);
|
||||
if(removed > 0) {
|
||||
AddAlternateCurrencyValue(reclaim->currency_id, removed);
|
||||
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Item to Currency */
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Reclaim :: Item to Currency :: alt_currency_id:%i amount:%i to currency tab in zoneid:%i instid:%i", reclaim->currency_id, removed, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
/* Cursor to Item storage */
|
||||
else {
|
||||
uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id);
|
||||
|
||||
/* If you input more than you have currency wise, just give the max of the currency you currently have */
|
||||
if(reclaim->count > max_currency) {
|
||||
SummonItem(item_id, max_currency);
|
||||
SetAlternateCurrencyValue(reclaim->currency_id, 0);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
SummonItem(item_id, reclaim->count, 0, 0, 0, 0, 0, false, MainCursor);
|
||||
AddAlternateCurrencyValue(reclaim->currency_id, -((int32)reclaim->count));
|
||||
}
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Cursor to Item Storage */
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Reclaim :: Cursor to Item :: alt_currency_id:%i amount:-%i in zoneid:%i instid:%i", reclaim->currency_id, reclaim->count, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12829,6 +12829,7 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) {
|
||||
uint32 cost = 0;
|
||||
uint32 current_currency = GetAlternateCurrencyValue(alt_cur_id);
|
||||
uint32 merchant_id = tar->MerchantType;
|
||||
uint32 npc_id = tar->GetNPCTypeID();
|
||||
bool found = false;
|
||||
std::list<MerchantList> merlist = zone->merchanttable[merchant_id];
|
||||
std::list<MerchantList>::const_iterator itr;
|
||||
@ -12881,6 +12882,12 @@ void Client::Handle_OP_AltCurrencySell(const EQApplicationPacket *app) {
|
||||
|
||||
sell->cost = cost;
|
||||
|
||||
/* QS: PlayerLogAlternateCurrencyTransactions :: Sold to Merchant*/
|
||||
if (RuleB(QueryServ, PlayerLogAlternateCurrencyTransactions)){
|
||||
std::string event_desc = StringFormat("Sold to Merchant :: itemid:%u npcid:%u alt_currency_id:%u cost:%u in zoneid:%u instid:%i", item->ID, npc_id, alt_cur_id, cost, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Alternate_Currency_Transactions, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
FastQueuePacket(&outapp);
|
||||
AddAlternateCurrencyValue(alt_cur_id, cost);
|
||||
Save(1);
|
||||
|
||||
@ -63,7 +63,9 @@
|
||||
#include "guild_mgr.h"
|
||||
#include <string>
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern Zone* zone;
|
||||
extern volatile bool ZoneLoaded;
|
||||
extern WorldServer worldserver;
|
||||
@ -770,38 +772,40 @@ bool Client::Process() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//just a set of actions preformed all over in Client::Process
|
||||
/* Just a set of actions preformed all over in Client::Process */
|
||||
void Client::OnDisconnect(bool hard_disconnect) {
|
||||
if(hard_disconnect) {
|
||||
LeaveGroup();
|
||||
|
||||
Raid *MyRaid = entity_list.GetRaidByClient(this);
|
||||
|
||||
if (MyRaid)
|
||||
MyRaid->MemberZoned(this);
|
||||
|
||||
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
|
||||
|
||||
/* QS: PlayerLogConnectDisconnect */
|
||||
if (RuleB(QueryServ, PlayerLogConnectDisconnect)){
|
||||
std::string event_desc = StringFormat("Disconnect :: in zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
Mob *Other = trade->With();
|
||||
|
||||
if(Other)
|
||||
{
|
||||
if(Other) {
|
||||
mlog(TRADING__CLIENT, "Client disconnected during a trade. Returning their items.");
|
||||
|
||||
FinishTrade(this);
|
||||
|
||||
if(Other->IsClient())
|
||||
Other->CastToClient()->FinishTrade(Other);
|
||||
|
||||
/* Reset both sides of the trade */
|
||||
trade->Reset();
|
||||
|
||||
Other->trade->Reset();
|
||||
}
|
||||
|
||||
database.SetFirstLogon(CharacterID(), 0); //We change firstlogon status regardless of if a player logs out to zone or not, because we only want to trigger it on their first login from world.
|
||||
|
||||
//remove ourself from all proximities
|
||||
/* Remove ourself from all proximities */
|
||||
ClearAllProximities();
|
||||
|
||||
EQApplicationPacket *outapp = new EQApplicationPacket(OP_LogoutReply);
|
||||
|
||||
@ -62,8 +62,9 @@
|
||||
#include "guild_mgr.h"
|
||||
#include "titles.h"
|
||||
#include "../common/patches/patches.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
// these should be in the headers...
|
||||
extern QueryServ* QServ;
|
||||
extern WorldServer worldserver;
|
||||
extern TaskManager *taskmanager;
|
||||
void CatchSignal(int sig_num);
|
||||
@ -588,6 +589,12 @@ int command_realdispatch(Client *c, const char *message)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* QS: Player_Log_Issued_Commands */
|
||||
if (RuleB(QueryServ, PlayerLogIssuedCommandes)){
|
||||
std::string event_desc = StringFormat("Issued command :: '%s' in zoneid:%i instid:%i", message, c->GetZoneID(), c->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Issued_Commands, c->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
#ifdef COMMANDS_LOGGING
|
||||
if(cur->access >= COMMANDS_LOGGING_MIN_STATUS) {
|
||||
LogFile->write(EQEMuLog::Commands, "%s (%s) used command: %s (target=%s)", c->GetName(), c->AccountName(), message, c->GetTarget()?c->GetTarget()->GetName():"NONE");
|
||||
|
||||
@ -127,7 +127,8 @@ enum {
|
||||
FLEE_PERCENT = 37,
|
||||
ALLOW_BENEFICIAL = 38,
|
||||
DISABLE_MELEE = 39,
|
||||
MAX_SPECIAL_ATTACK = 40
|
||||
NPC_CHASE_DISTANCE = 40,
|
||||
MAX_SPECIAL_ATTACK = 41
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -28,8 +28,10 @@
|
||||
#include "embxs.h"
|
||||
#include "entity.h"
|
||||
#include "zone.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern Zone* zone;
|
||||
extern QueryServ* QServ;
|
||||
|
||||
/*
|
||||
|
||||
@ -3370,6 +3372,36 @@ XS(XS__clear_npctype_cache)
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__qs_send_query);
|
||||
XS(XS__qs_send_query)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1){
|
||||
Perl_croak(aTHX_ "Usage: qs_send_query(query)");
|
||||
}
|
||||
else{
|
||||
// char *Query = (char *)SvPV_nolen(ST(0));
|
||||
std::string Query = (std::string)SvPV_nolen(ST(0));
|
||||
QServ->SendQuery(Query);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__qs_player_event);
|
||||
XS(XS__qs_player_event)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2){
|
||||
Perl_croak(aTHX_ "Usage: qs_player_event(char_id, event_desc)");
|
||||
}
|
||||
else{
|
||||
int char_id = (int)SvIV(ST(0));
|
||||
std::string event_desc = (std::string)SvPV_nolen(ST(1));
|
||||
QServ->PlayerLogEvent(Player_Log_Quest, char_id, event_desc);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the callback perl will look for to setup the
|
||||
quest package's XSUBs
|
||||
@ -3591,6 +3623,8 @@ EXTERN_C XS(boot_quest)
|
||||
newXS(strcpy(buf, "enablerecipe"), XS__enablerecipe, file);
|
||||
newXS(strcpy(buf, "disablerecipe"), XS__disablerecipe, file);
|
||||
newXS(strcpy(buf, "clear_npctype_cache"), XS__clear_npctype_cache, file);
|
||||
newXS(strcpy(buf, "qs_send_query"), XS__qs_send_query, file);
|
||||
newXS(strcpy(buf, "qs_player_event"), XS__qs_player_event, file);
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -4170,6 +4170,20 @@ void EntityList::SignalAllClients(uint32 data)
|
||||
}
|
||||
}
|
||||
|
||||
uint16 EntityList::GetClientCount(){
|
||||
uint16 ClientCount = 0;
|
||||
std::list<Client*> client_list;
|
||||
entity_list.GetClientList(client_list);
|
||||
std::list<Client*>::iterator iter = client_list.begin();
|
||||
while (iter != client_list.end()) {
|
||||
Client *entry = (*iter);
|
||||
entry->GetCleanName();
|
||||
ClientCount++;
|
||||
iter++;
|
||||
}
|
||||
return ClientCount;
|
||||
}
|
||||
|
||||
void EntityList::GetMobList(std::list<Mob *> &m_list)
|
||||
{
|
||||
m_list.clear();
|
||||
|
||||
@ -398,6 +398,7 @@ public:
|
||||
void UpdateFindableNPCState(NPC *n, bool Remove);
|
||||
void HideCorpses(Client *c, uint8 CurrentMode, uint8 NewMode);
|
||||
|
||||
uint16 GetClientCount();
|
||||
void GetMobList(std::list<Mob*> &m_list);
|
||||
void GetNPCList(std::list<NPC*> &n_list);
|
||||
void GetMercList(std::list<Merc*> &n_list);
|
||||
|
||||
83
zone/exp.cpp
83
zone/exp.cpp
@ -22,6 +22,9 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
|
||||
|
||||
static uint32 MaxBankedGroupLeadershipPoints(int Level)
|
||||
@ -212,7 +215,6 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
return; // Must be invalid class/race
|
||||
}
|
||||
|
||||
|
||||
if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) {
|
||||
if (isrezzexp)
|
||||
this->Message_StringID(MT_Experience, REZ_REGAIN);
|
||||
@ -288,6 +290,14 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
//Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
|
||||
char val1[20]={0};
|
||||
Message_StringID(MT_Experience, GAIN_ABILITY_POINT,ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
|
||||
|
||||
/* QS: PlayerLogAARate */
|
||||
if (RuleB(QueryServ, PlayerLogAARate)){
|
||||
int add_points = (m_pp.aapoints - last_unspentAA);
|
||||
std::string query = StringFormat("INSERT INTO `qs_player_aa_rate_hourly` (char_id, aa_count, hour_time) VALUES (%i, %i, UNIX_TIMESTAMP() - MOD(UNIX_TIMESTAMP(), 3600)) ON DUPLICATE KEY UPDATE `aa_count` = `aa_count` + %i", this->CharacterID(), add_points, add_points);
|
||||
QServ->SendQuery(query.c_str());
|
||||
}
|
||||
|
||||
//Message(15, "You now have %d skill points available to spend.", m_pp.aapoints);
|
||||
}
|
||||
|
||||
@ -299,12 +309,10 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
if(check_level > maxlevel) {
|
||||
check_level = maxlevel;
|
||||
|
||||
if(RuleB(Character, KeepLevelOverMax))
|
||||
{
|
||||
if(RuleB(Character, KeepLevelOverMax)) {
|
||||
set_exp = GetEXPForLevel(GetLevel()+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
set_exp = GetEXPForLevel(maxlevel);
|
||||
}
|
||||
}
|
||||
@ -314,8 +322,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
if(MaxLevel){
|
||||
if(GetLevel() >= MaxLevel){
|
||||
uint32 expneeded = GetEXPForLevel(MaxLevel);
|
||||
if(set_exp > expneeded)
|
||||
{
|
||||
if(set_exp > expneeded) {
|
||||
set_exp = expneeded;
|
||||
}
|
||||
}
|
||||
@ -327,11 +334,11 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
if (GetLevel() == check_level-1){
|
||||
Message_StringID(MT_Experience, GAIN_LEVEL,ConvertArray(check_level,val1));
|
||||
SendLevelAppearance();
|
||||
//Message(15, "You have gained a level! Welcome to level %i!", check_level);
|
||||
/* Message(15, "You have gained a level! Welcome to level %i!", check_level); */
|
||||
}
|
||||
if (GetLevel() == check_level){
|
||||
Message_StringID(MT_Experience, LOSE_LEVEL,ConvertArray(check_level,val1));
|
||||
//Message(15, "You lost a level! You are now level %i!", check_level);
|
||||
/* Message(15, "You lost a level! You are now level %i!", check_level); */
|
||||
}
|
||||
else
|
||||
Message(15, "Welcome to level %i!", check_level);
|
||||
@ -352,8 +359,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
|
||||
//If were at max level then stop gaining experience if we make it to the cap
|
||||
if(GetLevel() == maxlevel - 1){
|
||||
uint32 expneeded = GetEXPForLevel(maxlevel);
|
||||
if(set_exp > expneeded)
|
||||
{
|
||||
if(set_exp > expneeded) {
|
||||
set_exp = expneeded;
|
||||
}
|
||||
}
|
||||
@ -405,15 +411,13 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
|
||||
level = set_level;
|
||||
|
||||
if(IsRaidGrouped())
|
||||
{
|
||||
if(IsRaidGrouped()) {
|
||||
Raid *r = this->GetRaid();
|
||||
if(r){
|
||||
r->UpdateLevel(GetName(), set_level);
|
||||
}
|
||||
}
|
||||
if(set_level > m_pp.level2)
|
||||
{
|
||||
if(set_level > m_pp.level2) {
|
||||
if(m_pp.level2 == 0)
|
||||
m_pp.points += 5;
|
||||
else
|
||||
@ -423,6 +427,18 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
}
|
||||
if(set_level > m_pp.level) {
|
||||
parse->EventPlayer(EVENT_LEVEL_UP, this, "", 0);
|
||||
/* QS: PlayerLogLevels */
|
||||
if (RuleB(QueryServ, PlayerLogLevels)){
|
||||
std::string event_desc = StringFormat("Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
else if (set_level < m_pp.level){
|
||||
/* QS: PlayerLogLevels */
|
||||
if (RuleB(QueryServ, PlayerLogLevels)){
|
||||
std::string event_desc = StringFormat("Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i", set_level, m_pp.level, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Levels, this->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
m_pp.level = set_level;
|
||||
@ -432,8 +448,7 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
lu->exp = 0;
|
||||
}
|
||||
else {
|
||||
float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) /
|
||||
( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
|
||||
float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel()));
|
||||
lu->exp = (uint32)(330.0f * tmpxp);
|
||||
}
|
||||
QueuePacket(outapp);
|
||||
@ -443,14 +458,13 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level);
|
||||
|
||||
CalcBonuses();
|
||||
if(!RuleB(Character, HealOnLevel))
|
||||
{
|
||||
|
||||
if(!RuleB(Character, HealOnLevel)) {
|
||||
int mhp = CalcMaxHP();
|
||||
if(GetHP() > mhp)
|
||||
SetHP(mhp);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
SetHP(CalcMaxHP()); // Why not, lets give them a free heal
|
||||
}
|
||||
|
||||
@ -458,8 +472,10 @@ void Client::SetLevel(uint8 set_level, bool command)
|
||||
SendHPUpdate();
|
||||
SetMana(CalcMaxMana());
|
||||
UpdateWho();
|
||||
|
||||
if(GetMerc())
|
||||
UpdateMercLevel();
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
@ -508,23 +524,13 @@ uint32 Client::GetEXPForLevel(uint16 check_level)
|
||||
uint32 finalxp = uint32(base * mod);
|
||||
finalxp = mod_client_xp_for_level(finalxp, check_level);
|
||||
|
||||
return(finalxp);
|
||||
return finalxp;
|
||||
}
|
||||
|
||||
void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) {
|
||||
|
||||
if (exp_percentage > 100)
|
||||
{
|
||||
exp_percentage = 100;
|
||||
}
|
||||
|
||||
if (!max_level || GetLevel() < max_level)
|
||||
{
|
||||
max_level = GetLevel();
|
||||
}
|
||||
|
||||
if (exp_percentage > 100) { exp_percentage = 100; }
|
||||
if (!max_level || GetLevel() < max_level) { max_level = GetLevel(); }
|
||||
uint32 newexp = GetEXP() + ((GetEXPForLevel(max_level + 1) - GetEXPForLevel(max_level)) * exp_percentage / 100);
|
||||
|
||||
SetEXP(newexp, GetAAXP());
|
||||
}
|
||||
|
||||
@ -666,22 +672,19 @@ void Client::SendLeadershipEXPUpdate() {
|
||||
}
|
||||
|
||||
uint32 Client::GetCharMaxLevelFromQGlobal() {
|
||||
|
||||
QGlobalCache *char_c = nullptr;
|
||||
char_c = this->GetQGlobals();
|
||||
|
||||
std::list<QGlobal> globalMap;
|
||||
uint32 ntype = 0;
|
||||
|
||||
if(char_c)
|
||||
{
|
||||
if(char_c) {
|
||||
QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, this->CharacterID(), zone->GetZoneID());
|
||||
}
|
||||
|
||||
std::list<QGlobal>::iterator iter = globalMap.begin();
|
||||
uint32 gcount = 0;
|
||||
while(iter != globalMap.end())
|
||||
{
|
||||
while(iter != globalMap.end()) {
|
||||
if((*iter).name.compare("CharMaxLevel") == 0){
|
||||
return atoi((*iter).value.c_str());
|
||||
}
|
||||
@ -689,5 +692,5 @@ uint32 Client::GetCharMaxLevelFromQGlobal() {
|
||||
++gcount;
|
||||
}
|
||||
|
||||
return false; // Default is false
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -196,7 +196,6 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu
|
||||
Client *c = members[i]->CastToClient();
|
||||
//I could not get MoneyOnCorpse to work, so we use this
|
||||
c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true);
|
||||
|
||||
c->Message(2, msg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1134,7 +1134,7 @@ void Lua_Client::Signal(uint32 id) {
|
||||
|
||||
void Lua_Client::AddAlternateCurrencyValue(uint32 currency, int amount) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->AddAlternateCurrencyValue(currency, amount);
|
||||
self->AddAlternateCurrencyValue(currency, amount, 1);
|
||||
}
|
||||
|
||||
void Lua_Client::SendWebLink(const char *site) {
|
||||
|
||||
@ -183,6 +183,7 @@ Mob::Mob(const char* in_name,
|
||||
has_MGB = false;
|
||||
has_ProjectIllusion = false;
|
||||
SpellPowerDistanceMod = 0;
|
||||
last_los_check = false;
|
||||
|
||||
if(in_aa_title>0)
|
||||
aa_title = in_aa_title;
|
||||
@ -341,6 +342,7 @@ Mob::Mob(const char* in_name,
|
||||
viral_spells[i] = 0;
|
||||
}
|
||||
pStandingPetOrder = SPO_Follow;
|
||||
pseudo_rooted = false;
|
||||
|
||||
see_invis = in_see_invis;
|
||||
see_invis_undead = in_see_invis_undead != 0;
|
||||
|
||||
@ -464,6 +464,8 @@ public:
|
||||
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
|
||||
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
|
||||
inline const uint32 LastChange() const { return pLastChange; }
|
||||
inline void SetLastLosState(bool value) { last_los_check = value; }
|
||||
inline bool CheckLastLosState() const { return last_los_check; }
|
||||
|
||||
//Quest
|
||||
void QuestReward(Client *c = nullptr, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0);
|
||||
@ -752,7 +754,8 @@ public:
|
||||
inline const bool IsRooted() const { return rooted || permarooted; }
|
||||
inline const bool HasVirus() const { return has_virus; }
|
||||
int GetSnaredAmount();
|
||||
|
||||
inline const bool IsPseudoRooted() const { return pseudo_rooted; }
|
||||
inline void SetPseudoRoot(bool prState) { pseudo_rooted = prState; }
|
||||
|
||||
int GetCurWp() { return cur_wp; }
|
||||
|
||||
@ -1119,6 +1122,8 @@ protected:
|
||||
bool has_MGB;
|
||||
bool has_ProjectIllusion;
|
||||
int16 SpellPowerDistanceMod;
|
||||
bool last_los_check;
|
||||
bool pseudo_rooted;
|
||||
|
||||
// Bind wound
|
||||
Timer bindwound_timer;
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#include "worldserver.h"
|
||||
#include "net.h"
|
||||
#include "zone.h"
|
||||
#include "queryserv.h"
|
||||
#include "command.h"
|
||||
#include "zone_config.h"
|
||||
#include "titles.h"
|
||||
@ -98,6 +99,7 @@ npcDecayTimes_Struct npcCorpseDecayTimes[100];
|
||||
TitleManager title_manager;
|
||||
DBAsyncFinishedQueue MTdbafq;
|
||||
DBAsync *dbasync = nullptr;
|
||||
QueryServ *QServ = 0;
|
||||
TaskManager *taskmanager = 0;
|
||||
QuestParserCollection *parse = 0;
|
||||
|
||||
@ -114,6 +116,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
const char *zone_name;
|
||||
|
||||
QServ = new QueryServ;
|
||||
|
||||
if(argc == 3) {
|
||||
worldserver.SetLauncherName(argv[2]);
|
||||
worldserver.SetLaunchedName(argv[1]);
|
||||
@ -622,7 +626,7 @@ void LoadSpells(EQEmu::MemoryMappedFile **mmf) {
|
||||
SPDAT_RECORDS = records;
|
||||
}
|
||||
|
||||
|
||||
/* Update Window Title with relevant information */
|
||||
void UpdateWindowTitle(char* iNewTitle) {
|
||||
#ifdef _WINDOWS
|
||||
char tmp[500];
|
||||
@ -634,7 +638,7 @@ void UpdateWindowTitle(char* iNewTitle) {
|
||||
#if defined(GOTFRAGS) || defined(_EQDEBUG)
|
||||
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid());
|
||||
#else
|
||||
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients);
|
||||
snprintf(tmp, sizeof(tmp), "%s :: clients: %i inst_id: %i inst_ver: %i :: port: %i", zone->GetShortName(), numclients, zone->GetInstanceID(), zone->GetInstanceVersion(), ZoneConfig::get()->ZonePort);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
|
||||
@ -1321,6 +1321,8 @@ XS(XS_Client_MovePCInstance)
|
||||
_log(CLIENT__ERROR, "Perl(XS_Client_MovePCInstance) attempted to process an Unknown type reference");
|
||||
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
}
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
|
||||
@ -300,8 +300,6 @@ void ZoneDatabase::RefreshPetitionsFromDB()
|
||||
newpet->SetSentTime2(atol(row[13]));
|
||||
newpet->SetGMText(row[14]);
|
||||
|
||||
std::cout << "Petition " << row[0] << " pettime = " << newpet->GetSentTime() << std::endl;
|
||||
|
||||
if (atoi(row[12]) == 1)
|
||||
newpet->SetCheckedOut(true);
|
||||
else
|
||||
|
||||
52
zone/queryserv.cpp
Normal file
52
zone/queryserv.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "../common/debug.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "queryserv.h"
|
||||
#include "worldserver.h"
|
||||
#include "net.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
extern WorldServer worldserver;
|
||||
extern QueryServ* QServ;
|
||||
|
||||
QueryServ::QueryServ(){
|
||||
}
|
||||
|
||||
QueryServ::~QueryServ(){
|
||||
}
|
||||
|
||||
void QueryServ::SendQuery(std::string Query)
|
||||
{
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_QSSendQuery, Query.length() + 5);
|
||||
pack->WriteUInt32(Query.length()); /* Pack Query String Size so it can be dynamically broken out at queryserv */
|
||||
pack->WriteString(Query.c_str()); /* Query */
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void QueryServ::PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"INSERT INTO `qs_player_events` (event, char_id, event_desc, time) VALUES (%i, %i, '%s', UNIX_TIMESTAMP(now()))",
|
||||
Event_Type, Character_ID, EscapeString(Event_Desc.c_str()).c_str());
|
||||
SendQuery(query);
|
||||
}
|
||||
35
zone/queryserv.h
Normal file
35
zone/queryserv.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef QUERYSERV_ZONE_H
|
||||
#define QUERYSERV_ZONE_H
|
||||
|
||||
|
||||
/*
|
||||
enum PlayerGenericLogEventTypes
|
||||
These Enums are for the generic logging table that are not complex and require more advanced logic
|
||||
*/
|
||||
|
||||
enum PlayerGenericLogEventTypes {
|
||||
Player_Log_Quest = 1,
|
||||
Player_Log_Zoning,
|
||||
Player_Log_Deaths,
|
||||
Player_Log_Connect_State,
|
||||
Player_Log_Levels,
|
||||
Player_Log_Keyring_Addition,
|
||||
Player_Log_QGlobal_Update,
|
||||
Player_Log_Task_Updates,
|
||||
Player_Log_AA_Purchases,
|
||||
Player_Log_Trade_Skill_Events,
|
||||
Player_Log_Issued_Commands,
|
||||
Player_Log_Money_Transactions,
|
||||
Player_Log_Alternate_Currency_Transactions,
|
||||
};
|
||||
|
||||
|
||||
class QueryServ{
|
||||
public:
|
||||
QueryServ();
|
||||
~QueryServ();
|
||||
void SendQuery(std::string Query);
|
||||
void PlayerLogEvent(int Event_Type, int Character_ID, std::string Event_Desc);
|
||||
};
|
||||
|
||||
#endif /* QUERYSERV_ZONE_H */
|
||||
@ -75,12 +75,12 @@ And then at then end of embparser.cpp, add:
|
||||
#include "../common/rulesys.h"
|
||||
#include "qglobals.h"
|
||||
#include "quest_parser_collection.h"
|
||||
|
||||
#include "queryserv.h"
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern Zone* zone;
|
||||
extern WorldServer worldserver;
|
||||
extern EntityList entity_list;
|
||||
@ -173,7 +173,6 @@ void QuestManager::EndQuest() {
|
||||
else
|
||||
++cur;
|
||||
}
|
||||
|
||||
run.owner->Depop();
|
||||
}
|
||||
quests_running_.pop();
|
||||
@ -1306,21 +1305,17 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti
|
||||
6 this all all
|
||||
7 all all all
|
||||
*/
|
||||
if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved
|
||||
{
|
||||
|
||||
if (initiator && initiator->IsClient()){ // some events like waypoint and spawn don't have a player involved
|
||||
qgCharid=initiator->CharacterID();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
else {
|
||||
qgCharid=-qgNpcid; // make char id negative npc id as a fudge
|
||||
}
|
||||
if (options < 0 || options > 7)
|
||||
{
|
||||
if (options < 0 || options > 7) {
|
||||
std::cerr << "Invalid options for global var " << varname << " using defaults" << std::endl;
|
||||
} // default = 0 (only this npcid,player and zone)
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (options & 1)
|
||||
qgNpcid=0;
|
||||
if (options & 2)
|
||||
@ -1330,30 +1325,32 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti
|
||||
}
|
||||
|
||||
InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration));
|
||||
|
||||
/* QS: PlayerLogQGlobalUpdate */
|
||||
if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){
|
||||
std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Inserts global variable into quest_globals table */
|
||||
int QuestManager::InsertQuestGlobal(
|
||||
int charid, int npcid, int zoneid,
|
||||
const char *varname, const char *varvalue,
|
||||
int duration)
|
||||
{
|
||||
int QuestManager::InsertQuestGlobal(int charid, int npcid, int zoneid, const char *varname, const char *varvalue, int duration) {
|
||||
char *query = 0;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
|
||||
// Make duration string either "unix_timestamp(now()) + xxx" or "NULL"
|
||||
std::stringstream duration_ss;
|
||||
if (duration == INT_MAX)
|
||||
{
|
||||
if (duration == INT_MAX) {
|
||||
duration_ss << "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
duration_ss << "unix_timestamp(now()) + " << duration;
|
||||
}
|
||||
|
||||
//NOTE: this should be escaping the contents of arglist
|
||||
//npcwise a malicious script can arbitrarily alter the DB
|
||||
/*
|
||||
NOTE: this should be escaping the contents of arglist
|
||||
npcwise a malicious script can arbitrarily alter the DB
|
||||
*/
|
||||
uint32 last_id = 0;
|
||||
if (!database.RunQuery(query, MakeAnyLenString(&query,
|
||||
"REPLACE INTO quest_globals (charid, npcid, zoneid, name, value, expdate)"
|
||||
@ -1365,9 +1362,8 @@ int QuestManager::InsertQuestGlobal(
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
if(zone)
|
||||
{
|
||||
//first delete our global
|
||||
if(zone) {
|
||||
/* Delete existing qglobal data and update zone processes */
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
|
||||
ServerQGlobalDelete_Struct *qgd = (ServerQGlobalDelete_Struct*)pack->pBuffer;
|
||||
qgd->npc_id = npcid;
|
||||
@ -1383,18 +1379,16 @@ int QuestManager::InsertQuestGlobal(
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
|
||||
//then create a new one with the new id
|
||||
/* Create new qglobal data and update zone processes */
|
||||
pack = new ServerPacket(ServerOP_QGlobalUpdate, sizeof(ServerQGlobalUpdate_Struct));
|
||||
ServerQGlobalUpdate_Struct *qgu = (ServerQGlobalUpdate_Struct*)pack->pBuffer;
|
||||
qgu->npc_id = npcid;
|
||||
qgu->char_id = charid;
|
||||
qgu->zone_id = zoneid;
|
||||
if(duration == INT_MAX)
|
||||
{
|
||||
if(duration == INT_MAX) {
|
||||
qgu->expdate = 0xFFFFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
qgu->expdate = Timer::GetTimeSeconds() + duration;
|
||||
}
|
||||
strcpy((char*)qgu->name, varname);
|
||||
@ -1420,8 +1414,7 @@ int QuestManager::InsertQuestGlobal(
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QuestManager::targlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid)
|
||||
{
|
||||
void QuestManager::targlobal(const char *varname, const char *value, const char *duration, int qgNpcid, int qgCharid, int qgZoneid) {
|
||||
InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, value, QGVarDuration(duration));
|
||||
}
|
||||
|
||||
@ -1432,15 +1425,24 @@ void QuestManager::delglobal(const char *varname) {
|
||||
int qgZoneid=zone->GetZoneID();
|
||||
int qgCharid=0;
|
||||
int qgNpcid=owner->GetNPCTypeID();
|
||||
|
||||
|
||||
|
||||
if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved
|
||||
{
|
||||
qgCharid=initiator->CharacterID();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
else {
|
||||
qgCharid=-qgNpcid; // make char id negative npc id as a fudge
|
||||
}
|
||||
|
||||
/* QS: PlayerLogQGlobalUpdate */
|
||||
if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){
|
||||
std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc);
|
||||
}
|
||||
|
||||
if (!database.RunQuery(query,
|
||||
MakeAnyLenString(&query,
|
||||
"DELETE FROM quest_globals WHERE name='%s'"
|
||||
@ -1451,8 +1453,7 @@ void QuestManager::delglobal(const char *varname) {
|
||||
}
|
||||
safe_delete_array(query);
|
||||
|
||||
if(zone)
|
||||
{
|
||||
if(zone) {
|
||||
ServerPacket* pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
|
||||
ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer;
|
||||
|
||||
@ -1701,17 +1702,14 @@ void QuestManager::showgrid(int grid) {
|
||||
pts.push_back(pt);
|
||||
|
||||
// Retrieve all waypoints for this grid
|
||||
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result))
|
||||
{
|
||||
while((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if(database.RunQuery(query,MakeAnyLenString(&query,"SELECT `x`,`y`,`z` FROM grid_entries WHERE `gridid`=%i AND `zoneid`=%i ORDER BY `number`",grid,zone->GetZoneID()),errbuf,&result)) {
|
||||
while((row = mysql_fetch_row(result))) {
|
||||
pt.x = atof(row[0]);
|
||||
pt.y = atof(row[1]);
|
||||
pt.z = atof(row[2]);
|
||||
pts.push_back(pt);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
|
||||
initiator->SendPathPacket(pts);
|
||||
}
|
||||
else // DB query error!
|
||||
|
||||
@ -28,8 +28,7 @@
|
||||
|
||||
extern EntityList entity_list;
|
||||
|
||||
SpawnEntry::SpawnEntry( uint32 in_NPCType, int in_chance, uint8 in_npc_spawn_limit )
|
||||
{
|
||||
SpawnEntry::SpawnEntry( uint32 in_NPCType, int in_chance, uint8 in_npc_spawn_limit ) {
|
||||
NPCType = in_NPCType;
|
||||
chance = in_chance;
|
||||
npc_spawn_limit = in_npc_spawn_limit;
|
||||
@ -57,7 +56,6 @@ uint32 SpawnGroup::GetNPCType() {
|
||||
int npcType = 0;
|
||||
int totalchance = 0;
|
||||
|
||||
//check limits on this spawn group and npc type
|
||||
if(!entity_list.LimitCheckGroup(id, group_spawn_limit))
|
||||
return(0);
|
||||
|
||||
@ -68,7 +66,6 @@ uint32 SpawnGroup::GetNPCType() {
|
||||
for(; cur != end; ++cur) {
|
||||
SpawnEntry *se = *cur;
|
||||
|
||||
//check limits on this spawn group and npc type
|
||||
if(!entity_list.LimitCheckType(se->NPCType, se->npc_spawn_limit))
|
||||
continue;
|
||||
|
||||
@ -93,7 +90,6 @@ uint32 SpawnGroup::GetNPCType() {
|
||||
roll -= se->chance;
|
||||
}
|
||||
}
|
||||
//CODER implement random table
|
||||
return npcType;
|
||||
}
|
||||
|
||||
@ -149,7 +145,6 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
// CODER new spawn code
|
||||
query = 0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT DISTINCT(spawngroupID), spawngroup.name, spawngroup.spawn_limit, spawngroup.dist, spawngroup.max_x, spawngroup.min_x, spawngroup.max_y, spawngroup.min_y, spawngroup.delay, spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay FROM spawn2,spawngroup WHERE spawn2.spawngroupID=spawngroup.ID and spawn2.version=%u and zone='%s'", version, zone_name), errbuf, &result))
|
||||
{
|
||||
@ -162,7 +157,7 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error2 in PopulateZoneLists query '" << query << "' " << errbuf << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query '%s' ", query);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
@ -182,18 +177,17 @@ bool ZoneDatabase::LoadSpawnGroups(const char* zone_name, uint16 version, SpawnG
|
||||
if (sg)
|
||||
sg->AddSpawnEntry(newSpawnEntry);
|
||||
else
|
||||
std::cout << "Error in SpawngroupID: " << row[0] << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error in LoadSpawnGroups %s ", query);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error3 in PopulateZoneLists query '" << query << "' " << errbuf << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query '%'", query);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
// CODER end new spawn code
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -203,8 +197,6 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
|
||||
// CODER new spawn code
|
||||
query = 0;
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT DISTINCT spawngroup.id, spawngroup.name, spawngroup.spawn_limit, spawngroup.dist, spawngroup.max_x, spawngroup.min_x, spawngroup.max_y, spawngroup.min_y, spawngroup.delay, spawngroup.despawn, spawngroup.despawn_timer, spawngroup.mindelay FROM spawngroup WHERE spawngroup.ID='%i'", spawngroupid), errbuf, &result))
|
||||
{
|
||||
@ -217,7 +209,7 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error2 in PopulateZoneLists query '" << query << "' " << errbuf << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error2 in PopulateZoneLists query %s", query);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
@ -233,17 +225,16 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawngroupid, SpawnGroupList* spawn_g
|
||||
if (sg)
|
||||
sg->AddSpawnEntry(newSpawnEntry);
|
||||
else
|
||||
std::cout << "Error in SpawngroupID: " << row[0] << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error in SpawngroupID: %s ", row[0]);
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error3 in PopulateZoneLists query '" << query << "' " << errbuf << std::endl;
|
||||
_log(ZONE__SPAWNS, "Error3 in PopulateZoneLists query '%s'", row[0]);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
// CODER end new spawn code
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -28,8 +28,6 @@
|
||||
#include "../common/rulesys.h"
|
||||
|
||||
|
||||
|
||||
|
||||
int Mob::GetKickDamage() {
|
||||
int multiple=(GetLevel()*100/5);
|
||||
multiple += 100;
|
||||
@ -64,11 +62,9 @@ int Mob::GetBashDamage() {
|
||||
}
|
||||
|
||||
void Mob::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) {
|
||||
|
||||
int item_slot = -1;
|
||||
//1: Apply bonus from AC (BOOT/SHIELD/HANDS) est. 40AC=6dmg
|
||||
if (IsClient()){
|
||||
|
||||
switch (skill){
|
||||
|
||||
case SkillFlyingKick:
|
||||
@ -112,10 +108,8 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if(hate_override > -1)
|
||||
hate = hate_override;
|
||||
|
||||
if(skill == SkillBash)
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
if(skill == SkillBash){
|
||||
if(IsClient()){
|
||||
ItemInst *item = CastToClient()->GetInv().GetItem(MainSecondary);
|
||||
if(item)
|
||||
{
|
||||
@ -186,6 +180,10 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
|
||||
CombatAbility_Struct* ca_atk = (CombatAbility_Struct*) app->pBuffer;
|
||||
|
||||
/* Check to see if actually have skill */
|
||||
if (!MaxSkill(static_cast<SkillUseTypes>(ca_atk->m_skill)))
|
||||
return;
|
||||
|
||||
if(GetTarget()->GetID() != ca_atk->m_target)
|
||||
return; //invalid packet.
|
||||
|
||||
@ -274,8 +272,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillFrenzy))
|
||||
{
|
||||
if ((ca_atk->m_atk == 100) && (ca_atk->m_skill == SkillFrenzy)){
|
||||
CheckIncreaseSkill(SkillFrenzy, GetTarget(), 10);
|
||||
int AtkRounds = 3;
|
||||
int skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy);
|
||||
@ -311,8 +308,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(GetClass())
|
||||
{
|
||||
switch(GetClass()){
|
||||
case BERSERKER:
|
||||
case WARRIOR:
|
||||
case RANGER:
|
||||
@ -384,8 +380,7 @@ void Client::OPCombatAbility(const EQApplicationPacket *app) {
|
||||
}
|
||||
|
||||
ReuseTime = (ReuseTime*HasteMod)/100;
|
||||
if(ReuseTime > 0)
|
||||
{
|
||||
if(ReuseTime > 0){
|
||||
p_timers.Start(pTimerCombatAbility, ReuseTime);
|
||||
}
|
||||
}
|
||||
@ -403,8 +398,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
SkillUseTypes skill_type; //to avoid casting... even though it "would work"
|
||||
uint8 itemslot = MainFeet;
|
||||
|
||||
switch(unchecked_type)
|
||||
{
|
||||
switch(unchecked_type){
|
||||
case SkillFlyingKick:{
|
||||
skill_type = SkillFlyingKick;
|
||||
max_dmg = ((GetSTR()+GetSkill(skill_type)) * RuleI(Combat, FlyingKickBonus) / 100) + 35;
|
||||
@ -484,8 +478,7 @@ int Mob::MonkSpecialAttack(Mob* other, uint8 unchecked_type)
|
||||
else
|
||||
ht = ndamage = MakeRandomInt(min_dmg, max_dmg);
|
||||
}
|
||||
else
|
||||
{
|
||||
else{
|
||||
ht = max_dmg;
|
||||
}
|
||||
}
|
||||
@ -535,7 +528,6 @@ void Mob::TryBackstab(Mob *other, int ReuseTime) {
|
||||
|
||||
RogueBackstab(other,false,ReuseTime);
|
||||
if (level > 54) {
|
||||
|
||||
if(IsClient() && CastToClient()->CheckDoubleAttack(false))
|
||||
{
|
||||
if(other->GetHP() > 0)
|
||||
@ -619,12 +611,10 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
}
|
||||
|
||||
// determine minimum hits
|
||||
if (level < 51)
|
||||
{
|
||||
if (level < 51) {
|
||||
min_hit = (level*15/10);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Trumpcard: Replaced switch statement with formula calc. This will give minhit increases all the way to 65.
|
||||
min_hit = (level * ( level*5 - 105)) / 100;
|
||||
}
|
||||
@ -636,8 +626,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
if(min_damage){
|
||||
ndamage = min_hit;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (max_hit < min_hit)
|
||||
max_hit = min_hit;
|
||||
|
||||
@ -645,7 +634,6 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
|
||||
ndamage = max_hit;
|
||||
else
|
||||
ndamage = MakeRandomInt(min_hit, max_hit);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -793,14 +781,12 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
}
|
||||
|
||||
SendItemAnimation(GetTarget(), AmmoItem, SkillArchery);
|
||||
|
||||
DoArcheryAttackDmg(GetTarget(), RangeWeapon, Ammo);
|
||||
|
||||
//EndlessQuiver AA base1 = 100% Chance to avoid consumption arrow.
|
||||
int ChanceAvoidConsume = aabonuses.ConsumeProjectile + itembonuses.ConsumeProjectile + spellbonuses.ConsumeProjectile;
|
||||
|
||||
if (!ChanceAvoidConsume || (ChanceAvoidConsume < 100 && MakeRandomInt(0,99) > ChanceAvoidConsume)){
|
||||
|
||||
DeleteItemInInventory(ammo_slot, 1, true);
|
||||
mlog(COMBAT__RANGED, "Consumed one arrow from slot %d", ammo_slot);
|
||||
} else {
|
||||
@ -808,12 +794,10 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
||||
}
|
||||
|
||||
CheckIncreaseSkill(SkillArchery, GetTarget(), -15);
|
||||
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime)
|
||||
{
|
||||
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime) {
|
||||
if (!CanDoSpecialAttack(other))
|
||||
return;
|
||||
|
||||
@ -842,8 +826,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
if (focus) //From FcBaseEffects
|
||||
WDmg += WDmg*focus/100;
|
||||
|
||||
if((WDmg > 0) || (ADmg > 0))
|
||||
{
|
||||
if((WDmg > 0) || (ADmg > 0)) {
|
||||
if(WDmg < 0)
|
||||
WDmg = 0;
|
||||
if(ADmg < 0)
|
||||
@ -944,8 +927,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if((RangeWeapon != nullptr) && GetTarget() && other && !other->HasDied())
|
||||
{
|
||||
if((RangeWeapon != nullptr) && GetTarget() && other && !other->HasDied()){
|
||||
TryWeaponProc(RangeWeapon, other, MainRange);
|
||||
}
|
||||
|
||||
@ -965,14 +947,19 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
||||
|
||||
void NPC::RangedAttack(Mob* other)
|
||||
{
|
||||
|
||||
if (!other)
|
||||
return;
|
||||
//make sure the attack and ranged timers are up
|
||||
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
|
||||
if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check()))
|
||||
{
|
||||
if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())){
|
||||
mlog(COMBAT__RANGED, "Archery canceled. Timer not up. Attack %d, ranged %d", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!CheckLosFN(other))
|
||||
return;
|
||||
|
||||
int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0);
|
||||
attacks = attacks > 0 ? attacks : 1;
|
||||
for(int i = 0; i < attacks; ++i) {
|
||||
@ -1087,9 +1074,7 @@ void NPC::RangedAttack(Mob* other)
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg)
|
||||
{
|
||||
|
||||
uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) {
|
||||
uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(SkillThrowing)) / 100);
|
||||
|
||||
if (MaxDmg == 0)
|
||||
@ -1101,8 +1086,7 @@ uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg)
|
||||
TotalDmg = MakeRandomInt(1, MaxDmg);
|
||||
|
||||
minDmg = 1;
|
||||
if(GetLevel() > 25)
|
||||
{
|
||||
if(GetLevel() > 25){
|
||||
TotalDmg += ((GetLevel()-25)/3);
|
||||
minDmg += ((GetLevel()-25)/3);
|
||||
minDmg += minDmg * GetMeleeMinDamageMod_SE(SkillThrowing) / 100;
|
||||
@ -1196,7 +1180,6 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
||||
//consume ammo
|
||||
DeleteItemInInventory(ammo_slot, 1, true);
|
||||
CheckIncreaseSkill(SkillThrowing, GetTarget());
|
||||
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
|
||||
@ -1227,8 +1210,7 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
||||
if (GetClass() == ROGUE && (BehindMob(other, GetX(), GetY())))
|
||||
Assassinate_Dmg = TryAssassinate(other, SkillThrowing, ranged_timer.GetDuration());
|
||||
|
||||
if(WDmg > 0)
|
||||
{
|
||||
if(WDmg > 0){
|
||||
int minDmg = 1;
|
||||
uint16 MaxDmg = GetThrownDamage(WDmg, TotalDmg, minDmg);
|
||||
|
||||
@ -1319,7 +1301,6 @@ void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skil
|
||||
}
|
||||
|
||||
void Mob::ProjectileAnimation(Mob* to, int item_id, bool IsArrow, float speed, float angle, float tilt, float arc, const char *IDFile, SkillUseTypes skillInUse) {
|
||||
|
||||
if (!to)
|
||||
return;
|
||||
|
||||
@ -1453,17 +1434,11 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
break;
|
||||
case MONK: case MONKGM: {
|
||||
uint8 satype = SkillKick;
|
||||
if(level > 29) {
|
||||
satype = SkillFlyingKick;
|
||||
} else if(level > 24) {
|
||||
satype = SkillDragonPunch;
|
||||
} else if(level > 19) {
|
||||
satype = SkillEagleStrike;
|
||||
} else if(level > 9) {
|
||||
satype = SkillTigerClaw;
|
||||
} else if(level > 4) {
|
||||
satype = SkillRoundKick;
|
||||
}
|
||||
if(level > 29) { satype = SkillFlyingKick; }
|
||||
else if(level > 24) { satype = SkillDragonPunch; }
|
||||
else if(level > 19) { satype = SkillEagleStrike; }
|
||||
else if(level > 9) { satype = SkillTigerClaw; }
|
||||
else if(level > 4) { satype = SkillRoundKick; }
|
||||
reuse = MonkSpecialAttack(target, satype);
|
||||
|
||||
reuse *= 1000;
|
||||
@ -1472,8 +1447,7 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
}
|
||||
case WARRIOR: case WARRIORGM:{
|
||||
if(level >= RuleI(Combat, NPCBashKickLevel)){
|
||||
if(MakeRandomInt(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
|
||||
{
|
||||
if(MakeRandomInt(0, 100) > 25){ //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
|
||||
DoAnim(animKick);
|
||||
int32 dmg = 0;
|
||||
|
||||
@ -1494,8 +1468,7 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
DoSpecialAttackDamage(target, SkillKick, dmg, 1, -1, reuse);
|
||||
did_attack = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
DoAnim(animTailRake);
|
||||
int32 dmg = 0;
|
||||
|
||||
@ -1518,8 +1491,7 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BERSERKER: case BERSERKERGM:
|
||||
{
|
||||
case BERSERKER: case BERSERKERGM:{
|
||||
int AtkRounds = 3;
|
||||
int32 max_dmg = 26 + ((GetLevel()-6) * 2);
|
||||
int32 min_dmg = 0;
|
||||
@ -1536,7 +1508,6 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
reuse = FrenzyReuseTime * 1000;
|
||||
|
||||
while(AtkRounds > 0) {
|
||||
|
||||
if (GetTarget() && (AtkRounds == 1 || MakeRandomInt(0,100) < 75)){
|
||||
DoSpecialAttackDamage(GetTarget(), SkillFrenzy, max_dmg, min_dmg, -1 , reuse, true);
|
||||
}
|
||||
@ -1574,8 +1545,7 @@ void NPC::DoClassAttacks(Mob *target) {
|
||||
}
|
||||
case CLERIC: case CLERICGM: //clerics can bash too.
|
||||
case SHADOWKNIGHT: case SHADOWKNIGHTGM:
|
||||
case PALADIN: case PALADINGM:
|
||||
{
|
||||
case PALADIN: case PALADINGM:{
|
||||
if(level >= RuleI(Combat, NPCBashKickLevel)){
|
||||
DoAnim(animTailRake);
|
||||
int32 dmg = 0;
|
||||
@ -1615,8 +1585,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
return;
|
||||
|
||||
//check range for all these abilities, they are all close combat stuff
|
||||
if(!CombatRange(ca_target))
|
||||
{
|
||||
if(!CombatRange(ca_target)){
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1639,9 +1608,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
uint16 skill_to_use = -1;
|
||||
|
||||
if (skill == -1){
|
||||
|
||||
switch(GetClass())
|
||||
{
|
||||
switch(GetClass()){
|
||||
case WARRIOR:
|
||||
case RANGER:
|
||||
case BEASTLORD:
|
||||
@ -1692,14 +1659,11 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
if(skill_to_use == -1)
|
||||
return;
|
||||
|
||||
if(skill_to_use == SkillBash)
|
||||
{
|
||||
if (ca_target!=this)
|
||||
{
|
||||
if(skill_to_use == SkillBash) {
|
||||
if (ca_target!=this) {
|
||||
DoAnim(animTailRake);
|
||||
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(MainSecondary)) <= 0 &&
|
||||
GetWeaponDamage(ca_target, GetInv().GetItem(MainShoulders)) <= 0){
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(MainSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(MainShoulders)) <= 0){
|
||||
dmg = -5;
|
||||
}
|
||||
else{
|
||||
@ -1720,16 +1684,14 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
|
||||
DoSpecialAttackDamage(ca_target, SkillBash, dmg, 1,-1,ReuseTime);
|
||||
|
||||
if(ReuseTime > 0 && !IsRiposte)
|
||||
{
|
||||
if(ReuseTime > 0 && !IsRiposte) {
|
||||
p_timers.Start(pTimerCombatAbility, ReuseTime);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(skill_to_use == SkillFrenzy)
|
||||
{
|
||||
if(skill_to_use == SkillFrenzy){
|
||||
CheckIncreaseSkill(SkillFrenzy, GetTarget(), 10);
|
||||
int AtkRounds = 3;
|
||||
int skillmod = 100*GetSkill(SkillFrenzy)/MaxSkill(SkillFrenzy);
|
||||
@ -1763,10 +1725,8 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
return;
|
||||
}
|
||||
|
||||
if(skill_to_use == SkillKick)
|
||||
{
|
||||
if(ca_target!=this)
|
||||
{
|
||||
if(skill_to_use == SkillKick){
|
||||
if(ca_target!=this){
|
||||
DoAnim(animKick);
|
||||
|
||||
if(GetWeaponDamage(ca_target, GetInv().GetItem(MainFeet)) <= 0){
|
||||
@ -1790,12 +1750,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
}
|
||||
|
||||
if(skill_to_use == SkillFlyingKick ||
|
||||
skill_to_use == SkillDragonPunch ||
|
||||
skill_to_use == SkillEagleStrike ||
|
||||
skill_to_use == SkillTigerClaw ||
|
||||
skill_to_use == SkillRoundKick)
|
||||
{
|
||||
if(skill_to_use == SkillFlyingKick || skill_to_use == SkillDragonPunch || skill_to_use == SkillEagleStrike || skill_to_use == SkillTigerClaw || skill_to_use == SkillRoundKick) {
|
||||
ReuseTime = MonkSpecialAttack(ca_target, skill_to_use) - 1;
|
||||
MonkSpecialAttack(ca_target, skill_to_use);
|
||||
|
||||
@ -1810,7 +1765,6 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
MonkSpecialAttack(ca_target, MonkSPA[MakeRandomInt(0,4)]);
|
||||
|
||||
int TripleChance = 25;
|
||||
|
||||
if (bDoubleSpecialAttack > 100)
|
||||
TripleChance += TripleChance*(100-bDoubleSpecialAttack)/100;
|
||||
|
||||
@ -1820,8 +1774,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
}
|
||||
|
||||
if(skill_to_use == SkillBackstab)
|
||||
{
|
||||
if(skill_to_use == SkillBackstab){
|
||||
ReuseTime = BackstabReuseTime-1;
|
||||
|
||||
if (IsRiposte)
|
||||
@ -1831,8 +1784,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
|
||||
}
|
||||
|
||||
ReuseTime = (ReuseTime*HasteMod)/100;
|
||||
if(ReuseTime > 0 && !IsRiposte)
|
||||
{
|
||||
if(ReuseTime > 0 && !IsRiposte){
|
||||
p_timers.Start(pTimerCombatAbility, ReuseTime);
|
||||
}
|
||||
}
|
||||
@ -1900,7 +1852,6 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
tauntchance /= 100.0f;
|
||||
|
||||
if (tauntchance > MakeRandomFloat(0, 1)) {
|
||||
|
||||
if (hate_top && hate_top != this){
|
||||
newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1;
|
||||
who->CastToNPC()->AddToHateList(this, newhate);
|
||||
@ -1923,7 +1874,6 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
||||
if (HasSkillProcs())
|
||||
TrySkillProc(who, SkillTaunt, TauntReuseTime*1000);
|
||||
|
||||
|
||||
if (Success && HasSkillProcSuccess())
|
||||
TrySkillProc(who, SkillTaunt, TauntReuseTime*1000, true);
|
||||
}
|
||||
@ -1944,8 +1894,7 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
if(!CombatRange(who))
|
||||
return;
|
||||
|
||||
if(IsClient())
|
||||
{
|
||||
if(IsClient()) {
|
||||
CastToClient()->CheckIncreaseSkill(SkillIntimidation, who, 10);
|
||||
}
|
||||
|
||||
@ -1976,13 +1925,11 @@ void Mob::InstillDoubt(Mob *who) {
|
||||
}
|
||||
|
||||
uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
|
||||
//Only works on YOUR target.
|
||||
if(defender && (defender->GetBodyType() == BT_Humanoid) && !defender->IsClient()
|
||||
&& (skillInUse == SkillArchery) && (GetTarget() == defender)) {
|
||||
|
||||
uint32 HeadShot_Dmg = aabonuses.HeadShot[1] + spellbonuses.HeadShot[1] + itembonuses.HeadShot[1];
|
||||
|
||||
uint8 HeadShot_Level = 0; //Get Highest Headshot Level
|
||||
HeadShot_Level = aabonuses.HSLevel;
|
||||
if (HeadShot_Level < spellbonuses.HSLevel)
|
||||
@ -1991,7 +1938,6 @@ uint32 Mob::TryHeadShot(Mob* defender, SkillUseTypes skillInUse) {
|
||||
HeadShot_Level = itembonuses.HSLevel;
|
||||
|
||||
if(HeadShot_Dmg && HeadShot_Level && (defender->GetLevel() <= HeadShot_Level)){
|
||||
|
||||
float ProcChance = GetSpecialProcChances(MainRange);
|
||||
if(ProcChance > MakeRandomFloat(0,1))
|
||||
return HeadShot_Dmg;
|
||||
@ -2097,8 +2043,10 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
if (!CanDoSpecialAttack(other))
|
||||
return;
|
||||
|
||||
//For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically.
|
||||
//Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects.
|
||||
/*
|
||||
For spells using skill value 98 (feral swipe ect) server sets this to 67 automatically.
|
||||
Kayen: This is unlikely to be completely accurate but use OFFENSE skill value for these effects.
|
||||
*/
|
||||
if (skillinuse == SkillBegging)
|
||||
skillinuse = SkillOffense;
|
||||
|
||||
@ -2108,7 +2056,6 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
if (hate == 0 && weapon_damage > 1) hate = weapon_damage;
|
||||
|
||||
if(weapon_damage > 0){
|
||||
|
||||
if (focus) //From FcBaseEffects
|
||||
weapon_damage += weapon_damage*focus/100;
|
||||
|
||||
@ -2120,10 +2067,8 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
int32 min_hit = 1;
|
||||
int32 max_hit = (2 * weapon_damage*GetDamageTable(skillinuse)) / 100;
|
||||
|
||||
if(GetLevel() >= 28 && IsWarriorClass() )
|
||||
{
|
||||
if(GetLevel() >= 28 && IsWarriorClass() ) {
|
||||
int ucDamageBonus = GetWeaponDamageBonus((const Item_Struct*) nullptr );
|
||||
|
||||
min_hit += (int) ucDamageBonus;
|
||||
max_hit += (int) ucDamageBonus;
|
||||
hate += ucDamageBonus;
|
||||
@ -2143,7 +2088,6 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
}
|
||||
|
||||
ApplySpecialAttackMod(skillinuse, max_hit, min_hit);
|
||||
|
||||
min_hit += min_hit * GetMeleeMinDamageMod_SE(skillinuse) / 100;
|
||||
|
||||
if(max_hit < min_hit)
|
||||
@ -2204,8 +2148,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
||||
TrySkillProc(other, skillinuse, ReuseTime, true);
|
||||
}
|
||||
|
||||
bool Mob::CanDoSpecialAttack(Mob *other)
|
||||
{
|
||||
bool Mob::CanDoSpecialAttack(Mob *other) {
|
||||
//Make sure everything is valid before doing any attacks.
|
||||
if (!other) {
|
||||
SetTarget(nullptr);
|
||||
@ -2215,8 +2158,7 @@ bool Mob::CanDoSpecialAttack(Mob *other)
|
||||
if(!GetTarget())
|
||||
SetTarget(other);
|
||||
|
||||
if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead))
|
||||
|| HasDied() || (!IsAttackAllowed(other)))) {
|
||||
if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(other)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -34,18 +34,16 @@ Copyright (C) 2001-2008 EQEMu Development Team (http://eqemulator.net)
|
||||
#include "../common/features.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "mob.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
|
||||
TaskManager::TaskManager() {
|
||||
|
||||
for(int i=0; i<MAXTASKS; i++)
|
||||
Tasks[i] = nullptr;
|
||||
|
||||
|
||||
}
|
||||
|
||||
TaskManager::~TaskManager() {
|
||||
|
||||
for(int i=0; i<MAXTASKS; i++) {
|
||||
if(Tasks[i] != nullptr) {
|
||||
for(int j=0; j<Tasks[i]->ActivityCount; j++) {
|
||||
@ -62,11 +60,8 @@ TaskManager::~TaskManager() {
|
||||
}
|
||||
|
||||
bool TaskManager::LoadTaskSets() {
|
||||
|
||||
|
||||
const char *TaskSetQuery = "SELECT `id`, `taskid` from `tasksets` WHERE `id` > 0 AND `id` < %i "
|
||||
"AND `taskid` >= 0 AND `taskid` < %i ORDER BY `id`, `taskid` ASC";
|
||||
|
||||
const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::LoadTaskSets: %s";
|
||||
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
@ -1985,12 +1980,17 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T
|
||||
// Inform the client the task has been updated, both by a chat message
|
||||
c->Message(0, "Your task '%s' has been updated.", Task->Title);
|
||||
|
||||
if(Task->Activity[ActivityID].GoalMethod != METHODQUEST)
|
||||
{
|
||||
if(Task->Activity[ActivityID].GoalMethod != METHODQUEST) {
|
||||
char buf[24];
|
||||
snprintf(buf, 23, "%d %d", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID);
|
||||
buf[23] = '\0';
|
||||
parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, c, buf, 0);
|
||||
|
||||
/* QS: PlayerLogTaskUpdates :: Update */
|
||||
if (RuleB(QueryServ, PlayerLogTaskUpdates)){
|
||||
std::string event_desc = StringFormat("Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc);
|
||||
}
|
||||
}
|
||||
|
||||
// If this task is now complete, the Completed tasks will have been
|
||||
@ -2002,6 +2002,12 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T
|
||||
buf[23] = '\0';
|
||||
parse->EventPlayer(EVENT_TASK_COMPLETE, c, buf, 0);
|
||||
|
||||
/* QS: PlayerLogTaskUpdates :: Complete */
|
||||
if (RuleB(QueryServ, PlayerLogTaskUpdates)){
|
||||
std::string event_desc = StringFormat("Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", ActiveTasks[TaskIndex].TaskID, ActiveTasks[TaskIndex].Activity[ActivityID].ActivityID, ActiveTasks[TaskIndex].Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
taskmanager->SendCompletedTasksToClient(c, this);
|
||||
c->SendTaskActivityComplete(ActiveTasks[TaskIndex].TaskID, 0, TaskIndex, false);
|
||||
taskmanager->SaveClientState(c, this);
|
||||
@ -2011,6 +2017,7 @@ void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation* Task, int T
|
||||
// If Experience and/or cash rewards are set, reward them from the task even if RewardMethod is METHODQUEST
|
||||
RewardTask(c, Task);
|
||||
//RemoveTask(c, TaskIndex);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,9 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
|
||||
static const SkillUseTypes TradeskillUnknown = Skill1HBlunt; /* an arbitrary non-tradeskill */
|
||||
|
||||
@ -1076,16 +1079,24 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
|
||||
//should we check this crap?
|
||||
SummonItem(itr->first, itr->second);
|
||||
item = database.GetItem(itr->first);
|
||||
if (this->GetGroup())
|
||||
{
|
||||
if (this->GetGroup()) {
|
||||
entity_list.MessageGroup(this, true, MT_Skills, "%s has successfully fashioned %s!", GetName(), item->Name);
|
||||
}
|
||||
|
||||
/* QS: Player_Log_Trade_Skill_Events */
|
||||
if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){
|
||||
std::string event_desc = StringFormat("Success :: fashioned recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(ActivityTradeSkill, itr->first, itr->second);
|
||||
++itr;
|
||||
}
|
||||
return(true);
|
||||
} else {
|
||||
}
|
||||
/* Tradeskill Fail */
|
||||
else {
|
||||
success_modifier = 2; // Halves the chance
|
||||
|
||||
if(over_trivial < 0)
|
||||
@ -1097,6 +1108,13 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
|
||||
if (this->GetGroup())
|
||||
{
|
||||
entity_list.MessageGroup(this,true,MT_Skills,"%s was unsuccessful in %s tradeskill attempt.",GetName(),this->GetGender() == 0 ? "his" : this->GetGender() == 1 ? "her" : "its");
|
||||
|
||||
}
|
||||
|
||||
/* QS: Player_Log_Trade_Skill_Events */
|
||||
if (RuleB(QueryServ, PlayerLogTradeSkillEvents)){
|
||||
std::string event_desc = StringFormat("Failed :: recipe_id:%i tskillid:%i trivial:%i chance:%4.2f in zoneid:%i instid:%i", spec->recipe_id, spec->tradeskill, spec->trivial, chance, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Trade_Skill_Events, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
itr = spec->onfail.begin();
|
||||
@ -1106,6 +1124,8 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
|
||||
++itr;
|
||||
}
|
||||
|
||||
/* Salvage Item rolls */
|
||||
|
||||
// Rolls on each item, is possible to return everything
|
||||
int SalvageChance = aabonuses.SalvageChance + itembonuses.SalvageChance + spellbonuses.SalvageChance;
|
||||
// Skip check if not a normal TS or if a quest recipe these should be nofail, but check amyways
|
||||
|
||||
@ -262,19 +262,17 @@ Mob* EntityList::GetTrapTrigger(Trap* trap) {
|
||||
|
||||
//todo: rewrite this to not need direct access to trap members.
|
||||
bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
// int char_num = 0;
|
||||
unsigned long* lengths;
|
||||
std::string query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
|
||||
"maxzdiff, radius, chance, message, respawn_time, respawn_var, level "
|
||||
"FROM traps WHERE zone='%s' AND version=%u", zonename, version);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTraps query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RunQuery(query, MakeAnyLenString(&query, "SELECT id,x,y,z,effect,effectvalue,effectvalue2,skill,maxzdiff,radius,chance,message,respawn_time,respawn_var,level FROM traps WHERE zone='%s' AND version=%u", zonename, version), errbuf, &result)) {
|
||||
safe_delete_array(query);
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
lengths = mysql_fetch_lengths(result);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
Trap* trap = new Trap();
|
||||
trap->trap_id = atoi(row[0]);
|
||||
trap->x = atof(row[1]);
|
||||
@ -294,13 +292,6 @@ bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
|
||||
entity_list.AddTrap(trap);
|
||||
trap->CreateHiddenTrigger();
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTraps query '%s': %s", query, errbuf);
|
||||
safe_delete_array(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -378,42 +378,39 @@ void Client::SendGuildTributes() {
|
||||
}
|
||||
|
||||
bool ZoneDatabase::LoadTributes() {
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
|
||||
TributeData t;
|
||||
memset(&t.tiers, 0, sizeof(t.tiers));
|
||||
t.tier_count = 0;
|
||||
TributeData tributeData;
|
||||
memset(&tributeData.tiers, 0, sizeof(tributeData.tiers));
|
||||
tributeData.tier_count = 0;
|
||||
|
||||
tribute_list.clear();
|
||||
|
||||
const char *query = "SELECT id,name,descr,unknown,isguild FROM tributes";
|
||||
if (RunQuery(query, strlen(query), errbuf, &result)) {
|
||||
int r;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
r = 0;
|
||||
uint32 id = atoul(row[r++]);
|
||||
t.name = row[r++];
|
||||
t.description = row[r++];
|
||||
t.unknown = strtoul(row[r++], nullptr, 10);
|
||||
t.is_guild = atol(row[r++])==0?false:true;
|
||||
|
||||
tribute_list[id] = t;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTributes first query '%s': %s", query, errbuf);
|
||||
const std::string query = "SELECT id, name, descr, unknown, isguild FROM tributes";
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTributes first query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
uint32 id = atoul(row[0]);
|
||||
tributeData.name = row[1];
|
||||
tributeData.description = row[2];
|
||||
tributeData.unknown = strtoul(row[3], nullptr, 10);
|
||||
tributeData.is_guild = atol(row[4]) == 0? false: true;
|
||||
|
||||
const char *query2 = "SELECT tribute_id,level,cost,item_id FROM tribute_levels ORDER BY tribute_id,level";
|
||||
if (RunQuery(query2, strlen(query2), errbuf, &result)) {
|
||||
int r;
|
||||
while ((row = mysql_fetch_row(result))) {
|
||||
r = 0;
|
||||
uint32 id = atoul(row[r++]);
|
||||
tribute_list[id] = tributeData;
|
||||
}
|
||||
|
||||
const std::string query2 = "SELECT tribute_id, level, cost, item_id FROM tribute_levels ORDER BY tribute_id, level";
|
||||
results = QueryDatabase(query2);
|
||||
if (!results.Success()) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTributes level query '%s': %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
uint32 id = atoul(row[0]);
|
||||
|
||||
if(tribute_list.count(id) != 1) {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTributes: unknown tribute %lu in tribute_levels", (unsigned long)id);
|
||||
@ -429,16 +426,11 @@ bool ZoneDatabase::LoadTributes() {
|
||||
|
||||
TributeLevel_Struct &s = cur.tiers[cur.tier_count];
|
||||
|
||||
s.level = atoul(row[r++]);
|
||||
s.cost = atoul(row[r++]);
|
||||
s.tribute_item_id = atoul(row[r++]);
|
||||
s.level = atoul(row[1]);
|
||||
s.cost = atoul(row[2]);
|
||||
s.tribute_item_id = atoul(row[3]);
|
||||
cur.tier_count++;
|
||||
}
|
||||
mysql_free_result(result);
|
||||
} else {
|
||||
LogFile->write(EQEMuLog::Error, "Error in LoadTributes level query '%s': %s", query, errbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3226,3 +3226,11 @@ bool ZoneDatabase::GetFactionIdsForNPC(uint32 nfl_id, std::list<struct NPCFactio
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZoneDatabase::StoreCharacterLookup(uint32 char_id) {
|
||||
std::string c_lookup = StringFormat("REPLACE INTO `character_lookup` (id, account_id, `name`, timelaston, x, y, z, zonename, zoneid, instanceid, pktime, groupid, class, `level`, lfp, lfg, mailkey, xtargets, firstlogon, inspectmessage)"
|
||||
" SELECT id, account_id, `name`, timelaston, x, y, z, zonename, zoneid, instanceid, pktime, groupid, class, `level`, lfp, lfg, mailkey, xtargets, firstlogon, inspectmessage"
|
||||
" FROM `character_` "
|
||||
" WHERE `id` = %i ", char_id);
|
||||
QueryDatabase(c_lookup);
|
||||
}
|
||||
@ -246,6 +246,7 @@ public:
|
||||
/*
|
||||
* General Character Related Stuff
|
||||
*/
|
||||
void StoreCharacterLookup(uint32 char_id);
|
||||
bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
|
||||
uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
|
||||
bool GetAccountInfoForLogin(uint32 account_id, int16* admin = 0, char* account_name = 0,
|
||||
|
||||
@ -25,7 +25,9 @@
|
||||
#include "../common/string_util.h"
|
||||
#include "string_ids.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern WorldServer worldserver;
|
||||
extern Zone* zone;
|
||||
|
||||
@ -147,7 +149,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
}
|
||||
}
|
||||
|
||||
//make sure its a valid zone.
|
||||
/* Check for Valid Zone */
|
||||
const char *target_zone_name = database.GetZoneName(target_zone_id);
|
||||
if(target_zone_name == nullptr) {
|
||||
//invalid zone...
|
||||
@ -157,7 +159,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
return;
|
||||
}
|
||||
|
||||
//load up the safe coords, restrictions, and verify the zone name
|
||||
/* Load up the Safe Coordinates, restrictions and verify the zone name*/
|
||||
float safe_x, safe_y, safe_z;
|
||||
int16 minstatus = 0;
|
||||
uint8 minlevel = 0;
|
||||
@ -327,15 +329,19 @@ void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instanc
|
||||
|
||||
SendLogoutPackets();
|
||||
|
||||
//dont clear aggro until the zone is successful
|
||||
/* QS: PlayerLogZone */
|
||||
if (RuleB(QueryServ, PlayerLogZone)){
|
||||
std::string event_desc = StringFormat("Zoning :: zoneid:%u instid:%u x:%4.2f y:%4.2f z:%4.2f h:%4.2f zonemode:%d from zoneid:%u instid:%i", zone_id, instance_id, dest_x, dest_y, dest_z, dest_h, zone_mode, this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Zoning, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
/* Dont clear aggro until the zone is successful */
|
||||
entity_list.RemoveFromHateLists(this);
|
||||
|
||||
if(this->GetPet())
|
||||
entity_list.RemoveFromHateLists(this->GetPet());
|
||||
|
||||
LogFile->write(EQEMuLog::Status, "Zoning '%s' to: %s (%i) - (%i) x=%f, y=%f, z=%f",
|
||||
m_pp.name, database.GetZoneName(zone_id), zone_id, instance_id,
|
||||
dest_x, dest_y, dest_z);
|
||||
LogFile->write(EQEMuLog::Status, "Zoning '%s' to: %s (%i) - (%i) x=%f, y=%f, z=%f", m_pp.name, database.GetZoneName(zone_id), zone_id, instance_id, dest_x, dest_y, dest_z);
|
||||
|
||||
//set the player's coordinates in the new zone so they have them
|
||||
//when they zone into it
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user