package net.sf.l2j.gameserver.model.itemcontainer.listeners;
import net.sf.l2j.commons.pool.ThreadPool;
import net.sf.l2j.gameserver.enums.Paperdoll;
import net.sf.l2j.gameserver.model.actor.Creature;
import net.sf.l2j.gameserver.model.actor.Npc;
import net.sf.l2j.gameserver.model.actor.Playable;
import net.sf.l2j.gameserver.model.actor.Player;
import net.sf.l2j.gameserver.model.item.instance.ItemInstance;
/**
* By Atrein:
*/
public class MonasteryWeaponAggroListener implements OnEquipListener
{
private static final int CHECK_RANGE = 1200;
private static final long UNEQUIP_CHECK_DELAY = 150L;
@Override
public void onEquip(Paperdoll slot, ItemInstance item, Playable actor)
{
}
@Override
public void onUnequip(Paperdoll slot, ItemInstance item, Playable actor)
{
if (slot != Paperdoll.RHAND)
return;
if (item == null || !item.isWeapon())
return;
if (!(actor instanceof Player player))
return;
ThreadPool.schedule(() -> clearMonasteryWeaponAggro(player), UNEQUIP_CHECK_DELAY);
}
private static void clearMonasteryWeaponAggro(Player player)
{
if (player == null || player.isDead())
return;
if (player.getActiveWeaponInstance() != null)
return;
for (Npc npc : player.getKnownTypeInRadius(Npc.class, CHECK_RANGE))
clearMonasteryWeaponAggro(npc, player);
}
private static void clearMonasteryWeaponAggro(Npc npc, Player player)
{
if (npc == null || npc.isDead())
return;
if (!isMonasteryWeaponAggroNpc(npc.getNpcId()))
return;
if (wasDamagedByPlayer(npc, player))
return;
boolean cleaned = false;
if (npc.getTarget() != null && npc.getTarget().getActingPlayer() == player)
{
npc.abortAll(true);
cleaned = true;
}
if (npc.getAI().getDesires().removeIf(desire -> isRelatedToPlayer(desire.getFinalTarget(), player)))
cleaned = true;
for (Creature target : npc.getAI().getAggroList().keySet())
{
if (isRelatedToPlayer(target, player))
{
npc.getAI().getAggroList().stopHate(target);
cleaned = true;
}
}
for (Creature target : npc.getAI().getHateList().keySet())
{
if (isRelatedToPlayer(target, player))
{
npc.getAI().getHateList().stopHate(target);
cleaned = true;
}
}
if (clearAiTargetReferences(npc, player))
cleaned = true;
if (cleaned && !hasAttackDesire(npc))
npc.getAI().setBackToPeace();
}
private static boolean wasDamagedByPlayer(Npc npc, Player player)
{
final Creature lastAttacker = npc.getLastAttacker();
return lastAttacker != null && lastAttacker.getActingPlayer() == player;
}
private static boolean isRelatedToPlayer(Creature target, Player player)
{
return target != null && target.getActingPlayer() == player;
}
private static boolean clearAiTargetReferences(Npc npc, Player player)
{
boolean cleaned = false;
if (isRelatedToPlayer(npc._c_ai0, player))
{
npc._c_ai0 = null;
cleaned = true;
}
if (isRelatedToPlayer(npc._c_ai1, player))
{
npc._c_ai1 = null;
cleaned = true;
}
if (isRelatedToPlayer(npc._c_ai2, player))
{
npc._c_ai2 = null;
cleaned = true;
}
if (isRelatedToPlayer(npc._c_ai3, player))
{
npc._c_ai3 = null;
cleaned = true;
}
if (isRelatedToPlayer(npc._c_ai4, player))
{
npc._c_ai4 = null;
cleaned = true;
}
return cleaned;
}
private static boolean hasAttackDesire(Npc npc)
{
return npc.getAI().getDesires().stream().anyMatch(desire -> desire.getType() == net.sf.l2j.gameserver.enums.IntentionType.ATTACK);
}
private static boolean isMonasteryWeaponAggroNpc(int npcId)
{
return switch (npcId)
{
case 22124, // Solina Brother
22126, // Silent Seeker
22129 // Warrior Monk
-> true;
default -> false;
};
}
public static MonasteryWeaponAggroListener getInstance()
{
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder
{
protected static final MonasteryWeaponAggroListener INSTANCE = new MonasteryWeaponAggroListener();
}
}