diff --git a/src/main/java/kamkeel/npcs/network/PacketHandler.java b/src/main/java/kamkeel/npcs/network/PacketHandler.java index 4dcf50bac..745962aba 100644 --- a/src/main/java/kamkeel/npcs/network/PacketHandler.java +++ b/src/main/java/kamkeel/npcs/network/PacketHandler.java @@ -60,6 +60,7 @@ import kamkeel.npcs.network.packets.player.MailActionPacket; import kamkeel.npcs.network.packets.player.SaveBookPacket; import kamkeel.npcs.network.packets.player.SaveSignPacket; import kamkeel.npcs.network.packets.player.ScreenSizePacket; +import kamkeel.npcs.network.packets.player.SpecialKeyStatePacket; import kamkeel.npcs.network.packets.player.TransportPacket; import kamkeel.npcs.network.packets.player.customgui.CustomGuiButtonPacket; import kamkeel.npcs.network.packets.player.customgui.CustomGuiClosePacket; @@ -575,6 +576,7 @@ public class PacketHandler { PLAYER_PACKET.registerPacket(new InputDevicePacket()); PLAYER_PACKET.registerPacket(new ScreenSizePacket()); + PLAYER_PACKET.registerPacket(new SpecialKeyStatePacket()); PLAYER_PACKET.registerPacket(new SyncRevisionInfoPacket()); diff --git a/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java b/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java index 04d3d3396..0c1db3cd9 100644 --- a/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java +++ b/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java @@ -14,6 +14,7 @@ public enum EnumPlayerPacket { CompanionAction, GetRole, InputDevice, + SpecialKeyState, ScreenSize, MagicCycles, diff --git a/src/main/java/kamkeel/npcs/network/packets/player/SpecialKeyStatePacket.java b/src/main/java/kamkeel/npcs/network/packets/player/SpecialKeyStatePacket.java new file mode 100644 index 000000000..3b9f56690 --- /dev/null +++ b/src/main/java/kamkeel/npcs/network/packets/player/SpecialKeyStatePacket.java @@ -0,0 +1,60 @@ +package kamkeel.npcs.network.packets.player; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import io.netty.buffer.ByteBuf; +import kamkeel.npcs.network.AbstractPacket; +import kamkeel.npcs.network.PacketChannel; +import kamkeel.npcs.network.PacketClient; +import kamkeel.npcs.network.PacketHandler; +import kamkeel.npcs.network.enums.EnumPlayerPacket; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.PlayerData; + +import java.io.IOException; + +public final class SpecialKeyStatePacket extends AbstractPacket { + private boolean pressed; + + public SpecialKeyStatePacket() { + } + + private SpecialKeyStatePacket(boolean pressed) { + this.pressed = pressed; + } + + public static void send(boolean pressed) { + PacketClient.sendClient(new SpecialKeyStatePacket(pressed)); + } + + @Override + public Enum getType() { + return EnumPlayerPacket.SpecialKeyState; + } + + @Override + public PacketChannel getChannel() { + return PacketHandler.PLAYER_PACKET; + } + + @Override + @SideOnly(Side.CLIENT) + public void sendData(ByteBuf out) throws IOException { + out.writeBoolean(pressed); + } + + @Override + public void receiveData(ByteBuf in, EntityPlayer player) throws IOException { + boolean keyDown = in.readBoolean(); + if (!(player instanceof EntityPlayerMP)) { + return; + } + + PlayerData data = PlayerDataController.Instance.getPlayerData((EntityPlayerMP) player); + if (data != null) { + data.setSpecialKeyDown(keyDown); + } + } +} diff --git a/src/main/java/noppes/npcs/ai/EntityAILeapAtTargetNpc.java b/src/main/java/noppes/npcs/ai/EntityAILeapAtTargetNpc.java new file mode 100644 index 000000000..437dbd6d3 --- /dev/null +++ b/src/main/java/noppes/npcs/ai/EntityAILeapAtTargetNpc.java @@ -0,0 +1,63 @@ +package noppes.npcs.ai; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.MathHelper; +import noppes.npcs.entity.EntityNPCInterface; + +public class EntityAILeapAtTargetNpc extends EntityAIBase { + private final EntityNPCInterface npc; + private EntityLivingBase leapTarget; + private final float leapMotionY; + + public EntityAILeapAtTargetNpc(EntityNPCInterface npc, float leapMotionY) { + this.npc = npc; + this.leapMotionY = leapMotionY; + this.setMutexBits(5); + } + + @Override + public boolean shouldExecute() { + this.leapTarget = this.npc.getAttackTarget(); + if (this.leapTarget == null) { + return false; + } + double distanceSq = this.npc.getDistanceSqToEntity(this.leapTarget); + if (distanceSq < 4.0D || distanceSq > 16.0D) { + return false; + } + if (!this.npc.onGround) { + return false; + } + return this.npc.getRNG().nextInt(5) == 0; + } + + @Override + public boolean continueExecuting() { + boolean airborne = !this.npc.onGround; + if (!airborne) { + this.npc.setNpcJumpingState(false); + } + return airborne; + } + + @Override + public void startExecuting() { + double d0 = this.leapTarget.posX - this.npc.posX; + double d1 = this.leapTarget.posZ - this.npc.posZ; + float f = MathHelper.sqrt_double(d0 * d0 + d1 * d1); + + if ((double) f >= 1.0E-4D) { + this.npc.motionX += d0 / (double) f * 0.5D * 0.8D + this.npc.motionX * 0.2D; + this.npc.motionZ += d1 / (double) f * 0.5D * 0.8D + this.npc.motionZ * 0.2D; + } + + this.npc.motionY = this.leapMotionY; + this.npc.setNpcJumpingState(true); + } + + @Override + public void resetTask() { + this.npc.setNpcJumpingState(false); + } +} diff --git a/src/main/java/noppes/npcs/ai/EntityAIPounceTarget.java b/src/main/java/noppes/npcs/ai/EntityAIPounceTarget.java index 5dbe5f233..4f87575bf 100644 --- a/src/main/java/noppes/npcs/ai/EntityAIPounceTarget.java +++ b/src/main/java/noppes/npcs/ai/EntityAIPounceTarget.java @@ -30,7 +30,11 @@ public class EntityAIPounceTarget extends EntityAIBase { @Override public boolean continueExecuting() { - return !this.npc.onGround; + boolean airborne = !this.npc.onGround; + if (!airborne) { + this.npc.setNpcJumpingState(false); + } + return airborne; } @Override @@ -47,6 +51,12 @@ public class EntityAIPounceTarget extends EntityAIBase { this.npc.motionX *= this.leapSpeed; this.npc.motionZ *= this.leapSpeed; this.npc.motionY *= this.leapSpeed; + this.npc.setNpcJumpingState(true); + } + + @Override + public void resetTask() { + this.npc.setNpcJumpingState(false); } public float getAngleForXYZ(double varX, double varY, double varZ, double horiDist) { diff --git a/src/main/java/noppes/npcs/client/ClientProxy.java b/src/main/java/noppes/npcs/client/ClientProxy.java index f0346a5d3..7cc3d7b76 100644 --- a/src/main/java/noppes/npcs/client/ClientProxy.java +++ b/src/main/java/noppes/npcs/client/ClientProxy.java @@ -222,6 +222,7 @@ import java.util.Random; public class ClientProxy extends CommonProxy { public static KeyBinding NPCButton; + public static KeyBinding SpecialKey; public static final Random RAND = new Random(); public static FontContainer Font; @@ -288,8 +289,10 @@ public class ClientProxy extends CommonProxy { Minecraft mc = Minecraft.getMinecraft(); NPCButton = new KeyBinding("NPC Inventory", Keyboard.KEY_N, "key.categories.customnpc"); + SpecialKey = new KeyBinding("key.customnpcs.special", Keyboard.KEY_C, "key.categories.customnpc"); ClientRegistry.registerKeyBinding(NPCButton); + ClientRegistry.registerKeyBinding(SpecialKey); new PresetController(CustomNpcs.Dir); diff --git a/src/main/java/noppes/npcs/client/ClientTickHandler.java b/src/main/java/noppes/npcs/client/ClientTickHandler.java index 46af7df1a..af44405dc 100644 --- a/src/main/java/noppes/npcs/client/ClientTickHandler.java +++ b/src/main/java/noppes/npcs/client/ClientTickHandler.java @@ -8,6 +8,7 @@ import cpw.mods.fml.common.gameevent.TickEvent.Phase; import kamkeel.npcs.network.PacketClient; import kamkeel.npcs.network.packets.player.CheckPlayerValue; import kamkeel.npcs.network.packets.player.InputDevicePacket; +import kamkeel.npcs.network.packets.player.SpecialKeyStatePacket; import kamkeel.npcs.network.packets.player.ScreenSizePacket; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -23,9 +24,12 @@ import noppes.npcs.client.gui.hud.EnumHudComponent; import noppes.npcs.client.gui.hud.HudComponent; import noppes.npcs.client.gui.player.inventory.GuiCNPCInventory; import noppes.npcs.client.renderer.RenderNPCInterface; +import noppes.npcs.constants.EnumRoleType; import noppes.npcs.constants.MarkType; import noppes.npcs.controllers.data.MarkData; +import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.roles.RoleMount; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import tconstruct.client.tabs.InventoryTabCustomNpc; @@ -42,6 +46,7 @@ public class ClientTickHandler { private int buttonPressed = -1; private long buttonTime = 0L; private final int[] ignoreKeys = new int[]{157, 29, 54, 42, 184, 56, 220, 219}; + private boolean lastSpecialKeyDown = false; @SubscribeEvent(priority = EventPriority.LOWEST) public void onClientTick(TickEvent.ClientTickEvent event) { @@ -52,6 +57,30 @@ public class ClientTickHandler { } this.prevWorld = mc.theWorld; } + if (event.phase == Phase.START) { + EntityPlayer player = mc.thePlayer; + if (player != null) { + boolean specialKeyDown = ClientProxy.SpecialKey != null && Keyboard.isKeyDown(ClientProxy.SpecialKey.getKeyCode()); + if (specialKeyDown != lastSpecialKeyDown) { + PlayerData data = CustomNpcs.proxy.getPlayerData(player); + if (data != null) { + data.setSpecialKeyDown(specialKeyDown); + } + SpecialKeyStatePacket.send(specialKeyDown); + lastSpecialKeyDown = specialKeyDown; + } + + if (player.ridingEntity instanceof EntityNPCInterface) { + EntityNPCInterface mount = (EntityNPCInterface) player.ridingEntity; + if (mount.advanced.role == EnumRoleType.Mount && mount.roleInterface instanceof RoleMount) { + RoleMount role = (RoleMount) mount.roleInterface; + if (!role.isSprintAllowed() && player.isSprinting()) { + player.setSprinting(false); + } + } + } + } + } if (event.phase == Phase.END) { if (mc.thePlayer != null && mc.theWorld != null && !mc.isGamePaused() && ClientEventHandler.hasOverlays(mc.thePlayer)) { renderCNPCPlayer.itemRenderer.updateEquippedItem(); diff --git a/src/main/java/noppes/npcs/client/gui/roles/GuiNpcMount.java b/src/main/java/noppes/npcs/client/gui/roles/GuiNpcMount.java index 5f4d228e2..8c63d2c99 100644 --- a/src/main/java/noppes/npcs/client/gui/roles/GuiNpcMount.java +++ b/src/main/java/noppes/npcs/client/gui/roles/GuiNpcMount.java @@ -13,8 +13,6 @@ import noppes.npcs.client.gui.util.ITextfieldListener; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.roles.RoleMount; -import java.util.Locale; - public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener { private final RoleMount role; @@ -32,55 +30,86 @@ public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener return; } - int y = guiTop + 6; - addOffsetRow(0, "role.mount.offsetx", role.getOffsetX(), y); - y += 24; - addOffsetRow(1, "role.mount.offsety", role.getOffsetY(), y); - y += 24; - addOffsetRow(2, "role.mount.offsetz", role.getOffsetZ(), y); - y += 24; - addJumpRow(3, "role.mount.jumpheight", role.getJumpStrength(), y); - y += 24; + int leftLabelX = guiLeft + 4; + int leftFieldX = guiLeft + 140; + int leftY = guiTop + 6; - addLabel(new GuiNpcLabel(5, "role.mount.sprint", guiLeft + 4, y + 5)); - addButton(new GuiNpcButton(5, guiLeft + 140, y, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isSprintAllowed() ? 1 : 0)); + leftY = addOffsetRow(0, 10, "role.mount.offsetx", role.getOffsetX(), leftLabelX, leftFieldX, leftY); + leftY = addOffsetRow(1, 11, "role.mount.offsety", role.getOffsetY(), leftLabelX, leftFieldX, leftY); + leftY = addOffsetRow(2, 12, "role.mount.offsetz", role.getOffsetZ(), leftLabelX, leftFieldX, leftY); + leftY = addJumpRow(3, 13, "role.mount.jumpheight", role.getJumpStrength(), leftLabelX, leftFieldX, leftY); - addButton(new GuiNpcButton(4, guiLeft + 4, y + 30, 80, 20, "role.mount.reset")); + addLabel(new GuiNpcLabel(4, "role.mount.sprint", leftLabelX, leftY + 5)); + addButton(new GuiNpcButton(101, leftFieldX, leftY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isSprintAllowed() ? 1 : 0)); + leftY += 24; - GuiNpcLabel speedLabel = new GuiNpcLabel(6, "", guiLeft + 4, y + 56); + GuiNpcLabel speedLabel = new GuiNpcLabel(5, "", leftLabelX, leftY + 5); speedLabel.label = StatCollector.translateToLocalFormatted("role.mount.walkspeed", npc.ais.getWalkingSpeed()); addLabel(speedLabel); + + int rightLabelX = guiLeft + 214; + int rightFieldX = guiLeft + 320; + int rightY = guiTop + 6; + + addLabel(new GuiNpcLabel(20, "role.mount.fly", rightLabelX, rightY + 5)); + addButton(new GuiNpcButton(102, rightFieldX, rightY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isFlyingMountEnabled() ? 1 : 0)); + rightY += 24; + + if (role.isFlyingMountEnabled()) { + addLabel(new GuiNpcLabel(21, "role.mount.hover", rightLabelX, rightY + 5)); + addButton(new GuiNpcButton(103, rightFieldX, rightY, 60, 20, new String[]{"gui.no", "gui.yes"}, role.isHoverModeEnabled() ? 1 : 0)); + rightY += 24; + + rightY = addSpeedRow(22, 14, "role.mount.ascendspeed", role.getFlyingAscendSpeed(), rightLabelX, rightFieldX, rightY, 0.1F, 3.0F, 0.60F); + rightY = addSpeedRow(23, 15, "role.mount.descendspeed", role.getFlyingDescendSpeed(), rightLabelX, rightFieldX, rightY, 0.05F, 3.0F, 0.35F); + } } - private void addOffsetRow(int id, String translationKey, float value, int y) { - addLabel(new GuiNpcLabel(id, translationKey, guiLeft + 4, y + 5)); - GuiNpcTextField field = new GuiNpcTextField(id, this, guiLeft + 140, y, 80, 20, format(value)); + private int addOffsetRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y) { + addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5)); + GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value)); field.floatsOnly = true; field.setMinMaxDefaultFloat(-5.0F, 5.0F, 0.0F); addTextField(field); + return y + 24; } - private void addJumpRow(int id, String translationKey, float value, int y) { - addLabel(new GuiNpcLabel(id, translationKey, guiLeft + 4, y + 5)); - GuiNpcTextField field = new GuiNpcTextField(id, this, guiLeft + 140, y, 80, 20, format(value)); + private int addJumpRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y) { + addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5)); + GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value)); field.floatsOnly = true; field.setMinMaxDefaultFloat(0.1F, 15.0F, 1.0F); addTextField(field); + return y + 24; + } + + private int addSpeedRow(int labelId, int fieldId, String translationKey, float value, int labelX, int fieldX, int y, float min, float max, float defaultValue) { + addLabel(new GuiNpcLabel(labelId, translationKey, labelX, y + 5)); + GuiNpcTextField field = new GuiNpcTextField(fieldId, this, fieldX, y, 80, 20, format(value)); + field.floatsOnly = true; + field.setMinMaxDefaultFloat(min, max, defaultValue); + addTextField(field); + return y + 24; } private String format(float value) { - return String.format(Locale.ROOT, "%.2f", value); + return String.format(java.util.Locale.ROOT, "%.2f", value); } @Override public void buttonEvent(GuiButton guibutton) { if (role == null) return; - if (guibutton.id == 4) { - role.resetOffsets(); - initGui(); - } else if (guibutton.id == 5 && guibutton instanceof GuiNpcButton) { - role.setSprintAllowed(((GuiNpcButton) guibutton).getValue() == 1); + if (guibutton instanceof GuiNpcButton) { + GuiNpcButton button = (GuiNpcButton) guibutton; + if (guibutton.id == 101) { + role.setSprintAllowed(button.getValue() == 1); + } else if (guibutton.id == 102) { + role.setFlyingMountEnabled(button.getValue() == 1); + initGui(); + } else if (guibutton.id == 103) { + role.setHoverModeEnabled(button.getValue() == 1); + } } } @@ -90,32 +119,42 @@ public class GuiNpcMount extends GuiNPCInterface2 implements ITextfieldListener return; float value = textfield.isFloat() ? textfield.getFloat() : 0.0F; switch (textfield.id) { - case 0: + case 10: role.setOffsetX(value); break; - case 1: + case 11: role.setOffsetY(value); break; - case 2: + case 12: role.setOffsetZ(value); break; - case 3: + case 13: role.setJumpStrength(value); break; + case 14: + role.setFlyingAscendSpeed(value); + break; + case 15: + role.setFlyingDescendSpeed(value); + break; } textfield.setText(format(valueForField(textfield.id))); } private float valueForField(int id) { switch (id) { - case 0: + case 10: return role.getOffsetX(); - case 1: + case 11: return role.getOffsetY(); - case 2: + case 12: return role.getOffsetZ(); - case 3: + case 13: return role.getJumpStrength(); + case 14: + return role.getFlyingAscendSpeed(); + case 15: + return role.getFlyingDescendSpeed(); default: return 0.0F; } diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerData.java b/src/main/java/noppes/npcs/controllers/data/PlayerData.java index 5f6a5e00d..599f81ff1 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerData.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerData.java @@ -84,6 +84,7 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { public ScreenSize screenSize = new ScreenSize(-1, -1); public int profileSlot = 0; + private boolean specialKeyDown = false; public void onLogin() { // Continue playing animation for self when re-logging @@ -267,6 +268,14 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { return this.isGUIOpen; } + public boolean isSpecialKeyDown() { + return specialKeyDown; + } + + public void setSpecialKeyDown(boolean specialKeyDown) { + this.specialKeyDown = specialKeyDown; + } + public ScreenSize getScreenSize() { return screenSize; } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCFlying.java b/src/main/java/noppes/npcs/entity/EntityNPCFlying.java index 78a7ee23a..2996ca7f3 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCFlying.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCFlying.java @@ -45,6 +45,7 @@ public abstract class EntityNPCFlying extends EntityNPCInterface { if (handleMountedMovement(p_70612_1_, p_70612_2_)) return; if (!this.canFly() || this.hurtTime != 0 || !this.canBreathe()) { + setNpcFlyingState(false); super.moveEntityWithHeading(p_70612_1_, p_70612_2_); return; } @@ -66,11 +67,13 @@ public abstract class EntityNPCFlying extends EntityNPCInterface { if (!this.getNavigator().noPath() && this.motionY > 0) { this.motionY = 0; } else { + setNpcFlyingState(false); super.moveEntityWithHeading(p_70612_1_, p_70612_2_); return; } } this.flyLimitAllow = true; + setNpcFlyingState(true); double d3 = this.motionY; super.moveEntityWithHeading(p_70612_1_, p_70612_2_); @@ -97,9 +100,10 @@ public abstract class EntityNPCFlying extends EntityNPCInterface { } @Override - protected void doMountedMovement(float strafe, float forward, float moveSpeed) { + public void performMountedMovement(float strafe, float forward, float moveSpeed) { if (!this.canFly() || this.hurtTime != 0 || !this.canBreathe()) { - super.doMountedMovement(strafe, forward, moveSpeed); + setNpcFlyingState(false); + super.performMountedMovement(strafe, forward, moveSpeed); return; } @@ -120,14 +124,16 @@ public abstract class EntityNPCFlying extends EntityNPCInterface { if (!this.getNavigator().noPath() && this.motionY > 0) { this.motionY = 0; } else { - super.doMountedMovement(strafe, forward, moveSpeed); + setNpcFlyingState(false); + super.performMountedMovement(strafe, forward, moveSpeed); return; } } this.flyLimitAllow = true; + setNpcFlyingState(true); double d3 = this.motionY; - super.doMountedMovement(strafe, forward, moveSpeed); + super.performMountedMovement(strafe, forward, moveSpeed); this.motionY = d3; if (this.getNavigator().noPath()) { diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index 96310a01e..305a9098b 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -32,7 +32,6 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAIAttackOnCollide; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.ai.EntityAIHurtByTarget; -import net.minecraft.entity.ai.EntityAILeapAtTarget; import net.minecraft.entity.ai.EntityAIOpenDoor; import net.minecraft.entity.ai.EntityAIRestrictSun; import net.minecraft.entity.ai.EntityAISwimming; @@ -101,6 +100,7 @@ import noppes.npcs.ai.EntityAIMoveIndoors; import noppes.npcs.ai.EntityAIMovingPath; import noppes.npcs.ai.EntityAIOrbitTarget; import noppes.npcs.ai.EntityAIPanic; +import noppes.npcs.ai.EntityAILeapAtTargetNpc; import noppes.npcs.ai.EntityAIPounceTarget; import noppes.npcs.ai.EntityAIRangedAttack; import noppes.npcs.ai.EntityAIReturn; @@ -160,6 +160,7 @@ import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.entity.ScriptNpc; import noppes.npcs.scripted.event.NpcEvent; import noppes.npcs.util.GameProfileAlt; +import noppes.npcs.util.NPCMountUtil; import java.io.IOException; import java.util.ArrayList; @@ -211,7 +212,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti public ResourceLocation textureLocation = null; - private Entity lastRider; + private final NPCMountUtil.MountState mountState = new NPCMountUtil.MountState(); + private static final int NPC_STATE_FLAG_FLYING = 1; + private static final int NPC_STATE_FLAG_JUMPING = 1 << 1; public EnumAnimation currentAnimation = EnumAnimation.NONE; @@ -282,6 +285,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti this.dataWatcher.addObject(14, Integer.valueOf(0)); // Animation this.dataWatcher.addObject(15, Integer.valueOf(0)); // isWalking this.dataWatcher.addObject(16, ""); // Role + this.dataWatcher.addObject(17, Byte.valueOf((byte) 0)); // Mount state flags } protected boolean isAIEnabled() { @@ -967,7 +971,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti */ public void setLeapTask() { if (this.ais.leapType == 1) - this.tasks.addTask(this.taskCount++, aiLeap = new EntityAILeapAtTarget(this, 0.4F)); + this.tasks.addTask(this.taskCount++, aiLeap = new EntityAILeapAtTargetNpc(this, 0.4F)); if (this.ais.leapType == 2) this.tasks.addTask(this.taskCount++, aiLeap = new EntityAIPounceTarget(this)); } @@ -1486,13 +1490,14 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti delete(); } else { if (this.riddenByEntity != null) { - stabilizeDismountedRider(this.riddenByEntity); + NPCMountUtil.stabilizeDismountedRider(this.riddenByEntity); this.riddenByEntity.mountEntity(null); - haltMountedMotion(); + NPCMountUtil.haltMountedMotion(this, mountState); } if (this.ridingEntity != null) this.mountEntity(null); - lastRider = null; + mountState.lastRider = null; + NPCMountUtil.resetMountedFlightState(this, mountState); setHealth(-1); setSprinting(false); getNavigator().clearPathEntity(); @@ -1623,7 +1628,32 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } public boolean isFlying() { - return isWalking() && !onGround; + return isNpcFlying(); + } + + public boolean isNpcFlying() { + return (dataWatcher.getWatchableObjectByte(17) & NPC_STATE_FLAG_FLYING) != 0; + } + + public boolean isNpcJumping() { + return (dataWatcher.getWatchableObjectByte(17) & NPC_STATE_FLAG_JUMPING) != 0; + } + + private void setNpcStateFlag(int mask, boolean value) { + byte current = dataWatcher.getWatchableObjectByte(17); + byte updated = value ? (byte) (current | mask) : (byte) (current & ~mask); + if (current != updated) { + dataWatcher.updateObject(17, updated); + } + } + + public void setNpcFlyingState(boolean flying) { + setNpcStateFlag(NPC_STATE_FLAG_FLYING, flying); + } + + public void setNpcJumpingState(boolean jumping) { + setNpcStateFlag(NPC_STATE_FLAG_JUMPING, jumping); + this.isJumping = jumping; } public void setBoolFlag(boolean bo, int id) { @@ -1872,9 +1902,12 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } @Override - protected void fall(float par1) { + protected void fall(float distance) { + if (NPCMountUtil.isFlyingMountWithFlightEnabled(this)) { + return; + } if (!this.stats.noFallDamage) - super.fall(par1); + super.fall(distance); } @Override @@ -2089,57 +2122,10 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } protected boolean handleMountedMovement(float strafe, float forward) { - if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount)) - return false; - if (riddenByEntity != null && !(riddenByEntity instanceof EntityPlayer)) { - riddenByEntity.mountEntity(null); - return false; - } - if (!(riddenByEntity instanceof EntityPlayer)) - return false; - - RoleMount mount = (RoleMount) roleInterface; - EntityPlayer rider = (EntityPlayer) riddenByEntity; - this.prevRotationYaw = this.rotationYaw = rider.rotationYaw; - this.rotationPitch = rider.rotationPitch * 0.5F; - this.setRotation(this.rotationYaw, this.rotationPitch); - this.renderYawOffset = this.rotationYaw; - this.rotationYawHead = this.rotationYaw; - - float controlledStrafe = rider.moveStrafing * 0.5F; - float controlledForward = rider.moveForward; - if (controlledForward <= 0.0F) { - controlledForward *= 0.25F; - } - - float moveSpeed = Math.max(0.1F, getSpeed()); - boolean riderSprinting = rider.isSprinting() && mount.isSprintAllowed(); - if (riderSprinting) { - moveSpeed *= 1.2F; - } - - if (!mount.isSprintAllowed() && rider.isSprinting()) { - rider.setSprinting(false); - } - - this.setSprinting(riderSprinting); - this.stepHeight = 1.0F; - this.jumpMovementFactor = moveSpeed * 0.1F; - - this.getNavigator().clearPathEntity(); - this.setAttackTarget(null); - this.setRevengeTarget(null); - - this.fallDistance = 0.0F; - rider.fallDistance = 0.0F; - - applyMountedVerticalMotion(rider, moveSpeed, controlledForward); - doMountedMovement(controlledStrafe, controlledForward, moveSpeed); - - return true; + return NPCMountUtil.handleMountedMovement(this, mountState, strafe, forward); } - - protected void doMountedMovement(float strafe, float forward, float moveSpeed) { + + public void performMountedMovement(float strafe, float forward, float moveSpeed) { this.moveStrafing = strafe; this.moveForward = forward; if (!worldObj.isRemote) { @@ -2162,46 +2148,6 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti this.limbSwing += this.limbSwingAmount; } - protected void applyMountedVerticalMotion(EntityLivingBase rider, float moveSpeed, float forward) { - if (!(roleInterface instanceof RoleMount)) { - return; - } - RoleMount mount = (RoleMount) roleInterface; - double jumpFactor = MathHelper.clamp_double(mount.getJumpStrength(), 0.1D, 3.0D); - - if (canFly()) { - double verticalBase = Math.max(0.1D, moveSpeed * 0.6D); - double vertical = MathHelper.clamp_double(verticalBase * jumpFactor, 0.05D, 2.0D); - if (rider.isJumping) { - this.motionY = Math.min(this.motionY + vertical, vertical); - this.isAirBorne = true; - this.velocityChanged = true; - } else { - float pitch = rider.rotationPitch; - if (pitch < -10F) { - this.motionY = vertical; - } else if (pitch > 10F) { - this.motionY = -vertical; - } else if (!this.onGround) { - this.motionY *= 0.6D; - } - } - } else if (rider.isJumping && this.onGround) { - double baseVelocity = MathHelper.clamp_double(0.4D + moveSpeed * 1.5D, 0.2D, 1.2D); - double jumpVelocity = MathHelper.clamp_double(baseVelocity * jumpFactor, 0.2D, 2.0D); - this.motionY = jumpVelocity; - this.isAirBorne = true; - this.velocityChanged = true; - if (forward > 0.0F) { - float yawRadians = this.rotationYaw * (float) Math.PI / 180.0F; - double boost = 0.4D * forward; - this.motionX += -MathHelper.sin(yawRadians) * boost; - this.motionZ += MathHelper.cos(yawRadians) * boost; - } - ForgeHooks.onLivingJump(this); - } - } - @Override public boolean allowLeashing() { return false; @@ -2240,71 +2186,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } private void handleMountRiderState() { - if (worldObj.isRemote) { - if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount)) { - lastRider = null; - } - return; - } - - if (advanced.role != EnumRoleType.Mount || !(roleInterface instanceof RoleMount)) { - lastRider = null; - return; - } - - Entity currentRider = this.riddenByEntity; - if (currentRider != null && !(currentRider instanceof EntityPlayer)) { - Entity dismount = currentRider; - dismount.mountEntity(null); - stabilizeDismountedRider(dismount); - haltMountedMotion(); - currentRider = null; - } - if (currentRider != lastRider) { - if (lastRider != null) { - stabilizeDismountedRider(lastRider); - haltMountedMotion(); - } - lastRider = currentRider; - } - } - - private void stabilizeDismountedRider(Entity rider) { - boolean wasOnGround = rider.onGround; - double previousMotionX = rider.motionX; - double previousMotionY = rider.motionY; - double previousMotionZ = rider.motionZ; - float previousFall = rider.fallDistance; - - if (wasOnGround) { - rider.motionX = 0.0D; - rider.motionY = 0.0D; - rider.motionZ = 0.0D; - rider.fallDistance = 0.0F; - rider.onGround = true; - } else { - rider.motionX = previousMotionX; - rider.motionY = previousMotionY; - rider.motionZ = previousMotionZ; - rider.fallDistance = previousFall; - } - - rider.velocityChanged = true; - } - - private void haltMountedMotion() { - this.motionX = 0.0D; - this.motionY = 0.0D; - this.motionZ = 0.0D; - this.velocityChanged = true; - this.isAirBorne = false; - this.setSprinting(false); - this.moveForward = 0.0F; - this.moveStrafing = 0.0F; - this.setAIMoveSpeed(0.0F); - this.limbSwingAmount = 0.0F; - this.limbSwing = 0.0F; - this.getNavigator().clearPathEntity(); + NPCMountUtil.handleMountRiderState(this, mountState); } // Model Types: 0: Steve 64x32, 1: Steve 64x64, 2: Alex 64x64 diff --git a/src/main/java/noppes/npcs/entity/EntityNpcDragon.java b/src/main/java/noppes/npcs/entity/EntityNpcDragon.java index 6f490583f..a9df9da99 100644 --- a/src/main/java/noppes/npcs/entity/EntityNpcDragon.java +++ b/src/main/java/noppes/npcs/entity/EntityNpcDragon.java @@ -94,6 +94,7 @@ public class EntityNpcDragon extends EntityNPCInterface { field_40172_ax += f1 * 0.5F; } super.onLivingUpdate(); + this.isFlying = isNpcFlying(); } // public float ticks = 0.0f; diff --git a/src/main/java/noppes/npcs/entity/EntityNpcPony.java b/src/main/java/noppes/npcs/entity/EntityNpcPony.java index ed6ca617c..81ba41233 100644 --- a/src/main/java/noppes/npcs/entity/EntityNpcPony.java +++ b/src/main/java/noppes/npcs/entity/EntityNpcPony.java @@ -35,4 +35,10 @@ public class EntityNpcPony extends EntityNPCInterface { super.onUpdate(); } + @Override + public void onLivingUpdate() { + super.onLivingUpdate(); + this.isFlying = isNpcFlying(); + } + } diff --git a/src/main/java/noppes/npcs/roles/RoleMount.java b/src/main/java/noppes/npcs/roles/RoleMount.java index a1a07c800..f930a4975 100644 --- a/src/main/java/noppes/npcs/roles/RoleMount.java +++ b/src/main/java/noppes/npcs/roles/RoleMount.java @@ -10,12 +10,13 @@ public class RoleMount extends RoleInterface { private float offsetX; private float offsetY; private float offsetZ; - private static final float MIN_JUMP_STRENGTH = 0.1F; - private static final float MAX_JUMP_STRENGTH = 3.0F; - private boolean storedReturnToStart; private float jumpStrength = 1.0F; private boolean allowSprint = true; + private boolean flyingMountEnabled = false; + private boolean hoverMode = false; + private float flyingAscendSpeed = 0.60F; + private float flyingDescendSpeed = 0.35F; public RoleMount(EntityNPCInterface npc) { super(npc); @@ -31,6 +32,10 @@ public class RoleMount extends RoleInterface { compound.setBoolean("MountReturnFlag", storedReturnToStart); compound.setFloat("MountJumpStrength", jumpStrength); compound.setBoolean("MountAllowSprint", allowSprint); + compound.setBoolean("MountAllowFlying", flyingMountEnabled); + compound.setBoolean("MountHoverMode", hoverMode); + compound.setFloat("MountFlyingAscendSpeed", flyingAscendSpeed); + compound.setFloat("MountFlyingDescendSpeed", flyingDescendSpeed); return compound; } @@ -50,6 +55,20 @@ public class RoleMount extends RoleInterface { jumpStrength = 1.0F; } allowSprint = !compound.hasKey("MountAllowSprint") || compound.getBoolean("MountAllowSprint"); + flyingMountEnabled = compound.hasKey("MountAllowFlying") && compound.getBoolean("MountAllowFlying"); + hoverMode = compound.hasKey("MountHoverMode") && compound.getBoolean("MountHoverMode"); + if (compound.hasKey("MountFlyingAscendSpeed")) { + setFlyingAscendSpeed(compound.getFloat("MountFlyingAscendSpeed")); + } else { + flyingAscendSpeed = 0.60F; + } + if (compound.hasKey("MountFlyingDescendSpeed")) { + setFlyingDescendSpeed(compound.getFloat("MountFlyingDescendSpeed")); + } else if (compound.hasKey("MountFlyingFallSpeed")) { + setFlyingDescendSpeed(compound.getFloat("MountFlyingFallSpeed")); + } else { + flyingDescendSpeed = 0.35F; + } npc.ais.returnToStart = false; } @@ -106,7 +125,7 @@ public class RoleMount extends RoleInterface { } public void setJumpStrength(float value) { - this.jumpStrength = ValueUtil.clamp(value, MIN_JUMP_STRENGTH, MAX_JUMP_STRENGTH); + this.jumpStrength = ValueUtil.clamp(value, 0.1F, 3.0F); } public float getJumpStrength() { @@ -121,6 +140,38 @@ public class RoleMount extends RoleInterface { return allowSprint; } + public void setFlyingMountEnabled(boolean enabled) { + this.flyingMountEnabled = enabled; + } + + public boolean isFlyingMountEnabled() { + return flyingMountEnabled; + } + + public void setHoverModeEnabled(boolean enabled) { + this.hoverMode = enabled; + } + + public boolean isHoverModeEnabled() { + return hoverMode; + } + + public void setFlyingAscendSpeed(float value) { + this.flyingAscendSpeed = ValueUtil.clamp(value, 0.1F, 3.0F); + } + + public float getFlyingAscendSpeed() { + return flyingAscendSpeed; + } + + public void setFlyingDescendSpeed(float value) { + this.flyingDescendSpeed = ValueUtil.clamp(value, 0.05F, 3.0F); + } + + public float getFlyingDescendSpeed() { + return flyingDescendSpeed; + } + public void setReturnToStartPreference(boolean value) { this.storedReturnToStart = value; npc.ais.returnToStart = false; diff --git a/src/main/java/noppes/npcs/util/NPCMountUtil.java b/src/main/java/noppes/npcs/util/NPCMountUtil.java new file mode 100644 index 000000000..fc04248a8 --- /dev/null +++ b/src/main/java/noppes/npcs/util/NPCMountUtil.java @@ -0,0 +1,335 @@ +package noppes.npcs.util; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MathHelper; +import noppes.npcs.CustomNpcs; +import noppes.npcs.controllers.PlayerDataController; +import noppes.npcs.controllers.data.PlayerData; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.constants.EnumRoleType; +import noppes.npcs.roles.RoleMount; + +public final class NPCMountUtil { + private static final int MOUNT_FLIGHT_TOGGLE_WINDOW = 7; + + private NPCMountUtil() { + } + + public static class MountState { + public Entity lastRider; + public boolean flightMode; + public boolean jumpPressed; + public int flightToggleTimer; + } + + public static boolean handleMountedMovement(EntityNPCInterface npc, MountState state, float strafe, float forward) { + if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) { + resetMountedFlightState(npc, state); + return false; + } + if (npc.riddenByEntity != null && !(npc.riddenByEntity instanceof EntityPlayer)) { + npc.riddenByEntity.mountEntity(null); + return false; + } + if (!(npc.riddenByEntity instanceof EntityPlayer)) { + resetMountedFlightState(npc, state); + return false; + } + + RoleMount mount = (RoleMount) npc.roleInterface; + EntityPlayer rider = (EntityPlayer) npc.riddenByEntity; + updateMountedFlightState(npc, state, mount, rider); + + npc.prevRotationYaw = npc.rotationYaw = rider.rotationYaw; + npc.rotationPitch = rider.rotationPitch * 0.5F; + npc.setPositionAndRotation(npc.posX, npc.posY, npc.posZ, npc.rotationYaw, npc.rotationPitch); + npc.renderYawOffset = npc.rotationYaw; + npc.rotationYawHead = npc.rotationYaw; + + float controlledStrafe = rider.moveStrafing; + float controlledForward = rider.moveForward; + if (controlledForward <= 0.0F) { + controlledForward *= 0.25F; + } + + float moveSpeed = Math.max(0.0F, npc.getSpeed()); + boolean riderSprinting = rider.isSprinting() && mount.isSprintAllowed(); + if (riderSprinting) { + moveSpeed *= 1.2F; + } + + if (!mount.isSprintAllowed() && rider.isSprinting()) { + rider.setSprinting(false); + } + + if (moveSpeed <= 0.0F) { + controlledStrafe = 0.0F; + controlledForward = 0.0F; + } + + npc.setSprinting(riderSprinting); + npc.stepHeight = 1.0F; + npc.jumpMovementFactor = moveSpeed * 0.1F; + + npc.getNavigator().clearPathEntity(); + npc.setAttackTarget(null); + npc.setRevengeTarget(null); + + npc.fallDistance = 0.0F; + rider.fallDistance = 0.0F; + + applyMountedVerticalMotion(npc, state, mount, rider, moveSpeed, controlledForward); + npc.performMountedMovement(controlledStrafe, controlledForward, moveSpeed); + + return true; + } + + private static void applyMountedVerticalMotion(EntityNPCInterface npc, MountState state, RoleMount mount, EntityLivingBase rider, float moveSpeed, float forward) { + if (mount == null) { + return; + } + double jumpFactor = MathHelper.clamp_double(mount.getJumpStrength(), 0.1D, 3.0D); + boolean flyingEnabled = mount.isFlyingMountEnabled(); + + npc.setNpcJumpingState(false); + + if (flyingEnabled) { + double ascendSpeed = MathHelper.clamp_double(mount.getFlyingAscendSpeed(), 0.1D, 3.0D); + double descendSpeed = MathHelper.clamp_double(mount.getFlyingDescendSpeed(), 0.05D, 3.0D); + boolean flightMode = isMountInFlightMode(state); + boolean jumpPressed = rider.isJumping; + boolean descendPressed = rider instanceof EntityPlayer && isSpecialKeyDown((EntityPlayer) rider); + + if (flightMode) { + npc.motionY = 0.0D; + + if (jumpPressed) { + npc.motionY += ascendSpeed; + } else if (descendPressed) { + npc.motionY -= descendSpeed; + } + + npc.motionY = MathHelper.clamp_double(npc.motionY, -descendSpeed, ascendSpeed); + + npc.setNpcFlyingState(true); + npc.setNpcJumpingState(jumpPressed); + npc.isAirBorne = true; + npc.velocityChanged = true; + npc.fallDistance = 0.0F; + + if (!npc.worldObj.isRemote && rider instanceof EntityPlayer) { + EntityPlayer player = (EntityPlayer) rider; + if (!player.capabilities.isFlying) { + player.motionY = npc.motionY; + player.velocityChanged = true; + } + } + return; + } + + if (jumpPressed && npc.onGround) { + npc.motionY = jumpFactor; + npc.setNpcJumpingState(true); + npc.isAirBorne = true; + npc.velocityChanged = true; + npc.fallDistance = 0.0F; + if (!npc.worldObj.isRemote) { + net.minecraftforge.common.ForgeHooks.onLivingJump(npc); + } + return; + } + + if (!npc.onGround) { + npc.motionY = Math.max(npc.motionY, -descendSpeed); + npc.setNpcFlyingState(!npc.isInWater()); + } else { + npc.setNpcFlyingState(false); + } + + return; + } + + if (npc.onGround) { + if (rider.isJumping) { + npc.motionY = jumpFactor; + npc.setNpcJumpingState(true); + npc.isAirBorne = true; + npc.velocityChanged = true; + npc.fallDistance = 0.0F; + if (!npc.worldObj.isRemote) { + net.minecraftforge.common.ForgeHooks.onLivingJump(npc); + } + } else { + npc.motionY = 0.0D; + } + return; + } + + npc.setNpcFlyingState(false); + } + + public static void handleMountRiderState(EntityNPCInterface npc, MountState state) { + if (npc.worldObj.isRemote) { + if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) { + state.lastRider = null; + } + return; + } + + if (npc.advanced.role != EnumRoleType.Mount || !(npc.roleInterface instanceof RoleMount)) { + state.lastRider = null; + return; + } + + RoleMount mount = (RoleMount) npc.roleInterface; + Entity currentRider = npc.riddenByEntity; + if (currentRider != null && !(currentRider instanceof EntityPlayer)) { + Entity dismount = currentRider; + dismount.mountEntity(null); + stabilizeDismountedRider(dismount); + haltMountedMotion(npc, state); + applyUnriddenFlightDescent(npc, state, mount); + currentRider = null; + } + if (currentRider != state.lastRider) { + if (state.lastRider != null) { + stabilizeDismountedRider(state.lastRider); + } + if (currentRider == null) { + haltMountedMotion(npc, state); + applyUnriddenFlightDescent(npc, state, mount); + } else { + resetMountedFlightState(npc, state); + } + state.lastRider = currentRider; + } else if (currentRider == null) { + applyUnriddenFlightDescent(npc, state, mount); + } + } + + public static boolean isFlyingMountWithFlightEnabled(EntityNPCInterface npc) { + return npc.advanced.role == EnumRoleType.Mount && npc.roleInterface instanceof RoleMount && ((RoleMount) npc.roleInterface).isFlyingMountEnabled(); + } + + public static void haltMountedMotion(EntityNPCInterface npc, MountState state) { + npc.motionX = 0.0D; + npc.motionY = 0.0D; + npc.motionZ = 0.0D; + npc.velocityChanged = true; + npc.isAirBorne = false; + npc.setSprinting(false); + npc.moveForward = 0.0F; + npc.moveStrafing = 0.0F; + npc.setAIMoveSpeed(0.0F); + npc.limbSwingAmount = 0.0F; + npc.limbSwing = 0.0F; + npc.getNavigator().clearPathEntity(); + npc.fallDistance = 0.0F; + resetMountedFlightState(npc, state); + } + + public static void applyUnriddenFlightDescent(EntityNPCInterface npc, MountState state, RoleMount mount) { + if (mount == null || !mount.isFlyingMountEnabled()) { + npc.setNpcFlyingState(false); + npc.setNpcJumpingState(false); + return; + } + if (npc.onGround) { + npc.motionY = 0.0D; + npc.setNpcFlyingState(false); + npc.setNpcJumpingState(false); + return; + } + + double descendSpeed = MathHelper.clamp_double(mount.getFlyingDescendSpeed(), 0.05D, 3.0D); + if (descendSpeed <= 0.0D) { + npc.setNpcFlyingState(false); + npc.setNpcJumpingState(false); + return; + } + + double desired = -descendSpeed; + npc.motionY = desired; + npc.isAirBorne = true; + npc.velocityChanged = true; + npc.fallDistance = 0.0F; + npc.setNpcFlyingState(true); + npc.setNpcJumpingState(false); + } + + public static void stabilizeDismountedRider(Entity rider) { + boolean wasOnGround = rider.onGround; + double previousMotionX = rider.motionX; + double previousMotionY = rider.motionY; + double previousMotionZ = rider.motionZ; + float previousFall = rider.fallDistance; + + if (wasOnGround) { + rider.motionX = 0.0D; + rider.motionY = 0.0D; + rider.motionZ = 0.0D; + rider.fallDistance = 0.0F; + rider.onGround = true; + } else { + rider.motionX = previousMotionX; + rider.motionY = previousMotionY; + rider.motionZ = previousMotionZ; + rider.fallDistance = previousFall; + } + + rider.velocityChanged = true; + } + + private static void updateMountedFlightState(EntityNPCInterface npc, MountState state, RoleMount mount, EntityPlayer rider) { + if (mount == null || rider == null || !mount.isFlyingMountEnabled()) { + resetMountedFlightState(npc, state); + return; + } + + if (npc.onGround) { + state.flightMode = false; + } + + boolean jumpPressed = rider.isJumping; + if (jumpPressed && !state.jumpPressed) { + if (state.flightToggleTimer > 0) { + state.flightMode = !state.flightMode; + state.flightToggleTimer = 0; + } else { + state.flightToggleTimer = MOUNT_FLIGHT_TOGGLE_WINDOW; + } + } + + if (state.flightToggleTimer > 0) { + state.flightToggleTimer--; + } + + state.jumpPressed = jumpPressed; + } + + public static boolean isMountInFlightMode(MountState state) { + return state.flightMode; + } + + public static void resetMountedFlightState(EntityNPCInterface npc, MountState state) { + state.flightMode = false; + state.jumpPressed = false; + state.flightToggleTimer = 0; + npc.setNpcFlyingState(false); + npc.setNpcJumpingState(false); + } + + private static boolean isSpecialKeyDown(EntityPlayer rider) { + if (rider == null) { + return false; + } + if (rider.worldObj.isRemote) { + PlayerData data = CustomNpcs.proxy.getPlayerData(rider); + return data != null && data.isSpecialKeyDown(); + } + PlayerData data = PlayerDataController.Instance.getPlayerData(rider); + return data != null && data.isSpecialKeyDown(); + } +} diff --git a/src/main/resources/assets/customnpcs/lang/cs_CZ.lang b/src/main/resources/assets/customnpcs/lang/cs_CZ.lang index e574a1fb1..c45e3dade 100644 --- a/src/main/resources/assets/customnpcs/lang/cs_CZ.lang +++ b/src/main/resources/assets/customnpcs/lang/cs_CZ.lang @@ -440,10 +440,11 @@ item.npcCrown.name=Koruna item.npcCrown2.name=Koruna key.npcInventory=NPC inventář role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/de_DE.lang b/src/main/resources/assets/customnpcs/lang/de_DE.lang index 86269b7b0..32170875b 100644 --- a/src/main/resources/assets/customnpcs/lang/de_DE.lang +++ b/src/main/resources/assets/customnpcs/lang/de_DE.lang @@ -872,10 +872,11 @@ companion.stage=Bühne key.npcInventory=NPC Inventar role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index 6026ed59a..466acfb99 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -1,6 +1,7 @@ customnpcs.defaultTextColor=404040 key.categories.customnpc=CustomNPC+ +key.customnpcs.special=Special Key key.npcInventory=NPC Inventory entity.CustomNpc.name=Custom Npc @@ -418,13 +419,16 @@ role.mailman=Mailman role.marketname=Linked Marketname role.companion=Companion role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting -role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint +role.mount.fly=Flying +role.mount.hover=Hover +role.mount.ascendspeed=Ascend Speed +role.mount.descendspeed=Descend Speed +role.mount.walkspeed=Walk Speed: %s trader.insufficient=Insufficient Currency trader.sufficient=Sufficient Currency diff --git a/src/main/resources/assets/customnpcs/lang/es_AR.lang b/src/main/resources/assets/customnpcs/lang/es_AR.lang index f0d9533a2..03e80082e 100644 --- a/src/main/resources/assets/customnpcs/lang/es_AR.lang +++ b/src/main/resources/assets/customnpcs/lang/es_AR.lang @@ -500,10 +500,11 @@ item.npcMusket.name=Mosquete item.npcExcalibur.name=Excalibur key.npcInventory=Inventario de NPC role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/es_MX.lang b/src/main/resources/assets/customnpcs/lang/es_MX.lang index 9b3ee6a1f..7ea1b25b2 100644 --- a/src/main/resources/assets/customnpcs/lang/es_MX.lang +++ b/src/main/resources/assets/customnpcs/lang/es_MX.lang @@ -500,10 +500,11 @@ item.npcMusket.name=Mosquete item.npcExcalibur.name=Excalibur key.npcInventory=Inventario de NPC role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/fr_FR.lang b/src/main/resources/assets/customnpcs/lang/fr_FR.lang index 6fc66154c..cea83f824 100644 --- a/src/main/resources/assets/customnpcs/lang/fr_FR.lang +++ b/src/main/resources/assets/customnpcs/lang/fr_FR.lang @@ -542,10 +542,11 @@ item.npcMusket.name=Mousquet item.npcExcalibur.name=Excalibur key.npcInventory=Inventaire Pnj role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/hu_HU.lang b/src/main/resources/assets/customnpcs/lang/hu_HU.lang index 63ee943af..db2fc6c38 100644 --- a/src/main/resources/assets/customnpcs/lang/hu_HU.lang +++ b/src/main/resources/assets/customnpcs/lang/hu_HU.lang @@ -542,10 +542,11 @@ item.npcMusket.name=Muskéta item.npcExcalibur.name=Excalibur key.npcInventory=NPC felszerelés role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/id_ID.lang b/src/main/resources/assets/customnpcs/lang/id_ID.lang index 2b53a9639..025320030 100644 --- a/src/main/resources/assets/customnpcs/lang/id_ID.lang +++ b/src/main/resources/assets/customnpcs/lang/id_ID.lang @@ -317,10 +317,11 @@ item.npcRuby.name=Permata Rubi role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/ko_KR.lang b/src/main/resources/assets/customnpcs/lang/ko_KR.lang index 89f7c8d7d..e3a672289 100644 --- a/src/main/resources/assets/customnpcs/lang/ko_KR.lang +++ b/src/main/resources/assets/customnpcs/lang/ko_KR.lang @@ -797,10 +797,11 @@ enchantment.poison=독 key.npcInventory=NPC 인벤토리 role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/nl_NL.lang b/src/main/resources/assets/customnpcs/lang/nl_NL.lang index acae2f273..297cfa1fc 100644 --- a/src/main/resources/assets/customnpcs/lang/nl_NL.lang +++ b/src/main/resources/assets/customnpcs/lang/nl_NL.lang @@ -232,10 +232,11 @@ item.npcNinjaHead.name=Ninja Helm item.npcNinjaChest.name=Ninja Borst item.npcNinjaPants.name=Ninja Broek role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/pl_PL.lang b/src/main/resources/assets/customnpcs/lang/pl_PL.lang index ff860e0ab..e84de64ee 100644 --- a/src/main/resources/assets/customnpcs/lang/pl_PL.lang +++ b/src/main/resources/assets/customnpcs/lang/pl_PL.lang @@ -498,10 +498,11 @@ item.npcMusket.name=Muszkiet item.npcExcalibur.name=Excalibur key.npcInventory=Inwentarz npc role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/pt_BR.lang b/src/main/resources/assets/customnpcs/lang/pt_BR.lang index 066697e8c..6d07b2df0 100644 --- a/src/main/resources/assets/customnpcs/lang/pt_BR.lang +++ b/src/main/resources/assets/customnpcs/lang/pt_BR.lang @@ -498,10 +498,11 @@ item.npcMusket.name=Mosquete item.npcExcalibur.name=Excalibur key.npcInventory=Inventário NPC role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/ru_RU.lang b/src/main/resources/assets/customnpcs/lang/ru_RU.lang index a34739f0d..2c6f76422 100644 --- a/src/main/resources/assets/customnpcs/lang/ru_RU.lang +++ b/src/main/resources/assets/customnpcs/lang/ru_RU.lang @@ -1021,10 +1021,11 @@ questgui.accept=Принять key.npcInventory=Инвентарь NPC role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/sv_SE.lang b/src/main/resources/assets/customnpcs/lang/sv_SE.lang index 70a29ebc9..7e536400b 100644 --- a/src/main/resources/assets/customnpcs/lang/sv_SE.lang +++ b/src/main/resources/assets/customnpcs/lang/sv_SE.lang @@ -308,10 +308,11 @@ item.npcPendant.name=Pendant item.npcBlueprint.name=Blueprint item.npcRing.name=Ring role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/zh_CN.lang b/src/main/resources/assets/customnpcs/lang/zh_CN.lang index 00fb8c796..32105c7db 100644 --- a/src/main/resources/assets/customnpcs/lang/zh_CN.lang +++ b/src/main/resources/assets/customnpcs/lang/zh_CN.lang @@ -1244,10 +1244,11 @@ hitbox.height=身高比例 key.npcInventory=NPC物品栏 role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key diff --git a/src/main/resources/assets/customnpcs/lang/zh_TW.lang b/src/main/resources/assets/customnpcs/lang/zh_TW.lang index a4f3d4ae5..b7f2c04f5 100644 --- a/src/main/resources/assets/customnpcs/lang/zh_TW.lang +++ b/src/main/resources/assets/customnpcs/lang/zh_TW.lang @@ -314,10 +314,11 @@ item.npcSaphire.name=藍寶石 item.npcAmethyst.name=紫水晶 item.npcRuby.name=紅寶石 role.mount=Mount -role.mount.offsetx=Seat Offset X -role.mount.offsety=Seat Offset Y -role.mount.offsetz=Seat Offset Z -role.mount.jumpheight=Jump Strength -role.mount.sprint=Allow Sprinting +role.mount.offsetx=Seat X +role.mount.offsety=Seat Y +role.mount.offsetz=Seat Z +role.mount.jumpheight=Jump +role.mount.sprint=Sprint role.mount.reset=Reset Position -role.mount.walkspeed=Walking speed: %s +role.mount.walkspeed=Walk Speed: %s +key.customnpcs.special=Special Key