Conflicts:
	zone/client_packet.cpp
	zone/merc.cpp
	zone/npc.cpp
This commit is contained in:
SecretsOTheP 2013-03-23 05:02:27 -04:00
commit 8e604fd3db
7 changed files with 321 additions and 210 deletions

View File

@ -1,6 +1,14 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) 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 == == 03/18/2013 ==
Bad_Captain: Fixed zone crash due to merc focus effects & tribute. 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. Bad_Captain: Fixed merc aggro issues when client in melee range & spell recast timers.

View File

@ -1100,6 +1100,7 @@ public:
bool CheckCanHireMerc(Mob* merchant, uint32 template_id); bool CheckCanHireMerc(Mob* merchant, uint32 template_id);
bool CheckCanRetainMerc(uint32 upkeep); bool CheckCanRetainMerc(uint32 upkeep);
bool CheckCanUnsuspendMerc(); bool CheckCanUnsuspendMerc();
bool CheckCanDismissMerc();
inline uint32 GetMercID() const { return mercid; } inline uint32 GetMercID() const { return mercid; }
inline uint8 GetMercSlot() const { return mercSlot; } inline uint8 GetMercSlot() const { return mercSlot; }
void SetMercID( uint32 newmercid) { mercid = newmercid; } void SetMercID( uint32 newmercid) { mercid = newmercid; }

View File

