Fixed merc buffing bugs, added checks before dismissing merc to prevent possible bugged mercs, merged in Secret's merc memory leak fixes.

This commit is contained in:
badcaptain
2013-03-22 00:03:50 -04:00
parent 09df77b56e
commit a20c7735e8
6 changed files with 227 additions and 150 deletions
+153 -103
View File
@@ -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) {