commit 3725799de3eae810f97237ae12cf41b5b0abdf04 Author: squeek Date: Sat Apr 19 01:57:15 2014 -0700 Initial version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd835da --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Builds & binaries +build/ +bin/ +target/ +lib/ +launcher/ +.gradle/ +*.zip +*.jar +*.gradle + +# Misc mod files +media/ +libs/ + +# Tmp files +*~ +*# + +# IDEs +.classpath +.project +.settings +.pydevproject + +# MCP Files +docs/ +conf/ +eclipse/ +jars/ +logs/ +runtime/ +temp/ +reobf/ +CHANGELOG +LICENSE.txt +*.bat +*.sh + +# Misc +*.rej \ No newline at end of file diff --git a/java/squeek/quakemovement/ModConfig.java b/java/squeek/quakemovement/ModConfig.java new file mode 100644 index 0000000..a29fb5f --- /dev/null +++ b/java/squeek/quakemovement/ModConfig.java @@ -0,0 +1,89 @@ +package squeek.mods.quakemovement; + +import java.io.File; + +import net.minecraftforge.common.Configuration; + +public class ModConfig { + + private static final String CATEGORY_MOVEMENT = "movement"; + + public static float TRIMP_MULTIPLIER; + private static final String TRIMP_MULTIPLIER_NAME = "trimpMultiplier"; + private static final double TRIMP_MULTIPLIER_DEFAULT = 1.4D; + + public static float HARD_CAP; + private static final String HARD_CAP_NAME = "hardCapThreshold"; + private static final double HARD_CAP_DEFAULT = 2.0D; + + public static float SOFT_CAP; + private static final String SOFT_CAP_NAME = "softCapThreshold"; + private static final double SOFT_CAP_DEFAULT = 1.4D; + + public static float SOFT_CAP_DEGEN; + private static final String SOFT_CAP_DEGEN_NAME = "softCapDegen"; + private static final double SOFT_CAP_DEGEN_DEFAULT = 0.65D; // 0.65 + + public static boolean SHARKING_ENABLED; + private static final String SHARKING_ENABLED_NAME = "sharkingEnabled"; + private static final boolean SHARKING_ENABLED_DEFAULT = true; + + public static double SHARKING_SURFACE_TENSION; + private static final String SHARKING_SURFACE_TENSION_NAME = "sharkingSurfaceTension"; + private static final double SHARKING_SURFACE_TENSION_DEFAULT = 0.2D; + + public static double SHARKING_WATER_FRICTION; + private static final String SHARKING_WATER_FRICTION_NAME = "sharkingWaterFriction"; + private static final double SHARKING_WATER_FRICTION_DEFAULT = 0.1D; + + public static double ACCELERATE; + private static final String ACCELERATE_NAME = "groundAccelerate"; + private static final double ACCELERATE_DEFAULT = 10.0D; + + public static double AIR_ACCELERATE; + private static final String AIR_ACCELERATE_NAME = "airAccelerate"; + private static final double AIR_ACCELERATE_DEFAULT = 14.0D; + + public static boolean UNCAPPED_BUNNYHOP_ENABLED; + private static final String UNCAPPED_BUNNYHOP_ENABLED_NAME = "uncappedBunnyhopEnabled"; + private static final boolean UNCAPPED_BUNNYHOP_ENABLED_DEFAULT = true; + + public static boolean TRIMPING_ENABLED; + private static final String TRIMPING_ENABLED_NAME = "trimpEnabled"; + private static final boolean TRIMPING_ENABLED_DEFAULT = true; + + private static Configuration config; + + public static void init( File file ) + { + config = new Configuration( file ); + + load(); + + UNCAPPED_BUNNYHOP_ENABLED = config.get(CATEGORY_MOVEMENT, UNCAPPED_BUNNYHOP_ENABLED_NAME, UNCAPPED_BUNNYHOP_ENABLED_DEFAULT, "if enabled, holding jump while swimming at the surface of water allows you to glide").getBoolean(true); + AIR_ACCELERATE = config.get(CATEGORY_MOVEMENT, AIR_ACCELERATE_NAME, AIR_ACCELERATE_DEFAULT, "a higher value means you can turn more sharply in the air without losing speed and vice versa; recommended: 14").getDouble(0.0D); + ACCELERATE = config.get(CATEGORY_MOVEMENT, ACCELERATE_NAME, ACCELERATE_DEFAULT, "a higher value means you accelerate faster on the ground and vice versa; recommended: 10").getDouble(0.0D); + HARD_CAP = (float)(config.get(CATEGORY_MOVEMENT, HARD_CAP_NAME, HARD_CAP_DEFAULT, "if you ever jump while above the hard cap speed (moveSpeed*hardCapThreshold), your speed is set to the hard cap speed; recommended: 1.8").getDouble(0.0D)); + SOFT_CAP = (float)(config.get(CATEGORY_MOVEMENT, SOFT_CAP_NAME, SOFT_CAP_DEFAULT, "particles spawn when you jump while above the soft cap, so to have uncapped bunnyhopping, set the soft cap degen to 1.0 instead of altering this value; recommended: 1.4").getDouble(1.0D)); + SOFT_CAP_DEGEN = (float)(config.get(CATEGORY_MOVEMENT, SOFT_CAP_DEGEN_NAME, SOFT_CAP_DEGEN_DEFAULT, "set to 1.0 for uncapped bunnyhop; recommended: 0.65").getDouble(1.0D)); + + SHARKING_ENABLED = config.get(CATEGORY_MOVEMENT, SHARKING_ENABLED_NAME, SHARKING_ENABLED_DEFAULT, "if enabled, holding jump while swimming at the surface of water allows you to glide").getBoolean(true); + SHARKING_WATER_FRICTION = 1.0D - config.get(CATEGORY_MOVEMENT, SHARKING_WATER_FRICTION_NAME, SHARKING_WATER_FRICTION_DEFAULT, "amount of friction while sharking (between 0 and 1); recommended: 0.1").getDouble(0.0D) * 0.05D; + SHARKING_SURFACE_TENSION = 1.0D - config.get(CATEGORY_MOVEMENT, SHARKING_SURFACE_TENSION_NAME, SHARKING_SURFACE_TENSION_DEFAULT, "amount of downward momentum you lose while entering water, a higher value means that you are able to shark after hitting the water from higher up; recommended: 0.2").getDouble(0.0D); + + TRIMPING_ENABLED = config.get(CATEGORY_MOVEMENT, TRIMPING_ENABLED_NAME, TRIMPING_ENABLED_DEFAULT, "if enabled, holding sneak while jumping will convert your horizontal speed into vertical speed").getBoolean(true); + TRIMP_MULTIPLIER = (float)(config.get(CATEGORY_MOVEMENT, TRIMP_MULTIPLIER_NAME, TRIMP_MULTIPLIER_DEFAULT, "a lower value means less horizontal speed converted to vertical speed and vice versa; recommended: 1.4").getDouble(TRIMP_MULTIPLIER_DEFAULT)); + + save(); + } + + public static void save() + { + config.save(); + } + + public static void load() + { + config.load(); + } +} diff --git a/java/squeek/quakemovement/ModQuakeMovement.java b/java/squeek/quakemovement/ModQuakeMovement.java new file mode 100644 index 0000000..c99b08a --- /dev/null +++ b/java/squeek/quakemovement/ModQuakeMovement.java @@ -0,0 +1,41 @@ +package squeek.mods.quakemovement; + +import api.player.client.ClientPlayerAPI; +import api.player.server.ServerPlayerAPI; +import cpw.mods.fml.client.FMLClientHandler; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.Mod.Instance; +import cpw.mods.fml.common.SidedProxy; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPostInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.network.NetworkMod; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +@Mod(modid="squeek_QuakeMovement", name="Quake Movement", version="0.1.0", dependencies="required-after:PlayerAPI") +@NetworkMod(clientSideRequired=true) +public class ModQuakeMovement { + + // The instance of your mod that Forge uses. + @Instance(value = "squeek_QuakeMovement") + public static ModQuakeMovement instance; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) { + ModConfig.init(event.getSuggestedConfigurationFile()); + } + + @EventHandler + public void load(FMLInitializationEvent event) { + } + + @EventHandler + public void postInit(FMLPostInitializationEvent event) { + ServerPlayerAPI.register("squeek_QuakeMovement", QuakeServerPlayer.class); + + if (event.getSide() == Side.CLIENT) + ClientPlayerAPI.register("squeek_QuakeMovement", QuakeClientPlayer.class); + } +} diff --git a/java/squeek/quakemovement/QuakeClientPlayer.java b/java/squeek/quakemovement/QuakeClientPlayer.java new file mode 100644 index 0000000..7a6e02e --- /dev/null +++ b/java/squeek/quakemovement/QuakeClientPlayer.java @@ -0,0 +1,745 @@ +package squeek.mods.quakemovement; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.MathHelper; +import api.player.client.ClientPlayerAPI; +import api.player.client.ClientPlayerBase; + +import java.lang.reflect.Method; +import cpw.mods.fml.common.Loader; + +public class QuakeClientPlayer extends ClientPlayerBase { + + // added member variables + public boolean didJumpThisTick = false; + + // the stuff + public QuakeClientPlayer(ClientPlayerAPI playerapi) + { + super(playerapi); + } + + public void moveEntityWithHeading( float sidemove, float forwardmove ) + { + double d0 = this.player.posX; + double d1 = this.player.posY; + double d2 = this.player.posZ; + + if (this.player.capabilities.isFlying && this.player.ridingEntity == null) + super.moveEntityWithHeading( sidemove, forwardmove ); + else + this.quake_moveEntityWithHeading(sidemove, forwardmove); + + this.player.addMovementStat(this.player.posX - d0, this.player.posY - d1, this.player.posZ - d2); + } + + public void beforeOnLivingUpdate() + { + this.didJumpThisTick = false; + if (Loader.isModLoaded("squeek_Speedometer")) + { + try { + Class guiSpeedometer = Class.forName("squeek.speedometer.GuiSpeedometer"); + Method setDidJumpThisTick = guiSpeedometer.getDeclaredMethod("setDidJumpThisTick", new Class[]{boolean.class}); + setDidJumpThisTick.invoke(null, false); + } catch(Exception e) { + e.printStackTrace(); + } + } + + super.beforeOnLivingUpdate(); + } + + public void onLivingUpdate() + { + if (Loader.isModLoaded("squeek_Speedometer")) + { + try { + Class guiSpeedometer = Class.forName("squeek.speedometer.GuiSpeedometer"); + Method setDidJumpThisTick = guiSpeedometer.getDeclaredMethod("setIsJumping", new Class[]{boolean.class}); + setDidJumpThisTick.invoke(null, this.playerAPI.getIsJumpingField()); + } catch(Exception e) { + e.printStackTrace(); + } + } + + super.onLivingUpdate(); + } + + public void jump() + { + super.jump(); + + // undo this dumb thing + if (this.player.isSprinting()) + { + float f = this.player.rotationYaw * 0.017453292F; + this.player.motionX += (double)(MathHelper.sin(f) * 0.2F); + this.player.motionZ -= (double)(MathHelper.cos(f) * 0.2F); + } + + quake_Jump(); + + this.didJumpThisTick = true; + if (Loader.isModLoaded("squeek_Speedometer")) + { + try { + Class guiSpeedometer = Class.forName("squeek.speedometer.GuiSpeedometer"); + Method setDidJumpThisTick = guiSpeedometer.getDeclaredMethod("setDidJumpThisTick", new Class[]{boolean.class}); + setDidJumpThisTick.invoke(null, true); + } catch(Exception e) { + e.printStackTrace(); + } + } + } + + /* ================================================= + * START HELPERS + * ================================================= + */ + + public double getSpeed() + { + return MathHelper.sqrt_double(this.player.motionX*this.player.motionX + this.player.motionZ*this.player.motionZ); + } + + public float getSurfaceFriction() + { + float f2 = 1.0F; + + if (this.player.onGround) + { + int j = this.player.worldObj.getBlockId(MathHelper.floor_double(this.player.posX), MathHelper.floor_double(this.player.boundingBox.minY) - 1, MathHelper.floor_double(this.player.posZ)); + + if (j > 0) + { + f2 = 1.0F - Block.blocksList[j].slipperiness; + } + } + + return f2; + } + + public float getSlipperiness() + { + float f2 = 0.91F; + if (this.player.onGround) + { + f2 = 0.54600006F; + int j = this.player.worldObj.getBlockId(MathHelper.floor_double(this.player.posX), MathHelper.floor_double(this.player.boundingBox.minY) - 1, MathHelper.floor_double(this.player.posZ)); + + if (j > 0) + { + f2 = Block.blocksList[j].slipperiness * 0.91F; + } + } + return f2; + } + + public float minecraft_getMoveSpeed() + { + float f2 = this.getSlipperiness(); + + float f3 = 0.16277136F / (f2 * f2 * f2); + + return this.player.getAIMoveSpeed() * f3; + } + + public float[] getMovementDirection( float sidemove, float forwardmove ) + { + float f3 = sidemove * sidemove + forwardmove * forwardmove; + float[] dir = { 0.0F, 0.0F }; + + if (f3 >= 1.0E-4F) + { + f3 = MathHelper.sqrt_float(f3); + + if (f3 < 1.0F) + { + f3 = 1.0F; + } + + f3 = 1.0F / f3; + sidemove *= f3; + forwardmove *= f3; + float f4 = MathHelper.sin(this.player.rotationYaw * (float)Math.PI / 180.0F); + float f5 = MathHelper.cos(this.player.rotationYaw * (float)Math.PI / 180.0F); + dir[0] = (sidemove * f5 - forwardmove * f4); + dir[1] = (forwardmove * f5 + sidemove * f4); + } + + return dir; + } + + public float quake_getMoveSpeed() + { + float baseSpeed = this.player.getAIMoveSpeed(); + return !this.player.isSneaking() ? baseSpeed*2.15F : baseSpeed*1.11F; + } + + public float quake_getMaxMoveSpeed() + { + float baseSpeed = this.player.getAIMoveSpeed(); + return baseSpeed*2.15F; + } + + private void spawnBunnyhopParticles( int numParticles ) + { + // taken from sprint + int j = MathHelper.floor_double(this.player.posX); + int i = MathHelper.floor_double(this.player.posY - 0.20000000298023224D - (double)this.player.yOffset); + int k = MathHelper.floor_double(this.player.posZ); + int l = this.player.worldObj.getBlockId(j, i, k); + + if (l > 0) + { + for( int iParticle=0; iParticle < numParticles; iParticle++ ) + { + this.player.worldObj.spawnParticle("tilecrack_" + l + "_" + this.player.worldObj.getBlockMetadata(j, i, k), this.player.posX + ((double)this.playerAPI.getRandField().nextFloat() - 0.5D) * (double)this.player.width, this.player.boundingBox.minY + 0.1D, this.player.posZ + ((double)this.playerAPI.getRandField().nextFloat() - 0.5D) * (double)this.player.width, -this.player.motionX * 4.0D, 1.5D, -this.player.motionZ * 4.0D); + } + } + } + + public boolean isJumping() + { + return this.playerAPI.getIsJumpingField(); + } + + /* ================================================= + * END HELPERS + * ================================================= + */ + + /* ================================================= + * START MINECRAFT PHYSICS + * ================================================= + */ + + private void minecraft_ApplyGravity() + { + if (this.player.worldObj.isRemote && (!this.player.worldObj.blockExists((int)this.player.posX, 0, (int)this.player.posZ) || !this.player.worldObj.getChunkFromBlockCoords((int)this.player.posX, (int)this.player.posZ).isChunkLoaded)) + { + if (this.player.posY > 0.0D) + { + this.player.motionY = -0.1D; + } + else + { + this.player.motionY = 0.0D; + } + } + else + { + // gravity + this.player.motionY -= 0.08D; + } + + // air resistance + this.player.motionY *= 0.9800000190734863D; + } + + private void minecraft_ApplyFriction( float momentumRetention ) + { + this.player.motionX *= momentumRetention; + this.player.motionZ *= momentumRetention; + } + + private void minecraft_ApplyLadderPhysics() + { + if (this.player.isOnLadder()) + { + float f5 = 0.15F; + + if (this.player.motionX < (double)(-f5)) + { + this.player.motionX = (double)(-f5); + } + + if (this.player.motionX > (double)f5) + { + this.player.motionX = (double)f5; + } + + if (this.player.motionZ < (double)(-f5)) + { + this.player.motionZ = (double)(-f5); + } + + if (this.player.motionZ > (double)f5) + { + this.player.motionZ = (double)f5; + } + + this.player.fallDistance = 0.0F; + + if (this.player.motionY < -0.15D) + { + this.player.motionY = -0.15D; + } + + boolean flag = this.player.isSneaking() && this.player instanceof EntityPlayer; + + if (flag && this.player.motionY < 0.0D) + { + this.player.motionY = 0.0D; + } + } + } + + private void minecraft_ClimbLadder() + { + if (this.player.isCollidedHorizontally && this.player.isOnLadder()) + { + this.player.motionY = 0.2D; + } + } + + private void minecraft_SwingLimbsBasedOnMovement() + { + this.player.prevLimbSwingAmount = this.player.limbSwingAmount; + double d0 = this.player.posX - this.player.prevPosX; + double d1 = this.player.posZ - this.player.prevPosZ; + float f6 = MathHelper.sqrt_double(d0 * d0 + d1 * d1) * 4.0F; + + if (f6 > 1.0F) + { + f6 = 1.0F; + } + + this.player.limbSwingAmount += (f6 - this.player.limbSwingAmount) * 0.4F; + this.player.limbSwing += this.player.limbSwingAmount; + } + + private void minecraft_WaterMove(float sidemove, float forwardmove) + { + double d0 = this.player.posY; + this.player.moveFlying(sidemove, forwardmove, 0.04F); + this.player.moveEntity(this.player.motionX, this.player.motionY, this.player.motionZ); + this.player.motionX *= 0.800000011920929D; + this.player.motionY *= 0.800000011920929D; + this.player.motionZ *= 0.800000011920929D; + this.player.motionY -= 0.02D; + + if (this.player.isCollidedHorizontally && this.player.isOffsetPositionInLiquid(this.player.motionX, this.player.motionY + 0.6000000238418579D - this.player.posY + d0, this.player.motionZ)) + { + this.player.motionY = 0.30000001192092896D; + } + } + + public void minecraft_moveEntityWithHeading(float sidemove, float forwardmove) + { + // take care of water and lava movement using default code + if ( (this.player.isInWater() && !this.player.capabilities.isFlying) + || (this.player.handleLavaMovement() && !this.player.capabilities.isFlying) ) + { + super.moveEntityWithHeading(sidemove, forwardmove); + } + else + { + // get friction + float momentumRetention = this.getSlipperiness(); + + // alter motionX/motionZ based on desired movement + this.player.moveFlying(sidemove, forwardmove, this.minecraft_getMoveSpeed()); + + // make adjustments for ladder interaction + minecraft_ApplyLadderPhysics(); + + // do the movement + this.player.moveEntity(this.player.motionX, this.player.motionY, this.player.motionZ); + + // climb ladder here for some reason + minecraft_ClimbLadder(); + + // gravity + friction + minecraft_ApplyGravity(); + minecraft_ApplyFriction( momentumRetention ); + + // swing them arms + minecraft_SwingLimbsBasedOnMovement(); + } + } + + /* ================================================= + * END MINECRAFT PHYSICS + * ================================================= + */ + + + /* ================================================= + * START QUAKE PHYSICS + * ================================================= + */ + + /** + * Moves the entity based on the specified heading. Args: strafe, forward + */ + public void quake_moveEntityWithHeading(float sidemove, float forwardmove) + { + // take care of lava movement using default code + if ( (this.player.handleLavaMovement() && !this.player.capabilities.isFlying) ) + { + super.moveEntityWithHeading(sidemove, forwardmove); + return; + } + else if (this.player.isInWater() && !this.player.capabilities.isFlying) + { + if (ModConfig.SHARKING_ENABLED) + quake_WaterMove(sidemove, forwardmove); + else + { + super.moveEntityWithHeading(sidemove, forwardmove); + return; + } + } + else + { + // get all relevant movement values + float wishspeed = (sidemove != 0.0F || forwardmove != 0.0F) ? this.quake_getMoveSpeed() : 0.0F; + float[] wishdir = this.getMovementDirection(sidemove, forwardmove); + boolean onGroundForReal = this.player.onGround && !this.isJumping(); + float momentumRetention = this.getSlipperiness(); + + // ground movement + if (onGroundForReal) + { + // apply friction before acceleration so we can accelerate back up to maxspeed afterwards + //quake_Friction(); // buggy because material-based friction uses a totally different format + minecraft_ApplyFriction( momentumRetention ); + + double sv_accelerate = ModConfig.ACCELERATE; + + if (wishspeed != 0.0F) + { + // alter based on the surface friction + sv_accelerate *= this.minecraft_getMoveSpeed()*2.15F / wishspeed; + + quake_Accelerate( wishspeed, wishdir[0], wishdir[1], sv_accelerate ); + } + } + // air movement + else + { + double sv_airaccelerate = ModConfig.AIR_ACCELERATE; + quake_AirAccelerate( wishspeed, wishdir[0], wishdir[1], sv_airaccelerate ); + + if (ModConfig.SHARKING_ENABLED && ModConfig.SHARKING_SURFACE_TENSION > 0.0D && this.playerAPI.getIsJumpingField() && this.player.motionY < 0.0F) + { + AxisAlignedBB axisalignedbb = this.player.boundingBox.getOffsetBoundingBox(this.player.motionX, this.player.motionY, this.player.motionZ); + boolean isFallingIntoWater = this.player.worldObj.isAnyLiquid(axisalignedbb); + + if (isFallingIntoWater) + this.player.motionY *= ModConfig.SHARKING_SURFACE_TENSION; + } + } + + // make adjustments for ladder interaction + minecraft_ApplyLadderPhysics(); + + // apply velocity + this.player.moveEntity(this.player.motionX, this.player.motionY, this.player.motionZ); + + // climb ladder here for some reason + minecraft_ClimbLadder(); + + // HL2 code applies half gravity before acceleration and half after acceleration, but this seems to work fine + minecraft_ApplyGravity(); + } + + // swing them arms + minecraft_SwingLimbsBasedOnMovement(); + } + + private void quake_Jump() + { + quake_ApplySoftCap( this.quake_getMaxMoveSpeed() ); + + boolean didTrimp = quake_DoTrimp(); + + if (!didTrimp) + { + quake_ApplyHardCap( this.quake_getMaxMoveSpeed() ); + } + } + + private boolean quake_DoTrimp() + { + if (ModConfig.TRIMPING_ENABLED && this.player.isSneaking()) + { + double curspeed = this.getSpeed(); + float movespeed = this.quake_getMaxMoveSpeed(); + if (curspeed > movespeed) + { + double speedbonus = curspeed/movespeed*0.5F; + if (speedbonus > 1.0F) + speedbonus = 1.0F; + + this.player.motionY += speedbonus * curspeed * ModConfig.TRIMP_MULTIPLIER; + + if (ModConfig.TRIMP_MULTIPLIER > 0) + { + float mult = 1.0f / ModConfig.TRIMP_MULTIPLIER; + this.player.motionX *= mult; + this.player.motionZ *= mult; + } + + spawnBunnyhopParticles( 30 ); + + return true; + } + } + + return false; + } + + private void quake_ApplyWaterFriction( double friction ) + { + this.player.motionX *= friction; + this.player.motionY *= friction; + this.player.motionZ *= friction; + + /* + float speed = (float)(this.player.getSpeed()); + float newspeed = 0.0F; + if (speed != 0.0F) + { + newspeed = speed - 0.05F * speed * friction; //* player->m_surfaceFriction; + + float mult = newspeed/speed; + this.player.motionX *= mult; + this.player.motionY *= mult; + this.player.motionZ *= mult; + } + + return newspeed; + */ + + /* + // slow in water + this.player.motionX *= 0.800000011920929D; + this.player.motionY *= 0.800000011920929D; + this.player.motionZ *= 0.800000011920929D; + */ + } + + private void quake_WaterAccelerate( float wishspeed, float speed, double wishX, double wishZ, double accel ) + { + float addspeed = wishspeed - speed; + if (addspeed > 0) + { + float accelspeed = (float)(accel * wishspeed * 0.05F); + if (accelspeed > addspeed) + { + accelspeed = addspeed; + } + + this.player.motionX += accelspeed * wishX; + this.player.motionZ += accelspeed * wishZ; + } + } + + private void quake_WaterMove( float sidemove, float forwardmove ) + { + double lastPosY = this.player.posY; + + // get all relevant movement values + float wishspeed = (sidemove != 0.0F || forwardmove != 0.0F) ? this.quake_getMaxMoveSpeed() : 0.0F; + float[] wishdir = this.getMovementDirection(sidemove, forwardmove); + boolean isSharking = this.isJumping() && this.player.isOffsetPositionInLiquid(0.0D, 1.0D, 0.0D); + double curspeed = this.getSpeed(); + + if (!isSharking || curspeed < 0.078F) + { + minecraft_WaterMove(sidemove, forwardmove); + } + else + { + if (curspeed > 0.09) + quake_ApplyWaterFriction( ModConfig.SHARKING_WATER_FRICTION ); + + if (curspeed > 0.098) + quake_AirAccelerate( wishspeed, wishdir[0], wishdir[1], ModConfig.ACCELERATE ); + else + quake_Accelerate( .0980F, wishdir[0], wishdir[1], ModConfig.ACCELERATE ); + + this.player.moveEntity(this.player.motionX, this.player.motionY, this.player.motionZ); + + this.player.motionY = 0.0D; + } + + // water jump + if (this.player.isCollidedHorizontally && this.player.isOffsetPositionInLiquid(this.player.motionX, this.player.motionY + 0.6000000238418579D - this.player.posY + lastPosY, this.player.motionZ)) + { + this.player.motionY = 0.30000001192092896D; + } + } + + private void quake_Accelerate( float wishspeed, double wishX, double wishZ, double accel ) + { + int i; + double addspeed, accelspeed, currentspeed; + + // Determine veer amount + // this is a dot product + currentspeed = this.player.motionX * wishX + this.player.motionZ * wishZ; + + // See how much to add + addspeed = wishspeed - currentspeed; + + // If not adding any, done. + if (addspeed <= 0) + return; + + // Determine acceleration speed after acceleration + accelspeed = accel * wishspeed * 0.05F; + + // Cap it + if (accelspeed > addspeed) + accelspeed = addspeed; + + // Adjust pmove vel. + this.player.motionX += accelspeed * wishX; + this.player.motionZ += accelspeed * wishZ; + } + + private void quake_AirAccelerate( float wishspeed, double wishX, double wishZ, double accel ) + { + int i; + double addspeed, accelspeed, currentspeed; + + float wishspd = wishspeed; + float maxAirAcceleration = 0.03F; + + if (wishspd > maxAirAcceleration) + wishspd = maxAirAcceleration; + + // Determine veer amount + // this is a dot product + currentspeed = this.player.motionX * wishX + this.player.motionZ * wishZ; + + // See how much to add + addspeed = wishspd - currentspeed; + + // If not adding any, done. + if (addspeed <= 0) + return; + + // Determine acceleration speed after acceleration + accelspeed = accel * wishspeed * 0.05F; + + // Cap it + if (accelspeed > addspeed) + accelspeed = addspeed; + + // Adjust pmove vel. + this.player.motionX += accelspeed * wishX; + this.player.motionZ += accelspeed * wishZ; + } + + private void quake_Friction() + { + double speed, newspeed, control; + float friction; + float drop; + + // Calculate speed + speed = this.getSpeed(); + + // If too slow, return + if (speed <= 0.0F) + { + return; + } + + drop = 0.0F; + + // convars + float sv_friction = 1.0F; + float sv_stopspeed = 0.005F; + + float surfaceFriction = this.getSurfaceFriction(); + friction = sv_friction * surfaceFriction; + + // Bleed off some speed, but if we have less than the bleed + // threshold, bleed the threshold amount. + control = (speed < sv_stopspeed) ? sv_stopspeed : speed; + + // Add the amount to the drop amount. + drop += control*friction*0.05F; + + // scale the velocity + newspeed = speed - drop; + if (newspeed < 0.0F) + newspeed = 0.0F; + + if ( newspeed != speed ) + { + // Determine proportion of old speed we are using. + newspeed /= speed; + // Adjust velocity according to proportion. + this.player.motionX *= newspeed; + this.player.motionZ *= newspeed; + } + } + + private void quake_ApplySoftCap( float movespeed ) + { + float softCapPercent = ModConfig.SOFT_CAP; + float softCapDegen = ModConfig.SOFT_CAP_DEGEN; + + if (ModConfig.UNCAPPED_BUNNYHOP_ENABLED) + { + softCapPercent = 1.0F; + softCapDegen = 1.0F; + } + + float speed = (float)(this.getSpeed()); + float softCap = movespeed * softCapPercent; + + // apply soft cap first; if soft -> hard is not done, then you can continually trigger only the hard cap and stay at the hard cap + if (speed > softCap) + { + if (softCapDegen != 1.0F) + { + float applied_cap = (speed - softCap) * softCapDegen + softCap; + float multi = applied_cap / speed; + this.player.motionX *= multi; + this.player.motionZ *= multi; + } + + spawnBunnyhopParticles( 10 ); + } + } + + private void quake_ApplyHardCap( float movespeed ) + { + if (ModConfig.UNCAPPED_BUNNYHOP_ENABLED) + return; + + float hardCapPercent = ModConfig.HARD_CAP; + + float speed = (float)(this.getSpeed()); + float hardCap = movespeed * hardCapPercent; + + if (speed > hardCap && hardCap != 0.0F) + { + float multi = hardCap / speed; + this.player.motionX *= multi; + this.player.motionZ *= multi; + + spawnBunnyhopParticles( 30 ); + } + } + + private void quake_OnLivingUpdate() + { + this.didJumpThisTick = false; + } + + /* ================================================= + * END QUAKE PHYSICS + * ================================================= + */ +} diff --git a/java/squeek/quakemovement/QuakeServerPlayer.java b/java/squeek/quakemovement/QuakeServerPlayer.java new file mode 100644 index 0000000..add71f4 --- /dev/null +++ b/java/squeek/quakemovement/QuakeServerPlayer.java @@ -0,0 +1,30 @@ +package squeek.mods.quakemovement; + +import api.player.server.ServerPlayerAPI; +import api.player.server.ServerPlayerBase; + +public class QuakeServerPlayer extends ServerPlayerBase { + + private boolean wasVelocityChangedBeforeFall = false; + public boolean isFallDistanceLeniencyEnabled = false; + public float increasedFallDistanceLeniency = 3.0F; + + public QuakeServerPlayer(ServerPlayerAPI playerapi) + { + super(playerapi); + } + + public void fall( float fallDistance ) + { + wasVelocityChangedBeforeFall = this.playerAPI.getVelocityChangedField() || this.player.velocityChanged; + + if (isFallDistanceLeniencyEnabled) + { + fallDistance -= increasedFallDistanceLeniency; + } + super.fall( fallDistance ); + + this.playerAPI.setVelocityChangedField(wasVelocityChangedBeforeFall); + this.player.velocityChanged = wasVelocityChangedBeforeFall; + } +} diff --git a/resources/mcmod.info b/resources/mcmod.info new file mode 100644 index 0000000..64ab019 --- /dev/null +++ b/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "QuakeMovement", + "name": "Quake Movement", + "description": "A quake movement.", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "", + "updateUrl": "", + "authors": ["squeek"], + "credits": "", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +]