2025-05-13 19:22:01 +08:00

446 lines
10 KiB
C#

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<IDs> seamlessMusic;
[Export(PropertyHint.None, "")]
private Array<SaveFile.Flags> musicFlags;
[Export(PropertyHint.None, "")]
private Array<SaveFile.Flags> resetOnLoad;
[Export(PropertyHint.None, "")]
private Array<SaveFile.Flags> applyOnLoad;
[Export(PropertyHint.None, "")]
public Vector2 camOffset = CameraController.defaultOffset;
public HashSet<StringName> tempFlags = new HashSet<StringName>();
public System.Collections.Generic.Dictionary<StringName, int> tempValue = new System.Collections.Generic.Dictionary<StringName, int>();
public static Room current;
public int waterBullet;
public float lifeTime;
public System.Collections.Generic.Dictionary<string, Texts.TextBlock[]> dialogue = new System.Collections.Generic.Dictionary<string, Texts.TextBlock[]>();
public HashSet<Entity> entities = new HashSet<Entity>();
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<SaveFile.Flags> array = resetOnLoad;
if (array != null && array.Count > 0)
{
for (int j = 0; j < resetOnLoad.Count; j++)
{
SaveFile.current.flags.Remove(resetOnLoad[j]);
}
}
Array<SaveFile.Flags> 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<PackedScene>("res://Objects/Characters/" + SaveFile.current.followers[i].ToString() + ".tscn").Instantiate<Entity>(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<SaveFile.Flags> 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<IDs> 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<PackedScene>("res://Objects/Rooms/" + id.ToString() + ".tscn").Instantiate<Room>(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<PackedScene>("res://Objects/Characters/" + id.ToString() + ".tscn").Instantiate<Entity>(PackedScene.GenEditState.Disabled);
current.AddChild(entity, forceReadableName: false, InternalMode.Disabled);
entity.GlobalPosition = pos;
if (addToArray)
{
current.entities.Add(entity);
}
return entity;
}
}