/pet no cast and /pet focus
Took a little time to dig through the opcodes and figured out how the /pet commands are handled for the newer clients.
Here are the base changes required for /pet no cast and /pet focus to work similar to EQLive for all clients up to Underfoot.
Required Code:
Code:
Index: common/patches/Underfoot.cpp
===================================================================
--- common/patches/Underfoot.cpp (revision 2260)
+++ common/patches/Underfoot.cpp (working copy)
@@ -3260,6 +3260,15 @@
case 0x1d:
emu->command = 0x02; // Leave/Go Away
break;
+ case 0x15:
+ emu->command = 0x12; // No Cast - /command
+ break;
+ case 0x16:
+ emu->command = 0x12; // No Cast - Pet Window
+ break;
+ case 0x18:
+ emu->command = 0x13; // Focus - Pet Window
+ break;
default:
emu->command = eq->command;
}
Code:
Index: zone/attack.cpp
===================================================================
--- zone/attack.cpp (revision 2260)
+++ zone/attack.cpp (working copy)
@@ -2265,6 +2265,7 @@
Mob* owner = other->GetOwner();
Mob* mypet = this->GetPet();
Mob* myowner = this->GetOwner();
+ Mob* targetmob = this->GetTarget();
if(other){
AddRampage(other);
@@ -2274,10 +2275,15 @@
hate = ((hate * (hatemod))/100);
}
- if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld()){
+ if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus
return;
- }
+ }
+ if(IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) {
+ if (!targetmob)
+ return;
+ }
+
if(IsClient() && !IsAIControlled())
return;
@@ -3214,10 +3220,12 @@
Mob *pet = GetPet();
if (pet && !pet->IsFamiliar() && !pet->SpecAttacks[IMMUNE_AGGRO] && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse())
{
- mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName());
- pet->AddToHateList(attacker, 1);
- pet->SetTarget(attacker);
- Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName());
+ if (!pet->IsHeld()) {
+ mlog(PETS__AGGRO, "Sending pet %s into battle due to attack.", pet->GetName());
+ pet->AddToHateList(attacker, 1);
+ pet->SetTarget(attacker);
+ Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName());
+ }
}
//see if any runes want to reduce this damage
Code:
Index: zone/client_packet.cpp
===================================================================
--- zone/client_packet.cpp (revision 2260)
+++ zone/client_packet.cpp (working copy)
@@ -6864,9 +6864,15 @@
if((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) {
if (GetTarget() != this && mypet->DistNoRootNoZ(*GetTarget()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) {
- 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);
+ 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(GetTarget());
+ }
+ }
zone->AddAggroMob();
mypet->AddToHateList(GetTarget(), 1);
Message_StringID(10, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName());
@@ -7012,6 +7018,60 @@
}
break;
}
+ case PET_NOCAST: {
+ if(GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) {
+ if (mypet->IsFeared())
+ break;
+ if (mypet->IsNoCast()) {
+ Message(0,"%s says, 'I will now cast spells, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetNoCast(false);
+ } else {
+ Message(0,"%s says, 'I will no longer cast spells, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetNoCast(true);
+ }
+ }
+ break;
+ }
+ case PET_FOCUS: {
+ if(GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) {
+ if (mypet->IsFeared())
+ break;
+ if (mypet->IsFocused()) {
+ Message(0,"%s says, 'I am no longer focused, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetFocused(false);
+ } else {
+ Message(0,"%s says, 'I will now focus my attention, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetFocused(true);
+ }
+ }
+ break;
+ }
+ case PET_FOCUS_ON: {
+ if(GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) {
+ if (mypet->IsFeared())
+ break;
+ if (mypet->IsFocused()) {
+ Message(0,"%s says, 'I am already focused, Master!",mypet->GetCleanName());
+ } else {
+ Message(0,"%s says, 'I will now focus my attention, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetFocused(true);
+ }
+ }
+ break;
+ }
+ case PET_FOCUS_OFF: {
+ if(GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) {
+ if (mypet->IsFeared())
+ break;
+ if (mypet->IsFocused()) {
+ Message(0,"%s says, 'I am no longer focused, Master!",mypet->GetCleanName());
+ mypet->CastToNPC()->SetFocused(false);
+ } else {
+ Message(0,"%s says, 'I am already not focused, Master!",mypet->GetCleanName());
+ }
+ }
+ break;
+ }
default:
printf("Client attempted to use a unknown pet command:\n");
break;
Code:
Index: zone/mob.cpp
===================================================================
--- zone/mob.cpp (revision 2260)
+++ zone/mob.cpp (working copy)
@@ -306,6 +306,8 @@
typeofpet = petCharmed; //default to charmed...
petpower = 0;
held = false;
+ nocast = false;
+ focused = false;
attacked_count = 0;
mezzed = false;
@@ -2741,6 +2743,10 @@
if(spell_id == SPELL_UNKNOWN || on->SpecAttacks[NO_HARM_FROM_CLIENT]){ //This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
return;
}
+
+ if (IsNoCast())
+ return;
+
if(!IsValidSpell(spell_id)){ // Check for a valid spell otherwise it will crash through the function
if(this->IsClient()){
this->Message(0, "Invalid spell proc %u", spell_id);
Code:
Index: zone/mob.h
===================================================================
--- zone/mob.h (revision 2260)
+++ zone/mob.h (working copy)
@@ -1100,6 +1100,10 @@
inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; }
inline void SetHeld(bool nState) { held = nState; }
inline const bool IsHeld() const { return held; }
+ inline void SetNoCast(bool nState) { nocast = nState; }
+ inline const bool IsNoCast() const { return nocast; }
+ inline void SetFocused(bool nState) { focused = nState; }
+ inline const bool IsFocused() const { return focused; }
inline const bool IsRoamer() const { return roamer; }
inline const bool IsRooted() const { return rooted || permarooted; }
inline const bool HasVirus() const { return has_virus; }
@@ -1332,6 +1336,8 @@
float runspeed;
int32 pLastChange;
bool held;
+ bool nocast;
+ bool focused;
void CalcSpellBonuses(StatBonuses* newbon);
virtual void CalcBonuses();
void TrySkillProc(Mob *on, int16 skill, float chance);
Code:
Index: zone/MobAI.cpp
===================================================================
--- zone/MobAI.cpp (revision 2260)
+++ zone/MobAI.cpp (working copy)
@@ -58,6 +58,9 @@
if (!tar)
return false;
+ if (IsNoCast())
+ return false;
+
if(AI_HasSpells() == false)
return false;
@@ -1064,7 +1067,14 @@
{
if(AItarget_check_timer->Check())
{
- SetTarget(hate_list.GetTop(this));
+ if (IsFocused()) {
+ if (!target) {
+ SetTarget(hate_list.GetTop(this));
+ }
+ } else {
+ SetTarget(hate_list.GetTop(this));
+ }
+
}
}
Code:
Index: zone/pets.h
===================================================================
--- zone/pets.h (revision 2260)
+++ zone/pets.h (working copy)
@@ -15,6 +15,10 @@
#define PET_NOTAUNT 14
#define PET_LEADER 16
#define PET_SLUMBER 17
+ #define PET_NOCAST 18
+ #define PET_FOCUS 19
+ #define PET_FOCUS_ON 25
+ #define PET_FOCUS_OFF 26
class Pet : public NPC {
public:
Required SQL:
Code:
DELETE FROM `aa_effects` WHERE aaid = 288 or aaid = 1129 or aaid = 1130;
INSERT INTO `aa_effects` (`id` ,`aaid` ,`slot` ,`effectid` ,`base1` ,`base2`) VALUES (NULL , '288', '1', '267', '1', '15');
INSERT INTO `aa_effects` (`id` ,`aaid` ,`slot` ,`effectid` ,`base1` ,`base2`) VALUES (NULL , '1129', '1', '267', '1', '0');
INSERT INTO `aa_effects` (`id` ,`aaid` ,`slot` ,`effectid` ,`base1` ,`base2`) VALUES (NULL , '1129', '2', '267', '1', '24');
INSERT INTO `aa_effects` (`id` ,`aaid` ,`slot` ,`effectid` ,`base1` ,`base2`) VALUES (NULL , '1130', '1', '267', '1', '21');
INSERT INTO `aa_effects` (`id` ,`aaid` ,`slot` ,`effectid` ,`base1` ,`base2`) VALUES (NULL , '1130', '2', '267', '1', '24');
Vaion
|