diff --git a/common/spdat.h b/common/spdat.h index 913ee5a4b..bd1dacdf8 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -468,7 +468,7 @@ typedef enum { #define SE_Blank 254 // implemented #define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield #define SE_ShroudofStealth 256 // implemented -#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold +#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold #define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab #define SE_CombatStability 259 // implemented[AA] - damage mitigation #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType @@ -478,7 +478,7 @@ typedef enum { #define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. -#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast +#define SE_AddPetCommand 267 // implemented - sets command base2 to base1 #define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance #define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. #define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo) diff --git a/zone/attack.cpp b/zone/attack.cpp index bbb17d2ec..179534966 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2522,7 +2522,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b // we skip these checks if it's forced through a pet command if (!pet_command) { - if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline)) { + if (IsPet()) { if ((IsGHeld() || (IsHeld() && IsFocused())) && !on_hatelist) // we want them to be able to climb the hate list return; if (IsHeld() && !wasengaged) @@ -2632,7 +2632,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } - if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it + if (mypet && !mypet->IsHeld()) { // I have a pet, add other to it if (!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e732d596b..7544ceb5f 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1442,11 +1442,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->FeignedCastOnChance = base1; break; + case SE_AddPetCommand: + if (base1 && base2 < PET_MAXCOMMANDS) + newbon->PetCommands[base2] = true; + break; + + case SE_FeignedMinion: + if (newbon->FeignedMinionChance < base1) + newbon->FeignedMinionChance = base1; + break; + // to do case SE_PetDiscipline: break; - case SE_PetDiscipline2: - break; case SE_PotionBeltSlots: break; case SE_BandolierSlots: @@ -1465,8 +1473,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_TrapCircumvention: break; - case SE_FeignedMinion: - break; // not handled here case SE_HastenedAASkill: diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 499402997..600d02757 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9978,9 +9978,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->GetPetType() == petTargetLock && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST)) return; - if (mypet->GetPetType() == petAnimation && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST) && !GetAA(aaAnimationEmpathy)) - return; - // just let the command "/pet get lost" work for familiars if (mypet->GetPetType() == petFamiliar && pet->command != PET_GETLOST) return; @@ -10014,7 +10011,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { zone->AddAggroMob(); // classic acts like qattack @@ -10047,7 +10044,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { zone->AddAggroMob(); mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); @@ -10059,7 +10056,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_BACKOFF: { if (mypet->IsFeared()) break; //keeps pet running while feared - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_CALMING); mypet->WipeHateList(); mypet->SetTarget(nullptr); @@ -10067,9 +10064,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HEALTHREPORT: { - Message_StringID(MT_PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); - mypet->ShowBuffList(this); - //Message(10,"%s tells you, 'I have %d percent of my hit points left.'",mypet->GetName(),(uint8)mypet->GetHPRatio()); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + Message_StringID(MT_PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); + mypet->ShowBuffList(this); + } break; } case PET_GETLOST: { @@ -10102,7 +10100,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_GUARDHERE: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->IsNPC()) { mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE); mypet->SetPetOrder(SPO_Guard); @@ -10114,7 +10112,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_FOLLOWME: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10122,7 +10120,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_TAUNT: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->CastToNPC()->IsTaunting()) { Message_StringID(MT_PetResponse, PET_NO_TAUNT); @@ -10137,14 +10135,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_TAUNT_ON: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_DO_TAUNT); mypet->CastToNPC()->SetTaunting(true); } break; } case PET_TAUNT_OFF: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_NO_TAUNT); mypet->CastToNPC()->SetTaunting(false); } @@ -10153,7 +10151,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_GUARDME: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10163,7 +10161,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_SIT: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->GetPetOrder() == SPO_Sit) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); @@ -10185,7 +10183,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_STANDUP: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10195,7 +10193,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_SITDOWN: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Sit); mypet->SetRunAnimSpeed(0); @@ -10206,7 +10204,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsHeld()) { mypet->SetHeld(false); @@ -10222,7 +10220,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD_ON: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && !mypet->IsHeld()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) { mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); mypet->SetGHeld(false); @@ -10231,12 +10229,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD_OFF: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) mypet->SetHeld(false); break; } case PET_GHOLD: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsGHeld()) { mypet->SetGHeld(false); @@ -10252,7 +10250,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_GHOLD_ON: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetGHeld(true); mypet->SetHeld(false); @@ -10261,12 +10259,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_GHOLD_OFF: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsGHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) mypet->SetGHeld(false); break; } case PET_SPELLHOLD: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsNoCast()) { @@ -10281,7 +10279,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_SPELLHOLD_ON: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (!mypet->IsNoCast()) { @@ -10292,7 +10290,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_SPELLHOLD_OFF: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsNoCast()) { @@ -10303,7 +10301,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsFocused()) { @@ -10318,7 +10316,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS_ON: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (!mypet->IsFocused()) { @@ -10329,7 +10327,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS_OFF: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsFocused()) { diff --git a/zone/common.h b/zone/common.h index 02d26b041..dad32925e 100644 --- a/zone/common.h +++ b/zone/common.h @@ -91,6 +91,7 @@ #define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list #define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup #define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup +#define PET_MAXCOMMANDS PET_REGROUPOFF + 1 // can change the state of these buttons with a packet #define PET_BUTTON_SIT 0 @@ -533,6 +534,8 @@ struct StatBonuses { uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill. int16 NoBreakAESneak; // Percent value int16 FeignedCastOnChance; // Percent Value + bool PetCommands[PET_MAXCOMMANDS]; // SPA 267 + int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD }; typedef struct