mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-22 16:28:28 +00:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 579294fbf0 | |||
| a3b54e5cae | |||
| b392d16808 | |||
| 84310ec8f0 | |||
| ffed5a9e22 | |||
| 92c9ff6e53 | |||
| 986a424322 | |||
| c3e7c48939 | |||
| 281b321237 | |||
| ba0e4bfc1d | |||
| 3cda62acf4 | |||
| 2ef43212e1 | |||
| f69eccc42b | |||
| a1e425f936 | |||
| 6186c3d866 | |||
| 1d0a6bdc71 | |||
| da121137e5 | |||
| c953f1dee1 | |||
| 32b595afb4 | |||
| 37d3daaf9a | |||
| 22742b6a25 | |||
| 891952eb79 | |||
| e6a0b01f37 | |||
| 64c324a42b | |||
| f909e76260 | |||
| b7dfdc5060 | |||
| e25239a50d | |||
| 76d3edc534 | |||
| 7301182b3e | |||
| 832e5e90d1 | |||
| 7ddaabee30 | |||
| 41d57ddab6 | |||
| 8dd00f5288 | |||
| 15f217b594 | |||
| 8422178233 | |||
| eebe902917 | |||
| 04dc593df9 |
@@ -1,5 +1,34 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 09/07/2014 ==
|
||||
Akkadius: Fixed ROF Augment item dupe with not checking for available slots properly and adding items to the virtual instance
|
||||
|
||||
== 09/06/2014 ==
|
||||
Uleat: Tweaked 'Smart' trading code to return main slots before sub slots in stackable and free space search processes. (If enough people ask for it, I'll add an optional rule to allow 'bag packing' - the original implementation behavior)
|
||||
|
||||
== 09/05/2014 ==
|
||||
Uleat: Fix for cursor item loss when zoning. (Thanks to the other devs who traced and fixed the 'macro' issue!)
|
||||
demonstar55: Fix size getting nuked with lua's SendIllusionPacket
|
||||
|
||||
== 09/03/2014 ==
|
||||
Secrets: Identified the routines needed to augment items in RoF. Currently, only Insert and Remove are supported. Swap and Destroy do not work due to missing functions related to the cursor.
|
||||
demonstar55: Added work around command to show numhits on your buffs (#shownumhits)
|
||||
Uleat: Fix for timer issue introduced by Zone::ShutDown() fix.
|
||||
|
||||
== 09/02/2014 ==
|
||||
Secrets: Identified OP_GuildPromote for RoF clients.
|
||||
Secrets: Fixed promotion, demotion, transferring a leader and displaying of client ranks in the Rain of Fear client. The rain of fear client, as such, will only have 3 ranks like the other clients, but supports a theoretical 8 ranks later.
|
||||
Secrets/Akkadius: Fixed an issue involving character name lookup in the new DB code.
|
||||
demonstar55: crash fix checking DivineAura in hate_list.cpp
|
||||
Secrets: Reverted some code that got in the main branch that shouldn't have gotten there.
|
||||
Uleat: Changed #loc to report the same precision as /loc for Cartesians
|
||||
|
||||
== 08/31/2014 ==
|
||||
KLS: Fixed a bug in fishing in S3D zones
|
||||
KLS: Fixed a bug in turnins with new any abstraction
|
||||
KLS: Fixed a few quest related inconsistencies.
|
||||
KLS: Added Lua EntityList::ChannelMessage(from, type, msg, language)
|
||||
|
||||
== 08/30/2014 ==
|
||||
demonstar55: (noudess) Merchants should be more descriptive of why they don't sell to you
|
||||
|
||||
|
||||
+4
-2
@@ -319,7 +319,7 @@ bool Database::DeleteAccount(const char* name) {
|
||||
}
|
||||
|
||||
bool Database::SetLocalPassword(uint32 accid, const char* password) {
|
||||
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", password, accid);
|
||||
std::string query = StringFormat("UPDATE account SET password=MD5('%s') where id=%i;", EscapeString(password).c_str(), accid);
|
||||
|
||||
auto results = QueryDatabase(query);
|
||||
|
||||
@@ -771,7 +771,9 @@ void Database::GetCharName(uint32 char_id, char* name) {
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
strcpy(name, row[0]);
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
strcpy(name, row[0]);
|
||||
}
|
||||
}
|
||||
|
||||
bool Database::LoadVariables() {
|
||||
|
||||
@@ -540,3 +540,4 @@ N(OP_OpenInventory),
|
||||
N(OP_OpenContainer),
|
||||
N(OP_Marquee),
|
||||
N(OP_ClientTimeStamp),
|
||||
N(OP_GuildPromote),
|
||||
|
||||
@@ -2287,10 +2287,13 @@ struct Stun_Struct { // 4 bytes total
|
||||
};
|
||||
|
||||
struct AugmentItem_Struct {
|
||||
/*00*/ int16 container_slot;
|
||||
/*02*/ char unknown02[2];
|
||||
/*04*/ int32 augment_slot;
|
||||
/*08*/
|
||||
/*00*/ uint32 container_index;
|
||||
/*04*/ int32 container_slot;
|
||||
/*08*/ uint32 augment_index;
|
||||
/*12*/ int32 augment_slot;
|
||||
/*16*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented
|
||||
/*20*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug
|
||||
/*24*/
|
||||
};
|
||||
|
||||
// OP_Emote
|
||||
@@ -4461,6 +4464,14 @@ struct GuildBankPromote_Struct
|
||||
/*12*/ uint32 Slot2; // Always appears to be the same as Slot for Action code 3
|
||||
};
|
||||
|
||||
struct GuildPromoteStruct {
|
||||
/*000*/ char target[64];
|
||||
/*064*/ char name[64];
|
||||
/*128*/ uint32 rank;
|
||||
/*132*/ uint32 myrank;
|
||||
/*136*/
|
||||
};
|
||||
|
||||
struct GuildBankPermissions_Struct
|
||||
{
|
||||
/*00*/ uint32 Action; // 6
|
||||
|
||||
@@ -534,7 +534,7 @@ void EQStream::FastQueuePacket(EQApplicationPacket **p, bool ack_req)
|
||||
|
||||
uint16 opcode = (*OpMgr)->EmuToEQ(pack->emu_opcode);
|
||||
|
||||
_log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size);
|
||||
//_log(NET__APP_TRACE, "Queueing %sacked packet with opcode 0x%x (%s) and length %d", ack_req?"":"non-", opcode, OpcodeManager::EmuToName(pack->emu_opcode), pack->size);
|
||||
|
||||
if (!ack_req) {
|
||||
NonSequencedPush(new EQProtocolPacket(opcode, pack->pBuffer, pack->size));
|
||||
|
||||
@@ -474,6 +474,11 @@ bool BaseGuildManager::SetBankerFlag(uint32 charid, bool is_banker) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool BaseGuildManager::ForceRankUpdate(uint32 charid) {
|
||||
SendRankUpdate(charid);
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool BaseGuildManager::SetAltFlag(uint32 charid, bool is_alt)
|
||||
{
|
||||
if(!DBSetAltFlag(charid, is_alt))
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
bool SetGuild(uint32 charid, uint32 guild_id, uint8 rank);
|
||||
bool SetGuildRank(uint32 charid, uint8 rank);
|
||||
bool SetBankerFlag(uint32 charid, bool is_banker);
|
||||
bool ForceRankUpdate(uint32 charid);
|
||||
bool GetAltFlag(uint32 CharID);
|
||||
bool SetAltFlag(uint32 charid, bool is_alt);
|
||||
bool GetBankerFlag(uint32 CharID);
|
||||
|
||||
+22
-1
@@ -683,6 +683,13 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
if ((main_inst->GetID() == inst->GetID()) && (main_inst->GetCharges() < main_inst->GetItem()->StackSize))
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (!main_inst)
|
||||
continue;
|
||||
|
||||
if (main_inst->IsType(ItemClassContainer)) { // if item-specific containers already have bad items, we won't fix it here...
|
||||
for (uint8 free_bag_slot = SUB_BEGIN; (free_bag_slot < main_inst->GetItem()->BagSlots) && (free_bag_slot < EmuConstants::ITEM_CONTAINER_SIZE); ++free_bag_slot) {
|
||||
@@ -732,8 +739,12 @@ int16 Inventory::FindFreeSlotForTradeItem(const ItemInst* inst) {
|
||||
|
||||
if (!main_inst)
|
||||
return free_slot;
|
||||
}
|
||||
|
||||
if (main_inst->IsType(ItemClassContainer)) {
|
||||
for (int16 free_slot = EmuConstants::GENERAL_BEGIN; free_slot <= EmuConstants::GENERAL_END; ++free_slot) {
|
||||
const ItemInst* main_inst = m_inv[free_slot];
|
||||
|
||||
if (main_inst && main_inst->IsType(ItemClassContainer)) {
|
||||
if ((main_inst->GetItem()->BagSize < inst->GetItem()->Size) || (main_inst->GetItem()->BagType == BagTypeBandolier) || (main_inst->GetItem()->BagType == BagTypeQuiver))
|
||||
continue;
|
||||
|
||||
@@ -1569,6 +1580,16 @@ int8 ItemInst::AvailableAugmentSlot(int32 augtype) const
|
||||
return (i < EmuConstants::ITEM_COMMON_SIZE) ? i : INVALID_INDEX;
|
||||
}
|
||||
|
||||
bool ItemInst::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const {
|
||||
if (m_item->ItemClass != ItemClassCommon || !m_item)
|
||||
return false;
|
||||
|
||||
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve item inside container
|
||||
ItemInst* ItemInst::GetItem(uint8 index) const
|
||||
{
|
||||
|
||||
@@ -274,6 +274,7 @@ public:
|
||||
inline bool IsAugmentable() const { return m_item->AugSlotType[0]!=0 || m_item->AugSlotType[1]!=0 || m_item->AugSlotType[2]!=0 || m_item->AugSlotType[3]!=0 || m_item->AugSlotType[4]!=0; }
|
||||
bool AvailableWearSlot(uint32 aug_wear_slots) const;
|
||||
int8 AvailableAugmentSlot(int32 augtype) const;
|
||||
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
|
||||
inline int32 GetAugmentType() const { return m_item->AugType; }
|
||||
|
||||
inline bool IsExpendable() const { return ((m_item->Click.Type == ET_Expendable ) || (m_item->ItemType == ItemTypePotion)); }
|
||||
|
||||
+3
-3
@@ -92,8 +92,8 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_message_mob(LogType type, Mob *who, const char *fmt, ...);
|
||||
#define mlog( type, format, ...) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_message_mob(type, this, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
@@ -150,16 +150,16 @@ extern void log_raw_packet(LogType type, uint16 seq, const BasePacket *p);
|
||||
class Mob;
|
||||
extern void log_hex_mob(LogType type, Mob *who, const char *data, uint32 length);
|
||||
#define mhex( type, data, len) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_hex_mob(type, this, data, len); \
|
||||
} \
|
||||
} while(false)
|
||||
extern void log_packet_mob(LogType type, Mob *who, const BasePacket *p);
|
||||
#define mpkt( type, packet) \
|
||||
if(IsLoggingEnabled()) \
|
||||
do { \
|
||||
if(IsLoggingEnabled()) \
|
||||
if(log_type_info[ type ].enabled) { \
|
||||
log_packet_mob(type, this, packet); \
|
||||
} \
|
||||
|
||||
+32
-7
@@ -1,4 +1,3 @@
|
||||
|
||||
#include "../debug.h"
|
||||
#include "rof.h"
|
||||
#include "../opcodemgr.h"
|
||||
@@ -1974,7 +1973,14 @@ ENCODE(OP_ZoneSpawns)
|
||||
else
|
||||
{
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildID);
|
||||
VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank);
|
||||
|
||||
/* Translate older ranks to new values */
|
||||
switch (emu->guildrank) {
|
||||
case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0
|
||||
case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1
|
||||
case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2
|
||||
default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } //
|
||||
}
|
||||
}
|
||||
|
||||
VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->class_);
|
||||
@@ -2406,7 +2412,15 @@ ENCODE(OP_GuildMemberList) {
|
||||
PutFieldN(level);
|
||||
PutFieldN(banker);
|
||||
PutFieldN(class_);
|
||||
PutFieldN(rank);
|
||||
|
||||
/* Translate older ranks to new values */
|
||||
switch (emu_e->rank) {
|
||||
case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0
|
||||
case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1
|
||||
case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2
|
||||
default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE
|
||||
}
|
||||
|
||||
PutFieldN(time_last_on);
|
||||
PutFieldN(tribute_enable);
|
||||
e->unknown01 = 0;
|
||||
@@ -3330,7 +3344,15 @@ ENCODE(OP_SetGuildRank)
|
||||
ENCODE_LENGTH_EXACT(GuildSetRank_Struct);
|
||||
SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct);
|
||||
eq->GuildID = emu->Unknown00;
|
||||
OUT(Rank);
|
||||
|
||||
/* Translate older ranks to new values */
|
||||
switch (emu->Rank) {
|
||||
case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0
|
||||
case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1
|
||||
case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2
|
||||
default: { eq->Rank = emu->Rank; break; }
|
||||
}
|
||||
|
||||
memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName));
|
||||
OUT(Banker);
|
||||
eq->Unknown76 = 1;
|
||||
@@ -4660,8 +4682,11 @@ DECODE(OP_AugmentItem) {
|
||||
SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct);
|
||||
|
||||
emu->container_slot = RoFToServerSlot(eq->container_slot);
|
||||
//emu->augment_slot = eq->augment_slot;
|
||||
|
||||
emu->augment_slot = RoFToServerSlot(eq->augment_slot);
|
||||
emu->container_index = eq->container_index;
|
||||
emu->augment_index = eq->augment_index;
|
||||
emu->dest_inst_id = eq->dest_inst_id;
|
||||
emu->augment_action = eq->augment_action;
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
|
||||
@@ -5068,7 +5093,7 @@ char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint
|
||||
memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct));
|
||||
|
||||
isbs.augtype = item->AugType;
|
||||
isbs.augdistiller = 0;
|
||||
isbs.augdistiller = 65535;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
|
||||
|
||||
@@ -2519,10 +2519,10 @@ struct Stun_Struct { // 8 bytes total
|
||||
|
||||
struct AugmentItem_Struct {
|
||||
/*00*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented
|
||||
/*04*/ uint32 unknown04; // Seen 0
|
||||
/*04*/ uint32 container_index; // Seen 0
|
||||
/*08*/ ItemSlotStruct container_slot; // Slot of the item being augmented
|
||||
/*20*/ uint32 unknown20; // Seen 0
|
||||
/*24*/ ItemSlotStruct distiller_slot; // Slot of the distiller to use (if one applies)
|
||||
/*20*/ uint32 augment_index; // Seen 0
|
||||
/*24*/ ItemSlotStruct augment_slot; // Slot of the distiller to use (if one applies)
|
||||
/*36*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug
|
||||
/*36*/ //int32 augment_slot;
|
||||
/*40*/
|
||||
|
||||
+15
-10
@@ -143,19 +143,22 @@ uint32 SharedDatabase::GetTotalTimeEntitledOnAccount(uint32 AccountID) {
|
||||
|
||||
bool SharedDatabase::SaveCursor(uint32 char_id, std::list<ItemInst*>::const_iterator &start, std::list<ItemInst*>::const_iterator &end)
|
||||
{
|
||||
iter_queue it;
|
||||
int i;
|
||||
bool ret=true;
|
||||
iter_queue it;
|
||||
int i;
|
||||
bool ret = true;
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char* query = 0;
|
||||
// Delete cursor items
|
||||
if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid=%i AND ( (slotid >=8000 and slotid<=8999) or slotid=%i or (slotid>=%i and slotid<=%i))", char_id, MainCursor,EmuConstants::CURSOR_BAG_BEGIN,EmuConstants::CURSOR_BAG_END), errbuf))) {
|
||||
for(it=start,i=8000;it!=end;++it,i++) {
|
||||
ItemInst *inst=*it;
|
||||
if (!(ret=SaveInventory(char_id,inst,(i==8000) ? MainCursor : i)))
|
||||
if ((ret = RunQuery(query, MakeAnyLenString(&query, "DELETE FROM inventory WHERE charid = %i AND ((slotid >= 8000 AND slotid <= 8999) OR slotid = %i OR (slotid >= %i AND slotid <= %i))",
|
||||
char_id, MainCursor, EmuConstants::CURSOR_BAG_BEGIN, EmuConstants::CURSOR_BAG_END), errbuf))) {
|
||||
|
||||
for (it = start, i = 8000; it != end; ++it, i++) {
|
||||
ItemInst *inst = *it;
|
||||
if (!(ret = SaveInventory(char_id, inst, (i == 8000) ? MainCursor : i)))
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
std::cout << "Clearing cursor failed: " << errbuf << std::endl;
|
||||
}
|
||||
safe_delete_array(query);
|
||||
@@ -2145,7 +2148,8 @@ void SharedDatabase::SetPlayerInspectMessage(char* playername, const InspectMess
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", message->text, playername), errbuf)) {
|
||||
std::string msg = EscapeString(message->text);
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE character_ SET inspectmessage='%s' WHERE name='%s'", msg.c_str(), playername), errbuf)) {
|
||||
std::cerr << "Error in SetPlayerInspectMessage query '" << query << "' " << errbuf << std::endl;
|
||||
}
|
||||
|
||||
@@ -2180,7 +2184,8 @@ void SharedDatabase::SetBotInspectMessage(uint32 botid, const InspectMessage_Str
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", message->text, botid), errbuf)) {
|
||||
std::string msg = EscapeString(message->text);
|
||||
if (!RunQuery(query, MakeAnyLenString(&query, "UPDATE bots SET BotInspectMessage='%s' WHERE BotID=%i", msg.c_str(), botid), errbuf)) {
|
||||
std::cerr << "Error in SetBotInspectMessage query '" << query << "' " << errbuf << std::endl;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -522,7 +522,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status`=4 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireTrash));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__ERROR, "Error expiring trash messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
else
|
||||
_log(UCS__INIT, "Expired %i trash messages.", results.RowsAffected());
|
||||
@@ -534,7 +534,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status` = 3 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireRead));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__INIT, "Expired %i read messages.", results.RowsAffected());
|
||||
else
|
||||
_log(UCS__ERROR, "Error expiring read messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
@@ -545,7 +545,7 @@ void Database::ExpireMail() {
|
||||
query = StringFormat("DELETE FROM `mail` WHERE `status`=1 AND `timestamp` < %i",
|
||||
time(nullptr) - RuleI(Mail, ExpireUnread));
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
if(results.Success())
|
||||
_log(UCS__INIT, "Expired %i unread messages.", results.RowsAffected());
|
||||
else
|
||||
_log(UCS__ERROR, "Error expiring unread messages, %s %s", query.c_str(), results.ErrorMessage().c_str());
|
||||
|
||||
@@ -125,6 +125,7 @@ OP_GuildLeader=0x7c6f
|
||||
OP_GuildDelete=0x241b
|
||||
OP_GuildInviteAccept=0x78a5
|
||||
OP_GuildDemote=0x3100
|
||||
OP_GuildPromote=0x2945
|
||||
OP_GuildPublicNote=0x3c2c
|
||||
OP_GuildManageBanker=0x096d # Was 0x0737
|
||||
OP_GuildBank=0x2ab0 # Was 0x10c3
|
||||
|
||||
@@ -23,8 +23,8 @@ VERBOSE = False # messaging: {False - minimal, True - robust}
|
||||
base_path = os.getcwd()[:-14] # '/utils/scripts'
|
||||
base_path = base_path.replace('\\', '/')
|
||||
|
||||
client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2', 'ClientTest']
|
||||
server_list = ['Login', 'World', 'Zone', 'UCS', 'ServerTest']
|
||||
client_list = ['6.2', 'Titanium', 'SoF', 'SoD', 'Underfoot', 'RoF', 'RoF2']
|
||||
server_list = ['Login', 'World', 'Zone', 'UCS']
|
||||
|
||||
client_opcodes = {} # x[key='Client'][key='OP_CodeName'](value='0x####')
|
||||
server_opcodes = {} # x[key='OP_CodeName'](value=<integer>) - opcodes apply to all servers
|
||||
@@ -248,7 +248,7 @@ def loadclientopcodes():
|
||||
|
||||
for client in client_list:
|
||||
try:
|
||||
short_name = '/patch_{0}.conf'.format(client)
|
||||
short_name = '/patch_{0}.conf'.format(client).lower()
|
||||
|
||||
file_name = '{0}/utils/patches{1}'.format(
|
||||
base_path,
|
||||
@@ -455,9 +455,9 @@ def loadclienttranslators():
|
||||
for client in client_list:
|
||||
try:
|
||||
if client == '6.2':
|
||||
short_name = '/Client62_ops.h'
|
||||
short_name = '/client62_ops.h'
|
||||
else:
|
||||
short_name = '/{0}_ops.h'.format(client)
|
||||
short_name = '/{0}_ops.h'.format(client).lower()
|
||||
|
||||
file_name = '{0}/common/patches{1}'.format(
|
||||
base_path,
|
||||
@@ -734,15 +734,15 @@ def discoverserverhandlers():
|
||||
locations[server] = []
|
||||
|
||||
if 'Login' in locations:
|
||||
locations['Login'].append('/loginserver/Client.cpp')
|
||||
locations['Login'].append('/loginserver/ServerManager.cpp')
|
||||
locations['Login'].append('/loginserver/WorldServer.cpp')
|
||||
locations['Login'].append('/loginserver/client.cpp')
|
||||
locations['Login'].append('/loginserver/server_manager.cpp')
|
||||
locations['Login'].append('/loginserver/world_server.cpp')
|
||||
|
||||
if 'World' in locations:
|
||||
locations['World'].append('/world/client.cpp')
|
||||
|
||||
if 'Zone' in locations:
|
||||
locations['Zone'].append('/zone/AA.cpp')
|
||||
locations['Zone'].append('/zone/aa.cpp')
|
||||
locations['Zone'].append('/zone/attack.cpp')
|
||||
locations['Zone'].append('/zone/bot.cpp')
|
||||
locations['Zone'].append('/zone/client.cpp')
|
||||
@@ -762,8 +762,8 @@ def discoverserverhandlers():
|
||||
locations['Zone'].append('/zone/loottables.cpp')
|
||||
locations['Zone'].append('/zone/merc.cpp')
|
||||
locations['Zone'].append('/zone/mob.cpp')
|
||||
locations['Zone'].append('/zone/MobAI.cpp')
|
||||
locations['Zone'].append('/zone/Object.cpp')
|
||||
locations['Zone'].append('/zone/mob_ai.cpp')
|
||||
locations['Zone'].append('/zone/object.cpp')
|
||||
locations['Zone'].append('/zone/pathing.cpp')
|
||||
locations['Zone'].append('/zone/petitions.cpp')
|
||||
locations['Zone'].append('/zone/questmgr.cpp')
|
||||
|
||||
@@ -715,7 +715,7 @@ bool AdventureManager::LoadAdventureEntries()
|
||||
|
||||
std::list<AdventureTemplate*> temp;
|
||||
auto iter = adventure_entries.find(id);
|
||||
if(iter == adventure_entries.end())
|
||||
if(iter != adventure_entries.end())
|
||||
temp = adventure_entries[id];
|
||||
|
||||
temp.push_back(tid);
|
||||
|
||||
@@ -11741,8 +11741,6 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
if(!strcasecmp(sep->arg[1], "augmentitem")) {
|
||||
AugmentItem_Struct* in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)];
|
||||
in_augment->container_slot = 1000; // <watch>
|
||||
in_augment->unknown02[0] = 0;
|
||||
in_augment->unknown02[1] = 0;
|
||||
in_augment->augment_slot = -1;
|
||||
Object::HandleAugmentation(c, in_augment, c->GetTradeskillObject());
|
||||
return;
|
||||
|
||||
+13
-1
@@ -7978,7 +7978,7 @@ void Client::ItemTimerCheck()
|
||||
TryItemTimer(i);
|
||||
}
|
||||
|
||||
for(i = EmuConstants::GENERAL_BAGS_BEGIN; i <= MainCursor; i++)
|
||||
for(i = EmuConstants::GENERAL_BEGIN; i <= MainCursor; i++)
|
||||
{
|
||||
TryItemTimer(i);
|
||||
}
|
||||
@@ -8334,3 +8334,15 @@ void Client::ExpeditionSay(const char *str, int ExpID) {
|
||||
mysql_free_result(result);
|
||||
|
||||
}
|
||||
|
||||
void Client::ShowNumHits()
|
||||
{
|
||||
uint32 buffcount = GetMaxTotalSlots();
|
||||
for (uint32 buffslot = 0; buffslot < buffcount; buffslot++) {
|
||||
const Buffs_Struct &curbuff = buffs[buffslot];
|
||||
if (curbuff.spellid != SPELL_UNKNOWN && curbuff.numhits)
|
||||
Message(0, "You have %d hits left on %s", curbuff.numhits, GetSpellName(curbuff.spellid));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1200,7 +1200,9 @@ public:
|
||||
|
||||
void SetEngagedRaidTarget(bool value) { EngagedRaidTarget = value; }
|
||||
bool GetEngagedRaidTarget() const { return EngagedRaidTarget; }
|
||||
|
||||
|
||||
void ShowNumHits(); // work around function for numhits not showing on buffs
|
||||
|
||||
protected:
|
||||
friend class Mob;
|
||||
void CalcItemBonuses(StatBonuses* newbon);
|
||||
|
||||
+227
-8
@@ -190,6 +190,7 @@ void MapOpcodes() {
|
||||
ConnectedOpcodes[OP_GuildWar] = &Client::Handle_OP_GuildWar;
|
||||
ConnectedOpcodes[OP_GuildLeader] = &Client::Handle_OP_GuildLeader;
|
||||
ConnectedOpcodes[OP_GuildDemote] = &Client::Handle_OP_GuildDemote;
|
||||
ConnectedOpcodes[OP_GuildPromote] = &Client::Handle_OP_GuildPromote;
|
||||
ConnectedOpcodes[OP_GuildInvite] = &Client::Handle_OP_GuildInvite;
|
||||
ConnectedOpcodes[OP_GuildRemove] = &Client::Handle_OP_GuildRemove;
|
||||
ConnectedOpcodes[OP_GetGuildMOTD] = &Client::Handle_OP_GetGuildMOTD;
|
||||
@@ -4088,7 +4089,7 @@ void Client::Handle_OP_GuildLeader(const EQApplicationPacket *app)
|
||||
GuildMakeLeader* gml=(GuildMakeLeader*)app->pBuffer;
|
||||
if (!IsInAGuild())
|
||||
Message(0, "Error: You arent in a guild!");
|
||||
else if (!guild_mgr.IsGuildLeader(GuildID(), CharacterID()))
|
||||
else if (GuildRank() != GUILD_LEADER)
|
||||
Message(0, "Error: You arent the guild leader!");
|
||||
else if (!worldserver.Connected())
|
||||
Message(0, "Error: World server disconnected");
|
||||
@@ -4169,6 +4170,57 @@ void Client::Handle_OP_GuildDemote(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Client::Handle_OP_GuildPromote(const EQApplicationPacket *app)
|
||||
{
|
||||
mlog(GUILDS__IN_PACKETS, "Received OP_GuildPromote");
|
||||
mpkt(GUILDS__IN_PACKET_TRACE, app);
|
||||
|
||||
if(app->size != sizeof(GuildPromoteStruct)) {
|
||||
mlog(GUILDS__ERROR, "Error: app size of %i != size of GuildDemoteStruct of %i\n",app->size,sizeof(GuildPromoteStruct));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsInAGuild())
|
||||
Message(0, "Error: You arent in a guild!");
|
||||
else if (!guild_mgr.CheckPermission(GuildID(), GuildRank(), GUILD_PROMOTE))
|
||||
Message(0, "You dont have permission to invite.");
|
||||
else if (!worldserver.Connected())
|
||||
Message(0, "Error: World server disconnected");
|
||||
else {
|
||||
GuildPromoteStruct* promote = (GuildPromoteStruct*)app->pBuffer;
|
||||
|
||||
CharGuildInfo gci;
|
||||
if(!guild_mgr.GetCharInfo(promote->target, gci)) {
|
||||
Message(0, "Unable to find '%s'", promote->target);
|
||||
return;
|
||||
}
|
||||
if(gci.guild_id != GuildID()) {
|
||||
Message(0, "You aren't in the same guild, what do you think you are doing?");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 rank = gci.rank + 1;
|
||||
|
||||
if(rank > GUILD_OFFICER)
|
||||
return;
|
||||
|
||||
|
||||
mlog(GUILDS__ACTIONS, "Promoting %s (%d) from rank %s (%d) to %s (%d) in %s (%d)",
|
||||
promote->target, gci.char_id,
|
||||
guild_mgr.GetRankName(GuildID(), gci.rank), gci.rank,
|
||||
guild_mgr.GetRankName(GuildID(), rank), rank,
|
||||
guild_mgr.GetGuildName(GuildID()), GuildID());
|
||||
|
||||
if(!guild_mgr.SetGuildRank(gci.char_id, rank)) {
|
||||
Message(13, "Error while setting rank %d on '%s'.", rank, promote->target);
|
||||
return;
|
||||
}
|
||||
Message(0, "Successfully promoted %s to rank %d", promote->target, rank);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_GuildInvite(const EQApplicationPacket *app)
|
||||
{
|
||||
mlog(GUILDS__IN_PACKETS, "Received OP_GuildInvite");
|
||||
@@ -4379,6 +4431,16 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app)
|
||||
|
||||
GuildInviteAccept_Struct* gj = (GuildInviteAccept_Struct*) app->pBuffer;
|
||||
|
||||
if(GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
if(gj->response > 9)
|
||||
{
|
||||
//dont care if the check fails (since we dont know the rank), just want to clear the entry.
|
||||
guild_mgr.VerifyAndClearInvite(CharacterID(), gj->guildeqid, gj->response);
|
||||
worldserver.SendEmoteMessage(gj->inviter, 0, 0, "%s has declined to join the guild.", this->GetName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (gj->response == 5 || gj->response == 4) {
|
||||
//dont care if the check fails (since we dont know the rank), just want to clear the entry.
|
||||
guild_mgr.VerifyAndClearInvite(CharacterID(), gj->guildeqid, gj->response);
|
||||
@@ -4424,15 +4486,24 @@ void Client::Handle_OP_GuildInviteAccept(const EQApplicationPacket *app)
|
||||
guild_mgr.GetGuildName(gj->guildeqid), gj->guildeqid,
|
||||
gj->response);
|
||||
|
||||
//change guild and rank.
|
||||
if(!guild_mgr.SetGuild(CharacterID(), gj->guildeqid, gj->response)) {
|
||||
//change guild and rank
|
||||
|
||||
uint32 guildrank = gj->response;
|
||||
|
||||
if(GetClientVersion() == EQClientRoF)
|
||||
{
|
||||
if(gj->response == 8)
|
||||
{
|
||||
guildrank = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!guild_mgr.SetGuild(CharacterID(), gj->guildeqid, guildrank)) {
|
||||
Message(13, "There was an error during the invite, DB may now be inconsistent.");
|
||||
return;
|
||||
}
|
||||
if(zone->GetZoneID() == RuleI(World, GuildBankZoneID) && GuildBanks)
|
||||
GuildBanks->SendGuildBank(this);
|
||||
SendGuildRanks();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6210,7 +6281,145 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
|
||||
|
||||
// Delegate to tradeskill object to perform combine
|
||||
AugmentItem_Struct* in_augment = (AugmentItem_Struct*)app->pBuffer;
|
||||
Object::HandleAugmentation(this, in_augment, m_tradeskill_object);
|
||||
bool deleteItems = false;
|
||||
if(GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
ItemInst *itemOneToPush = nullptr, *itemTwoToPush = nullptr;
|
||||
|
||||
//Message(15, "%i %i %i %i %i %i", in_augment->container_slot, in_augment->augment_slot, in_augment->container_index, in_augment->augment_index, in_augment->augment_action, in_augment->dest_inst_id);
|
||||
|
||||
// Adding augment
|
||||
if (in_augment->augment_action == 0)
|
||||
{
|
||||
ItemInst *tobe_auged, *auged_with = nullptr;
|
||||
int8 slot=-1;
|
||||
Inventory& user_inv = GetInv();
|
||||
|
||||
uint16 slot_id = in_augment->container_slot;
|
||||
uint16 aug_slot_id = in_augment->augment_slot;
|
||||
//Message(13, "%i AugSlot", aug_slot_id);
|
||||
if(slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX)
|
||||
{
|
||||
Message(13, "Error: Invalid Aug Index.");
|
||||
return;
|
||||
}
|
||||
|
||||
tobe_auged = user_inv.GetItem(slot_id);
|
||||
auged_with = user_inv.GetItem(MainCursor);
|
||||
|
||||
if (tobe_auged && auged_with)
|
||||
{
|
||||
if (((tobe_auged->IsAugmentSlotAvailable(auged_with->GetAugmentType(), in_augment->augment_index)) != -1) &&
|
||||
(tobe_auged->AvailableWearSlot(auged_with->GetItem()->Slots)))
|
||||
{
|
||||
tobe_auged->PutAugment(in_augment->augment_index, *auged_with);
|
||||
|
||||
ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if(aug) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_AUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
parse->EventItem(EVENT_AUGMENT_INSERT, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation at index %i. Aborting.", in_augment->augment_index);
|
||||
return;
|
||||
}
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
// Must push items after the items in inventory are deleted - necessary due to lore items...
|
||||
if (itemOneToPush)
|
||||
{
|
||||
DeleteItemInInventory(slot_id, 0, true);
|
||||
DeleteItemInInventory(MainCursor, 0, true);
|
||||
if(PutItemInInventory(slot_id, *itemOneToPush, true))
|
||||
{
|
||||
//Message(13, "Sucessfully added an augment to your item!");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for end result. Please free up some bag space.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error in cloning item for augment. Aborted.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: No available slot for augment in that item.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(in_augment->augment_action == 1)
|
||||
{
|
||||
ItemInst *tobe_auged, *auged_with = nullptr;
|
||||
int8 slot=-1;
|
||||
Inventory& user_inv = GetInv();
|
||||
|
||||
uint16 slot_id = in_augment->container_slot;
|
||||
uint16 aug_slot_id = in_augment->augment_slot; //it's actually solvent slot
|
||||
if(slot_id == INVALID_INDEX || aug_slot_id == INVALID_INDEX)
|
||||
{
|
||||
Message(13, "Error: Invalid Aug Index.");
|
||||
return;
|
||||
}
|
||||
|
||||
tobe_auged = user_inv.GetItem(slot_id);
|
||||
auged_with = user_inv.GetItem(aug_slot_id);
|
||||
|
||||
ItemInst *old_aug = nullptr;
|
||||
if(!auged_with)
|
||||
return;
|
||||
const uint32 id = auged_with->GetID();
|
||||
ItemInst *aug = tobe_auged->GetAugment(in_augment->augment_index);
|
||||
if(aug) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(aug);
|
||||
parse->EventItem(EVENT_UNAUGMENT_ITEM, this, tobe_auged, nullptr, "", in_augment->augment_index, &args);
|
||||
|
||||
args.assign(1, tobe_auged);
|
||||
|
||||
args.push_back(false);
|
||||
|
||||
parse->EventItem(EVENT_AUGMENT_REMOVE, this, aug, nullptr, "", in_augment->augment_index, &args);
|
||||
}
|
||||
else
|
||||
{
|
||||
Message(13, "Error: Could not find augmentation at index %i. Aborting.");
|
||||
return;
|
||||
}
|
||||
old_aug = tobe_auged->RemoveAugment(in_augment->augment_index);
|
||||
|
||||
itemOneToPush = tobe_auged->Clone();
|
||||
if (old_aug)
|
||||
itemTwoToPush = old_aug->Clone();
|
||||
if(itemOneToPush && itemTwoToPush && auged_with)
|
||||
{
|
||||
DeleteItemInInventory(slot_id, 0, true);
|
||||
DeleteItemInInventory(aug_slot_id, auged_with->IsStackable() ? 1 : 0, true);
|
||||
if(!PutItemInInventory(slot_id, *itemOneToPush, true))
|
||||
{
|
||||
Message(15, "Shouldn't happen, contact an admin!");
|
||||
}
|
||||
|
||||
if(PutItemInInventory(MainCursor, *itemTwoToPush, true))
|
||||
{
|
||||
//Message(15, "Successfully removed an augmentation!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Object::HandleAugmentation(this, in_augment, m_tradeskill_object);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6225,7 +6434,7 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app)
|
||||
if(!currentdoor)
|
||||
{
|
||||
Message(0,"Unable to find door, please notify a GM (DoorID: %i).",cd->doorid);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[20];
|
||||
@@ -9301,8 +9510,18 @@ void Client::CompleteConnect() {
|
||||
UpdateAdmin(false);
|
||||
|
||||
if (IsInAGuild()){
|
||||
uint8 rank = GuildRank();
|
||||
if(GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
switch (rank) {
|
||||
case 0: { rank = 5; break; } // GUILD_MEMBER 0
|
||||
case 1: { rank = 3; break; } // GUILD_OFFICER 1
|
||||
case 2: { rank = 1; break; } // GUILD_LEADER 2
|
||||
default: { break; } // GUILD_NONE
|
||||
}
|
||||
}
|
||||
SendAppearancePacket(AT_GuildID, GuildID(), false);
|
||||
SendAppearancePacket(AT_GuildRank, GuildRank(), false);
|
||||
SendAppearancePacket(AT_GuildRank, rank, false);
|
||||
}
|
||||
for (uint32 spellInt = 0; spellInt < MAX_PP_SPELLBOOK; spellInt++)
|
||||
{
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
void Handle_OP_GuildWar(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildLeader(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildDemote(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildPromote(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildInvite(const EQApplicationPacket *app);
|
||||
void Handle_OP_GuildRemove(const EQApplicationPacket *app);
|
||||
void Handle_OP_GetGuildMOTD(const EQApplicationPacket *app);
|
||||
|
||||
@@ -836,8 +836,6 @@ void Client::BulkSendInventoryItems() {
|
||||
}
|
||||
}
|
||||
|
||||
// Where are cursor buffer items processed? They need to be validated as well... -U
|
||||
|
||||
bool deletenorent = database.NoRentExpired(GetName());
|
||||
if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items
|
||||
|
||||
|
||||
+10
-5
@@ -453,7 +453,8 @@ int command_init(void) {
|
||||
command_add("merchant_open_shop", "Opens a merchants shop", 100, command_merchantopenshop) ||
|
||||
command_add("open_shop", nullptr, 100, command_merchantopenshop) ||
|
||||
command_add("merchant_close_shop", "Closes a merchant shop", 100, command_merchantcloseshop) ||
|
||||
command_add("close_shop", nullptr, 100, command_merchantcloseshop)
|
||||
command_add("close_shop", nullptr, 100, command_merchantcloseshop) ||
|
||||
command_add("shownumhits", "Shows buffs numhits for yourself.", 0, command_shownumhits)
|
||||
)
|
||||
{
|
||||
command_deinit();
|
||||
@@ -4692,7 +4693,7 @@ void command_loc(Client *c, const Seperator *sep)
|
||||
{
|
||||
Mob *t=c->GetTarget()?c->GetTarget():c->CastToMob();
|
||||
|
||||
c->Message(0, "%s's Location (XYZ): %1.1f, %1.1f, %1.1f; heading=%1.1f", t->GetName(), t->GetX(), t->GetY(), t->GetZ(), t->GetHeading());
|
||||
c->Message(0, "%s's Location (XYZ): %1.2f, %1.2f, %1.2f; heading=%1.1f", t->GetName(), t->GetX(), t->GetY(), t->GetZ(), t->GetHeading());
|
||||
}
|
||||
|
||||
void command_goto(Client *c, const Seperator *sep)
|
||||
@@ -6767,7 +6768,7 @@ void command_npcedit(Client *c, const Seperator *sep)
|
||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
||||
char *query = 0;
|
||||
c->Message(15,"NPCID %u now regens %i hitpoints per tick.",c->GetTarget()->CastToNPC()->GetNPCTypeID(),atoi(sep->arg[2]));
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set hp_regen_rate=%i where hp_regen_rate=%i",atoi(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf);
|
||||
database.RunQuery(query, MakeAnyLenString(&query, "update npc_types set hp_regen_rate=%i where id=%i",atoi(sep->argplus[2]),c->GetTarget()->CastToNPC()->GetNPCTypeID()), errbuf);
|
||||
c->LogSQL(query);
|
||||
safe_delete_array(query);
|
||||
}
|
||||
@@ -11429,8 +11430,6 @@ void command_augmentitem(Client *c, const Seperator *sep)
|
||||
|
||||
AugmentItem_Struct* in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)];
|
||||
in_augment->container_slot = 1000; // <watch>
|
||||
in_augment->unknown02[0] = 0;
|
||||
in_augment->unknown02[1] = 0;
|
||||
in_augment->augment_slot = -1;
|
||||
if(c->GetTradeskillObject() != nullptr)
|
||||
Object::HandleAugmentation(c, in_augment, c->GetTradeskillObject());
|
||||
@@ -11557,3 +11556,9 @@ void command_merchantcloseshop(Client *c, const Seperator *sep)
|
||||
|
||||
merchant->CastToNPC()->MerchantCloseShop();
|
||||
}
|
||||
|
||||
void command_shownumhits(Client *c, const Seperator *sep)
|
||||
{
|
||||
c->ShowNumHits();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -325,6 +325,7 @@ void command_showspellslist(Client *c, const Seperator *sep);
|
||||
void command_npctype_cache(Client *c, const Seperator *sep);
|
||||
void command_merchantopenshop(Client *c, const Seperator *sep);
|
||||
void command_merchantcloseshop(Client *c, const Seperator *sep);
|
||||
void command_shownumhits(Client *c, const Seperator *sep);
|
||||
|
||||
#ifdef EQPROFILE
|
||||
void command_profiledump(Client *c, const Seperator *sep);
|
||||
|
||||
+3
-1
@@ -1130,8 +1130,10 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
|
||||
|
||||
case EVENT_TRADE: {
|
||||
if(extra_pointers) {
|
||||
for(size_t i = 0; i < extra_pointers->size(); ++i) {
|
||||
size_t sz = extra_pointers->size();
|
||||
for(size_t i = 0; i < sz; ++i) {
|
||||
ItemInst *inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
|
||||
|
||||
std::string var_name = "item";
|
||||
var_name += std::to_string(static_cast<long long>(i + 1));
|
||||
|
||||
|
||||
+2
-1
@@ -3242,7 +3242,8 @@ void EntityList::ProcessMove(Client *c, float x, float y, float z)
|
||||
for (auto iter = events.begin(); iter != events.end(); ++iter) {
|
||||
quest_proximity_event& evt = (*iter);
|
||||
if (evt.npc) {
|
||||
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0);
|
||||
std::vector<EQEmu::Any> args;
|
||||
parse->EventNPC(evt.event_id, evt.npc, evt.client, "", 0, &args);
|
||||
} else {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(&evt.area_id);
|
||||
|
||||
+13
-9
@@ -235,7 +235,7 @@ bool Client::CanFish() {
|
||||
dest.y = RodY;
|
||||
dest.z = z_pos+10;
|
||||
|
||||
RodZ = zone->zonemap->FindBestZ(dest, nullptr) - 1;
|
||||
RodZ = zone->zonemap->FindBestZ(dest, nullptr) + 4;
|
||||
bool in_lava = zone->watermap->InLava(RodX, RodY, RodZ);
|
||||
bool in_water = zone->watermap->InWater(RodX, RodY, RodZ) || zone->watermap->InVWater(RodX, RodY, RodZ);
|
||||
//Message(0, "Rod is at %4.3f, %4.3f, %4.3f, InWater says %d, InLava says %d", RodX, RodY, RodZ, in_water, in_lava);
|
||||
@@ -355,11 +355,13 @@ void Client::GoFish()
|
||||
safe_delete(inst);
|
||||
inst = m_inv.GetItem(MainCursor);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(inst);
|
||||
parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst != nullptr ? inst->GetItem()->ID : 0, &args);
|
||||
if(inst) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(inst);
|
||||
parse->EventPlayer(EVENT_FISH_SUCCESS, this, "", inst->GetID(), &args);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -469,11 +471,13 @@ void Client::ForageItem(bool guarantee) {
|
||||
safe_delete(inst);
|
||||
inst = m_inv.GetItem(MainCursor);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(inst);
|
||||
parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst ? inst->GetItem()->ID : 0, &args);
|
||||
if(inst) {
|
||||
std::vector<EQEmu::Any> args;
|
||||
args.push_back(inst);
|
||||
parse->EventPlayer(EVENT_FORAGE_SUCCESS, this, "", inst->GetID(), &args);
|
||||
}
|
||||
}
|
||||
|
||||
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
|
||||
if(!guarantee && MakeRandomInt(0,99) < ChanceSecondForage) {
|
||||
|
||||
+9
-1
@@ -160,9 +160,17 @@ void Client::SendGuildSpawnAppearance() {
|
||||
uint8 rank = guild_mgr.GetDisplayedRank(GuildID(), GuildRank(), CharacterID());
|
||||
mlog(GUILDS__OUT_PACKETS, "Sending spawn appearance for guild %d at rank %d", GuildID(), rank);
|
||||
SendAppearancePacket(AT_GuildID, GuildID());
|
||||
if(GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
switch (rank) {
|
||||
case 0: { rank = 5; break; } // GUILD_MEMBER 0
|
||||
case 1: { rank = 3; break; } // GUILD_OFFICER 1
|
||||
case 2: { rank = 1; break; } // GUILD_LEADER 2
|
||||
default: { break; } // GUILD_NONE
|
||||
}
|
||||
}
|
||||
SendAppearancePacket(AT_GuildRank, rank);
|
||||
}
|
||||
|
||||
UpdateWho();
|
||||
}
|
||||
|
||||
|
||||
+19
-8
@@ -374,6 +374,10 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) {
|
||||
else if(c != nullptr && s->guild_id != GUILD_NONE) {
|
||||
//char is in zone, and has changed into a new guild, send MOTD.
|
||||
c->SendGuildMOTD();
|
||||
if(c->GetClientVersion() >= EQClientRoF)
|
||||
{
|
||||
c->SendGuildRanks();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -686,19 +690,26 @@ bool GuildBankManager::Load(uint32 guildID)
|
||||
else
|
||||
whoFor[0] = '\0';
|
||||
|
||||
if(slot < 0 ||
|
||||
((area != GuildBankMainArea || slot >= GUILD_BANK_MAIN_AREA_SIZE) ||
|
||||
(area == GuildBankMainArea || slot >= GUILD_BANK_DEPOSIT_AREA_SIZE)))
|
||||
if(slot < 0)
|
||||
continue;
|
||||
|
||||
bank->Items.MainArea[slot].ItemID = itemID;
|
||||
bank->Items.MainArea[slot].Quantity = qty;
|
||||
GuildBankItem *itemSection = nullptr;
|
||||
|
||||
strn0cpy(bank->Items.MainArea[slot].Donator, donator, sizeof(donator));
|
||||
if (area == GuildBankMainArea && slot < GUILD_BANK_MAIN_AREA_SIZE)
|
||||
itemSection = bank->Items.MainArea;
|
||||
else if (area != GuildBankMainArea && slot < GUILD_BANK_DEPOSIT_AREA_SIZE)
|
||||
itemSection = bank->Items.DepositArea;
|
||||
else
|
||||
continue;
|
||||
|
||||
bank->Items.MainArea[slot].Permissions = permissions;
|
||||
itemSection[slot].ItemID = itemID;
|
||||
itemSection[slot].Quantity = qty;
|
||||
|
||||
strn0cpy(bank->Items.MainArea[slot].WhoFor, whoFor, sizeof(whoFor));
|
||||
strn0cpy(itemSection[slot].Donator, donator, sizeof(donator));
|
||||
|
||||
itemSection[slot].Permissions = permissions;
|
||||
|
||||
strn0cpy(itemSection[slot].WhoFor, whoFor, sizeof(whoFor));
|
||||
}
|
||||
|
||||
Banks.push_back(bank);
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ Mob* HateList::GetClosest(Mob *hater) {
|
||||
++iterator;
|
||||
}
|
||||
|
||||
if (close == 0 && hater->IsNPC() || close->DivineAura())
|
||||
if ((!close && hater->IsNPC()) || (close && close->DivineAura()))
|
||||
close = hater->CastToNPC()->GetHateTop();
|
||||
|
||||
return close;
|
||||
|
||||
+122
-23
@@ -2002,11 +2002,10 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
|
||||
}
|
||||
|
||||
void Client::RemoveNoRent(bool client_update) {
|
||||
int16 slot_id = 0;
|
||||
|
||||
int16 slot_id;
|
||||
|
||||
// personal
|
||||
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
|
||||
// equipment
|
||||
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
@@ -2014,11 +2013,22 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
}
|
||||
}
|
||||
|
||||
// general
|
||||
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
|
||||
const ItemInst* inst = m_inv[slot_id];
|
||||
if (inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
DeleteItemInInventory(slot_id, 0, client_update);
|
||||
}
|
||||
}
|
||||
|
||||
// power source
|
||||
const ItemInst* inst = m_inv[MainPowerSource];
|
||||
if(inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource);
|
||||
DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
|
||||
if (m_inv[MainPowerSource]) {
|
||||
const ItemInst* inst = m_inv[MainPowerSource];
|
||||
if (inst && !inst->GetItem()->NoRent) {
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from slot %i", inst->GetItem()->Name, MainPowerSource);
|
||||
DeleteItemInInventory(MainPowerSource, 0, (GetClientVersion() >= EQClientSoF) ? client_update : false); // Ti slot non-existent
|
||||
}
|
||||
}
|
||||
|
||||
// containers
|
||||
@@ -2065,15 +2075,42 @@ void Client::RemoveNoRent(bool client_update) {
|
||||
DeleteItemInInventory(slot_id, 0, false); // Can't delete from client Shared Bank Container slots
|
||||
}
|
||||
}
|
||||
|
||||
// cursor & limbo
|
||||
if (!m_inv.CursorEmpty()) {
|
||||
std::list<ItemInst*> local;
|
||||
ItemInst* inst = nullptr;
|
||||
|
||||
while (!m_inv.CursorEmpty()) {
|
||||
inst = m_inv.PopItem(MainCursor);
|
||||
if (inst)
|
||||
local.push_back(inst);
|
||||
}
|
||||
|
||||
std::list<ItemInst*>::iterator iter = local.begin();
|
||||
while (iter != local.end()) {
|
||||
inst = *iter;
|
||||
if (!inst->GetItem()->NoRent)
|
||||
mlog(INVENTORY__SLOTS, "NoRent Timer Lapse: Deleting %s from `Limbo`", inst->GetItem()->Name);
|
||||
else
|
||||
m_inv.PushCursor(**iter);
|
||||
|
||||
safe_delete(*iter);
|
||||
iter = local.erase(iter);
|
||||
}
|
||||
|
||||
std::list<ItemInst*>::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end();
|
||||
database.SaveCursor(this->CharacterID(), s, e);
|
||||
local.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Two new methods to alleviate perpetual login desyncs
|
||||
void Client::RemoveDuplicateLore(bool client_update) {
|
||||
// Split-charge stacking may be added at some point -U
|
||||
int16 slot_id;
|
||||
int16 slot_id = 0;
|
||||
|
||||
// personal
|
||||
for(slot_id = MAIN_BEGIN; slot_id < EmuConstants::MAP_POSSESSIONS_SIZE; slot_id++) {
|
||||
// equipment
|
||||
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
@@ -2087,17 +2124,34 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
}
|
||||
}
|
||||
|
||||
// general
|
||||
for (slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; slot_id++) {
|
||||
ItemInst* inst = m_inv.PopItem(slot_id);
|
||||
if (inst) {
|
||||
if (CheckLoreConflict(inst->GetItem())) {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
database.SaveInventory(character_id, nullptr, slot_id);
|
||||
}
|
||||
else {
|
||||
m_inv.PutItem(slot_id, *inst);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
}
|
||||
|
||||
// power source
|
||||
ItemInst* inst = m_inv.PopItem(MainPowerSource);
|
||||
if(inst) {
|
||||
if(CheckLoreConflict(inst->GetItem())) {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
database.SaveInventory(character_id, nullptr, MainPowerSource);
|
||||
if (m_inv[MainPowerSource]) {
|
||||
ItemInst* inst = m_inv.PopItem(MainPowerSource);
|
||||
if (inst) {
|
||||
if (CheckLoreConflict(inst->GetItem())) {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from slot %i", inst->GetItem()->Name, slot_id);
|
||||
database.SaveInventory(character_id, nullptr, MainPowerSource);
|
||||
}
|
||||
else {
|
||||
m_inv.PutItem(MainPowerSource, *inst);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
else {
|
||||
m_inv.PutItem(MainPowerSource, *inst);
|
||||
}
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
// containers
|
||||
@@ -2146,11 +2200,56 @@ void Client::RemoveDuplicateLore(bool client_update) {
|
||||
}
|
||||
|
||||
// Shared Bank and Shared Bank Containers are not checked due to their allowing duplicate lore items -U
|
||||
|
||||
// cursor & limbo
|
||||
if (!m_inv.CursorEmpty()) {
|
||||
std::list<ItemInst*> local;
|
||||
ItemInst* inst = nullptr;
|
||||
|
||||
while (!m_inv.CursorEmpty()) {
|
||||
inst = m_inv.PopItem(MainCursor);
|
||||
if (inst)
|
||||
local.push_back(inst);
|
||||
}
|
||||
|
||||
std::list<ItemInst*>::iterator iter = local.begin();
|
||||
while (iter != local.end()) {
|
||||
inst = *iter;
|
||||
if (CheckLoreConflict(inst->GetItem())) {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
|
||||
safe_delete(*iter);
|
||||
iter = local.erase(iter);
|
||||
}
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
iter = local.begin();
|
||||
while (iter != local.end()) {
|
||||
inst = *iter;
|
||||
if (!inst->GetItem()->LoreFlag ||
|
||||
((inst->GetItem()->LoreGroup == -1) && (m_inv.HasItem(inst->GetID(), 0, invWhereCursor) == INVALID_INDEX)) ||
|
||||
(inst->GetItem()->LoreGroup && ~inst->GetItem()->LoreGroup && (m_inv.HasItemByLoreGroup(inst->GetItem()->LoreGroup, invWhereCursor) == INVALID_INDEX))) {
|
||||
|
||||
m_inv.PushCursor(**iter);
|
||||
}
|
||||
else {
|
||||
mlog(INVENTORY__ERROR, "Lore Duplication Error: Deleting %s from `Limbo`", inst->GetItem()->Name);
|
||||
}
|
||||
|
||||
safe_delete(*iter);
|
||||
iter = local.erase(iter);
|
||||
}
|
||||
|
||||
std::list<ItemInst*>::const_iterator s = m_inv.cursor_begin(), e = m_inv.cursor_end();
|
||||
database.SaveCursor(this->CharacterID(), s, e);
|
||||
local.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Client::MoveSlotNotAllowed(bool client_update) {
|
||||
|
||||
int16 slot_id;
|
||||
int16 slot_id = 0;
|
||||
|
||||
// equipment
|
||||
for(slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; slot_id++) {
|
||||
|
||||
@@ -416,6 +416,11 @@ void Lua_EntityList::SignalAllClients(int signal) {
|
||||
self->SignalAllClients(signal);
|
||||
}
|
||||
|
||||
void Lua_EntityList::ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->ChannelMessage(from, channel_num, language, message);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_entity_list() {
|
||||
return luabind::class_<Lua_EntityList>("EntityList")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -479,7 +484,8 @@ luabind::scope lua_register_entity_list() {
|
||||
.def("GetObjectList", (Lua_Object_List(Lua_EntityList::*)(void))&Lua_EntityList::GetObjectList)
|
||||
.def("GetDoorsList", (Lua_Doors_List(Lua_EntityList::*)(void))&Lua_EntityList::GetDoorsList)
|
||||
.def("GetSpawnList", (Lua_Spawn_List(Lua_EntityList::*)(void))&Lua_EntityList::GetSpawnList)
|
||||
.def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients);
|
||||
.def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients)
|
||||
.def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob,int,int,const char*))&Lua_EntityList::ChannelMessage);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_mob_list() {
|
||||
|
||||
@@ -106,6 +106,7 @@ public:
|
||||
Lua_Doors_List GetDoorsList();
|
||||
Lua_Spawn_List GetSpawnList();
|
||||
void SignalAllClients(int signal);
|
||||
void ChannelMessage(Lua_Mob from, int channel_num, int language, const char *message);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1451,11 +1451,7 @@ luabind::scope lua_register_slot() {
|
||||
luabind::value("General6", static_cast<int>(MainGeneral6)),
|
||||
luabind::value("General7", static_cast<int>(MainGeneral7)),
|
||||
luabind::value("General8", static_cast<int>(MainGeneral8)),
|
||||
//luabind::value("General9", static_cast<int>(MainGeneral9)),
|
||||
//luabind::value("General10", static_cast<int>(MainGeneral10)),
|
||||
luabind::value("Cursor", static_cast<int>(MainCursor)),
|
||||
//luabind::value("EquipmentBegin", static_cast<int>(EmuConstants::EQUIPMENT_BEGIN)),
|
||||
//luabind::value("EquipmentEnd", static_cast<int>(EmuConstants::EQUIPMENT_END)),
|
||||
luabind::value("PersonalBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)), // deprecated
|
||||
luabind::value("GeneralBegin", static_cast<int>(EmuConstants::GENERAL_BEGIN)),
|
||||
luabind::value("PersonalEnd", static_cast<int>(EmuConstants::GENERAL_END)), // deprecated
|
||||
@@ -1483,7 +1479,6 @@ luabind::scope lua_register_material() {
|
||||
luabind::value("Secondary", static_cast<int>(MaterialSecondary)),
|
||||
luabind::value("Max", static_cast<int>(_MaterialCount)), // deprecated
|
||||
luabind::value("Count", static_cast<int>(_MaterialCount)),
|
||||
//luabind::value("TintCount", static_cast<int>(_MaterialCount - 2)),
|
||||
luabind::value("Invalid", static_cast<int>(_MaterialInvalid))
|
||||
];
|
||||
}
|
||||
@@ -1498,8 +1493,7 @@ luabind::scope lua_register_client_version() {
|
||||
luabind::value("SoF", static_cast<int>(EQClientSoF)),
|
||||
luabind::value("SoD", static_cast<int>(EQClientSoD)),
|
||||
luabind::value("Underfoot", static_cast<int>(EQClientUnderfoot)),
|
||||
luabind::value("RoF", static_cast<int>(EQClientRoF))//,
|
||||
//luabind::value("RoF2", static_cast<int>(EQClientRoF2))
|
||||
luabind::value("RoF", static_cast<int>(EQClientRoF))
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -54,9 +54,12 @@ void handle_npc_event_trade(QuestInterface *parse, lua_State* L, NPC* npc, Mob *
|
||||
ident << npc->GetNPCTypeID();
|
||||
|
||||
if(extra_pointers) {
|
||||
for(size_t i = 0; i < extra_pointers->size(); ++i) {
|
||||
size_t sz = extra_pointers->size();
|
||||
for(size_t i = 0; i < sz; ++i) {
|
||||
std::string prefix = "item" + std::to_string(static_cast<long long>(i + 1));
|
||||
Lua_ItemInst l_inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
|
||||
ItemInst *inst = EQEmu::any_cast<ItemInst*>(extra_pointers->at(i));
|
||||
|
||||
Lua_ItemInst l_inst = inst;
|
||||
luabind::adl::object l_inst_o = luabind::adl::object(L, l_inst);
|
||||
l_inst_o.push(L);
|
||||
|
||||
|
||||
+1
-1
@@ -1460,7 +1460,7 @@ void Mob::SendIllusionPacket(uint16 in_race, uint8 in_gender, uint8 in_texture,
|
||||
else
|
||||
this->drakkin_details = in_drakkin_details;
|
||||
|
||||
if (in_size == 0xFFFFFFFF)
|
||||
if (in_size <= 0.0f)
|
||||
this->size = GetSize();
|
||||
else
|
||||
this->size = in_size;
|
||||
|
||||
+2
-1
@@ -563,7 +563,7 @@ public:
|
||||
uint8 in_haircolor = 0xFF, uint8 in_beardcolor = 0xFF, uint8 in_eyecolor1 = 0xFF, uint8 in_eyecolor2 = 0xFF,
|
||||
uint8 in_hairstyle = 0xFF, uint8 in_luclinface = 0xFF, uint8 in_beard = 0xFF, uint8 in_aa_title = 0xFF,
|
||||
uint32 in_drakkin_heritage = 0xFFFFFFFF, uint32 in_drakkin_tattoo = 0xFFFFFFFF,
|
||||
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = 0xFFFFFFFF);
|
||||
uint32 in_drakkin_details = 0xFFFFFFFF, float in_size = -1.0f);
|
||||
virtual void Stun(int duration);
|
||||
virtual void UnStun();
|
||||
inline void Silence(bool newval) { silenced = newval; }
|
||||
@@ -727,6 +727,7 @@ public:
|
||||
virtual void AI_Init();
|
||||
virtual void AI_Start(uint32 iMoveDelay = 0);
|
||||
virtual void AI_Stop();
|
||||
virtual void AI_ShutDown();
|
||||
virtual void AI_Process();
|
||||
|
||||
const char* GetEntityVariable(const char *id);
|
||||
|
||||
+28
-24
@@ -550,30 +550,6 @@ void Mob::AI_Stop() {
|
||||
safe_delete(AItarget_check_timer);
|
||||
safe_delete(AIscanarea_timer);
|
||||
safe_delete(AIfeignremember_timer);
|
||||
safe_delete(PathingLOSCheckTimer);
|
||||
safe_delete(PathingRouteUpdateTimerShort);
|
||||
safe_delete(PathingRouteUpdateTimerLong);
|
||||
|
||||
attack_timer.Disable();
|
||||
attack_dw_timer.Disable();
|
||||
ranged_timer.Disable();
|
||||
tic_timer.Disable();
|
||||
mana_timer.Disable();
|
||||
spellend_timer.Disable();
|
||||
projectile_timer.Disable();
|
||||
rewind_timer.Disable();
|
||||
bindwound_timer.Disable();
|
||||
stunned_timer.Disable();
|
||||
spun_timer.Disable();
|
||||
bardsong_timer.Disable();
|
||||
gravity_timer.Disable();
|
||||
viral_timer.Disable();
|
||||
flee_timer.Disable();
|
||||
|
||||
for (int sat = 0; sat < MAX_SPECIAL_ATTACK; ++sat) {
|
||||
if (SpecialAbilities[sat].timer)
|
||||
SpecialAbilities[sat].timer->Disable();
|
||||
}
|
||||
|
||||
hate_list.Wipe();
|
||||
}
|
||||
@@ -609,6 +585,34 @@ void Client::AI_Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
// only call this on a zone shutdown event
|
||||
void Mob::AI_ShutDown() {
|
||||
safe_delete(PathingLOSCheckTimer);
|
||||
safe_delete(PathingRouteUpdateTimerShort);
|
||||
safe_delete(PathingRouteUpdateTimerLong);
|
||||
|
||||
attack_timer.Disable();
|
||||
attack_dw_timer.Disable();
|
||||
ranged_timer.Disable();
|
||||
tic_timer.Disable();
|
||||
mana_timer.Disable();
|
||||
spellend_timer.Disable();
|
||||
projectile_timer.Disable();
|
||||
rewind_timer.Disable();
|
||||
bindwound_timer.Disable();
|
||||
stunned_timer.Disable();
|
||||
spun_timer.Disable();
|
||||
bardsong_timer.Disable();
|
||||
gravity_timer.Disable();
|
||||
viral_timer.Disable();
|
||||
flee_timer.Disable();
|
||||
|
||||
for (int sat = 0; sat < MAX_SPECIAL_ATTACK; ++sat) {
|
||||
if (SpecialAbilities[sat].timer)
|
||||
SpecialAbilities[sat].timer->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
//todo: expand the logic here to cover:
|
||||
//redundant debuffs
|
||||
//buffing owner
|
||||
|
||||
+1
-1
@@ -7140,7 +7140,7 @@ XS(XS_Mob_SendIllusion)
|
||||
uint32 drakkin_heritage = 0xFFFFFFFF;
|
||||
uint32 drakkin_tattoo = 0xFFFFFFFF;
|
||||
uint32 drakkin_details = 0xFFFFFFFF;
|
||||
float size = 0xFFFFFFFF;
|
||||
float size = -1.0f;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
|
||||
+7
-9
@@ -4501,13 +4501,12 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
}
|
||||
else
|
||||
{
|
||||
resist_chance -= roll;
|
||||
if(resist_chance < 1)
|
||||
{
|
||||
resist_chance = 1;
|
||||
}
|
||||
|
||||
int partial_modifier = ((150 * (roll - resist_chance)) / resist_chance);
|
||||
int partial_modifier = ((150 * (resist_chance - roll)) / resist_chance);
|
||||
|
||||
if(IsNPC())
|
||||
{
|
||||
@@ -4535,17 +4534,16 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
||||
}
|
||||
}
|
||||
|
||||
if(partial_modifier < 0)
|
||||
if(partial_modifier <= 0)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
else if(partial_modifier >= 100)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(partial_modifier > 100)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
return partial_modifier;
|
||||
return (100.0f - partial_modifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -871,7 +871,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
items[i - EmuConstants::TRADE_BEGIN] = inst->GetItem()->ID;
|
||||
item_list.push_back(inst);
|
||||
} else {
|
||||
item_list.push_back(nullptr);
|
||||
item_list.push_back((ItemInst*)nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+20
-19
@@ -1245,45 +1245,45 @@ void ZoneDatabase::DeleteWaypoint(Client *client, uint32 grid_num, uint32 wp_num
|
||||
uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, float xpos, float ypos, float zpos, uint32 pause, int type1, int type2, uint16 zoneid, float heading) {
|
||||
|
||||
uint32 grid_num; // The grid number the spawn is assigned to (if spawn has no grid, will be the grid number we end up creating)
|
||||
uint32 next_wp_num; // The waypoint number we should be assigning to the new waypoint
|
||||
uint32 next_wp_num; // The waypoint number we should be assigning to the new waypoint
|
||||
bool createdNewGrid; // Did we create a new grid in this function?
|
||||
|
||||
// See what grid number our spawn is assigned
|
||||
std::string query = StringFormat("SELECT pathgrid FROM spawn2 WHERE id = %i", spawn2id);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
// Query error
|
||||
// Query error
|
||||
LogFile->write(EQEMuLog::Error, "Error setting pathgrid '%s': '%s'", query.c_str(), results.ErrorMessage().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
auto row = results.begin();
|
||||
grid_num = atoi(row[0]);
|
||||
auto row = results.begin();
|
||||
grid_num = atoi(row[0]);
|
||||
|
||||
if (grid_num == 0)
|
||||
{ // Our spawn doesn't have a grid assigned to it -- we need to create a new grid and assign it to the spawn
|
||||
createdNewGrid = true;
|
||||
grid_num = GetFreeGrid(zoneid);
|
||||
if(grid_num == 0) // There are no grids for the current zone -- create Grid #1
|
||||
grid_num = 1;
|
||||
grid_num = 1;
|
||||
|
||||
query = StringFormat("INSERT INTO grid SET id = '%i', zoneid = %i, type ='%i', type2 = '%i'",
|
||||
grid_num, zoneid, type1, type2);
|
||||
results = QueryDatabase(query);
|
||||
query = StringFormat("INSERT INTO grid SET id = '%i', zoneid = %i, type ='%i', type2 = '%i'",
|
||||
grid_num, zoneid, type1, type2);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
LogFile->write(EQEMuLog::Error, "Error adding grid '%s': '%s'", query.c_str(), results.ErrorMessage().c_str());
|
||||
else if(client)
|
||||
client->LogSQL(query.c_str());
|
||||
client->LogSQL(query.c_str());
|
||||
|
||||
query = StringFormat("UPDATE spawn2 SET pathgrid = '%i' WHERE id = '%i'", grid_num, spawn2id);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
LogFile->write(EQEMuLog::Error, "Error updating spawn2 pathing '%s': '%s'", query.c_str(), results.ErrorMessage().c_str());
|
||||
else if(client)
|
||||
client->LogSQL(query.c_str());
|
||||
client->LogSQL(query.c_str());
|
||||
}
|
||||
else // NPC had a grid assigned to it
|
||||
createdNewGrid = false;
|
||||
@@ -1291,25 +1291,26 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, float xpos,
|
||||
// Find out what the next waypoint is for this grid
|
||||
query = StringFormat("SELECT max(`number`) FROM grid_entries WHERE zoneid = '%i' AND gridid = '%i'", zoneid, grid_num);
|
||||
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success()) { // Query error
|
||||
LogFile->write(EQEMuLog::Error, "Error getting next waypoint id '%s': '%s'", query.c_str(), results.ErrorMessage().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
row = results.begin();
|
||||
if(row[0] != 0)
|
||||
next_wp_num = atoi(row[0]) + 1;
|
||||
else // No waypoints in this grid yet
|
||||
row = results.begin();
|
||||
if(row[0] != 0)
|
||||
next_wp_num = atoi(row[0]) + 1;
|
||||
else // No waypoints in this grid yet
|
||||
next_wp_num = 1;
|
||||
|
||||
query = StringFormat("INSERT INTO grid_entries(gridid, zoneid, `number`, x, y, z, pause, heading) "
|
||||
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
|
||||
grid_num, zoneid, next_wp_num, xpos, ypos, zpos, pause, heading);
|
||||
results = QueryDatabase(query);
|
||||
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
|
||||
grid_num, zoneid, next_wp_num, xpos, ypos, zpos, pause, heading);
|
||||
results = QueryDatabase(query);
|
||||
if(!results.Success())
|
||||
LogFile->write(EQEMuLog::Error, "Error adding grid entry '%s': '%s'", query.c_str(), results.ErrorMessage().c_str());
|
||||
else if(client)
|
||||
client->LogSQL(query.c_str());
|
||||
client->LogSQL(query.c_str());
|
||||
|
||||
return createdNewGrid? grid_num: 0;
|
||||
}
|
||||
|
||||
+4
-1
@@ -594,15 +594,17 @@ void Zone::LoadMercTemplates(){
|
||||
tempMercTemplate.Stances[i] = 0;
|
||||
|
||||
int stanceIndex = 0;
|
||||
for (std::list<MercStanceInfo>::iterator mercStanceListItr = merc_stances.begin(); mercStanceListItr != merc_stances.end(); ++mercStanceListItr, ++stanceIndex) {
|
||||
for (auto mercStanceListItr = merc_stances.begin(); mercStanceListItr != merc_stances.end(); ++mercStanceListItr) {
|
||||
if(mercStanceListItr->ClassID != tempMercTemplate.ClassID || mercStanceListItr->ProficiencyID != tempMercTemplate.ProficiencyID)
|
||||
continue;
|
||||
|
||||
zone->merc_stance_list[tempMercTemplate.MercTemplateID].push_back((*mercStanceListItr));
|
||||
tempMercTemplate.Stances[stanceIndex] = mercStanceListItr->StanceID;
|
||||
++stanceIndex;
|
||||
}
|
||||
|
||||
merc_templates[tempMercTemplate.MercTemplateID] = tempMercTemplate;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -733,6 +735,7 @@ void Zone::Shutdown(bool quite)
|
||||
while (mob_itr != mob_list.end()) {
|
||||
Mob* mob_inst = *mob_itr;
|
||||
mob_inst->AI_Stop();
|
||||
mob_inst->AI_ShutDown();
|
||||
++mob_itr;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user