diff --git a/ClassicalSharp/2D/Utils/FastColour.cs b/ClassicalSharp/2D/Utils/FastColour.cs
index 2021ed48a..13d916dd6 100644
--- a/ClassicalSharp/2D/Utils/FastColour.cs
+++ b/ClassicalSharp/2D/Utils/FastColour.cs
@@ -82,7 +82,7 @@ namespace ClassicalSharp {
public int ToArgb() { return A << 24 | R << 16 | G << 8 | B; }
public static FastColour Argb(int c) {
- FastColour col = default(FastColour);
+ FastColour col;
col.A = (byte)(c >> 24);
col.R = (byte)(c >> 16);
col.G = (byte)(c >> 8);
@@ -102,7 +102,7 @@ namespace ClassicalSharp {
}
public static FastColour Unpack(int c) {
- FastColour col = default(FastColour);
+ FastColour col;
col.A = (byte)(c >> 24);
col.G = (byte)(c >> 8);
#if USE_DX
diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index 50509552a..8d61d5631 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -144,7 +144,6 @@
-
diff --git a/ClassicalSharp/Entities/Components/AnimatedComponent.cs b/ClassicalSharp/Entities/Components/AnimatedComponent.cs
index 0f25e1779..3649b954a 100644
--- a/ClassicalSharp/Entities/Components/AnimatedComponent.cs
+++ b/ClassicalSharp/Entities/Components/AnimatedComponent.cs
@@ -117,7 +117,7 @@ namespace ClassicalSharp.Entities {
// TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second
for (int i = 0; i < 3; i++) {
- AnimatedComponent.DoTilt(ref velTiltStrengthN, p.Hacks.Noclip || p.Hacks.Flying);
+ AnimatedComponent.DoTilt(ref velTiltStrengthN, p.Hacks.Floating);
}
}
diff --git a/ClassicalSharp/Entities/Components/CollisionsComponent.cs b/ClassicalSharp/Entities/Components/CollisionsComponent.cs
index 3d98fde9b..bd72d9fe9 100644
--- a/ClassicalSharp/Entities/Components/CollisionsComponent.cs
+++ b/ClassicalSharp/Entities/Components/CollisionsComponent.cs
@@ -111,7 +111,7 @@ namespace ClassicalSharp.Entities {
}
void ClipXMin(ref AABB blockBB, ref AABB entityBB, bool wasOn, ref AABB finalBB, ref AABB extentBB, ref Vector3 size) {
- if (!wasOn || !DidSlide(blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
+ if (!wasOn || !DidSlide(ref blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
entity.Position.X = blockBB.Min.X - size.X / 2 - Adjustment;
ClipX(ref size, ref entityBB, ref extentBB);
hitXMin = true;
@@ -119,7 +119,7 @@ namespace ClassicalSharp.Entities {
}
void ClipXMax(ref AABB blockBB, ref AABB entityBB, bool wasOn, ref AABB finalBB, ref AABB extentBB, ref Vector3 size) {
- if (!wasOn || !DidSlide(blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
+ if (!wasOn || !DidSlide(ref blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
entity.Position.X = blockBB.Max.X + size.X / 2 + Adjustment;
ClipX(ref size, ref entityBB, ref extentBB);
hitXMax = true;
@@ -127,7 +127,7 @@ namespace ClassicalSharp.Entities {
}
void ClipZMax(ref AABB blockBB, ref AABB entityBB, bool wasOn, ref AABB finalBB, ref AABB extentBB, ref Vector3 size) {
- if (!wasOn || !DidSlide(blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
+ if (!wasOn || !DidSlide(ref blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
entity.Position.Z = blockBB.Max.Z + size.Z / 2 + Adjustment;
ClipZ(ref size, ref entityBB, ref extentBB);
hitZMax = true;
@@ -135,7 +135,7 @@ namespace ClassicalSharp.Entities {
}
void ClipZMin(ref AABB blockBB, ref AABB entityBB, bool wasOn, ref AABB finalBB, ref AABB extentBB, ref Vector3 size) {
- if (!wasOn || !DidSlide(blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
+ if (!wasOn || !DidSlide(ref blockBB, ref size, ref finalBB, ref entityBB, ref extentBB)) {
entity.Position.Z = blockBB.Min.Z - size.Z / 2 - Adjustment;
ClipZ(ref size, ref entityBB, ref extentBB);
hitZMin = true;
@@ -155,26 +155,24 @@ namespace ClassicalSharp.Entities {
hitYMax = true;
}
- bool DidSlide(AABB blockBB, ref Vector3 size, ref AABB finalBB, ref AABB entityBB, ref AABB extentBB) {
+ bool DidSlide(ref AABB blockBB, ref Vector3 size, ref AABB finalBB, ref AABB entityBB, ref AABB extentBB) {
float yDist = blockBB.Max.Y - entityBB.Min.Y;
if (yDist > 0 && yDist <= entity.StepSize + 0.01f) {
- float blockXMin = blockBB.Min.X, blockZMin = blockBB.Min.Z;
- blockBB.Min.X = Math.Max(blockBB.Min.X, blockBB.Max.X - size.X / 2);
- blockBB.Max.X = Math.Min(blockBB.Max.X, blockXMin + size.X / 2);
- blockBB.Min.Z = Math.Max(blockBB.Min.Z, blockBB.Max.Z - size.Z / 2);
- blockBB.Max.Z = Math.Min(blockBB.Max.Z, blockZMin + size.Z / 2);
+ float blockBB_MinX = Math.Max(blockBB.Min.X, blockBB.Max.X - size.X / 2);
+ float blockBB_MaxX = Math.Min(blockBB.Max.X, blockBB.Min.X + size.X / 2);
+ float blockBB_MinZ = Math.Max(blockBB.Min.Z, blockBB.Max.Z - size.Z / 2);
+ float blockBB_MaxZ = Math.Min(blockBB.Max.Z, blockBB.Min.Z + size.Z / 2);
AABB adjBB;
- adjBB.Min.X = Math.Min(finalBB.Min.X, blockBB.Min.X + Adjustment);
- adjBB.Max.X = Math.Max(finalBB.Max.X, blockBB.Max.X - Adjustment);
+ adjBB.Min.X = Math.Min(finalBB.Min.X, blockBB_MinX + Adjustment);
+ adjBB.Max.X = Math.Max(finalBB.Max.X, blockBB_MaxX - Adjustment);
adjBB.Min.Y = blockBB.Max.Y + Adjustment;
adjBB.Max.Y = adjBB.Min.Y + size.Y;
- adjBB.Min.Z = Math.Min(finalBB.Min.Z, blockBB.Min.Z + Adjustment);
- adjBB.Max.Z = Math.Max(finalBB.Max.Z, blockBB.Max.Z - Adjustment);
+ adjBB.Min.Z = Math.Min(finalBB.Min.Z, blockBB_MinZ + Adjustment);
+ adjBB.Max.Z = Math.Max(finalBB.Max.Z, blockBB_MaxZ - Adjustment);
- if (!CanSlideThrough(ref adjBB)) return false;
-
- entity.Position.Y = blockBB.Max.Y + Adjustment;
+ if (!CanSlideThrough(ref adjBB)) return false;
+ entity.Position.Y = adjBB.Min.Y;
entity.onGround = true;
ClipY(ref size, ref entityBB, ref extentBB);
return true;
@@ -187,13 +185,15 @@ namespace ClassicalSharp.Entities {
Vector3I bbMax = Vector3I.Floor(adjFinalBB.Max);
AABB blockBB;
+ Vector3 pos;
for (int y = bbMin.Y; y <= bbMax.Y; y++)
for (int z = bbMin.Z; z <= bbMax.Z; z++)
for (int x = bbMin.X; x <= bbMax.X; x++)
{
+ pos.X = x; pos.Y = y; pos.Z = z;
BlockID block = game.World.GetPhysicsBlock(x, y, z);
- blockBB.Min = new Vector3(x, y, z) + BlockInfo.MinBB[block];
- blockBB.Max = new Vector3(x, y, z) + BlockInfo.MaxBB[block];
+ blockBB.Min = pos + BlockInfo.MinBB[block];
+ blockBB.Max = pos + BlockInfo.MaxBB[block];
if (!blockBB.Intersects(adjFinalBB)) continue;
if (BlockInfo.Collide[block] == CollideType.Solid) return false;
diff --git a/ClassicalSharp/Entities/Components/HacksComponent.cs b/ClassicalSharp/Entities/Components/HacksComponent.cs
index a3b10b417..12e4af476 100644
--- a/ClassicalSharp/Entities/Components/HacksComponent.cs
+++ b/ClassicalSharp/Entities/Components/HacksComponent.cs
@@ -51,7 +51,7 @@ namespace ClassicalSharp.Entities {
public bool Noclip, Flying, FlyingUp, FlyingDown, Speeding, HalfSpeeding;
public bool CanJumpHigher { get { return Enabled && CanAnyHacks && CanSpeed; } }
- public bool Floating { get { return Noclip || Flying; } }
+ public bool Floating; // true if Noclip or Flying
public string HacksFlags;
string GetFlagValue(string flag) {
diff --git a/ClassicalSharp/Entities/Components/InputComponent.cs b/ClassicalSharp/Entities/Components/InputComponent.cs
deleted file mode 100644
index fdca5222d..000000000
--- a/ClassicalSharp/Entities/Components/InputComponent.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
-using System;
-using ClassicalSharp.Physics;
-using OpenTK;
-using OpenTK.Input;
-using BlockID = System.UInt16;
-
-namespace ClassicalSharp.Entities {
-
- /// Entity component that performs input handling.
- public sealed class InputComponent {
-
- Entity entity;
- Game game;
- public HacksComponent Hacks;
- public PhysicsComponent physics;
-
- public InputComponent(Game game, Entity entity) {
- this.game = game;
- this.entity = entity;
- }
-
- internal bool Handles(Key key) {
- LocalPlayer p = (LocalPlayer)entity;
- KeyMap keys = game.Input.Keys;
-
- if (key == keys[KeyBind.Respawn] && Hacks.CanRespawn) {
- DoRespawn();
- } else if (key == keys[KeyBind.SetSpawn] && Hacks.CanRespawn) {
- p.Spawn = entity.Position;
- p.Spawn.X = Utils.Floor(p.Spawn.X) + 0.5f;
- p.Spawn.Z = Utils.Floor(p.Spawn.Z) + 0.5f;
- p.SpawnRotY = entity.RotY;
- p.SpawnHeadX = entity.HeadX;
- DoRespawn();
- } else if (key == keys[KeyBind.Fly] && Hacks.CanFly && Hacks.Enabled) {
- Hacks.Flying = !Hacks.Flying;
- } else if (key == keys[KeyBind.NoClip] && Hacks.CanNoclip && Hacks.Enabled && !Hacks.WOMStyleHacks) {
- if (Hacks.Noclip) entity.Velocity.Y = 0;
- Hacks.Noclip = !Hacks.Noclip;
- } else if (key == keys[KeyBind.Jump] && !entity.onGround && !(Hacks.Flying || Hacks.Noclip)) {
- int maxJumps = Hacks.CanDoubleJump && Hacks.WOMStyleHacks ? 2 : 0;
- maxJumps = Math.Max(maxJumps, Hacks.MaxJumps - 1);
-
- if (physics.multiJumps < maxJumps) {
- physics.DoNormalJump();
- physics.multiJumps++;
- }
- } else {
- return false;
- }
- return true;
- }
-
- void DoRespawn() {
- if (!game.World.HasBlocks) return;
- LocalPlayer p = (LocalPlayer)entity;
- Vector3 spawn = p.Spawn;
- if (game.World.IsValidPos(Vector3I.Floor(spawn)))
- FindHighestFree(ref spawn);
-
- spawn.Y += 2/16f;
- LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, p.SpawnRotY, p.SpawnHeadX, false);
- entity.SetLocation(update, false);
- entity.Velocity = Vector3.Zero;
-
- // Update onGround, otherwise if 'respawn' then 'space' is pressed, you still jump into the air if onGround was true before
- AABB bb = entity.Bounds;
- bb.Min.Y -= 0.01f; bb.Max.Y = bb.Min.Y;
- entity.onGround = entity.TouchesAny(bb, touchesAnySolid);
- }
-
- static Predicate touchesAnySolid = IsSolidCollide;
- static bool IsSolidCollide(BlockID b) { return BlockInfo.Collide[b] == CollideType.Solid; }
-
- void FindHighestFree(ref Vector3 spawn) {
- AABB bb = AABB.Make(spawn, entity.Size);
-
- Vector3I P = Vector3I.Floor(spawn);
- // Spawn player at highest valid position.
- for (int y = P.Y; y <= game.World.Height; y++) {
- float spawnY = Respawn.HighestFreeY(game, ref bb);
- if (spawnY == float.NegativeInfinity) {
- BlockID block = game.World.GetPhysicsBlock(P.X, y, P.Z);
- float height = BlockInfo.Collide[block] == CollideType.Solid ? BlockInfo.MaxBB[block].Y : 0;
- spawn.Y = y + height + Entity.Adjustment;
- return;
- }
- bb.Min.Y += 1; bb.Max.Y += 1;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/ClassicalSharp/Entities/Components/PhysicsComponent.cs b/ClassicalSharp/Entities/Components/PhysicsComponent.cs
index 495d9366a..cd85f4486 100644
--- a/ClassicalSharp/Entities/Components/PhysicsComponent.cs
+++ b/ClassicalSharp/Entities/Components/PhysicsComponent.cs
@@ -7,7 +7,7 @@ using BlockID = System.UInt16;
namespace ClassicalSharp.Entities {
- /// Entity component that performs collision detection.
+ /// Entity component that performs collisions.
public sealed class PhysicsComponent {
bool useLiquidGravity = false; // used by BlockDefinitions.
@@ -32,7 +32,7 @@ namespace ClassicalSharp.Entities {
int dir = (hacks.FlyingUp || jumping) ? 1 : (hacks.FlyingDown ? -1 : 0);
entity.Velocity.Y += 0.12f * dir;
- if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.12f * dir;
+ if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.12f * dir;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += 0.06f * dir;
} else if (jumping && entity.TouchesAnyRope() && entity.Velocity.Y > 0.02f) {
entity.Velocity.Y = 0.02f;
@@ -60,19 +60,20 @@ namespace ClassicalSharp.Entities {
if (!pastJumpPoint) {
canLiquidJump = true;
entity.Velocity.Y += 0.04f;
- if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
+ if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += 0.02f;
} else if (pastJumpPoint) {
- // either A) jump bob in water B) climb up solid on side
- if (collisions.HorizontalCollision)
+ // either A) climb up solid on side B) jump bob in water
+ if (collisions.HorizontalCollision) {
entity.Velocity.Y += touchLava ? 0.30f : 0.13f;
- else if (canLiquidJump)
+ } else if (canLiquidJump) {
entity.Velocity.Y += touchLava ? 0.20f : 0.10f;
+ }
canLiquidJump = false;
}
} else if (useLiquidGravity) {
entity.Velocity.Y += 0.04f;
- if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
+ if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += 0.04f;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += 0.02f;
canLiquidJump = false;
} else if (entity.TouchesAnyRope()) {
@@ -87,7 +88,7 @@ namespace ClassicalSharp.Entities {
if (jumpVel == 0 || hacks.MaxJumps == 0) return;
entity.Velocity.Y = jumpVel;
- if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += jumpVel;
+ if (hacks.Speeding && hacks.CanSpeed) entity.Velocity.Y += jumpVel;
if (hacks.HalfSpeeding && hacks.CanSpeed) entity.Velocity.Y += jumpVel / 2;
canLiquidJump = false;
}
@@ -152,17 +153,14 @@ namespace ClassicalSharp.Entities {
bool OnIce(Entity entity) {
Vector3 under = entity.Position; under.Y -= 0.01f;
- if (BlockInfo.ExtendedCollide[GetBlock(under)] == CollideType.Ice) return true;
+ BlockID blockUnder = game.World.SafeGetBlock(Vector3I.Floor(under));
+ if (BlockInfo.ExtendedCollide[blockUnder] == CollideType.Ice) return true;
AABB bounds = entity.Bounds;
bounds.Min.Y -= 0.01f; bounds.Max.Y = bounds.Min.Y;
return entity.TouchesAny(bounds, touchesSlipperyIce);
}
- BlockID GetBlock(Vector3 coords) {
- return game.World.SafeGetBlock(Vector3I.Floor(coords));
- }
-
static Predicate touchesSlipperyIce = IsSlipperyIce;
static bool IsSlipperyIce(BlockID b) { return BlockInfo.ExtendedCollide[b] == CollideType.SlipperyIce; }
@@ -227,7 +225,7 @@ namespace ClassicalSharp.Entities {
Vector3I max = Vector3I.Floor(bounds.Max);
float modifier = inf;
- AABB blockBB = default(AABB);
+ AABB blockBB;
min.X = min.X < 0 ? 0 : min.X; max.X = max.X > game.World.MaxX ? game.World.MaxX : max.X;
min.Y = min.Y < 0 ? 0 : min.Y; max.Y = max.Y > game.World.MaxY ? game.World.MaxY : max.Y;
min.Z = min.Z < 0 ? 0 : min.Z; max.Z = max.Z > game.World.MaxZ ? game.World.MaxZ : max.Z;
@@ -237,7 +235,7 @@ namespace ClassicalSharp.Entities {
for (int x = min.X; x <= max.X; x++)
{
BlockID block = game.World.GetBlock(x, y, z);
- if (block == 0) continue;
+ if (block == Block.Air) continue;
byte collide = BlockInfo.Collide[block];
if (collide == CollideType.Solid && !checkSolid) continue;
diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs
index 6e83c7840..553617d5f 100644
--- a/ClassicalSharp/Entities/Entity.cs
+++ b/ClassicalSharp/Entities/Entity.cs
@@ -170,7 +170,7 @@ namespace ClassicalSharp.Entities {
Vector3I min = Vector3I.Floor(bounds.Min);
Vector3I max = Vector3I.Floor(bounds.Max);
- AABB blockBB = default(AABB);
+ AABB blockBB;
Vector3 v;
min.X = min.X < 0 ? 0 : min.X; max.X = max.X > game.World.MaxX ? game.World.MaxX : max.X;
min.Y = min.Y < 0 ? 0 : min.Y; max.Y = max.Y > game.World.MaxY ? game.World.MaxY : max.Y;
diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs
index f0309e9c6..c29e2bb3b 100644
--- a/ClassicalSharp/Entities/LocalPlayer.cs
+++ b/ClassicalSharp/Entities/LocalPlayer.cs
@@ -1,9 +1,11 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
+using ClassicalSharp.Physics;
using ClassicalSharp.Renderers;
using OpenTK;
using OpenTK.Input;
+using BlockID = System.UInt16;
namespace ClassicalSharp.Entities {
@@ -27,7 +29,6 @@ namespace ClassicalSharp.Entities {
internal CollisionsComponent collisions;
public HacksComponent Hacks;
internal PhysicsComponent physics;
- internal InputComponent input;
internal SoundComponent sound;
internal LocalInterpComponent interp;
internal TiltComponent tilt;
@@ -39,31 +40,28 @@ namespace ClassicalSharp.Entities {
collisions = new CollisionsComponent(game, this);
Hacks = new HacksComponent(game);
physics = new PhysicsComponent(game, this);
- input = new InputComponent(game, this);
sound = new SoundComponent(game, this);
interp = new LocalInterpComponent(game, this);
- tilt = new TiltComponent(game);
-
- physics.hacks = Hacks; input.Hacks = Hacks;
- physics.collisions = collisions;
- input.physics = physics;
+ tilt = new TiltComponent(game);
+ physics.hacks = Hacks; physics.collisions = collisions;
}
public override void Tick(double delta) {
if (!game.World.HasBlocks) return;
- StepSize = Hacks.FullBlockStep && Hacks.Enabled && Hacks.CanAnyHacks
- && Hacks.CanSpeed ? 1 : 0.5f;
+ StepSize = Hacks.FullBlockStep && Hacks.Enabled && Hacks.CanAnyHacks && Hacks.CanSpeed ? 1 : 0.5f;
OldVelocity = Velocity;
float xMoving = 0, zMoving = 0;
interp.AdvanceState();
bool wasOnGround = onGround;
HandleInput(ref xMoving, ref zMoving);
+ Hacks.Floating = Hacks.Noclip || Hacks.Flying;
if (!Hacks.Floating && Hacks.CanBePushed) physics.DoEntityPush();
// Immediate stop in noclip mode
- if (!Hacks.NoclipSlide && (Hacks.Noclip && xMoving == 0 && zMoving == 0))
+ if (!Hacks.NoclipSlide && (Hacks.Noclip && xMoving == 0 && zMoving == 0)) {
Velocity = Vector3.Zero;
+ }
physics.UpdateVelocityState();
physics.PhysicsTick(GetHeadingVelocity(zMoving, xMoving));
@@ -161,5 +159,70 @@ namespace ClassicalSharp.Entities {
physics.serverJumpVel = 0.42f;
Health = 20;
}
+
+
+ static Predicate touchesAnySolid = IsSolidCollide;
+ static bool IsSolidCollide(BlockID b) { return BlockInfo.Collide[b] == CollideType.Solid; }
+ void DoRespawn() {
+ if (!game.World.HasBlocks) return;
+ Vector3 spawn = Spawn;
+ Vector3I P = Vector3I.Floor(spawn);
+ AABB bb;
+
+ // Spawn player at highest valid position
+ if (game.World.IsValidPos(P)) {
+ bb = AABB.Make(spawn, Size);
+ for (int y = P.Y; y <= game.World.Height; y++) {
+ float spawnY = Respawn.HighestFreeY(game, ref bb);
+ if (spawnY == float.NegativeInfinity) {
+ BlockID block = game.World.GetPhysicsBlock(P.X, y, P.Z);
+ float height = BlockInfo.Collide[block] == CollideType.Solid ? BlockInfo.MaxBB[block].Y : 0;
+ spawn.Y = y + height + Entity.Adjustment;
+ break;
+ }
+ bb.Min.Y += 1; bb.Max.Y += 1;
+ }
+ }
+
+ spawn.Y += 2/16f;
+ LocationUpdate update = LocationUpdate.MakePosAndOri(spawn, SpawnRotY, SpawnHeadX, false);
+ SetLocation(update, false);
+ Velocity = Vector3.Zero;
+
+ // Update onGround, otherwise if 'respawn' then 'space' is pressed, you still jump into the air if onGround was true before
+ bb = Bounds;
+ bb.Min.Y -= 0.01f; bb.Max.Y = bb.Min.Y;
+ onGround = TouchesAny(bb, touchesAnySolid);
+ }
+
+ public bool HandlesKey(Key key) {
+ KeyMap keys = game.Input.Keys;
+ if (key == keys[KeyBind.Respawn] && Hacks.CanRespawn) {
+ DoRespawn();
+ } else if (key == keys[KeyBind.SetSpawn] && Hacks.CanRespawn) {
+ Spawn = Position;
+ Spawn.X = Utils.Floor(Spawn.X) + 0.5f;
+ Spawn.Z = Utils.Floor(Spawn.Z) + 0.5f;
+ SpawnRotY = RotY;
+ SpawnHeadX = HeadX;
+ DoRespawn();
+ } else if (key == keys[KeyBind.Fly] && Hacks.CanFly && Hacks.Enabled) {
+ Hacks.Flying = !Hacks.Flying;
+ } else if (key == keys[KeyBind.NoClip] && Hacks.CanNoclip && Hacks.Enabled && !Hacks.WOMStyleHacks) {
+ if (Hacks.Noclip) Velocity.Y = 0;
+ Hacks.Noclip = !Hacks.Noclip;
+ } else if (key == keys[KeyBind.Jump] && !onGround && !(Hacks.Flying || Hacks.Noclip)) {
+ int maxJumps = Hacks.CanDoubleJump && Hacks.WOMStyleHacks ? 2 : 0;
+ maxJumps = Math.Max(maxJumps, Hacks.MaxJumps - 1);
+
+ if (physics.multiJumps < maxJumps) {
+ physics.DoNormalJump();
+ physics.multiJumps++;
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
}
}
\ No newline at end of file
diff --git a/ClassicalSharp/Game/InputHandler.cs b/ClassicalSharp/Game/InputHandler.cs
index 284b42479..f4d29595e 100644
--- a/ClassicalSharp/Game/InputHandler.cs
+++ b/ClassicalSharp/Game/InputHandler.cs
@@ -160,7 +160,7 @@ namespace ClassicalSharp {
} else if (key == Keys[KeyBind.Screenshot]) {
game.screenshotRequested = true;
} else if (!game.Gui.ActiveScreen.HandlesKeyDown(key)) {
- if (!HandleBuiltinKey(key) && !game.LocalPlayer.input.Handles(key))
+ if (!HandleBuiltinKey(key) && !game.LocalPlayer.HandlesKey(key))
HandleHotkey(key);
}
lastKey = key;
diff --git a/ClassicalSharp/Rendering/Env/EnvRenderer.cs b/ClassicalSharp/Rendering/Env/EnvRenderer.cs
index 2c43e8b33..a2c5a6ebf 100644
--- a/ClassicalSharp/Rendering/Env/EnvRenderer.cs
+++ b/ClassicalSharp/Rendering/Env/EnvRenderer.cs
@@ -160,8 +160,11 @@ namespace ClassicalSharp.Renderers {
// TODO: rewrite this to avoid raising the event? want to avoid recreating vbos too many times often
if (fogDensity != 0) {
// Exp fog mode: f = e^(-density*coord)
- // Solve for f = 0.05 to figure out coord (good approx for fog end)
- float dist = (float)Math.Log(0.05) / -fogDensity;
+ // Solve coord for f = 0.05 (good approx for fog end)
+ // i.e. log(0.05) = -density * coord
+
+ const double log005 = -2.99573227355399;
+ double dist = log005 / -fogDensity;
game.SetViewDistance((int)dist, false);
} else {
game.SetViewDistance(game.UserViewDistance, false);
@@ -233,7 +236,9 @@ namespace ClassicalSharp.Renderers {
// 0.99=z/end --> z=end*0.99
// therefore
// d = -ln(0.01)/(end*0.99)
- double density = -Math.Log(0.01) / (game.ViewDistance * 0.99);
+
+ const double log001 = -4.60517018598809;
+ double density = -log001 / (game.ViewDistance * 0.99);
gfx.SetFogDensity((float)density);
} else {
gfx.SetFogMode(Fog.Linear);
diff --git a/ClassicalSharp/Utils/Respawn.cs b/ClassicalSharp/Utils/Respawn.cs
index ae883ad3d..5a1c15fbd 100644
--- a/ClassicalSharp/Utils/Respawn.cs
+++ b/ClassicalSharp/Utils/Respawn.cs
@@ -16,7 +16,7 @@ namespace ClassicalSharp {
int minZ = Utils.Floor(bb.Min.Z), maxZ = Utils.Floor(bb.Max.Z);
float spawnY = float.NegativeInfinity;
- AABB blockBB = default(AABB);
+ AABB blockBB;
for (int y = minY; y <= maxY; y++)
for (int z = minZ; z <= maxZ; z++)
diff --git a/ClassicalSharp/Utils/Utils.Math.cs b/ClassicalSharp/Utils/Utils.Math.cs
index 921334f23..135fe801b 100644
--- a/ClassicalSharp/Utils/Utils.Math.cs
+++ b/ClassicalSharp/Utils/Utils.Math.cs
@@ -93,7 +93,7 @@ namespace ClassicalSharp {
public static void GetHeading(Vector3 dir, out double yaw, out double pitch) {
pitch = Math.Asin(-dir.Y);
- yaw = Math.Atan2(dir.X, -dir.Z);
+ yaw = Math.Atan2(dir.X, -dir.Z);
}
#endif
diff --git a/OpenTK/Math/Vector3.cs b/OpenTK/Math/Vector3.cs
index 6572253a6..2fae6ad9f 100644
--- a/OpenTK/Math/Vector3.cs
+++ b/OpenTK/Math/Vector3.cs
@@ -74,8 +74,6 @@ namespace OpenTK {
public static readonly Vector3 One = new Vector3(1, 1, 1);
- public static readonly int SizeInBytes = 3 * sizeof( float );
-
public static void Add(ref Vector3 a, ref Vector3 b, out Vector3 result) {
result = new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
diff --git a/src/Client/Animations.c b/src/Client/Animations.c
index 37dca986b..3a63a9dcf 100644
--- a/src/Client/Animations.c
+++ b/src/Client/Animations.c
@@ -30,8 +30,8 @@ void LavaAnimation_Tick(UInt32* ptr, Int32 size) {
for (y = 0; y < size; y++) {
for (x = 0; x < size; x++) {
/* Calculate the colour at this coordinate in the heatmap */
- Int32 xx = x + (Int32)(1.2f * Math_Sin(y * 22.5f * MATH_DEG2RAD));
- Int32 yy = y + (Int32)(1.2f * Math_Sin(x * 22.5f * MATH_DEG2RAD));
+ Int32 xx = x + (Int32)(1.2f * Math_SinF(y * 22.5f * MATH_DEG2RAD));
+ Int32 yy = y + (Int32)(1.2f * Math_SinF(x * 22.5f * MATH_DEG2RAD));
Real32 lSoupHeat =
L_soupHeat[((yy - 1) & mask) << shift | ((xx - 1) & mask)] +
L_soupHeat[((yy - 1) & mask) << shift | (xx & mask)] +
diff --git a/src/Client/Block.c b/src/Client/Block.c
index 1c23a8a0e..c74b0750a 100644
--- a/src/Client/Block.c
+++ b/src/Client/Block.c
@@ -487,7 +487,7 @@ BlockID AutoRotate_RotateBlock(BlockID block) {
Vector3 translated, offset;
Vector3I_ToVector3(&translated, &Game_SelectedPos.TranslatedPos);
- Vector3_Subtract(&offset, &Game_SelectedPos.Intersect, &translated);
+ Vector3_Sub(&offset, &Game_SelectedPos.Intersect, &translated);
if (AR_EQ2(dir, 'n', 'w') || AR_EQ2(dir, 'n', 'e') || AR_EQ2(dir, 's', 'w') || AR_EQ2(dir, 's', 'e')) {
return AutoRotate_RotateCorner(block, &baseName, offset);
diff --git a/src/Client/Camera.c b/src/Client/Camera.c
index d5993f7cf..f76ee39e6 100644
--- a/src/Client/Camera.c
+++ b/src/Client/Camera.c
@@ -148,8 +148,8 @@ Vector3 FirstPersonCamera_GetCameraPos(Real32 t) {
camPos.Y += Camera_BobbingVer;
Real32 headY = (p->HeadY * MATH_DEG2RAD);
- camPos.X += Camera_BobbingHor * Math_Cos(headY);
- camPos.Z += Camera_BobbingHor * Math_Sin(headY);
+ camPos.X += Camera_BobbingHor * Math_CosF(headY);
+ camPos.Z += Camera_BobbingHor * Math_SinF(headY);
return camPos;
}
diff --git a/src/Client/Client.vcxproj b/src/Client/Client.vcxproj
index 3a78fc2bf..097dbd0ec 100644
--- a/src/Client/Client.vcxproj
+++ b/src/Client/Client.vcxproj
@@ -138,6 +138,7 @@
false
+ NoExtensions
Windows
@@ -166,6 +167,7 @@
false
+ NoExtensions
Windows
diff --git a/src/Client/Entity.c b/src/Client/Entity.c
index c96c5ad77..15a41bb70 100644
--- a/src/Client/Entity.c
+++ b/src/Client/Entity.c
@@ -16,12 +16,13 @@
#include "AsyncDownloader.h"
#include "ErrorHandler.h"
#include "IModel.h"
+#include "Input.h"
const UInt8* NameMode_Names[NAME_MODE_COUNT] = { "None", "Hovered", "All", "AllHovered", "AllUnscaled" };
const UInt8* ShadowMode_Names[SHADOW_MODE_COUNT] = { "None", "SnapToBlock", "Circle", "CircleAll" };
Real32 LocationUpdate_Clamp(Real32 degrees) {
- degrees = Math_Mod(degrees, 360.0f);
+ degrees = Math_ModF(degrees, 360.0f);
if (degrees < 0) degrees += 360.0f;
return degrees;
}
@@ -154,33 +155,29 @@ void Entity_SetModel(Entity* entity, STRING_PURE String* model) {
void Entity_UpdateModelBounds(Entity* entity) {
IModel* model = entity->Model;
Vector3 baseSize = model->GetCollisionSize();
- Vector3_Multiply3(&entity->Size, &baseSize, &entity->ModelScale);
+ Vector3_Mul3(&entity->Size, &baseSize, &entity->ModelScale);
AABB* bb = &entity->ModelAABB;
model->GetPickingBounds(bb);
- Vector3_Multiply3(&bb->Min, &bb->Min, &entity->ModelScale);
- Vector3_Multiply3(&bb->Max, &bb->Max, &entity->ModelScale);
+ Vector3_Mul3By(&bb->Min, &entity->ModelScale);
+ Vector3_Mul3By(&bb->Max, &entity->ModelScale);
}
bool Entity_TouchesAny(AABB* bounds, bool (*touches_condition)(BlockID block__)) {
Vector3I bbMin, bbMax;
Vector3I_Floor(&bbMin, &bounds->Min);
Vector3I_Floor(&bbMax, &bounds->Max);
- AABB blockBB;
- Vector3 v;
bbMin.X = max(bbMin.X, 0); bbMax.X = min(bbMax.X, World_MaxX);
bbMin.Y = max(bbMin.Y, 0); bbMax.Y = min(bbMax.Y, World_MaxY);
bbMin.Z = max(bbMin.Z, 0); bbMax.Z = min(bbMax.Z, World_MaxZ);
+ AABB blockBB;
+ Vector3 v;
Int32 x, y, z;
- for (y = bbMin.Y; y <= bbMax.Y; y++) {
- v.Y = (Real32)y;
- for (z = bbMin.Z; z <= bbMax.Z; z++) {
- v.Z = (Real32)z;
- for (x = bbMin.X; x <= bbMax.X; x++) {
- v.X = (Real32)x;
-
+ for (y = bbMin.Y; y <= bbMax.Y; y++) { v.Y = (Real32)y;
+ for (z = bbMin.Z; z <= bbMax.Z; z++) { v.Z = (Real32)z;
+ for (x = bbMin.X; x <= bbMax.X; x++) { v.X = (Real32)x;
BlockID block = World_GetBlock(x, y, z);
Vector3_Add(&blockBB.Min, &v, &Block_MinBB[block]);
Vector3_Add(&blockBB.Max, &v, &Block_MaxBB[block]);
@@ -728,3 +725,84 @@ void Player_Init(Player* player) {
entity->VTABLE->ContextRecreated = Player_ContextRecreated;
entity->VTABLE->Despawn = Player_Despawn;
}
+
+Real32 LocalPlayer_JumpHeight(void) {
+ LocalPlayer* p = &LocalPlayer_Instance;
+ return (Real32)PhysicsComp_GetMaxHeight(p->Physics.JumpVel);
+}
+
+void LocalPlayer_CheckHacksConsistency(void) {
+ LocalPlayer* p = &LocalPlayer_Instance;
+ HacksComp_CheckConsistency(&p->Hacks);
+ if (!HacksComp_CanJumpHigher(&p->Hacks)) {
+ p->Physics.JumpVel = p->Physics.ServerJumpVel;
+ }
+}
+
+bool LocalPlayer_IsSolidCollide(BlockID b) { return Block_Collide[b] == COLLIDE_SOLID; }
+void LocalPlayer_DoRespawn(void) {
+ if (World_Blocks == NULL) return;
+ LocalPlayer* p = &LocalPlayer_Instance;
+ Vector3 spawn = p->Spawn;
+ Vector3I P; Vector3I_Floor(&P, &spawn);
+ AABB bb;
+
+ /* Spawn player at highest valid position */
+ if (World_IsValidPos_3I(P)) {
+ AAABB_Make(&bb, &spawn, &p->Base.Size);
+ Int32 y;
+ for (y = P.Y; y <= World_Height; y++) {
+ Real32 spawnY = Respawn_HighestFreeY(&bb);
+ if (spawnY == RESPAWN_NOT_FOUND) {
+ BlockID block = World_GetPhysicsBlock(P.X, y, P.Z);
+ Real32 height = Block_Collide[block] == COLLIDE_SOLID ? Block_MaxBB[block].Y : 0.0f;
+ spawn.Y = y + height + ENTITY_ADJUSTMENT;
+ break;
+ }
+ bb.Min.Y += 1.0f; bb.Max.Y += 1.0f;
+ }
+ }
+
+ spawn.Y += 2.0f / 16.0f;
+ LocationUpdate update; LocationUpdate_MakePosAndOri(&update, spawn, p->SpawnRotY, p->SpawnHeadX, false);
+ p->Base.VTABLE->SetLocation(&p->Base, &update, false);
+ Vector3 zero = Vector3_Zero; p->Base.Velocity = zero;
+
+ /* Update onGround, otherwise if 'respawn' then 'space' is pressed, you still jump into the air if onGround was true before */
+ Entity_GetBounds(&p->Base, &bb);
+ bb.Min.Y -= 0.01f; bb.Max.Y = bb.Min.Y;
+ p->Base.OnGround = Entity_TouchesAny(&bb, LocalPlayer_IsSolidCollide);
+}
+
+bool LocalPlayer_HandlesKey(Int32 key) {
+ LocalPlayer* p = &LocalPlayer_Instance;
+ HacksComp* hacks = &p->Hacks;
+ PhysicsComp* physics = &p->Physics;
+
+ if (key == KeyBind_Get(KeyBind_Respawn) && hacks->CanRespawn) {
+ DoRespawn();
+ } else if (key == KeyBind_Get(KeyBind_SetSpawn) && hacks->CanRespawn) {
+ p->Spawn = p->Base.Position;
+ p->Spawn.X = Math_Floor(p->Spawn.X) + 0.5f;
+ p->Spawn.Z = Math_Floor(p->Spawn.Z) + 0.5f;
+ p->SpawnRotY = p->Base.RotY;
+ p->SpawnHeadX = p->Base.HeadX;
+ DoRespawn();
+ } else if (key == KeyBind_Get(KeyBind_Fly) && hacks->CanFly && hacks->Enabled) {
+ hacks->Flying = !hacks->Flying;
+ } else if (key == KeyBind_Get(KeyBind_NoClip) && hacks->CanNoclip && hacks->Enabled && !hacks->WOMStyleHacks) {
+ if (hacks->Noclip) p->Base.Velocity.Y = 0;
+ hacks->Noclip = !hacks->Noclip;
+ } else if (key == KeyBind_Get(KeyBind_Jump) && !p->Base.OnGround && !(hacks->Flying || hacks->Noclip)) {
+ Int32 maxJumps = hacks->CanDoubleJump && hacks->WOMStyleHacks ? 2 : 0;
+ maxJumps = max(maxJumps, hacks->MaxJumps - 1);
+
+ if (physics->MultiJumps < maxJumps) {
+ PhysicsComp_DoNormalJump(physics);
+ physics->MultiJumps++;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
\ No newline at end of file
diff --git a/src/Client/Entity.h b/src/Client/Entity.h
index 3bcbe89ec..c2a7b63d7 100644
--- a/src/Client/Entity.h
+++ b/src/Client/Entity.h
@@ -52,15 +52,16 @@ void LocationUpdate_MakeOri(LocationUpdate* update, Real32 rotY, Real32 headX);
void LocationUpdate_MakePos(LocationUpdate* update, Vector3 pos, bool rel);
void LocationUpdate_MakePosAndOri(LocationUpdate* update, Vector3 pos, Real32 rotY, Real32 headX, bool rel);
+typedef struct Entity_ Entity;
typedef struct EntityVTABLE_ {
- void (*Tick)(struct Entity_* entity, ScheduledTask* task);
- void (*SetLocation)(struct Entity_* entity, LocationUpdate* update, bool interpolate);
- void (*RenderModel)(struct Entity_* entity, Real64 deltaTime, Real32 t);
- void (*RenderName)(struct Entity_* entity);
- void (*ContextLost)(struct Entity_* entity);
- void (*ContextRecreated)(struct Entity_* entity);
- void (*Despawn)(struct Entity_* entity);
- PackedCol (*GetCol)(struct Entity_* entity);
+ void (*Tick)(Entity* entity, ScheduledTask* task);
+ void (*SetLocation)(Entity* entity, LocationUpdate* update, bool interpolate);
+ void (*RenderModel)(Entity* entity, Real64 deltaTime, Real32 t);
+ void (*RenderName)(Entity* entity);
+ void (*ContextLost)(Entity* entity);
+ void (*ContextRecreated)(Entity* entity);
+ void (*Despawn)(Entity* entity);
+ PackedCol (*GetCol)(Entity* entity);
} EntityVTABLE;
/* Contains a model, along with position, velocity, and rotation. May also contain other fields and properties. */
@@ -149,10 +150,13 @@ typedef struct LocalPlayer_ {
HacksComp Hacks;
TiltComp Tilt;
InterpComp Interp;
+ CollisionsComp Collisions;
+ PhysicsComp Physics;
} LocalPlayer;
LocalPlayer LocalPlayer_Instance;
void LocalPlayer_Init(void);
Real32 LocalPlayer_JumpHeight(void);
-void LocalPlayer_ChecksHackConsistency();
+void LocalPlayer_CheckHacksConsistency(void);
+bool LocalPlayer_HandlesKey(Int32 key);
#endif
\ No newline at end of file
diff --git a/src/Client/EntityComponents.c b/src/Client/EntityComponents.c
index f9e67cfd0..6d63feb34 100644
--- a/src/Client/EntityComponents.c
+++ b/src/Client/EntityComponents.c
@@ -1,4 +1,4 @@
-#include "EntityComponents.h"
+#include "EntityComponents.h"
#include "ExtMath.h"
#include "World.h"
#include "Block.h"
@@ -36,9 +36,9 @@ void AnimatedComp_DoTilt(Real32* tilt, bool reduce) {
}
void AnimatedComp_PerpendicularAnim(AnimatedComp* anim, Real32 flapSpeed, Real32 idleXRot, Real32 idleZRot, bool left) {
- Real32 verAngle = 0.5f + 0.5f * Math_Sin(anim->WalkTime * flapSpeed);
+ Real32 verAngle = 0.5f + 0.5f * Math_SinF(anim->WalkTime * flapSpeed);
Real32 zRot = -idleZRot - verAngle * anim->Swing * ANIM_MAX_ANGLE;
- Real32 horAngle = Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX * 1.5f;
+ Real32 horAngle = Math_CosF(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX * 1.5f;
Real32 xRot = idleXRot + horAngle;
if (left) {
@@ -64,7 +64,7 @@ void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Rea
anim->SwingO = anim->SwingN;
Real32 dx = newPos.X - oldPos.X;
Real32 dz = newPos.Z - oldPos.Z;
- Real32 distance = Math_Sqrt(dx * dx + dz * dz);
+ Real32 distance = Math_SqrtF(dx * dx + dz * dz);
if (distance > 0.05f) {
Real32 walkDelta = distance * 2 * (Real32)(20 * delta);
@@ -90,20 +90,20 @@ void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims)
anim->BobStrength = Math_Lerp(anim->BobStrengthO, anim->BobStrengthN, t);
Real32 idleTime = (Real32)Game_Accumulator;
- Real32 idleXRot = Math_Sin(idleTime * ANIM_IDLE_XPERIOD) * ANIM_IDLE_MAX;
- Real32 idleZRot = ANIM_IDLE_MAX + Math_Cos(idleTime * ANIM_IDLE_ZPERIOD) * ANIM_IDLE_MAX;
+ Real32 idleXRot = Math_SinF(idleTime * ANIM_IDLE_XPERIOD) * ANIM_IDLE_MAX;
+ Real32 idleZRot = ANIM_IDLE_MAX + Math_CosF(idleTime * ANIM_IDLE_ZPERIOD) * ANIM_IDLE_MAX;
- anim->LeftArmX = (Math_Cos(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX) - idleXRot;
+ anim->LeftArmX = (Math_CosF(anim->WalkTime) * anim->Swing * ANIM_ARM_MAX) - idleXRot;
anim->LeftArmZ = -idleZRot;
- anim->LeftLegX = -(Math_Cos(anim->WalkTime) * anim->Swing * ANIM_LEG_MAX);
+ anim->LeftLegX = -(Math_CosF(anim->WalkTime) * anim->Swing * ANIM_LEG_MAX);
anim->LeftLegZ = 0;
anim->RightLegX = -anim->LeftLegX; anim->RightLegZ = -anim->LeftLegZ;
anim->RightArmX = -anim->LeftArmX; anim->RightArmZ = -anim->LeftArmZ;
- anim->BobbingHor = Math_Cos(anim->WalkTime) * anim->Swing * (2.5f / 16.0f);
- anim->BobbingVer = Math_AbsF(Math_Sin(anim->WalkTime)) * anim->Swing * (2.5f / 16.0f);
- anim->BobbingModel = Math_AbsF(Math_Cos(anim->WalkTime)) * anim->Swing * (4.0f / 16.0f);
+ anim->BobbingHor = Math_CosF(anim->WalkTime) * anim->Swing * (2.5f / 16.0f);
+ anim->BobbingVer = Math_AbsF(Math_SinF(anim->WalkTime)) * anim->Swing * (2.5f / 16.0f);
+ anim->BobbingModel = Math_AbsF(Math_CosF(anim->WalkTime)) * anim->Swing * (4.0f / 16.0f);
if (calcHumanAnims && !Game_SimpleArmsAnim) {
AnimatedComp_CalcHumanAnim(anim, idleXRot, idleZRot);
@@ -126,7 +126,7 @@ void TiltComp_Update(TiltComp* anim, Real64 delta) {
/* TODO: the Tilt code was designed for 60 ticks/second, fix it up for 20 ticks/second */
Int32 i;
for (i = 0; i < 3; i++) {
- AnimatedComp_DoTilt(&anim->VelTiltStrengthN, p->Hacks.Noclip || p->Hacks.Flying);
+ AnimatedComp_DoTilt(&anim->VelTiltStrengthN, p->Hacks.Floating);
}
}
@@ -135,8 +135,8 @@ void TiltComp_GetCurrent(TiltComp* anim, Real32 t) {
anim->VelTiltStrength = Math_Lerp(anim->VelTiltStrengthO, anim->VelTiltStrengthN, t);
AnimatedComp* pAnim = &p->Base.Anim;
- anim->TiltX = Math_Cos(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
- anim->TiltY = Math_Sin(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
+ anim->TiltX = Math_CosF(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
+ anim->TiltY = Math_SinF(pAnim->WalkTime) * pAnim->Swing * (0.15f * MATH_DEG2RAD);
}
@@ -665,29 +665,126 @@ void ShadowComponent_Draw(Entity* entity) {
}
-typedef struct CollisionsComponent_ {
- Entity* Entity;
- bool HitXMin, HitYMin, HitZMin, HitXMax, HitYMax, HitZMax, WasOn;
-} CollisionsComponent;
-
+/*########################################################################################################################*
+*---------------------------------------------------CollisionsComponent---------------------------------------------------*
+*#########################################################################################################################*/
/* Whether a collision occurred with any horizontal sides of any blocks */
-bool Collisions_HitHorizontal(CollisionsComponent* comp) {
+bool Collisions_HitHorizontal(CollisionsComp* comp) {
return comp->HitXMin || comp->HitXMax || comp->HitZMin || comp->HitZMax;
}
+#define COLLISIONS_ADJ 0.001f
-
-/* TODO: test for corner cases, and refactor this */
-void Collisions_MoveAndWallSlide(CollisionsComponent* comp) {
- Vector3 zero = Vector3_Zero;
- Entity* entity = comp->Entity;
- if (Vector3_Equals(&entity->Velocity, &zero)) return;
-
- AABB entityBB, entityExtentBB;
- UInt32 count = Searcher_FindReachableBlocks(entity, &entityBB, &entityExtentBB);
- CollideWithReachableBlocks(comp, count, &entityBB, &entityExtentBB);
+void Collisions_ClipX(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
+ entity->Velocity.X = 0.0f;
+ entityBB->Min.X = entity->Position.X - size->X / 2; extentBB->Min.X = entityBB->Min.X;
+ entityBB->Max.X = entity->Position.X + size->X / 2; extentBB->Max.X = entityBB->Max.X;
}
-void Collisions_CollideWithReachableBlocks(CollisionsComponent* comp, UInt32 count, AABB* entityBB, AABB* extentBB) {
+void Collisions_ClipY(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
+ entity->Velocity.Y = 0.0f;
+ entityBB->Min.Y = entity->Position.Y; extentBB->Min.Y = entityBB->Min.Y;
+ entityBB->Max.Y = entity->Position.Y + size->Y; extentBB->Max.Y = entityBB->Max.Y;
+}
+
+void Collisions_ClipZ(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
+ entity->Velocity.Z = 0.0f;
+ entityBB->Min.Z = entity->Position.Z - size->Z / 2; extentBB->Min.Z = entityBB->Min.Z;
+ entityBB->Max.Z = entity->Position.Z + size->Z / 2; extentBB->Max.Z = entityBB->Max.Z;
+}
+
+bool Collisions_CanSlideThrough(AABB* adjFinalBB) {
+ Vector3I bbMin; Vector3I_Floor(&bbMin, &adjFinalBB->Min);
+ Vector3I bbMax; Vector3I_Floor(&bbMax, &adjFinalBB->Max);
+
+ AABB blockBB;
+ Vector3 v;
+ Int32 x, y, z;
+ for (y = bbMin.Y; y <= bbMax.Y; y++) { v.Y = (Real32)y;
+ for (z = bbMin.Z; z <= bbMax.Z; z++) { v.Z = (Real32)z;
+ for (x = bbMin.X; x <= bbMax.X; x++) { v.X = (Real32)x;
+ BlockID block = World_GetPhysicsBlock(x, y, z);
+ Vector3_Add(&blockBB.Min, &v, &Block_MinBB[block]);
+ Vector3_Add(&blockBB.Max, &v, &Block_MaxBB[block]);
+
+ if (!AABB_Intersects(&blockBB, adjFinalBB)) continue;
+ if (Block_Collide[block] == COLLIDE_SOLID) return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool Collisions_DidSlide(CollisionsComp* comp, AABB* blockBB, Vector3* size, AABB* finalBB, AABB* entityBB, AABB* extentBB) {
+ Real32 yDist = blockBB->Max.Y - entityBB->Min.Y;
+ if (yDist > 0.0f && yDist <= comp->Entity->StepSize + 0.01f) {
+ Real32 blockBB_MinX = max(blockBB->Min.X, blockBB->Max.X - size->X / 2);
+ Real32 blockBB_MaxX = min(blockBB->Max.X, blockBB->Min.X + size->X / 2);
+ Real32 blockBB_MinZ = max(blockBB->Min.Z, blockBB->Max.Z - size->Z / 2);
+ Real32 blockBB_MaxZ = min(blockBB->Max.Z, blockBB->Min.Z + size->Z / 2);
+
+ AABB adjBB;
+ adjBB.Min.X = min(finalBB->Min.X, blockBB_MinX + COLLISIONS_ADJ);
+ adjBB.Max.X = max(finalBB->Max.X, blockBB_MaxX - COLLISIONS_ADJ);
+ adjBB.Min.Y = blockBB->Max.Y + COLLISIONS_ADJ;
+ adjBB.Max.Y = adjBB.Min.Y + size->Y;
+ adjBB.Min.Z = min(finalBB->Min.Z, blockBB_MinZ + COLLISIONS_ADJ);
+ adjBB.Max.Z = max(finalBB->Max.Z, blockBB_MaxZ - COLLISIONS_ADJ);
+
+ if (!Collisions_CanSlideThrough(&adjBB)) return false;
+ comp->Entity->Position.Y = adjBB.Min.Y;
+ comp->Entity->OnGround = true;
+ Collisions_ClipY(comp->Entity, size, entityBB, extentBB);
+ return true;
+ }
+ return false;
+}
+
+void Collisions_ClipXMin(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
+ if (!wasOn || !Collisions_DidSlide(comp, blockBB, size, finalBB, entityBB, extentBB)) {
+ comp->Entity->Position.X = blockBB->Min.X - size->X / 2 - COLLISIONS_ADJ;
+ Collisions_ClipX(comp->Entity, size, entityBB, extentBB);
+ comp->HitXMin = true;
+ }
+}
+
+void Collisions_ClipXMax(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
+ if (!wasOn || !Collisions_DidSlide(comp, blockBB, size, finalBB, entityBB, extentBB)) {
+ comp->Entity->Position.X = blockBB->Max.X + size->X / 2 + COLLISIONS_ADJ;
+ Collisions_ClipX(comp->Entity, size, entityBB, extentBB);
+ comp->HitXMax = true;
+ }
+}
+
+void Collisions_ClipZMax(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
+ if (!wasOn || !Collisions_DidSlide(comp, blockBB, size, finalBB, entityBB, extentBB)) {
+ comp->Entity->Position.Z = blockBB->Max.Z + size->Z / 2 + COLLISIONS_ADJ;
+ Collisions_ClipZ(comp->Entity, size, entityBB, extentBB);
+ comp->HitZMax = true;
+ }
+}
+
+void Collisions_ClipZMin(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
+ if (!wasOn || !Collisions_DidSlide(comp, blockBB, size, finalBB, entityBB, extentBB)) {
+ comp->Entity->Position.Z = blockBB->Min.Z - size->Z / 2 - COLLISIONS_ADJ;
+ Collisions_ClipZ(comp->Entity, size, entityBB, extentBB);
+ comp->HitZMin = true;
+ }
+}
+
+void Collisions_ClipYMin(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, AABB* extentBB, Vector3* size) {
+ comp->Entity->Position.Y = blockBB->Min.Y - size->Y - COLLISIONS_ADJ;
+ Collisions_ClipY(comp->Entity, size, entityBB, extentBB);
+ comp->HitYMin = true;
+}
+
+void Collisions_ClipYMax(CollisionsComp* comp, AABB* blockBB, AABB* entityBB, AABB* extentBB, Vector3* size) {
+ comp->Entity->Position.Y = blockBB->Max.Y + COLLISIONS_ADJ;
+ comp->Entity->OnGround = true;
+ Collisions_ClipY(comp->Entity, size, entityBB, extentBB);
+ comp->HitYMax = true;
+}
+
+void Collisions_CollideWithReachableBlocks(CollisionsComp* comp, UInt32 count, AABB* entityBB, AABB* extentBB) {
Entity* entity = comp->Entity;
/* Reset collision detection states */
bool wasOn = entity->OnGround;
@@ -712,7 +809,8 @@ void Collisions_CollideWithReachableBlocks(CollisionsComponent* comp, UInt32 cou
Real32 tx, ty, tz;
Searcher_CalcTime(&entity->Velocity, entityBB, &blockBB, &tx, &ty, &tz);
if (tx > 1.0f || ty > 1.0f || tz > 1.0f) {
- Utils.LogDebug("t > 1 in physics calculation.. this shouldn't have happened.");
+ String warn = String_FromConst("t > 1 in physics calculation.. this shouldn't have happened.");
+ Platform_Log(&warn);
}
/* Calculate the location of the entity when it collides with this block */
@@ -722,148 +820,364 @@ void Collisions_CollideWithReachableBlocks(CollisionsComponent* comp, UInt32 cou
Vector3_Add(&finalBB.Min, &entityBB->Min, &v);
Vector3_Add(&finalBB.Min, &entityBB->Max, &v);
- // if we have hit the bottom of a block, we need to change the axis we test first.
- if (!hitYMin) {
- if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) {
- ClipYMax(&blockBB, entityBB, extentBB, size);
- } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) {
- ClipYMin(&blockBB, entityBB, extentBB, size);
- } else if (finalBB.Min.X + Adjustment >= blockBB.Max.X) {
- ClipXMax(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) {
- ClipXMin(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) {
- ClipZMax(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) {
- ClipZMin(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
+ /* if we have hit the bottom of a block, we need to change the axis we test first */
+ if (!comp->HitYMin) {
+ if (finalBB.Min.Y + COLLISIONS_ADJ >= blockBB.Max.Y) {
+ Collisions_ClipYMax(comp, &blockBB, entityBB, extentBB, &size);
+ } else if (finalBB.Max.Y - COLLISIONS_ADJ <= blockBB.Min.Y) {
+ Collisions_ClipYMin(comp, &blockBB, entityBB, extentBB, &size);
+ } else if (finalBB.Min.X + COLLISIONS_ADJ >= blockBB.Max.X) {
+ Collisions_ClipXMax(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Max.X - COLLISIONS_ADJ <= blockBB.Min.X) {
+ Collisions_ClipXMin(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Min.Z + COLLISIONS_ADJ >= blockBB.Max.Z) {
+ Collisions_ClipZMax(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Max.Z - COLLISIONS_ADJ <= blockBB.Min.Z) {
+ Collisions_ClipZMin(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
}
continue;
}
- // if flying or falling, test the horizontal axes first.
- if (finalBB.Min.X + Adjustment >= blockBB.Max.X) {
- ClipXMax(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Max.X - Adjustment <= blockBB.Min.X) {
- ClipXMin(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Min.Z + Adjustment >= blockBB.Max.Z) {
- ClipZMax(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Max.Z - Adjustment <= blockBB.Min.Z) {
- ClipZMin(&blockBB, entityBB, wasOn, finalBB, extentBB, size);
- } else if (finalBB.Min.Y + Adjustment >= blockBB.Max.Y) {
- ClipYMax(&blockBB, entityBB, extentBB, size);
- } else if (finalBB.Max.Y - Adjustment <= blockBB.Min.Y) {
- ClipYMin(&blockBB, entityBB, extentBB, size);
+ /* if flying or falling, test the horizontal axes first */
+ if (finalBB.Min.X + COLLISIONS_ADJ >= blockBB.Max.X) {
+ Collisions_ClipXMax(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Max.X - COLLISIONS_ADJ <= blockBB.Min.X) {
+ Collisions_ClipXMin(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Min.Z + COLLISIONS_ADJ >= blockBB.Max.Z) {
+ Collisions_ClipZMax(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Max.Z - COLLISIONS_ADJ <= blockBB.Min.Z) {
+ Collisions_ClipZMin(comp, &blockBB, entityBB, wasOn, &finalBB, extentBB, &size);
+ } else if (finalBB.Min.Y + COLLISIONS_ADJ >= blockBB.Max.Y) {
+ Collisions_ClipYMax(comp, &blockBB, entityBB, extentBB, &size);
+ } else if (finalBB.Max.Y - COLLISIONS_ADJ <= blockBB.Min.Y) {
+ Collisions_ClipYMin(comp, &blockBB, entityBB, extentBB, &size);
}
}
}
-void Collisions_ClipXMin(AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
- if (!wasOn || !DidSlide(blockBB, size, finalBB, entityBB, extentBB)) {
- entity.Position.X = blockBB.Min.X - size.X / 2 - Adjustment;
- ClipX(size, entityBB, extentBB);
- hitXMin = true;
+/* TODO: test for corner cases, and refactor this */
+void Collisions_MoveAndWallSlide(CollisionsComp* comp) {
+ Vector3 zero = Vector3_Zero;
+ Entity* entity = comp->Entity;
+ if (Vector3_Equals(&entity->Velocity, &zero)) return;
+
+ AABB entityBB, entityExtentBB;
+ UInt32 count = Searcher_FindReachableBlocks(entity, &entityBB, &entityExtentBB);
+ Collisions_CollideWithReachableBlocks(comp, count, &entityBB, &entityExtentBB);
+}
+
+
+/*########################################################################################################################*
+*----------------------------------------------------PhysicsComponent-----------------------------------------------------*
+*#########################################################################################################################*/
+void PhysicsComp_Init(PhysicsComp* comp, Entity* entity) {
+ Platform_MemSet(comp, 0, sizeof(PhysicsComp));
+ comp->CanLiquidJump = true;
+ comp->Entity = entity;
+ comp->JumpVel = 0.42f;
+ comp->UserJumpVel = 0.42f;
+ comp->ServerJumpVel = 0.42f;
+}
+
+bool PhysicsComp_TouchesLiquid(BlockID block) { return Block_Collide[block] == COLLIDE_LIQUID; }
+void PhysicsComp_UpdateVelocityState(PhysicsComp* comp) {
+ Entity* entity = comp->Entity;
+ HacksComp* hacks = comp->Hacks;
+
+ if (hacks->Floating) {
+ entity->Velocity.Y = 0.0f; /* eliminate the effect of gravity */
+ Int32 dir = (hacks->FlyingUp || comp->Jumping) ? 1 : (hacks->FlyingDown ? -1 : 0);
+
+ entity->Velocity.Y += 0.12f * dir;
+ if (hacks->Speeding && hacks->CanSpeed) entity->Velocity.Y += 0.12f * dir;
+ if (hacks->HalfSpeeding && hacks->CanSpeed) entity->Velocity.Y += 0.06f * dir;
+ } else if (comp->Jumping && Entity_TouchesAnyRope(entity) && entity->Velocity.Y > 0.02f) {
+ entity->Velocity.Y = 0.02f;
+ }
+
+ if (!comp->Jumping) {
+ comp->CanLiquidJump = false; return;
+ }
+
+ bool touchWater = Entity_TouchesAnyWater(entity);
+ bool touchLava = Entity_TouchesAnyLava(entity);
+ if (touchWater || touchLava) {
+ AABB bounds; Entity_GetBounds(entity, &bounds);
+ Int32 feetY = Math_Floor(bounds.Min.Y), bodyY = feetY + 1;
+ Int32 headY = Math_Floor(bounds.Max.Y);
+ if (bodyY > headY) bodyY = headY;
+
+ bounds.Max.Y = bounds.Min.Y = feetY;
+ bool liquidFeet = Entity_TouchesAny(&bounds, PhysicsComp_TouchesLiquid);
+ bounds.Min.Y = min(bodyY, headY);
+ bounds.Max.Y = max(bodyY, headY);
+ bool liquidRest = Entity_TouchesAny(&bounds, PhysicsComp_TouchesLiquid);
+
+ bool pastJumpPoint = liquidFeet && !liquidRest && (Math_ModF(entity->Position.Y, 1.0f) >= 0.4f);
+ if (!pastJumpPoint) {
+ comp->CanLiquidJump = true;
+ entity->Velocity.Y += 0.04f;
+ if (hacks->Speeding && hacks->CanSpeed) entity->Velocity.Y += 0.04f;
+ if (hacks->HalfSpeeding && hacks->CanSpeed) entity->Velocity.Y += 0.02f;
+ } else if (pastJumpPoint) {
+ /* either A) climb up solid on side B) jump bob in water */
+ if (Collisions_HitHorizontal(comp->Collisions)) {
+ entity->Velocity.Y += touchLava ? 0.30f : 0.13f;
+ } else if (comp->CanLiquidJump) {
+ entity->Velocity.Y += touchLava ? 0.20f : 0.10f;
+ }
+ comp->CanLiquidJump = false;
+ }
+ } else if (comp->UseLiquidGravity) {
+ entity->Velocity.Y += 0.04f;
+ if (hacks->Speeding && hacks->CanSpeed) entity->Velocity.Y += 0.04f;
+ if (hacks->HalfSpeeding && hacks->CanSpeed) entity->Velocity.Y += 0.02f;
+ comp->CanLiquidJump = false;
+ } else if (Entity_TouchesAnyRope(entity)) {
+ entity->Velocity.Y += (hacks->Speeding && hacks->CanSpeed) ? 0.15f : 0.10f;
+ comp->CanLiquidJump = false;
+ } else if (entity->OnGround) {
+ PhysicsComp_DoNormalJump(comp);
}
}
-void Collisions_ClipXMax(AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
- if (!wasOn || !DidSlide(blockBB, size, finalBB, entityBB, extentBB)) {
- entity.Position.X = blockBB.Max.X + size.X / 2 + Adjustment;
- ClipX(size, entityBB, extentBB);
- hitXMax = true;
+void PhysicsComp_DoNormalJump(PhysicsComp* comp) {
+ Entity* entity = comp->Entity;
+ HacksComp* hacks = comp->Hacks;
+ if (comp->JumpVel == 0.0f || hacks->MaxJumps == 0) return;
+
+ entity->Velocity.Y = comp->JumpVel;
+ if (hacks->Speeding && hacks->CanSpeed) entity->Velocity.Y += comp->JumpVel;
+ if (hacks->HalfSpeeding && hacks->CanSpeed) entity->Velocity.Y += comp->JumpVel / 2;
+ comp->CanLiquidJump = false;
+}
+
+bool PhysicsComp_TouchesSlipperyIce(BlockID b) { return Block_ExtendedCollide[b] == COLLIDE_SLIPPERY_ICE; }
+bool PhysicsComp_OnIce(Entity* entity) {
+ Vector3 under = entity->Position; under.Y -= 0.01f;
+ Vector3I underCoords; Vector3I_Floor(&underCoords, &under);
+ BlockID blockUnder = World_SafeGetBlock_3I(underCoords);
+ if (Block_ExtendedCollide[blockUnder] == COLLIDE_ICE) return true;
+
+ AABB bounds; Entity_GetBounds(entity, &bounds);
+ bounds.Min.Y -= 0.01f; bounds.Max.Y = bounds.Min.Y;
+ return Entity_TouchesAny(&bounds, PhysicsComp_TouchesSlipperyIce);
+}
+
+void PhysicsComp_MoveHor(PhysicsComp* comp, Vector3 vel, Real32 factor) {
+ Real32 dist = Math_SqrtF(vel.X * vel.X + vel.Z * vel.Z);
+ if (dist < 0.00001f) return;
+ if (dist < 1.0f) dist = 1.0f;
+
+ /* entity.Velocity += vel * (factor / dist) */
+ Entity* entity = comp->Entity;
+ Vector3_Mul1By(&vel, factor / dist);
+ Vector3_AddBy(&entity->Velocity, &vel);
+}
+
+void PhysicsComp_Move(PhysicsComp* comp, Vector3 drag, Real32 gravity, Real32 yMul) {
+ Entity* entity = comp->Entity;
+ entity->Velocity.Y *= yMul;
+ if (!comp->Hacks->Noclip) {
+ Collisions_MoveAndWallSlide(comp->Collisions);
}
+ Vector3_AddBy(&entity->Position, &entity->Velocity);
+
+ entity->Velocity.Y /= yMul;
+ Vector3_Mul3By(&entity->Velocity, &drag);
+ entity->Velocity.Y -= gravity;
}
-void Collisions_ClipZMax(AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
- if (!wasOn || !DidSlide(blockBB, size, finalBB, entityBB, extentBB)) {
- entity.Position.Z = blockBB.Max.Z + size.Z / 2 + Adjustment;
- ClipZ(size, entityBB, extentBB);
- hitZMax = true;
+void PhysicsComp_MoveFlying(PhysicsComp* comp, Vector3 vel, Real32 factor, Vector3 drag, Real32 gravity, Real32 yMul) {
+ Entity* entity = comp->Entity;
+ HacksComp* hacks = comp->Hacks;
+
+ PhysicsComp_MoveHor(comp, vel, factor);
+ Real32 yVel = Math_SqrtF(entity->Velocity.X * entity->Velocity.X + entity->Velocity.Z * entity->Velocity.Z);
+ /* make horizontal speed the same as vertical speed */
+ if ((vel.X != 0.0f || vel.Z != 0.0f) && yVel > 0.001f) {
+ entity->Velocity.Y = 0.0f;
+ yMul = 1.0f;
+ if (hacks->FlyingUp || comp->Jumping) entity->Velocity.Y += yVel;
+ if (hacks->FlyingDown) entity->Velocity.Y -= yVel;
}
+ PhysicsComp_Move(comp, drag, gravity, yMul);
}
-void Collisions_ClipZMin(AABB* blockBB, AABB* entityBB, bool wasOn, AABB* finalBB, AABB* extentBB, Vector3* size) {
- if (!wasOn || !DidSlide(blockBB, size, finalBB, entityBB, extentBB)) {
- entity.Position.Z = blockBB.Min.Z - size.Z / 2 - Adjustment;
- ClipZ(size, entityBB, extentBB);
- hitZMin = true;
- }
+void PhysicsComp_MoveNormal(PhysicsComp* comp, Vector3 vel, Real32 factor, Vector3 drag, Real32 gravity, Real32 yMul) {
+ PhysicsComp_MoveHor(comp, vel, factor);
+ PhysicsComp_Move(comp, drag, gravity, yMul);
}
-void Collisions_ClipYMin(AABB* blockBB, AABB* entityBB, AABB* extentBB, Vector3* size) {
- entity.Position.Y = blockBB.Min.Y - size.Y - Adjustment;
- ClipY(size, entityBB, ref extentBB);
- hitYMin = true;
-}
+Real32 PhysicsComp_LowestModifier(PhysicsComp* comp, AABB* bounds, bool checkSolid) {
+ Vector3I bbMin, bbMax;
+ Vector3I_Floor(&bbMin, &bounds->Min);
+ Vector3I_Floor(&bbMax, &bounds->Max);
+ Real32 modifier = MATH_POS_INF;
-void Collisions_ClipYMax(AABB* blockBB, AABB* entityBB, AABB* extentBB, Vector3* size) {
- entity.Position.Y = blockBB.Max.Y + Adjustment;
- entity.onGround = true;
- ClipY(size, entityBB, ref extentBB);
- hitYMax = true;
-}
+ bbMin.X = max(bbMin.X, 0); bbMax.X = min(bbMax.X, World_MaxX);
+ bbMin.Y = max(bbMin.Y, 0); bbMax.Y = min(bbMax.Y, World_MaxY);
+ bbMin.Z = max(bbMin.Z, 0); bbMax.Z = min(bbMax.Z, World_MaxZ);
-bool Collisions_DidSlide(AABB blockBB, Vector3* size, AABB* finalBB, AABB* entityBB, AABB* extentBB) {
- Real32 yDist = blockBB.Max.Y - entityBB.Min.Y;
- if (yDist > 0 && yDist <= entity.StepSize + 0.01f) {
- float blockXMin = blockBB.Min.X, blockZMin = blockBB.Min.Z;
- blockBB.Min.X = Math.Max(blockBB.Min.X, blockBB.Max.X - size.X / 2);
- blockBB.Max.X = Math.Min(blockBB.Max.X, blockXMin + size.X / 2);
- blockBB.Min.Z = Math.Max(blockBB.Min.Z, blockBB.Max.Z - size.Z / 2);
- blockBB.Max.Z = Math.Min(blockBB.Max.Z, blockZMin + size.Z / 2);
-
- AABB adjBB;
- adjBB.Min.X = min(finalBB->Min.X, blockBB.Min.X + Adjustment);
- adjBB.Max.X = max(finalBB->Max.X, blockBB.Max.X - Adjustment);
- adjBB.Min.Y = blockBB.Max.Y + Adjustment;
- adjBB.Max.Y = adjBB.Min.Y + size->Y;
- adjBB.Min.Z = min(finalBB->Min.Z, blockBB.Min.Z + Adjustment);
- adjBB.Max.Z = max(finalBB->Max.Z, blockBB.Max.Z - Adjustment);
-
- if (!Collisions_CanSlideThrough(&adjBB)) return false;
-
- entity.Position.Y = blockBB.Max.Y + Adjustment;
- entity.onGround = true;
- ClipY(size, entityBB, extentBB);
- return true;
- }
- return false;
-}
-
-bool Collisions_CanSlideThrough(AABB* adjFinalBB) {
- Vector3I bbMin; Vector3I_Floor(&bbMin, &adjFinalBB->Min);
- Vector3I bbMax; Vector3I_Floor(&bbMax, &adjFinalBB->Max);
AABB blockBB;
+ Vector3 v;
Int32 x, y, z;
+ for (y = bbMin.Y; y <= bbMax.Y; y++) { v.Y = (Real32)y;
+ for (z = bbMin.Z; z <= bbMax.Z; z++) { v.Z = (Real32)z;
+ for (x = bbMin.X; x <= bbMax.X; x++) { v.X = (Real32)x;
+ BlockID block = World_GetBlock(x, y, z);
+ if (block == BLOCK_AIR) continue;
+ UInt8 collide = Block_Collide[block];
+ if (collide == COLLIDE_SOLID && !checkSolid) continue;
- for (y = bbMin.Y; y <= bbMax.Y; y++) {
- for (z = bbMin.Z; z <= bbMax.Z; z++) {
- for (x = bbMin.X; x <= bbMax.X; x++) {
- BlockID block = World_GetPhysicsBlock(x, y, z);
- blockBB.Min = new Vector3(x, y, z) + Block_MinBB[block];
- blockBB.Max = new Vector3(x, y, z) + Block_MaxBB[block];
+ Vector3_Add(&blockBB.Min, &v, &Block_MinBB[block]);
+ Vector3_Add(&blockBB.Max, &v, &Block_MaxBB[block]);
+ if (!AABB_Intersects(&blockBB, bounds)) continue;
- if (!AABB_Intersects(&blockBB, adjFinalBB)) continue;
- if (Block_Collide[block] == COLLIDE_SOLID) return false;
+ modifier = min(modifier, Block_SpeedMultiplier[block]);
+ if (Block_ExtendedCollide[block] == COLLIDE_LIQUID) {
+ comp->UseLiquidGravity = true;
+ }
}
}
}
- return true;
+ return modifier;
}
-void Collisions_ClipX(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
- entity->Velocity.X = 0.0f;
- entityBB->Min.X = entity->Position.X - size->X / 2; extentBB->Min.X = entityBB->Min.X;
- entityBB->Max.X = entity->Position.X + size->X / 2; extentBB->Max.X = entityBB->Max.X;
+Real32 PhysicsComp_GetSpeed(HacksComp* hacks, Real32 speedMul) {
+ Real32 factor = hacks->Floating ? speedMul : 1.0f, speed = factor;
+ if (hacks->Speeding && hacks->CanSpeed) speed += factor * hacks->SpeedMultiplier;
+ if (hacks->HalfSpeeding && hacks->CanSpeed) speed += factor * hacks->SpeedMultiplier / 2;
+ return hacks->CanSpeed ? speed : min(speed, 1.0f);
}
-void Collisions_ClipY(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
- entity->Velocity.Y = 0.0f;
- entityBB->Min.Y = entity->Position.Y; extentBB->Min.Y = entityBB->Min.Y;
- entityBB->Max.Y = entity->Position.Y + size->Y; extentBB->Max.Y = entityBB->Max.Y;
+Real32 PhysicsComp_GetBaseSpeed(PhysicsComp* comp) {
+ AABB bounds; Entity_GetBounds(comp->Entity, &bounds);
+ comp->UseLiquidGravity = false;
+ Real32 baseModifier = PhysicsComp_LowestModifier(comp, &bounds, false);
+ bounds.Min.Y -= 0.5f / 16.0f; /* also check block standing on */
+ Real32 solidModifier = PhysicsComp_LowestModifier(comp, &bounds, true);
+
+ if (baseModifier == MATH_POS_INF && solidModifier == MATH_POS_INF) return 1.0f;
+ return baseModifier == MATH_POS_INF ? solidModifier : baseModifier;
}
-void Collisions_ClipZ(Entity* entity, Vector3* size, AABB* entityBB, AABB* extentBB) {
- entity->Velocity.Z = 0.0f;
- entityBB->Min.Z = entity->Position.Z - size->Z / 2; extentBB->Min.Z = entityBB->Min.Z;
- entityBB->Max.Z = entity->Position.Z + size->Z / 2; extentBB->Max.Z = entityBB->Max.Z;
+#define LIQUID_GRAVITY 0.02f
+#define ROPE_GRAVITY 0.034f
+void PhysicsComp_PhysicsTick(PhysicsComp* comp, Vector3 vel) {
+ Entity* entity = comp->Entity;
+ HacksComp* hacks = comp->Hacks;
+
+ if (hacks->Noclip) entity->OnGround = false;
+ Real32 baseSpeed = PhysicsComp_GetBaseSpeed(comp);
+ Real32 verSpeed = baseSpeed * (PhysicsComp_GetSpeed(hacks, 8.0f) / 5.0f);
+ Real32 horSpeed = baseSpeed * PhysicsComp_GetSpeed(hacks, 8.0f / 5.0f) * hacks->BaseHorSpeed;
+ /* previously horSpeed used to be multiplied by factor of 0.02 in last case */
+ /* it's now multiplied by 0.1, so need to divide by 5 so user speed modifier comes out same */
+
+ /* TODO: this is a temp fix to avoid crashing for high horizontal speed */
+ if (horSpeed > 75.0f) horSpeed = 75.0f;
+ /* vertical speed never goes below: base speed * 1.0 */
+ if (verSpeed < baseSpeed) verSpeed = baseSpeed;
+
+ bool womSpeedBoost = hacks->CanDoubleJump && hacks->WOMStyleHacks;
+ if (!hacks->Floating && womSpeedBoost) {
+ if (comp->MultiJumps == 1) { horSpeed *= 46.5f; verSpeed *= 7.5f; }
+ else if (comp->MultiJumps > 1) { horSpeed *= 93.0f; verSpeed *= 10.0f; }
+ }
+
+ if (Entity_TouchesAnyWater(entity) && !hacks->Floating) {
+ Vector3 waterDrag = VECTOR3_CONST(0.8f, 0.8f, 0.8f);
+ PhysicsComp_MoveNormal(comp, vel, 0.02f * horSpeed, waterDrag, LIQUID_GRAVITY, verSpeed);
+ } else if (Entity_TouchesAnyLava(entity) && !hacks->Floating) {
+ Vector3 lavaDrag = VECTOR3_CONST(0.5f, 0.5f, 0.5f);
+ PhysicsComp_MoveNormal(comp, vel, 0.02f * horSpeed, lavaDrag, LIQUID_GRAVITY, verSpeed);
+ } else if (Entity_TouchesAnyRope(entity) && !hacks->Floating) {
+ Vector3 ropeDrag = VECTOR3_CONST(0.5f, 0.85f, 0.5f);
+ PhysicsComp_MoveNormal(comp, vel, 0.02f * 1.7f, ropeDrag, ROPE_GRAVITY, verSpeed);
+ } else {
+ Real32 factor = hacks->Floating || entity->OnGround ? 0.1f : 0.02f;
+ Real32 gravity = comp->UseLiquidGravity ? LIQUID_GRAVITY : entity->Model->Gravity;
+
+ if (hacks->Floating) {
+ PhysicsComp_MoveFlying(comp, vel, factor * horSpeed, entity->Model->Drag, gravity, verSpeed);
+ } else {
+ PhysicsComp_MoveNormal(comp, vel, factor * horSpeed, entity->Model->Drag, gravity, verSpeed);
+ }
+
+ if (PhysicsComp_OnIce(entity) && !hacks->Floating) {
+ /* limit components to +-0.25f by rescaling vector to [-0.25, 0.25] */
+ if (Math_AbsF(entity->Velocity.X) > 0.25f || Math_AbsF(entity->Velocity.Z) > 0.25f) {
+ Real32 xScale = Math_AbsF(0.25f / entity->Velocity.X);
+ Real32 zScale = Math_AbsF(0.25f / entity->Velocity.Z);
+
+ Real32 scale = min(xScale, zScale);
+ entity->Velocity.X *= scale;
+ entity->Velocity.Z *= scale;
+ }
+ } else if (entity->OnGround || hacks->Flying) {
+ Vector3_Mul3By(&entity->Velocity, &entity->Model->GroundFriction); /* air drag or ground friction */
+ }
+ }
+
+ if (entity->OnGround) comp->MultiJumps = 0;
+}
+
+Real64 PhysicsComp_YPosAt(Int32 t, Real32 u) {
+ /* v(t, u) = (4 + u) * (0.98^t) - 4, where u = initial velocity */
+ /* x(t, u) = Σv(t, u) from 0 to t (since we work in discrete timesteps) */
+ /* plugging into Wolfram Alpha gives 1 equation as */
+ /* (0.98^t) * (-49u - 196) - 4t + 50u + 196 */
+ Real64 a = Math_Exp(-0.0202027 * t); /* ~0.98^t */
+ return a * (-49 * u - 196) - 4 * t + 50 * u + 196;
+}
+
+Real64 PhysicsComp_GetMaxHeight(Real32 u) {
+ /* equation below comes from solving diff(x(t, u))= 0 */
+ /* We only work in discrete timesteps, so test both rounded up and down */
+ Real64 t = 49.49831645 * Math_Log(0.247483075 * u + 0.9899323);
+ Real64 value_floor = PhysicsComp_YPosAt((Int32)t, u);
+ Real64 value_ceil = PhysicsComp_YPosAt((Int32)t + 1, u);
+ return max(value_floor, value_ceil);
+}
+
+/* Calculates the jump velocity required such that when a client presses
+the jump binding they will be able to jump up to the given height. */
+void PhysicsComp_CalculateJumpVelocity(PhysicsComp* comp, bool userVel, Real32 jumpHeight) {
+ comp->JumpVel = 0.0f;
+ if (jumpHeight == 0.0f) return;
+
+ if (jumpHeight >= 256.0f) comp->JumpVel = 10.0f;
+ if (jumpHeight >= 512.0f) comp->JumpVel = 16.5f;
+ if (jumpHeight >= 768.0f) comp->JumpVel = 22.5f;
+
+ while (PhysicsComp_GetMaxHeight(comp->JumpVel) <= jumpHeight) { comp->JumpVel += 0.001f; }
+ if (userVel) comp->UserJumpVel = comp->JumpVel;
+}
+
+void PhysicsComp_DoEntityPush(Entity* entity) {
+ Int32 id;
+ Vector3 dir; dir.Y = 0.0f;
+
+ for (id = 0; id < ENTITIES_MAX_COUNT; id++) {
+ Entity* other = Entities_List[id];
+ if (other == NULL || other == entity) continue;
+ if (!other->Model->Pushes) continue;
+
+ bool yIntersects =
+ entity->Position.Y <= (other->Position.Y + other->Size.Y) &&
+ other->Position.Y <= (entity->Position.Y + entity->Size.Y);
+ if (!yIntersects) continue;
+
+ dir.X = other->Position.X - entity->Position.X;
+ dir.Z = other->Position.Z - entity->Position.Z;
+ Real32 dist = dir.X * dir.X + dir.Z * dir.Z;
+ if (dist < 0.002f || dist > 1.0f) continue; /* TODO: range needs to be lower? */
+
+ Vector3_Normalize(&dir, &dir);
+ Real32 pushStrength = (1 - dist) / 32.0f; /* TODO: should be 24/25 */
+ /* entity.Velocity -= dir * pushStrength */
+ Vector3_Mul1By(&dir, pushStrength);
+ Vector3_SubBy(&entity->Velocity, &dir);
+ }
}
\ No newline at end of file
diff --git a/src/Client/EntityComponents.h b/src/Client/EntityComponents.h
index f2635ccc5..768f059d3 100644
--- a/src/Client/EntityComponents.h
+++ b/src/Client/EntityComponents.h
@@ -9,7 +9,7 @@
typedef struct Entity_ Entity;
typedef struct LocationUpdate_ LocationUpdate;
-/* Entity component that performs model animation depending on movement speed and time. */
+/* Entity component that performs model animation depending on movement speed and time */
typedef struct AnimatedComp_ {
Real32 BobbingHor, BobbingVer, BobbingModel;
Real32 WalkTime, Swing, BobStrength;
@@ -23,7 +23,7 @@ void AnimatedComp_Init(AnimatedComp* anim);
void AnimatedComp_Update(AnimatedComp* anim, Vector3 oldPos, Vector3 newPos, Real64 delta, bool onGround);
void AnimatedComp_GetCurrent(AnimatedComp* anim, Real32 t, bool calcHumanAnims);
-/* Entity component that performs tilt animation depending on movement speed and time. */
+/* Entity component that performs tilt animation depending on movement speed and time */
typedef struct TiltComp_ {
Real32 TiltX, TiltY, VelTiltStrength;
Real32 VelTiltStrengthO, VelTiltStrengthN;
@@ -33,33 +33,34 @@ void TiltComp_Init(TiltComp* anim);
void TiltComp_Update(TiltComp* anim, Real64 delta);
void TiltComp_GetCurrent(TiltComp* anim, Real32 t);
-/* Entity component that performs management of hack states. */
+/* Entity component that performs management of hack states */
typedef struct HacksComponent_ {
UInt8 UserType;
- /* Speed player move at, relative to normal speed, when the 'speeding' key binding is held down. */
+ /* Speed player move at, relative to normal speed, when the 'speeding' key binding is held down */
Real32 SpeedMultiplier;
/* Whether blocks that the player places that intersect themselves, should cause the player to
- be pushed back in the opposite direction of the placed block. */
+ be pushed back in the opposite direction of the placed block */
bool PushbackPlacing;
- /* Whether the player should be able to step up whole blocks, instead of just slabs. */
+ /* Whether the player should be able to step up whole blocks, instead of just slabs */
bool FullBlockStep;
- /* Whether the player has allowed hacks usage as an option. Note 'can use X' set by the server override this. */
+ /* Whether the player has allowed hacks usage as an option. Note 'can use X' set by the server override this */
bool Enabled;
bool CanAnyHacks, CanUseThirdPersonCamera, CanSpeed, CanFly;
bool CanRespawn, CanNoclip, CanPushbackBlocks,CanSeeAllNames;
bool CanDoubleJump, CanBePushed;
- /* Maximum speed the entity can move at horizontally when CanSpeed is false. */
+ /* Maximum speed the entity can move at horizontally when CanSpeed is false */
Real32 BaseHorSpeed;
- /* Max amount of jumps the player can perform. */
+ /* Max amount of jumps the player can perform */
Int32 MaxJumps;
- /* Whether the player should slide after letting go of movement buttons in noclip. */
+ /* Whether the player should slide after letting go of movement buttons in noclip */
bool NoclipSlide;
- /* Whether the player has allowed the usage of fast double jumping abilities. */
+ /* Whether the player has allowed the usage of fast double jumping abilities */
bool WOMStyleHacks;
- bool Noclip, Flying,FlyingUp, FlyingDown, Speeding, HalfSpeeding;
+ bool Noclip, Flying, FlyingUp, FlyingDown, Speeding, HalfSpeeding;
+ bool Floating; /* true if NoClip or Flying */
UInt8 HacksFlagsBuffer[String_BufferSize(128)];
String HacksFlags;
} HacksComp;
@@ -71,13 +72,13 @@ void HacksComp_SetUserType(HacksComp* hacks, UInt8 value, bool setBlockPerms);
void HacksComp_CheckConsistency(HacksComp* hacks);
void HacksComp_UpdateState(HacksComp* hacks);
-/* Represents a position and orientation state. */
+/* Represents a position and orientation state */
typedef struct InterpState_ {
Vector3 Pos;
Real32 HeadX, HeadY, RotX, RotZ;
} InterpState;
-/* Base entity component that performs interpolation of position and orientation. */
+/* Base entity component that performs interpolation of position and orientation */
typedef struct InterpComp_ {
InterpState Prev, Next;
Real32 PrevRotY, NextRotY;
@@ -91,10 +92,10 @@ void InterpComp_LerpAngles(InterpComp* interp, Entity* entity, Real32 t);
void LocalInterpComp_SetLocation(InterpComp* interp, LocationUpdate* update, bool interpolate);
void LocalInterpComp_AdvanceState(InterpComp* interp);
-/* Entity component that performs interpolation for network players. */
+/* Entity component that performs interpolation for network players */
typedef struct NetInterpComp_ {
InterpComp Base;
- /* Last known position and orientation sent by the server. */
+ /* Last known position and orientation sent by the server */
InterpState Cur;
Int32 StatesCount;
InterpState States[10];
@@ -103,10 +104,37 @@ typedef struct NetInterpComp_ {
void NetInterpComp_SetLocation(NetInterpComp* interp, LocationUpdate* update, bool interpolate);
void NetInterpComp_AdvanceState(NetInterpComp* interp);
-/* Entity component that draws square and circle shadows beneath entities. */
+/* Entity component that draws square and circle shadows beneath entities */
bool ShadowComponent_BoundShadowTex;
GfxResourceID ShadowComponent_ShadowTex;
void ShadowComponent_Draw(Entity* entity);
+/* Entity component that performs collision detection */
+typedef struct CollisionsComp_ {
+ Entity* Entity;
+ bool HitXMin, HitYMin, HitZMin, HitXMax, HitYMax, HitZMax, WasOn;
+} CollisionsComp;
+bool Collisions_HitHorizontal(CollisionsComp* comp);
+void Collisions_MoveAndWallSlide(CollisionsComp* comp);
+
+/* Entity component that performs collisions */
+typedef struct PhysicsComp_ {
+ bool UseLiquidGravity; /* used by BlockDefinitions */
+ bool CanLiquidJump, Jumping;
+ Int32 MultiJumps;
+ Entity* Entity;
+
+ Real32 JumpVel, UserJumpVel, ServerJumpVel;
+ HacksComp* Hacks;
+ CollisionsComp* Collisions;
+} PhysicsComp;
+
+void PhysicsComp_Init(PhysicsComp* comp, Entity* entity);
+void PhysicsComp_UpdateVelocityState(PhysicsComp* comp);
+void PhysicsComp_DoNormalJump(PhysicsComp* comp);
+void PhysicsComp_PhysicsTick(PhysicsComp* comp, Vector3 vel);
+void PhysicsComp_CalculateJumpVelocity(PhysicsComp* comp, bool userVel, Real32 jumpHeight);
+Real64 PhysicsComp_GetMaxHeight(Real32 u);
+void PhysicsComp_DoEntityPush(Entity* entity);
#endif
\ No newline at end of file
diff --git a/src/Client/EnvRenderer.c b/src/Client/EnvRenderer.c
index d291cbb81..5a13e5578 100644
--- a/src/Client/EnvRenderer.c
+++ b/src/Client/EnvRenderer.c
@@ -18,11 +18,11 @@ GfxResourceID env_cloudsVb, env_skyVb, env_cloudsTex;
Int32 env_cloudVertices, env_skyVertices;
Real32 EnvRenderer_BlendFactor(Real32 x) {
- /* return -0.05 + 0.22 * (Math_LogE(x) * 0.25f); */
- Real32 blend = -0.13f + 0.28f * (Math_LogE(x) * 0.25f);
- if (blend < 0.0f) blend = 0.0f;
- if (blend > 1.0f) blend = 1.0f;
- return blend;
+ /* return -0.05 + 0.22 * (Math_Log(x) * 0.25f); */
+ Real64 blend = -0.13 + 0.28 * (Math_Log(x) * 0.25);
+ if (blend < 0.0) blend = 0.0;
+ if (blend > 1.0) blend = 1.0;
+ return (Real32)blend;
}
void EnvRenderer_BlockOn(Real32* fogDensity, PackedCol* fogCol) {
@@ -59,8 +59,11 @@ void EnvRenderer_RenderMinimal(Real64 deltaTime) {
/* TODO: rewrite this to avoid raising the event? want to avoid recreating vbos too many times often */
if (fogDensity != 0.0f) {
/* Exp fog mode: f = e^(-density*coord) */
- /* Solve for f = 0.05 to figure out coord (good approx for fog end) */
- Real32 dist = (Real32)Math_LogE(0.05f) / -fogDensity;
+ /* Solve coord for f = 0.05 (good approx for fog end) */
+ /* i.e. log(0.05) = -density * coord */
+
+ #define LOG_005 -2.99573227355399
+ Real64 dist = LOG_005 / -fogDensity;
Game_SetViewDistance((Int32)dist, false);
} else {
Game_SetViewDistance(Game_UserViewDistance, false);
@@ -129,8 +132,10 @@ void EnvRenderer_UpdateFog(void) {
0.99=z/end --> z=end*0.99
therefore
d = -ln(0.01)/(end*0.99) */
- Real32 density = -Math_LogE(0.01f) / (Game_ViewDistance * 0.99f);
- Gfx_SetFogDensity(density);
+
+ #define LOG_001 -4.60517018598809
+ Real64 density = -(LOG_001) / (Game_ViewDistance * 0.99);
+ Gfx_SetFogDensity((Real32)density);
} else {
Gfx_SetFogMode(FOG_LINEAR);
Gfx_SetFogEnd(Game_ViewDistance);
diff --git a/src/Client/ExtMath.c b/src/Client/ExtMath.c
index 6d2aa4ee1..ffb594366 100644
--- a/src/Client/ExtMath.c
+++ b/src/Client/ExtMath.c
@@ -1,5 +1,21 @@
#include "ExtMath.h"
+#include
+/* TODO: Replace with own functions that don't rely on stdlib */
+
+Real32 Math_AbsF(Real32 x) { return fabsf(x); }
+Real32 Math_SinF(Real32 x) { return sinf(x); }
+Real32 Math_CosF(Real32 x) { return cosf(x); }
+Real32 Math_TanF(Real32 x) { return tanf(x); }
+Real32 Math_SqrtF(Real32 x) { return sqrtf(x); }
+Real32 Math_ModF(Real32 x, Real32 y) { return fmodf(x, y); }
+
+Real64 Math_Log(Real64 x) { return log(x); }
+Real64 Math_Exp(Real64 x) { return exp(x); }
+Real64 Math_Asin(Real64 x) { return asin(x); }
+Real64 Math_Atan2(Real64 y, Real64 x) { return atan2(y, x); }
+
+Int32 Math_AbsI(Int32 x) { return abs(x); }
Int32 Math_Floor(Real32 value) {
Int32 valueI = (Int32)value;
return valueI > value ? valueI - 1 : valueI;
diff --git a/src/Client/ExtMath.h b/src/Client/ExtMath.h
index 49920ba30..273a33bc5 100644
--- a/src/Client/ExtMath.h
+++ b/src/Client/ExtMath.h
@@ -1,6 +1,5 @@
#ifndef CC_MATH_H
#define CC_MATH_H
-#include
#include "Typedefs.h"
/* Simple math functions and constants.
Copyright 2017 ClassicalSharp | Licensed under BSD-3
@@ -15,21 +14,19 @@
#define Math_Deg2Packed(x) ((UInt8)((x) * 256.0f / 360.0f))
#define Math_Packed2Deg(x) ((x) * 360.0f / 256.0f)
-#define Math_AbsF(x) fabsf(x)
-#define Math_AbsI(x) abs(x)
+Real32 Math_AbsF(Real32 x);
+Real32 Math_SinF(Real32 x);
+Real32 Math_CosF(Real32 x);
+Real32 Math_TanF(Real32 x);
+Real32 Math_SqrtF(Real32 x);
+Real32 Math_ModF(Real32 x, Real32 y);
-#define Math_LogE(x) logf(x)
-#define Math_PowE(x) expf(x)
-
-#define Math_Sin(x) sinf(x)
-#define Math_Cos(x) cosf(x)
-#define Math_Tan(x) tanf(x)
-#define Math_Asin(x) asinf(x)
-#define Math_Atan2(y, x) atan2f(y, x)
-
-#define Math_Sqrt(x) sqrtf(x)
-#define Math_Mod(x, y) fmodf(x, y)
+Real64 Math_Log(Real64 x);
+Real64 Math_Exp(Real64 x);
+Real64 Math_Asin(Real64 x);
+Real64 Math_Atan2(Real64 y, Real64 x);
+Int32 Math_AbsI(Int32 x);
Int32 Math_Floor(Real32 value);
Int32 Math_Ceil(Real32 value);
Int32 Math_Log2(Int32 value);
diff --git a/src/Client/HeldBlockRenderer.c b/src/Client/HeldBlockRenderer.c
index c9a2c7026..cebbfa9b0 100644
--- a/src/Client/HeldBlockRenderer.c
+++ b/src/Client/HeldBlockRenderer.c
@@ -103,16 +103,16 @@ void HeldBlockRenderer_ProjectionChanged(void* obj) {
*/
void HeldBlockRenderer_DigAnimation(void) {
Real32 t = held_time / held_period;
- Real32 sinHalfCircle = Math_Sin(t * MATH_PI);
- Real32 sqrtLerpPI = Math_Sqrt(t) * MATH_PI;
+ Real32 sinHalfCircle = Math_SinF(t * MATH_PI);
+ Real32 sqrtLerpPI = Math_SqrtF(t) * MATH_PI;
- held_entity.Position.X -= Math_Sin(sqrtLerpPI) * 0.4f;
- held_entity.Position.Y += Math_Sin((sqrtLerpPI * 2)) * 0.2f;
+ held_entity.Position.X -= Math_SinF(sqrtLerpPI) * 0.4f;
+ held_entity.Position.Y += Math_SinF((sqrtLerpPI * 2)) * 0.2f;
held_entity.Position.Z -= sinHalfCircle * 0.2f;
- Real32 sinHalfCircleWeird = Math_Sin(t * t * MATH_PI);
- held_entity.RotY -= Math_Sin(sqrtLerpPI) * 80.0f;
- held_entity.HeadY -= Math_Sin(sqrtLerpPI) * 80.0f;
+ Real32 sinHalfCircleWeird = Math_SinF(t * t * MATH_PI);
+ held_entity.RotY -= Math_SinF(sqrtLerpPI) * 80.0f;
+ held_entity.HeadY -= Math_SinF(sqrtLerpPI) * 80.0f;
held_entity.RotX += sinHalfCircleWeird * 20.0f;
}
@@ -172,7 +172,7 @@ void HeldBlockRenderer_DoAnimation(Real64 delta, Real32 lastSwingY) {
if (held_swinging || !held_breaking) {
Real32 t = held_time / held_period;
- held_swingY = -0.4f * Math_Sin(t * MATH_PI);
+ held_swingY = -0.4f * Math_SinF(t * MATH_PI);
held_entity.Position.Y += held_swingY;
if (held_swinging) {
diff --git a/src/Client/IModel.c b/src/Client/IModel.c
index 038c4f815..d2a5f7a07 100644
--- a/src/Client/IModel.c
+++ b/src/Client/IModel.c
@@ -118,8 +118,8 @@ void IModel_SetupState(IModel* model, Entity* entity) {
IModel_Cols[5] = IModel_Cols[4];
Real32 yawDelta = entity->HeadY - entity->RotY;
- IModel_cosHead = Math_Cos(yawDelta * MATH_DEG2RAD);
- IModel_sinHead = Math_Sin(yawDelta * MATH_DEG2RAD);
+ IModel_cosHead = Math_CosF(yawDelta * MATH_DEG2RAD);
+ IModel_sinHead = Math_SinF(yawDelta * MATH_DEG2RAD);
}
void IModel_UpdateVB(void) {
@@ -158,9 +158,9 @@ void IModel_DrawPart(ModelPart part) {
void IModel_DrawRotate(Real32 angleX, Real32 angleY, Real32 angleZ, ModelPart part, bool head) {
IModel* model = IModel_ActiveModel;
- Real32 cosX = Math_Cos(-angleX), sinX = Math_Sin(-angleX);
- Real32 cosY = Math_Cos(-angleY), sinY = Math_Sin(-angleY);
- Real32 cosZ = Math_Cos(-angleZ), sinZ = Math_Sin(-angleZ);
+ Real32 cosX = Math_CosF(-angleX), sinX = Math_SinF(-angleX);
+ Real32 cosY = Math_CosF(-angleY), sinY = Math_SinF(-angleY);
+ Real32 cosZ = Math_CosF(-angleZ), sinZ = Math_SinF(-angleZ);
Real32 x = part.RotX, y = part.RotY, z = part.RotZ;
ModelVertex* src = &model->vertices[part.Offset];
diff --git a/src/Client/InputHandler.c b/src/Client/InputHandler.c
index ee10e83a6..5443e2c4e 100644
--- a/src/Client/InputHandler.c
+++ b/src/Client/InputHandler.c
@@ -386,7 +386,7 @@ void InputHandler_KeyDown(void* obj, Int32 key) {
Game_ScreenshotRequested = true;
} else if (active->VTABLE->HandlesKeyDown(active, key)) {
} else if (InputHandler_HandleCoreKey(key)) {
- } else if (LocalPlayer_Instance.Input.Handles(key)) {
+ } else if (LocalPlayer_HandlesKey(key)) {
} else {
UInt8 textBuffer[String_BufferSize(STRING_SIZE)];
String text = String_InitAndClearArray(textBuffer);
diff --git a/src/Client/IsometricDrawer.c b/src/Client/IsometricDrawer.c
index 4995683f7..053a27f65 100644
--- a/src/Client/IsometricDrawer.c
+++ b/src/Client/IsometricDrawer.c
@@ -44,10 +44,10 @@ void IsometricDrawer_InitCache(void) {
Matrix_RotateX(&rotX, -30.0f * MATH_DEG2RAD);
Matrix_Mul(&iso_transform, &rotY, &rotX);
- iso_cosX = Math_Cos(30.0f * MATH_DEG2RAD);
- iso_sinX = Math_Sin(30.0f * MATH_DEG2RAD);
- iso_cosY = Math_Cos(-45.0f * MATH_DEG2RAD);
- iso_sinY = Math_Sin(-45.0f * MATH_DEG2RAD);
+ iso_cosX = Math_CosF(30.0f * MATH_DEG2RAD);
+ iso_sinX = Math_SinF(30.0f * MATH_DEG2RAD);
+ iso_cosY = Math_CosF(-45.0f * MATH_DEG2RAD);
+ iso_sinY = Math_SinF(-45.0f * MATH_DEG2RAD);
}
void IsometricDrawer_Flush(void) {
diff --git a/src/Client/MapGenerator.c b/src/Client/MapGenerator.c
index 45c0ddf44..f2b9f6958 100644
--- a/src/Client/MapGenerator.c
+++ b/src/Client/MapGenerator.c
@@ -212,13 +212,13 @@ void NotchyGen_CarveCaves(void) {
Int32 caveLen = (Int32)(Random_Float(&rnd) * Random_Float(&rnd) * 200.0f);
Real32 theta = Random_Float(&rnd) * 2.0f * MATH_PI, deltaTheta = 0.0f;
- Real32 phi = Random_Float(&rnd) * 2.0f * MATH_PI, deltaPhi = 0.0f;
+ Real32 phi = Random_Float(&rnd) * 2.0f * MATH_PI, deltaPhi = 0.0f;
Real32 caveRadius = Random_Float(&rnd) * Random_Float(&rnd);
for (j = 0; j < caveLen; j++) {
- caveX += Math_Sin(theta) * Math_Cos(phi);
- caveZ += Math_Cos(theta) * Math_Cos(phi);
- caveY += Math_Sin(phi);
+ caveX += Math_SinF(theta) * Math_CosF(phi);
+ caveZ += Math_CosF(theta) * Math_CosF(phi);
+ caveY += Math_SinF(phi);
theta = theta + deltaTheta * 0.2f;
deltaTheta = deltaTheta * 0.9f + Random_Float(&rnd) - Random_Float(&rnd);
@@ -232,7 +232,7 @@ void NotchyGen_CarveCaves(void) {
Real32 radius = (Gen_Height - cenY) / (Real32)Gen_Height;
radius = 1.2f + (radius * 3.5f + 1.0f) * caveRadius;
- radius = radius * Math_Sin(j * MATH_PI / caveLen);
+ radius = radius * Math_SinF(j * MATH_PI / caveLen);
NotchyGen_FillOblateSpheroid(cenX, cenY, cenZ, radius, BLOCK_AIR);
}
}
@@ -254,16 +254,16 @@ void NotchyGen_CarveOreVeins(Real32 abundance, const UInt8* state, BlockID block
Real32 phi = Random_Float(&rnd) * 2.0f * MATH_PI, deltaPhi = 0.0f;
for (j = 0; j < veinLen; j++) {
- veinX += Math_Sin(theta) * Math_Cos(phi);
- veinZ += Math_Cos(theta) * Math_Cos(phi);
- veinY += Math_Sin(phi);
+ veinX += Math_SinF(theta) * Math_CosF(phi);
+ veinZ += Math_CosF(theta) * Math_CosF(phi);
+ veinY += Math_SinF(phi);
theta = deltaTheta * 0.2f;
deltaTheta = deltaTheta * 0.9f + Random_Float(&rnd) - Random_Float(&rnd);
phi = phi * 0.5f + deltaPhi * 0.25f;
deltaPhi = deltaPhi * 0.9f + Random_Float(&rnd) - Random_Float(&rnd);
- Real32 radius = abundance * Math_Sin(j * MATH_PI / veinLen) + 1.0f;
+ Real32 radius = abundance * Math_SinF(j * MATH_PI / veinLen) + 1.0f;
NotchyGen_FillOblateSpheroid((Int32)veinX, (Int32)veinY, (Int32)veinZ, radius, block);
}
}
diff --git a/src/Client/Menus.c b/src/Client/Menus.c
index cd59afda1..4e9381c9f 100644
--- a/src/Client/Menus.c
+++ b/src/Client/Menus.c
@@ -2611,9 +2611,13 @@ void HacksSettingsScreen_SetClipping(STRING_PURE String* v) {
void HacksSettingsScreen_GetJump(STRING_TRANSIENT String* v) { String_AppendReal32(v, LocalPlayer_JumpHeight(), 3); }
void HacksSettingsScreen_SetJump(STRING_PURE String* v) {
- LocalPlayer_Instance.physics.CalculateJumpVelocity(true, Menu_Real32(v));
- Real32 jumpVel = LocalPlayer_Instance.physics.jumpVel;
- Options_Set(OPT_JUMP_VELOCITY, jumpVel.ToString());
+ PhysicsComp* physics = &LocalPlayer_Instance.Physics;
+ PhysicsComp_CalculateJumpVelocity(physics, true, Menu_Real32(v));
+
+ UInt8 strBuffer[String_BufferSize(STRING_SIZE)];
+ String str = String_InitAndClearArray(strBuffer);
+ String_AppendReal32(&str, physics->JumpVel, 8);
+ Options_Set(OPT_JUMP_VELOCITY, &str);
}
void HacksSettingsScreen_GetWOMHacks(STRING_TRANSIENT String* v) { Menu_GetBool(v, LocalPlayer_Instance.Hacks.WOMStyleHacks); }
diff --git a/src/Client/ModelCache.c b/src/Client/ModelCache.c
index cbc7a5d4a..fcad864e5 100644
--- a/src/Client/ModelCache.c
+++ b/src/Client/ModelCache.c
@@ -572,9 +572,9 @@ void SpiderModel_DrawModel(Entity* entity) {
IModel_DrawPart(Spider_Link);
IModel_DrawPart(Spider_End);
- Real32 rotX = Math_Sin(entity->Anim.WalkTime) * entity->Anim.Swing * MATH_PI;
- Real32 rotZ = Math_Cos(entity->Anim.WalkTime * 2) * entity->Anim.Swing * MATH_PI / 16.0f;
- Real32 rotY = Math_Sin(entity->Anim.WalkTime * 2) * entity->Anim.Swing * MATH_PI / 32.0f;
+ Real32 rotX = Math_SinF(entity->Anim.WalkTime) * entity->Anim.Swing * MATH_PI;
+ Real32 rotZ = Math_CosF(entity->Anim.WalkTime * 2) * entity->Anim.Swing * MATH_PI / 16.0f;
+ Real32 rotY = Math_SinF(entity->Anim.WalkTime * 2) * entity->Anim.Swing * MATH_PI / 32.0f;
IModel_Rotation = ROTATE_ORDER_XZY;
IModel_DrawRotate(rotX, quarterPi + rotY, eighthPi + rotZ, Spider_LeftLeg, false);
@@ -1120,10 +1120,10 @@ Real32 BlockModel_GetEyeY(Entity* entity) {
Vector3 BlockModel_GetCollisionSize(void) {
Vector3 size;
- Vector3_Subtract(&size, &BlockModel_maxBB, &BlockModel_minBB);
+ Vector3_Sub(&size, &BlockModel_maxBB, &BlockModel_minBB);
/* to fit slightly inside */
- Vector3 sizeShrink = Vector3_Create1(0.75f / 16.0f);
- Vector3_Subtract(&size, &size, &sizeShrink);
+ Vector3 sizeShrink = VECTOR3_CONST1(0.75f / 16.0f);
+ Vector3_SubBy(&size, &sizeShrink);
return size;
}
diff --git a/src/Client/Particle.c b/src/Client/Particle.c
index d98b0de6f..774cc9963 100644
--- a/src/Client/Particle.c
+++ b/src/Client/Particle.c
@@ -105,7 +105,7 @@ bool Particle_PhysicsTick(Particle* p, Real32 gravity, bool throughLiquids, Real
p->Velocity.Y -= gravity * (Real32)delta;
Int32 startY = Math_Floor(p->NextPos.Y);
Vector3 velocity;
- Vector3_Multiply1(&velocity, &p->Velocity, (Real32)delta * 3.0f);
+ Vector3_Mul1(&velocity, &p->Velocity, (Real32)delta * 3.0f);
Vector3_Add(&p->NextPos, &p->NextPos, &velocity);
Int32 endY = Math_Floor(p->NextPos.Y);
diff --git a/src/Client/Physics.c b/src/Client/Physics.c
index 79e40bffd..7c8b8cdb2 100644
--- a/src/Client/Physics.c
+++ b/src/Client/Physics.c
@@ -71,7 +71,7 @@ bool Intersection_RayIntersectsRotatedBox(Vector3 origin, Vector3 dir, Entity* t
* /
/
*/
- Vector3 delta; Vector3_Subtract(&delta, &origin, &target->Position); /* delta = origin - target.Position */
+ Vector3 delta; Vector3_Sub(&delta, &origin, &target->Position); /* delta = origin - target.Position */
delta = Intersection_InverseRotate(delta, target); /* delta = UndoRotation(delta) */
Vector3_Add(&origin, &delta, &target->Position); /* origin = delta + target.Position */
diff --git a/src/Client/Physics.h b/src/Client/Physics.h
index 57fcb08a6..15ddd1482 100644
--- a/src/Client/Physics.h
+++ b/src/Client/Physics.h
@@ -25,7 +25,7 @@ bool Intersection_RayIntersectsRotatedBox(Vector3 origin, Vector3 dir, Entity* t
Source: http://www.cs.utah.edu/~awilliam/box/box.pdf */
bool Intersection_RayIntersectsBox(Vector3 origin, Vector3 dir, Vector3 min, Vector3 max, Real32* t0, Real32* t1);
-typedef struct SearcherState_ { Int32 X, Y, Z; Real32 tSquared; } SearcherState;
+typedef struct SearcherState_ { Int32 X, Y, Z; Real32 tSquared; } SearcherState;
extern SearcherState* Searcher_States;
UInt32 Searcher_FindReachableBlocks(Entity* entity, AABB* entityBB, AABB* entityExtentBB);
void Searcher_CalcTime(Vector3* vel, AABB *entityBB, AABB* blockBB, Real32* tx, Real32* ty, Real32* tz);
diff --git a/src/Client/PickedPosRenderer.c b/src/Client/PickedPosRenderer.c
index 9ad2e5d48..f047cb4c2 100644
--- a/src/Client/PickedPosRenderer.c
+++ b/src/Client/PickedPosRenderer.c
@@ -71,7 +71,7 @@ void PickedPosRenderer_ZQuad(Real32 z, Real32 x1, Real32 y1, Real32 x2, Real32 y
void PickedPosRenderer_UpdateState(PickedPos* selected) {
pickedPos_ptr = pickedPos_vertices;
Vector3 delta;
- Vector3_Subtract(&delta, &Game_CurrentCameraPos, &selected->Min);
+ Vector3_Sub(&delta, &Game_CurrentCameraPos, &selected->Min);
Real32 dist = Vector3_LengthSquared(&delta);
Real32 offset = 0.01f;
diff --git a/src/Client/Picking.c b/src/Client/Picking.c
index db1217ee6..5c4de4eb5 100644
--- a/src/Client/Picking.c
+++ b/src/Client/Picking.c
@@ -185,7 +185,7 @@ bool Picking_ClipBlock(PickedPos* pos) {
}
Vector3 scaledDir, intersect;
- Vector3_Multiply1(&scaledDir, &tracer.Dir, t0); /* scaledDir = dir * t0 */
+ Vector3_Mul1(&scaledDir, &tracer.Dir, t0); /* scaledDir = dir * t0 */
Vector3_Add(&intersect, &tracer.Origin, &scaledDir); /* intersect = origin + scaledDir */
/* Only pick the block if the block is precisely within reach distance. */
Real32 lenSq = Vector3_LengthSquared(&scaledDir);
@@ -210,7 +210,7 @@ bool Picking_ClipCamera(PickedPos* pos) {
}
Vector3 intersect;
- Vector3_Multiply1(&intersect, &tracer.Dir, t0); /* intersect = dir * t0 */
+ Vector3_Mul1(&intersect, &tracer.Dir, t0); /* intersect = dir * t0 */
Vector3_Add(&intersect, &tracer.Origin, &intersect); /* intersect = origin + dir * t0 */
PickedPos_SetAsValid(pos, &tracer, intersect);
@@ -236,7 +236,7 @@ void Picking_ClipCameraPos(Vector3 origin, Vector3 dir, Real32 reach, PickedPos*
bool noClip = !Game_CameraClipping || LocalPlayer_Instance.Hacks.Noclip;
if (noClip || !Picking_RayTrace(origin, dir, reach, pos, Picking_ClipCamera)) {
PickedPos_SetAsInvalid(pos);
- Vector3_Multiply1(&pos->Intersect, &tracer.Dir, reach); /* intersect = dir * reach */
+ Vector3_Mul1(&pos->Intersect, &tracer.Dir, reach); /* intersect = dir * reach */
Vector3_Add(&pos->Intersect, &tracer.Origin, &pos->Intersect); /* intersect = origin + dir * reach */
}
}
\ No newline at end of file
diff --git a/src/Client/Vectors.c b/src/Client/Vectors.c
index 959f62896..d4cf009e5 100644
--- a/src/Client/Vectors.c
+++ b/src/Client/Vectors.c
@@ -18,11 +18,6 @@ Vector3I Vector3I_Create3(Int32 x, Int32 y, Int32 z) {
Vector3I v; v.X = x; v.Y = y; v.Z = z; return v;
}
-Real32 Vector3_Length(Vector3* v) {
- Real32 lenSquared = v->X * v->X + v->Y * v->Y + v->Z * v->Z;
- return Math_Sqrt(lenSquared);
-}
-
Real32 Vector3_LengthSquared(Vector3* v) {
return v->X * v->X + v->Y * v->Y + v->Z * v->Z;
}
@@ -35,15 +30,15 @@ void Vector3_Add1(Vector3* result, Vector3* a, Real32 b) {
result->X = a->X + b; result->Y = a->Y + b; result->Z = a->Z + b;
}
-void Vector3_Subtract(Vector3* result, Vector3* a, Vector3* b) {
+void Vector3_Sub(Vector3* result, Vector3* a, Vector3* b) {
result->X = a->X - b->X; result->Y = a->Y - b->Y; result->Z = a->Z - b->Z;
}
-void Vector3_Multiply1(Vector3* result, Vector3* a, Real32 scale) {
+void Vector3_Mul1(Vector3* result, Vector3* a, Real32 scale) {
result->X = a->X * scale; result->Y = a->Y * scale; result->Z = a->Z * scale;
}
-void Vector3_Multiply3(Vector3* result, Vector3* a, Vector3* scale) {
+void Vector3_Mul3(Vector3* result, Vector3* a, Vector3* scale) {
result->X = a->X * scale->X; result->Y = a->Y * scale->Y; result->Z = a->Z * scale->Z;
}
@@ -70,7 +65,8 @@ void Vector3_Cross(Vector3* result, Vector3* a, Vector3* b) {
}
void Vector3_Normalize(Vector3* result, Vector3* a) {
- Real32 scale = 1.0f / Vector3_Length(a);
+ Real32 lenSquared = a->X * a->X + a->Y * a->Y + a->Z * a->Z;
+ Real32 scale = 1.0f / Math_SqrtF(lenSquared);
result->X = a->X * scale;
result->Y = a->Y * scale;
result->Z = a->Z * scale;
@@ -103,22 +99,22 @@ void Vector3_TransformZ(Vector3* result, Real32 z, Matrix* mat) {
}
Vector3 Vector3_RotateX(Vector3 v, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
return Vector3_Create3(v.X, cosA * v.Y + sinA * v.Z, -sinA * v.Y + cosA * v.Z);
}
Vector3 Vector3_RotateY(Vector3 v, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
return Vector3_Create3(cosA * v.X - sinA * v.Z, v.Y, sinA * v.X + cosA * v.Z);
}
Vector3 Vector3_RotateY3(Real32 x, Real32 y, Real32 z, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
return Vector3_Create3(cosA * x - sinA * z, y, sinA * x + cosA * z);
}
Vector3 Vector3_RotateZ(Vector3 v, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
return Vector3_Create3(cosA * v.X + sinA * v.Y, -sinA * v.X + cosA * v.Y, v.Z);
}
@@ -150,15 +146,15 @@ void Vector3I_Max(Vector3I* result, Vector3I* a, Vector3I* b) {
Vector3 Vector3_GetDirVector(Real32 yawRad, Real32 pitchRad) {
- Real32 x = -Math_Cos(pitchRad) * -Math_Sin(yawRad);
- Real32 y = -Math_Sin(pitchRad);
- Real32 z = -Math_Cos(pitchRad) * Math_Cos(yawRad);
+ Real32 x = -Math_CosF(pitchRad) * -Math_SinF(yawRad);
+ Real32 y = -Math_SinF(pitchRad);
+ Real32 z = -Math_CosF(pitchRad) * Math_CosF(yawRad);
return Vector3_Create3(x, y, z);
}
void Vector3_GetHeading(Vector3 dir, Real32* yaw, Real32* pitch) {
- *pitch = Math_Asin(-dir.Y);
- *yaw = Math_Atan2(dir.X, -dir.Z);
+ *pitch = (Real32)Math_Asin(-dir.Y);
+ *yaw = (Real32)Math_Atan2(dir.X, -dir.Z);
}
@@ -172,23 +168,23 @@ Matrix Matrix_Identity = {
/* Transposed, source https://open.gl/transformations */
void Matrix_RotateX(Matrix* result, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
*result = Matrix_Identity;
- result->Row1.Y = cosA; result->Row1.Z = sinA;
+ result->Row1.Y = cosA; result->Row1.Z = sinA;
result->Row2.Y = -sinA; result->Row2.Z = cosA;
}
void Matrix_RotateY(Matrix* result, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
*result = Matrix_Identity;
result->Row1.X = cosA; result->Row1.Z = -sinA;
result->Row2.X = sinA; result->Row2.Z = cosA;
}
void Matrix_RotateZ(Matrix* result, Real32 angle) {
- Real32 cosA = Math_Cos(angle), sinA = Math_Sin(angle);
+ Real32 cosA = Math_CosF(angle), sinA = Math_SinF(angle);
*result = Matrix_Identity;
- result->Row1.X = cosA; result->Row1.Y = sinA;
+ result->Row1.X = cosA; result->Row1.Y = sinA;
result->Row2.X = -sinA; result->Row2.Y = cosA;
}
@@ -254,7 +250,7 @@ void Matrix_OrthographicOffCenter(Matrix* result, Real32 left, Real32 right, Rea
}
void Matrix_PerspectiveFieldOfView(Matrix* result, Real32 fovy, Real32 aspect, Real32 zNear, Real32 zFar) {
- Real32 c = zNear * Math_Tan(0.5f * fovy);
+ Real32 c = zNear * Math_TanF(0.5 * fovy);
Matrix_PerspectiveOffCenter(result, -c * aspect, c * aspect, -c, c, zNear, zFar);
}
@@ -275,9 +271,9 @@ void Matrix_PerspectiveOffCenter(Matrix* result, Real32 left, Real32 right, Real
void Matrix_LookAt(Matrix* result, Vector3 eye, Vector3 target, Vector3 up) {
/* Transposed, source https://msdn.microsoft.com/en-us/library/windows/desktop/bb281711(v=vs.85).aspx */
Vector3 x, y, z;
- Vector3_Subtract(&z, &eye, &target); Vector3_Normalize(&z, &z);
- Vector3_Cross(&x, &up, &z); Vector3_Normalize(&x, &x);
- Vector3_Cross(&y, &z, &x); Vector3_Normalize(&y, &y);
+ Vector3_Sub(&z, &eye, &target); Vector3_Normalize(&z, &z);
+ Vector3_Cross(&x, &up, &z); Vector3_Normalize(&x, &x);
+ Vector3_Cross(&y, &z, &x); Vector3_Normalize(&y, &y);
result->Row0.X = x.X; result->Row0.Y = y.X; result->Row0.Z = z.X; result->Row0.W = 0.0f;
result->Row1.X = x.Y; result->Row1.Y = y.Y; result->Row1.Z = z.Y; result->Row1.W = 0.0f;
@@ -298,7 +294,7 @@ frustum40, frustum41, frustum42, frustum43;
void FrustumCulling_Normalise(Real32* plane0, Real32* plane1, Real32* plane2, Real32* plane3) {
Real32 val1 = *plane0, val2 = *plane1, val3 = *plane2;
- Real32 t = Math_Sqrt(val1 * val1 + val2 * val2 + val3 * val3);
+ Real32 t = Math_SqrtF(val1 * val1 + val2 * val2 + val3 * val3);
*plane0 /= t; *plane1 /= t; *plane2 /= t; *plane3 /= t;
}
diff --git a/src/Client/Vectors.h b/src/Client/Vectors.h
index 1bf12bc45..2f7275acc 100644
--- a/src/Client/Vectors.h
+++ b/src/Client/Vectors.h
@@ -17,10 +17,9 @@ Vector3 Vector3_Create1(Real32 value);
Vector3 Vector3_Create3(Real32 x, Real32 y, Real32 z);
Vector3I Vector3I_Create1(Int32 value);
Vector3I Vector3I_Create3(Int32 x, Int32 y, Int32 z);
-
-Real32 Vector3_Length(Vector3* v);
Real32 Vector3_LengthSquared(Vector3* v);
+#define VECTOR3_CONST1(val) { val, val, val };
#define VECTOR3_CONST(x, y, z) { x, y, z };
#define Vector3_UnitX VECTOR3_CONST(1.0f, 0.0f, 0.0f)
#define Vector3_UnitY VECTOR3_CONST(0.0f, 1.0f, 0.0f)
@@ -30,11 +29,16 @@ Real32 Vector3_LengthSquared(Vector3* v);
void Vector3_Add(Vector3* result, Vector3* a, Vector3* b);
void Vector3_Add1(Vector3* result, Vector3* a, Real32 b);
-void Vector3_Subtract(Vector3* result, Vector3* a, Vector3* b);
-void Vector3_Multiply1(Vector3* result, Vector3* a, Real32 scale);
-void Vector3_Multiply3(Vector3* result, Vector3* a, Vector3* scale);
+void Vector3_Sub(Vector3* result, Vector3* a, Vector3* b);
+void Vector3_Mul1(Vector3* result, Vector3* a, Real32 scale);
+void Vector3_Mul3(Vector3* result, Vector3* a, Vector3* scale);
void Vector3_Negate(Vector3* result, Vector3* a);
+#define Vector3_AddBy(dst, value) Vector3_Add(dst, dst, value)
+#define Vector3_SubBy(dst, value) Vector3_Sub(dst, dst, value)
+#define Vector3_Mul1By(dst, value) Vector3_Mul1(dst, dst, value)
+#define Vector3_Mul3By(dst, value) Vector3_Mul3(dst, dst, value)
+
void Vector3_Lerp(Vector3* result, Vector3* a, Vector3* b, Real32 blend);
Real32 Vector3_Dot(Vector3* left, Vector3* right);
void Vector3_Cross(Vector3* result, Vector3* a, Vector3* b);
diff --git a/src/Client/Widgets.c b/src/Client/Widgets.c
index d508a0ccd..0b0952067 100644
--- a/src/Client/Widgets.c
+++ b/src/Client/Widgets.c
@@ -735,8 +735,8 @@ void TableWidget_Recreate(GuiElement* elem) {
void TableWidget_Reposition(GuiElement* elem) {
TableWidget* widget = (TableWidget*)elem;
Real32 scale = Game_GetInventoryScale();
- widget->BlockSize = (Int32)(50 * Math_Sqrt(scale));
- widget->SelBlockExpand = 25.0f * Math_Sqrt(scale);
+ widget->BlockSize = (Int32)(50 * Math_SqrtF(scale));
+ widget->SelBlockExpand = 25.0f * Math_SqrtF(scale);
TableWidget_UpdatePos(widget);
TableWidget_UpdateScrollbarPos(widget);
}
diff --git a/src/Client/World.c b/src/Client/World.c
index 38c03724f..639caf677 100644
--- a/src/Client/World.c
+++ b/src/Client/World.c
@@ -208,13 +208,12 @@ void WorldEnv_SetShadowCol(PackedCol col) {
Event_RaiseInt32(&WorldEvents_EnvVarChanged, ENV_VAR_SHADOW_COL);
}
-#define Respawn_NotFound -10000.0f
Real32 Respawn_HighestFreeY(AABB* bb) {
Int32 minX = Math_Floor(bb->Min.X), maxX = Math_Floor(bb->Max.X);
Int32 minY = Math_Floor(bb->Min.Y), maxY = Math_Floor(bb->Max.Y);
Int32 minZ = Math_Floor(bb->Min.Z), maxZ = Math_Floor(bb->Max.Z);
- Real32 spawnY = Respawn_NotFound;
+ Real32 spawnY = RESPAWN_NOT_FOUND;
AABB blockBB;
Int32 x, y, z;
Vector3 pos;
@@ -248,7 +247,7 @@ Vector3 Respawn_FindSpawnPosition(Real32 x, Real32 z, Vector3 modelSize) {
Int32 y;
for (y = World_Height; y >= 0; y--) {
Real32 highestY = Respawn_HighestFreeY(&bb);
- if (highestY != Respawn_NotFound) {
+ if (highestY != RESPAWN_NOT_FOUND) {
spawn.Y = highestY; break;
}
bb.Min.Y -= 1.0f; bb.Max.Y -= 1.0f;
diff --git a/src/Client/World.h b/src/Client/World.h
index a8d63b81f..a6cf69de2 100644
--- a/src/Client/World.h
+++ b/src/Client/World.h
@@ -87,9 +87,10 @@ void WorldEnv_SetCloudsCol(PackedCol col);
void WorldEnv_SetSunCol(PackedCol col);
void WorldEnv_SetShadowCol(PackedCol col);
-/* Finds the highest free Y coordinate in the given bounding box.*/
+#define RESPAWN_NOT_FOUND -100000.0f
+/* Finds the highest free Y coordinate in the given bounding box */
Real32 Respawn_HighestFreeY(AABB* bb);
/* Finds a suitable spawn position for the entity, by iterating
-downwards from top of the world until the ground is found. */
+downwards from top of the world until the ground is found */
Vector3 Respawn_FindSpawnPosition(Real32 x, Real32 z, Vector3 modelSize);
#endif
\ No newline at end of file