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