From 886c7bf634fe2643e883fefd7bb83fa26fde682f Mon Sep 17 00:00:00 2001 From: mackal Date: Wed, 20 Mar 2013 23:29:00 -0400 Subject: [PATCH 1/3] Fixed stacking issues with SE_Limit* (ex. Unholy Aura Discipline and Aura of Reverence) --- changelog.txt | 3 +++ zone/spells.cpp | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/changelog.txt b/changelog.txt index 372c908c7..81d29c717 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/20/2013 == +demonstar55: Fixed stacking issues with SE_Limit* (ex. Unholy Aura Discipline and Aura of Reverence) + == 03/18/2013 == Bad_Captain: Fixed zone crash due to merc focus effects & tribute. Bad_Captain: Fixed merc aggro issues when client in melee range & spell recast timers. diff --git a/zone/spells.cpp b/zone/spells.cpp index 6d624bfae..5c85b4445 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2564,6 +2564,22 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if(effect1 != effect2) continue; + /* + Skip check if effect is SE_Limit* + skip checking effect2 since we know they are equal + */ + if(effect1 == SE_LimitMaxLevel || + effect1 == SE_LimitResist || + effect1 == SE_LimitTarget || + effect1 == SE_LimitEffect || + effect1 == SE_LimitSpellType || + effect1 == SE_LimitSpell || + effect1 == SE_LimitMinDur || + effect1 == SE_LimitInstant || + effect1 == SE_LimitMinLevel || + effect1 == SE_LimitCastTime) + continue; + /* If target is a npc and caster1 and caster2 exist If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it. From a20c7735e8314ef6a8476216c735f2502fe3c584 Mon Sep 17 00:00:00 2001 From: badcaptain Date: Fri, 22 Mar 2013 00:03:50 -0400 Subject: [PATCH 2/3] Fixed merc buffing bugs, added checks before dismissing merc to prevent possible bugged mercs, merged in Secret's merc memory leak fixes. --- changelog.txt | 5 + zone/client.h | 1 + zone/client_packet.cpp | 109 ++++++++++-------- zone/groups.cpp | 3 + zone/merc.cpp | 256 ++++++++++++++++++++++++----------------- zone/npc.cpp | 3 +- 6 files changed, 227 insertions(+), 150 deletions(-) diff --git a/changelog.txt b/changelog.txt index 372c908c7..1ef3af6fd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/21/2013 == +Bad_Captain: Fixed merc buffing bugs. +Bad_Captain: Added checks before dismissing merc to prevent possible bugged mercs. +Bad_Captain: Merged in Secret's merc memory leak fixes. + == 03/18/2013 == Bad_Captain: Fixed zone crash due to merc focus effects & tribute. Bad_Captain: Fixed merc aggro issues when client in melee range & spell recast timers. diff --git a/zone/client.h b/zone/client.h index 219e11704..3ff2a28f9 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1100,6 +1100,7 @@ public: bool CheckCanHireMerc(Mob* merchant, uint32 template_id); bool CheckCanRetainMerc(uint32 upkeep); bool CheckCanUnsuspendMerc(); + bool CheckCanDismissMerc(); inline uint32 GetMercID() const { return mercid; } inline uint8 GetMercSlot() const { return mercSlot; } void SetMercID( uint32 newmercid) { mercid = newmercid; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c90dae9d0..6cf5fe4ac 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6484,15 +6484,6 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app) database.SetGroupID(inviter->GetName(), group->GetID(), inviter->CastToClient()->CharacterID()); database.SetGroupLeaderName(group->GetID(), inviter->GetName()); - // Add the merc back into the new group - if (GetMerc()) - { - if (GetMerc()->AddMercToGroup(GetMerc(), group)) - { - database.SetGroupID(GetMerc()->GetName(), group->GetID(), inviter->CastToClient()->CharacterID(), true); - } - } - group->UpdateGroupAAs(); //Invite the inviter into the group first.....dont ask @@ -6527,11 +6518,6 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app) if(!group->AddMember(this)) return; - if(GetMerc()) - { - group->AddMember(GetMerc()); - } - if(inviter->CastToClient()->IsLFP()) { // If the player who invited us to a group is LFP, have them update world now that we have joined // their group. @@ -6548,6 +6534,13 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app) if(inviter->CastToClient()->GetClientVersion() >= EQClientSoD) database.RefreshGroupFromDB(inviter->CastToClient()); + // Add the merc back into the new group + if (GetMerc()) { + if (GetMerc()->AddMercToGroup(GetMerc(), group)) { + database.SetGroupID(GetMerc()->GetName(), group->GetID(), inviter->CastToClient()->CharacterID(), true); + } + } + //send updates to clients out of zone... ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer; @@ -6659,47 +6652,69 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) if(!memberToDisband) memberToDisband = entity_list.GetMob(gd->name2); - if(memberToDisband ) - { - if(group->IsLeader(this)) // the group leader can kick other members out of the group... - { - group->DelMember(memberToDisband,false); + + if(memberToDisband ) { + if(group->IsLeader(this)) { + // the group leader can kick other members out of the group... + //group->DelMember(memberToDisband,false); if(memberToDisband->IsClient()) { + group->DelMember(memberToDisband,false); Client* memberClient = memberToDisband->CastToClient(); Merc* memberMerc = memberToDisband->CastToClient()->GetMerc(); - if(memberMerc != NULL) - { - memberMerc->RemoveMercFromGroup(memberMerc, group); - if(!memberMerc->IsGrouped() && !memberClient->IsGrouped()) - { - Group *g = new Group(memberClient); - if(memberMerc->AddMercToGroup(memberMerc, g)) { - entity_list.AddGroup(g); - database.SetGroupLeaderName(g->GetID(), memberClient->GetName()); - g->SaveGroupLeaderAA(); - database.SetGroupID(memberClient->GetName(), g->GetID(), memberClient->CharacterID()); - database.SetGroupID(memberMerc->GetName(), g->GetID(), memberClient->CharacterID(), true); - database.RefreshGroupFromDB(memberClient); - } - } + memberMerc->RemoveMercFromGroup(memberMerc, group); + + if(!memberMerc->IsGrouped() && !memberClient->IsGrouped()) { + Group *g = new Group(memberClient); + + if(!g) { + delete g; + g = NULL; + return; } + + entity_list.AddGroup(g); + + if(g->GetID() == 0) { + safe_delete(g); + return; + } + if(memberMerc->AddMercToGroup(memberMerc, g)) { + database.SetGroupLeaderName(g->GetID(), memberClient->GetName()); + g->SaveGroupLeaderAA(); + database.SetGroupID(memberClient->GetName(), g->GetID(), memberClient->CharacterID()); + database.SetGroupID(memberMerc->GetName(), g->GetID(), memberClient->CharacterID(), true); + database.RefreshGroupFromDB(memberClient); + } + } } - else if(memberToDisband->IsMerc()) - { + else if(memberToDisband->IsMerc()) { + memberToDisband->CastToMerc()->RemoveMercFromGroup(memberToDisband->CastToMerc(), group); memberToDisband->CastToMerc()->Suspend(); } } - else - { // ...but other members can only remove themselves + else { + // ...but other members can only remove themselves group->DelMember(this,false); - if(!IsGrouped() && GetMerc() != NULL) - { + if(!IsGrouped() && GetMerc() != NULL) { if(!IsGrouped()) { - Group *g = new Group(this); + Group *g = new Group(this); + + if(!g) { + delete g; + g = NULL; + return; + } + + entity_list.AddGroup(g); + + if(g->GetID() == 0) { + safe_delete(g); + return; + } + if(GetMerc()->AddMercToGroup(GetMerc(), g)) { - entity_list.AddGroup(g); database.SetGroupLeaderName(g->GetID(), this->GetName()); g->SaveGroupLeaderAA(); database.SetGroupID(this->GetName(), g->GetID(), this->CharacterID()); @@ -13752,12 +13767,14 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app) if(GetMercID()) { Merc* merc = GetMerc(); - if(merc) - merc->Dismiss(); + if(merc) { + if(CheckCanDismissMerc()) { + merc->Dismiss(); + } + } } - SendMercMerchantResponsePacket(10); - + //SendMercMerchantResponsePacket(10); } void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app) diff --git a/zone/groups.cpp b/zone/groups.cpp index 8457e5ad0..bcb100147 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -214,6 +214,9 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte if(!newmember && !NewMemberName) return false; + if(GroupCount() >= MAX_GROUP_MEMBERS) //Sanity check for merging groups together. + return false; + if(!newmember) InZone = false; else diff --git a/zone/merc.cpp b/zone/merc.cpp index 37155085f..a76bb4a91 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -71,6 +71,7 @@ Merc::Merc(const NPCType* d, float x, float y, float z, float heading) } Merc::~Merc() { + AI_Stop(); safe_delete(ourNPCData); //Since mercs are dynamically alloc'd we should probably safe_delete the data they were made from. I'm not entirely sure this is safe to delete a const. entity_list.RemoveMerc(this->GetID()); UninitializeBuffSlots(); @@ -1900,15 +1901,15 @@ void Merc::AI_Process() { } void Merc::AI_Start(int32 iMoveDelay) { - Mob::AI_Start(iMoveDelay); + NPC::AI_Start(iMoveDelay); if (!pAIControlled) return; if (merc_spells.size() == 0) { - AIautocastspell_timer = new Timer(1000); + AIautocastspell_timer->SetTimer(1000); AIautocastspell_timer->Disable(); } else { - AIautocastspell_timer = new Timer(750); + AIautocastspell_timer->SetTimer(750); AIautocastspell_timer->Start(RandomTimer(0, 2000), false); } @@ -2369,13 +2370,13 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { if(selectedMercSpell.spellid > 0) { if(isDiscipline) { - castedSpell = UseDiscipline(selectedMercSpell.spellid, GetID()); + castedSpell = UseDiscipline(selectedMercSpell.spellid, tar->GetID()); } else { - castedSpell = AIDoSpellCast(selectedMercSpell.spellid, this, -1, &TempDontBuffMeBeforeTime); + castedSpell = AIDoSpellCast(selectedMercSpell.spellid, tar, -1, &TempDontBuffMeBeforeTime); - if(TempDontBuffMeBeforeTime != this->DontBuffMeBefore()) - this->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); + if(TempDontBuffMeBeforeTime != tar->DontBuffMeBefore()) + tar->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); } } } @@ -2396,13 +2397,13 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) { if(selectedMercSpell.spellid > 0) { if(isDiscipline) { - castedSpell = UseDiscipline(selectedMercSpell.spellid, GetID()); + castedSpell = UseDiscipline(selectedMercSpell.spellid, tar->GetPet()->GetID()); } else { - castedSpell = AIDoSpellCast(selectedMercSpell.spellid, this, -1, &TempDontBuffMeBeforeTime); + castedSpell = AIDoSpellCast(selectedMercSpell.spellid, tar->GetPet(), -1, &TempDontBuffMeBeforeTime); - if(TempDontBuffMeBeforeTime != this->DontBuffMeBefore()) - this->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); + if(TempDontBuffMeBeforeTime != tar->GetPet()->DontBuffMeBefore()) + tar->GetPet()->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); } } } @@ -5167,8 +5168,8 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, snprintf(c->GetEPP().merc_name, 64, "%s", c->GetMercInfo().merc_name); merc->SetSuspended(c->GetMercInfo().IsSuspended); merc->gender = c->GetMercInfo().Gender; - merc->SetHP(c->GetMercInfo().hp); - merc->SetMana(c->GetMercInfo().mana); + merc->SetHP(c->GetMercInfo().hp <= 0 ? merc->GetMaxHP() : c->GetMercInfo().hp); + merc->SetMana(c->GetMercInfo().hp <= 0 ? merc->GetMaxMana() : c->GetMercInfo().mana); merc->SetEndurance(c->GetMercInfo().endurance); merc->luclinface = c->GetMercInfo().face; merc->hairstyle = c->GetMercInfo().luclinHairStyle; @@ -5353,7 +5354,71 @@ void Client::UpdateMercTimer() } bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { - bool result = true; + MercTemplate* mercTemplate = zone->GetMercTemplate(template_id); + + //invalid merc data + if(!mercTemplate) { + if (GetClientVersion() < EQClientRoF) + SendMercMerchantResponsePacket(9); + else + SendMercMerchantResponsePacket(10); + return false; + } + + //check client version + if(GetClientVersion() < mercTemplate->ClientVersion) { + SendMercMerchantResponsePacket(3); + return false; + } + + if(GetClientVersion() >= EQClientRoF && GetNumMercs() >= MAXMERCS) { + SendMercMerchantResponsePacket(6); + return false; + } + else if(GetMerc()) { //check for current merc + if (GetClientVersion() < EQClientRoF) + SendMercMerchantResponsePacket(6); + else + SendMercMerchantResponsePacket(6); + return false; + } + else if(GetMercInfo().mercid != 0 && GetMercInfo().IsSuspended) { //has suspended merc + if (GetClientVersion() < EQClientRoF) + SendMercMerchantResponsePacket(7); + else + SendMercMerchantResponsePacket(6); + return false; + } + + //check for sufficient funds + if(RuleB(Mercs, ChargeMercPurchaseCost)) { + uint32 cost = Merc::CalcPurchaseCost(template_id, GetLevel()) * 100; // Cost is in gold + if(cost > 0 && !HasMoney(cost)) { + SendMercMerchantResponsePacket(1); + return false; + } + } + + //check for raid + if(HasRaid()) { + SendMercMerchantResponsePacket(4); + return false; + } + + //check group size + if(HasGroup() && GetGroup()->GroupCount() >= MAX_GROUP_MEMBERS) { + if (GetClientVersion() < EQClientRoF) + SendMercMerchantResponsePacket(8); + else + SendMercMerchantResponsePacket(7); + return false; + } + + //check in combat + if(GetClientVersion() >= EQClientRoF && GetAggroCount() > 0) { + SendMercMerchantResponsePacket(8); + return false; + } //check for valid merchant - can check near area for any merchants if(!merchant) { @@ -5361,7 +5426,7 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { SendMercMerchantResponsePacket(14); else SendMercMerchantResponsePacket(16); - result = false; + return false; } //check for merchant too far away @@ -5370,65 +5435,13 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { SendMercMerchantResponsePacket(15); else SendMercMerchantResponsePacket(17); - result = false; + return false; } - - if(GetClientVersion() >= EQClientRoF && GetNumMercs() >= MAXMERCS) { - SendMercMerchantResponsePacket(6); - result = false; - } - else if(GetMerc()) { //check for current merc - if (GetClientVersion() < EQClientRoF) - SendMercMerchantResponsePacket(6); - else - SendMercMerchantResponsePacket(6); - result = false; - } - else if(GetMercInfo().mercid != 0 && GetMercInfo().IsSuspended) { //has suspended merc - if (GetClientVersion() < EQClientRoF) - SendMercMerchantResponsePacket(7); - else - SendMercMerchantResponsePacket(6); - result = false; - } - - //check for sufficient funds - if(RuleB(Mercs, ChargeMercPurchaseCost)) { - uint32 cost = Merc::CalcPurchaseCost(template_id, GetLevel()) * 100; // Cost is in gold - if(cost > 0 && !HasMoney(cost)) { - SendMercMerchantResponsePacket(1); - result = false; - } - } - - //check for raid - if(HasRaid()) { - SendMercMerchantResponsePacket(4); - result = false; - } - - //check group size - if(HasGroup() && GetGroup()->GroupCount() == 6) { - if (GetClientVersion() < EQClientRoF) - SendMercMerchantResponsePacket(8); - else - SendMercMerchantResponsePacket(7); - result = false; - } - - //check in combat - if(GetClientVersion() >= EQClientRoF && GetAggroCount() > 0) { - SendMercMerchantResponsePacket(8); - result = false; - } - - return result; + return true; } bool Client::CheckCanRetainMerc(uint32 upkeep) { - bool result = true; - Merc* merc = GetMerc(); //check for sufficient funds @@ -5436,30 +5449,45 @@ bool Client::CheckCanRetainMerc(uint32 upkeep) { if(merc) { if(upkeep > 0 && !HasMoney(upkeep * 100)) { SendMercMerchantResponsePacket(1); - result = false; + return false; } } } - return result; + return true; } bool Client::CheckCanUnsuspendMerc() { - bool result = true; + MercTemplate* mercTemplate = zone->GetMercTemplate(GetMercInfo().MercTemplateID); + + //invalid merc data + if(!mercTemplate) { + if (GetClientVersion() < EQClientRoF) + SendMercMerchantResponsePacket(9); + else + SendMercMerchantResponsePacket(10); + return false; + } + + //check client version + if(GetClientVersion() < mercTemplate->ClientVersion) { + SendMercMerchantResponsePacket(3); + return false; + } //check for raid if(HasRaid()) { SendMercMerchantResponsePacket(4); - result = false; + return false; } //check group size - if(HasGroup() && GetGroup()->GroupCount() == 6) { + if(HasGroup() && GetGroup()->GroupCount() >= MAX_GROUP_MEMBERS) { if (GetClientVersion() < EQClientRoF) SendMercMerchantResponsePacket(8); else SendMercMerchantResponsePacket(7); - result = false; + return false; } //check if zone allows mercs @@ -5468,15 +5496,30 @@ bool Client::CheckCanUnsuspendMerc() { SendMercMerchantResponsePacket(4); // ?? else SendMercMerchantResponsePacket(4); // ?? + return false; } //check in combat if(GetClientVersion() >= EQClientRoF && GetAggroCount() > 0) { SendMercMerchantResponsePacket(8); - result = false; + return false; } - return result; + return true; +} + +bool Client::CheckCanDismissMerc() { + if(!GetMerc()) { + Message(7, "You have no mercenary to dismiss."); + return false; + } + + if(GetMerc()->IsCasting()) { + Message(7, "Unable to dismiss mercenary."); + return false; + } + + return true; } void Client::CheckMercSuspendTimer() @@ -5592,9 +5635,9 @@ bool Merc::Suspend() { SetSuspended(true); - if(HasGroup()) { + /*if(HasGroup()) { RemoveMercFromGroup(this, GetGroup()); - } + }*/ Save(); @@ -5643,40 +5686,45 @@ bool Merc::Unsuspend(bool setMaxStats) { mercOwner->GetPTimers().Clear(&database, pTimerMercSuspend); mercOwner->SendMercPersonalInfo(); + Group* g = entity_list.GetGroupByClient(mercOwner); - if(!mercOwner->IsGrouped()) - { - Group *g = new Group(mercOwner); - if(g && AddMercToGroup(this, g)) - { - entity_list.AddGroup(g); + if(!g) { //nobody from our group is here... start a new group + g = new Group(mercOwner); + + if(!g) { + delete g; + g = NULL; + return false; + } + + entity_list.AddGroup(g); + + if(g->GetID() == 0) { + delete g; + g = NULL; + return false; + } + + if(AddMercToGroup(this, g)) { + entity_list.AddGroup(g, g->GetID()); database.SetGroupLeaderName(g->GetID(), mercOwner->GetName()); database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID()); database.SetGroupID(this->GetName(), g->GetID(), mercOwner->CharacterID(), true); database.RefreshGroupFromDB(mercOwner); g->SaveGroupLeaderAA(); - loaded = true; } - else - { - if(MERC_DEBUG > 0) - mercOwner->Message(7, "Mercenary failed to join the group - Suspending"); - - Suspend(); - safe_delete(g); - return false; + else { + g->DisbandGroup(); } - } - else if (AddMercToGroup(this, mercOwner->GetGroup())) - { + } //else, somebody from our group is already here... + else if (AddMercToGroup(this, mercOwner->GetGroup())) { database.SetGroupID(GetName(), mercOwner->GetGroup()->GetID(), mercOwner->CharacterID(), true); database.RefreshGroupFromDB(mercOwner); loaded = true; } - else - { + else { if(MERC_DEBUG > 0) mercOwner->Message(7, "Mercenary failed to join the group - Suspending"); @@ -5903,10 +5951,12 @@ void Client::UpdateMercLevel() { void Client::SendMercMerchantResponsePacket(int32 response_type) { // This response packet brings up the Mercenary Manager window - EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); - MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; - mmr->ResponseType = response_type; // send specified response type - FastQueuePacket(&outapp); + if(GetClientVersion() >= EQClientSoD) { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); + MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; + mmr->ResponseType = response_type; // send specified response type + FastQueuePacket(&outapp); + } } void Client::SendMercenaryUnknownPacket(uint8 type) { diff --git a/zone/npc.cpp b/zone/npc.cpp index 86efc0579..b2661e931 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -248,7 +248,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float npc_aggro = d->npc_aggro; - AI_Start(); + if(!IsMerc()) + AI_Start(); d_meele_texture1 = d->d_meele_texture1; d_meele_texture2 = d->d_meele_texture2; From ac040b519748aa44e985a1d99baf2d0787bdc36e Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 22 Mar 2013 21:48:57 -0400 Subject: [PATCH 3/3] Added some pointer checks as discussed in issue #36 --- zone/questmgr.cpp | 160 ++++++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 55 deletions(-) diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 847469149..b93a3102f 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -208,15 +208,28 @@ void QuestManager::echo(int colour, const char *str) { } void QuestManager::say(const char *str) { - - if(RuleB(NPC, EnableNPCQuestJournal) && initiator) - owner->QuestJournalledSay(initiator, str); - else - owner->Say(str); + if (!owner) { + LogFile->write(EQEMuLog::Quest, "QuestManager::say called with NULL owner. Probably syntax error in quest file."); + return; + } + else { + if(RuleB(NPC, EnableNPCQuestJournal) && initiator) { + owner->QuestJournalledSay(initiator, str); + } + else { + owner->Say(str); + } + } } void QuestManager::say(const char *str, uint8 language) { - entity_list.ChannelMessage(owner, 8, language, str); + if (!owner) { + LogFile->write(EQEMuLog::Quest, "QuestManager::say called with NULL owner. Probably syntax error in quest file."); + return; + } + else { + entity_list.ChannelMessage(owner, 8, language, str); + } } void QuestManager::me(const char *str) { @@ -242,14 +255,14 @@ void QuestManager::write(const char *file, const char *str) { uint16 QuestManager::spawn2(int npc_type, int grid, int unused, float x, float y, float z, float heading) { const NPCType* tmp = 0; - if ((tmp = database.GetNPCType(npc_type))) + if (tmp = database.GetNPCType(npc_type)) { NPC* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3); npc->AddLootTable(); entity_list.AddNPC(npc,true,true); - // Quag: Sleep in main thread? ICK! + // Sleep in main thread? ICK! // Sleep(200); - // Quag: check is irrelevent, it's impossible for npc to be 0 here + // check is irrelevent, it's impossible for npc to be 0 here // (we're in main thread, nothing else can possibly modify it) if(grid > 0) { @@ -268,14 +281,14 @@ uint16 QuestManager::unique_spawn(int npc_type, int grid, int unused, float x, f } const NPCType* tmp = 0; - if ((tmp = database.GetNPCType(npc_type))) + if (tmp = database.GetNPCType(npc_type)) { NPC* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3); npc->AddLootTable(); entity_list.AddNPC(npc,true,true); - // Quag: Sleep in main thread? ICK! + // Sleep in main thread? ICK! // Sleep(200); - // Quag: check is irrelevent, it's impossible for npc to be 0 here + // check is irrelevent, it's impossible for npc to be 0 here // (we're in main thread, nothing else can possibly modify it) if(grid > 0) { @@ -514,76 +527,113 @@ void QuestManager::stopalltimers() { } void QuestManager::emote(const char *str) { - owner->Emote(str); + if (!owner) { + LogFile->write(EQEMuLog::Quest, "QuestManager::emote called with NULL owner. Probably syntax error in quest file."); + return; + } + else { + owner->Emote(str); + } } void QuestManager::shout(const char *str) { - owner->Shout(str); + if (!owner) { + LogFile->write(EQEMuLog::Quest, "QuestManager::shout called with NULL owner. Probably syntax error in quest file."); + return; + } + else { + owner->Shout(str); + } } void QuestManager::shout2(const char *str) { - worldserver.SendEmoteMessage(0,0,0,13, "%s shouts, '%s'", owner->GetCleanName(), str); + if (!owner) { + LogFile->write(EQEMuLog::Quest, "QuestManager::shout2 called with NULL owner. Probably syntax error in quest file."); + return; + } + else { + worldserver.SendEmoteMessage(0,0,0,13, "%s shouts, '%s'", owner->GetCleanName(), str); + } } -void QuestManager::gmsay(const char *str, uint32 color, bool send_to_world, uint32 to_guilddbid, uint32 to_minstatus) -{ +void QuestManager::gmsay(const char *str, uint32 color, bool send_to_world, uint32 to_guilddbid, uint32 to_minstatus) { if(send_to_world) - worldserver.SendEmoteMessage(0, to_guilddbid, to_minstatus, color, "%s", str); + worldserver.SendEmoteMessage(0, to_guilddbid, to_minstatus, color, "%s", str); else entity_list.MessageStatus(to_guilddbid, to_minstatus, color, "%s", str); } void QuestManager::depop(int npc_type) { // depop NPC and don't start spawn timer - if (!owner->IsNPC()) + if (!owner || !owner->IsNPC()) { + LogFile->write(EQEMuLog::Quest, "QuestManager::depop called with NULL owner or non-NPC owner. Probably syntax error in quest file."); return; - if (npc_type != 0) { - Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); - if (tmp) { - if (tmp != owner) { - tmp->CastToNPC()->Depop(); - } - else { - depop_npc = true; + } + else { + if (npc_type != 0) { + Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); + if (tmp) { + if (tmp != owner) { + tmp->CastToNPC()->Depop(); + } + else { + depop_npc = true; + } } } - } - else { //depop self - depop_npc = true; + else { //depop self + depop_npc = true; + } } } void QuestManager::depop_withtimer(int npc_type) { // depop NPC and start spawn timer - if (!owner->IsNPC()) + if (!owner || !owner->IsNPC()) { + LogFile->write(EQEMuLog::Quest, "QuestManager::depop_withtimer called with NULL owner or non-NPC owner. Probably syntax error in quest file."); return; - if (npc_type != 0) { - Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); - if (tmp) { - if (tmp != owner) { - tmp->CastToNPC()->Depop(true); - } - else { - owner->Depop(true); + } + else { + if (npc_type != 0) { + Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); + if (tmp) { + if (tmp != owner) { + tmp->CastToNPC()->Depop(true); + } + else { + owner->Depop(true); + } } } - } - else { //depop self - owner->Depop(true); + else { //depop self + owner->Depop(true); + } } } void QuestManager::depopall(int npc_type) { - if(owner->IsNPC() && npc_type > 0) + if(owner && owner->IsNPC() && (npc_type > 0)) { entity_list.DepopAll(npc_type); + } + else { + LogFile->write(EQEMuLog::Quest, "QuestManager::depopall called with NULL owner, non-NPC owner, or invalid NPC Type ID. Probably syntax error in quest file."); + } } void QuestManager::depopzone(bool StartSpawnTimer) { - if(zone) + if(zone) { zone->Depop(StartSpawnTimer); + } + else { + LogFile->write(EQEMuLog::Quest, "QuestManager::depopzone called with NULL zone. Probably syntax error in quest file."); + } } void QuestManager::repopzone() { - if(zone) + if(zone) { zone->Repop(); + } + else { + LogFile->write(EQEMuLog::Quest, "QuestManager::repopzone called with NULL zone. Probably syntax error in quest file."); + } } void QuestManager::settarget(const char *type, int target_id) { @@ -615,7 +665,7 @@ void QuestManager::sfollow() { } void QuestManager::changedeity(int diety_id) { - //Cofruben:-Changes the deity. + //Changes the deity. if(initiator) { if(initiator->IsClient()) @@ -731,7 +781,7 @@ void QuestManager::snow(int weather) { } void QuestManager::surname(const char *name) { - //Cofruben:-Changes the last name. + //Changes the last name. if(initiator) { if(initiator->IsClient()) @@ -747,21 +797,21 @@ void QuestManager::surname(const char *name) { } void QuestManager::permaclass(int class_id) { - //Cofruben:-Makes the client the class specified + //Makes the client the class specified initiator->SetBaseClass(class_id); initiator->Save(2); initiator->Kick(); } void QuestManager::permarace(int race_id) { - //Cofruben:-Makes the client the race specified + //Makes the client the race specified initiator->SetBaseRace(race_id); initiator->Save(2); initiator->Kick(); } void QuestManager::permagender(int gender_id) { - //Cofruben:-Makes the client the gender specified + //Makes the client the gender specified initiator->SetBaseGender(gender_id); initiator->Save(2); initiator->Kick(); @@ -1039,7 +1089,7 @@ void QuestManager::save() { void QuestManager::faction(int faction_id, int faction_value, int temp) { if (initiator && initiator->IsClient()) { if(faction_id != 0 && faction_value != 0) { - // SCORPIOUS2K - fixed faction command + // fixed faction command //Client *p; initiator->SetFactionLevel2( initiator->CharacterID(), @@ -1111,7 +1161,7 @@ void QuestManager::itemlink(int item_id) { } void QuestManager::signalwith(int npc_id, int signal_id, int wait_ms) { -// SCORPIOUS2K - signal command +// signal command // signal(npcid) - generates EVENT_SIGNAL on specified npc if(wait_ms > 0) { STimerList.push_back(SignalTimer(wait_ms, npc_id, signal_id)); @@ -1134,7 +1184,7 @@ void QuestManager::signal(int npc_id, int wait_ms) { } void QuestManager::setglobal(const char *varname, const char *newvalue, int options, const char *duration) { -// SCORPIOUS2K - qglobal variable commands +// qglobal variable commands // setglobal(varname,value,options,duration) //MYSQL_ROW row; int qgZoneid=zone->GetZoneID(); @@ -1376,7 +1426,7 @@ int QuestManager::QGVarDuration(const char *fmt) } void QuestManager::ding() { - //-Cofruben:makes a sound. + //makes a sound. if (initiator && initiator->IsClient()) initiator->SendSound(); @@ -1495,7 +1545,7 @@ void QuestManager::clear_proximity() { } void QuestManager::setanim(int npc_type, int animnum) { - //Cisyouc: adds appearance changes + //adds appearance changes Mob* thenpc = entity_list.GetMobByNpcTypeID(npc_type); if(animnum < 0 || animnum >= _eaMaxAppearance) return;