diff --git a/changelog.txt b/changelog.txt index 372c908c7..66ffe50d7 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,14 @@ 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/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/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 ba67e4ba7..8ff898739 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -6533,15 +6533,12 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app) 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); + 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; @@ -6653,64 +6650,22 @@ 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... - { + + 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); + memberMerc->RemoveMercFromGroup(memberMerc, group); - if(!g) - { - delete g; - g = NULL; - return; - } + if(!memberMerc->IsGrouped() && !memberClient->IsGrouped()) { + Group *g = new Group(memberClient); - 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()) - { - memberToDisband->CastToMerc()->RemoveMercFromGroup(memberToDisband->CastToMerc(), group); - memberToDisband->CastToMerc()->Suspend(); - } - } - else - { - // ...but other members can only remove themselves - group->DelMember(this,false); - - if(!IsGrouped() && GetMerc() != NULL) - { - if(!IsGrouped()) { - Group *g = new Group(this); - - if(!g) - { + if(!g) { delete g; g = NULL; return; @@ -6718,8 +6673,42 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app) entity_list.AddGroup(g); - if(g->GetID() == 0) - { + 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()) { + memberToDisband->CastToMerc()->RemoveMercFromGroup(memberToDisband->CastToMerc(), group); + memberToDisband->CastToMerc()->RemoveMercFromGroup(memberToDisband->CastToMerc(), group); + memberToDisband->CastToMerc()->Suspend(); + } + } + else { + // ...but other members can only remove themselves + group->DelMember(this,false); + + if(!IsGrouped() && GetMerc() != NULL) { + if(!IsGrouped()) { + Group *g = new Group(this); + + if(!g) { + delete g; + g = NULL; + return; + } + + entity_list.AddGroup(g); + + if(g->GetID() == 0) { safe_delete(g); return; } @@ -13795,9 +13784,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); } void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app) diff --git a/zone/merc.cpp b/zone/merc.cpp index f6eb6bb96..e078efec4 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1904,7 +1904,6 @@ void Merc::AI_Process() { void Merc::AI_Start(int32 iMoveDelay) { NPC::AI_Start(iMoveDelay); - if (!pAIControlled) return; @@ -2373,13 +2372,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); } } } @@ -2400,13 +2399,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); } } } @@ -5171,8 +5170,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; @@ -5357,7 +5356,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) { @@ -5365,7 +5428,7 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { SendMercMerchantResponsePacket(14); else SendMercMerchantResponsePacket(16); - result = false; + return false; } //check for merchant too far away @@ -5374,65 +5437,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 @@ -5440,30 +5451,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 @@ -5472,15 +5498,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() @@ -5596,6 +5637,10 @@ bool Merc::Suspend() { SetSuspended(true); + /*if(HasGroup()) { + RemoveMercFromGroup(this, GetGroup()); + }*/ + Save(); mercOwner->GetMercInfo().IsSuspended = true; @@ -5645,16 +5690,15 @@ bool Merc::Unsuspend(bool setMaxStats) { mercOwner->SendMercPersonalInfo(); Group* g = entity_list.GetGroupByClient(mercOwner); - if(!g) - { //nobody from our group is here... start a new group + if(!g) { //nobody from our group is here... start a new group g = new Group(mercOwner); - if(!g) - { + if(!g) { delete g; g = NULL; return false; } + entity_list.AddGroup(g); if(g->GetID() == 0) { @@ -5663,8 +5707,7 @@ bool Merc::Unsuspend(bool setMaxStats) { return false; } - if(AddMercToGroup(this, g)) - { + if(AddMercToGroup(this, g)) { entity_list.AddGroup(g, g->GetID()); database.SetGroupLeaderName(g->GetID(), mercOwner->GetName()); database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID()); @@ -5673,20 +5716,17 @@ bool Merc::Unsuspend(bool setMaxStats) { g->SaveGroupLeaderAA(); loaded = true; } - else - { - g->DisbandGroup(); + else { + g->DisbandGroup(); } } //else, somebody from our group is already here... - else if (AddMercToGroup(this, mercOwner->GetGroup())) - { + 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"); @@ -5913,10 +5953,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 4dd24aba1..a2c1addb1 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -248,8 +248,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float npc_aggro = d->npc_aggro; - if(!IsMerc()) //memleak fix, this really shouldn't be here - AI_Start(); + if(!IsMerc()) + AI_Start(); d_meele_texture1 = d->d_meele_texture1; d_meele_texture2 = d->d_meele_texture2; 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; 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.