diff --git a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_1.0_Ertheia/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_2.5_Underground/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_3.0_Helios/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_4.0_GrandCrusade/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_5.0_Salvation/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_5.5_EtinasFate/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_6.0_Fafurion/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/others/SiegeGuards.java index 9953f564f6..65f427b6c5 100644 --- a/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_7.0_PreludeOfWar/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/scripts/ai/others/SiegeGuards.java index 538cf2cddc..2099ab03fd 100644 --- a/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_CT_2.4_Epilogue/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,43 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || (target.isPlayer() && target.getActingPlayer().isInvul())) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange())) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)) && (!pl.isInvisible() && !pl.isInvul())) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - addAttackDesire(guard, pl); - break; // no need to search more + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -157,22 +202,32 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @Override public String onSpawn(Npc npc) { - // npc.setRandomWalking(false); + npc.setRandomWalking(false); if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE)) { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/ai/others/SiegeGuards.java index 538cf2cddc..2099ab03fd 100644 --- a/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_CT_2.6_HighFive/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,16 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; +import org.l2jmobius.gameserver.instancemanager.FortManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -87,7 +92,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -104,43 +109,83 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } + + // Start tasks for fortresses. + for (Fort fort : FortManager.getInstance().getForts()) + { + final int residenceId = fort.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), 900 + ((residenceId - 100) * 100), 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || (target.isPlayer() && target.getActingPlayer().isInvul())) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange())) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)) && (!pl.isInvisible() && !pl.isInvul())) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - addAttackDesire(guard, pl); - break; // no need to search more + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -157,22 +202,32 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @Override public String onSpawn(Npc npc) { - // npc.setRandomWalking(false); + npc.setRandomWalking(false); if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE)) { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); } diff --git a/L2J_Mobius_Classic_Interlude/dist/game/data/scripts/ai/others/SiegeGuards.java b/L2J_Mobius_Classic_Interlude/dist/game/data/scripts/ai/others/SiegeGuards.java index 55d4a5b27b..4fed56d0ca 100644 --- a/L2J_Mobius_Classic_Interlude/dist/game/data/scripts/ai/others/SiegeGuards.java +++ b/L2J_Mobius_Classic_Interlude/dist/game/data/scripts/ai/others/SiegeGuards.java @@ -16,11 +16,15 @@ */ package ai.others; -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import org.l2jmobius.commons.concurrent.ThreadPool; import org.l2jmobius.gameserver.ai.CtrlIntention; import org.l2jmobius.gameserver.geoengine.GeoEngine; +import org.l2jmobius.gameserver.instancemanager.CastleManager; import org.l2jmobius.gameserver.model.World; import org.l2jmobius.gameserver.model.WorldObject; import org.l2jmobius.gameserver.model.actor.Attackable; @@ -63,7 +67,7 @@ public class SiegeGuards extends AbstractNpcAI 35134, 35135, 35136, 35176, 35177, 35178, 35218, 35219, 35220, 35261, 35262, 35263, 35264, 35265, 35308, 35309, 35310, 35352, 35353, 35354, 35497, 35498, 35499, 35500, 35501, 35544, 35545, 35546 }; //@formatter:on - private static final Collection SPAWNED_GUARDS = ConcurrentHashMap.newKeySet(); + private static final Map> RESIDENCE_GUARD_MAP = new HashMap<>(); public SiegeGuards() { @@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI addKillId(MERCENARIES); addKillId(STATIONARY_MERCENARIES); - startQuestTimer("AGGRO_CHECK", 3000, null, null, true); + // Start task for unknown residences. + RESIDENCE_GUARD_MAP.put(0, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(0), 0, 3000); + + // Start tasks for castles. + for (Castle castle : CastleManager.getInstance().getCastles()) + { + final int residenceId = castle.getResidenceId(); + RESIDENCE_GUARD_MAP.put(residenceId, new CopyOnWriteArrayList<>()); + ThreadPool.scheduleAtFixedRate(new AggroCheckTask(residenceId), residenceId * 100, 3000); + } } - @Override - public String onAdvEvent(String event, Npc npc, PlayerInstance player) + private class AggroCheckTask implements Runnable { - for (Npc guard : SPAWNED_GUARDS) + private final int _residenceId; + + public AggroCheckTask(int residenceId) { - if (guard != null) + _residenceId = residenceId; + } + + @Override + public void run() + { + final List guards = RESIDENCE_GUARD_MAP.get(_residenceId); + for (Npc guard : guards) { + if (guard == null) + { + continue; + } + if (guard.isDead()) { - SPAWNED_GUARDS.remove(guard); + guards.remove(guard); + continue; } - else + + final WorldObject target = guard.getTarget(); + if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) { - final WorldObject target = guard.getTarget(); - if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul()) + for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) { - for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange())) + if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) { - if (nearby.isPlayable() && GeoEngine.getInstance().canSeeTarget(guard, nearby)) + final Summon summon = nearby.isSummon() ? (Summon) nearby : null; + final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); + if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) { - final Summon summon = nearby.isSummon() ? (Summon) nearby : null; - final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner(); - if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))) + // skip invisible players + if (pl.isInvisible() || pl.isInvul()) { - if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players - { - addAttackPlayerDesire(guard, pl); - break; // no need to search more - } + continue; } + + if (guard.isAttackable()) + { + ((Attackable) guard).addDamageHate(nearby, 0, 999); + } + guard.setRunning(); + guard.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, target); + break; // no need to search more } } } } } } - return super.onAdvEvent(event, npc, player); } @Override @@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI @Override public String onKill(Npc npc, PlayerInstance killer, boolean isSummon) { - SPAWNED_GUARDS.remove(npc); + RESIDENCE_GUARD_MAP.get(npc.getScriptValue()).remove(npc); return super.onKill(npc, killer, isSummon); } @@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI { npc.setImmobilized(true); } + final Castle castle = npc.getCastle(); final Fort fortress = npc.getFort(); - npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0)); - SPAWNED_GUARDS.add(npc); + final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0); + npc.setScriptValue(residenceId); + if (RESIDENCE_GUARD_MAP.containsKey(residenceId)) + { + RESIDENCE_GUARD_MAP.get(residenceId).add(npc); + } + else // Residence id not found. + { + RESIDENCE_GUARD_MAP.get(0).add(npc); + } + return super.onSpawn(npc); }