Skip to content
Snippets Groups Projects
Commit 0c769caf authored by Zealar's avatar Zealar
Browse files

BETA: Few AI fixes:

Dorian, Rooney AI
 * Timer checkArea replaced by onSeeCreature listener
Isle of Prayer AI
 * Fixed drop chance (getRandom(1000) -> getRandom(10000))
 * Slightly updated code ;)
Tar Beetle AI
 * Added support for reloading script
 * Reworked spawn system
 
   Patch by: malyelfik
   Reviewed by: UnAfraid, Zealar
parent 21acfea4
No related branches found
No related tags found
No related merge requests found
......@@ -18,10 +18,14 @@
*/
package ai.group_template;
import java.util.HashMap;
import java.util.Map;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.ItemChanceHolder;
/**
* Isle of Prayer AI.
......@@ -35,122 +39,43 @@ public final class IsleOfPrayer extends AbstractNpcAI
private static final int BLUE_SEED_OF_EVIL_SHARD = 9595;
private static final int RED_SEED_OF_EVIL_SHARD = 9596;
// Monsters
private static final int ISLAND_GUARDIAN = 22257;
private static final int WHITE_SAND_MIRAGE = 22258;
private static final int MUDDY_CORAL = 22259;
private static final int KLEOPORA = 22260;
private static final int SEYCHELLES = 22261;
private static final int NAIAD = 22262;
private static final int SONNERATIA = 22263;
private static final int CASTALIA = 22264;
private static final int CHRYSOCOLLA = 22265;
private static final int PYTHIA = 22266;
private static final int DARK_WATER_DRAGON = 22267;
private static final int SHADE1 = 22268;
private static final int SHADE2 = 22269;
private static final int WATER_DRAGON_DETRACTOR1 = 22270;
private static final int WATER_DRAGON_DETRACTOR2 = 22271;
private static final Map<Integer, ItemChanceHolder> MONSTERS = new HashMap<>();
static
{
MONSTERS.put(22257, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2087)); // Island Guardian
MONSTERS.put(22258, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2147)); // White Sand Mirage
MONSTERS.put(22259, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2642)); // Muddy Coral
MONSTERS.put(22260, new ItemChanceHolder(YELLOW_SEED_OF_EVIL_SHARD, 2292)); // Kleopora
MONSTERS.put(22261, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1171)); // Seychelles
MONSTERS.put(22262, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1173)); // Naiad
MONSTERS.put(22263, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1403)); // Sonneratia
MONSTERS.put(22264, new ItemChanceHolder(GREEN_SEED_OF_EVIL_SHARD, 1207)); // Castalia
MONSTERS.put(22265, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 575)); // Chrysocolla
MONSTERS.put(22266, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 493)); // Pythia
MONSTERS.put(22267, new ItemChanceHolder(RED_SEED_OF_EVIL_SHARD, 770)); // Dark Water Dragon
MONSTERS.put(22268, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 987)); // Shade
MONSTERS.put(22269, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 995)); // Shade
MONSTERS.put(22270, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 1008)); // Water Dragon Detractor
MONSTERS.put(22271, new ItemChanceHolder(BLUE_SEED_OF_EVIL_SHARD, 1008)); // Water Dragon Detractor
}
private IsleOfPrayer()
{
super(IsleOfPrayer.class.getSimpleName(), "ai/group_template");
addKillId(ISLAND_GUARDIAN, WHITE_SAND_MIRAGE, MUDDY_CORAL, KLEOPORA, SEYCHELLES, NAIAD, SONNERATIA, CASTALIA, CHRYSOCOLLA, PYTHIA, DARK_WATER_DRAGON, SHADE1, SHADE2, WATER_DRAGON_DETRACTOR1, WATER_DRAGON_DETRACTOR2);
addKillId(MONSTERS.keySet());
}
@Override
public String onKill(L2Npc npc, L2PcInstance killer, boolean isSummon)
{
switch (npc.getId())
final ItemChanceHolder holder = MONSTERS.get(npc.getId());
if (getRandom(10000) <= holder.getChance())
{
case ISLAND_GUARDIAN:
{
doDrop(killer, npc, YELLOW_SEED_OF_EVIL_SHARD, 2087);
break;
}
case WHITE_SAND_MIRAGE:
{
doDrop(killer, npc, YELLOW_SEED_OF_EVIL_SHARD, 2147);
break;
}
case MUDDY_CORAL:
{
doDrop(killer, npc, YELLOW_SEED_OF_EVIL_SHARD, 2642);
break;
}
case KLEOPORA:
{
doDrop(killer, npc, YELLOW_SEED_OF_EVIL_SHARD, 2292);
break;
}
case SEYCHELLES:
{
doDrop(killer, npc, GREEN_SEED_OF_EVIL_SHARD, 1171);
break;
}
case NAIAD:
{
doDrop(killer, npc, GREEN_SEED_OF_EVIL_SHARD, 1173);
break;
}
case SONNERATIA:
{
doDrop(killer, npc, GREEN_SEED_OF_EVIL_SHARD, 1403);
break;
}
case CASTALIA:
{
doDrop(killer, npc, GREEN_SEED_OF_EVIL_SHARD, 1207);
break;
}
case CHRYSOCOLLA:
{
doDrop(killer, npc, RED_SEED_OF_EVIL_SHARD, 575);
break;
}
case PYTHIA:
{
doDrop(killer, npc, RED_SEED_OF_EVIL_SHARD, 493);
break;
}
case DARK_WATER_DRAGON:
{
doDrop(killer, npc, RED_SEED_OF_EVIL_SHARD, 770);
break;
}
case SHADE1:
{
doDrop(killer, npc, BLUE_SEED_OF_EVIL_SHARD, 987);
break;
}
case SHADE2:
{
doDrop(killer, npc, BLUE_SEED_OF_EVIL_SHARD, 995);
break;
}
case WATER_DRAGON_DETRACTOR1:
case WATER_DRAGON_DETRACTOR2:
{
doDrop(killer, npc, BLUE_SEED_OF_EVIL_SHARD, 1008);
break;
}
npc.dropItem(killer, holder);
}
return super.onKill(npc, killer, isSummon);
}
/**
* @param killer the player that kills the NPC
* @param npc the killed NPC that will drop
* @param itemId the item Id to drop
* @param chance the chance of this NPC to drop the item
*/
private static final void doDrop(L2PcInstance killer, L2Npc npc, int itemId, int chance)
{
if (getRandom(1000) <= chance)
{
npc.dropItem(killer, itemId, 1);
}
}
public static void main(String[] args)
{
new IsleOfPrayer();
......
......@@ -21,8 +21,7 @@ package ai.npc.Dorian;
import quests.Q00024_InhabitantsOfTheForestOfTheDead.Q00024_InhabitantsOfTheForestOfTheDead;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.datatables.SpawnTable;
import com.l2jserver.gameserver.model.L2Spawn;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.quest.QuestState;
......@@ -44,46 +43,25 @@ public final class Dorian extends AbstractNpcAI
private Dorian()
{
super(Dorian.class.getSimpleName(), "ai/npc");
addSpawnId(DORIAN);
for (L2Spawn spawn : SpawnTable.getInstance().getSpawns(DORIAN))
{
startQuestTimer("checkArea", 3000, spawn.getLastSpawn(), null, true);
}
addSeeCreatureId(DORIAN);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (event.equals("checkArea"))
if (creature.isPlayer())
{
if (npc.isDecayed())
{
cancelQuestTimers("checkArea");
}
else
final L2PcInstance pl = creature.getActingPlayer();
final QuestState qs = pl.getQuestState(Q00024_InhabitantsOfTheForestOfTheDead.class.getSimpleName());
if ((qs != null) && qs.isCond(3))
{
for (L2PcInstance pl : npc.getKnownList().getKnownPlayersInRadius(300))
{
final QuestState qs = pl.getQuestState(Q00024_InhabitantsOfTheForestOfTheDead.class.getSimpleName());
if ((qs != null) && qs.isCond(3))
{
qs.takeItems(SILVER_CROSS, -1);
qs.giveItems(BROKEN_SILVER_CROSS, 1);
qs.setCond(4, true);
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.THAT_SIGN);
}
}
takeItems(pl, SILVER_CROSS, -1);
giveItems(pl, BROKEN_SILVER_CROSS, 1);
qs.setCond(4, true);
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.THAT_SIGN);
}
}
return null;
}
@Override
public String onSpawn(L2Npc npc)
{
startQuestTimer("checkArea", 3000, npc, null, true);
return null;
return super.onSeeCreature(npc, creature, isSummon);
}
public static void main(String[] args)
......
......@@ -21,6 +21,7 @@ package ai.npc.ForgeOfTheGods;
import ai.npc.AbstractNpcAI;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.NpcStringId;
......@@ -81,47 +82,53 @@ public final class Rooney extends AbstractNpcAI
private Rooney()
{
super(Rooney.class.getSimpleName(), "ai/npc");
final L2Npc npc = addSpawn(ROONEY, LOCATIONS[getRandom(LOCATIONS.length)], false, 0);
startQuestTimer("checkArea", 1000, npc, null, true);
addSeeCreatureId(ROONEY);
addSpawn(ROONEY, LOCATIONS[getRandom(LOCATIONS.length)], false, 0);
}
@Override
public String onAdvEvent(String event, L2Npc npc, L2PcInstance player)
{
switch (event)
if (event.equals("teleport") && !npc.isDecayed())
{
case "checkArea":
if (!npc.getKnownList().getKnownPlayersInRadius(300).isEmpty())
{
cancelQuestTimers("checkArea");
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.WELCOME);
startQuestTimer("say1", 60000, npc, null);
}
break;
case "say1":
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HURRY_HURRY);
startQuestTimer("say2", 60000, npc, null);
break;
case "say2":
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_NOT_THAT_TYPE_OF_PERSON_WHO_STAYS_IN_ONE_PLACE_FOR_A_LONG_TIME);
startQuestTimer("say3", 60000, npc, null);
break;
case "say3":
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.ITS_HARD_FOR_ME_TO_KEEP_STANDING_LIKE_THIS);
startQuestTimer("say4", 60000, npc, null);
break;
case "say4":
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.WHY_DONT_I_GO_THAT_WAY_THIS_TIME);
startQuestTimer("teleport", 60000, npc, null);
break;
case "teleport":
npc.teleToLocation(LOCATIONS[getRandom(LOCATIONS.length)], false);
startQuestTimer("checkArea", 1000, npc, null, true);
break;
final int aiVal = npc.getScriptValue();
switch (aiVal)
{
case 1:
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.HURRY_HURRY);
break;
case 2:
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.I_AM_NOT_THAT_TYPE_OF_PERSON_WHO_STAYS_IN_ONE_PLACE_FOR_A_LONG_TIME);
break;
case 3:
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.ITS_HARD_FOR_ME_TO_KEEP_STANDING_LIKE_THIS);
break;
case 4:
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.WHY_DONT_I_GO_THAT_WAY_THIS_TIME);
break;
default:
npc.teleToLocation(LOCATIONS[getRandom(LOCATIONS.length)], false);
npc.setScriptValue(0);
return null;
}
npc.setScriptValue(aiVal + 1);
startQuestTimer("teleport", 60000, npc, null);
}
return null;
}
@Override
public String onSeeCreature(L2Npc npc, L2Character creature, boolean isSummon)
{
if (creature.isPlayer() && npc.isScriptValue(0))
{
broadcastNpcSay(npc, Say2.NPC_ALL, NpcStringId.WELCOME);
startQuestTimer("teleport", 60000, npc, null);
npc.setScriptValue(1);
}
return super.onSeeCreature(npc, creature, isSummon);
}
public static void main(String[] args)
{
new Rooney();
......
......@@ -50,25 +50,23 @@ public final class TarBeetle extends AbstractNpcAI
super(TarBeetle.class.getSimpleName(), "ai/npc");
addAggroRangeEnterId(TAR_BEETLE);
addSpellFinishedId(TAR_BEETLE);
spawn.startTasks();
}
@Override
public String onAggroRangeEnter(L2Npc npc, L2PcInstance player, boolean isSummon)
{
if ((spawn.getBeetle(npc).getScriptValue() > 0) && canCastSkill(npc))
if (npc.getScriptValue() > 0)
{
int level = 0;
final BuffInfo info = player.getEffectList().getBuffInfoBySkillId(TAR_SPITE);
if (info != null)
{
level = info.getSkill().getAbnormalLvl();
}
final int level = (info != null) ? info.getSkill().getAbnormalLvl() : 0;
if (level < 3)
{
npc.setTarget(player);
npc.doCast(SKILLS[level].getSkill());
final Skill skill = SKILLS[level].getSkill();
if (!npc.isSkillDisabled(skill))
{
npc.setTarget(player);
npc.doCast(skill);
}
}
}
return super.onAggroRangeEnter(npc, player, isSummon);
......@@ -79,29 +77,24 @@ public final class TarBeetle extends AbstractNpcAI
{
if ((skill != null) && (skill.getId() == TAR_SPITE))
{
int val = spawn.getBeetle(npc).getScriptValue() - 1;
final int val = npc.getScriptValue() - 1;
if ((val <= 0) || (SKILLS[0].getSkill().getMpConsume() > npc.getCurrentMp()))
{
spawn.removeBeetle(npc);
}
else
{
spawn.getBeetle(npc).isScriptValue(val);
npc.setScriptValue(val);
}
}
return super.onSpellFinished(npc, player, skill);
}
private boolean canCastSkill(L2Npc npc)
@Override
public boolean unload()
{
for (SkillHolder holder : SKILLS)
{
if (npc.isSkillDisabled(holder.getSkill()))
{
return false;
}
}
return true;
spawn.unload();
return super.unload();
}
public static void main(String[] args)
......
......@@ -19,13 +19,10 @@
package ai.npc.ForgeOfTheGods;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import javolution.util.FastMap;
import javolution.util.FastList;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
......@@ -45,14 +42,9 @@ import com.l2jserver.util.Rnd;
*/
public class TarBeetleSpawn extends DocumentParser
{
private static final Map<Integer, SpawnZone> _spawnZoneList = new HashMap<>();
private static final Map<Integer, L2Npc> _spawnList = new FastMap<>();
public static List<Integer> lowerZones = new ArrayList<>();
public static List<Integer> upperZones = new ArrayList<>();
public static int lowerNpcCount = 0;
public static int upperNpcCount = 0;
private final List<SpawnZone> zones = new ArrayList<>();
private ScheduledFuture<?> spawnTask;
private ScheduledFuture<?> shotTask;
public TarBeetleSpawn()
{
......@@ -62,139 +54,101 @@ public class TarBeetleSpawn extends DocumentParser
@Override
public void load()
{
_spawnZoneList.clear();
_spawnList.clear();
parseDatapackFile("data/spawnZones/tar_beetle.xml");
_log.info(TarBeetleSpawn.class.getSimpleName() + ": Loaded " + _spawnZoneList.size() + " spawn zones.");
if (!zones.isEmpty())
{
spawnTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> zones.forEach(SpawnZone::refreshSpawn), 1000, 60000);
shotTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> zones.forEach(SpawnZone::refreshShots), 300000, 300000);
}
}
@Override
protected void parseDocument()
{
final Node n = getCurrentDocument().getFirstChild();
for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
int i = 0;
for (Node d = getCurrentDocument().getFirstChild(); d != null; d = d.getNextSibling())
{
if (d.getNodeName().equals("spawnZones"))
if (d.getNodeName().equals("list"))
{
for (Node r = d.getFirstChild(); r != null; r = r.getNextSibling())
{
if (r.getNodeName().equals("zone"))
if (r.getNodeName().equals("spawnZone"))
{
NamedNodeMap attrs = r.getAttributes();
int id = parseInteger(attrs, "id");
int minZ = parseInteger(attrs, "minZ");
int maxZ = parseInteger(attrs, "maxZ");
String type = parseString(attrs, "type");
if (type.equals("upper"))
{
upperZones.add(id);
}
else if (type.equals("lower"))
{
lowerZones.add(id);
}
int[] bZones = null;
String bZonesStr = parseString(attrs, "bZones", "");
if (!bZonesStr.isEmpty())
final int npcCount = parseInteger(attrs, "maxNpcCount");
final SpawnZone sp = new SpawnZone(npcCount, i);
for (Node b = r.getFirstChild(); b != null; b = b.getNextSibling())
{
String[] str = bZonesStr.split(";");
bZones = new int[str.length];
for (int i = 0; i < str.length; i++)
if (b.getNodeName().equals("zone"))
{
bZones[i] = Integer.parseInt(str[i]);
attrs = b.getAttributes();
final int minZ = parseInteger(attrs, "minZ");
final int maxZ = parseInteger(attrs, "maxZ");
final Zone zone = new Zone();
for (Node c = b.getFirstChild(); c != null; c = c.getNextSibling())
{
attrs = c.getAttributes();
if (c.getNodeName().equals("point"))
{
final int x = parseInteger(attrs, "x");
final int y = parseInteger(attrs, "y");
zone.add(x, y, minZ, maxZ, 0);
}
else if (c.getNodeName().equals("bannedZone"))
{
final Zone bannedZone = new Zone();
final int bMinZ = parseInteger(attrs, "minZ");
final int bMaxZ = parseInteger(attrs, "maxZ");
for (Node f = c.getFirstChild(); f != null; f = f.getNextSibling())
{
if (f.getNodeName().equals("point"))
{
attrs = f.getAttributes();
int x = parseInteger(attrs, "x");
int y = parseInteger(attrs, "y");
bannedZone.add(x, y, bMinZ, bMaxZ, 0);
}
}
zone.addBannedZone(bannedZone);
}
}
sp.addZone(zone);
}
}
SpawnZone zone = new SpawnZone(id, bZones);
for (Node c = r.getFirstChild(); c != null; c = c.getNextSibling())
{
if (c.getNodeName().equals("point"))
{
attrs = c.getAttributes();
int x = parseInteger(attrs, "x");
int y = parseInteger(attrs, "y");
zone.add(x, y, minZ, maxZ, 0);
}
}
_spawnZoneList.put(id, zone);
zones.add(i++, sp);
}
}
}
}
}
public void removeBeetle(L2Npc npc)
public final void unload()
{
npc.deleteMe();
_spawnList.remove(npc.getObjectId());
if (npc.getSpawn().getZ() < -5000)
if (spawnTask != null)
{
lowerNpcCount--;
spawnTask.cancel(false);
}
else
if (shotTask != null)
{
upperNpcCount--;
shotTask.cancel(false);
}
zones.forEach(SpawnZone::unload);
zones.clear();
}
public void spawn(List<Integer> zone)
{
try
{
Collections.shuffle(zone);
int[] loc = getSpawnZoneById(zone.get(0)).getRandomPoint();
final L2Spawn spawn = new L2Spawn(NpcData.getInstance().getTemplate(18804));
spawn.setHeading(Rnd.get(65535));
spawn.setX(loc[0]);
spawn.setY(loc[1]);
spawn.setZ(GeoData.getInstance().getSpawnHeight(loc[0], loc[1], loc[2], loc[3]));
final L2Npc npc = spawn.doSpawn();
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
npc.setIsInvul(true);
npc.disableCoreAI(true);
npc.setScriptValue(5);
_spawnList.put(npc.getObjectId(), npc);
}
catch (Exception e)
{
_log.warning(TarBeetleSpawn.class.getSimpleName() + ": Could not spawn npc! Error: " + e.getMessage());
}
}
public void startTasks()
{
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new SpawnTask(), 1000, 60000);
ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(new NumShotTask(), 300000, 300000);
}
public SpawnZone getSpawnZoneById(int id)
{
return _spawnZoneList.get(id);
}
public L2Npc getBeetle(L2Npc npc)
{
return _spawnList.get(npc.getObjectId());
}
public static Map<Integer, L2Npc> getSpawnList()
public final void removeBeetle(L2Npc npc)
{
return _spawnList;
zones.get(npc.getVariables().getInt("zoneIndex", 0)).removeSpawn(npc);
npc.deleteMe();
}
private class SpawnZone extends L2Territory
private final class Zone extends L2Territory
{
private final int[] _bZones;
private List<Zone> _bannedZones;
public SpawnZone(int terr, int[] bZones)
public Zone()
{
super(terr);
_bZones = bZones;
super(1);
}
@Override
......@@ -208,13 +162,22 @@ public class TarBeetleSpawn extends DocumentParser
return loc;
}
private boolean isInsideBannedZone(int[] loc)
public final void addBannedZone(Zone bZone)
{
if (_bannedZones == null)
{
_bannedZones = new ArrayList<>();
}
_bannedZones.add(bZone);
}
private final boolean isInsideBannedZone(int[] loc)
{
if (_bZones != null)
if (_bannedZones != null)
{
for (int i : _bZones)
for (Zone z : _bannedZones)
{
if (getSpawnZoneById(i).isInside(loc[0], loc[1]))
if (z.isInside(loc[0], loc[1]))
{
return true;
}
......@@ -224,52 +187,82 @@ public class TarBeetleSpawn extends DocumentParser
}
}
public class SpawnTask implements Runnable
private final class SpawnZone
{
@Override
public void run()
private final List<Zone> _zones = new ArrayList<>();
private final List<L2Npc> _spawn = new FastList<>();
private final int _maxNpcCount;
private final int _index;
public SpawnZone(int maxNpcCount, int index)
{
while (lowerNpcCount < 4)
_maxNpcCount = maxNpcCount;
_index = index;
}
public final void addZone(Zone zone)
{
_zones.add(zone);
}
public final void removeSpawn(L2Npc obj)
{
_spawn.remove(obj);
}
public final void unload()
{
_spawn.forEach(L2Npc::deleteMe);
_spawn.clear();
_zones.clear();
}
public final void refreshSpawn()
{
try
{
spawn(lowerZones);
lowerNpcCount++;
while (_spawn.size() < _maxNpcCount)
{
final int[] loc = _zones.get(Rnd.get(_zones.size())).getRandomPoint();
final L2Spawn spawn = new L2Spawn(NpcData.getInstance().getTemplate(18804));
spawn.setHeading(Rnd.get(65535));
spawn.setX(loc[0]);
spawn.setY(loc[1]);
spawn.setZ(GeoData.getInstance().getSpawnHeight(loc[0], loc[1], loc[2], loc[3]));
final L2Npc npc = spawn.doSpawn();
npc.setIsNoRndWalk(true);
npc.setIsImmobilized(true);
npc.setIsInvul(true);
npc.disableCoreAI(true);
npc.setScriptValue(5);
npc.getVariables().set("zoneIndex", _index);
_spawn.add(npc);
}
}
while (upperNpcCount < 12)
catch (Exception e)
{
spawn(upperZones);
upperNpcCount++;
e.printStackTrace();
}
}
}
public class NumShotTask implements Runnable
{
@Override
public void run()
public final void refreshShots()
{
Iterator<L2Npc> iterator = getSpawnList().values().iterator();
while (iterator.hasNext())
if (_spawn.size() > 0)
{
L2Npc npc = iterator.next();
int val = npc.getScriptValue();
if (val == 5)
for (L2Npc npc : _spawn)
{
npc.deleteMe();
iterator.remove();
if (npc.getSpawn().getZ() < -5000)
final int val = npc.getScriptValue();
if (val == 5)
{
lowerNpcCount--;
npc.deleteMe();
_spawn.remove(npc);
}
else
{
upperNpcCount--;
npc.setScriptValue(val + 1);
}
}
else
{
npc.setScriptValue(val + 1);
}
}
}
}
......
This diff is collapsed.
......@@ -2,36 +2,40 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="list">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="spawnZones" minOccurs="1" maxOccurs="1">
<xs:sequence>
<xs:element name="spawnZone" maxOccurs="2">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="zone" minOccurs="1" maxOccurs="unbounded">
<xs:sequence>
<xs:element name="zone" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="point" maxOccurs="unbounded" minOccurs="1">
<xs:sequence>
<xs:element name="point" maxOccurs="unbounded" >
<xs:complexType>
<xs:attribute name="x" type="xs:integer" use="required" />
<xs:attribute name="y" type="xs:integer" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="bannedZone" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="x" type="xs:integer" use="required" />
<xs:attribute name="y" type="xs:integer" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="maxZ" type="xs:integer" use="required" />
<xs:attribute name="minZ" type="xs:integer" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:nonNegativeInteger" use="required" />
<xs:attribute name="maxZ" type="xs:integer" use="required" />
<xs:attribute name="minZ" type="xs:integer" use="required" />
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="upper" />
<xs:enumeration value="lower" />
<xs:enumeration value="bZone" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="bZones" type="xs:normalizedString" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="maxNpcCount" type="xs:integer" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment