/// <summary> /// Mods the lighting of a new room being loaded. /// </summary> /// <param name="self">The level we are in</param> /// <param name="introType">How the player enters the level</param> private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (Settings.RoomLighting != -1) { float lightingTarget = 1 - Settings.RoomLighting / 10f; if (playerIntro == Player.IntroTypes.Transition) { // we force the game into thinking this is not a dark room, so that it uses the BaseLightingAlpha + LightingAlphaAdd formula // (this change is not permanent, exiting and re-entering will reset this flag) self.DarkRoom = false; // we mod BaseLightingAlpha temporarily so that it adds up with LightingAlphaAdd to the right value: the transition routine will smoothly switch to it // (we are sure BaseLightingAlpha will not move for the entire session: it's only set when the map is loaded) initialBaseLightingAlpha = self.BaseLightingAlpha; self.BaseLightingAlpha = lightingTarget - self.Session.LightingAlphaAdd; } else { // just set the initial value self.Lighting.Alpha = lightingTarget; } } }
private void OnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { BGModeToggle.BGMode = BGModeToggle.Persist; BGModeToggle.OldBGMode = !BGModeToggle.Persist; orig(self, playerIntro, isFromLoader); if (self != null) { if (self.Tracker != null) { if (self.Tracker.GetEntity <Player>() != null) { if (self.Entities.Any(entity => (entity is BGModeToggle)) || BGModeToggle.BGMode) { self.Tracker.GetEntity <Player>().Sprite.Position = new Vector2(); if (!BGModeToggle.Persist) { self.Tracker.GetEntity <Player>().Sprite.Position += new Vector2(0, +2); } BGModeToggle.Setup(self); BGModeToggle.UpdateBG(self); } } } } }
[PatchLevelLoader] // Manually manipulate the method via MonoModRules public new void LoadLevel(Player.IntroTypes playerIntro, bool isFromLoader = false) { // Read player introType from metadata as player enter the C-Side if (Session.FirstLevel && Session.StartedFromBeginning && Session.JustStarted && Session.Area.Mode == AreaMode.CSide && AreaData.GetMode(Session.Area)?.GetMapMeta() is MapMeta mapMeta && (mapMeta.OverrideASideMeta ?? false) && mapMeta.IntroType is Player.IntroTypes introType) { playerIntro = introType; } try { orig_LoadLevel(playerIntro, isFromLoader); } catch (Exception e) { Mod.Logger.Log(LogLevel.Warn, "misc", $"Failed loading level {Session.Area}"); e.LogDetailed(); string message = Dialog.Get("postcard_levelloadfailed"); if (e is ArgumentOutOfRangeException && e.StackTrace.Contains("get_DefaultSpawnPoint")) { message = Dialog.Get("postcard_levelnospawn"); } message = message .Replace("((player))", SaveData.Instance.Name) .Replace("((sid))", Session.Area.GetSID()); Entity helperEntity = new Entity(); helperEntity.Add(new Coroutine(ErrorRoutine(message))); Add(helperEntity); return; } Everest.Events.Level.LoadLevel(this, playerIntro, isFromLoader); }
public void OnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level level, Player.IntroTypes playerIntro, bool isFromLoader) { orig(level, playerIntro, isFromLoader); if (isFromLoader) { GhostManager?.RemoveSelf(); GhostManager = null; GhostRecorder?.RemoveSelf(); GhostRecorder = null; Run = Guid.NewGuid(); } Player player = level.Tracker.GetEntity <Player>(); if (player == null) { level.Add(new Entity { new Coroutine(WaitForPlayer(level)) }); } else { Step(level); } }
private void OnLoadLevel(Level level, Player.IntroTypes playerIntro, bool isFromLoader) { var settings = this.InRandomizerSettings; if (settings != null) { // set summit gems SaveData.Instance.SummitGems = new bool[6]; if (settings.Length == MapLength.Short) { SaveData.Instance.SummitGems[0] = true; SaveData.Instance.SummitGems[1] = true; SaveData.Instance.SummitGems[2] = true; } // set life berries if (isFromLoader && settings.Algorithm == LogicType.Endless) { var glb = Entities.LifeBerry.GrabbedLifeBerries; if (settings.EndlessLevel == 0) { glb.Carrying = settings.EndlessLives; } else if (glb.Carrying < settings.EndlessLives) { glb.Carrying++; } } } }
[PatchLevelLoader] // Manually manipulate the method via MonoModRules public new void LoadLevel(Player.IntroTypes playerIntro, bool isFromLoader = false) { // These two fields are missing before Celeste 1.2.5.0. // This is only here because Leo bugged me enough to add this here. CassetteBlockTempo = 1f; CassetteBlockBeats = 2; try { orig_LoadLevel(playerIntro, isFromLoader); } catch (Exception e) { Mod.Logger.Log(LogLevel.Warn, "misc", $"Failed loading level {Session.Area}"); e.LogDetailed(); string message = Dialog.Get("postcard_levelloadfailed"); if (e is ArgumentOutOfRangeException && e.StackTrace.Contains("get_DefaultSpawnPoint")) { message = Dialog.Get("postcard_levelnospawn"); } message = message .Replace("((player))", SaveData.Instance.Name) .Replace("((sid))", Session.Area.GetSID()); Entity helperEntity = new Entity(); helperEntity.Add(new Coroutine(ErrorRoutine(message))); Add(helperEntity); return; } Everest.Events.Level.LoadLevel(this, playerIntro, isFromLoader); }
private void onLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { // strawberries weren't made golden yet, they were just spawned. strawberriesWereMadeGolden = false; orig(self, playerIntro, isFromLoader); }
private static void LevelLoadHandler(Level loadedLevel, Player.IntroTypes playerIntro, bool isFromLoader) { if (loadedLevel.Session.GetFlag("lightsDisabled")) { DisableAllLights(loadedLevel); On.Celeste.Level.TransitionTo += TransitionLightSources; } }
private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (playerIntro != Player.IntroTypes.Transition) { applyWind(self); } }
private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); // if we killed the slowdown earlier, stop now! killSeekerSlowdownToFixHeart = false; Level level = self; Player player = level.Tracker.GetEntity <Player>(); if (player != null && Settings.AddSeekers != 0) { // make the seeker barriers temporarily collidable so that they are taken in account in Solid collide checks // and seekers can't spawn in them // (... yes, this is also what vanilla does in the seekers' Update method.) foreach (Entity entity in self.Tracker.GetEntities <SeekerBarrier>()) { entity.Collidable = true; } for (int seekerCount = 0; seekerCount < Settings.AddSeekers; seekerCount++) { for (int i = 0; i < 100; i++) { // roll a seeker position in the room int x = randomGenerator.Next(level.Bounds.Width) + level.Bounds.X; int y = randomGenerator.Next(level.Bounds.Height) + level.Bounds.Y; // should be at least 100 pixels from the player double playerDistance = Math.Sqrt(Math.Pow(MathHelper.Distance(x, player.X), 2) + Math.Pow(MathHelper.Distance(y, player.Y), 2)); // also check if we are not spawning in a wall, that would be a shame Rectangle collideRectangle = new Rectangle(x - 8, y - 8, 16, 16); if (playerDistance > 100 && !level.CollideCheck <Solid>(collideRectangle) && !level.CollideCheck <Seeker>(collideRectangle)) { // build a Seeker with a proper EntityID to make Speedrun Tool happy (this is useless in vanilla Celeste but the constructor call is intercepted by Speedrun Tool) EntityData seekerData = ExtendedVariantsModule.GenerateBasicEntityData(level, 10 + seekerCount); seekerData.Position = new Vector2(x, y); Seeker seeker = new AutoDestroyingSeeker(seekerData, Vector2.Zero); level.Add(seeker); break; } } } foreach (Entity entity in self.Tracker.GetEntities <SeekerBarrier>()) { entity.Collidable = false; } if (playerIntro != Player.IntroTypes.Transition) { level.Entities.UpdateLists(); } } }
private void onLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); Player player = self.Tracker.GetEntity <Player>(); if (Settings.FriendlyBadelineFollower && player != null && self.Tracker.CountEntities <FriendlyBaddy>() == 0) { self.Add(new FriendlyBaddy(player.Center + new Vector2(-16f * (int)player.Facing, -16f))); } }
public void OnLoadLevel(Level level, Player.IntroTypes playerIntro, bool isFromLoader) { if (isFromLoader) { Ghosts.Clear(); GhostRecorder?.RemoveSelf(); GhostRecorder = null; } Step(level); }
private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); // failsafe: kill the glitch effect. Glitch.Value = 0; if (Settings.BadelineBossesEverywhere && playerIntro != Player.IntroTypes.Transition) { injectBadelineBosses(self); } }
public static void TeleportTo(Scene scene, Player player, string room, Player.IntroTypes introType = Player.IntroTypes.Transition, Vector2?nearestSpawn = null) { Level level = scene as Level; if (level != null) { level.OnEndOfFrame += () => { level.TeleportTo(player, room, introType, nearestSpawn); }; } }
private static void OnLoadLevel(Level level, Player.IntroTypes playerIntro, bool isFromLoader) { DateTime now = DateTime.UtcNow; if (DiscordPresence.startTimestamp == 0) { DiscordPresence.startTimestamp = DateTimeToDiscordTime(DateTime.UtcNow); } DiscordPresence.endTimestamp = 0; UpdateText(CoreModule.Settings.DiscordTextInGame, CoreModule.Settings.DiscordSubtextInGame, level.Session); }
/// <summary> /// Checks how many lives should be given to the player when a level is loaded. /// </summary> /// <param name="level">Level object.</param> /// <param name="playerIntro">Intro type (how the player entered the level).</param> /// <param name="isFromLoader">Whether level entry is from after file select or not.</param> private void OnLevelLoad(Level level, Player.IntroTypes playerIntro, bool isFromLoader) { // Check if chapter name is in the dictionary, return if otherwise enabled = chapters.TryGetValue(level.Session.MapData.Filename, out Chapter c); display.SetEnabled(enabled); if (!enabled) { return; } // Check if should restart chapter, do so if needed if (shouldRestart) { display.SetDisplayText(infiniteLives ? "inf" : lifeCount.ToString()); Action restartChapter = delegate { Engine.Scene = new LevelExit(LevelExit.Mode.Restart, level.Session); }; if (isFromLoader) { level.DoScreenWipe(false, restartChapter); } else { restartChapter(); } shouldRestart = false; return; } // Check if player has not visited this level before, return if otherwise if (!level.NewLevel) { display.SetDisplayText(infiniteLives ? "inf" : lifeCount.ToString()); return; } int?newLives = c.GetLives(level.Session.LevelData.Name); // Do not try to change life count if non-existent new life count if (!newLives.HasValue) { return; } lifeCount = Math.Max(lifeCount, newLives.Value); // Don't punish player for being too good infiniteLives = newLives.Value < 0; SaveSessionData(); display.SetDisplayText(infiniteLives ? "inf" : lifeCount.ToString()); Log($"OnLevelLoad: map={level.Session.MapData.Filename}, level: {level.Session.LevelData.Name}, lifeCount={lifeCount}, infiniteLives={infiniteLives}"); }
public void OnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level level, Player.IntroTypes playerIntro, bool isFromLoader) { orig(level, playerIntro, isFromLoader); if (isFromLoader) { GhostManager?.RemoveSelf(); GhostManager = null; GhostRecorder?.RemoveSelf(); GhostRecorder = null; Run = Guid.NewGuid(); } Step(level); }
private void OnLoadLevel(Level level, Player.IntroTypes playerIntro, bool isFromLoader) { var settings = this.InRandomizerSettings; if (settings != null) { // set summit gems SaveData.Instance.SummitGems = new bool[6]; if (settings.Length == MapLength.Short) { SaveData.Instance.SummitGems[0] = true; SaveData.Instance.SummitGems[1] = true; SaveData.Instance.SummitGems[2] = true; } } }
private void onLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (!self.Session?.LevelData?.Underwater ?? false) { // inject a controller that will spawn/despawn water depending on the extended variant setting. self.Add(new UnderwaterSwitchController(Settings)); // when transitioning, don't update lists. this messes with sandwich lava, and the hook below will take care of updating lists. if (playerIntro != Player.IntroTypes.Transition) { self.Entities.UpdateLists(); } } }
private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (playerIntro != Player.IntroTypes.Transition) { // always reset the jump count when the player enters a new level (respawn, new map, etc... everything but a transition) RefillJumpBuffer(); } if (!self.Entities.Any(entity => entity is JumpIndicator)) { // add the entity showing the jump count self.Add(new JumpIndicator()); self.Entities.UpdateLists(); } }
private static void LevelOnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (!isFromLoader && playerIntro != Player.IntroTypes.Respawn) { return; } // entities with Tags.Global will not be removed after level reloading, so we need to remove them manually self.Entities.Remove(self.Entities.FindAll <CollectablePointer>()); var entities = self.Session.MapData.Levels.SelectMany(data => data.Entities); foreach (EntityData entityData in entities) { TryAddPointer(self, entityData); } }
private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (playerIntro != Player.IntroTypes.Transition) { injectTheoCrystal(self); } else if ((Settings.AllowLeavingTheoBehind || Settings.AllowThrowingTheoOffscreen) && !(self.Tracker.GetEntity<Player>()?.Holding?.Entity is TheoCrystal)) { // player is transitioning into a new room, but doesn't have Theo with them. injectTheoCrystalAfterTransition(self); } else if (self.Tracker.CountEntities<ExtendedVariantTheoCrystal>() == 0) { // player is transitioning into a new room, and no Theo crystal is in the room: we should add one if the variant is enabled. injectTheoCrystalAfterTransition(self); } }
private void OnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level level, Player.IntroTypes playerIntro, bool isFromLoader) { orig(level, playerIntro, isFromLoader); Debug.WriteLine($"OnLoadLevel called, intro type {playerIntro}, isFromLoader {isFromLoader}"); if (isFromLoader) { List <Monocle.Entity> e = level.Tracker.GetEntities <CounterEntity>(); if (e.Count == 1) { Debug.WriteLine("counter already exists"); } else { Debug.WriteLine("Creating counter entity"); level.Add(new CounterEntity(level)); } } }
private void onLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); if (!self.Session?.LevelData?.Underwater ?? false) { // inject a controller that will spawn/despawn water depending on the extended variant setting. self.Add(new UnderwaterSwitchController(Settings)); // when transitioning, don't update lists right away, but on the end of the frame. if (playerIntro != Player.IntroTypes.Transition) { self.Entities.UpdateLists(); } else { self.OnEndOfFrame += () => self.Entities.UpdateLists(); } } }
private static void LevelOnLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); // 切换章节清理历史记录 if (RoomHistory.Count > 0 && RoomHistory[0].Area != self.Session.Area) { Reset(); } // 非初始房间 if (HistoryIndex != -1) { return; } // 进入章节的第一个房间 RoomHistory.Add(self.Session.DeepClone()); HistoryIndex = 0; }
[PatchLevelLoader] // Manually manipulate the method via MonoModRules public new void LoadLevel(Player.IntroTypes playerIntro, bool isFromLoader = false) { try { orig_LoadLevel(playerIntro, isFromLoader); } catch (Exception e) { Mod.Logger.Log(LogLevel.Warn, "misc", $"Failed loading level {Session.Area}"); e.LogDetailed(); string message = Dialog.Get("postcard_levelloadfailed"); if (e is ArgumentOutOfRangeException && e.StackTrace.Contains("get_DefaultSpawnPoint")) { message = Dialog.Get("postcard_levelnospawn"); } message = message .Replace("((player))", SaveData.Instance.Name) .Replace("((sid))", Session.Area.GetSID()); Entity helperEntity = new Entity(); helperEntity.Add(new Coroutine(ErrorRoutine(message))); Add(helperEntity); return; } Everest.Events.Level.LoadLevel(this, playerIntro, isFromLoader); }
/// <summary> /// Wraps the LoadLevel method in order to add Badeline chasers when needed. /// </summary> /// <param name="orig">The base method</param> /// <param name="self">The level entity</param> /// <param name="playerIntro">The type of player intro</param> /// <param name="isFromLoader">unused</param> private void modLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); // this method takes care of every situation except transitions, we let this one to TransitionRoutine if (Settings.BadelineChasersEverywhere && playerIntro != Player.IntroTypes.Transition) { // set this to avoid the player being instakilled during the level intro animation Player player = self.Tracker.GetEntity <Player>(); if (player != null) { player.JustRespawned = true; } } if (playerIntro != Player.IntroTypes.Transition) { if ((Settings.BadelineChasersEverywhere || Settings.AffectExistingChasers)) { injectBadelineChasers(self); } updateLastChaserLag(self); } }
private static void onLoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { orig(self, playerIntro, isFromLoader); DynData <Session> sessionData = new DynData <Session>(self.Session); if (sessionData.Data.ContainsKey("pauseTimerUntilAction") && sessionData.Get <bool>("pauseTimerUntilAction")) { sessionData["pauseTimerUntilAction"] = false; self.TimerStopped = true; unpauseTimerOnNextAction = true; } }
public extern void orig_LoadLevel(Player.IntroTypes playerIntro, bool isFromLoader = false);
private void Level_LoadLevel(On.Celeste.Level.orig_LoadLevel orig, Level self, Player.IntroTypes playerIntro, bool isFromLoader) { if (playerIntro != Player.IntroTypes.Respawn) { deaths.Clear(); } orig(self, playerIntro, isFromLoader); }