EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Server Code Submissions (https://www.eqemulator.org/forums/forumdisplay.php?f=669)
-   -   /pet no cast and /pet focus (https://www.eqemulator.org/forums/showthread.php?t=36029)

Weldarr 11-24-2012 11:35 AM

/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

ghanja 11-24-2012 01:05 PM

Not quite sure if replies by those other than the contributor and/or emu devs is 'allowed' but this is one addition/fix I have to thank you for. It -was- a project I was in the middle of attempting to resolve as well, appreciate reducing my labor. :)

sorvani 11-24-2012 01:40 PM

i started to look into this once myself and realized i need to understand eqemu source better unfortunately.
This is built with no errors for me on my test server.

I find it easier to make and apply a single diff for large patches like this.
Code:

Index: trunk/EQEmuServer/common/patches/Underfoot.cpp
===================================================================
--- trunk/EQEmuServer/common/patches/Underfoot.cpp        (revision 2260)
+++ trunk/EQEmuServer/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;
        }
Index: trunk/EQEmuServer/zone/attack.cpp
===================================================================
--- trunk/EQEmuServer/zone/attack.cpp        (revision 2260)
+++ trunk/EQEmuServer/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
Index: trunk/EQEmuServer/zone/client_packet.cpp
===================================================================
--- trunk/EQEmuServer/zone/client_packet.cpp        (revision 2260)
+++ trunk/EQEmuServer/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;
Index: trunk/EQEmuServer/zone/mob.cpp
===================================================================
--- trunk/EQEmuServer/zone/mob.cpp        (revision 2260)
+++ trunk/EQEmuServer/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);
Index: trunk/EQEmuServer/zone/mob.h
===================================================================
--- trunk/EQEmuServer/zone/mob.h        (revision 2260)
+++ trunk/EQEmuServer/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);
Index: trunk/EQEmuServer/zone/MobAI.cpp
===================================================================
--- trunk/EQEmuServer/zone/MobAI.cpp        (revision 2260)
+++ trunk/EQEmuServer/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));
+                                }
+
                        }
                }
Index: trunk/EQEmuServer/zone/pets.h
===================================================================
--- trunk/EQEmuServer/zone/pets.h        (revision 2260)
+++ trunk/EQEmuServer/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:


Weldarr 11-24-2012 01:42 PM

Aye I had it as a single patch, but figured it would be easier for people to read through if I separated it.

sorvani 11-24-2012 01:53 PM

damn was going to test it and realized i lost my x64 test box when i decided to rebuild a new web server.
rebuilding x32 and installing everything on a different test box :)

sorvani 11-24-2012 04:11 PM

was confused why it did not work then realized i was level 65. upped the level to 70 on my test server and it worked fine.

committed asrev 2262

sorvani 11-24-2012 04:26 PM

on this same subject, one would then assume that the /pet hold toggle would be found around here then. before I go look at how the source is handling it, have you already solved that one too?

Weldarr 11-24-2012 09:43 PM

Pet hold was already fixed awhile back. There were a few modification that I made with the SQL to clean up the AA effects that were not required for anything.

In the SQL the effect 267 with base 15 is the pet hold command for the UF client. So this fix already incorporates pet hold.

To use it you just need to purchase the pet discipline AA. To use focus/no cast you need to purchase the advanced pet discipline AAs.

sorvani 11-25-2012 09:15 PM

with a default PEQ database pet hold does not toggle. i tested that to make sure before I posted. Yes pet hold works. no it does not toggle.


All times are GMT -4. The time now is 10:19 PM.

Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.