Separated siege guard task to one task per residence.
This commit is contained in:
parent
e7db7efaa7
commit
de2871bef6
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,46 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -160,7 +202,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,10 +214,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,43 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > 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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)) && (!pl.isInvisible() && !pl.isInvul()))
|
|
||||||
{
|
{
|
||||||
addAttackDesire(guard, pl);
|
continue;
|
||||||
break; // no need to search more
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -157,22 +202,32 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String onSpawn(Npc npc)
|
public String onSpawn(Npc npc)
|
||||||
{
|
{
|
||||||
// npc.setRandomWalking(false);
|
npc.setRandomWalking(false);
|
||||||
if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE))
|
if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE))
|
||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
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.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -104,43 +109,83 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > 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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)) && (!pl.isInvisible() && !pl.isInvul()))
|
|
||||||
{
|
{
|
||||||
addAttackDesire(guard, pl);
|
continue;
|
||||||
break; // no need to search more
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -157,22 +202,32 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String onSpawn(Npc npc)
|
public String onSpawn(Npc npc)
|
||||||
{
|
{
|
||||||
// npc.setRandomWalking(false);
|
npc.setRandomWalking(false);
|
||||||
if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE))
|
if ((npc.getTemplate().getBaseAttackType() != WeaponType.SWORD) && (npc.getTemplate().getBaseAttackType() != WeaponType.POLE))
|
||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
*/
|
*/
|
||||||
package ai.others;
|
package ai.others;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
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.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
|
import org.l2jmobius.gameserver.instancemanager.CastleManager;
|
||||||
import org.l2jmobius.gameserver.model.World;
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.WorldObject;
|
import org.l2jmobius.gameserver.model.WorldObject;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
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
|
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
|
//@formatter:on
|
||||||
private static final Collection<Npc> SPAWNED_GUARDS = ConcurrentHashMap.newKeySet();
|
private static final Map<Integer, List<Npc>> RESIDENCE_GUARD_MAP = new HashMap<>();
|
||||||
|
|
||||||
public SiegeGuards()
|
public SiegeGuards()
|
||||||
{
|
{
|
||||||
@ -77,46 +81,75 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
addKillId(MERCENARIES);
|
addKillId(MERCENARIES);
|
||||||
addKillId(STATIONARY_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
|
private class AggroCheckTask implements Runnable
|
||||||
public String onAdvEvent(String event, Npc npc, PlayerInstance player)
|
|
||||||
{
|
{
|
||||||
for (Npc guard : SPAWNED_GUARDS)
|
private final int _residenceId;
|
||||||
|
|
||||||
|
public AggroCheckTask(int residenceId)
|
||||||
{
|
{
|
||||||
if (guard != null)
|
_residenceId = residenceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
final List<Npc> guards = RESIDENCE_GUARD_MAP.get(_residenceId);
|
||||||
|
for (Npc guard : guards)
|
||||||
{
|
{
|
||||||
|
if (guard == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (guard.isDead())
|
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();
|
for (Creature nearby : World.getInstance().getVisibleObjectsInRange(guard, Creature.class, guard.getAggroRange()))
|
||||||
if (!guard.isInCombat() || (target == null) || (guard.calculateDistance2D(target) > guard.getAggroRange()) || target.isInvul())
|
|
||||||
{
|
{
|
||||||
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;
|
// skip invisible players
|
||||||
final PlayerInstance pl = summon == null ? (PlayerInstance) nearby : summon.getOwner();
|
if (pl.isInvisible() || pl.isInvul())
|
||||||
if (((pl.getSiegeState() != 2) || pl.isRegisteredOnThisSiegeField(guard.getScriptValue())) && ((pl.getSiegeState() != 0) || (guard.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE)))
|
|
||||||
{
|
{
|
||||||
if (!pl.isInvisible() && !pl.isInvul()) // skip invisible players
|
continue;
|
||||||
{
|
|
||||||
addAttackPlayerDesire(guard, pl);
|
|
||||||
break; // no need to search more
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
@ -133,7 +166,7 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
@Override
|
@Override
|
||||||
public String onKill(Npc npc, PlayerInstance killer, boolean isSummon)
|
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);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,10 +178,20 @@ public class SiegeGuards extends AbstractNpcAI
|
|||||||
{
|
{
|
||||||
npc.setImmobilized(true);
|
npc.setImmobilized(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Castle castle = npc.getCastle();
|
final Castle castle = npc.getCastle();
|
||||||
final Fort fortress = npc.getFort();
|
final Fort fortress = npc.getFort();
|
||||||
npc.setScriptValue(fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0));
|
final int residenceId = fortress != null ? fortress.getResidenceId() : (castle != null ? castle.getResidenceId() : 0);
|
||||||
SPAWNED_GUARDS.add(npc);
|
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);
|
return super.onSpawn(npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user