More pet command changes

Tweaks to attack
Initial implementation of ghold
Tweaks to hold
This commit is contained in:
Michael Cook (mackal) 2017-05-03 23:41:06 -04:00
parent 14c9ddf15a
commit b3d8bcab4a
10 changed files with 80 additions and 41 deletions

View File

@ -196,6 +196,7 @@ OP_Consent=0x400e
OP_ConsentDeny=0x34c1
OP_AutoFire=0x314e
OP_PetCommands=0x0093
OP_PetCommandState=0x74ed
OP_PetHoTT=0x0df4
OP_DeleteSpell=0x305c
OP_Surname=0x1a87

View File

@ -195,6 +195,7 @@ OP_Consent=0x1fd1
OP_ConsentDeny=0x7a45
OP_AutoFire=0x241e
OP_PetCommands=0x0159
OP_PetCommandState=0x1dc8
OP_PetHoTT=0x794a
OP_DeleteSpell=0x3358
OP_Surname=0x0423

View File

@ -198,6 +198,7 @@ OP_Consent=0x6bb9 # C
OP_ConsentDeny=0x4cd1 # C
OP_AutoFire=0x5db5 # C
OP_PetCommands=0x7706 # C
OP_PetCommandState=0x1a79
OP_PetHoTT=0x2528
OP_DeleteSpell=0x0698 # C
OP_Surname=0x44ae # C

View File

@ -2477,7 +2477,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil
return true;
}
void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/, uint16 spell_id)
void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/, uint16 spell_id, bool pet_command)
{
if (!other)
return;
@ -2516,13 +2516,18 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
}
}
if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus
return;
}
// Pet that is /pet hold on will not add to their hate list if they're not engaged
// Pet that is /pet hold on and /pet focus on will not add others to their hate list
// Pet that is /pet ghold on will never add to their hate list unless /pet attack or /pet qattack
if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) {
if (!targetmob)
return;
// we skip these checks if it's forced through a pet command
if (!pet_command) {
if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline)) {
if ((IsGHeld() || (IsHeld() && IsFocused())) && !on_hatelist) // we want them to be able to climb the hate list
return;
if (IsHeld() && !wasengaged)
return;
}
}
if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0))
@ -3306,7 +3311,10 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
} //end `if there is some damage being done and theres anattacker person involved`
Mob *pet = GetPet();
if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse())
// pets that have GHold will never automatically add NPCs
// pets that have Hold and no Focus will add NPCs if they're engaged
// pets that have Hold and Focus will not add NPCs
if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse() && !pet->IsGHeld())
{
if (!pet->IsHeld()) {
Log(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName());
@ -5295,4 +5303,4 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts)
}
}
}
}
}

View File

@ -3852,8 +3852,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT
}
//void Bot::AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false)
void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic);
void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic, bool pet_command) {
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic, pet_command);
}
bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) {

View File

@ -325,7 +325,7 @@ public:
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
void Camp(bool databaseSave = true);
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false);
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false);
virtual void SetTarget(Mob* mob);
virtual void Zone();
std::vector<AISpells_Struct> GetBotSpells() { return AIspells; }

View File

