diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index cad6c0eb3..7e04ff02c 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -868,6 +868,20 @@ public class NPCCommands { } } + @Command( + aliases = { "npc" }, + usage = "deselect", + desc = "Deselect currently selected NPC", + modifiers = { "deselect", "desel" }, + min = 1, + max = 1, + permission = "citizens.npc.deselect") + @Requirements + public void deselect(CommandContext args, final CommandSender sender, final NPC npc) { + selector.deselect(sender); + Messaging.sendTr(sender, Messages.DESELECTED_NPC); + } + @Command( aliases = { "npc" }, usage = "despawn (id)", @@ -1553,7 +1567,7 @@ public class NPCCommands { } if (range != null) { trait.setRange(range); - Messaging.sendTr(sender, Messages.LOOKCLOSE_RANGE_SET, range); + Messaging.sendTr(sender, Messages.LOOKCLOSE_RANGE_SET, npc.getName(), range); toggle = false; } if (args.hasFlag('r')) { diff --git a/main/src/main/java/net/citizensnpcs/npc/NPCSelector.java b/main/src/main/java/net/citizensnpcs/npc/NPCSelector.java index 8228faddd..bc19c6114 100644 --- a/main/src/main/java/net/citizensnpcs/npc/NPCSelector.java +++ b/main/src/main/java/net/citizensnpcs/npc/NPCSelector.java @@ -41,13 +41,22 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect } + @Override + public void deselect(CommandSender sender) { + if (sender instanceof ConsoleCommandSender) { + consoleSelectedNPC = null; + } else if (sender instanceof Metadatable) { + removeMetadata((Metadatable) sender); + } + } + @Override public NPC getSelected(CommandSender sender) { CitizensGetSelectedNPCEvent event = new CitizensGetSelectedNPCEvent(sender); Bukkit.getPluginManager().callEvent(event); - if (event.getSelected() != null) { + if (event.getSelected() != null) return event.getSelected(); - } + if (sender instanceof Player) { return getSelectedFromMetadatable((Player) sender); } else if (sender instanceof BlockCommandSender) { @@ -72,7 +81,7 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect } @EventHandler - public void onNPCRemove(NPCRemoveEvent event) { + private void onNPCRemove(NPCRemoveEvent event) { NPC npc = event.getNPC(); List selectors = npc.data().get("selectors"); if (selectors == null) @@ -96,7 +105,7 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect } @EventHandler - public void onNPCRightClick(NPCRightClickEvent event) { + private void onNPCRightClick(NPCRightClickEvent event) { Player player = event.getClicker(); NPC npc = event.getNPC(); List selected = player.getMetadata("selected"); diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java index 2215f9224..ce891927b 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java @@ -47,8 +47,10 @@ public class CitizensNavigator implements Navigator, Runnable { private Location activeTicket; private final NavigatorParameters defaultParams = new NavigatorParameters().baseSpeed(UNINITIALISED_SPEED) .range(Setting.DEFAULT_PATHFINDING_RANGE.asFloat()).debug(Setting.DEBUG_PATHFINDING.asBoolean()) - .defaultAttackStrategy(MCTargetStrategy.DEFAULT_ATTACK_STRATEGY) - .attackRange(Setting.NPC_ATTACK_DISTANCE.asDouble()) + .defaultAttackStrategy((attacker, target) -> { + NMS.attack(attacker, target); + return false; + }).attackRange(Setting.NPC_ATTACK_DISTANCE.asDouble()) .updatePathRate(Setting.DEFAULT_PATHFINDER_UPDATE_PATH_RATE.asTicks()) .distanceMargin(Setting.DEFAULT_DISTANCE_MARGIN.asDouble()) .pathDistanceMargin(Setting.DEFAULT_PATH_DISTANCE_MARGIN.asDouble()) diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java index bf47b58af..3d9ed26da 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java @@ -42,7 +42,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { private boolean canAttack() { BoundingBox handleBB = NMS.getBoundingBox(handle), targetBB = NMS.getBoundingBox(target); return attackTicks <= 0 && (handleBB.maxY > targetBB.minY && handleBB.minY < targetBB.maxY) - && closeEnough(distance()) && hasLineOfSight(); + && distance() <= parameters.attackRange() && ((LivingEntity) handle).hasLineOfSight(target); } @Override @@ -50,10 +50,6 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { cancelReason = null; } - private boolean closeEnough(double distance) { - return distance <= parameters.attackRange(); - } - private double distance() { return handle.getLocation().distance(target.getLocation()); } @@ -88,10 +84,6 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { return TargetType.ENTITY; } - private boolean hasLineOfSight() { - return ((LivingEntity) handle).hasLineOfSight(target); - } - @Override public boolean isAggressive() { return aggro; @@ -113,16 +105,19 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { cancelReason = CancelReason.TARGET_DIED; return true; } + if (target.getWorld() != handle.getWorld()) { cancelReason = CancelReason.TARGET_MOVED_WORLD; return true; } - if (cancelReason != null) { + + if (cancelReason != null) return true; - } + if (parameters.straightLineTargetingDistance() > 0 && !(targetNavigator instanceof StraightLineTargeter)) { targetNavigator = new StraightLineTargeter(targetNavigator); } + if (!aggro && distance() <= parameters.distanceMargin()) { stop(); return false; @@ -130,6 +125,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { targetNavigator.setPath(); updateCounter = 0; } + targetNavigator.update(); NMS.look(handle, target); @@ -141,6 +137,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { } attackTicks = parameters.attackDelayTicks(); } + if (attackTicks > 0) { attackTicks--; } @@ -239,9 +236,9 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { @Override public void setPath() { Location location = parameters.entityTargetLocationMapper().apply(target); - if (location == null) { + if (location == null) throw new IllegalStateException("mapper should not return null"); - } + if (parameters.straightLineTargetingDistance() > 0) { double distance = npc.getStoredLocation().distance(location); if (distance < parameters.straightLineTargetingDistance()) { @@ -251,6 +248,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { return; } } + active = null; fallback.setPath(); } @@ -284,12 +282,4 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { void update(); } - - static final AttackStrategy DEFAULT_ATTACK_STRATEGY = new AttackStrategy() { - @Override - public boolean handle(LivingEntity attacker, LivingEntity bukkitTarget) { - NMS.attack(attacker, bukkitTarget); - return false; - } - }; } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java index 4de2eac90..d6cd45a98 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java @@ -58,18 +58,18 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy { @Override public boolean update() { - if (getCancelReason() != null || npc.getStoredLocation().getWorld() != destination.getWorld()) { + if (getCancelReason() != null || npc.getStoredLocation().getWorld() != destination.getWorld()) return true; - } + Location currLoc = npc.getEntity().getLocation(); - if (currLoc.distance(destination) <= params.distanceMargin()) { + if (currLoc.distance(destination) <= params.distanceMargin()) return true; - } + if (target != null) { destination = params.entityTargetLocationMapper().apply(target); } - Vector destVector = npc.getStoredLocation().toVector() - .add(destination.toVector().subtract(npc.getStoredLocation().toVector()).normalize()); + + Vector destVector = currLoc.toVector().add(destination.toVector().subtract(currLoc.toVector()).normalize()); Location destLoc = destVector.toLocation(destination.getWorld()); if (!npc.isFlyable() && destVector.getBlockY() > currLoc.getBlockY()) { Block block = destLoc.getBlock(); @@ -84,6 +84,7 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy { destLoc = block.getLocation(); destVector = destLoc.toVector(); } + double dX = destVector.getX() - currLoc.getX(); double dZ = destVector.getZ() - currLoc.getZ(); double dY = destVector.getY() - currLoc.getY(); @@ -104,6 +105,7 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy { while (normalisedTargetYaw >= 180.0F) { normalisedTargetYaw -= 360.0F; } + while (normalisedTargetYaw < -180.0F) { normalisedTargetYaw += 360.0F; } diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index bb4276978..88d8bf343 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -193,7 +193,7 @@ public class HologramTrait extends Trait { * @return the hologram lines, in bottom-up order */ public List getLines() { - return Lists.transform(lines, (l) -> l.text); + return Lists.transform(lines, l -> l.text); } private double getMaxHeight() { diff --git a/main/src/main/java/net/citizensnpcs/trait/LookClose.java b/main/src/main/java/net/citizensnpcs/trait/LookClose.java index 1fad968b6..f813261a8 100644 --- a/main/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/main/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -366,8 +366,8 @@ public class LookClose extends Trait implements Toggleable { /** * Sets the maximum range in blocks to look at other Entities */ - public void setRange(double d) { - this.range = d; + public void setRange(double range) { + this.range = range; } /** diff --git a/main/src/main/java/net/citizensnpcs/trait/Poses.java b/main/src/main/java/net/citizensnpcs/trait/Poses.java index 3c634e2a0..06c03ad01 100644 --- a/main/src/main/java/net/citizensnpcs/trait/Poses.java +++ b/main/src/main/java/net/citizensnpcs/trait/Poses.java @@ -19,7 +19,6 @@ import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.api.util.Paginator; import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Pose; -import net.citizensnpcs.util.Util; /** * Persists named {@link Pose}s. @@ -64,7 +63,7 @@ public class Poses extends Trait { if (!npc.isSpawned()) { npc.spawn(npc.getStoredLocation(), SpawnReason.COMMAND); } - Util.setRotation(npc.getEntity(), yaw, pitch); + npc.getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToHave(yaw, pitch); } /** diff --git a/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java index 24ea60ae6..31457db54 100644 --- a/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java +++ b/main/src/main/java/net/citizensnpcs/trait/waypoint/LinearWaypointProvider.java @@ -5,8 +5,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -30,8 +28,6 @@ import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.ai.Goal; import net.citizensnpcs.api.ai.GoalSelector; import net.citizensnpcs.api.ai.Navigator; -import net.citizensnpcs.api.ai.event.CancelReason; -import net.citizensnpcs.api.ai.event.NavigatorCallback; import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer; import net.citizensnpcs.api.command.CommandContext; import net.citizensnpcs.api.command.CommandMessages; @@ -596,21 +592,21 @@ public class LinearWaypointProvider implements EnumerableWaypointProvider { @Override public boolean shouldExecute(final GoalSelector selector) { - if (paused || currentDestination != null || !npc.isSpawned() || getNavigator().isNavigating()) { + if (paused || currentDestination != null || !npc.isSpawned() || getNavigator().isNavigating()) return false; - } + ensureItr(); boolean shouldExecute = itr.hasNext(); - if (!shouldExecute) { + if (!shouldExecute) return false; - } + this.selector = selector; Waypoint next = itr.next(); final Location npcLoc = npc.getEntity().getLocation(cachedLocation); if (npcLoc.getWorld() != next.getLocation().getWorld() - || npcLoc.distance(next.getLocation()) < npc.getNavigator().getLocalParameters().distanceMargin()) { + || npcLoc.distance(next.getLocation()) <= npc.getNavigator().getLocalParameters().distanceMargin()) return false; - } + currentDestination = next; if (cachePaths) { SourceDestinationPair key = new SourceDestinationPair(npcLoc, currentDestination); @@ -623,26 +619,26 @@ public class LinearWaypointProvider implements EnumerableWaypointProvider { } } } + if (!getNavigator().isNavigating()) { getNavigator().setTarget(currentDestination.getLocation()); } - getNavigator().getLocalParameters().addSingleUseCallback(new NavigatorCallback() { - @Override - public void onCompletion(@Nullable CancelReason cancelReason) { - if (npc.isSpawned() && currentDestination != null - && Util.locationWithinRange(npc.getStoredLocation(), currentDestination.getLocation(), - Setting.DEFAULT_DISTANCE_MARGIN.asDouble() + 1)) { - currentDestination.onReach(npc); - if (cachePaths && cancelReason == null) { - Iterable path = getNavigator().getPathStrategy().getPath(); - if (Iterables.size(path) > 0) { - cachedPaths.put(new SourceDestinationPair(npcLoc, currentDestination), path); - } + + double margin = getNavigator().getLocalParameters().distanceMargin(); + getNavigator().getLocalParameters().addSingleUseCallback(cancelReason -> { + if (npc.isSpawned() && currentDestination != null && Util.locationWithinRange(npc.getStoredLocation(), + currentDestination.getLocation(), margin + 1)) { + currentDestination.onReach(npc); + if (cachePaths && cancelReason == null) { + Iterable path = getNavigator().getPathStrategy().getPath(); + if (Iterables.size(path) > 0) { + cachedPaths.put(new SourceDestinationPair(npcLoc, currentDestination), path); } } - selector.finish(); } + selector.finish(); }); + return true; } } @@ -662,12 +658,12 @@ public class LinearWaypointProvider implements EnumerableWaypointProvider { @Override public boolean equals(Object obj) { - if (this == obj) { + if (this == obj) return true; - } - if (obj == null || getClass() != obj.getClass()) { + + if (obj == null || getClass() != obj.getClass()) return false; - } + SourceDestinationPair other = (SourceDestinationPair) obj; if (from == null) { if (other.from != null) { diff --git a/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java index d8ac67e5e..94f34f359 100644 --- a/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java +++ b/main/src/main/java/net/citizensnpcs/trait/waypoint/Waypoint.java @@ -46,7 +46,7 @@ public class Waypoint { } public void describeTriggers(CommandSender sender) { - String base = ""; + String base = " "; if (triggers == null) return; for (int i = 0; i < triggers.size(); i++) { diff --git a/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java index 80857ea94..a7d000338 100644 --- a/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java +++ b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerAddPrompt.java @@ -8,16 +8,9 @@ import org.bukkit.conversations.StringPrompt; import com.google.common.base.Joiner; import net.citizensnpcs.api.util.Messaging; -import net.citizensnpcs.trait.waypoint.WaypointEditor; import net.citizensnpcs.util.Messages; public class TriggerAddPrompt extends StringPrompt { - private final WaypointEditor editor; - - public TriggerAddPrompt(WaypointEditor editor) { - this.editor = editor; - } - @Override public Prompt acceptInput(ConversationContext context, String input) { input = input.toLowerCase().trim(); @@ -30,10 +23,10 @@ public class TriggerAddPrompt extends StringPrompt { split[0] = null; Prompt prompt = WaypointTriggerRegistry.getTriggerPromptFrom(input); String extraInput = Joiner.on(' ').skipNulls().join(split); + context.setSessionData("said", false); if (prompt == null) { Messaging.sendErrorTr((CommandSender) context.getForWhom(), Messages.WAYPOINT_TRIGGER_EDITOR_INVALID_TRIGGER, input); - context.setSessionData("said", false); return this; } else if (extraInput.length() > 0) { WaypointTrigger returned = ((WaypointTriggerPrompt) prompt).createFromShortInput(context, extraInput); diff --git a/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java index 463ff7150..813eda702 100644 --- a/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java +++ b/main/src/main/java/net/citizensnpcs/trait/waypoint/triggers/TriggerEditPrompt.java @@ -39,7 +39,7 @@ public class TriggerEditPrompt extends StringPrompt { } if (input.contains("add")) { context.setSessionData("said", false); - return new TriggerAddPrompt(editor); + return new TriggerAddPrompt(); } return this; } diff --git a/main/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java index f2e033778..9017d5b62 100644 --- a/main/src/main/java/net/citizensnpcs/util/Messages.java +++ b/main/src/main/java/net/citizensnpcs/util/Messages.java @@ -62,17 +62,17 @@ public class Messages { public static final String COMMAND_ADDED = "citizens.commands.npc.command.command-added"; public static final String COMMAND_AGE_HELP = "citizens.commands.npc.age.help"; public static final String COMMAND_COST_SET = "citizens.commands.npc.command.cost-set"; - public static final String COMMAND_INDIVIDUAL_COST_SET = "citizens.commands.npc.command.individual-cost-set"; - public static final String COMMAND_MISSING_COST = "citizens.commands.npc.command.cost-missing"; public static final String COMMAND_DESCRIBE_TEMPLATE = "citizens.commands.npc.command.describe-format"; public static final String COMMAND_EXPERIENCE_COST_SET = "citizens.commands.npc.command.experience-cost-set"; - public static final String COMMAND_INDIVIDUAL_EXPERIENCE_COST_SET = "citizens.commands.npc.command.individual-experience-cost-set"; public static final String COMMAND_HELP_HEADER = "citizens.commands.help.header"; public static final String COMMAND_HIDE_ERROR_MESSAGES_SET = "citizens.commands.npc.command.hide-error-messages-set"; public static final String COMMAND_HIDE_ERROR_MESSAGES_UNSET = "citizens.commands.npc.command.hide-error-messages-unset"; + public static final String COMMAND_INDIVIDUAL_COST_SET = "citizens.commands.npc.command.individual-cost-set"; + public static final String COMMAND_INDIVIDUAL_EXPERIENCE_COST_SET = "citizens.commands.npc.command.individual-experience-cost-set"; public static final String COMMAND_INVALID_MOBTYPE = "citizens.commands.invalid-mobtype"; public static final String COMMAND_LEFT_HAND_HEADER = "citizens.commands.npc.command.left-hand-header"; public static final String COMMAND_MISSING = "citizens.commands.help.command-missing"; + public static final String COMMAND_MISSING_COST = "citizens.commands.npc.command.cost-missing"; public static final String COMMAND_NO_COMMANDS_ADDED = "citizens.commands.npc.command.none-added"; public static final String COMMAND_PAGE_MISSING = "citizens.commands.page-missing"; public static final String COMMAND_REMOVED = "citizens.commands.npc.command.command-removed"; @@ -97,6 +97,7 @@ public class Messages { public static final String DATABASE_CONNECTION_FAILED = "citizens.notifications.database-connection-failed"; public static final String DEFAULT_POSE_SET = "citizens.commands.npc.pose.default-pose-set"; public static final String DELAY_TRIGGER_PROMPT = "citizens.editors.waypoints.triggers.delay.prompt"; + public static final String DESELECTED_NPC = "citizens.commands.npc.deselect"; public static final String ELDER_SET = "citizens.commands.npc.guardian.elder-set"; public static final String ELDER_UNSET = "citizens.commands.npc.guardian.elder-unset"; public static final String ENDERCRYSTAL_NOT_SHOWING_BOTTOM = "citizens.commands.npc.endercrystal.not-showing-bottom"; diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 186bbfb31..a4891d984 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -142,7 +142,9 @@ public class NMS { public static void cancelMoveDestination(Entity entity) { BRIDGE.cancelMoveDestination(entity); - }/* + } + + /* * Yggdrasil's default implementation of this method silently fails instead of throwing * an Exception like it should. */ diff --git a/main/src/main/java/net/citizensnpcs/util/Util.java b/main/src/main/java/net/citizensnpcs/util/Util.java index 05a94e5c3..e89df16b8 100644 --- a/main/src/main/java/net/citizensnpcs/util/Util.java +++ b/main/src/main/java/net/citizensnpcs/util/Util.java @@ -477,13 +477,6 @@ public class Util { } } - /** - * Sets the entity's yaw and pitch directly including head yaw. - */ - public static void setRotation(Entity entity, float yaw, float pitch) { - NMS.look(entity, yaw, pitch); - } - public static void talk(SpeechContext context) { if (context.getTalker() == null) return; diff --git a/main/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties index 23a0f7533..5419cda16 100644 --- a/main/src/main/resources/messages_en.properties +++ b/main/src/main/resources/messages_en.properties @@ -88,6 +88,7 @@ citizens.commands.npc.create.invalid-mobtype=[[{0}]] is not a valid mob type. citizens.commands.npc.create.npc-name-too-long=NPC names cannot be longer than [[{0}]] characters. The name has been shortened. citizens.commands.npc.create.no-player-for-spawn=No player could be found by that name to spawn an NPC at. citizens.commands.npc.despawn.despawned=You despawned [[{0}]]. +citizens.commands.npc.deselect=Deselected NPC. citizens.commands.npc.endercrystal.showing-bottom=[[{0}]] is now showing its base. citizens.commands.npc.endercrystal.not-showing-bottom=[[{0}]] is no longer showing its base. citizens.commands.npc.enderman.angry-set=[[{0}]] is now angry. @@ -440,7 +441,7 @@ citizens.editors.waypoints.triggers.add.invalid-trigger=Couldn''t create a trigg citizens.editors.waypoints.triggers.add.prompt=Enter in a trigger name to add or type [[back]] to return to the edit prompt. Valid trigger names are {0}. citizens.editors.waypoints.triggers.animation.added=Animation [[{0}]] added. citizens.editors.waypoints.triggers.animation.at-set=Animation location set to [[{0}]]. -citizens.editors.waypoints.triggers.list=Current triggers are:{0} +citizens.editors.waypoints.triggers.list=Current triggers are: {0} citizens.editors.waypoints.triggers.command.added=Command [[{0}]] added. citizens.editors.waypoints.triggers.command.prompt=Enter one or more commands (without the leading slash). citizens.editors.waypoints.triggers.animation.prompt=Enter in animations to perform - valid animations are {0}.
[[at (x:y:z:world)]] optionally set a location to perform the animation at.
Type in [[finish]] to finish the animation trigger or [[back]] to return to the previous prompt.