@ -6533,15 +6533,12 @@ void Client::Handle_OP_GroupFollow2(const EQApplicationPacket *app)
database.RefreshGroupFromDB(inviter->CastToClient()); database.RefreshGroupFromDB(inviter->CastToClient());
// Add the merc back into the new group // Add the merc back into the new group
if (GetMerc()) if (GetMerc()) {
{ if (GetMerc()->AddMercToGroup(GetMerc(), group)) {
if (GetMerc()->AddMercToGroup(GetMerc(), group)) database.SetGroupID(GetMerc()->GetName(), group->GetID(), inviter->CastToClient()->CharacterID(), true);
{
database.SetGroupID(GetMerc()->GetName(), group->GetID(), inviter->CastToClient()->CharacterID(), true);
} }
} }
//send updates to clients out of zone... //send updates to clients out of zone...
ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct)); ServerPacket* pack = new ServerPacket(ServerOP_GroupJoin, sizeof(ServerGroupJoin_Struct));
ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer; ServerGroupJoin_Struct* gj = (ServerGroupJoin_Struct*)pack->pBuffer;
@ -6653,64 +6650,22 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
if(!memberToDisband) if(!memberToDisband)
memberToDisband = entity_list.GetMob(gd->name2); memberToDisband = entity_list.GetMob(gd->name2);
if(memberToDisband )
{ if(memberToDisband ) {
if(group->IsLeader(this)) // the group leader can kick other members out of the group... if(group->IsLeader(this)) {
{ // the group leader can kick other members out of the group...
//group->DelMember(memberToDisband,false);
if(memberToDisband->IsClient()) if(memberToDisband->IsClient())
{ {
group->DelMember(memberToDisband,false); group->DelMember(memberToDisband,false);
Client* memberClient = memberToDisband->CastToClient(); Client* memberClient = memberToDisband->CastToClient();
Merc* memberMerc = memberToDisband->CastToClient()->GetMerc(); Merc* memberMerc = memberToDisband->CastToClient()->GetMerc();
if(memberMerc != NULL) memberMerc->RemoveMercFromGroup(memberMerc, group);
{
memberMerc->RemoveMercFromGroup(memberMerc, group);
if(!memberMerc->IsGrouped() && !memberClient->IsGrouped())
{
Group *g = new Group(memberClient);
if(!g) if(!memberMerc->IsGrouped() && !memberClient->IsGrouped()) {
{ Group *g = new Group(memberClient);
delete g;
g = NULL;
return;
}
entity_list.AddGroup(g); if(!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)
{
delete g; delete g;
g = NULL; g = NULL;
return; return;
@ -6718,8 +6673,42 @@ void Client::Handle_OP_GroupDisband(const EQApplicationPacket *app)
entity_list.AddGroup(g); 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); safe_delete(g);
return; return;
} }
@ -13795,9 +13784,14 @@ void Client::Handle_OP_MercenaryDismiss(const EQApplicationPacket *app)
if(GetMercID()) { if(GetMercID()) {
Merc* merc = GetMerc(); Merc* merc = GetMerc();
if(merc) if(merc) {
merc->Dismiss(); if(CheckCanDismissMerc()) {
merc->Dismiss();
}
}
} }
//SendMercMerchantResponsePacket(10);
} }
void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app) void Client::Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app)

View File

@ -1904,7 +1904,6 @@ void Merc::AI_Process() {
void Merc::AI_Start(int32 iMoveDelay) { void Merc::AI_Start(int32 iMoveDelay) {
NPC::AI_Start(iMoveDelay); NPC::AI_Start(iMoveDelay);
if (!pAIControlled) if (!pAIControlled)
return; return;
@ -2373,13 +2372,13 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
if(selectedMercSpell.spellid > 0) { if(selectedMercSpell.spellid > 0) {
if(isDiscipline) { if(isDiscipline) {
castedSpell = UseDiscipline(selectedMercSpell.spellid, GetID()); castedSpell = UseDiscipline(selectedMercSpell.spellid, tar->GetID());
} }
else { else {
castedSpell = AIDoSpellCast(selectedMercSpell.spellid, this, -1, &TempDontBuffMeBeforeTime); castedSpell = AIDoSpellCast(selectedMercSpell.spellid, tar, -1, &TempDontBuffMeBeforeTime);
if(TempDontBuffMeBeforeTime != this->DontBuffMeBefore()) if(TempDontBuffMeBeforeTime != tar->DontBuffMeBefore())
this->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); tar->SetDontBuffMeBefore(TempDontBuffMeBeforeTime);
} }
} }
} }
@ -2400,13 +2399,13 @@ bool Merc::AICastSpell(int8 iChance, int32 iSpellTypes) {
if(selectedMercSpell.spellid > 0) { if(selectedMercSpell.spellid > 0) {
if(isDiscipline) { if(isDiscipline) {
castedSpell = UseDiscipline(selectedMercSpell.spellid, GetID()); castedSpell = UseDiscipline(selectedMercSpell.spellid, tar->GetPet()->GetID());
} }
else { else {
castedSpell = AIDoSpellCast(selectedMercSpell.spellid, this, -1, &TempDontBuffMeBeforeTime); castedSpell = AIDoSpellCast(selectedMercSpell.spellid, tar->GetPet(), -1, &TempDontBuffMeBeforeTime);
if(TempDontBuffMeBeforeTime != this->DontBuffMeBefore()) if(TempDontBuffMeBeforeTime != tar->GetPet()->DontBuffMeBefore())
this->SetDontBuffMeBefore(TempDontBuffMeBeforeTime); 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); snprintf(c->GetEPP().merc_name, 64, "%s", c->GetMercInfo().merc_name);
merc->SetSuspended(c->GetMercInfo().IsSuspended); merc->SetSuspended(c->GetMercInfo().IsSuspended);
merc->gender = c->GetMercInfo().Gender; merc->gender = c->GetMercInfo().Gender;
merc->SetHP(c->GetMercInfo().hp); merc->SetHP(c->GetMercInfo().hp <= 0 ? merc->GetMaxHP() : c->GetMercInfo().hp);
merc->SetMana(c->GetMercInfo().mana); merc->SetMana(c->GetMercInfo().hp <= 0 ? merc->GetMaxMana() : c->GetMercInfo().mana);
merc->SetEndurance(c->GetMercInfo().endurance); merc->SetEndurance(c->GetMercInfo().endurance);
merc->luclinface = c->GetMercInfo().face; merc->luclinface = c->GetMercInfo().face;
merc->hairstyle = c->GetMercInfo().luclinHairStyle; merc->hairstyle = c->GetMercInfo().luclinHairStyle;
@ -5357,7 +5356,71 @@ void Client::UpdateMercTimer()
} }
bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) { 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 //check for valid merchant - can check near area for any merchants
if(!merchant) { if(!merchant) {
@ -5365,7 +5428,7 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) {
SendMercMerchantResponsePacket(14); SendMercMerchantResponsePacket(14);
else else
SendMercMerchantResponsePacket(16); SendMercMerchantResponsePacket(16);
result = false; return false;
} }
//check for merchant too far away //check for merchant too far away
@ -5374,65 +5437,13 @@ bool Client::CheckCanHireMerc(Mob* merchant, uint32 template_id) {
SendMercMerchantResponsePacket(15); SendMercMerchantResponsePacket(15);
else else
SendMercMerchantResponsePacket(17); SendMercMerchantResponsePacket(17);
result = false; return false;
} }
return true;
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;
} }
bool Client::CheckCanRetainMerc(uint32 upkeep) { bool Client::CheckCanRetainMerc(uint32 upkeep) {
bool result = true;
Merc* merc = GetMerc(); Merc* merc = GetMerc();
//check for sufficient funds //check for sufficient funds
@ -5440,30 +5451,45 @@ bool Client::CheckCanRetainMerc(uint32 upkeep) {
if(merc) { if(merc) {
if(upkeep > 0 && !HasMoney(upkeep * 100)) { if(upkeep > 0 && !HasMoney(upkeep * 100)) {
SendMercMerchantResponsePacket(1); SendMercMerchantResponsePacket(1);
result = false; return false;
} }
} }
} }
return result; return true;
} }
bool Client::CheckCanUnsuspendMerc() { 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 //check for raid
if(HasRaid()) { if(HasRaid()) {
SendMercMerchantResponsePacket(4); SendMercMerchantResponsePacket(4);
result = false; return false;
} }
//check group size //check group size
if(HasGroup() && GetGroup()->GroupCount() == 6) { if(HasGroup() && GetGroup()->GroupCount() >= MAX_GROUP_MEMBERS) {
if (GetClientVersion() < EQClientRoF) if (GetClientVersion() < EQClientRoF)
SendMercMerchantResponsePacket(8); SendMercMerchantResponsePacket(8);
else else
SendMercMerchantResponsePacket(7); SendMercMerchantResponsePacket(7);
result = false; return false;
} }
//check if zone allows mercs //check if zone allows mercs
@ -5472,15 +5498,30 @@ bool Client::CheckCanUnsuspendMerc() {
SendMercMerchantResponsePacket(4); // ?? SendMercMerchantResponsePacket(4); // ??
else else
SendMercMerchantResponsePacket(4); // ?? SendMercMerchantResponsePacket(4); // ??
return false;
} }
//check in combat //check in combat
if(GetClientVersion() >= EQClientRoF && GetAggroCount() > 0) { if(GetClientVersion() >= EQClientRoF && GetAggroCount() > 0) {
SendMercMerchantResponsePacket(8); 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() void Client::CheckMercSuspendTimer()
@ -5596,6 +5637,10 @@ bool Merc::Suspend() {
SetSuspended(true); SetSuspended(true);
/*if(HasGroup()) {
RemoveMercFromGroup(this, GetGroup());
}*/
Save(); Save();
mercOwner->GetMercInfo().IsSuspended = true; mercOwner->GetMercInfo().IsSuspended = true;
@ -5645,16 +5690,15 @@ bool Merc::Unsuspend(bool setMaxStats) {
mercOwner->SendMercPersonalInfo(); mercOwner->SendMercPersonalInfo();
Group* g = entity_list.GetGroupByClient(mercOwner); Group* g = entity_list.GetGroupByClient(mercOwner);
if(!g) if(!g) { //nobody from our group is here... start a new group
{ //nobody from our group is here... start a new group
g = new Group(mercOwner); g = new Group(mercOwner);
if(!g) if(!g) {
{
delete g; delete g;
g = NULL; g = NULL;
return false; return false;
} }
entity_list.AddGroup(g); entity_list.AddGroup(g);
if(g->GetID() == 0) { if(g->GetID() == 0) {
@ -5663,8 +5707,7 @@ bool Merc::Unsuspend(bool setMaxStats) {
return false; return false;
} }
if(AddMercToGroup(this, g)) if(AddMercToGroup(this, g)) {
{
entity_list.AddGroup(g, g->GetID()); entity_list.AddGroup(g, g->GetID());
database.SetGroupLeaderName(g->GetID(), mercOwner->GetName()); database.SetGroupLeaderName(g->GetID(), mercOwner->GetName());
database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID()); database.SetGroupID(mercOwner->GetName(), g->GetID(), mercOwner->CharacterID());
@ -5673,20 +5716,17 @@ bool Merc::Unsuspend(bool setMaxStats) {
g->SaveGroupLeaderAA(); g->SaveGroupLeaderAA();
loaded = true; loaded = true;
} }
else else {
{ g->DisbandGroup();
g->DisbandGroup();
} }
} //else, somebody from our group is already here... } //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.SetGroupID(GetName(), mercOwner->GetGroup()->GetID(), mercOwner->CharacterID(), true);
database.RefreshGroupFromDB(mercOwner); database.RefreshGroupFromDB(mercOwner);
loaded = true; loaded = true;
} }
else else {
{
if(MERC_DEBUG > 0) if(MERC_DEBUG > 0)
mercOwner->Message(7, "Mercenary failed to join the group - Suspending"); mercOwner->Message(7, "Mercenary failed to join the group - Suspending");
@ -5913,10 +5953,12 @@ void Client::UpdateMercLevel() {
void Client::SendMercMerchantResponsePacket(int32 response_type) { void Client::SendMercMerchantResponsePacket(int32 response_type) {
// This response packet brings up the Mercenary Manager window // This response packet brings up the Mercenary Manager window
EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct)); if(GetClientVersion() >= EQClientSoD) {
MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer; EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryHire, sizeof(MercenaryMerchantResponse_Struct));
mmr->ResponseType = response_type; // send specified response type MercenaryMerchantResponse_Struct* mmr = (MercenaryMerchantResponse_Struct*)outapp->pBuffer;
FastQueuePacket(&outapp); mmr->ResponseType = response_type; // send specified response type
FastQueuePacket(&outapp);
}
} }
void Client::SendMercenaryUnknownPacket(uint8 type) { void Client::SendMercenaryUnknownPacket(uint8 type) {

View File

@ -248,8 +248,8 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
npc_aggro = d->npc_aggro; npc_aggro = d->npc_aggro;
if(!IsMerc()) //memleak fix, this really shouldn't be here if(!IsMerc())
AI_Start(); AI_Start();
d_meele_texture1 = d->d_meele_texture1; d_meele_texture1 = d->d_meele_texture1;
d_meele_texture2 = d->d_meele_texture2; d_meele_texture2 = d->d_meele_texture2;

View File

@ -208,15 +208,28 @@ void QuestManager::echo(int colour, const char *str) {
} }
void QuestManager::say(const char *str) { void QuestManager::say(const char *str) {
if (!owner) {
if(RuleB(NPC, EnableNPCQuestJournal) && initiator) LogFile->write(EQEMuLog::Quest, "QuestManager::say called with NULL owner. Probably syntax error in quest file.");
owner->QuestJournalledSay(initiator, str); return;
else }
owner->Say(str); else {
if(RuleB(NPC, EnableNPCQuestJournal) && initiator) {
owner->QuestJournalledSay(initiator, str);
}
else {
owner->Say(str);
}
}
} }
void QuestManager::say(const char *str, uint8 language) { 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) { 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) { uint16 QuestManager::spawn2(int npc_type, int grid, int unused, float x, float y, float z, float heading) {
const NPCType* tmp = 0; 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* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3);
npc->AddLootTable(); npc->AddLootTable();
entity_list.AddNPC(npc,true,true); entity_list.AddNPC(npc,true,true);
// Quag: Sleep in main thread? ICK! // Sleep in main thread? ICK!
// Sleep(200); // 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) // (we're in main thread, nothing else can possibly modify it)
if(grid > 0) 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; 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* npc = new NPC(tmp, 0, x, y, z, heading, FlyMode3);
npc->AddLootTable(); npc->AddLootTable();
entity_list.AddNPC(npc,true,true); entity_list.AddNPC(npc,true,true);
// Quag: Sleep in main thread? ICK! // Sleep in main thread? ICK!
// Sleep(200); // 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) // (we're in main thread, nothing else can possibly modify it)
if(grid > 0) if(grid > 0)
{ {
@ -514,76 +527,113 @@ void QuestManager::stopalltimers() {
} }
void QuestManager::emote(const char *str) { 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) { 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) { 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) 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 else
entity_list.MessageStatus(to_guilddbid, to_minstatus, color, "%s", str); entity_list.MessageStatus(to_guilddbid, to_minstatus, color, "%s", str);
} }
void QuestManager::depop(int npc_type) { // depop NPC and don't start spawn timer 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; return;
if (npc_type != 0) { }
Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); else {
if (tmp) { if (npc_type != 0) {
if (tmp != owner) { Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type);
tmp->CastToNPC()->Depop(); if (tmp) {
} if (tmp != owner) {
else { tmp->CastToNPC()->Depop();
depop_npc = true; }
else {
depop_npc = true;
}
} }
} }
} else { //depop self
else { //depop self depop_npc = true;
depop_npc = true; }
} }
} }
void QuestManager::depop_withtimer(int npc_type) { // depop NPC and start spawn timer 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; return;
if (npc_type != 0) { }
Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type); else {
if (tmp) { if (npc_type != 0) {
if (tmp != owner) { Mob * tmp = entity_list.GetMobByNpcTypeID(npc_type);
tmp->CastToNPC()->Depop(true); if (tmp) {
} if (tmp != owner) {
else { tmp->CastToNPC()->Depop(true);
owner->Depop(true); }
else {
owner->Depop(true);
}
} }
} }
} else { //depop self
else { //depop self owner->Depop(true);
owner->Depop(true); }
} }
} }
void QuestManager::depopall(int npc_type) { void QuestManager::depopall(int npc_type) {
if(owner->IsNPC() && npc_type > 0) if(owner && owner->IsNPC() && (npc_type > 0)) {
entity_list.DepopAll(npc_type); 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) { void QuestManager::depopzone(bool StartSpawnTimer) {
if(zone) if(zone) {
zone->Depop(StartSpawnTimer); zone->Depop(StartSpawnTimer);
}
else {
LogFile->write(EQEMuLog::Quest, "QuestManager::depopzone called with NULL zone. Probably syntax error in quest file.");
}
} }
void QuestManager::repopzone() { void QuestManager::repopzone() {
if(zone) if(zone) {
zone->Repop(); 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) { void QuestManager::settarget(const char *type, int target_id) {
@ -615,7 +665,7 @@ void QuestManager::sfollow() {
} }
void QuestManager::changedeity(int diety_id) { void QuestManager::changedeity(int diety_id) {
//Cofruben:-Changes the deity. //Changes the deity.
if(initiator) if(initiator)
{ {
if(initiator->IsClient()) if(initiator->IsClient())
@ -731,7 +781,7 @@ void QuestManager::snow(int weather) {
} }
void QuestManager::surname(const char *name) { void QuestManager::surname(const char *name) {
//Cofruben:-Changes the last name. //Changes the last name.
if(initiator) if(initiator)
{ {
if(initiator->IsClient()) if(initiator->IsClient())
@ -747,21 +797,21 @@ void QuestManager::surname(const char *name) {
} }
void QuestManager::permaclass(int class_id) { void QuestManager::permaclass(int class_id) {
//Cofruben:-Makes the client the class specified //Makes the client the class specified
initiator->SetBaseClass(class_id); initiator->SetBaseClass(class_id);
initiator->Save(2); initiator->Save(2);
initiator->Kick(); initiator->Kick();
} }
void QuestManager::permarace(int race_id) { void QuestManager::permarace(int race_id) {
//Cofruben:-Makes the client the race specified //Makes the client the race specified
initiator->SetBaseRace(race_id); initiator->SetBaseRace(race_id);
initiator->Save(2); initiator->Save(2);
initiator->Kick(); initiator->Kick();
} }
void QuestManager::permagender(int gender_id) { void QuestManager::permagender(int gender_id) {
//Cofruben:-Makes the client the gender specified //Makes the client the gender specified
initiator->SetBaseGender(gender_id); initiator->SetBaseGender(gender_id);
initiator->Save(2); initiator->Save(2);
initiator->Kick(); initiator->Kick();
@ -1039,7 +1089,7 @@ void QuestManager::save() {
void QuestManager::faction(int faction_id, int faction_value, int temp) { void QuestManager::faction(int faction_id, int faction_value, int temp) {
if (initiator && initiator->IsClient()) { if (initiator && initiator->IsClient()) {
if(faction_id != 0 && faction_value != 0) { if(faction_id != 0 && faction_value != 0) {
// SCORPIOUS2K - fixed faction command // fixed faction command
//Client *p; //Client *p;
initiator->SetFactionLevel2( initiator->SetFactionLevel2(
initiator->CharacterID(), initiator->CharacterID(),
@ -1111,7 +1161,7 @@ void QuestManager::itemlink(int item_id) {
} }
void QuestManager::signalwith(int npc_id, int signal_id, int wait_ms) { 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 // signal(npcid) - generates EVENT_SIGNAL on specified npc
if(wait_ms > 0) { if(wait_ms > 0) {
STimerList.push_back(SignalTimer(wait_ms, npc_id, signal_id)); 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) { 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) // setglobal(varname,value,options,duration)
//MYSQL_ROW row; //MYSQL_ROW row;
int qgZoneid=zone->GetZoneID(); int qgZoneid=zone->GetZoneID();
@ -1376,7 +1426,7 @@ int QuestManager::QGVarDuration(const char *fmt)
} }
void QuestManager::ding() { void QuestManager::ding() {
//-Cofruben:makes a sound. //makes a sound.
if (initiator && initiator->IsClient()) if (initiator && initiator->IsClient())
initiator->SendSound(); initiator->SendSound();
@ -1495,7 +1545,7 @@ void QuestManager::clear_proximity() {
} }
void QuestManager::setanim(int npc_type, int animnum) { void QuestManager::setanim(int npc_type, int animnum) {
//Cisyouc: adds appearance changes //adds appearance changes
Mob* thenpc = entity_list.GetMobByNpcTypeID(npc_type); Mob* thenpc = entity_list.GetMobByNpcTypeID(npc_type);
if(animnum < 0 || animnum >= _eaMaxAppearance) if(animnum < 0 || animnum >= _eaMaxAppearance)
return; return;

View File

@ -2564,6 +2564,22 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if(effect1 != effect2) if(effect1 != effect2)
continue; 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 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. If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it.