@@ -1305,15 +1305,17 @@ index b82bd78f34..d58f648db8 100644
setCompoundState.StateChanges.emplace_back(SMSG_MOVE_ROOT, m_movementCounter++);
if (HasAuraType(SPELL_AURA_FEATHER_FALL))
@@ -27740,6 +27836,13 @@ void Player::StoreLootItem(ObjectGuid lootWorldObjectGuid, uint8 lootSlot, Loot*
@@ -27740,6 +27836,15 @@ void Player::StoreLootItem(ObjectGuid lootWorldObjectGuid, uint8 lootSlot, Loot*
Item* newitem = StoreNewItem(dest, item->itemid, true, item->randomBonusListId, item->GetAllowedLooters(), item->context);
+#if TRINITY_PLAYERBOT_V2
+ // Quest-item propagation: when the owner loots a quest item,
+ // give a copy to all owned bots who still need it. (f47eaa0740)
+ if (newitem)
+ Playerbot::Hooks::OnPlayerLootItem(this, item->itemid, item->count);
+ // Fire regardless of whether StoreNewItem created a physical item —
+ // quest-BOUND items return nullptr from StoreNewItem (objective
+ // guard) but must still propagate to owned bots.
+ Playerbot::Hooks::OnPlayerLootItem(this, item->itemid, item->count);
+#endif
+
if (newitem && (newitem->GetQuality() > ITEM_QUALITY_EPIC || (newitem->GetQuality() == ITEM_QUALITY_EPIC && newitem->GetItemLevel(this) >= MinNewsItemLevel)))
@@ -1360,7 +1362,7 @@ index 4577fffa77..1126d89a09 100644
void RemoveLootRoll(LootRoll* roll);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 1f376653f2..971fb43af8 100644
index 43e3ba2..ac73ca7 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -91,6 +91,7 @@
@@ -1371,7 +1373,7 @@ index 1f376653f2..971fb43af8 100644
#include <queue>
#include <sstream>
#include <cmath>
@@ -870,6 +871,13 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit const* excludeCasterChannel
@@ -884,6 +885,13 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit const* excludeCasterChannel
// Hook for OnDamage Event
sScriptMgr->OnDamage(attacker, victim, tmpDamage);
@@ -1385,7 +1387,7 @@ index 1f376653f2..971fb43af8 100644
// if any script modified damage, we need to also apply the same modification to unscaled damage value
if (tmpDamage != damageTaken)
{
@@ -6041,6 +6049,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
@@ -6055,6 +6063,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
if (Creature* cControlled = controlled->ToCreature())
if (CreatureAI* controlledAI = cControlled->AI())
controlledAI->OwnerAttacked(victim);
@@ -1396,7 +1398,7 @@ index 1f376653f2..971fb43af8 100644
}
return true;
@@ -6624,6 +6636,13 @@ void Unit::SetCharm(Unit* charm, bool apply)
@@ -6636,6 +6648,13 @@ void Unit::SetCharm(Unit* charm, bool apply)
// Hook for OnHeal Event
sScriptMgr->OnHeal(healer, victim, (uint32&)gain);
@@ -1410,7 +1412,7 @@ index 1f376653f2..971fb43af8 100644
Unit* unit = healer;
if (healer && healer->GetTypeId() == TYPEID_UNIT && healer->IsTotem())
unit = healer->GetOwner();
@@ -8430,6 +8431,15 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
@@ -8443,6 +8462,15 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
SetUnitFlag(UNIT_FLAG_MOUNT);
@@ -1426,7 +1428,7 @@ index 1f376653f2..971fb43af8 100644
CalculateHoverHeight();
if (Player* player = ToPlayer())
@@ -8460,6 +8470,13 @@ void Unit::Dismount()
@@ -8473,6 +8501,13 @@ void Unit::Dismount()
if (!IsMounted())
return;
@@ -1440,7 +1442,7 @@ index 1f376653f2..971fb43af8 100644
SetMountDisplayId(0);
RemoveUnitFlag(UNIT_FLAG_MOUNT);
@@ -11459,6 +11478,13 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
@@ -11489,6 +11524,13 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
if (attacker && !attacker->IsInMap(victim))
attacker = nullptr;
@@ -1451,11 +1453,10 @@ index 1f376653f2..971fb43af8 100644
+ Playerbot::Hooks::OnDeath(victim, attacker);
+#endif
+
// find player: owner of controlled `this` or `this` itself maybe
Player* player = nullptr;
if (attacker)
@@ -13071,5 +13113,13 @@ void Unit::_ExitVehicle(Position const* exitPosition)
// If the player is on mounted duel and exits the mount, he should immediatly lose the duel
// find player: owner of controlled `this` or `this` itself maybe
Player* player = nullptr;
if (attacker)
@@ -13682,6 +13724,14 @@ void Unit::_ExitVehicle(Position const* exitPosition)
if (player && player->duel && player->duel->IsMounted)
player->DuelComplete(DUEL_FLED);
@@ -1468,6 +1469,11 @@ index 1f376653f2..971fb43af8 100644
+#endif
+
SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
AddUnitState(UNIT_STATE_MOVE);
diff --git a/src/server/game/Entities/Unit/Unit.cpp.rej b/src/server/game/Entities/Unit/Unit.cpp.rej
new file mode 100644
index 0000000..e69de29
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index 58951339b2..7ce860e770 100644
--- a/src/server/game/Groups/GroupMgr.h