using System.Collections; using System.Collections.Generic; using System.ComponentModel; using Godot; using Godot.Bridge; using Godot.Collections; using Godot.NativeInterop; [ScriptPath("res://Scripts/Room.cs")] public partial class Room : Node2D { public enum IDs { None = -1, DebugRoom, WildEastMain, WildEastWest, MartletHouse, KetsukaneShop, SuperMarket, TownHall, SchoolMain, SchoolLibrary, MinesEntrance, MinesMiddle, MinesTop, DarkPrisonMain, SchoolDWEntrance, SchoolDWFirstCorridor, SchoolDWFirstPuzzle, SchoolDWKanako, SchoolDWAfterKanako, SchoolDWChase, SchoolDWCenter, SchoolDWBridge, SchoolDWFortMain, SchoolDWPenny, SchoolSupplyCave, DarkPrisonLeft, DarkPrisonNorth, DarkPrisonRight, DarkPrisonSouth, SchoolDWLake, SchoolDWFortressRightmost, SchoolDWFortFirstPuzzle, SchoolDWFortLeft, SchoolDWFortRest, SchoolDWFortBigCorridor, SchoolDWFortTreasure, SchoolDWFortPrison, SchoolDWFortBossRoom, FountainRoom, SchoolCloset, SchoolDWFoxRoom, Cafe, Church, Jail, Hospital, ChujinDWEntrance, ChujinDWFirstCorridor, ChujinDWLongSlide, ChujinDWAxisRoom, ChujinDWPostAxis, ChujinDWOverview, ChujinDWSouthPuzzle, ChujinDWBeforeTown, ChujinDWTown, ChujinDWFactoryPath, ChujinDWFactoryMain, ChujinDWFactoryStation, ChujinDWInsideTrain, ChujinDWTowerStation, ChujinDWTownAlley, ChujinDWFactoryLeft, ChujinDWFactoryRight, ChujinDWPostTram1, ChujinDWPostTram2, ChujinDWPostTram3, ChujinDWPostTram4, ChujinDWUpstairsPort, ChujinDWUpstairsView, ChujinDWUpstairsGreen, ChujinDWUpstairsBalloons, ChujinDWUpstairsSpire, ChujinDWArchiveOutside, ChujinDWArchiveLobby, ChujinDWArchivePuzzle, ChujinDWArchiveSecret, ChujinDWSpireTop, ChujinDWSpriteElevator, ChujinDWSpireChujinRoom, ChujinDWSpirePreBoss, ChujinDWSpireFountain, SchoolDWAfterKanako2, WildEastSouth } private static IDs lastRoom; [Export(PropertyHint.None, "")] public IDs id; [Export(PropertyHint.None, "")] public Vector2[] cameraLimit = new Vector2[2] { new Vector2(-999f, -999f), new Vector2(999f, 999f) }; [Export(PropertyHint.None, "")] public string mapName; [Export(PropertyHint.None, "")] public TileMap tileMap; [Export(PropertyHint.None, "")] public int shadowLayer = -1; [Export(PropertyHint.None, "")] public int hideLayer = -1; [Export(PropertyHint.None, "")] private Color modOverride = Main.colorWhite; [Export(PropertyHint.None, "")] private Color nightColor = Main.colorWhite; [Export(PropertyHint.None, "")] private SaveFile.Flags nightFlag = SaveFile.Flags.None; [Export(PropertyHint.None, "")] public Node2D[] modOverrideNodes; [Export(PropertyHint.None, "")] public Node2D[] eventPointers; [Export(PropertyHint.None, "")] public Node[] stopOnDiag; [Export(PropertyHint.None, "")] public AudioStream stepSound; [Export(PropertyHint.None, "")] public AudioStream[] music = new AudioStream[1]; [Export(PropertyHint.None, "")] private Array seamlessMusic; [Export(PropertyHint.None, "")] private Array musicFlags; [Export(PropertyHint.None, "")] private Array resetOnLoad; [Export(PropertyHint.None, "")] private Array applyOnLoad; [Export(PropertyHint.None, "")] public Vector2 camOffset = CameraController.defaultOffset; public HashSet tempFlags = new HashSet(); public System.Collections.Generic.Dictionary tempValue = new System.Collections.Generic.Dictionary(); public static Room current; public int waterBullet; public float lifeTime; public System.Collections.Generic.Dictionary dialogue = new System.Collections.Generic.Dictionary(); public HashSet entities = new HashSet(); public override void _EnterTree() { current = this; base.YSortEnabled = true; if (tileMap != null) { tileMap.YSortEnabled = true; } if (modOverrideNodes != null) { for (int i = 0; i < modOverrideNodes.Length; i++) { modOverrideNodes[i].Modulate = modOverride; } } if (Main.inEvent == null || Main.inEvent.done) { DoMusic(); } if (Player.instance != null) { Player.instance.stepCD = 0f; } Array array = resetOnLoad; if (array != null && array.Count > 0) { for (int j = 0; j < resetOnLoad.Count; j++) { SaveFile.current.flags.Remove(resetOnLoad[j]); } } Array array2 = applyOnLoad; if (array2 != null && array2.Count > 0) { for (int k = 0; k < applyOnLoad.Count; k++) { SaveFile.AddFlag(applyOnLoad[k]); } } if (nightFlag != SaveFile.Flags.None && SaveFile.HasFlag(nightFlag)) { if (shadowLayer > -1 && tileMap != null) { tileMap.SetLayerEnabled(shadowLayer, enabled: false); } base.Modulate = nightColor; } if (hideLayer > -1) { tileMap?.SetLayerModulate(hideLayer, Main.colorClear); } Party.UpdateFollowerEntities(); for (int l = 0; l < SaveFile.current.activeParty.Count; l++) { entities.Add(Party.party[SaveFile.current.activeParty[l]].oEntity); } RenderingServer.SetDefaultClearColor(Main.colorBlack); CameraController.instance.offset = camOffset; string filename = "Rooms/" + id.ToString() + ".txt"; if (FileAccess.FileExists(Texts.textFolder + filename)) { TextSystem.LoadText(in filename, ref dialogue); } } public static void SpawnFollowers() { if (SaveFile.current.followers.Count > 0) { for (int i = 0; i < SaveFile.current.followers.Count; i++) { Entity entity; current.AddChild(entity = GD.Load("res://Objects/Characters/" + SaveFile.current.followers[i].ToString() + ".tscn").Instantiate(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled); entity.GlobalPosition = Player.instance.GlobalPosition + Vector2.Up; Party.AddNPCFollower(entity); } } } public void DoMusic(int id = -1) { AudioStream[] array = music; if (array == null || array.Length == 0) { return; } if (id == -1) { id = 0; Array array2 = musicFlags; if (array2 != null && array2.Count > 0) { for (int num = musicFlags.Count - 1; num >= 0; num--) { if (SaveFile.current.flags.Contains(musicFlags[num])) { id = num; break; } } } } Array array3 = seamlessMusic; if (array3 != null && array3.Count > 0 && seamlessMusic.Contains(lastRoom)) { float playbackPosition = Audio.music.GetPlaybackPosition(); Audio.music.Stream = music[id]; Audio.music.Play(playbackPosition); } else { Audio.ChangeMusic(music[id]); } } public static Entity GetEntity(string name, bool removeNull = false) { if (removeNull) { UpdateEntityList(); } foreach (Entity entity in current.entities) { if (entity.Name == (StringName)name) { return entity; } } return null; } public void DoEvent(int objID, string name) { eventPointers[objID].GetType().GetMethod(name).Invoke(eventPointers[objID], null); } public override void _Process(double delta) { if (lifeTime < 500f) { lifeTime += Main.deltaTime; } if (modOverrideNodes == null) { return; } for (int i = 0; i < modOverrideNodes.Length; i++) { if (GodotObject.IsInstanceValid(modOverrideNodes[i])) { if (Player.instance.dangerZoneCD > 0f) { modOverrideNodes[i].Modulate = modOverrideNodes[i].Modulate.Lerp(Main.colorDark, 0.1f); } else { modOverrideNodes[i].Modulate = modOverrideNodes[i].Modulate.Lerp(modOverride, 0.1f); } } } } public static void UpdateEntityList() { current.entities.RemoveWhere((Entity x) => !GodotObject.IsInstanceValid(x)); } public void DisableProcess() { base.ProcessMode = ProcessModeEnum.Disabled; } public void EnableProcess() { base.ProcessMode = ProcessModeEnum.Inherit; } public static IEnumerator SwitchRooms(IDs id, Vector2? pos = null, Entity.Direction direction = Entity.Direction.None, bool lockMovement = false, AudioStream[] clips = null) { lastRoom = current.id; if (clips != null) { Audio.PlaySound(clips[0]); } Party.StopMoving(); Player.instance.canInput = false; CameraController.Transition(Main.colorBlack, 20f, null, Main.colorClearB); while (true) { Coroutine transitionRoutine = CameraController.transitionRoutine; if (transitionRoutine == null || transitionRoutine.done) { break; } yield return null; } yield return null; Party.Reparent(Main.instance); LoadRoom(id); yield return null; if (pos.HasValue) { Party.SetPosition(pos.Value); } Player.instance.ResetFollowStep(); Party.Reparent(current); if (CameraController.instance.follow == Player.instance) { CameraController.instance.GlobalPosition = Player.instance.GlobalPosition + CameraController.instance.offset; } if (direction != Entity.Direction.None) { Party.LookAt(direction); } else { Party.LookAt(Player.instance.direction); } yield return null; if (clips != null && clips.Length > 1) { Audio.PlaySound(clips[1]); } if (!lockMovement) { current.DoMusic(); } CameraController.Transition(Main.colorClearB, 20f, null, Main.colorBlack); while (true) { Coroutine transitionRoutine2 = CameraController.transitionRoutine; if (transitionRoutine2 == null || transitionRoutine2.done) { break; } yield return null; } Player.instance.canInput = !lockMovement; } public static void LoadRoom(IDs id, bool reparent = false) { if (reparent) { Party.Reparent(Main.instance); } if (GodotObject.IsInstanceValid(current)) { current.QueueFree(); } Main.instance.AddChild(current = GD.Load("res://Objects/Rooms/" + id.ToString() + ".tscn").Instantiate(PackedScene.GenEditState.Disabled), forceReadableName: false, InternalMode.Disabled); if (reparent) { Party.Reparent(current); } Main.instance.CallDeferred(Main.MethodName.GCCollect); } public static Entity NewEntity(Entity.IDs id, Vector2 pos, bool addToArray = false) { Entity entity = GD.Load("res://Objects/Characters/" + id.ToString() + ".tscn").Instantiate(PackedScene.GenEditState.Disabled); current.AddChild(entity, forceReadableName: false, InternalMode.Disabled); entity.GlobalPosition = pos; if (addToArray) { current.entities.Add(entity); } return entity; } }