/* * Copyright (C) 2004-2015 L2J DataPack * * This file is part of L2J DataPack. * * L2J DataPack is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * L2J DataPack is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package ai.npc.ForgeOfTheGods; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledFuture; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import com.l2jserver.gameserver.GeoData; import com.l2jserver.gameserver.ThreadPoolManager; import com.l2jserver.gameserver.model.L2Spawn; import com.l2jserver.gameserver.model.L2Territory; import com.l2jserver.gameserver.model.Location; import com.l2jserver.gameserver.model.actor.L2Npc; import com.l2jserver.util.Rnd; import com.l2jserver.util.data.xml.IXmlReader; /** * Tar Beetle zone spawn * @author malyelfik */ public class TarBeetleSpawn implements IXmlReader { private final List zones = new ArrayList<>(); private ScheduledFuture spawnTask; private ScheduledFuture shotTask; public TarBeetleSpawn() { load(); } @Override public void load() { parseDatapackFile("data/spawnZones/tar_beetle.xml"); if (!zones.isEmpty()) { spawnTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> zones.forEach(SpawnZone::refreshSpawn), 1000, 60000); shotTask = ThreadPoolManager.getInstance().scheduleGeneralAtFixedRate(() -> zones.forEach(SpawnZone::refreshShots), 300000, 300000); } } @Override public void parseDocument(Document doc) { int i = 0; for (Node d = doc.getFirstChild(); d != null; d = d.getNextSibling()) { if (d.getNodeName().equals("list")) { for (Node r = d.getFirstChild(); r != null; r = r.getNextSibling()) { if (r.getNodeName().equals("spawnZone")) { NamedNodeMap attrs = r.getAttributes(); final int npcCount = parseInteger(attrs, "maxNpcCount"); final SpawnZone sp = new SpawnZone(npcCount, i); for (Node b = r.getFirstChild(); b != null; b = b.getNextSibling()) { if (b.getNodeName().equals("zone")) { 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); } } zones.add(i++, sp); } } } } } public final void unload() { if (spawnTask != null) { spawnTask.cancel(false); } if (shotTask != null) { shotTask.cancel(false); } zones.forEach(SpawnZone::unload); zones.clear(); } public final void removeBeetle(L2Npc npc) { zones.get(npc.getVariables().getInt("zoneIndex", 0)).removeSpawn(npc); npc.deleteMe(); } private final class Zone extends L2Territory { private List _bannedZones; public Zone() { super(1); } @Override public Location getRandomPoint() { Location location = super.getRandomPoint(); while ((location != null) && isInsideBannedZone(location)) { location = super.getRandomPoint(); } return location; } public final void addBannedZone(Zone bZone) { if (_bannedZones == null) { _bannedZones = new ArrayList<>(); } _bannedZones.add(bZone); } private final boolean isInsideBannedZone(Location location) { if (_bannedZones != null) { for (Zone z : _bannedZones) { if (z.isInside(location.getX(), location.getY())) { return true; } } } return false; } } private final class SpawnZone { private final List _zones = new ArrayList<>(); private final List _spawn = new CopyOnWriteArrayList<>(); private final int _maxNpcCount; private final int _index; public SpawnZone(int maxNpcCount, int index) { _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 { while (_spawn.size() < _maxNpcCount) { final Location location = _zones.get(Rnd.get(_zones.size())).getRandomPoint(); if (location != null) { final L2Spawn spawn = new L2Spawn(18804); spawn.setHeading(Rnd.get(65535)); spawn.setX(location.getX()); spawn.setY(location.getY()); spawn.setZ(GeoData.getInstance().getSpawnHeight(location)); 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); } } } catch (Exception e) { LOGGER.warn("{}: Could not refresh spawns!", getClass().getSimpleName(), e); } } public final void refreshShots() { if (_spawn.size() > 0) { for (L2Npc npc : _spawn) { final int val = npc.getScriptValue(); if (val == 5) { npc.deleteMe(); _spawn.remove(npc); } else { npc.setScriptValue(val + 1); } } } } } }