View Single Post
  #1  
Old 11-24-2012, 11:35 AM
Weldarr
Sarnak
 
Join Date: Oct 2005
Posts: 45
Default /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
Reply With Quote