private PlayerDeadBody Player_Die(On.Celeste.Player.orig_Die orig, Player self, Microsoft.Xna.Framework.Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { PlayerDeadBody result = orig(self, direction, evenIfInvincible, registerDeathInStats); if (result == null) { return(null); } if (Settings.RecordDeaths) { Vector2 newlocation = self.Position; newlocation.Y -= 16; deaths.Add(newlocation); } deathspopupdelays.Clear(); deaths.ForEach((_) => { deathspopupdelays.Add(GetRandom.NextFloat(0.25f)); }); if (Settings.RecordDeaths) { deathspopupdelays[deaths.Count - 1] = 0f; } deathTimer = 0f; return(result); }
private static PlayerDeadBody PlayerDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { Session session = (self.Scene as Level).Session; PlayerDeadBody playerDeadBody = orig(self, direction, evenIfInvincible, registerDeathInStats); if (playerDeadBody != null) { Strawberry goldenStrawb = null; foreach (Follower follower in self.Leader.Followers) { if (follower.Entity is Strawberry && (follower.Entity as Strawberry).Golden && !(follower.Entity as Strawberry).Winged) { goldenStrawb = (follower.Entity as Strawberry); } } Vector2?specialBoxLevel = (FactoryHelperModule.Instance._Session as FactoryHelperSession).SpecialBoxPosition; if (goldenStrawb == null && specialBoxLevel != null) { playerDeadBody.DeathAction = delegate { Engine.Scene = new LevelExit(LevelExit.Mode.Restart, session); }; } } return(playerDeadBody); }
new public PlayerDeadBody Die(Vector2 direction, bool evenIfInvincible = false, bool registerDeathInStats = true) { PlayerDeadBody orig = orig_Die(direction, evenIfInvincible, registerDeathInStats); Everest.Events.Player.Die(this); return(orig); }
public PlayerDeadBody OnDie(On.Celeste.Player.orig_Die orig, Player player, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { PlayerDeadBody corpse = orig(player, direction, evenIfInvincible, registerDeathInStats); if (GhostRecorder == null || GhostRecorder.Data == null) { return(corpse); } // This is hacky, but it works: // Check the stack trace for Celeste.Level+* <Pause>* // and throw away the data when we're just retrying. foreach (StackFrame frame in new StackTrace().GetFrames()) { MethodBase method = frame?.GetMethod(); if (method == null || method.DeclaringType == null) { continue; } if (!method.DeclaringType.FullName.StartsWith("Celeste.Level+") || !method.Name.StartsWith("<Pause>")) { continue; } GhostRecorder.Data = null; return(corpse); } GhostRecorder.Data.Dead = true; return(corpse); }
private void PlayerDeadBodyOnEnd(On.Celeste.PlayerDeadBody.orig_End orig, PlayerDeadBody self) { orig(self); if (Enabled) { Died = true; } }
private Celeste.PlayerDeadBody OnPlayerDie(On.Celeste.Player.orig_Die orig, Celeste.Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { PlayerDeadBody result = orig(self, direction, evenIfInvincible, registerDeathInStats); if (Settings.Enabled && result != null) { ApplyRules(self.Scene, "Die"); } return(result); }
private static PlayerDeadBody OnPlayerDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { PlayerDeadBody result = orig(self, direction, evenIfInvincible, registerDeathInStats); if (result != null && self.Scene is Level level && overworldWrapper != null) { // the player died, so we should close the "in-game overworld" before weird stuff happens. Close(level, true, true); } return(result); }
private PlayerDeadBody PlayerOnDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { PlayerDeadBody playerDeadBody = orig(self, direction, evenIfInvincible, registerDeathInStats); if (playerDeadBody != null && Enabled) { causeOfDeath = GetCauseOfDeath(); deathPosition = self.Position; } return(playerDeadBody); }
private PlayerDeadBody onPlayerDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { if (!Settings.AllStrawberriesAreGoldens) { return(orig(self, direction, evenIfInvincible, registerDeathInStats)); } // get the first following strawberry before it is detached by the orig method Strawberry firstStrawberry = null; foreach (Follower follower in self.Leader.Followers) { if (follower.Entity is Strawberry) { firstStrawberry = (follower.Entity as Strawberry); break; } } Level level = self.SceneAs <Level>(); // call the orig method PlayerDeadBody deadBody = orig(self, direction, evenIfInvincible, registerDeathInStats); if (deadBody != null && !deadBody.HasGolden && firstStrawberry != null) { // the player is dead, doesn't have the actual golden but has a strawberry. // we have to do magic to make the game believe they had the golden. // (actually, we just do what vanilla does, but with a regular berry instead.) deadBody.HasGolden = true; deadBody.DeathAction = () => { LevelExit exit = new LevelExit(LevelExit.Mode.GoldenBerryRestart, level.Session) { GoldenStrawberryEntryLevel = firstStrawberry.ID.Level }; // if the berry saved the player's inventory on collection, pass it over to the scene. DynData <Strawberry> firstStrawberryData = new DynData <Strawberry>(firstStrawberry); if (firstStrawberryData.Data.ContainsKey("playerInventoryOnCollection")) { new DynData <LevelExit>(exit)["playerInventoryToRestore"] = firstStrawberryData.Get <PlayerInventory>("playerInventoryOnCollection"); } Engine.Scene = exit; }; } // proceed return(deadBody); }
private void AutoLoadStateWhenDeath(On.Celeste.PlayerDeadBody.orig_End orig, PlayerDeadBody self) { if (SpeedrunToolModule.Settings.Enabled && SpeedrunToolModule.Settings.AutoLoadAfterDeath && IsSaved && !(bool)self.GetFieldValue("finished") && Engine.Scene is Level level ) { level.OnEndOfFrame += () => LoadState(); self.RemoveSelf(); } else { orig(self); } }
private void onLightingRender(On.Celeste.LightingRenderer.orig_BeforeRender orig, LightingRenderer self, Scene scene) { float origSpotlightAlpha = 0f; Player player = scene?.Tracker.GetEntity <Player>(); PlayerDeadBody deadPlayer = null; if (player == null) { deadPlayer = scene?.Entities?.OfType <PlayerDeadBody>().FirstOrDefault(); } if (Settings.DisableMadelineSpotlight) { // save the lighting alpha, then replace it. if (player != null) { origSpotlightAlpha = player.Light.Alpha; player.Light.Alpha = 0f; } else if (deadPlayer != null) { VertexLight light = new DynData <PlayerDeadBody>(deadPlayer).Get <VertexLight>("light"); origSpotlightAlpha = light.Alpha; light.Alpha = 0f; } } orig(self, scene); if (Settings.DisableMadelineSpotlight) { // restore the spotlight if (player != null) { player.Light.Alpha = origSpotlightAlpha; } else if (deadPlayer != null) { VertexLight light = new DynData <PlayerDeadBody>(deadPlayer).Get <VertexLight>("light"); light.Alpha = origSpotlightAlpha; } } }
new public PlayerDeadBody Die(Vector2 direction, bool evenIfInvincible = false, bool registerDeathInStats = true) { Level level = Scene as Level; // 2 catches spawn-blade-kill GBJs. // 4 catches spawn-OOB-kill GBJs. if (framesAlive < 6 && level != null) { diedInGBJ++; if (diedInGBJ != 0 && (diedInGBJ % 2) == 0 && level.Session.Area.GetLevelSet() != "Celeste" && !CoreModule.Settings.DisableAntiSoftlock) { level.Pause(); return(null); } } PlayerDeadBody orig = orig_Die(direction, evenIfInvincible, registerDeathInStats); Everest.Events.Player.Die(this); return(orig); }
// Everest 的 Bug,另外的 Mod Hook 了 PlayerDeadBody.End 方法后 Level.DoScreenWipe Hook 的方法 wipeIn 为 false 时就不触发了 // 所以改成了 Hook AreaData.DoScreenWipe 方法 private void QuickLoadWhenDeath(On.Celeste.AreaData.orig_DoScreenWipe orig, AreaData self, Scene scene, bool wipeIn, Action onComplete) { if (SpeedrunToolModule.Settings.Enabled && SpeedrunToolModule.Settings.AutoLoadAfterDeath && IsSaved && !wipeIn && scene is Level level && onComplete != null && (onComplete == level.Reload || currentPlayerDeadBody?.HasGolden == true)) { Action complete = onComplete; currentPlayerDeadBody = null; onComplete = () => { if (IsSaved) { LoadState(); } else { complete(); } }; } orig(self, scene, wipeIn, onComplete); }
private static PlayerDeadBody Player_OnDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible = false, bool registerDeathsInStats = true) { IEnumerable <Player> players = self.Scene.Tracker.GetEntities <Player>().Cast <Player>(); int playerCount = players.Count(); int deadPlayers = players.Where(p => p.Dead).Count(); PlayerDeadBody body = self.Scene.Entities.FindFirst <PlayerDeadBody>(); // Kill all other players with "fake deaths" if we are the first player to die if (deadPlayers == 0) { if (!SaveData.Instance.Assists.Invincible || evenIfInvincible) { foreach (Player player in players) { if (player != self) { foreach (Follower follower in player.Leader.Followers) { self.Leader.Followers.Add(follower); } if (!player.Dead) { player.Scene.Add(new CustomPlayerDeadBody(player, Vector2.Zero, false, true)); } player.Scene.Remove(player); } } return(orig(self, direction, evenIfInvincible, registerDeathsInStats)); } } return(null); }
private static PlayerDeadBody onPlayerDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { bool hasSilver = false; SpeedBerry speedBerry = null; // check if the player is actually going to die first. if (!self.Dead && (evenIfInvincible || !SaveData.Instance.Assists.Invincible) && self.StateMachine.State != Player.StReflectionFall) { hasSilver = self.Leader.Followers.Any(follower => follower.Entity is SilverBerry); Follower speedBerryFollower = self.Leader.Followers.Find(follower => follower.Entity is SpeedBerry); if (speedBerryFollower != null) { speedBerry = (SpeedBerry)speedBerryFollower.Entity; // Don't restart the player to the starting room if there's still time left on the speed berry if (!speedBerry.TimeRanOut) { DynData <Strawberry> data = new DynData <Strawberry>(speedBerry); data["Golden"] = false; // set the starting position to the spawn point Level level = self.SceneAs <Level>(); data["start"] = level.GetSpawnPoint(new Vector2(level.Bounds.Left, level.Bounds.Top)) + new Vector2(8, -16); } } } PlayerDeadBody body = orig(self, direction, evenIfInvincible, registerDeathInStats); if (body != null) { DynData <PlayerDeadBody> data = new DynData <PlayerDeadBody>(body); data["hasSilver"] = hasSilver; data["hasSpeedBerry"] = (speedBerry != null); storedSpeedBerry = speedBerry; } return(body); }
private PlayerDeadBody PlayerOnDie(On.Celeste.Player.orig_Die orig, Player self, Vector2 direction, bool evenIfInvincible, bool registerDeathInStats) { currentPlayerDeadBody = orig(self, direction, evenIfInvincible, registerDeathInStats); return(currentPlayerDeadBody); }
public override void Update() { base.Update(); if (fadeOut) { tiles.Alpha = Calc.Approach(tiles.Alpha, 0f, 3f * Engine.DeltaTime); cutout.Alpha = tiles.Alpha; if (tiles.Alpha <= 0f) { tiles.Alpha = 0; } } else if (fadeIn) { tiles.Alpha = Calc.Approach(tiles.Alpha, 1f, 3f * Engine.DeltaTime); cutout.Alpha = tiles.Alpha; if (tiles.Alpha >= 1f) { tiles.Alpha = 1; } } if (MasterOfGroup) { Player player = null; foreach (CaveWall entity in Group) { player = entity.CollideFirst <Player>(); if (player != null) { break; } } // The wall shouldn't fade out when a player dies in it PlayerDeadBody playerDeadBody = null; bool bodyCollided = false; if ((playerDeadBody = SceneAs <Level>().Entities.FindFirst <PlayerDeadBody>()) != null) { foreach (CaveWall entity in Group) { bodyCollided = playerDeadBody.Position.X >= entity.Left && playerDeadBody.Position.X <= entity.Right && playerDeadBody.Position.Y >= entity.Top && playerDeadBody.Position.Y <= entity.Bottom; if (bodyCollided) { break; } } } if ((player != null && player.StateMachine.State != 9) || bodyCollided) { fadeOut = true; foreach (CaveWall entity in Group) { entity.fadeOut = true; } } else if (fadeOut) { fadeOut = false; fadeIn = true; foreach (CaveWall entity in Group) { entity.fadeOut = false; entity.fadeIn = true; } } } }
private void PlayerDeadBody_Render(On.Celeste.PlayerDeadBody.orig_Render orig, PlayerDeadBody self) { if (Settings.DisplayDeaths) { Level level = self.Scene as Level; int i = 0; deaths.ForEach((location) => { if (level.IsInBounds(location) && deathTimer >= deathspopupdelays[i]) { float alpha = deathTimer - deathspopupdelays[i]; if (i == deaths.Count - 1) { alpha *= 2; } if (alpha > 1f) { alpha = 1f; } deathsprite.DrawCentered(location, Color.White, alpha); } i++; }); } orig(self); }
private void PlayerDeadBody_Update(On.Celeste.PlayerDeadBody.orig_Update orig, PlayerDeadBody self) { deathTimer += Engine.DeltaTime; orig(self); }
private void PlayerDeadBodyRenderHook(On.Celeste.PlayerDeadBody.orig_Render orig, PlayerDeadBody self) { DynData <PlayerDeadBody> deadBody = new DynData <PlayerDeadBody>(self); int dashCount = deadBody.Get <Player>("player").Dashes; if (UniqueSkinSelected()) { string colorGradePath = skinConfigs[Settings.SelectedSkinMod].GetUniquePath() + "dash"; while (dashCount > 2 && !GFX.ColorGrades.Has(colorGradePath + dashCount)) { dashCount--; } if (GFX.ColorGrades.Has(colorGradePath + dashCount)) { Effect fxColorGrading = GFX.FxColorGrading; fxColorGrading.CurrentTechnique = fxColorGrading.Techniques["ColorGradeSingle"]; Engine.Graphics.GraphicsDevice.Textures[1] = GFX.ColorGrades[colorGradePath + dashCount].Texture.Texture_Safe; Draw.SpriteBatch.End(); Draw.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.None, RasterizerState.CullNone, fxColorGrading, (self.Scene as Level).GameplayRenderer.Camera.Matrix); orig(self); Draw.SpriteBatch.End(); Draw.SpriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointWrap, DepthStencilState.None, RasterizerState.CullNone, null, (self.Scene as Level).GameplayRenderer.Camera.Matrix); return; } } orig(self); }