public static void Update(bool updateVel = false) { if (Engine.Scene is Level level) { Player player = level.Tracker.GetEntity <Player>(); if (player != null) { string pos = GetAdjustedPos(player, out string exactPos); string speed = GetAdjustedSpeed(player.Speed, out string exactSpeed); Vector2Double diff = player.GetMoreExactPosition(false) - LastPos; if (!Frozen && updateVel) { LastDiff = diff; } else { diff = LastDiff; } if (TasSettings.SpeedUnit == SpeedUnit.PixelPerSecond) { diff *= FramesPerRealSecond; } string velocity = GetAdjustedVelocity(diff, out string exactVelocity); string polarVel = $"Fly: {diff.Length():F2}, {diff.Angle():F5}°"; string analog = string.Empty; if (Manager.Running && Manager.Controller.Previous is { } inputFrame&& inputFrame.HasActions(Actions.Feather)) { Vector2 angleVector2 = inputFrame.AngleVector2; analog = $"Analog: {angleVector2.X:F5}, {angleVector2.Y:F5}, {GetAngle(new Vector2(angleVector2.X, -angleVector2.Y)):F5}°"; } string retainedSpeed = GetAdjustedRetainedSpeed(player, out string exactRetainedSpeed); string liftBoost = GetAdjustedLiftBoost(player, out string exactLiftBoost); string miscStats = $"Stamina: {player.Stamina:0} " + (WallJumpCheck(player, 1) ? "Wall-R " : string.Empty) + (WallJumpCheck(player, -1) ? "Wall-L " : string.Empty) + PlayerStates.GetStateName(player.StateMachine.State); int dashCooldown = DashCooldownTimer(player).ToFloorFrames(); PlayerSeeker playerSeeker = level.Tracker.GetEntity <PlayerSeeker>(); if (playerSeeker != null) { pos = GetAdjustedPos(playerSeeker, out exactPos); speed = GetAdjustedSpeed(PlayerSeekerSpeed(playerSeeker), out exactSpeed); diff = playerSeeker.GetMoreExactPosition(false) - LastPlayerSeekerPos; if (!Frozen && updateVel) { LastPlayerSeekerDiff = diff; } else { diff = LastPlayerSeekerDiff; } if (TasSettings.SpeedUnit == SpeedUnit.PixelPerSecond) { diff *= FramesPerRealSecond; } velocity = GetAdjustedVelocity(diff, out exactVelocity); polarVel = $"Chase: {diff.Length():F2}, {diff.Angle():F5}°"; dashCooldown = PlayerSeekerDashTimer(playerSeeker).ToCeilingFrames(); } string statuses = GetStatuses(level, player, dashCooldown); string timers = string.Empty; Follower firstRedBerryFollower = player.Leader.Followers.Find(follower => follower.Entity is Strawberry { Golden: false });
public static void UpdatePlayerInfo() { if (Engine.Scene is Level level) { Player player = level.Tracker.GetEntity <Player>(); if (player != null) { long chapterTime = level.Session.Time; if (chapterTime != lastTimer || LastPos != player.ExactPosition) { framesPerSecond = 60f / Engine.TimeRateB; string pos = GetAdjustedPos(player.Position, player.PositionRemainder); string speed = $"Speed: {player.Speed.X:F2}, {player.Speed.Y:F2}"; Vector2 diff = (player.ExactPosition - LastPos) * 60f; string vel = $"Vel: {diff.X:F2}, {diff.Y:F2}"; string polarvel = $"Fly: {diff.Length():F2}, {GetAngle(diff):F5}°"; string joystick; if (Running && Controller.Previous is InputFrame inputFrame && inputFrame.HasActions(Actions.Feather)) { joystick = $"Analog: {AnalogHelper.LastDirection.X:F5}, {AnalogHelper.LastDirection.Y:F5}, {GetAngle(new Vector2(AnalogHelper.LastDirection.X, -AnalogHelper.LastDirection.Y)):F5}°"; } else { joystick = string.Empty; } string miscstats = $"Stamina: {player.Stamina:0} " + (WallJumpCheck(player, 1) ? "Wall-R " : string.Empty) + (WallJumpCheck(player, -1) ? "Wall-L " : string.Empty); int dashCooldown = (int)(DashCooldownTimer(player) * framesPerSecond); PlayerSeeker playerSeeker = level.Entities.FindFirst <PlayerSeeker>(); if (playerSeeker != null) { pos = GetAdjustedPos(playerSeeker.Position, playerSeeker.PositionRemainder); speed = $"Speed: {PlayerSeekerSpeed(playerSeeker).X:F2}, {PlayerSeekerSpeed(playerSeeker).Y:F2}"; diff = (playerSeeker.ExactPosition - LastPlayerSeekerPos) * 60f; vel = $"Vel: {diff.X:F2}, {diff.Y:F2}"; polarvel = $"Chase: {diff.Length():F2}, {GetAngle(diff):F2}°"; dashCooldown = (int)(PlayerSeekerDashTimer(playerSeeker) * framesPerSecond); } string statuses = (dashCooldown < 1 && player.Dashes > 0 ? "Dash " : string.Empty) + (player.LoseShards ? "Ground " : string.Empty) + (!player.LoseShards && JumpGraceTimer(player) > 0 ? $"Coyote({(int) (JumpGraceTimer(player) * framesPerSecond)})" : string.Empty); string transitionFrames = PlayerInfo.TransitionFrames > 0 ? $"({PlayerInfo.TransitionFrames})" : string.Empty; statuses = (player.InControl && !level.Transitioning ? statuses : $"NoControl{transitionFrames} ") + (player.TimePaused ? "Paused " : string.Empty) + (level.InCutscene ? "Cutscene " : string.Empty) + (AdditionalStatusInfo ?? string.Empty); if (player.Holding == null) { foreach (Component component in level.Tracker.GetComponents <Holdable>()) { Holdable holdable = (Holdable)component; if (holdable.Check(player)) { statuses += "Grab "; break; } } } int berryTimer = -10; Follower firstRedBerryFollower = player.Leader.Followers.Find(follower => follower.Entity is Strawberry berry && !berry.Golden); if (firstRedBerryFollower?.Entity is Strawberry firstRedBerry) { object collectTimer; if (firstRedBerry.GetType() == typeof(Strawberry) || (collectTimer = StrawberryCollectTimer(firstRedBerry)) == null) { // if this is a vanilla berry or a mod berry having no collectTimer, use the cached FieldInfo for Strawberry.collectTimer. collectTimer = StrawberryCollectTimerFieldInfo.GetValue(firstRedBerry); } berryTimer = 9 - (int)Math.Round((float)collectTimer * framesPerSecond); } string timers = (berryTimer != -10 ? berryTimer <= 9 ? $"BerryTimer: {berryTimer} " : $"BerryTimer: 9+{berryTimer - 9} " : string.Empty) + (dashCooldown != 0 ? $"DashTimer: {(dashCooldown).ToString()} " : string.Empty); string roomNameAndTime = $"[{level.Session.Level}] Timer: {(chapterTime / 10000000D):F3}({chapterTime / TimeSpan.FromSeconds(Engine.RawDeltaTime).Ticks})"; StringBuilder sb = new StringBuilder(); sb.AppendLine(pos); sb.AppendLine(speed); sb.AppendLine(vel); if (player.StateMachine.State == Player.StStarFly || playerSeeker != null || SaveData.Instance.Assists.ThreeSixtyDashing || SaveData.Instance.Assists.SuperDashing) { sb.AppendLine(polarvel); } if (!string.IsNullOrEmpty(joystick)) { sb.AppendLine(joystick); } sb.AppendLine(miscstats); if (!string.IsNullOrEmpty(statuses)) { sb.AppendLine(statuses); } if (!string.IsNullOrEmpty(timers)) { sb.AppendLine(timers); } sb.Append(roomNameAndTime); LastPos = player.ExactPosition; LastPlayerSeekerPos = playerSeeker?.ExactPosition ?? default; lastTimer = chapterTime; PlayerStatus = sb.ToString().TrimEnd(); } } else { PlayerStatus = level.InCutscene ? "Cutscene" : string.Empty; } }
public static void Update(bool updateVel = false) { if (Engine.Scene is Level level) { Player player = level.Tracker.GetEntity <Player>(); long chapterTime = level.Session.Time; if (player != null) { StringBuilder stringBuilder = new(); string pos = GetAdjustedPos(player.Position, player.PositionRemainder); string speed = GetAdjustedSpeed(player.Speed); Vector2Double diff = (player.GetMoreExactPosition() - LastPos) * FramesPerSecond; string velocity = GetAdjustedVelocity(diff); if (!Frozen && updateVel) { LastVel = velocity; } else { velocity = LastVel; } string polarVel = $"Fly: {diff.Length():F2}, {diff.Angle():F5}°"; string analog = string.Empty; if (Manager.Running && Manager.Controller.Previous is { } inputFrame&& inputFrame.HasActions(Actions.Feather)) { Vector2 angleVector2 = inputFrame.AngleVector2; analog = $"Analog: {angleVector2.X:F5}, {angleVector2.Y:F5}, {Manager.GetAngle(new Vector2(angleVector2.X, -angleVector2.Y)):F5}°"; } string retainedSpeed = string.Empty; if (PlayerRetainedSpeedTimer(player) is float retainedSpeedTimer and > 0f) { retainedSpeed = $"Retained: {PlayerRetainedSpeed(player):F2} ({retainedSpeedTimer.ToCeilingFrames()})"; } string liftBoost = string.Empty; if (PlayerLiftBoost(player) is var liftBoostVector2 && liftBoostVector2 != Vector2.Zero) { liftBoost = $"LiftBoost: {liftBoostVector2.X:F2}, {liftBoostVector2.Y:F2} ({ActorLiftSpeedTimer(player).ToCeilingFrames()})"; } string miscStats = $"Stamina: {player.Stamina:0} " + (WallJumpCheck(player, 1) ? "Wall-R " : string.Empty) + (WallJumpCheck(player, -1) ? "Wall-L " : string.Empty) + PlayerStates.GetStateName(player.StateMachine.State); int dashCooldown = DashCooldownTimer(player).ToFloorFrames(); PlayerSeeker playerSeeker = level.Tracker.GetEntity <PlayerSeeker>(); if (playerSeeker != null) { pos = GetAdjustedPos(playerSeeker.Position, playerSeeker.PositionRemainder); speed = GetAdjustedSpeed(PlayerSeekerSpeed(playerSeeker)); diff = (playerSeeker.GetMoreExactPosition() - LastPlayerSeekerPos) * FramesPerSecond; velocity = GetAdjustedVelocity(diff); if (!Frozen && updateVel) { LastPlayerSeekerVel = velocity; } else { velocity = LastPlayerSeekerVel; } polarVel = $"Chase: {diff.Length():F2}, {diff.Angle():F5}°"; dashCooldown = PlayerSeekerDashTimer(playerSeeker).ToCeilingFrames(); } string statuses = (dashCooldown <= 0 && player.Dashes > 0 ? "CanDash " : string.Empty) + (player.LoseShards ? "Ground " : string.Empty) + (!player.LoseShards && JumpGraceTimer(player).ToFloorFrames() is int coyote and > 0 ? $"Coyote({coyote}) " : string.Empty); string noControlFrames = transitionFrames > 0 ? $"({transitionFrames})" : string.Empty; float unpauseTimer = LevelUnpauseTimer?.Invoke(level) ?? 0f; if (unpauseTimer > 0f) { noControlFrames = $"({unpauseTimer.ToCeilingFrames()})"; } statuses = (Engine.FreezeTimer > 0f ? $"Frozen({Engine.FreezeTimer.ToCeilingFrames()}) " : string.Empty) + (player.InControl && !level.Transitioning && unpauseTimer <= 0f ? statuses : $"NoControl{noControlFrames} ") + (player.Dead ? "Dead " : string.Empty) + (level.InCutscene ? "Cutscene " : string.Empty) + (AdditionalStatusInfo ?? string.Empty); if (player.Holding == null && level.Tracker.GetComponents <Holdable>().Any(holdable => ((Holdable)holdable).Check(player))) { statuses += "Grab "; } string timers = string.Empty; Follower firstRedBerryFollower = player.Leader.Followers.Find(follower => follower.Entity is Strawberry { Golden: false });