446 lines
10 KiB
C#
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;
|
|
}
|
|
|
|
}
|