diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 663a49257..c44b30170 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -151,9 +151,7 @@ - - - + @@ -343,7 +341,6 @@ - diff --git a/ClassicalSharp/Entities/Components/PhysicsComponent.cs b/ClassicalSharp/Entities/Components/PhysicsComponent.cs index 26af64473..472a2c62f 100644 --- a/ClassicalSharp/Entities/Components/PhysicsComponent.cs +++ b/ClassicalSharp/Entities/Components/PhysicsComponent.cs @@ -25,9 +25,7 @@ namespace ClassicalSharp.Entities { info = game.BlockInfo; } - public void UpdateVelocityState(float xMoving, float zMoving) { - if (!hacks.NoclipSlide && (hacks.Noclip && xMoving == 0 && zMoving == 0)) - entity.Velocity = Vector3.Zero; + public void UpdateVelocityState() { if (hacks.Flying || hacks.Noclip) { entity.Velocity.Y = 0; // eliminate the effect of gravity int dir = (hacks.FlyingUp || jumping) ? 1 : (hacks.FlyingDown ? -1 : 0); @@ -104,7 +102,7 @@ namespace ClassicalSharp.Entities { airDrag = new Vector3(0.6f, 1f, 0.6f); const float liquidGrav = 0.02f, ropeGrav = 0.034f, normalGrav = 0.08f; - public void PhysicsTick(float xMoving, float zMoving) { + public void PhysicsTick(Vector3 vel) { if (hacks.Noclip) entity.onGround = false; float multiply = GetBaseMultiply(true); float yMultiply = GetBaseMultiply(hacks.CanSpeed); @@ -118,18 +116,20 @@ namespace ClassicalSharp.Entities { } if (entity.TouchesAnyWater() && !hacks.Flying && !hacks.Noclip) { - MoveNormal(xMoving, zMoving, 0.02f * horMul, waterDrag, liquidGrav, yMul); + MoveNormal(vel, 0.02f * horMul, waterDrag, liquidGrav, yMul); } else if (entity.TouchesAnyLava() && !hacks.Flying && !hacks.Noclip) { - MoveNormal(xMoving, zMoving, 0.02f * horMul, lavaDrag, liquidGrav, yMul); + MoveNormal(vel, 0.02f * horMul, lavaDrag, liquidGrav, yMul); } else if (entity.TouchesAnyRope() && !hacks.Flying && !hacks.Noclip) { - MoveNormal(xMoving, zMoving, 0.02f * 1.7f, ropeDrag, ropeGrav, yMul); + MoveNormal(vel, 0.02f * 1.7f, ropeDrag, ropeGrav, yMul); } else { float factor = !(hacks.Flying || hacks.Noclip) && entity.onGround ? 0.1f : 0.02f; float gravity = useLiquidGravity ? liquidGrav : normalGrav; - if (hacks.Flying || hacks.Noclip) - MoveFlying(xMoving, zMoving, factor * horMul, normalDrag, gravity, yMul); - else - MoveNormal(xMoving, zMoving, factor * horMul, normalDrag, gravity, yMul); + + if (hacks.Flying || hacks.Noclip) { + MoveFlying(vel, factor * horMul, normalDrag, gravity, yMul); + } else { + MoveNormal(vel, factor * horMul, normalDrag, gravity, yMul); + } if (entity.BlockUnderFeet == Block.Ice && !(hacks.Flying || hacks.Noclip)) { // limit components to +-0.25f by rescaling vector to [-0.25, 0.25] @@ -147,20 +147,19 @@ namespace ClassicalSharp.Entities { if (entity.onGround) { firstJump = false; secondJump = false; } } - void AdjHeadingVelocity(float x, float z, float factor) { - float dist = (float)Math.Sqrt(x * x + z * z); + void MoveHor(Vector3 vel, float factor) { + float dist = (float)Math.Sqrt(vel.X * vel.X + vel.Z * vel.Z); if (dist < 0.00001f) return; if (dist < 1) dist = 1; - - float multiply = factor / dist; - entity.Velocity += Utils.RotateY(x * multiply, 0, z * multiply, entity.HeadYRadians); + + entity.Velocity += vel * (factor / dist); } - void MoveFlying(float xMoving, float zMoving, float factor, Vector3 drag, float gravity, float yMul) { - AdjHeadingVelocity(zMoving, xMoving, factor); + void MoveFlying(Vector3 vel, float factor, Vector3 drag, float gravity, float yMul) { + MoveHor(vel, factor); float yVel = (float)Math.Sqrt(entity.Velocity.X * entity.Velocity.X + entity.Velocity.Z * entity.Velocity.Z); // make horizontal speed the same as vertical speed. - if ((xMoving != 0 || zMoving != 0) && yVel > 0.001f) { + if ((vel.X != 0 || vel.Z != 0) && yVel > 0.001f) { entity.Velocity.Y = 0; yMul = 1; if (hacks.FlyingUp || jumping) entity.Velocity.Y += yVel; @@ -169,8 +168,8 @@ namespace ClassicalSharp.Entities { Move(drag, gravity, yMul); } - void MoveNormal(float xMoving, float zMoving, float factor, Vector3 drag, float gravity, float yMul) { - AdjHeadingVelocity(zMoving, xMoving, factor); + void MoveNormal(Vector3 vel, float factor, Vector3 drag, float gravity, float yMul) { + MoveHor(vel, factor); Move(drag, gravity, yMul); } @@ -269,9 +268,9 @@ namespace ClassicalSharp.Entities { public void DoEntityPush() { if (!game.ClassicMode || hacks.Noclip) return; - for (int id = 0; id < EntityList.SelfID; id++) { + for (int id = 0; id < EntityList.MaxCount; id++) { Entity other = game.Entities[id]; - if (other == null) continue; + if (other == null || other == entity) continue; bool yIntersects = entity.Position.Y <= (other.Position.Y + other.Size.Y) && diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs index 2bb2c5db0..a933e1901 100644 --- a/ClassicalSharp/Entities/LocalPlayer.cs +++ b/ClassicalSharp/Entities/LocalPlayer.cs @@ -60,8 +60,12 @@ namespace ClassicalSharp.Entities { HandleInput(ref xMoving, ref zMoving); physics.DoEntityPush(); - physics.UpdateVelocityState(xMoving, zMoving); - physics.PhysicsTick(xMoving, zMoving); + + // Immediate stop in noclip mode + if (!Hacks.NoclipSlide && (Hacks.Noclip && xMoving == 0 && zMoving == 0)) + Velocity = Vector3.Zero; + physics.UpdateVelocityState(); + physics.PhysicsTick(GetHeadingVelocity(zMoving, xMoving)); interp.next.Pos = Position; Position = interp.prev.Pos; anim.UpdateAnimState(interp.prev.Pos, interp.next.Pos, delta); @@ -69,6 +73,11 @@ namespace ClassicalSharp.Entities { CheckSkin(); sound.Tick(wasOnGround); } + + Vector3 GetHeadingVelocity(float xMoving, float zMoving) { + return Utils.RotateY(xMoving, 0, zMoving, HeadYRadians); + } + public override void RenderModel(double deltaTime, float t) { anim.GetCurrentAnimState(t); diff --git a/ClassicalSharp/Entities/Mobs/AI.cs b/ClassicalSharp/Entities/Mobs/AI.cs new file mode 100644 index 000000000..7775f127f --- /dev/null +++ b/ClassicalSharp/Entities/Mobs/AI.cs @@ -0,0 +1,82 @@ +// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 +using System; +using OpenTK; + +namespace ClassicalSharp.Entities.Mobs { + + public abstract class AI { + + protected Game game; + protected Entity entity; + static Random random = new Random(); + + public Vector3 MoveVelocity; + + public AI(Game game, Entity entity) { + this.game = game; + this.entity = entity; + } + + public abstract void Tick(Entity target); + + public abstract void AttackedBy(Entity source); + + + int randomCount; + Vector3 randomDir; + protected void MoveRandomly(Entity source) { + // Move in new direction + if (randomCount == 0) { + randomDir.X = (float)(random.NextDouble() - 0.5); + randomDir.Z = (float)(random.NextDouble() - 0.5); + } + + randomCount = (randomCount + 1) & 0x1F; + MoveInDirection(source, randomDir); + } + + protected void MoveInDirection(Entity source, Vector3 dir) { + double rotYRadians, headXRadians; + Utils.GetHeading(dir, out rotYRadians, out headXRadians); + + float rotY = (float)(rotYRadians * Utils.Rad2Deg); + float headX = (float)(headXRadians * Utils.Rad2Deg); + LocationUpdate update = LocationUpdate.MakeOri(rotY, headX); + source.SetLocation(update, false); + MoveVelocity = dir * 0.9f; + } + } + + public sealed class FleeAI : AI { + + public FleeAI(Game game, Entity entity) : base(game, entity) { } + + public override void Tick(Entity target) { + MoveRandomly(entity); + } + + public override void AttackedBy(Entity source) { + Vector3 fleeDir = -Vector3.Normalize(source.Position - entity.Position); + MoveInDirection(source, fleeDir * 5); + } + } + + public sealed class HostileAI : AI { + + public HostileAI(Game game, Entity entity) : base(game, entity) { } + + public override void Tick(Entity target) { + float distSq = (target.Position - entity.Position).LengthSquared; + if (distSq > 32 * 32) { + MoveRandomly(entity); + } else { + Vector3 dir = Vector3.Normalize(target.Position - entity.Position); + dir.Y = 0; + MoveInDirection(entity, dir); + } + } + + public override void AttackedBy(Entity source) { + } + } +} \ No newline at end of file diff --git a/ClassicalSharp/Entities/Mobs/AI/AI.cs b/ClassicalSharp/Entities/Mobs/AI/AI.cs deleted file mode 100644 index d651c6865..000000000 --- a/ClassicalSharp/Entities/Mobs/AI/AI.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 -using System; -using OpenTK; - -namespace ClassicalSharp.Entities.Mobs { - - public abstract class AI { - - protected Game game; - protected Entity entity; - static Random random = new Random(); - - public AI(Game game, Entity entity) { - this.game = game; - this.entity = entity; - } - - public abstract void Tick(Entity target); - - public abstract void AttackedBy(Entity source); - - protected static void MoveRandomly(Entity source) { - double dirX = random.NextDouble() - 0.5, dirZ = random.NextDouble() - 0.5; - MoveInDirection(source, new Vector3((float)dirX, 0, (float)dirZ)); - } - - protected static void MoveInDirection(Entity source, Vector3 dir) { - double rotYRadians, headXRadians; - Utils.GetHeading(dir, out rotYRadians, out headXRadians); - - float rotY = (float)(rotYRadians * Utils.Rad2Deg); - float headX = (float)(headXRadians * Utils.Rad2Deg); - LocationUpdate update = LocationUpdate.MakePosAndOri(dir, rotY, headX, true); - source.SetLocation(update, false); - } - } -} \ No newline at end of file diff --git a/ClassicalSharp/Entities/Mobs/AI/FleeAI.cs b/ClassicalSharp/Entities/Mobs/AI/FleeAI.cs deleted file mode 100644 index 455bf2c7d..000000000 --- a/ClassicalSharp/Entities/Mobs/AI/FleeAI.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 -using System; -using OpenTK; - -namespace ClassicalSharp.Entities.Mobs { - - public sealed class FleeAI : AI { - - public FleeAI(Game game, Entity entity) : base(game, entity) { } - - public override void Tick(Entity target) { - MoveRandomly(entity); - } - - public override void AttackedBy(Entity source) { - Vector3 fleeDir = -Vector3.Normalize(source.Position - entity.Position); - MoveInDirection(source, fleeDir * 5); - } - } -} diff --git a/ClassicalSharp/Entities/Mobs/AI/HostileAI.cs b/ClassicalSharp/Entities/Mobs/AI/HostileAI.cs deleted file mode 100644 index fa38119f0..000000000 --- a/ClassicalSharp/Entities/Mobs/AI/HostileAI.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 -using System; -using OpenTK; - -namespace ClassicalSharp.Entities.Mobs { - - public sealed class HostileAI : AI { - - public HostileAI(Game game, Entity entity) : base(game, entity) { } - - public override void Tick(Entity target) { - float distSq = (target.Position - entity.Position).LengthSquared; - if (distSq > 32 * 32) { - MoveRandomly(entity); - } else { - Vector3 dir = Vector3.Normalize(target.Position - entity.Position); - MoveInDirection(entity, dir); - } - } - - public override void AttackedBy(Entity source) { - } - } -} diff --git a/ClassicalSharp/Entities/Mobs/MobEntity.cs b/ClassicalSharp/Entities/Mobs/MobEntity.cs index 8db1c7227..6f928d996 100644 --- a/ClassicalSharp/Entities/Mobs/MobEntity.cs +++ b/ClassicalSharp/Entities/Mobs/MobEntity.cs @@ -10,6 +10,7 @@ namespace ClassicalSharp.Entities.Mobs { CollisionsComponent collisions; PhysicsComponent physics; static HacksComponent hacks = new HacksComponent(null, null); + AI ai; public MobEntity(Game game, string model) : base(game) { StepSize = 0.5f; @@ -20,6 +21,12 @@ namespace ClassicalSharp.Entities.Mobs { physics = new PhysicsComponent(game, this); physics.hacks = hacks; physics.collisions = collisions; + + if (Utils.CaselessEquals(model, "pig") || Utils.CaselessEquals(model, "sheep")) { + ai = new FleeAI(game, this); + } else { + ai = new HostileAI(game, this); + } } public override void Despawn() { } @@ -29,11 +36,11 @@ namespace ClassicalSharp.Entities.Mobs { static Random rand = new Random(); public override void Tick(double delta) { if (game.World.IsNotLoaded) return; - float xMoving = 0.98f, zMoving = 0.98f; interp.AdvanceState(); - bool wasOnGround = onGround; - physics.UpdateVelocityState(xMoving, zMoving); - physics.PhysicsTick(xMoving, zMoving); + physics.UpdateVelocityState(); + + ai.Tick(game.LocalPlayer); + physics.PhysicsTick(ai.MoveVelocity); interp.next.Pos = Position; Position = interp.prev.Pos; anim.UpdateAnimState(interp.prev.Pos, interp.next.Pos, delta); } diff --git a/ClassicalSharp/Utils/Utils.Math.cs b/ClassicalSharp/Utils/Utils.Math.cs index 09ac7fad4..5d42e85c5 100644 --- a/ClassicalSharp/Utils/Utils.Math.cs +++ b/ClassicalSharp/Utils/Utils.Math.cs @@ -128,7 +128,7 @@ namespace ClassicalSharp { public static void GetHeading(Vector3 dir, out double yaw, out double pitch) { pitch = Math.Asin(-dir.Y); - yaw = Math.Atan2(dir.Z, dir.X); + yaw = Math.Atan2(dir.X, -dir.Z); } public static int Floor(float value) {