I was curious why the Backpacks plugin even uses the CanLootPlayer hook, so I spent some time investigating. Looking at the game code, it seems this is required for a few reasons. First, Backpacks uses just an ItemContainer, not an actual storage entity. A source entity is required for the player to loot something, so Backpacks assigns the player themself as the entity when attempting to open the backpack loot panel. By itself, this wouldn't work because the game is hard coded to not allow a player to loot themself. That's where the CanLootPlayer hook comes in. It allows a plugin to forcibly allow (or disallow) a player to loot another player (including themself). The issue here is that Backpacks has indicated to Oxide that it wants to allow the player to loot themself, and Zone Manager has indicated to Oxide that it wants to disallow looting.
This conflict cannot be resolved automatically because Oxide can't know which plugin should take priority. This needs to be resolved by one of the plugins specifically calling the other and deciding to return the same value. In this case, in order for the player to open their backpack, both plugins must return true. Editing the Backpacks plugin won't do any good since Backpacks is already returning true. Therefore, the only solution is to update Zone Manager to return true in specific situations. Specifically, when the looting player and the looted player are equal, Zone Manager should check if the Backpacks plugin is loaded, call the CanLootPlayer method of Backpacks, and if that method returns true, Zone Manager should return true as well.
Zone Manager change #1:
[PluginReference] Plugin PopupNotifications, Spawns;
should become:
[PluginReference] Plugin Backpacks, PopupNotifications, Spawns;
Zone Manager change #2:private object OnLootPlayerInternal(BasePlayer looter, BasePlayer target)
{
if (HasPlayerFlag(looter, ZoneFlags.NoPlayerLoot, false) || (target != null && HasPlayerFlag(target, ZoneFlags.NoPlayerLoot, false)))
{
SendMessage(looter, Message("noLoot", looter.UserIDString));
NextTick(looter.EndLooting);
return false;
}
return null;
}
should become:
private object OnLootPlayerInternal(BasePlayer looter, BasePlayer target)
{
if (HasPlayerFlag(looter, ZoneFlags.NoPlayerLoot, false) || (target != null && HasPlayerFlag(target, ZoneFlags.NoPlayerLoot, false)))
{
if (looter == target && Backpacks != null)
{
// Allow players to open their own backpacks
object hookResult = Backpacks.Call("CanLootPlayer", target, looter);
if (hookResult is bool && (bool)hookResult)
return true;
}
SendMessage(looter, Message("noLoot", looter.UserIDString));
NextTick(looter.EndLooting);
return false;
}
return null;
}
If this works for you, then I'll ping the Zone Manager maintainer about adding this fix since patching isn't currently enabled on the plugin.