public static void FinishPickingColor(Vector3 color) // Called from ColorPicker client, tells server what color the player chose { var cl = ConsoleSystem.Caller; cl.Camera = null; // Remove client's priority camera so Pawn camera can be used cl.SetScore("mtk_customcolor", color); var player = new TankPlayer(); cl.Pawn = player; player.Respawn(); }
public override void OnPlayerControlTick(TankPlayer player, bool allowDebug) { Position = player.Base.Position; if (Input.Down(InputButton.Jump)) { return; } if (frameCount < 5) // Wait for server to tell client which way we're actually facing { frameCount++; return; } var desiredHeadRot = Rotation.FromYaw(Input.Rotation.Yaw()); Rotation = Rotation.Lerp(Rotation, desiredHeadRot, Time.Delta * HeadSpinSpeed); }
public void FireRocket(TankPlayer player, Vector3 cannonEnd) { timeSinceCannonFire = 0; if (!Host.IsServer) { return; } var rocket = new Rocket { Position = cannonEnd, Rotation = Rotation, Shooter = player, RenderColor = player.GetClientOwner().GetScore("mtk_customcolor", Vector3.Zero).ToColor().ToColor32() }; rocket.SetupPhysicsFromModel(PhysicsMotionType.Keyframed); using (Prediction.Off()) { Particles.Create("particles/tank_shoot.vpcf", cannonEnd).SetForward(0, Rotation.Forward); Sound.FromWorld("shoot", cannonEnd); } }
public override void OnPlayerControlTick(TankPlayer player, bool allowDebug) { var extents = CollisionBounds.Maxs; var cannonEndLocal = extents.WithY(0) + Vector3.Down * 4; var cannonStart = player.Base.Position + cannonEndLocal.WithX(0); var cannonEnd = player.Base.Position + player.Head.Rotation * cannonEndLocal; var cannonTr = Trace.Ray(cannonStart, cannonEnd).Radius(4).WithoutTags("rocket").Run(); if (allowDebug) { DebugOverlay.Sphere(cannonTr.EndPos, 4, cannonTr.Hit ? Color.Red : Color.Green, true); DebugOverlay.Line(cannonStart, cannonEnd, Color.Blue, 0, false); } float retractTime = CannonCooldown * 0.1f, expandTime = CannonCooldown * 0.6f, cannonRecoilDistance = 16; float cannonRecoilOffset = 0; if (timeSinceCannonFire < retractTime) // Retracting { cannonRecoilOffset = cannonRecoilDistance * (timeSinceCannonFire / retractTime); } else if (timeSinceCannonFire < expandTime + retractTime) // Expanding { cannonRecoilOffset = cannonRecoilDistance - cannonRecoilDistance * ((timeSinceCannonFire - retractTime) / expandTime); } cannonRecoilOffset *= MathF.Pow(cannonTr.Distance / extents.x, 2); // Reduces recoil the more the cannon is pushed in due to collision float cannonOffset = (cannonRecoilOffset - cannonTr.Distance).Clamp(float.MinValue, -28.5f); LocalPosition = Vector3.Backward * (extents.x + cannonOffset); if (Input.Down(InputButton.Attack1) && timeSinceCannonFire > CannonCooldown) { cannonEnd = Position + player.Head.Rotation * cannonEndLocal; // Recalc cannon end after recoil and retracting was applied FireRocket(player, cannonEnd); } }
public override void OnPlayerControlTick(TankPlayer player, bool allowDebug) { float throttle = Input.Forward; float steering = Input.Left * (throttle >= 0 ? 1 : -1) * TurnSpeed; var moveDelta = Rotation.Forward * throttle * MoveSpeed; // Corner world position var frontLeft = moveDelta + Position + Rotation * (extents * new Vector3(1, 1, 0.5f)); var frontRight = moveDelta + Position + Rotation * (extents * new Vector3(1, -1, 0.5f)); var backLeft = moveDelta + Position + Rotation * (extents * new Vector3(-1, 1, 0.5f)); var backRight = moveDelta + Position + Rotation * extents * new Vector3(-1, -1, 0.5f); var center = moveDelta + Position + extents * new Vector3(0, 0, 0.5f); // Base world directions var frontDir = Rotation.Forward; var leftDir = Rotation.Left; var backDir = Rotation.Backward; var rightDir = Rotation.Right; var frontLeftDir = (frontDir + leftDir).Normal; var frontRightDir = (frontDir + rightDir).Normal; var backLeftDir = (backDir + leftDir).Normal; var backRightDir = (backDir + rightDir).Normal; float testDistance = 2 * MoveSpeed; if (allowDebug) { /*DebugOverlay.Axis(frontLeft, Rotation); * DebugOverlay.Axis(frontRight, Rotation); * DebugOverlay.Axis(backLeft, Rotation); * DebugOverlay.Axis(backRight, Rotation);*/ DebugOverlay.Sphere(frontLeft, testDistance, Color.Red); DebugOverlay.Sphere(frontRight, testDistance, Color.Red); DebugOverlay.Sphere(backLeft, testDistance, Color.Red); DebugOverlay.Sphere(backRight, testDistance, Color.Red); } var cornerResults = new TraceResult[12]; cornerResults[0] = Trace.Ray(frontLeft, frontLeft + frontDir * testDistance).Run(); // Forward cornerResults[1] = Trace.Ray(frontLeft, frontLeft + leftDir * testDistance).Run(); // Side cornerResults[2] = Trace.Ray(frontLeft, frontLeft + frontRightDir * testDistance).Run(); // Diagonal inward cornerResults[3] = Trace.Ray(frontRight, frontRight + frontDir * testDistance).Run(); cornerResults[4] = Trace.Ray(frontRight, frontRight + rightDir * testDistance).Run(); cornerResults[5] = Trace.Ray(frontRight, frontRight + frontLeftDir * testDistance).Run(); cornerResults[6] = Trace.Ray(backLeft, backLeft + backDir * testDistance).Run(); cornerResults[7] = Trace.Ray(backLeft, backLeft + leftDir * testDistance).Run(); cornerResults[8] = Trace.Ray(backLeft, backLeft + backRightDir * testDistance).Run(); cornerResults[9] = Trace.Ray(backRight, backRight + backDir * testDistance).Run(); cornerResults[10] = Trace.Ray(backRight, backRight + rightDir * testDistance).Run(); cornerResults[11] = Trace.Ray(backRight, backRight + backLeftDir * testDistance).Run(); // Turn off movement and don't collide if both front or back corners are colliding (but only if pushing against an axis-aligned wall) bool noMove = (cornerResults[0].Hit && cornerResults[3].Hit) || (cornerResults[6].Hit && cornerResults[9].Hit); float yaw = Rotation.Yaw(); noMove &= yaw.SnapToGrid(90).AlmostEqual(yaw, 2); if (noMove) { moveDelta = 0; } for (int i = 0; i < cornerResults.Length; i++) { var result = cornerResults[i]; if (!result.Hit) { if (allowDebug) { DebugOverlay.Line(result.StartPos, result.StartPos + result.Direction * testDistance * 8, Color.Green, 0, false); } continue; } if (i % 3 != 0 && cornerResults[i - (i % 3)].Hit) // Skip the side and diagonal tests if the primary one already hit { if (allowDebug) { DebugOverlay.Line(result.StartPos, result.StartPos + result.Direction * testDistance * 8, Color.Yellow, 0, false); } continue; } if (i % 3 == 0 && noMove) { continue; } if (allowDebug) { DebugOverlay.Line(result.StartPos, result.StartPos + result.Direction * testDistance * 8, Color.Red, 0, false); } Position += result.Normal * (testDistance - result.Distance); float torque = Vector3.Cross(result.StartPos - center, result.Normal).z *Time.Delta; Rotation *= Rotation.FromYaw(torque); if (allowDebug) { DebugOverlay.Line(result.EndPos, result.EndPos + result.Normal * MathF.Abs(torque) * 50, Color.Blue, 0, false); } } var edgeResults = new TraceResult[8]; edgeResults[0] = Trace.Ray(frontLeft, frontRight).Run(); edgeResults[2] = Trace.Ray(backLeft, backRight).Run(); edgeResults[4] = Trace.Ray(frontLeft, backLeft).Run(); edgeResults[6] = Trace.Ray(frontRight, backRight).Run(); for (int i = 0; i < edgeResults.Length; i += 2) { var result = edgeResults[i]; if (result.Hit) // Only run the partner trace if the first one on that edge hits { if (i == 0) { edgeResults[i + 1] = Trace.Ray(frontRight, frontLeft).Run(); } else if (i == 2) { edgeResults[i + 1] = Trace.Ray(backRight, backLeft).Run(); } else if (i == 4) { edgeResults[i + 1] = Trace.Ray(backLeft, frontLeft).Run(); } else if (i == 6) { edgeResults[i + 1] = Trace.Ray(backRight, frontRight).Run(); } } else { continue; } if (allowDebug) { DebugOverlay.Line(result.StartPos, result.EndPos, 0, false); } Vector3 correctionDir = Vector3.Zero; if (i == 0) { correctionDir = frontDir; } else if (i == 2) { correctionDir = backDir; } else if (i == 4) { correctionDir = leftDir; } else if (i == 6) { correctionDir = rightDir; } float distance = Vector3.DistanceBetween(result.EndPos, edgeResults[i + 1].EndPos); float angle = Vector3.GetAngle(result.EndPos - result.StartPos, result.Normal) - 90; float correction = distance * 0.5f * MathF.Sin(2 * angle.DegreeToRadian()); // How much to push out of the corner, finds the altitude of a right triangle Position -= correctionDir * correction; var avgPos = (result.EndPos + edgeResults[i + 1].EndPos) * 0.5f; float torque = Vector3.Cross(avgPos - center, -correctionDir).z *Time.Delta; Rotation *= Rotation.FromYaw(torque); if (allowDebug) { DebugOverlay.Line(avgPos, avgPos - correctionDir * MathF.Abs(torque) * 50, Color.Cyan, 0, false); DebugOverlay.Line(result.EndPos, edgeResults[i + 1].EndPos, Color.Red, 0, false); DebugOverlay.Line(result.EndPos, result.EndPos + correctionDir * correction * 10, Color.Green, 0, false); DebugOverlay.Line(edgeResults[i + 1].EndPos, edgeResults[i + 1].EndPos + correctionDir * correction * 10, Color.Green, 0, false); } } moveDelta = moveDelta.WithZ(0); Position += moveDelta; Rotation *= Rotation.FromYaw(steering); }
public abstract void OnPlayerControlTick(TankPlayer player, bool allowDebug);