diff --git a/src/main/java/net/citizensnpcs/command/command/EditorCommands.java b/src/main/java/net/citizensnpcs/command/command/EditorCommands.java index 1b4e8c0b2..c6ad6aa20 100644 --- a/src/main/java/net/citizensnpcs/command/command/EditorCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/EditorCommands.java @@ -38,7 +38,7 @@ public class EditorCommands { max = 1, permission = "npc.edit.path") @Requirements(selected = true, ownership = true, excludedTypes = { EntityType.BLAZE, - EntityType.ENDER_DRAGON, EntityType.GHAST, EntityType.SQUID }) + EntityType.ENDER_DRAGON, EntityType.GHAST, EntityType.BAT, EntityType.WITHER, EntityType.SQUID }) public void path(CommandContext args, Player player, NPC npc) { Editor.enterOrLeave(player, npc.getTrait(Waypoints.class).getEditor(player)); } diff --git a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java index 7f8df941e..70652a1db 100644 --- a/src/main/java/net/citizensnpcs/command/command/NPCCommands.java +++ b/src/main/java/net/citizensnpcs/command/command/NPCCommands.java @@ -35,6 +35,7 @@ import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.Poses; import net.citizensnpcs.trait.Powered; +import net.citizensnpcs.trait.SkeletonType; import net.citizensnpcs.trait.SlimeSize; import net.citizensnpcs.trait.VillagerProfession; import net.citizensnpcs.util.Anchor; @@ -318,35 +319,36 @@ public class NPCCommands { } if (args.hasValueFlag("at")) { String[] parts = Iterables.toArray(Splitter.on(':').split(args.getFlag("at")), String.class); - String worldName = sender instanceof Player ? ((Player) sender).getLocation().getWorld() - .getName() : ""; - int x = 0, y = 0, z = 0; - float yaw = 0F, pitch = 0F; - switch (parts.length) { - case 6: - pitch = Float.parseFloat(parts[5]); - case 5: - yaw = Float.parseFloat(parts[4]); - case 4: - worldName = parts[3]; - case 3: - case 2: - case 1: - if (parts.length < 3) + if (parts.length > 0) { + String worldName = sender instanceof Player ? ((Player) sender).getLocation().getWorld() + .getName() : ""; + int x = 0, y = 0, z = 0; + float yaw = 0F, pitch = 0F; + switch (parts.length) { + case 6: + pitch = Float.parseFloat(parts[5]); + case 5: + yaw = Float.parseFloat(parts[4]); + case 4: + worldName = parts[3]; + case 3: + x = Integer.parseInt(parts[0]); + y = Integer.parseInt(parts[1]); + z = Integer.parseInt(parts[2]); + break; + default: throw new CommandException(Messages.INVALID_SPAWN_LOCATION); - x = Integer.parseInt(parts[0]); - y = Integer.parseInt(parts[1]); - z = Integer.parseInt(parts[2]); - break; - default: - break; - case 0: + } + World world = Bukkit.getWorld(worldName); + if (world == null) throw new CommandException(Messages.INVALID_SPAWN_LOCATION); + spawnLoc = new Location(world, x, y, z, yaw, pitch); + } else { + Player search = Bukkit.getPlayerExact(args.getFlag("at")); + if (search == null) + throw new CommandException(Messages.PLAYER_NOT_FOUND_FOR_SPAWN); + spawnLoc = search.getLocation(); } - World world = Bukkit.getWorld(worldName); - if (world == null) - throw new CommandException(Messages.INVALID_SPAWN_LOCATION); - spawnLoc = new Location(world, x, y, z, yaw, pitch); } if (spawnLoc == null) { npc.destroy(); @@ -818,6 +820,21 @@ public class NPCCommands { Messaging.sendTr(sender, Messages.NPC_RENAMED, oldName, newName); } + @Command( + aliases = { "npc" }, + usage = "skeletontype [type]", + desc = "Sets the NPC's skeleton type", + modifiers = { "skeletontype", "sktype" }, + min = 2, + max = 2, + permission = "npc.skeletontype") + @Requirements(selected = true, ownership = true, types = EntityType.SKELETON) + public void skeletonType(CommandContext args, CommandSender sender, NPC npc) { + int type = args.getInteger(1); + npc.getTrait(SkeletonType.class).setType(type); + Messaging.sendTr(sender, Messages.SKELETON_TYPE_SET, npc.getName(), type); + } + @Command( aliases = { "npc" }, usage = "select|sel [id|name] (--r range)", diff --git a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index 513b5f763..bae00d71e 100644 --- a/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ b/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -26,6 +26,7 @@ import net.citizensnpcs.trait.Poses; import net.citizensnpcs.trait.Powered; import net.citizensnpcs.trait.Saddle; import net.citizensnpcs.trait.Sheared; +import net.citizensnpcs.trait.SkeletonType; import net.citizensnpcs.trait.SlimeSize; import net.citizensnpcs.trait.VillagerProfession; import net.citizensnpcs.trait.WoolColor; @@ -41,26 +42,27 @@ public class CitizensTraitFactory implements TraitFactory { public CitizensTraitFactory() { registerTrait(TraitInfo.create(Age.class).withName("age")); - registerTrait(TraitInfo.create(CurrentLocation.class).withName("location")); + registerTrait(TraitInfo.create(Anchors.class).withName("anchors")); + registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour")); + registerTrait(TraitInfo.create(Controllable.class).withName("controllable")); registerTrait(TraitInfo.create(Equipment.class).withName("equipment")); - registerTrait(TraitInfo.create(Inventory.class).withName("inventory")); - registerTrait(TraitInfo.create(LookClose.class).withName("lookclose")); registerTrait(TraitInfo.create(Gravity.class).withName("gravity")); - registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize")); - registerTrait(TraitInfo.create(MobType.class).withName("type")); + registerTrait(TraitInfo.create(Inventory.class).withName("inventory")); + registerTrait(TraitInfo.create(CurrentLocation.class).withName("location")); + registerTrait(TraitInfo.create(LookClose.class).withName("lookclose")); registerTrait(TraitInfo.create(Owner.class).withName("owner")); + registerTrait(TraitInfo.create(Poses.class).withName("poses")); registerTrait(TraitInfo.create(Powered.class).withName("powered")); + registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession")); registerTrait(TraitInfo.create(Saddle.class).withName("saddle")); registerTrait(TraitInfo.create(Sheared.class).withName("sheared")); + registerTrait(TraitInfo.create(SkeletonType.class).withName("skeletontype")); + registerTrait(TraitInfo.create(SlimeSize.class).withName("slimesize")); registerTrait(TraitInfo.create(Spawned.class).withName("spawned")); registerTrait(TraitInfo.create(Text.class).withName("text")); - registerTrait(TraitInfo.create(VillagerProfession.class).withName("profession")); + registerTrait(TraitInfo.create(MobType.class).withName("type")); registerTrait(TraitInfo.create(Waypoints.class).withName("waypoints")); registerTrait(TraitInfo.create(WoolColor.class).withName("woolcolor")); - registerTrait(TraitInfo.create(Controllable.class).withName("controllable")); - registerTrait(TraitInfo.create(Behaviour.class).withName("behaviour")); - registerTrait(TraitInfo.create(Poses.class).withName("poses")); - registerTrait(TraitInfo.create(Anchors.class).withName("anchors")); for (String trait : registered.keySet()) INTERNAL_TRAITS.add(trait); diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensBatNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensBatNPC.java index 8f5cc9c2f..1706fa8c6 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensBatNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensBatNPC.java @@ -54,13 +54,15 @@ public class CitizensBatNPC extends CitizensMobNPC { if (npc != null) { NMS.clearGoals(goalSelector, targetSelector); NMS.setPersistent(this); + f(false); } } @Override public void bi() { - super.bi(); - if (npc != null) + if (npc == null) + super.bi(); + else npc.update(); } @@ -109,8 +111,8 @@ public class CitizensBatNPC extends CitizensMobNPC { @Override public void j_() { - if (npc == null) - super.j_(); + super.j_(); + npc.update(); } } } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java index 9e5793fd4..9e98293b5 100644 --- a/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java +++ b/src/main/java/net/citizensnpcs/npc/entity/CitizensHumanNPC.java @@ -34,7 +34,7 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable { Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { @Override public void run() { - handle.ay = loc.getYaw() % 360; + NMS.setHeadYaw(handle, loc.getYaw() % 360); // set the head yaw in another tick - if done immediately, // minecraft will not update it. boolean removeFromPlayerList = Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean(); @@ -96,6 +96,7 @@ public class CitizensHumanNPC extends CitizensNPC implements Equipable { } } Messaging.sendTr(equipper, Messages.EQUIPMENT_EDITOR_ALL_ITEMS_REMOVED, getName()); + break; default: break; } diff --git a/src/main/java/net/citizensnpcs/trait/Age.java b/src/main/java/net/citizensnpcs/trait/Age.java index 5ede88e62..249ab3484 100644 --- a/src/main/java/net/citizensnpcs/trait/Age.java +++ b/src/main/java/net/citizensnpcs/trait/Age.java @@ -1,6 +1,7 @@ package net.citizensnpcs.trait; import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.util.Messages; @@ -10,7 +11,9 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Ageable; public class Age extends Trait implements Toggleable { + @Persist private int age = 0; + @Persist private boolean locked = true; public Age() { @@ -29,8 +32,6 @@ public class Age extends Trait implements Toggleable { public void load(DataKey key) throws NPCLoadException { if (npc.isSpawned() && !(npc.getBukkitEntity() instanceof Ageable)) throw new NPCLoadException("NPC must be ageable"); - age = key.getInt("age"); - locked = key.getBoolean("locked"); } @Override @@ -48,12 +49,6 @@ public class Age extends Trait implements Toggleable { age = ((Ageable) npc.getBukkitEntity()).getAge(); } - @Override - public void save(DataKey key) { - key.setInt("age", age); - key.setBoolean("locked", locked); - } - public void setAge(int age) { this.age = age; if (isAgeable()) diff --git a/src/main/java/net/citizensnpcs/trait/Controllable.java b/src/main/java/net/citizensnpcs/trait/Controllable.java index aa00f2895..b144ca186 100644 --- a/src/main/java/net/citizensnpcs/trait/Controllable.java +++ b/src/main/java/net/citizensnpcs/trait/Controllable.java @@ -5,6 +5,7 @@ import java.util.Map; import net.citizensnpcs.api.event.NPCRightClickEvent; import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.command.CommandConfigurable; @@ -27,6 +28,7 @@ import com.google.common.collect.Maps; //TODO: reduce reliance on CitizensNPC public class Controllable extends Trait implements Toggleable, CommandConfigurable { private Controller controller = new GroundController(); + @Persist private boolean enabled; private EntityType explicitType; @@ -68,7 +70,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab @Override public void load(DataKey key) throws NPCLoadException { - enabled = key.getBoolean("enabled"); explicitType = Util.matchEntityType(key.getString("explicittype")); } @@ -150,7 +151,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab @Override public void save(DataKey key) { - key.setBoolean("enabled", enabled); if (explicitType == null) key.removeKey("explicittype"); else diff --git a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java index ca30dd820..e381b08a9 100644 --- a/src/main/java/net/citizensnpcs/trait/CurrentLocation.java +++ b/src/main/java/net/citizensnpcs/trait/CurrentLocation.java @@ -1,13 +1,12 @@ package net.citizensnpcs.trait; -import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.util.DataKey; -import org.bukkit.Bukkit; import org.bukkit.Location; public class CurrentLocation extends Trait { + @Persist(required = true) private Location loc; public CurrentLocation() { @@ -18,15 +17,6 @@ public class CurrentLocation extends Trait { return loc; } - @Override - public void load(DataKey key) throws NPCLoadException { - if (Bukkit.getWorld(key.getString("world")) == null) - throw new NPCLoadException("'" + key.getString("world") + "' is not a valid world."); - - loc = new Location(Bukkit.getWorld(key.getString("world")), key.getDouble("x"), key.getDouble("y"), - key.getDouble("z"), (float) key.getDouble("yaw"), (float) key.getDouble("pitch")); - } - @Override public void run() { if (!npc.isSpawned()) @@ -34,21 +24,6 @@ public class CurrentLocation extends Trait { loc = npc.getBukkitEntity().getLocation(); } - @Override - public void save(DataKey key) { - if (loc == null) { - key.removeKey(getName()); - return; - } - - key.setString("world", loc.getWorld().getName()); - key.setDouble("x", loc.getX()); - key.setDouble("y", loc.getY()); - key.setDouble("z", loc.getZ()); - key.setDouble("yaw", loc.getYaw()); - key.setDouble("pitch", loc.getPitch()); - } - public void setLocation(Location loc) { this.loc = loc; } diff --git a/src/main/java/net/citizensnpcs/trait/LookClose.java b/src/main/java/net/citizensnpcs/trait/LookClose.java index bf5be23b4..90c91fd37 100644 --- a/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -11,7 +11,6 @@ import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.command.CommandConfigurable; import net.citizensnpcs.command.CommandContext; -import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Util; import org.bukkit.Location; @@ -30,7 +29,7 @@ public class LookClose extends Trait implements Toggleable, CommandConfigurable } private boolean canSeeTarget() { - return realisticLooking ? NMS.rayTrace(npc.getBukkitEntity(), lookingAt) : true; + return realisticLooking ? npc.getBukkitEntity().hasLineOfSight(lookingAt) : true; } @Override diff --git a/src/main/java/net/citizensnpcs/trait/Powered.java b/src/main/java/net/citizensnpcs/trait/Powered.java index 5a976e668..21ce2ee44 100644 --- a/src/main/java/net/citizensnpcs/trait/Powered.java +++ b/src/main/java/net/citizensnpcs/trait/Powered.java @@ -1,34 +1,24 @@ package net.citizensnpcs.trait; -import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Creeper; public class Powered extends Trait implements Toggleable { + @Persist("") private boolean powered; public Powered() { super("powered"); } - @Override - public void load(DataKey key) throws NPCLoadException { - powered = key.getBoolean(""); - } - @Override public void onSpawn() { if (npc.getBukkitEntity() instanceof Creeper) ((Creeper) npc.getBukkitEntity()).setPowered(powered); } - @Override - public void save(DataKey key) { - key.setBoolean("", powered); - } - @Override public boolean toggle() { powered = !powered; diff --git a/src/main/java/net/citizensnpcs/trait/Saddle.java b/src/main/java/net/citizensnpcs/trait/Saddle.java index cb7053b82..b85b5fe9d 100644 --- a/src/main/java/net/citizensnpcs/trait/Saddle.java +++ b/src/main/java/net/citizensnpcs/trait/Saddle.java @@ -1,9 +1,8 @@ package net.citizensnpcs.trait; import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Pig; import org.bukkit.event.EventHandler; @@ -11,17 +10,13 @@ import org.bukkit.event.player.PlayerInteractEntityEvent; public class Saddle extends Trait implements Toggleable { private boolean pig; + @Persist("") private boolean saddle; public Saddle() { super("saddle"); } - @Override - public void load(DataKey key) throws NPCLoadException { - saddle = key.getBoolean(""); - } - @EventHandler public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { if (pig && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getRightClicked()))) @@ -37,11 +32,6 @@ public class Saddle extends Trait implements Toggleable { pig = false; } - @Override - public void save(DataKey key) { - key.setBoolean("", saddle); - } - @Override public boolean toggle() { saddle = !saddle; diff --git a/src/main/java/net/citizensnpcs/trait/Sheared.java b/src/main/java/net/citizensnpcs/trait/Sheared.java index 71b821d98..71f6890c0 100644 --- a/src/main/java/net/citizensnpcs/trait/Sheared.java +++ b/src/main/java/net/citizensnpcs/trait/Sheared.java @@ -1,26 +1,21 @@ package net.citizensnpcs.trait; import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.exception.NPCLoadException; +import net.citizensnpcs.api.persistence.Persist; import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.util.DataKey; import org.bukkit.entity.Sheep; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerShearEntityEvent; public class Sheared extends Trait implements Toggleable { + @Persist("") private boolean sheared; public Sheared() { super("sheared"); } - @Override - public void load(DataKey key) throws NPCLoadException { - sheared = key.getBoolean(""); - } - @EventHandler public void onPlayerShearEntityEvent(PlayerShearEntityEvent event) { if (npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity()))) @@ -32,11 +27,6 @@ public class Sheared extends Trait implements Toggleable { ((Sheep) npc.getBukkitEntity()).setSheared(sheared); } - @Override - public void save(DataKey key) { - key.setBoolean("", sheared); - } - @Override public boolean toggle() { sheared = !sheared; diff --git a/src/main/java/net/citizensnpcs/trait/SkeletonType.java b/src/main/java/net/citizensnpcs/trait/SkeletonType.java new file mode 100644 index 000000000..10042b267 --- /dev/null +++ b/src/main/java/net/citizensnpcs/trait/SkeletonType.java @@ -0,0 +1,31 @@ +package net.citizensnpcs.trait; + +import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.api.trait.Trait; + +import org.bukkit.craftbukkit.entity.CraftSkeleton; + +public class SkeletonType extends Trait { + @Persist + private int type = 0; + private boolean skeleton; + + public SkeletonType() { + super("skeletontype"); + } + + public void setType(int type) { + this.type = Math.max(0, Math.min(1, type)); + } + + @Override + public void onSpawn() { + skeleton = npc.getBukkitEntity() instanceof CraftSkeleton; + } + + @Override + public void run() { + if (skeleton) + ((CraftSkeleton) npc.getBukkitEntity()).getHandle().setSkeletonType(type); + } +} diff --git a/src/main/java/net/citizensnpcs/util/Messages.java b/src/main/java/net/citizensnpcs/util/Messages.java index 4a1d6510f..0bbf42179 100644 --- a/src/main/java/net/citizensnpcs/util/Messages.java +++ b/src/main/java/net/citizensnpcs/util/Messages.java @@ -202,4 +202,6 @@ public class Messages { public static final String WAYPOINT_TRIGGER_TELEPORT_PROMPT = "citizens.editors.waypoints.triggers.teleport.prompt"; public static final String WORLD_NOT_FOUND = "citizens.commands.errors.missing-world"; public static final String WRITING_DEFAULT_SETTING = "citizens.settings.writing-default"; + public static final String SKELETON_TYPE_SET = "citizens.commands.npc.skeletontype.set"; + public static final String PLAYER_NOT_FOUND_FOR_SPAWN = "citizens.commands.npc.create.no-player-for-spawn"; } diff --git a/src/main/java/net/citizensnpcs/util/NMS.java b/src/main/java/net/citizensnpcs/util/NMS.java index d1c5e7f79..ead0675b2 100644 --- a/src/main/java/net/citizensnpcs/util/NMS.java +++ b/src/main/java/net/citizensnpcs/util/NMS.java @@ -141,12 +141,6 @@ public class NMS { handle.pitch = pitch; } - public static boolean rayTrace(LivingEntity entity, LivingEntity entity2) { - EntityLiving from = ((CraftLivingEntity) entity).getHandle(); - EntityLiving to = ((CraftLivingEntity) entity2).getHandle(); - return from.m(to); - } - public static void registerEntityClass(Class clazz) { if (ENTITY_CLASS_TO_INT.containsKey(clazz)) return; @@ -262,7 +256,6 @@ public class NMS { MOVEMENT_SPEEDS.put(EntityType.SHEEP, 0.25F); MOVEMENT_SPEEDS.put(EntityType.SNOWMAN, 0.25F); MOVEMENT_SPEEDS.put(EntityType.PIG, 0.27F); - MOVEMENT_SPEEDS.put(EntityType.PLAYER, 1F); MOVEMENT_SPEEDS.put(EntityType.VILLAGER, 0.3F); LAND_SPEED_MODIFIER_FIELD = getField(EntityLiving.class, "bQ"); @@ -281,4 +274,8 @@ public class NMS { Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); } } + + public static void setHeadYaw(EntityLiving handle, float yaw) { + handle.ay = yaw; + } } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 8f30a2354..b28a8f704 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -32,6 +32,7 @@ citizens.commands.npc.create.invalid-location=Spawn location could not be parsed citizens.commands.npc.create.invalid-mobtype={0} is not a valid mob type. Using default type. citizens.commands.npc.create.not-living-mobtype={0} is not a living entity type. Using default type. citizens.commands.npc.create.npc-name-too-long=NPC names cannot be longer than 16 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.gamemode.describe={0}''s gamemode is [[{1}]]. citizens.commands.npc.gamemode.invalid={0} is not a valid gamemode. @@ -66,6 +67,7 @@ citizens.commands.npc.rename.renamed=You renamed [[{0}]] to [[{1}]]. citizens.commands.npc.select.already-selected=You already have that NPC selected. citizens.commands.npc.size.description={0}''s size is [[{1}]]. citizens.commands.npc.size.set={0}''s size set to [[{1}]]. +citizens.commands.npc.skeletontype.set={0}''s skeleton type set to [[{1}]]. citizens.commands.npc.spawn.already-spawned={0} is already spawned at another location. Use ''/npc tphere'' to teleport the NPC to your location. citizens.commands.npc.spawn.missing-npc-id=No NPC with the ID {0} exists. citizens.commands.npc.spawn.no-location=No stored location available - command must be used ingame. @@ -135,7 +137,7 @@ citizens.editors.text.remove-prompt=Enter the index of the entry you wish to rem citizens.editors.text.removed-entry=[[Removed]] entry at index [[{0}]]. citizens.editors.text.start-prompt=Type [[add]] to add an entry, [[edit]] to edit entries, [[remove]] to remove entries, [[close]] to toggle the NPC as a close talker, and [[random]] to toggle the NPC as a random talker. Type [[help]] to show this again. citizens.editors.waypoints.linear.added-waypoint=[[Added]] a waypoint at ({0}) ([[{1}]], [[{2}]]) -citizens.editors.waypoints.linear.begin=Entered the linear waypoint editor!
[[Left click]] to add a waypoint, [[right click]] to remove.
Type [[toggle path]] to toggle showing entities at waypoints. +citizens.editors.waypoints.linear.begin=Entered the linear waypoint editor!
[[Left click]] to add a waypoint, [[right click]] to remove.
Type [[toggle path]] to toggle showing entities at waypoints. citizens.editors.waypoints.linear.edit-slot-set=Editing slot set to [[{0}]] ({1}). citizens.editors.waypoints.linear.end=Exited the linear waypoint editor. citizens.editors.waypoints.linear.not-showing-markers=[[Stopped]] showing waypoint markers. @@ -147,10 +149,10 @@ 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.chat.invalid-radius=The radius must be a number. citizens.editors.waypoints.triggers.chat.missing-radius=No radius supplied. -citizens.editors.waypoints.triggers.chat.prompt=Enter in chat lines to say.
Type in [[radius (radius)]] to set the block radius to broadcast the messages.
Type [[finish]] to finish the chat trigger or [[back]] to return to the previous prompt. +citizens.editors.waypoints.triggers.chat.prompt=Enter in chat lines to say.
Type in [[radius (radius)]] to set the block radius to broadcast the messages.
Type [[finish]] to finish the chat trigger or [[back]] to return to the previous prompt. citizens.editors.waypoints.triggers.delay.prompt=Enter the delay in [[server ticks]] to use. (20 ticks = 1 second) citizens.editors.waypoints.triggers.main.missing-waypoint=Not editing a waypoint. -citizens.editors.waypoints.triggers.main.prompt=Entered the waypoint trigger editor.
Type [[add]] to begin adding triggers and [[remove]] to remove triggers.

Current triggers are: +citizens.editors.waypoints.triggers.main.prompt=Entered the waypoint trigger editor.
Type [[add]] to begin adding triggers and [[remove]] to remove triggers.
Current triggers are: citizens.editors.waypoints.triggers.remove.index-out-of-range=Index must be in the range [[1-{0}]]. citizens.editors.waypoints.triggers.remove.not-a-number=Index must be a number. citizens.editors.waypoints.triggers.remove.prompt=Enter in the index of the trigger to delete or [[back]] to return to the edit prompt. Current triggers are: