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) {