diff --git a/src/main/java/com/l2jserver/datapack/custom/service/base/model/entity/CustomServiceProduct.java b/src/main/java/com/l2jserver/datapack/custom/service/base/model/entity/CustomServiceProduct.java index ff2aacf97afa21c4ffcbc6343b306479bd66a639..b09f476206028d4dcc4aebe6ede6403974ae35b0 100644 --- a/src/main/java/com/l2jserver/datapack/custom/service/base/model/entity/CustomServiceProduct.java +++ b/src/main/java/com/l2jserver/datapack/custom/service/base/model/entity/CustomServiceProduct.java @@ -40,6 +40,7 @@ public abstract class CustomServiceProduct extends Refable { if (!items.isEmpty()) { HTMLTemplatePlaceholder itemsPlaceholder = getPlaceholder().addChild("items", null).getChild("items"); for (ItemRequirement item : items) { + item.afterDeserialize(); itemsPlaceholder.addAliasChild(String.valueOf(itemsPlaceholder.getChildrenSize()), item.getPlaceholder()); } } diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterService.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterService.java new file mode 100644 index 0000000000000000000000000000000000000000..221eea3ef09061102e249676c15715a1d118eac5 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterService.java @@ -0,0 +1,557 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.l2jserver.datapack.custom.service.base.CustomServiceScript; +import com.l2jserver.datapack.custom.service.base.util.CommandProcessor; +import com.l2jserver.datapack.custom.service.base.util.htmltmpls.HTMLTemplatePlaceholder; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.AbstractTeleporter; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.GroupTeleport; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.GroupTeleportCategory; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.SoloTeleport; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.SoloTeleportCategory; +import com.l2jserver.gameserver.config.Configuration; +import com.l2jserver.gameserver.handler.BypassHandler; +import com.l2jserver.gameserver.handler.ItemHandler; +import com.l2jserver.gameserver.handler.VoicedCommandHandler; +import com.l2jserver.gameserver.instancemanager.InstanceManager; +import com.l2jserver.gameserver.model.AbstractPlayerGroup; +import com.l2jserver.gameserver.model.L2CommandChannel; +import com.l2jserver.gameserver.model.L2Party; +import com.l2jserver.gameserver.model.actor.L2Npc; +import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; +import com.l2jserver.gameserver.model.entity.TvTEvent; +import com.l2jserver.gameserver.model.instancezone.InstanceWorld; +import com.l2jserver.gameserver.network.SystemMessageId; +import com.l2jserver.gameserver.network.serverpackets.SystemMessage; +import com.l2jserver.gameserver.taskmanager.AttackStanceTaskManager; + +/** + * Teleporter service. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public final class TeleporterService extends CustomServiceScript { + private static final Logger LOG = LoggerFactory.getLogger(TeleporterService.class.getName()); + + public static final String SCRIPT_NAME = "teleporter"; + public static final Path SCRIPT_PATH = Paths.get(SCRIPT_COLLECTION, SCRIPT_NAME); + + private static TeleporterConfig config; + private static TeleporterService script; + + public static TeleporterConfig getConfig() { + return config; + } + + public static TeleporterService getService() { + return script; + } + + public static void main(String[] args) { + if (!Configuration.teleporterService().enable()) { + LOG.info("Disabled."); + return; + } + + LOG.info("Loading..."); + try { + config = new TeleporterConfig(); + script = new TeleporterService(); + } catch (Exception e) { + LOG.error("Failed to load!", e); + return; + } + + getConfig().registerNpcs(script); + } + + public TeleporterService() { + super(SCRIPT_NAME); + + BypassHandler.getInstance().registerHandler(TeleporterServiceBypassHandler.getInstance()); + + if (Configuration.teleporterService().getVoicedEnable()) { + VoicedCommandHandler.getInstance().registerHandler(TeleporterServiceVoicedCommandHandler.getInstance()); + ItemHandler.getInstance().registerHandler(TeleporterServiceItemHandler.getInstance()); + } + } + + @Override + public boolean unload() { + BypassHandler.getInstance().removeHandler(TeleporterServiceBypassHandler.getInstance()); + if (Configuration.teleporterService().getVoicedEnable()) { + VoicedCommandHandler.getInstance().removeHandler(TeleporterServiceVoicedCommandHandler.getInstance()); + ItemHandler.getInstance().removeHandler(TeleporterServiceItemHandler.getInstance()); + } + return super.unload(); + } + + // //////////////////////////////////// + // UTILITY METHODS + // //////////////////////////////////// + private void _showAdvancedHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String htmlPath, Map<String, HTMLTemplatePlaceholder> placeholders) { + showAdvancedHtml(player, teleporter, npc, htmlPath, placeholders); + } + + private void _showTeleportHtml(L2PcInstance player, AbstractTeleporter teleporter, SoloTeleport teleport, L2Npc npc, String htmlPath) { + Map<String, HTMLTemplatePlaceholder> placeholders = new HashMap<>(); + placeholders.put("teleport", teleport.getPlaceholder()); + + _showAdvancedHtml(player, teleporter, npc, htmlPath, placeholders); + } + + private boolean _takeTeleportItems(SoloTeleport teleport, L2PcInstance initiator) { + if (!teleport.getItems().isEmpty()) { + HashMap<Integer, Long> items = new HashMap<>(); + fillItemAmountMap(items, teleport); + + for (Entry<Integer, Long> item : items.entrySet()) { + if (initiator.getInventory().getInventoryItemCount(item.getKey(), 0, true) < item.getValue()) { + initiator.sendMessage("Not enough items!"); + return false; + } + } + + for (Entry<Integer, Long> item : items.entrySet()) { + initiator.destroyItemByItemId("TeleporterService", item.getKey(), item.getValue(), initiator, true); + } + } + + return true; + } + + private InstanceWorld _createInstance(String instanceDefinition) { + int instanceId = InstanceManager.getInstance().createDynamicInstance(instanceDefinition); + InstanceWorld world = new InstanceWorld(); + world.setInstanceId(instanceId); + // TODO: world.setTemplateId(???); + InstanceManager.getInstance().addWorld(world); + return world; + } + + // //////////////////////////////////// + // HTML COMMANDS + // //////////////////////////////////// + private boolean _showMainHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc) { + _showAdvancedHtml(player, teleporter, npc, "main.html", new HashMap<String, HTMLTemplatePlaceholder>()); + return true; + } + + private boolean _showSoloCategoryList(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc) { + _showAdvancedHtml(player, teleporter, npc, "solo_category_list.html", new HashMap<String, HTMLTemplatePlaceholder>()); + return true; + } + + private boolean _showPartyCategoryList(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc) { + _showAdvancedHtml(player, teleporter, npc, "p_category_list.html", new HashMap<String, HTMLTemplatePlaceholder>()); + return true; + } + + private boolean _showCommandChannelCategoryList(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc) { + _showAdvancedHtml(player, teleporter, npc, "cc_category_list.html", new HashMap<String, HTMLTemplatePlaceholder>()); + return true; + } + + private boolean _showSoloListHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String soloListIdent) { + Map<String, HTMLTemplatePlaceholder> placeholders = new HashMap<>(); + + if (soloListIdent != null && !soloListIdent.isEmpty()) { + SoloTeleportCategory category = teleporter.getSoloTeleportCategories().get(soloListIdent); + placeholders.put("category", category.getPlaceholder()); + } + + _showAdvancedHtml(player, teleporter, npc, "solo_teleport_list.html", placeholders); + return true; + } + + private boolean _showPartyListHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String partyListIdent) { + Map<String, HTMLTemplatePlaceholder> placeholders = new HashMap<>(); + + if (partyListIdent != null && !partyListIdent.isEmpty()) { + GroupTeleportCategory category = teleporter.getPartyTeleportCategories().get(partyListIdent); + placeholders.put("category", category.getPlaceholder()); + } + + _showAdvancedHtml(player, teleporter, npc, "p_teleport_list.html", placeholders); + return true; + } + + private boolean _showCommandChannelListHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String commandChannelListIdent) { + Map<String, HTMLTemplatePlaceholder> placeholders = new HashMap<>(); + + if (commandChannelListIdent != null && !commandChannelListIdent.isEmpty()) { + GroupTeleportCategory category = teleporter.getCommandChannelTeleportCategories().get(commandChannelListIdent); + placeholders.put("category", category.getPlaceholder()); + } + + _showAdvancedHtml(player, teleporter, npc, "cc_teleport_list.html", placeholders); + return true; + } + + private boolean _showSoloTeleportHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String teleIdent, String catIdent) { + SoloTeleport teleport = null; + if (catIdent != null && !catIdent.isEmpty()) { + SoloTeleportCategory category = teleporter.getSoloTeleportCategories().get(catIdent); + if (category == null) { + debug(player, "Invalid category ident: " + catIdent); + return false; + } + + teleport = category.getSoloTeleports().get(teleIdent); + } else { + teleport = teleporter.getSoloTeleports().get(teleIdent); + } + + if (teleport == null) { + debug(player, "Invalid teleport ident: " + teleIdent); + return false; + } + + _showTeleportHtml(player, teleporter, teleport, npc, "solo_teleport.html"); + return true; + } + + private boolean _showPartyTeleportHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String teleIdent, String catIdent) { + GroupTeleport teleport = null; + if (catIdent != null && !catIdent.isEmpty()) { + GroupTeleportCategory category = teleporter.getPartyTeleportCategories().get(catIdent); + if (category == null) { + debug(player, "Invalid category ident: " + catIdent); + return false; + } + + teleport = category.getGroupTeleports().get(teleIdent); + } else { + teleport = teleporter.getPartyTeleports().get(teleIdent); + } + + if (teleport == null) { + debug(player, "Invalid teleport ident: " + teleIdent); + return false; + } + + _showTeleportHtml(player, teleporter, teleport, npc, "p_teleport.html"); + return true; + } + + private boolean _showCommandChannelTeleportHtml(L2PcInstance player, AbstractTeleporter teleporter, L2Npc npc, String teleIdent, String catIdent) { + GroupTeleport teleport = null; + if (catIdent != null && !catIdent.isEmpty()) { + GroupTeleportCategory category = teleporter.getCommandChannelTeleportCategories().get(catIdent); + if (category == null) { + debug(player, "Invalid category ident: " + catIdent); + return false; + } + + teleport = category.getGroupTeleports().get(teleIdent); + } else { + teleport = teleporter.getCommandChannelTeleports().get(teleIdent); + } + + if (teleport == null) { + debug(player, "Invalid teleport ident: " + teleIdent); + return false; + } + + _showTeleportHtml(player, teleporter, teleport, npc, "cc_teleport.html"); + return true; + } + + // //////////////////////////////////// + // TELEPORT COMMANDS + // //////////////////////////////////// + private void _makeTeleport(SoloTeleport teleport, L2PcInstance initiator) { + if (!_takeTeleportItems(teleport, initiator)) { + return; + } + + InstanceWorld world = null; + if (!teleport.getInstance().isEmpty()) { + world = _createInstance(teleport.getInstance()); + world.addAllowed(initiator.getObjectId()); + } + + initiator.teleToLocation(teleport.getX(), teleport.getY(), teleport.getZ(), teleport.getHeading(), world != null ? world.getInstanceId() : initiator.getInstanceId(), teleport.getRandomOffset()); + } + + private void _makeGroupTeleport(GroupTeleport teleport, L2PcInstance initiator, AbstractPlayerGroup group) { + final L2PcInstance leader = group.getLeader(); + if (leader != initiator) { + initiator.sendMessage("You are not the leader!"); + return; + } + + final int memberCount = group.getMemberCount(); + if (group.getMemberCount() < teleport.getMinMembers()) { + group.broadcastString("Not enough members!"); + return; + } + + final int leaderInstanceId = leader.getInstanceId(); + final ArrayList<L2PcInstance> membersInRange = new ArrayList<>(memberCount); + membersInRange.add(leader); + + for (L2PcInstance member : group.getMembers()) { + if ((member != leader) && ((member.getInstanceId() != leaderInstanceId) || (member.calculateDistance(leader, false, false) > teleport.getMaxDistance()))) { + continue; + } + + membersInRange.add(member); + } + + if (membersInRange.size() < memberCount) { + if (!teleport.getAllowIncomplete()) { + group.broadcastString("Your group is not together!"); + return; + } else if (membersInRange.size() < teleport.getMinMembers()) { + group.broadcastString("Not enough members around!"); + return; + } + } + + if (membersInRange.size() > teleport.getMaxMembers()) { + group.broadcastString("Too many members!"); + return; + } + + if (!_takeTeleportItems(teleport, initiator)) { + return; + } + + InstanceWorld world = null; + int instanceId = initiator.getInstanceId(); + if (!teleport.getInstance().isEmpty()) { + world = _createInstance(teleport.getInstance()); + instanceId = world.getInstanceId(); + } + + for (L2PcInstance member : membersInRange) { + if (world != null) { + world.addAllowed(member.getObjectId()); + } + member.teleToLocation(teleport.getX(), teleport.getY(), teleport.getZ(), teleport.getHeading(), instanceId, teleport.getRandomOffset()); + } + } + + private void _teleportSolo(L2PcInstance player, AbstractTeleporter teleporter, String teleId, String catId) { + SoloTeleport teleport = null; + if (catId != null && !catId.isEmpty()) { + SoloTeleportCategory category = teleporter.getSoloTeleportCategories().get(catId); + if (category == null) { + debug(player, "Invalid category ident: " + catId); + return; + } + + teleport = category.getSoloTeleports().get(teleId); + } else { + teleport = teleporter.getSoloTeleports().get(teleId); + } + + if (teleport == null) { + debug(player, "Invalid solo teleport id: " + teleId); + return; + } + + _makeTeleport(teleport, player); + } + + private void _teleportParty(L2PcInstance player, AbstractTeleporter teleporter, String teleId, String catId) { + GroupTeleport teleport = null; + if (catId != null && !catId.isEmpty()) { + GroupTeleportCategory category = teleporter.getPartyTeleportCategories().get(catId); + if (category == null) { + debug(player, "Invalid category ident: " + catId); + return; + } + + teleport = category.getGroupTeleports().get(teleId); + } else { + teleport = teleporter.getPartyTeleports().get(teleId); + } + + if (teleport == null) { + debug(player, "Invalid party teleport id: " + teleId); + return; + } + + final L2Party party = player.getParty(); + if (party == null) { + player.sendMessage("You are not in a party!"); + return; + } + + _makeGroupTeleport(teleport, player, party); + } + + private void _teleportCommandChannel(L2PcInstance player, AbstractTeleporter teleporter, String teleId, String catId) { + GroupTeleport teleport = null; + if (catId != null && !catId.isEmpty()) { + GroupTeleportCategory category = teleporter.getCommandChannelTeleportCategories().get(catId); + if (category == null) { + debug(player, "Invalid category ident: " + catId); + return; + } + + teleport = category.getGroupTeleports().get(teleId); + } else { + teleport = teleporter.getCommandChannelTeleports().get(teleId); + } + + if (teleport == null) { + debug(player, "Invalid command channel teleport id: " + teleId); + return; + } + + final L2Party party = player.getParty(); + if (party == null) { + player.sendMessage("You are not in a party!"); + return; + } + + final L2CommandChannel commandChannel = party.getCommandChannel(); + if (commandChannel == null) { + player.sendMessage("Your party is not in a command channel!"); + return; + } + + _makeGroupTeleport(teleport, player, commandChannel); + } + + private void _executeTeleportCommand(L2PcInstance player, AbstractTeleporter teleporter, CommandProcessor command) { + if (command.matchAndRemove("solo ", "s ")) { + String[] args = command.splitRemaining(" "); + _teleportSolo(player, teleporter, args[0], args.length > 1 ? args[1] : null); + } else if (command.matchAndRemove("party ", "p ")) { + String[] args = command.splitRemaining(" "); + _teleportParty(player, teleporter, args[0], args.length > 1 ? args[1] : null); + } else if (command.matchAndRemove("command_channel ", "cc ")) { + String[] args = command.splitRemaining(" "); + _teleportCommandChannel(player, teleporter, args[0], args.length > 1 ? args[1] : null); + } + } + + // + // ////////////////////////////// + + @Override + protected boolean executeHtmlCommand(L2PcInstance player, L2Npc npc, CommandProcessor command) { + AbstractTeleporter teleporter = getConfig().determineTeleporter(npc, player); + if (teleporter == null) { + player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.S1_NOT_FOUND).addString("Teleporter")); + return false; + } + + if (command.matchAndRemove("main", "m")) { + return _showMainHtml(player, teleporter, npc); + } else if (command.matchAndRemove("solo_category_list", "scl")) { + return _showSoloCategoryList(player, teleporter, npc); + } else if (command.matchAndRemove("party_category_list", "pcl")) { + return _showPartyCategoryList(player, teleporter, npc); + } else if (command.matchAndRemove("command_channel_category_list", "cccl")) { + return _showCommandChannelCategoryList(player, teleporter, npc); + } else if (command.matchAndRemove("solo_list ", "sl ")) { + return _showSoloListHtml(player, teleporter, npc, command.getRemaining()); + } else if (command.matchAndRemove("party_list ", "pl ")) { + return _showPartyListHtml(player, teleporter, npc, command.getRemaining()); + } else if (command.matchAndRemove("command_channel_list ", "ccl ")) { + return _showCommandChannelListHtml(player, teleporter, npc, command.getRemaining()); + } else if (command.matchAndRemove("solo_list", "sl")) { + return _showSoloListHtml(player, teleporter, npc, null); + } else if (command.matchAndRemove("party_list", "pl")) { + return _showPartyListHtml(player, teleporter, npc, null); + } else if (command.matchAndRemove("command_channel_list", "ccl")) { + return _showCommandChannelListHtml(player, teleporter, npc, null); + } else if (command.matchAndRemove("solo_teleport ", "st ")) { + String[] args = command.splitRemaining(" "); + return _showSoloTeleportHtml(player, teleporter, npc, args[0], args.length > 1 ? args[1] : null); + } else if (command.matchAndRemove("party_teleport ", "pt ")) { + String[] args = command.splitRemaining(" "); + return _showPartyTeleportHtml(player, teleporter, npc, args[0], args.length > 1 ? args[1] : null); + } else if (command.matchAndRemove("command_channel_teleport ", "cct ")) { + String[] args = command.splitRemaining(" "); + return _showCommandChannelTeleportHtml(player, teleporter, npc, args[0], args.length > 1 ? args[1] : null); + } + + return false; + } + + @Override + protected boolean executeActionCommand(L2PcInstance player, L2Npc npc, CommandProcessor command) { + SystemMessage abortSysMsg = null; + AbstractTeleporter teleporter = null; + + if (player.isDead() || player.isAlikeDead()) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (isInsideAnyZoneOf(player, Configuration.teleporterService().getForbidInZones())) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (Configuration.teleporterService().getForbidInEvents() && ((player.getEventStatus() != null) || (player.getBlockCheckerArena() != -1) || player.isOnEvent() || player.isInOlympiadMode() || TvTEvent.isPlayerParticipant(player.getObjectId()))) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (Configuration.teleporterService().getForbidInDuell() && player.isInDuel()) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (Configuration.teleporterService().getForbidInFight() && AttackStanceTaskManager.getInstance().hasAttackStanceTask(player)) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (Configuration.teleporterService().getForbidInPvp() && (player.getPvpFlag() == 1)) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else if (Configuration.teleporterService().getForbidForChaoticPlayers() && player.getKarma() > 0) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_CANNOT_BE_USED); + abortSysMsg.addString("Teleporter"); + } else { + teleporter = getConfig().determineTeleporter(npc, player); + if (teleporter == null) { + abortSysMsg = SystemMessage.getSystemMessage(SystemMessageId.S1_NOT_FOUND); + abortSysMsg.addString("Teleporter"); + } + } + + if (abortSysMsg != null) { + player.sendPacket(abortSysMsg); + return false; + } + + if (command.matchAndRemove("teleport ", "t ")) { + _executeTeleportCommand(player, teleporter, command); + return false; + } + + return true; + } + + @Override + protected boolean isDebugEnabled() { + return Configuration.teleporterService().getDebug(); + } +} \ No newline at end of file diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceBypassHandler.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceBypassHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..373ed346405baa24866b3f56ecf261457ee5946f --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceBypassHandler.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter; + +import com.l2jserver.gameserver.handler.IBypassHandler; +import com.l2jserver.gameserver.model.actor.L2Character; +import com.l2jserver.gameserver.model.actor.L2Npc; +import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; + +/** + * Teleporter service bypass handler. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class TeleporterServiceBypassHandler implements IBypassHandler { + + public static final String BYPASS = "TeleporterService"; + private static final String[] BYPASS_LIST = new String[] { + BYPASS + }; + + private TeleporterServiceBypassHandler() { + } + + @Override + public boolean useBypass(String command, L2PcInstance activeChar, L2Character target) { + if ((target == null) || !target.isNpc()) { + return false; + } + + TeleporterService.getService().executeCommand(activeChar, (L2Npc) target, command.substring(BYPASS.length()).trim()); + return true; + } + + @Override + public String[] getBypassList() { + return BYPASS_LIST; + } + + static TeleporterServiceBypassHandler getInstance() { + return SingletonHolder.INSTANCE; + } + + private static final class SingletonHolder { + protected static final TeleporterServiceBypassHandler INSTANCE = new TeleporterServiceBypassHandler(); + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceItemHandler.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceItemHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..d3e297ac9fb5b85b0273c6caeb14f63a243ff6ad --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceItemHandler.java @@ -0,0 +1,53 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter; + +import com.l2jserver.gameserver.handler.IItemHandler; +import com.l2jserver.gameserver.model.actor.L2Playable; +import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; +import com.l2jserver.gameserver.model.items.instance.L2ItemInstance; + +/** + * Teleporter service item handler. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public final class TeleporterServiceItemHandler implements IItemHandler { + + private TeleporterServiceItemHandler() { + } + + @Override + public boolean useItem(L2Playable playable, L2ItemInstance item, boolean forceUse) { + if (!playable.isPlayer()) { + return false; + } + + TeleporterService.getService().executeCommand((L2PcInstance) playable, null, null); + return true; + } + + static TeleporterServiceItemHandler getInstance() { + return SingletonHolder.INSTANCE; + } + + private static final class SingletonHolder { + protected static final TeleporterServiceItemHandler INSTANCE = new TeleporterServiceItemHandler(); + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceVoicedCommandHandler.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceVoicedCommandHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..ddfd18c7865e2c64ecca5b5a95cd06df1cfc8702 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/TeleporterServiceVoicedCommandHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter; + +import com.l2jserver.gameserver.config.Configuration; +import com.l2jserver.gameserver.handler.IVoicedCommandHandler; +import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; + +/** + * Teleporter service voiced command handler. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public final class TeleporterServiceVoicedCommandHandler implements IVoicedCommandHandler { + private static final String[] COMMANDS = new String[] { + Configuration.teleporterService().getVoicedCommand() + }; + + private TeleporterServiceVoicedCommandHandler() { + } + + @Override + public boolean useVoicedCommand(String command, L2PcInstance activeChar, String params) { + TeleporterService.getService().executeCommand(activeChar, null, params); + return true; + } + + @Override + public String[] getVoicedCommandList() { + return COMMANDS; + } + + static TeleporterServiceVoicedCommandHandler getInstance() { + return SingletonHolder.INSTANCE; + } + + private static final class SingletonHolder { + protected static final TeleporterServiceVoicedCommandHandler INSTANCE = new TeleporterServiceVoicedCommandHandler(); + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/GlobalConfig.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/GlobalConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..9f404dcbf58bbdf1e64005a09706242d64a22f1d --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/GlobalConfig.java @@ -0,0 +1,73 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model; + +import java.util.Map; + +import com.l2jserver.datapack.custom.service.teleporter.model.entity.GroupTeleport; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.GroupTeleportCategory; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.SoloTeleport; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.SoloTeleportCategory; + +/** + * Global configuration. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class GlobalConfig { + private Map<String, SoloTeleport> soloTeleports; + private Map<String, GroupTeleport> groupTeleports; + + private Map<String, SoloTeleportCategory> soloTeleportCategories; + private Map<String, GroupTeleportCategory> groupTeleportCategories; + + public void afterDeserialize(TeleporterConfig config) { + for (SoloTeleport teleport : soloTeleports.values()) { + teleport.afterDeserialize(config); + } + + for (GroupTeleport teleport : groupTeleports.values()) { + teleport.afterDeserialize(config); + } + + for (SoloTeleportCategory soloCat : soloTeleportCategories.values()) { + soloCat.afterDeserialize(config); + } + + for (GroupTeleportCategory groupCat : groupTeleportCategories.values()) { + groupCat.afterDeserialize(config); + } + } + + public Map<String, SoloTeleport> getSoloTeleports() { + return soloTeleports; + } + + public Map<String, GroupTeleport> getGroupTeleports() { + return groupTeleports; + } + + public Map<String, SoloTeleportCategory> getSoloTeleportCategories() { + return soloTeleportCategories; + } + + public Map<String, GroupTeleportCategory> getGroupTeleportCategories() { + return groupTeleportCategories; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/TeleporterConfig.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/TeleporterConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..0973bf986bf2b563454116acf9d5b0dd6c1d1a10 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/TeleporterConfig.java @@ -0,0 +1,108 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; +import com.l2jserver.datapack.custom.service.teleporter.TeleporterService; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.AbstractTeleporter; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.NpcTeleporter; +import com.l2jserver.datapack.custom.service.teleporter.model.entity.VoicedTeleporter; +import com.l2jserver.gameserver.config.Configuration; +import com.l2jserver.gameserver.model.actor.L2Npc; +import com.l2jserver.gameserver.model.actor.instance.L2PcInstance; + +/** + * Teleporter config. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class TeleporterConfig { + private final GlobalConfig global; + private final VoicedTeleporter voiced; + private final Map<Integer, NpcTeleporter> npcs; + + public TeleporterConfig() throws JsonSyntaxException, JsonIOException, IOException { + Gson gson = new Gson(); + + Path jsonPath = Paths.get(Configuration.server().getDatapackRoot().getAbsolutePath(), "data", TeleporterService.SCRIPT_PATH.toString(), "json"); + + global = gson.fromJson(Files.newBufferedReader(jsonPath.resolve("global.json")), GlobalConfig.class); + voiced = gson.fromJson(Files.newBufferedReader(jsonPath.resolve("voiced.json")), VoicedTeleporter.class); + npcs = new HashMap<>(); + + Path npcsDir = Paths.get(jsonPath.toString(), "npcs"); + try (var dirStream = Files.newDirectoryStream(npcsDir, "*.json")) { + for (Path entry : dirStream) { + if (!Files.isRegularFile(entry)) { + continue; + } + + NpcTeleporter npc = gson.fromJson(Files.newBufferedReader(entry), NpcTeleporter.class); + npcs.put(npc.getId(), npc); + } + } + + global.afterDeserialize(this); + voiced.afterDeserialize(this); + for (NpcTeleporter npc : npcs.values()) { + npc.afterDeserialize(this); + } + } + + public AbstractTeleporter determineTeleporter(L2Npc npc, L2PcInstance player) { + if (npc == null) { + if (!Configuration.teleporterService().getVoicedEnable() || ((Configuration.teleporterService().getVoicedRequiredItem() > 0) && (player.getInventory().getAllItemsByItemId(Configuration.teleporterService().getVoicedRequiredItem()) == null))) { + return null; + } + return voiced; + } + return npcs.get(npc.getId()); + } + + public void registerNpcs(TeleporterService scriptInstance) { + for (NpcTeleporter npc : npcs.values()) { + if (npc.getDirectFirstTalk()) { + scriptInstance.addFirstTalkId(npc.getId()); + } + scriptInstance.addStartNpc(npc.getId()); + scriptInstance.addTalkId(npc.getId()); + } + } + + public GlobalConfig getGlobal() { + return global; + } + + public VoicedTeleporter getVoiced() { + return voiced; + } + + public Map<Integer, NpcTeleporter> getNpcs() { + return npcs; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleportCategory.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleportCategory.java new file mode 100644 index 0000000000000000000000000000000000000000..a34b4e2c4b990d070b1ee4ce3995bf0f77e7d9ae --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleportCategory.java @@ -0,0 +1,41 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import com.l2jserver.datapack.custom.service.base.model.entity.Refable; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Base class for teleporter categories. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public abstract class AbstractTeleportCategory extends Refable { + private String name; + + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(); + + getPlaceholder().addChild("name", name); + } + + public final String getName() { + return name; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleporter.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleporter.java new file mode 100644 index 0000000000000000000000000000000000000000..b7360c0c60983628a73d0a8da6fe8a96cd0a2cf2 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/AbstractTeleporter.java @@ -0,0 +1,149 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.l2jserver.datapack.custom.service.base.model.entity.CustomServiceServer; +import com.l2jserver.datapack.custom.service.base.util.htmltmpls.HTMLTemplatePlaceholder; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Base class for teleporter service types. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public abstract class AbstractTeleporter extends CustomServiceServer { + private List<String> soloTeleports; + private List<String> partyTeleports; + private List<String> commandChannelTeleports; + + private List<String> soloTeleportCategories; + private List<String> partyTeleportCategories; + private List<String> commandChannelTeleportCategories; + + public transient Map<String, SoloTeleport> soloTeleportsMap; + public transient Map<String, GroupTeleport> partyTeleportsMap; + public transient Map<String, GroupTeleport> commandChannelTeleportsMap; + + private transient Map<String, SoloTeleportCategory> soloTeleportCategoriesMap; + private transient Map<String, GroupTeleportCategory> partyTeleportCategoriesMap; + private transient Map<String, GroupTeleportCategory> commandChannelTeleportCategoriesMap; + + public AbstractTeleporter(String bypassPrefix) { + super(bypassPrefix, "teleporter"); + + soloTeleportsMap = new LinkedHashMap<>(); + partyTeleportsMap = new LinkedHashMap<>(); + commandChannelTeleportsMap = new LinkedHashMap<>(); + + soloTeleportCategoriesMap = new LinkedHashMap<>(); + partyTeleportCategoriesMap = new LinkedHashMap<>(); + commandChannelTeleportCategoriesMap = new LinkedHashMap<>(); + } + + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(); + + for (String id : soloTeleports) { + soloTeleportsMap.put(id, config.getGlobal().getSoloTeleports().get(id)); + } + for (String id : partyTeleports) { + partyTeleportsMap.put(id, config.getGlobal().getGroupTeleports().get(id)); + } + for (String id : commandChannelTeleports) { + commandChannelTeleportsMap.put(id, config.getGlobal().getGroupTeleports().get(id)); + } + + for (String id : soloTeleportCategories) { + soloTeleportCategoriesMap.put(id, config.getGlobal().getSoloTeleportCategories().get(id)); + } + for (String id : partyTeleportCategories) { + partyTeleportCategoriesMap.put(id, config.getGlobal().getGroupTeleportCategories().get(id)); + } + for (String id : commandChannelTeleportCategories) { + commandChannelTeleportCategoriesMap.put(id, config.getGlobal().getGroupTeleportCategories().get(id)); + } + + if (!soloTeleports.isEmpty()) { + HTMLTemplatePlaceholder telePlaceholder = getPlaceholder().addChild("solo_teleports", null).getChild("solo_teleports"); + for (Entry<String, SoloTeleport> soloTeleport : soloTeleportsMap.entrySet()) { + telePlaceholder.addAliasChild(String.valueOf(telePlaceholder.getChildrenSize()), soloTeleport.getValue().getPlaceholder()); + } + } + if (!partyTeleports.isEmpty()) { + HTMLTemplatePlaceholder telePlaceholder = getPlaceholder().addChild("party_teleports", null).getChild("party_teleports"); + for (Entry<String, GroupTeleport> partyTeleport : partyTeleportsMap.entrySet()) { + telePlaceholder.addAliasChild(String.valueOf(telePlaceholder.getChildrenSize()), partyTeleport.getValue().getPlaceholder()); + } + } + if (!commandChannelTeleports.isEmpty()) { + HTMLTemplatePlaceholder telePlaceholder = getPlaceholder().addChild("command_channel_teleports", null).getChild("command_channel_teleports"); + for (Entry<String, GroupTeleport> commandChannelTeleport : commandChannelTeleportsMap.entrySet()) { + telePlaceholder.addAliasChild(String.valueOf(telePlaceholder.getChildrenSize()), commandChannelTeleport.getValue().getPlaceholder()); + } + } + + if (!soloTeleportCategories.isEmpty()) { + HTMLTemplatePlaceholder catsPlaceholder = getPlaceholder().addChild("solo_categories", null).getChild("solo_categories"); + for (Entry<String, SoloTeleportCategory> soloTeleportCategories : soloTeleportCategoriesMap.entrySet()) { + catsPlaceholder.addAliasChild(String.valueOf(catsPlaceholder.getChildrenSize()), soloTeleportCategories.getValue().getPlaceholder()); + } + } + if (!partyTeleportCategories.isEmpty()) { + HTMLTemplatePlaceholder catsPlaceholder = getPlaceholder().addChild("party_categories", null).getChild("party_categories"); + for (Entry<String, GroupTeleportCategory> partyTeleportCategories : partyTeleportCategoriesMap.entrySet()) { + catsPlaceholder.addAliasChild(String.valueOf(catsPlaceholder.getChildrenSize()), partyTeleportCategories.getValue().getPlaceholder()); + } + } + if (!commandChannelTeleportCategories.isEmpty()) { + HTMLTemplatePlaceholder catsPlaceholder = getPlaceholder().addChild("command_channel_categories", null).getChild("command_channel_categories"); + for (Entry<String, GroupTeleportCategory> commandChannelTeleportCategories : commandChannelTeleportCategoriesMap.entrySet()) { + catsPlaceholder.addAliasChild(String.valueOf(catsPlaceholder.getChildrenSize()), commandChannelTeleportCategories.getValue().getPlaceholder()); + } + } + } + + public final Map<String, SoloTeleport> getSoloTeleports() { + return soloTeleportsMap; + } + + public final Map<String, GroupTeleport> getPartyTeleports() { + return partyTeleportsMap; + } + + public final Map<String, GroupTeleport> getCommandChannelTeleports() { + return commandChannelTeleportsMap; + } + + public final Map<String, SoloTeleportCategory> getSoloTeleportCategories() { + return soloTeleportCategoriesMap; + } + + public final Map<String, GroupTeleportCategory> getPartyTeleportCategories() { + return partyTeleportCategoriesMap; + } + + public final Map<String, GroupTeleportCategory> getCommandChannelTeleportCategories() { + return commandChannelTeleportCategoriesMap; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleport.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleport.java new file mode 100644 index 0000000000000000000000000000000000000000..c1e76a3068ce3ef5a4edd2e07c906e2d0059c733 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleport.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Group teleport. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class GroupTeleport extends SoloTeleport { + private int minMembers; + private int maxMembers; + private int maxDistance; + private boolean allowIncomplete; + + public GroupTeleport() { + } + + @Override + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(config); + + getPlaceholder().addChild("min_members", String.valueOf(minMembers)).addChild("max_members", String.valueOf(maxMembers)).addChild("max_distance", String.valueOf(maxDistance)); + } + + public int getMinMembers() { + return minMembers; + } + + public int getMaxMembers() { + return maxMembers; + } + + public int getMaxDistance() { + return maxDistance; + } + + public boolean getAllowIncomplete() { + return allowIncomplete; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleportCategory.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleportCategory.java new file mode 100644 index 0000000000000000000000000000000000000000..27cbb5b65ae2f68565c39318a27184b73fe4774a --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/GroupTeleportCategory.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.l2jserver.datapack.custom.service.base.util.htmltmpls.HTMLTemplatePlaceholder; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Group teleport category. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class GroupTeleportCategory extends AbstractTeleportCategory { + private List<String> groupTeleports; + + private transient Map<String, GroupTeleport> groupTeleportsMap; + + public GroupTeleportCategory() { + groupTeleportsMap = new LinkedHashMap<>(); + } + + @Override + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(config); + + for (String id : groupTeleports) { + groupTeleportsMap.put(id, config.getGlobal().getGroupTeleports().get(id)); + } + + if (!groupTeleports.isEmpty()) { + HTMLTemplatePlaceholder telePlaceholder = getPlaceholder().addChild("teleports", null).getChild("teleports"); + for (Entry<String, GroupTeleport> groupTeleport : groupTeleportsMap.entrySet()) { + telePlaceholder.addAliasChild(String.valueOf(telePlaceholder.getChildrenSize()), groupTeleport.getValue().getPlaceholder()); + } + } + } + + public Map<String, GroupTeleport> getGroupTeleports() { + return groupTeleportsMap; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/NpcTeleporter.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/NpcTeleporter.java new file mode 100644 index 0000000000000000000000000000000000000000..b09a58d06968c6df7a173c3df8cfafa5b3f3d43f --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/NpcTeleporter.java @@ -0,0 +1,68 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import com.l2jserver.datapack.custom.service.base.model.entity.IRefable; +import com.l2jserver.datapack.custom.service.teleporter.TeleporterServiceBypassHandler; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; +import com.l2jserver.gameserver.data.xml.impl.NpcData; +import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate; + +/** + * Npc teleporter. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public final class NpcTeleporter extends AbstractTeleporter implements IRefable<Integer> { + private int npcId; + private boolean directFirstTalk; + + public NpcTeleporter() { + super(TeleporterServiceBypassHandler.BYPASS); + } + + @Override + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(config); + + getPlaceholder().addChild("ident", String.valueOf(npcId)); + } + + public L2NpcTemplate getNpc() { + return NpcData.getInstance().getTemplate(npcId); + } + + public int getNpcId() { + return npcId; + } + + public boolean getDirectFirstTalk() { + return directFirstTalk; + } + + @Override + public final String getName() { + return getNpc().getName(); + } + + @Override + public final Integer getId() { + return npcId; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleport.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleport.java new file mode 100644 index 0000000000000000000000000000000000000000..2dd0e2b4d9ee32da2f89001551f88c7bc5771317 --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleport.java @@ -0,0 +1,74 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import com.l2jserver.datapack.custom.service.base.model.entity.CustomServiceProduct; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Solo teleport. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class SoloTeleport extends CustomServiceProduct { + private String name; + private int x; + private int y; + private int z; + private int heading; + private int randomOffset; + private String instance; + + public SoloTeleport() { + } + + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(); + + getPlaceholder().addChild("name", name); + } + + public String getName() { + return name; + } + + public int getRandomOffset() { + return randomOffset; + } + + public int getHeading() { + return heading; + } + + public String getInstance() { + return instance; + } + + public int getZ() { + return z; + } + + public int getY() { + return y; + } + + public int getX() { + return x; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleportCategory.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleportCategory.java new file mode 100644 index 0000000000000000000000000000000000000000..a98212b23c4eb669d00bc2eaf7b482660efdf39a --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/SoloTeleportCategory.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.l2jserver.datapack.custom.service.base.util.htmltmpls.HTMLTemplatePlaceholder; +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; + +/** + * Solo teleport category. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public class SoloTeleportCategory extends AbstractTeleportCategory { + private List<String> soloTeleports; + + private transient Map<String, SoloTeleport> soloTeleportsMap; + + public SoloTeleportCategory() { + soloTeleportsMap = new LinkedHashMap<>(); + } + + @Override + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(config); + + for (String id : soloTeleports) { + soloTeleportsMap.put(id, config.getGlobal().getSoloTeleports().get(id)); + } + + if (!soloTeleports.isEmpty()) { + HTMLTemplatePlaceholder telePlaceholder = getPlaceholder().addChild("teleports", null).getChild("teleports"); + for (Entry<String, SoloTeleport> soloTeleport : soloTeleportsMap.entrySet()) { + telePlaceholder.addAliasChild(String.valueOf(telePlaceholder.getChildrenSize()), soloTeleport.getValue().getPlaceholder()); + } + } + } + + public Map<String, SoloTeleport> getSoloTeleports() { + return soloTeleportsMap; + } +} diff --git a/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/VoicedTeleporter.java b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/VoicedTeleporter.java new file mode 100644 index 0000000000000000000000000000000000000000..81e4b1bd2151412ad54e22da7f127210b255a21c --- /dev/null +++ b/src/main/java/com/l2jserver/datapack/custom/service/teleporter/model/entity/VoicedTeleporter.java @@ -0,0 +1,49 @@ +/* + * Copyright © 2004-2021 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 <http://www.gnu.org/licenses/>. + */ +package com.l2jserver.datapack.custom.service.teleporter.model.entity; + +import com.l2jserver.datapack.custom.service.teleporter.model.TeleporterConfig; +import com.l2jserver.gameserver.config.Configuration; +import com.l2jserver.gameserver.datatables.ItemTable; +import com.l2jserver.gameserver.model.items.L2Item; + +/** + * Voiced teleporter. + * @author HorridoJoho + * @version 2.6.2.0 + */ +public final class VoicedTeleporter extends AbstractTeleporter { + public VoicedTeleporter() { + super("voice ." + Configuration.teleporterService().getVoicedCommand()); + } + + @Override + public void afterDeserialize(TeleporterConfig config) { + super.afterDeserialize(config); + } + + public L2Item getRequiredItem() { + return ItemTable.getInstance().getTemplate(Configuration.teleporterService().getVoicedRequiredItem()); + } + + @Override + public String getName() { + return Configuration.teleporterService().getVoicedName(); + } +} diff --git a/src/main/resources/data/scripts.cfg b/src/main/resources/data/scripts.cfg index 1e10f9add1f5c4ac17b49e435875252abdc15ca2..03779dd64faf0b595c1fd0e8eab0b78592b18fe0 100644 --- a/src/main/resources/data/scripts.cfg +++ b/src/main/resources/data/scripts.cfg @@ -9,6 +9,7 @@ com/l2jserver/datapack/features/SkillTransfer/SkillTransfer.java # Custom com/l2jserver/datapack/custom/Validators/SubClassSkills.java com/l2jserver/datapack/custom/service/buffer/BufferService.java +com/l2jserver/datapack/custom/service/teleporter/TeleporterService.java com/l2jserver/datapack/custom/service/discord/DiscordBot.java # Custom Events diff --git a/src/main/resources/data/service/teleporter/html/npc/cc_category_list.html b/src/main/resources/data/service/teleporter/html/npc/cc_category_list.html new file mode 100644 index 0000000000000000000000000000000000000000..bf1347f037dc1f77044c413815d3eb303ecda125 --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/cc_category_list.html @@ -0,0 +1,6 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <font color=LEVEL>Command Channel Teleports</font><br> +[FOREACH(teleport IN teleporter.command_channel_teleports DO <a action="%teleporter.bypass_prefix% t cc %teleport.ident%" msg="811;%teleport.name%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +<br1><center> +[FOREACH(category IN teleporter.command_channel_categories DO <button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="%category.name%" action="%teleporter.bypass_prefix% h ccl %category.ident%"><br1>)ENDEACH] +</center></body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/html/npc/cc_teleport_list.html b/src/main/resources/data/service/teleporter/html/npc/cc_teleport_list.html new file mode 100644 index 0000000000000000000000000000000000000000..3d9dfc3899df1fb735c4bcd87f024c289124ea72 --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/cc_teleport_list.html @@ -0,0 +1,7 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <a action="%teleporter.bypass_prefix% h cccl">Command Channel Teleports</a>[EXISTS(category, > <font color=LEVEL>%category.name%</font>)]<br> +[EXISTS(category, + [FOREACH(teleport IN teleporter.command_channel_teleports DO <a action="%teleporter.bypass_prefix% t cc %teleport.ident%" msg="811;%teleport.name%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +)ENDEXISTS] +[FOREACH(teleport IN category.teleports DO <a action="%teleporter.bypass_prefix% t cc %teleport.ident% %category.ident%" msg="811;%teleport.name%" msg="811;%teleport.name%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +</body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/html/npc/main.html b/src/main/resources/data/service/teleporter/html/npc/main.html new file mode 100644 index 0000000000000000000000000000000000000000..bb99021e48172d8cf8497b45ba29941cd5fa6f0f --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/main.html @@ -0,0 +1,5 @@ +<html noscrollbar><title>%teleporter.name%</title><body><center> +<button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="Solo Teleports" action="%teleporter.bypass_prefix% h scl"><br> +<button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="Party Teleports" action="%teleporter.bypass_prefix% h pcl"><br> +<button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="Command Channel Teleports" action="%teleporter.bypass_prefix% h cccl"> +</center></body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/html/npc/p_category_list.html b/src/main/resources/data/service/teleporter/html/npc/p_category_list.html new file mode 100644 index 0000000000000000000000000000000000000000..6e4400e63732348c9a80f64b63002ed9299e2ea8 --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/p_category_list.html @@ -0,0 +1,6 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <font color=LEVEL>Party Teleports</font><br> +[FOREACH(teleport IN teleporter.party_teleports DO <a action="%teleporter.bypass_prefix% t p %teleport.ident%" msg="811;%teleport.name%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +<br1><center> +[FOREACH(category IN teleporter.party_categories DO <button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="%category.name%" action="%teleporter.bypass_prefix% h pl %category.ident%"><br1>)ENDEACH] +</center></body></html> diff --git a/src/main/resources/data/service/teleporter/html/npc/p_teleport_list.html b/src/main/resources/data/service/teleporter/html/npc/p_teleport_list.html new file mode 100644 index 0000000000000000000000000000000000000000..2271959422a1b4692b0a4d7a2c6f1963e370ae2b --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/p_teleport_list.html @@ -0,0 +1,7 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <a action="%teleporter.bypass_prefix% h pcl">Party Teleports</a>[EXISTS(category, > <font color=LEVEL>%category.name%</font>)]<br> +[EXISTS(!category, + [FOREACH(teleport IN teleporter.party_teleports DO <a action="%teleporter.bypass_prefix% t p %teleport.ident%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +)ENDEXISTS] +[FOREACH(teleport IN category.teleports DO <a action="%teleporter.bypass_prefix% t p %teleport.ident% %category.ident%" msg="811;%teleport.name%">%teleport.name% (%teleport.min_members% - %teleport.max_members%, [FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +</body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/html/npc/solo_category_list.html b/src/main/resources/data/service/teleporter/html/npc/solo_category_list.html new file mode 100644 index 0000000000000000000000000000000000000000..3ffecfd35ceaa2352d81bfe6f859b06041aad0bc --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/solo_category_list.html @@ -0,0 +1,6 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <font color=LEVEL>Solo Teleports</font><br> +[FOREACH(teleport IN teleporter.solo_teleports DO <a action="%teleporter.bypass_prefix% t s %teleport.ident%" msg="811;%teleport.name%">%teleport.name% ([FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +<br1><center> +[FOREACH(category IN teleporter.solo_categories DO <button width=200 height=34 fore=L2UI_CT1.Button_DF back=L2UI_CT1.Button_DF_Down value="%category.name%" action="%teleporter.bypass_prefix% h sl %category.ident%"><br1>)ENDEACH] +</center></body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/html/npc/solo_teleport_list.html b/src/main/resources/data/service/teleporter/html/npc/solo_teleport_list.html new file mode 100644 index 0000000000000000000000000000000000000000..b097eeca0008ae17021c14084df73e0cbdacdf7a --- /dev/null +++ b/src/main/resources/data/service/teleporter/html/npc/solo_teleport_list.html @@ -0,0 +1,7 @@ +<html><title>%teleporter.name%</title><body> +<a action="%teleporter.bypass_prefix%">Home</a> > <a action="%teleporter.bypass_prefix% h scl">Solo Teleports</a>[EXISTS(category, > <font color=LEVEL>%category.name%</font>)ENDEXISTS]<br> +[EXISTS(!category, + [FOREACH(teleport IN teleporter.solo_teleports DO<a action="%teleporter.bypass_prefix% t s %teleport.ident%" msg="811;%teleport.name%">%teleport.name% ([FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +)ENDEXISTS] +[FOREACH(teleport IN category.teleports DO <a action="%teleporter.bypass_prefix% t s %teleport.ident% %category.ident%" msg="811;%teleport.name%">%teleport.name% ([FOREACH(item IN teleport.items DO %item.amount% %item.name%)ENDEACH])</a><br1>)ENDEACH] +</body></html> \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/json/documentation.txt b/src/main/resources/data/service/teleporter/json/documentation.txt new file mode 100644 index 0000000000000000000000000000000000000000..f25688c7ff5f5d76c014b6d1ea60a97e14f0760b --- /dev/null +++ b/src/main/resources/data/service/teleporter/json/documentation.txt @@ -0,0 +1,128 @@ +################################################################################ +# TeleporterService - JSON Docs # +################################################################################ + +############### +# global.json # +############### + + { + "soloTeleports": { + "<soloTeleportId>": { + "id": "<soloTeleportId>", + "name": (string), + "x": (number), + "y": (number), + "z"; (number), + "heading": (number), + "randomOffset": (number), + "instance": (string), + "items" : [ + { "id":(number), "amount":(number) }, + .... + ] + }, + .... + }, + + "groupTeleports": { + "<groupTeleportId>": { + "id": "<groupTeleportId>", + "name": (string), + "x": (number), + "y": (number), + "z"; (number), + "heading": (number), + "randomOffset": (number), + "instance": (string), + "minMembers": (number), + "maxMembers": (number), + "maxDistance": (number), + "allowIncomplete": (boolean), + "items" : [ + { "id":(number), "amount":(number) }, + .... + ] + }, + .... + }, + + "soloTeleportCategories": { + "<soloTeleportCategoryId>": { + "id": "<soloTeleportCategoryId>", + "name": (string), + "soloTeleports": ["<soloTeleportId>",...] + }, + ... + }, + + "groupTeleportCategories": { + "<groupTeleportCategoryId>": { + "id": "<groupTeleportCategoryId>", + "name": (string), + "groupTeleports": ["<groupTeleportId>",...] + }, + ... + } + } + + Notes: + • solo-/groupTeleports: An object where each property represents a solo/group teleport (the "id" property must match the key in "solo-/groupTeleports"). + • solo-/groupTeleports.name: the display name + • solo-/groupTeleports.randomOffset: a random offset is applied to the specified teleport location for each group member but the leader + • solo-/groupTeleports.<solo-/groupTeleportId>.instance: an instance is created from the specified instance definition xml and the players are teleported into that instance + • groupTeleports.<groupTeleportId>.minMembers: minimum members in the group, including leader + • groupTeleports.<groupTeleportId>.maxMembers: maximum members in the group, including leader + • groupTeleports.<groupTeleportId>.maxDistance: max distance of party members to the leader + • groupTeleports.<groupTeleportId>.allowIncomplete: allow an incomplete group to teleport; when not all group members are in maxDistance range to the party leader, only teleport the members which are in range, if the amount of members is at least minMembers + • solo-/groupTeleports.<solo-/groupTeleportId>.items: An array of item objects + • solo-/groupTeleportCategories.<solo-/groupTeleportCategoryId>: An object where each property represents a solo/group teleport category (the "id" property must match the key in solo-/groupTeleportCategories.<solo-/groupTeleportCategoryId>) + • solo-/groupTeleportCategories.<solo-/groupTeleportCategoryId>.name: Display name of the category + • solo-/groupTeleportCategories.<solo-/groupTeleportCategoryId>.groupTeleports: Array of solo-/groupTeleport id's + + +############### +# voiced.json # +############### + + { + "dialogType": "NPC" or "COMMUNITY", + "htmlFolder": (string), + + "soloTeleports": ["<soloTeleportId>", ...], + "partyTeleports": ["<groupTeleportId>", ...], + "commandChannelTeleports": ["<groupTeleportId>", ...], + + "soloTeleportCategories": ["<soloTeleportCategoryId>",...], + "partyTeleportCategories": ["<groupTeleportCategoryId>",...], + "commandChannelTeleportCategories": ["<groupTeleportCategoryId>",...] + } + + Notes: + • dialogType: NPC opens npc html window, COMMUNITY opens community board + • htmlFolder: where to load htmls from + • solo-/party-/commandChannelTeleports: array of solo-/groupTeleportId + • solo-/party-/commandChannelTeleportCategories: array of solo-/groupTeleportCategoryId + + +##################### +# npcs/<npcId>.json # +##################### + + { + "npcId": "<npcId>", + "directFirstTalk": (boolean), + "dialogType": "NPC" or "COMMUNITY", + "htmlFolder": (string), + + "soloTeleports": ["<soloTeleportId>", ...], + "partyTeleports": ["<groupTeleportId>", ...], + "commandChannelTeleports": ["<groupTeleportId>", ...], + + "soloTeleportCategories": ["<soloTeleportCategoryId>",...], + "partyTeleportCategories": ["<groupTeleportCategoryId>",...], + "commandChannelTeleportCategories": ["<groupTeleportCategoryId>",...] + } + + Notes: + • see notes from voiced.json \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/json/global.json b/src/main/resources/data/service/teleporter/json/global.json new file mode 100644 index 0000000000000000000000000000000000000000..6dba438eaf3b9c4691ff9673990e3f3cecd8cdbe --- /dev/null +++ b/src/main/resources/data/service/teleporter/json/global.json @@ -0,0 +1,425 @@ +{ + "soloTeleports": { + "S_GIRAN": {"id":"S_GIRAN", "name":"Giran", "x":82698, "y":148638, "z":-3473, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GODDARD": {"id":"S_GODDARD", "name":"Goddard", "x":147725, "y":-56517, "z":-2780, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DION": {"id":"S_DION", "name":"Dion", "x":18748, "y":145437, "z":-3132, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIO": {"id":"S_GLUDIO", "name":"Gludio", "x":-14225, "y":123540, "z":-3121, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SCHUTTGART": {"id":"S_SCHUTTGART", "name":"Schutgart", "x":87358, "y":-141982, "z":-1341, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HUNTERS": {"id":"S_HUNTERS", "name":"Hunters", "x":116589, "y":76268, "z":-2734, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ADEN": {"id":"S_ADEN", "name":"Aden", "x":147450, "y":27064, "z":-2208, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RUNE": {"id":"S_RUNE", "name":"Rune", "x":44070, "y":-50243, "z":-796, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_OREN": {"id":"S_OREN", "name":"Oren", "x":82321, "y":55139, "z":-1529, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIN": {"id":"S_GLUDIN", "name":"Gludin", "x":-83063, "y":150791, "z":-3133, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HEINE": {"id":"S_HEINE", "name":"Heine", "x":111115, "y":219017, "z":-3547, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FLORAN": {"id":"S_FLORAN", "name":"Floran", "x":17144, "y":170156, "z":-3502, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HUMAN": {"id":"S_HUMAN", "name":"Human", "x":-82687, "y":243157, "z":-3734, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ORC": {"id":"S_ORC", "name":"Orc", "x":-44133, "y":-113911, "z":-244, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ELVEN": {"id":"S_ELVEN", "name":"Elven", "x":45873, "y":49288, "z":-3064, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DWARVEN": {"id":"S_DWARVEN", "name":"Dwarven", "x":116551, "y":-182493, "z":-1525, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DARK_ELVEN": {"id":"S_DARK_ELVEN", "name":"Dark Elven", "x":12428, "y":16551, "z":-4588, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_KAMAEL": {"id":"S_KAMAEL", "name":"Kamael", "x":-116934, "y":46616, "z":368, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_ADEN_CASTLE": {"id":"S_ADEN_CASTLE", "name":"Aden Castle", "x":147457, "y":10843, "z":-736, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GODDARD_CASTLE": {"id":"S_GODDARD_CASTLE", "name":"Goddard Castle", "x":147482, "y":-45026, "z":-2084, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DION_CASTLE": {"id":"S_DION_CASTLE", "name":"Dion Castle", "x":22306, "y":156027, "z":-2953, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RUNE_CASTLE": {"id":"S_RUNE_CASTLE", "name":"Rune Castle", "x":19118, "y":-49136, "z":-1266, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_INNADRIL_CASTLE": {"id":"S_INNADRIL_CASTLE", "name":"Innadril Castle", "x":244631, "y":27064, "z":-1057, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GIRAN_CASTLE": {"id":"S_GIRAN_CASTLE", "name":"Giran Castle", "x":112122, "y":144855, "z":-2751, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_OREN_CASTLE": {"id":"S_OREN_CASTLE", "name":"Oren Castle", "x":78116, "y":36961, "z":-2458, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIO_CASTLE": {"id":"S_GLUDIO_CASTLE", "name":"Gludio Castle", "x":-18361, "y":113887, "z":-2767, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SCHUTTGART_CASTLE": {"id":"S_SCHUTTGART_CASTLE", "name":"Schuttgart Castle", "x":77540, "y":-149114, "z":-352, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_SAINTS": {"id":"S_SAINTS", "name":"Saint's", "x":82623, "y":209258, "z":-5439, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DISCIPLES": {"id":"S_DISCIPLES", "name":"Disciple's", "x":171880, "y":-17657, "z":-4901, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MARTYRDOM": {"id":"S_MARTYRDOM", "name":"Martyrdom", "x":117788, "y":132785, "z":-4830, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEVOTION": {"id":"S_DEVOTION", "name":"Devotion", "x":-52850, "y":79044, "z":-4741, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PATRIOTS": {"id":"S_PATRIOTS", "name":"Patriot's", "x":-22219, "y":77315, "z":-5173, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WORSHIP": {"id":"S_WORSHIP", "name":"Worship", "x":110663, "y":174008, "z":-5444, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PILGRIMS": {"id":"S_PILGRIMS", "name":"Pilgrim", "x":45221, "y":124407, "z":-5412, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SACRAFICE": {"id":"S_SACRAFICE", "name":"Sacrifice", "x":-41562, "y":209253, "z":-5086, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_DARK_OMENS": {"id":"S_DARK_OMENS", "name":"Dark Omens", "x":-19979, "y":13528, "z":-4900, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FORBIDDEN_PATH": {"id":"S_FORBIDDEN_PATH", "name":"Forbidden Path", "x":113434, "y":84523, "z":-6540, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WITCH": {"id":"S_WITCH", "name":"Witch", "x":140011, "y":79709, "z":-5428, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_APOSTATE": {"id":"S_APOSTATE", "name":"Apostate", "x":77199, "y":78370, "z":-5114, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BRANDED": {"id":"S_BRANDED", "name":"Branded", "x":45605, "y":170296, "z":-4986, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HERETIC": {"id":"S_HERETIC", "name":"Heretic", "x":42504, "y":143934, "z":-5381, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_FORTRESS_OF_RESISTANCE": {"id":"S_FORTRESS_OF_RESISTANCE", "name":"Fortress of Resistance", "x":45556, "y":109807, "z":-1990, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BANDIT_STRONGHOLD": {"id":"S_BANDIT_STRONGHOLD", "name":"Bandit Stronghold", "x":86575, "y":-19745, "z":-1931, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEVASTATED_CASTLE": {"id":"S_DEVASTATED_CASTLE", "name":"Devastated Castle", "x":178342, "y":-14003, "z":-2255, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WILD_BEAST_RESERVE": {"id":"S_WILD_BEAST_RESERVE", "name":"Wild Beast Reserve", "x":53556, "y":-94063, "z":-1630, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RAINDBOW_SPRINGS_CHATEAU": {"id":"S_RAINDBOW_SPRINGS_CHATEAU", "name":"Rainbow Springs Chateau", "x":140997, "y":-123379, "z":-1906, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FORTRESS_OF_THE_DEAD": {"id":"S_FORTRESS_OF_THE_DEAD", "name":"Fortress of the Dead", "x":57960, "y":-30188, "z":-501, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_EXECUTION_GROUNDS": {"id":"S_EXECUTION_GROUNDS", "name":"Execution Grounds", "x":38291, "y":148029, "z":-3696, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PARTISANS_HIDEAWAY": {"id":"S_PARTISANS_HIDEAWAY", "name":"Partisan's Hideaway", "x":50081, "y":116859, "z":-2176, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRUMA_MARSHLANDS": {"id":"S_CRUMA_MARSHLANDS", "name":"Cruma Marshlands", "x":5106, "y":126916, "z":-3664, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TANOR_CANYON": {"id":"S_TANOR_CANYON", "name":"Tanor Canyon", "x":58316, "y":163851, "z":-2816, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BEE_HIVE": {"id":"S_BEE_HIVE", "name":"Bee Hive", "x":34475, "y":188095, "z":-2976, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DION_HILLS": {"id":"S_DION_HILLS", "name":"Dion Hills", "x":29928, "y":151415, "z":2392, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FLORAN_AGRICULTURAL_AREA": {"id":"S_FLORAN_AGRICULTURAL_AREA", "name":"Floran Agricultural Area", "x":10610, "y":156322, "z":-2472, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PLAINS_OF_DION": {"id":"S_PLAINS_OF_DION", "name":"Plains of Dion", "x":630, "y":179184, "z":-3720, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRUMA_TOWER": {"id":"S_CRUMA_TOWER", "name":"Cruma Tower", "x":17225, "y":114173, "z":-3440, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRUMA_TOWER_1ST": {"id":"S_CRUMA_TOWER_1ST", "name":"Cruma Tower 1st Floor", "x":17724, "y":114004, "z":-11672, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRUMA_TOWER_2ND": {"id":"S_CRUMA_TOWER_2ND", "name":"Cruma Tower 2nd Floor", "x":17730, "y":108301, "z":-9057, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRUMA_TOWER_3RD": {"id":"S_CRUMA_TOWER_3RD", "name":"Cruma Tower 3rd Floor", "x":17719, "y":115430, "z":-6582, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_RUINS_OF_DESPAIR": {"id":"S_RUINS_OF_DESPAIR", "name":"Ruins of Despair", "x":-19120, "y":136816, "z":-3762, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RUINS_OF_AGONY": {"id":"S_RUINS_OF_AGONY", "name":"Ruins of Agony", "x":-42628, "y":119766, "z":-3528, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WASTELAND": {"id":"S_WASTELAND", "name":"Wasteland", "x":-16526, "y":208032, "z":-3664, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ABANDONED_CAMP": {"id":"S_ABANDONED_CAMP", "name":"Abandoned Camp", "x":-49853, "y":147089, "z":-2784, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ORC_BARRACKS": {"id":"S_ORC_BARRACKS", "name":"Orc Barracks", "x":-89763, "y":105359, "z":-3576, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WINDY_HILL": {"id":"S_WINDY_HILL", "name":"Windy Hill", "x":-88539, "y":83389, "z":-2864, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RED_ROCK_RIDGE": {"id":"S_RED_ROCK_RIDGE", "name":"Red Rock Ridge", "x":-44829, "y":188171, "z":-3256, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_LANGK_LIZARDMEN_DWELLINGS": {"id":"S_LANGK_LIZARDMEN_DWELLINGS", "name":"Langk Lizardmen Dwellings", "x":-44763, "y":203497, "z":-3592, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MAILLE_LIZARDMEN_BARRACKS": {"id":"S_MAILLE_LIZARDMEN_BARRACKS", "name":"Maille Lizardmen Barracks", "x":-25283, "y":106820, "z":-3416, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TALKING_ISLAND_NORTHERN_TERRITORY": {"id":"S_TALKING_ISLAND_NORTHERN_TERRITORY", "name":"Talking Island, Northern Territory", "x":-104344, "y":226217, "z":-3616, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TALKING_ISLAND_EASTERN_TERRITORY": {"id":"S_TALKING_ISLAND_EASTERN_TERRITORY", "name":"Talking Island, Eastern Territory", "x":-95336, "y":240478, "z":-3264, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FELLMERE_HARVESTING_GROUNDS": {"id":"S_FELLMERE_HARVESTING_GROUNDS", "name":"Fellmere Harvesting Grounds", "x":-63736, "y":101522, "z":-3552, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WINDMILL_HILL": {"id":"S_WINDMILL_HILL", "name":"Windmill Hill", "x":-75437, "y":168800, "z":-3632, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_EVIL_HUNTING_GROUNDS": {"id":"S_EVIL_HUNTING_GROUNDS", "name":"Evil Hunting Grounds", "x":-6989, "y":109503, "z":-3040, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WINDAWOOD_MANOR": {"id":"S_WINDAWOOD_MANOR", "name":"Windawood Manor", "x":-28327, "y":155125, "z":-3496, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_OL_MAHUM_CHECKPOINT": {"id":"S_OL_MAHUM_CHECKPOINT", "name":"Ol Mahum Checkpoint", "x":-6661, "y":201880, "z":-3632, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_NEUTRAL_ZONE": {"id":"S_THE_NEUTRAL_ZONE", "name":"The Neutral Zone", "x":-10612, "y":75881, "z":-3592, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_ANT_NEST": {"id":"S_THE_ANT_NEST", "name":"The Ant Nest", "x":-9959, "y":176184, "z":-4160, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FORGOTTEN_TEMPLE": {"id":"S_FORGOTTEN_TEMPLE", "name":"Forgotten Temple", "x":-53001, "y":191425, "z":-3568, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ELVEN_RUINS": {"id":"S_ELVEN_RUINS", "name":"Elven Ruins", "x":-112367, "y":234703, "z":-3688, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANT_INCUBATOR": {"id":"S_ANT_INCUBATOR", "name":"Ant Incubator", "x":-26489, "y":195307, "z":-3928, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIN_HARBOR": {"id":"S_GLUDIN_HARBOR", "name":"Gludin Harbor", "x":-91101, "y":150344, "z":-3624, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TALKING_ISLAND_HARBOR": {"id":"S_TALKING_ISLAND_HARBOR", "name":"Talking Island Harbor", "x":-96811, "y":259153, "z":-3616, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIN_ARENA": {"id":"S_GLUDIN_ARENA", "name":"Gludin Arena", "x":-87328, "y":142266, "z":-3640, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FELLMERE_LAKE": {"id":"S_FELLMERE_LAKE", "name":"Fellmere Lake", "x":-57798, "y":127629, "z":-2928, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_OBELISK_OF_VICTORY": {"id":"S_OBELISK_OF_VICTORY", "name":"Obelisk of Victory", "x":-99586, "y":237637, "z":-3568, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SINGING_WATERFALL": {"id":"S_SINGING_WATERFALL", "name":"Singing Waterfall", "x":-111728, "y":244330, "z":-3448, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HELLBOUND_ENTRANCE": {"id":"S_HELLBOUND_ENTRANCE", "name":"Hellbound Entrance", "x":-11802, "y":236360, "z":-3271, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GLUDIO_AIRSHIP_FIELD": {"id":"S_GLUDIO_AIRSHIP_FIELD", "name":"Gludio AirShip Field", "x":-149365, "y":255309, "z":-86, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_BLAZING_SWAMP": {"id":"S_BLAZING_SWAMP", "name":"Blazing Swamp", "x":155310, "y":-16339, "z":-3320, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_FORBIDDEN_GATEWAY": {"id":"S_THE_FORBIDDEN_GATEWAY", "name":"The Forbidden Gateway", "x":188611, "y":20588, "z":-3696, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_ENCHANTED_VALLEY": {"id":"S_THE_ENCHANTED_VALLEY", "name":"The Enchanted Valley", "x":124904, "y":61992, "z":-3973, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_CEMETERY": {"id":"S_THE_CEMETERY", "name":"The Cemetery", "x":167047, "y":20304, "z":-3328, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_FOREST_OF_MIRRORS": {"id":"S_THE_FOREST_OF_MIRRORS", "name":"The Forest of Mirrors", "x":142065, "y":81300, "z":-3000, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANCIENT_BATTLEGROUND": {"id":"S_ANCIENT_BATTLEGROUND", "name":"Ancient Battleground", "x":106517, "y":-2871, "z":-3454, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FORSAKEN_PLAINS": {"id":"S_FORSAKEN_PLAINS", "name":"Forsaken Plains", "x":168217, "y":37990, "z":-4072, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SILENT_VALLEY": {"id":"S_SILENT_VALLEY", "name":"Silent Valley", "x":170838, "y":55776, "z":-5280, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HUNTERS_VALLEY": {"id":"S_HUNTERS_VALLEY", "name":"Hunters Valley", "x":114306, "y":86573, "z":-3112, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PLAINS_OF_GLORY": {"id":"S_PLAINS_OF_GLORY", "name":"Plains of Glory", "x":135580, "y":19467, "z":-3424, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FIELDS_OF_MASSACRE": {"id":"S_FIELDS_OF_MASSACRE", "name":"Fields of Massacre", "x":183543, "y":-14974, "z":-2768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WAR-TORN_PLAINS": {"id":"S_WAR-TORN_PLAINS", "name":"War-Torn Plains", "x":156898, "y":11217, "z":-4032, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ISLE_OF_SOULS": {"id":"S_ISLE_OF_SOULS", "name":"Isle of Souls", "x":-121436, "y":56288, "z":-1586, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MIMIRS_FOREST": {"id":"S_MIMIRS_FOREST", "name":"Mimir's Forest", "x":-103032, "y":46457, "z":-1136, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HILLS_OF_GOLD": {"id":"S_HILLS_OF_GOLD", "name":"Hills of Gold", "x":-116114, "y":87005, "z":-3544, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TOWER_OF_INSOLENCE": {"id":"S_TOWER_OF_INSOLENCE", "name":"Tower of Insolence", "x":114649, "y":11115, "z":-5120, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_GIANTS_CAVE": {"id":"S_THE_GIANTS_CAVE", "name":"The Giant's Cave", "x":181737, "y":46469, "z":-4276, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_NORNILS_GARDEN": {"id":"S_NORNILS_GARDEN", "name":"Nornil's Garden", "x":-84728, "y":60089, "z":-2576, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_NORNILS_CAVE": {"id":"S_NORNILS_CAVE", "name":"Nornil's Cave", "x":-86961, "y":43356, "z":-2680, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_COLISEUM": {"id":"S_COLISEUM", "name":"Coliseum", "x":146440, "y":46723, "z":-3400, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANGHEL_WATERFALL": {"id":"S_ANGHEL_WATERFALL", "name":"Anghel Waterfall", "x":166182, "y":91560, "z":-3168, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_EASTERN_BORDER_OUTPOST": {"id":"S_EASTERN_BORDER_OUTPOST", "name":"Eastern Border Outpost", "x":158141, "y":-24543, "z":-1288, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_NARSELL_LAKE": {"id":"S_NARSELL_LAKE", "name":"Narsell Lake", "x":146440, "y":46723, "z":-3400, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WESTERN_BORDER_OUTPOST": {"id":"S_WESTERN_BORDER_OUTPOST", "name":"Western Border Outpost", "x":112405, "y":-16607, "z":-1864, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CAVE_OF_SOULS": {"id":"S_CAVE_OF_SOULS", "name":"Cave of Souls", "x":-123842, "y":38117, "z":1176, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_VALLEY_OF_HEROES": {"id":"S_VALLEY_OF_HEROES", "name":"Valley of Heroes", "x":-39347, "y":-107274, "z":-2072, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IMMORTAL_PLATEAU_NORTHERN_REGION": {"id":"S_IMMORTAL_PLATEAU_NORTHERN_REGION", "name":"Immortal Plateau, Northern Region", "x":-10983, "y":-117484, "z":-2464, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IMMORTAL_PLATEAU_SOUTHERN_REGION": {"id":"S_IMMORTAL_PLATEAU_SOUTHERN_REGION", "name":"Immortal Plateau, Southern Region", "x":-4190, "y":-80040, "z":-2696, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FROZEN_VALLEY": {"id":"S_FROZEN_VALLEY", "name":"Frozen Valley", "x":112971, "y":-174924, "z":-608, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WESTERN_MINING_ZONE": {"id":"S_WESTERN_MINING_ZONE", "name":"Western Mining Zone", "x":128527, "y":-204036, "z":-3408, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_EASTERN_MINING_ZONE": {"id":"S_EASTERN_MINING_ZONE", "name":"Eastern Mining Zone", "x":175836, "y":-205837, "z":-3384, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PLUNDEROUS_PLAINS": {"id":"S_PLUNDEROUS_PLAINS", "name":"Plunderous Plains", "x":111965, "y":-154172, "z":-1528, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FROZEN_LABYRINTH": {"id":"S_FROZEN_LABYRINTH", "name":"Frozen Labyrinth", "x":113903, "y":-108752, "z":-884, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FREYAS_GARDEN": {"id":"S_FREYAS_GARDEN", "name":"Freya's Garden", "x":102728, "y":-126242, "z":-2840, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PAVEL_RUINS": {"id":"S_PAVEL_RUINS", "name":"Pavel Ruins", "x":91280, "y":-117152, "z":-3952, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEN_OF_EVIL": {"id":"S_DEN_OF_EVIL", "name":"Den of Evil", "x":68693, "y":-110438, "z":-1946, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CRYPTS_OF_DISGRACE": {"id":"S_CRYPTS_OF_DISGRACE", "name":"Crypts of Disgrace", "x":47692, "y":-115745, "z":-3744, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SKY_WAGON_RELIC": {"id":"S_SKY_WAGON_RELIC", "name":"Sky Wagon Relic", "x":121618, "y":-141554, "z":-1496, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CAVE_OF_TRIALS": {"id":"S_CAVE_OF_TRIALS", "name":"Cave of Trials", "x":9340, "y":-112509, "z":-2536, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ABANDONED_COAL_MINES": {"id":"S_ABANDONED_COAL_MINES", "name":"Abandoned Coal Mines", "x":139714, "y":-177456, "z":-1536, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MITHRIL_MINES": {"id":"S_MITHRIL_MINES", "name":"Mithril Mines", "x":171946, "y":-173352, "z":3440, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ARCHAIC_LABORATORY": {"id":"S_ARCHAIC_LABORATORY", "name":"Archaic Laboratory", "x":90418, "y":-107317, "z":-3328, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FROZEN_WATERFALLS": {"id":"S_FROZEN_WATERFALLS", "name":"Frozen Waterfalls", "x":8652, "y":-139941, "z":-1144, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_STRIP_MINE": {"id":"S_STRIP_MINE", "name":"Strip Mine", "x":106561, "y":-173949, "z":-400, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SPINE_MOUNTAINS": {"id":"S_SPINE_MOUNTAINS", "name":"Spine Mountains", "x":147493, "y":-200840, "z":192, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MINING_ZONE_PASSAGE": {"id":"S_MINING_ZONE_PASSAGE", "name":"Mining Zone Passage", "x":113826, "y":-171150, "z":-160, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CARONS_DUNGEON": {"id":"S_CARONS_DUNGEON", "name":"Caron's Dungeon", "x":76021, "y":-110477, "z":-1704, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_VALLEY_OF_THE_LORDS": {"id":"S_VALLEY_OF_THE_LORDS", "name":"Valley of the Lords", "x":32173, "y":-122954, "z":-792, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FROST_LAKE": {"id":"S_FROST_LAKE", "name":"Frost Lake", "x":107577, "y":-122392, "z":-3632, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ICE_MERCHANT_CABIN": {"id":"S_ICE_MERCHANT_CABIN", "name":"Ice Merchant Cabin", "x":113750, "y":-109163, "z":-832, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BRIGAND_STRONGHOLD": {"id":"S_BRIGAND_STRONGHOLD", "name":"Brigand Stronghold", "x":126272, "y":-159336, "z":-1232, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GRAVEROBBER_HIDEOUT": {"id":"S_GRAVEROBBER_HIDEOUT", "name":"Graverobber Hideout", "x":48336, "y":-107734, "z":-1577, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_GARDEN_OF_BEASTS": {"id":"S_GARDEN_OF_BEASTS", "name":"Garden of Beasts", "x":132997, "y":-60608, "z":-2960, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HOT_SPRINGS": {"id":"S_HOT_SPRINGS", "name":"Hot Springs", "x":144880, "y":-113468, "z":-2560, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_KETRA_ORC_OUTPOST": {"id":"S_KETRA_ORC_OUTPOST", "name":"Ketra Orc Outpost", "x":146990, "y":-67128, "z":-3640, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WALL_OF_ARGOS": {"id":"S_WALL_OF_ARGOS", "name":"Wall of Argos", "x":165054, "y":-47861, "z":-3560, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SHRINE_OF_LOYALTY": {"id":"S_SHRINE_OF_LOYALTY", "name":"Shrine of Loyalty", "x":190112, "y":61776, "z":-2944, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_VARKA_SILENOS_BARRACKS": {"id":"S_VARKA_SILENOS_BARRACKS", "name":"Varka Silenos Barracks", "x":125740, "y":-40864, "z":-3736, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEVILS_PASS": {"id":"S_DEVILS_PASS", "name":"Devil's Pass", "x":42504, "y":-61870, "z":-2904, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FORGE_OF_THE_GODS": {"id":"S_FORGE_OF_THE_GODS", "name":"Forge of the Gods", "x":168902, "y":-116703, "z":-2417, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HALL_OF_FLAMES": {"id":"S_HALL_OF_FLAMES", "name":"Hall of Flames", "x":189964, "y":-116820, "z":-1624, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IMPERIAL_TOMB": {"id":"S_IMPERIAL_TOMB", "name":"Imperial Tomb", "x":186699, "y":-75915, "z":-2826, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FOUR_SEPULCHERS": {"id":"S_FOUR_SEPULCHERS", "name":"Four Sepulchers", "x":178127, "y":-84435, "z":-7215, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_KETRA_ORC_VILLAGE": {"id":"S_KETRA_ORC_VILLAGE", "name":"Ketra Orc Village", "x":149548, "y":-82014, "z":-5592, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_VARKA_SILENOS_VILLAGE": {"id":"S_VARKA_SILENOS_VILLAGE", "name":"Varka Silenos Village", "x":108155, "y":-53670, "z":-2472, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HOT_SPRINGS_ARENA": {"id":"S_HOT_SPRINGS_ARENA", "name":"Hot Springs Arena", "x":152180, "y":-126093, "z":-2282, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_DRAGON_VALLEY": {"id":"S_DRAGON_VALLEY", "name":"Dragon Valley", "x":73024, "y":118485, "z":-3720, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEATH_PASS": {"id":"S_DEATH_PASS", "name":"Death Pass", "x":67933, "y":117045, "z":-3544, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BREKAS_STRONGHOLD": {"id":"S_BREKAS_STRONGHOLD", "name":"Breka's Stronghold", "x":85546, "y":131328, "z":-3672, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GORGON_FLOWER_GARDEN": {"id":"S_GORGON_FLOWER_GARDEN", "name":"Gorgon Flower Garden", "x":113553, "y":134813, "z":-3540, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANTHARAS_LAIR": {"id":"S_ANTHARAS_LAIR", "name":"Antharas' Lair", "x":131557, "y":114509, "z":-3712, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEVILS_ISLE": {"id":"S_DEVILS_ISLE", "name":"Devil's Isle", "x":43408, "y":206881, "z":-3752, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HARDINS_ACADEMY": {"id":"S_HARDINS_ACADEMY", "name":"Hardin's Academy", "x":105918, "y":109759, "z":-3170, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GIRAN_HARBOR": {"id":"S_GIRAN_HARBOR", "name":"Giran Harbor", "x":47938, "y":186864, "z":-3420, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GIRAN_ARENA": {"id":"S_GIRAN_ARENA", "name":"Giran Arena", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PIRATE_TUNNEL": {"id":"S_PIRATE_TUNNEL", "name":"Pirate Tunnel", "x":41528, "y":198358, "z":-4648, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANTHARAS_HEART": {"id":"S_ANTHARAS_HEART", "name":"Antharas' Heart", "x":154623, "y":121134, "z":-3809, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_ELVEN_FOREST": {"id":"S_ELVEN_FOREST", "name":"Elven Forest", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SHADOW_OF_THE_MOTHER_TREE": {"id":"S_SHADOW_OF_THE_MOTHER_TREE", "name":"Shadow of the Mother Tree", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_DARK_FOREST": {"id":"S_THE_DARK_FOREST", "name":"The Dark Forest", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SWAMPLAND": {"id":"S_SWAMPLAND", "name":"Swampland", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SEA_OF_SPORES": {"id":"S_SEA_OF_SPORES", "name":"Sea of Spores", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PLAINS_OF_THE_LIZARDMEN": {"id":"S_PLAINS_OF_THE_LIZARDMEN", "name":"Palins of the Lizardmen", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SEL_MAHUM_TRAINING_GROUNDS": {"id":"S_SEL_MAHUM_TRAINING_GROUNDS", "name":"Sel Mahum Training Grounds", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SHILENS_GARDEN": {"id":"S_SHILENS_GARDEN", "name":"Shilens Garden", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BLACK_ROCK_HILL": {"id":"S_BLACK_ROCK_HILL", "name":"Black Rock Hill", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SPIDER_NEST": {"id":"S_SPIDER_NEST", "name":"Spider Nest", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TIMAK_OUTPOST": {"id":"S_TIMAK_OUTPOST", "name":"Timak Outpost", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IVORY_TOWER_CRATER": {"id":"S_IVORY_TOWER_CRATER", "name":"Ivory Tower Crater", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FOREST_OF_EVIL": {"id":"S_FOREST_OF_EVIL", "name":"Forest of Evil", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_OUTLAW_FOREST": {"id":"S_OUTLAW_FOREST", "name":"Outlaw Forest", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ELVEN_FORTRESS": {"id":"S_ELVEN_FORTRESS", "name":"Elven Fortress", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SCHOOL_OF_DARK_ARTS": {"id":"S_SCHOOL_OF_DARK_ARTS", "name":"School of Dark Arts", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IVORY_TOWER": {"id":"S_IVORY_TOWER", "name":"Ivory Tower", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IRIS_LAKE": {"id":"S_IRIS_LAKE", "name":"Iris Lake", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ALTAR_OF_RITES": {"id":"S_ALTAR_OF_RITES", "name":"Altar of Rites", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MISTY_MOUNTAINS": {"id":"S_MISTY_MOUNTAINS", "name":"Misty Mountains", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_STARLIGHT_WATERFALL": {"id":"S_STARLIGHT_WATERFALL", "name":"Starlight Waterfall", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_UNDINE_WATERFALL": {"id":"S_UNDINE_WATERFALL", "name":"Undine Waterfall", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_GODS_FALLS": {"id":"S_THE_GODS_FALLS", "name":"The Gods Falls", "x":73579, "y":142709, "z":-3768, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_FIELD_OF_SILENCE": {"id":"S_FIELD_OF_SILENCE", "name":"Field of Silence", "x":91088, "y":182384, "z":-3192, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FIELD_OF_WHISPERS": {"id":"S_FIELD_OF_WHISPERS", "name":"Field of Whispers", "x":74592, "y":207656, "z":-3032, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ALLIGATOR_ISLAND": {"id":"S_ALLIGATOR_ISLAND", "name":"Alligator Island", "x":115583, "y":192261, "z":-3488, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ALLIGATOR_BEACH": {"id":"S_ALLIGATOR_BEACH", "name":"Alligator Beach", "x":116267, "y":201177, "z":-3432, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ISLE_OF_PRAYER": {"id":"S_ISLE_OF_PRAYER", "name":"Isle of Prayer", "x":145159, "y":189247, "z":-3756, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PARNASSUS": {"id":"S_PARNASSUS", "name":"Parnassus", "x":149363, "y":172341, "z":-946, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CHROMATIC_HIGHLANDS": {"id":"S_CHROMATIC_HIGHLANDS", "name":"Chromatic Highlands", "x":148444, "y":160914, "z":-3102, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA": {"id":"S_GARDEN_OF_EVA", "name":"Garden of Eva", "x":84413, "y":234334, "z":-3656, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA_1ST_FLOOR": {"id":"S_GARDEN_OF_EVA_1ST_FLOOR", "name":"Garden of Eva 1st Floor", "x":80688, "y":245566, "z":-8926, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA_2ND_FLOOR": {"id":"S_GARDEN_OF_EVA_2ND_FLOOR", "name":"Garden of Eva 2nd Floor", "x":80629, "y":246420, "z":-9331, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA_3RD_FLOOR": {"id":"S_GARDEN_OF_EVA_3RD_FLOOR", "name":"Garden of Eva 3rd Floor", "x":87750, "y":252422, "z":-9851, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA_4TH_FLOOR": {"id":"S_GARDEN_OF_EVA_4TH_FLOOR", "name":"Garden of Eva 4th Floor", "x":82506, "y":255978, "z":-10363, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_GARDEN_OF_EVA_5TH_FLOOR": {"id":"S_GARDEN_OF_EVA_5TH_FLOOR", "name":"Garden of Eva 5th Floor", "x":82158, "y":252376, "z":-10592, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TOUR_BOAT_DOCK": {"id":"S_TOUR_BOAT_DOCK", "name":"Tour Boat Dock", "x":111418, "y":225960, "z":-3624, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CORAL_REEF": {"id":"S_CORAL_REEF", "name":"Coral Reef", "x":160074, "y":167893, "z":-3538, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_BEAST_FARM": {"id":"S_BEAST_FARM", "name":"Beast Farm", "x":43805, "y":-88010, "z":-2780, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_VALLEY_OF_SAINTS": {"id":"S_VALLEY_OF_SAINTS", "name":"Valley of Saints", "x":65797, "y":-71510, "z":-3744, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FOREST_OF_THE_DEAD": {"id":"S_FOREST_OF_THE_DEAD", "name":"Forest of the Dead", "x":52107, "y":-54328, "z":-3158, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SWAMP_OF_SCREAMS": {"id":"S_SWAMP_OF_SCREAMS", "name":"Swamp of Screams", "x":69340, "y":-50203, "z":-3314, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MONASTERY_OF_SILENCE": {"id":"S_MONASTERY_OF_SILENCE", "name":"Monastery of Silence", "x":106414, "y":-87799, "z":-2949, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_THE_PAGAN_TEMPLE": {"id":"S_THE_PAGAN_TEMPLE", "name":"The Pagan Temple", "x":35630, "y":-49748, "z":-760, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_STAKATO_NEST": {"id":"S_STAKATO_NEST", "name":"Stakato Nest", "x":88969, "y":-45307, "z":-2112, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CURSED_VILLAGE": {"id":"S_CURSED_VILLAGE", "name":"Cursed Village", "x":57670, "y":-41672, "z":-3154, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_RUNE_HARBOR": {"id":"S_RUNE_HARBOR", "name":"Rune Harbor", "x":36839, "y":-38435, "z":-3640, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_PRIMEVAL_ISLE_WHARF": {"id":"S_PRIMEVAL_ISLE_WHARF", "name":"Primeval Isle Wharf", "x":10448, "y":-24960, "z":-3664, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WINDTAIL_WATERFALL": {"id":"S_WINDTAIL_WATERFALL", "name":"Windtail Waterfall", "x":40723, "y":-94881, "z":-2096, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_AARU_FORT": {"id":"S_AARU_FORT", "name":"Aaru", "x":72889, "y":188048, "z":-2580, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ANTHARAS_FORT": {"id":"S_ANTHARAS_FORT", "name":"Antharas'", "x":77910, "y":89232, "z":-2883, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_ARCHAIC_FORT": {"id":"S_ARCHAIC_FORT", "name":"Archaic ", "x":111798, "y":-141743, "z":-2927, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BAYOU_FORT": {"id":"S_BAYOU_FORT", "name":"Bayou", "x":189897, "y":36705, "z":-3407, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_BORDERLAND_FORT": {"id":"S_BORDERLAND_FORT", "name":"Borderland", "x":157008, "y":-68935, "z":-2861, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_CLOUD_MOUNTAIN_FORT": {"id":"S_CLOUD_MOUNTAIN_FORT", "name":"Cloud Mountain", "x":-54316, "y":89187, "z":-2819, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DEMON_FORT": {"id":"S_DEMON_FORT", "name":"Demon", "x":98822, "y":-56465, "z":-649, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DRAGONSPINE_FORT": {"id":"S_DRAGONSPINE_FORT", "name":"Dragonspine", "x":10527, "y":96849, "z":-3424, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_FLORAN_FORT": {"id":"S_FLORAN_FORT", "name":"Floran", "x":7690, "y":150721, "z":-2887, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HIVE_FORT": {"id":"S_HIVE_FORT", "name":"Hive", "x":15447, "y":186169, "z":-2921, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_HUNTERS_FORT": {"id":"S_HUNTERS_FORT", "name":"Hunter's", "x":124188, "y":93295, "z":-2142, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_IVORY_FORT": {"id":"S_IVORY_FORT", "name":"Ivory", "x":71419, "y":6187, "z":-3036, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_MONASTIC_FORT": {"id":"S_MONASTIC_FORT", "name":"Monastic", "x":71894, "y":-92615, "z":-1420, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_NARSELL_FORT": {"id":"S_NARSELL_FORT", "name":"Narsell", "x":156707, "y":53966, "z":-3251, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SHANTY_FORT": {"id":"S_SHANTY_FORT", "name":"Shanty", "x":-55004, "y":157132, "z":-2050, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SOUTHERN_FORT": {"id":"S_SOUTHERN_FORT", "name":"Southern", "x":-25348, "y":219856, "z":-3249, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SWAMP_FORT": {"id":"S_SWAMP_FORT", "name":"Swamp", "x":68731, "y":-63848, "z":-2783, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_TANOR_FORT": {"id":"S_TANOR_FORT", "name":"Tanor", "x":58948, "y":137927, "z":-1752, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_VALLEY_FORT": {"id":"S_VALLEY_FORT", "name":"Valley", "x":126064, "y":120508, "z":-2583, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WESTERN_FORT": {"id":"S_WESTERN_FORT", "name":"Western", "x":112350, "y":-17183, "z":-992, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_WHITE_SANDS_FORT": {"id":"S_WHITE_SANDS_FORT", "name":"White Sands", "x":116400, "y":203804, "z":-3331, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_SEED_OF_DESTRUCTION": {"id":"S_SEED_OF_DESTRUCTION", "name":"Seed of Destruction", "x":-248140, "y":250678, "z":4331, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SEED_OF_INFINITY": {"id":"S_SEED_OF_INFINITY", "name":"Seed of Infinity", "x":-212843, "y":209695, "z":4280, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_SEED_OF_ANNIHILATION": {"id":"S_SEED_OF_ANNIHILATION", "name":"Seed of Annihilation", "x":-178480, "y":153561, "z":2471, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + "S_DARKCLOUD_MANSION": {"id":"S_DARKCLOUD_MANSION", "name":"Darkcloud Mansion", "x":140007, "y":150467, "z":-3112, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]}, + + "S_FANTASY_ISLAND": {"id":"S_FANTASY_ISLAND", "name":"Fantasy Island", "x":-59103, "y":-56895, "z":-2038, "heading":0, "randomOffset":0, "instance":"", "items":[{"id":57, "amount":100}]} + }, + + "groupTeleports": { + }, + + "soloTeleportCategories": { + "STC_TOWN_AREAS": { + "id":"STC_TOWN_AREAS", + "name":"Town Areas", + "soloTeleports": [ + "S_GIRAN", "S_GODDARD", "S_DION", "S_GLUDIO", "S_SCHUTTGART", "S_HUNTERS", "S_ADEN", "S_RUNE", "S_OREN", + "S_GLUDIN", "S_HEINE", "S_FLORAN", "S_HUMAN", "S_ORC", "S_ELVEN", "S_DWARVEN", "S_DARK_ELVEN", + "S_KAMAEL" + ] + }, + "STC_CASTLE_AREAS": { + "id":"STC_CASTLE_AREAS", + "name":"Castle Areas", + "soloTeleports": [ + "S_ADEN_CASTLE", "S_GODDARD_CASTLE", "S_DION_CASTLE", "S_RUNE_CASTLE", "S_INNADRIL_CASTLE", + "S_GIRAN_CASTLE", "S_OREN_CASTLE", "S_GLUDIO_CASTLE", "S_SCHUTTGART_CASTLE" + ] + }, + "STC_NECROPOLIS": { + "id":"STC_NECROPOLIS", + "name":"Necropolis", + "soloTeleports": [ + "S_SAINTS", "S_DISCIPLES", "S_MARTYRDOM", "S_DEVOTION", "S_PATRIOTS", "S_WORSHIP", "S_PILGRIMS", + "S_SACRAFICE" + ] + }, + "STC_CATACOMBS": { + "id":"STC_CATACOMBS", + "name":"Catacombs", + "soloTeleports": ["S_DARK_OMENS", "S_FORBIDDEN_PATH", "S_WITCH", "S_APOSTATE", "S_BRANDED", "S_HERETIC"] + }, + "STC_CONQUERABLE_CLAN_HALLS": { + "id":"STC_CONQUERABLE_CLAN_HALLS", + "name":"Conquerable Clan Halls", + "soloTeleports": [ + "S_FORTRESS_OF_RESISTANCE", "S_BANDIT_STRONGHOLD", "S_DEVASTATED_CASTLE", "S_WILD_BEAST_RESERVE", + "S_RAINDBOW_SPRINGS_CHATEAU", "S_FORTRESS_OF_THE_DEAD" + ] + }, + "STC_WORLD_AREAS_DION": { + "id":"STC_WORLD_AREAS_DION", + "name":"Dion Territory", + "soloTeleports": [ + "S_EXECUTION_GROUNDS", "S_PARTISANS_HIDEAWAY", "S_CRUMA_MARSHLANDS", "S_TANOR_CANYON", "S_BEE_HIVE", + "S_DION_HILLS", "S_FLORAN_AGRICULTURAL_AREA", "S_PLAINS_OF_DION", "S_CRUMA_TOWER", "S_CRUMA_TOWER_1ST", + "S_CRUMA_TOWER_2ND", "S_CRUMA_TOWER_3RD" + ] + }, + "STC_WORLD_AREAS_GLUDIO": { + "id":"STC_WORLD_AREAS_GLUDIO", + "name":"Gludio Territory", + "soloTeleports": [ + "S_RUINS_OF_DESPAIR", "S_RUINS_OF_AGONY", "S_WASTELAND", "S_ABANDONED_CAMP", "S_ORC_BARRACKS", + "S_WINDY_HILL", "S_RED_ROCK_RIDGE", "S_LANGK_LIZARDMEN_DWELLINGS", "S_MAILLE_LIZARDMEN_BARRACKS", + "S_TALKING_ISLAND_NORTHERN_TERRITORY", "S_TALKING_ISLAND_EASTERN_TERRITORY", + "S_FELLMERE_HARVESTING_GROUNDS", "S_WINDMILL_HILL", "S_EVIL_HUNTING_GROUNDS", "S_WINDAWOOD_MANOR", + "S_OL_MAHUM_CHECKPOINT", "S_THE_NEUTRAL_ZONE", "S_THE_ANT_NEST", "S_FORGOTTEN_TEMPLE", "S_ELVEN_RUINS", + "S_ANT_INCUBATOR", "S_GLUDIN_HARBOR", "S_TALKING_ISLAND_HARBOR", "S_GLUDIN_ARENA", "S_FELLMERE_LAKE", + "S_OBELISK_OF_VICTORY", "S_SINGING_WATERFALL", "S_HELLBOUND_ENTRANCE", "S_GLUDIO_AIRSHIP_FIELD" + ] + }, + "STC_WORLD_AREAS_ADEN": { + "id":"STC_WORLD_AREAS_ADEN", + "name":"Aden Territory", + "soloTeleports": [ + "S_BLAZING_SWAMP", "S_THE_FORBIDDEN_GATEWAY", "S_THE_ENCHANTED_VALLEY", "S_THE_CEMETERY", + "S_THE_FOREST_OF_MIRRORS", "S_ANCIENT_BATTLEGROUND", "S_FORSAKEN_PLAINS", "S_SILENT_VALLEY", + "S_HUNTERS_VALLEY", "S_PLAINS_OF_GLORY", "S_FIELDS_OF_MASSACRE", "S_WAR-TORN_PLAINS", "S_ISLE_OF_SOULS", + "S_MIMIRS_FOREST", "S_HILLS_OF_GOLD", "S_TOWER_OF_INSOLENCE", "S_THE_GIANTS_CAVE", + "S_NORNILS_GARDEN", "S_NORNILS_CAVE", "S_COLISEUM", "S_ANGHEL_WATERFALL", "S_EASTERN_BORDER_OUTPOST", + "S_NARSELL_LAKE", "S_WESTERN_BORDER_OUTPOST", "S_CAVE_OF_SOULS" + ] + }, + "STC_WORLD_AREAS_SCHUTTGART": { + "id":"STC_WORLD_AREAS_SCHUTTGART", + "name":"Schuttgart Territory", + "soloTeleports": [ + "S_VALLEY_OF_HEROES", "S_IMMORTAL_PLATEAU_NORTHERN_REGION", "S_IMMORTAL_PLATEAU_SOUTHERN_REGION", + "S_FROZEN_VALLEY", "S_WESTERN_MINING_ZONE", "S_EASTERN_MINING_ZONE", "S_PLUNDEROUS_PLAINS", + "S_FROZEN_LABYRINTH", "S_FREYAS_GARDEN", "S_PAVEL_RUINS", "S_DEN_OF_EVIL", "S_CRYPTS_OF_DISGRACE", + "S_SKY_WAGON_RELIC", "S_CAVE_OF_TRIALS", "S_ABANDONED_COAL_MINES", "S_MITHRIL_MINES", + "S_ARCHAIC_LABORATORY", "S_FROZEN_WATERFALLS", "S_STRIP_MINE", "S_SPINE_MOUNTAINS", + "S_MINING_ZONE_PASSAGE", "S_CARONS_DUNGEON", "S_VALLEY_OF_THE_LORDS", "S_FROST_LAKE", + "S_ICE_MERCHANT_CABIN", "S_BRIGAND_STRONGHOLD", "S_GRAVEROBBER_HIDEOUT" + ] + }, + "STC_WORLD_AREAS_GODDARD": { + "id":"STC_WORLD_AREAS_GODDARD", + "name":"Goddard Territory", + "soloTeleports": [ + "S_GARDEN_OF_BEASTS", "S_HOT_SPRINGS", "S_KETRA_ORC_OUTPOST", "S_WALL_OF_ARGOS", "S_SHRINE_OF_LOYALTY", + "S_VARKA_SILENOS_BARRACKS", "S_DEVILS_PASS", "S_FORGE_OF_THE_GODS", "S_HALL_OF_FLAMES", + "S_IMPERIAL_TOMB", "S_FOUR_SEPULCHERS", "S_KETRA_ORC_VILLAGE", "S_VARKA_SILENOS_VILLAGE", + "S_HOT_SPRINGS_ARENA" + ] + }, + "STC_WORLD_AREAS_GIRAN": { + "id":"STC_WORLD_AREAS_GIRAN", + "name":"Giran Territory", + "soloTeleports": [ + "S_DRAGON_VALLEY", "S_DEATH_PASS", "S_BREKAS_STRONGHOLD", "S_GORGON_FLOWER_GARDEN", "S_ANTHARAS_LAIR", + "S_DEVILS_ISLE", "S_HARDINS_ACADEMY", "S_GIRAN_HARBOR", "S_GIRAN_ARENA", "S_PIRATE_TUNNEL", + "S_ANTHARAS_HEART" + ] + }, + "STC_WORLD_AREAS_OREN": { + "id":"STC_WORLD_AREAS_OREN", + "name":"Oren Territory", + "soloTeleports": [ + "S_ELVEN_FOREST", "S_SHADOW_OF_THE_MOTHER_TREE", "S_THE_DARK_FOREST", "S_SWAMPLAND", "S_SEA_OF_SPORES", + "S_PLAINS_OF_THE_LIZARDMEN", "S_SEL_MAHUM_TRAINING_GROUNDS", "S_SHILENS_GARDEN", "S_BLACK_ROCK_HILL", + "S_SPIDER_NEST", "S_TIMAK_OUTPOST", "S_IVORY_TOWER_CRATER", "S_FOREST_OF_EVIL", "S_OUTLAW_FOREST", + "S_ELVEN_FORTRESS", "S_SCHOOL_OF_DARK_ARTS", "S_IVORY_TOWER", "S_IRIS_LAKE", "S_ALTAR_OF_RITES", + "S_MISTY_MOUNTAINS", "S_STARLIGHT_WATERFALL", "S_UNDINE_WATERFALL", "S_THE_GODS_FALLS" + ] + }, + "STC_WORLD_AREAS_INNADRIL": { + "id":"STC_WORLD_AREAS_INNADRIL", + "name":"Innadril Territory", + "soloTeleports": [ + "S_FIELD_OF_SILENCE", "S_FIELD_OF_WHISPERS", "S_ALLIGATOR_ISLAND", "S_ALLIGATOR_BEACH", "S_ISLE_OF_PRAYER", + "S_PARNASSUS", "S_CHROMATIC_HIGHLANDS", "S_GARDEN_OF_EVA", "S_GARDEN_OF_EVA_1ST_FLOOR", + "S_GARDEN_OF_EVA_2ND_FLOOR", "S_GARDEN_OF_EVA_3RD_FLOOR", "S_GARDEN_OF_EVA_4TH_FLOOR", + "S_GARDEN_OF_EVA_5TH_FLOOR", "S_TOUR_BOAT_DOCK", "S_CORAL_REEF" + ] + }, + "STC_WORLD_AREAS_RUNE": { + "id":"STC_WORLD_AREAS_RUNE", + "name":"Rune Territory", + "soloTeleports": [ + "S_BEAST_FARM", "S_VALLEY_OF_SAINTS", "S_FOREST_OF_THE_DEAD", "S_SWAMP_OF_SCREAMS", "S_MONASTERY_OF_SILENCE", + "S_THE_PAGAN_TEMPLE", "S_STAKATO_NEST", "S_CURSED_VILLAGE", "S_RUNE_HARBOR", "S_PRIMEVAL_ISLE_WHARF", + "S_WINDTAIL_WATERFALL" + ] + }, + "STC_FORTRESS": { + "id":"STC_FORTRESS", + "name":"Fortress", + "soloTeleports": [ + "S_AARU_FORT", "S_ANTHARAS_FORT", "S_ARCHAIC_FORT", "S_BAYOU_FORT", "S_BORDERLAND_FORT", "S_CLOUD_MOUNTAIN_FORT", + "S_DEMON_FORT", "S_DRAGONSPINE_FORT", "S_FLORAN_FORT", "S_HIVE_FORT", "S_HUNTERS_FORT", "S_IVORY_FORT", + "S_MONASTIC_FORT", "S_NARSELL_FORT", "S_SHANTY_FORT", "S_SOUTHERN_FORT", "S_SWAMP_FORT", "S_TANOR_FORT", + "S_VALLEY_FORT", "S_WESTERN_FORT", "S_WHITE_SANDS_FORT" + ] + }, + "STC_INSTANCES": { + "id":"STC_INSTANCES", + "name":"Instances", + "soloTeleports": [ + "S_SEED_OF_DESTRUCTION", "S_SEED_OF_INFINITY", "S_SEED_OF_ANNIHILATION", "S_DARKCLOUD_MANSION" + ] + }, + "STC_OTHER_LOCATIONS": { + "id":"STC_OTHER_LOCATIONS", + "name":"Other Locations", + "soloTeleports": ["S_FANTASY_ISLAND"] + } + }, + + "groupTeleportCategories": { + } +} \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/json/npcs/60002.json b/src/main/resources/data/service/teleporter/json/npcs/60002.json new file mode 100644 index 0000000000000000000000000000000000000000..70efaec188d8f1979599500f08b78560903e52e6 --- /dev/null +++ b/src/main/resources/data/service/teleporter/json/npcs/60002.json @@ -0,0 +1,14 @@ +{ + "npcId":60002, + "directFirstTalk":true, + "dialogType":"NPC", + "htmlFolder":"npc", + + "soloTeleports": [], + "partyTeleports": [], + "commandChannelTeleports": [], + + "soloTeleportCategories": ["STC_TOWN_AREAS", "STC_CASTLE_AREAS", "STC_NECROPOLIS", "STC_CATACOMBS", "STC_CONQUERABLE_CLAN_HALLS", "STC_WORLD_AREAS_DION", "STC_WORLD_AREAS_GLUDIO", "STC_WORLD_AREAS_ADEN", "STC_WORLD_AREAS_SCHUTTGART", "STC_WORLD_AREAS_GODDARD", "STC_WORLD_AREAS_GIRAN", "STC_WORLD_AREAS_OREN", "STC_WORLD_AREAS_INNADRIL", "STC_WORLD_AREAS_RUNE", "STC_FORTRESS", "STC_INSTANCES", "STC_OTHER_LOCATIONS"], + "partyTeleportCategories": [], + "commandChannelTeleportCategories": [] +} \ No newline at end of file diff --git a/src/main/resources/data/service/teleporter/json/voiced.json b/src/main/resources/data/service/teleporter/json/voiced.json new file mode 100644 index 0000000000000000000000000000000000000000..fcdc7ff36482eb0222b0e1a26e4c3fa40e761e24 --- /dev/null +++ b/src/main/resources/data/service/teleporter/json/voiced.json @@ -0,0 +1,12 @@ +{ + "dialogType":"NPC", + "htmlFolder":"npc", + + "soloTeleports": [], + "partyTeleports": [], + "commandChannelTeleports": [], + + "soloTeleportCategories": ["STC_TOWN_AREAS", "STC_CASTLE_AREAS", "STC_NECROPOLIS", "STC_CATACOMBS", "STC_CONQUERABLE_CLAN_HALLS", "STC_WORLD_AREAS_DION", "STC_WORLD_AREAS_GLUDIO", "STC_WORLD_AREAS_ADEN", "STC_WORLD_AREAS_SCHUTTGART", "STC_WORLD_AREAS_GODDARD", "STC_WORLD_AREAS_GIRAN", "STC_WORLD_AREAS_OREN", "STC_WORLD_AREAS_INNADRIL", "STC_WORLD_AREAS_RUNE", "STC_FORTRESS", "STC_INSTANCES", "STC_OTHER_LOCATIONS"], + "partyTeleportCategories": [], + "commandChannelTeleportCategories": [] +} \ No newline at end of file diff --git a/src/main/resources/data/stats/npcs/custom/custom_teleporterservice.xml b/src/main/resources/data/stats/npcs/custom/custom_teleporterservice.xml new file mode 100644 index 0000000000000000000000000000000000000000..b5d2a8f2845920c9fc4e0eeaa54d4f2d34f64bcd --- /dev/null +++ b/src/main/resources/data/stats/npcs/custom/custom_teleporterservice.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../xsd/npcs.xsd"> + <npc id="60002" displayId="32226" name="Selanta" usingServerSideName="true" title="Teleporter" usingServerSideTitle="true" type="L2Npc"> + <collision> + <radius normal="11" /> + <height normal="22.25" /> + </collision> + </npc> +</list> \ No newline at end of file