View Single Post
  #4  
Old 01-26-2016, 12:50 PM
Freshmaker
Fire Beetle
 
Join Date: May 2010
Posts: 5
Default

I've honestly never touched the eqemu codebase before, so everything is still entirely foreign to me.

I'm confident in most of the logic here other than how I attempt to grab the weapon(s) equipped by the pet. Random shot in the dark, untested, likely won't work. But, I can't test this right now.

Code:
diff --git a/zone/attack.cpp b/zone/attack.cpp
index 85ee29e..003acb3 100644
--- a/zone/attack.cpp
+++ b/zone/attack.cpp
@@ -4586,17 +4586,6 @@ void NPC::SetAttackTimer()
 	attack_timer.SetAtTrigger(4000, true);
 
 	Timer *TimerToUse = nullptr;
-	int hhe = itembonuses.HundredHands + spellbonuses.HundredHands;
-
-	// Technically NPCs should do some logic for weapons, but the effect is minimal
-	// What they do is take the lower of their set delay and the weapon's
-	// ex. Mob's delay set to 20, weapon set to 19, delay 19
-	// Mob's delay set to 20, weapon set to 21, delay 20
-	int speed = 0;
-	if (RuleB(Spells, Jun182014HundredHandsRevamp))
-		speed = static_cast<int>(((attack_delay / haste_mod) + ((hhe / 1000.0f) * (attack_delay / haste_mod))) * 100);
-	else
-		speed = static_cast<int>(((attack_delay / haste_mod) + ((hhe / 100.0f) * attack_delay)) * 100);
 
 	for (int i = MainRange; i <= MainSecondary; i++) {
 		//pick a timer
@@ -4609,6 +4598,13 @@ void NPC::SetAttackTimer()
 		else	//invalid slot (hands will always hit this)
 			continue;
 
+		const Item_Struct *ItemToUse = nullptr;
+
+		//find our item
+		ServerLootItem_Struct* item_data = GetItem(i);
+		if (item_data)
+			ItemToUse = database.GetItem(item_data->item_id);
+
 		//special offhand stuff
 		if (i == MainSecondary) {
 			// SPECATK_QUAD is uncheesable
@@ -4618,6 +4614,50 @@ void NPC::SetAttackTimer()
 			}
 		}
 
+		//see if we have a valid weapon
+		if (ItemToUse != nullptr) {
+			//check type and damage/delay
+			if (ItemToUse->ItemClass != ItemClassCommon
+					|| ItemToUse->Damage == 0
+					|| ItemToUse->Delay == 0) {
+				//no weapon
+				ItemToUse = nullptr;
+			}
+			// Check to see if skill is valid
+			else if ((ItemToUse->ItemType > ItemTypeLargeThrowing) &&
+					(ItemToUse->ItemType != ItemTypeMartial) &&
+					(ItemToUse->ItemType != ItemType2HPiercing)) {
+				//no weapon
+				ItemToUse = nullptr;
+			}
+		}
+
+		int hhe = itembonuses.HundredHands + spellbonuses.HundredHands;
+
+		// Client pets do some logic for weapons, but the effect is minimal
+		// What they do is take the lower of their set delay and the weapon's
+		// ex. Pet's delay set to 20, weapon set to 19, delay 19
+		// Pet's delay set to 20, weapon set to 21, delay 20
+		int speed = 0;
+		int delay = 100 * attack_delay;
+
+		// Only apply the weapon-based delay modifications to Client pets. Otherwise,
+		// this change would affect all NPCs and their pets
+		bool clientpet = false;
+		if ((IsPet() || IsTempPet()) && IsPetOwnerClient())
+			clientpet = true;
+
+		// Apply weapon delay only if it's faster than the pet's default attack_delay
+		if (clientpet && (ItemToUse != nullptr) && (ItemToUse->Delay < attack_delay))
+			delay = 100 * ItemToUse->Delay;
+
+		speed = delay / haste_mod;
+
+		if (RuleB(Spells, Jun182014HundredHandsRevamp))
+			speed = static_cast<int>(speed + ((hhe / 1000.0f) * speed));
+		else
+			speed = static_cast<int>(speed + ((hhe / 100.0f) * delay));
+
 		TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true);
 	}
 }
It at least compiles, but that means little. If you care to give 'er a whirl, let me know. I may be able to test this tonight.
Reply With Quote