@ -10001,26 +10001,17 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) {
if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
if (mypet->IsHeld()) {
if (!mypet->IsFocused()) {
mypet->SetHeld(false); //break the hold and guard if we explicitly tell the pet to attack.
if (mypet->GetPetOrder() != SPO_Guard)
mypet->SetPetOrder(SPO_Follow);
}
else {
mypet->SetTarget(target);
}
}
zone->AddAggroMob();
// classic acts like qattack
int hate = 1;
if (IsEngaged()) {
auto top = hate_list.GetEntWithMostHateOnList(this);
if (top)
hate += hate_list.GetEntHateAmount(top);
if (mypet->IsEngaged()) {
auto top = mypet->GetHateMost();
if (top && top != target)
hate += mypet->GetHateAmount(top) - mypet->GetHateAmount(target) + 100; // should be enough to cause target change
}
mypet->AddToHateList(target, hate);
mypet->AddToHateList(target, hate, 0, true, false, false, SPELL_UNKNOWN, true);
Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName());
SetTarget(target);
}
}
break;
@ -10044,7 +10035,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) {
if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
zone->AddAggroMob();
mypet->AddToHateList(GetTarget(), 1);
mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true);
Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName());
}
}
@ -10098,7 +10089,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) {
if (mypet->IsNPC()) {
mypet->SetHeld(false);
mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE);
mypet->SetPetOrder(SPO_Guard);
mypet->CastToNPC()->SaveGuardSpot();
@ -10110,7 +10100,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) {
mypet->SetHeld(false);
mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING);
mypet->SetPetOrder(SPO_Follow);
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
@ -10150,7 +10139,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF
if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) {
mypet->SetHeld(false);
mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING);
mypet->SetPetOrder(SPO_Follow);
mypet->SendAppearancePacket(AT_Anim, ANIM_STAND);
@ -10204,30 +10192,24 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
}
case PET_HOLD: {
if (GetAA(aaPetDiscipline) && mypet->IsNPC()) {
if (mypet->IsFeared())
break; //could be exploited like PET_BACKOFF
if (mypet->IsHeld())
{
mypet->SetHeld(false);
}
else
{
mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD);
mypet->WipeHateList();
mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // they use new messages now, but only SoD+?
mypet->SetHeld(true);
}
mypet->SetGHeld(false);
}
break;
}
case PET_HOLD_ON: {
if (GetAA(aaPetDiscipline) && mypet->IsNPC() && !mypet->IsHeld()) {
if (mypet->IsFeared())
break; //could be exploited like PET_BACKOFF
mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD);
mypet->WipeHateList();
mypet->SetHeld(true);
mypet->SetGHeld(false);
}
break;
}
@ -10236,6 +10218,34 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
mypet->SetHeld(false);
break;
}
case PET_GHOLD: {
if (GetAA(aaPetDiscipline) && mypet->IsNPC()) {
if (mypet->IsGHeld())
{
mypet->SetGHeld(false);
}
else
{
mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // message wrong
mypet->SetGHeld(true);
}
mypet->SetHeld(false);
}
break;
}
case PET_GHOLD_ON: {
if (GetAA(aaPetDiscipline) && mypet->IsNPC()) {
mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD);
mypet->SetGHeld(true);
mypet->SetHeld(false);
}
break;
}
case PET_GHOLD_OFF: {
if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsGHeld())
mypet->SetGHeld(false);
break;
}
case PET_SPELLHOLD: {
if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) {
if (mypet->IsFeared())

View File

@ -533,7 +533,7 @@ public:
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GRAY; }
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN);
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
bool RemoveFromHateList(Mob* mob);
void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); }
@ -869,6 +869,8 @@ public:
inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; }
inline void SetHeld(bool nState) { held = nState; }
inline const bool IsHeld() const { return held; }
inline void SetGHeld(bool nState) { gheld = nState; }
inline const bool IsGHeld() const { return gheld; }
inline void SetNoCast(bool nState) { nocast = nState; }
inline const bool IsNoCast() const { return nocast; }
inline void SetFocused(bool nState) { focused = nState; }
@ -1179,6 +1181,7 @@ protected:
uint32 pLastChange;
bool held;
bool gheld;
bool nocast;
bool focused;
bool spawned;

View File

@ -37,6 +37,18 @@
#define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup
#define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup
// can change the state of these buttons with a packet
#define PET_BUTTON_SIT 0
#define PET_BUTTON_STOP 1
#define PET_BUTTON_REGROUP 2
#define PET_BUTTON_FOLLOW 3
#define PET_BUTTON_GUARD 4
#define PET_BUTTON_TAUNT 5
#define PET_BUTTON_HOLD 6
#define PET_BUTTON_GHOLD 7
#define PET_BUTTON_FOCUS 8
#define PET_BUTTON_SPELLHOLD 9
class Mob;
struct NPCType;

View File

@ -322,6 +322,9 @@
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
#define IDENTIFY_SPELL 6765 //Item Lore: %1.
#define PET_ON_GHOLD 6843 //Pet greater hold has been set to on.
#define PET_OFF_GHOLD 6846 //Pet greater hold has been set to off.
#define PET_GHOLD_ON_MSG 6847 //Now greater holding master. I will only attack something new if ordered.
#define BUFF_NOT_BLOCKABLE 7608 //You cannot block this effect.
#define LDON_DONT_KNOW_TRAPPED 7552 //You do not know if this object is trapped.
#define LDON_HAVE_DISARMED 7553 //You have disarmed %1!