2023-03-22 21:22:51 -07:00
|
|
|
using Godot;
|
|
|
|
using SupaLidlGame.Characters;
|
2023-07-25 03:47:31 -07:00
|
|
|
using SupaLidlGame.Extensions;
|
2023-03-26 10:53:45 -07:00
|
|
|
using SupaLidlGame.Scenes;
|
2023-08-05 23:50:08 -07:00
|
|
|
using SupaLidlGame.State.Global;
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
namespace SupaLidlGame.Utils;
|
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
public partial class World : Node
|
2023-03-22 21:22:51 -07:00
|
|
|
{
|
2023-08-05 23:50:08 -07:00
|
|
|
public static World Instance { get; private set; }
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
[Export]
|
|
|
|
public Map CurrentMap { get; protected set; }
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
[Export]
|
|
|
|
public Player CurrentPlayer { get; set; }
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-07-24 12:40:28 -07:00
|
|
|
[Export]
|
|
|
|
public Boss CurrentBoss { get; set; }
|
|
|
|
|
2023-07-22 20:23:48 -07:00
|
|
|
[Export]
|
2023-07-23 11:05:01 -07:00
|
|
|
public UI.UIController UIController { get; set; }
|
2023-07-22 20:23:48 -07:00
|
|
|
|
2023-07-24 00:43:21 -07:00
|
|
|
[Export]
|
|
|
|
public AudioStreamPlayer MusicPlayer { get; set; }
|
|
|
|
|
2023-07-25 03:47:31 -07:00
|
|
|
[Export]
|
2023-08-06 02:53:49 -07:00
|
|
|
public Dialogue.Balloon DialogueBalloon
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
if (_dialogueBalloon is null || !IsInstanceValid(_dialogueBalloon))
|
|
|
|
{
|
|
|
|
var scene = GD.Load<PackedScene>("res://Dialogue/balloon.tscn");
|
|
|
|
_dialogueBalloon = scene.Instantiate<Dialogue.Balloon>();
|
|
|
|
//_uiViewport.AddChild(_dialogueBalloon);
|
|
|
|
_uiViewport.AddChild(_dialogueBalloon);
|
|
|
|
}
|
|
|
|
return _dialogueBalloon;
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
if (_dialogueBalloon != value && _dialogueBalloon is not null)
|
|
|
|
{
|
|
|
|
_dialogueBalloon.QueueFree();
|
|
|
|
}
|
|
|
|
_dialogueBalloon = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private Dialogue.Balloon _dialogueBalloon;
|
|
|
|
|
|
|
|
private SubViewport _uiViewport;
|
2023-07-25 03:47:31 -07:00
|
|
|
|
2023-08-01 02:10:55 -07:00
|
|
|
public State.Global.GlobalState GlobalState { get; set; }
|
|
|
|
|
2023-08-01 23:49:48 -07:00
|
|
|
public Events.EventBus EventBus { get; set; }
|
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
private CacheStore<string, Map> _maps = new();
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
private string _currentConnector;
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
private string _currentMapResourcePath;
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-10 22:15:28 -07:00
|
|
|
//private Entities.Campfire _lastCampfire = null;
|
|
|
|
public Vector2 SaveLocation { get; set; }
|
|
|
|
public string SaveMapKey { get; set; }
|
2023-06-06 18:39:23 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
private const string PLAYER_PATH = "res://Characters/Player.tscn";
|
|
|
|
private PackedScene _playerScene;
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
public World()
|
|
|
|
{
|
|
|
|
_playerScene = ResourceLoader.Load<PackedScene>(PLAYER_PATH);
|
2023-08-05 23:50:08 -07:00
|
|
|
if (Instance is null)
|
|
|
|
{
|
|
|
|
Instance = this;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw new System.Exception("Another World instance is running.");
|
|
|
|
}
|
2023-06-03 18:21:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void _Ready()
|
|
|
|
{
|
2023-07-24 12:40:28 -07:00
|
|
|
// check if world already exists
|
|
|
|
|
2023-08-01 23:49:48 -07:00
|
|
|
GlobalState = this.GetGlobalState();
|
2023-07-24 12:40:28 -07:00
|
|
|
|
2023-07-19 01:25:02 -07:00
|
|
|
Godot.RenderingServer.SetDefaultClearColor(Godot.Colors.Black);
|
2023-07-24 12:40:28 -07:00
|
|
|
|
2023-08-06 02:53:49 -07:00
|
|
|
_uiViewport = GetNode<SubViewport>("CanvasLayer/SubViewportContainer/UIViewport");
|
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
// create a player (currently unparented)
|
2023-06-03 18:21:46 -07:00
|
|
|
CreatePlayer();
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-08-01 23:49:48 -07:00
|
|
|
EventBus = this.GetEventBus();
|
|
|
|
EventBus.RequestMoveToArea += (Events.RequestAreaArgs args) =>
|
|
|
|
{
|
|
|
|
GD.Print("request move to area");
|
|
|
|
MoveToArea(args.Area, args.Connector);
|
|
|
|
};
|
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
base._Ready();
|
|
|
|
}
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-07-23 11:05:01 -07:00
|
|
|
public void RegisterBoss(Boss boss)
|
|
|
|
{
|
2023-07-24 12:40:28 -07:00
|
|
|
CurrentBoss = boss;
|
2023-07-23 11:05:01 -07:00
|
|
|
UIController.BossBar.Boss = boss;
|
2023-07-24 00:43:21 -07:00
|
|
|
MusicPlayer.Stream = boss.Music;
|
|
|
|
MusicPlayer.Play();
|
2023-07-23 11:05:01 -07:00
|
|
|
}
|
|
|
|
|
2023-07-24 12:40:28 -07:00
|
|
|
public void DeregisterBoss(Boss boss)
|
|
|
|
{
|
|
|
|
CurrentBoss = null;
|
|
|
|
UIController.BossBar.Boss = null;
|
|
|
|
MusicPlayer.Stop();
|
|
|
|
}
|
|
|
|
|
2023-06-10 22:15:28 -07:00
|
|
|
private void LoadMap(Map map)
|
2023-06-03 18:21:46 -07:00
|
|
|
{
|
2023-06-10 22:15:28 -07:00
|
|
|
GD.Print("Loading map " + map.Name);
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
if (CurrentMap is not null)
|
|
|
|
{
|
|
|
|
CurrentMap.Entities.RemoveChild(CurrentPlayer);
|
2023-08-03 16:17:34 -07:00
|
|
|
GetTree().Root.RemoveChild(CurrentMap);
|
2023-06-03 18:21:46 -07:00
|
|
|
CurrentMap.Active = false;
|
|
|
|
}
|
2023-03-26 13:03:45 -07:00
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
GetTree().Root.AddChild(map);
|
2023-06-03 18:21:46 -07:00
|
|
|
InitTilemap(map);
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
CurrentMap = map;
|
|
|
|
CurrentMap.Active = true;
|
2023-07-31 01:12:47 -07:00
|
|
|
CurrentMap.Load();
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
if (CurrentPlayer is not null)
|
2023-03-22 21:22:51 -07:00
|
|
|
{
|
2023-03-26 10:53:45 -07:00
|
|
|
CurrentMap.Entities.AddChild(CurrentPlayer);
|
2023-03-22 21:22:51 -07:00
|
|
|
}
|
2023-06-03 18:21:46 -07:00
|
|
|
}
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
public void LoadScene(Map map)
|
|
|
|
{
|
|
|
|
_maps.Update(map.SceneFilePath, map);
|
|
|
|
LoadMap(map);
|
|
|
|
}
|
|
|
|
|
2023-06-10 22:15:28 -07:00
|
|
|
public void LoadScene(PackedScene scene)
|
|
|
|
{
|
2023-08-03 16:17:34 -07:00
|
|
|
if (CurrentMap is not null)
|
|
|
|
{
|
|
|
|
_maps.Update(CurrentMap.SceneFilePath);
|
|
|
|
}
|
|
|
|
|
2023-06-10 22:15:28 -07:00
|
|
|
Map map;
|
2023-08-03 16:17:34 -07:00
|
|
|
string path = scene.ResourcePath;
|
|
|
|
|
|
|
|
if (_maps.IsItemValid(path))
|
2023-06-10 22:15:28 -07:00
|
|
|
{
|
2023-08-03 16:17:34 -07:00
|
|
|
GD.Print($"{path} is cached");
|
|
|
|
map = _maps.Retrieve(path);
|
2023-06-10 22:15:28 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-08-03 16:17:34 -07:00
|
|
|
if (_maps.IsItemStale(path))
|
|
|
|
{
|
|
|
|
_maps[path].Value.QueueFree();
|
|
|
|
GD.Print("Freeing stale map " + path);
|
|
|
|
}
|
2023-06-10 22:15:28 -07:00
|
|
|
map = scene.Instantiate<Map>();
|
2023-08-03 16:17:34 -07:00
|
|
|
_maps.Update(path, map);
|
2023-06-10 22:15:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
LoadMap(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void LoadScene(string path)
|
|
|
|
{
|
|
|
|
Map map;
|
2023-08-03 16:17:34 -07:00
|
|
|
if (_maps.IsItemValid(path))
|
2023-06-10 22:15:28 -07:00
|
|
|
{
|
2023-08-03 16:17:34 -07:00
|
|
|
GD.Print($"{path} is cached");
|
|
|
|
map = _maps.Retrieve(path);
|
2023-06-10 22:15:28 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-08-03 16:17:34 -07:00
|
|
|
if (_maps.IsItemStale(path))
|
|
|
|
{
|
|
|
|
_maps[path].Value.QueueFree();
|
|
|
|
GD.Print("Freeing stale map " + path);
|
|
|
|
}
|
2023-06-10 22:15:28 -07:00
|
|
|
var scene = ResourceLoader.Load<PackedScene>(path);
|
|
|
|
map = scene.Instantiate<Map>();
|
2023-08-03 16:17:34 -07:00
|
|
|
_maps.Update(scene.ResourcePath, map);
|
2023-06-10 22:15:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
LoadMap(map);
|
|
|
|
}
|
|
|
|
|
2023-08-03 16:17:34 -07:00
|
|
|
public Player CreatePlayer()
|
2023-06-03 18:21:46 -07:00
|
|
|
{
|
|
|
|
CurrentPlayer = _playerScene.Instantiate<Player>();
|
2023-08-03 16:17:34 -07:00
|
|
|
|
|
|
|
CurrentPlayer.Death += (Events.HealthChangedArgs args) =>
|
|
|
|
{
|
|
|
|
// TODO: respawn the player at the last campfire.
|
|
|
|
GetTree().CreateTimer(3).Timeout += () =>
|
|
|
|
{
|
|
|
|
SpawnPlayer();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
CurrentPlayer.Hurt += (Events.HealthChangedArgs args) =>
|
|
|
|
{
|
|
|
|
// TODO: move this to UI controller and add a setup method
|
|
|
|
var bar = UIController.GetNode<UI.HealthBar>("Top/Margin/HealthBar");
|
|
|
|
bar.ProgressBar.Value = args.NewHealth;
|
|
|
|
};
|
|
|
|
|
|
|
|
return CurrentPlayer;
|
2023-06-03 18:21:46 -07:00
|
|
|
}
|
2023-03-22 21:22:51 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
private void InitTilemap(Map map)
|
|
|
|
{
|
2023-08-01 23:49:48 -07:00
|
|
|
// this is being replaced with interaction triggers
|
2023-06-03 18:21:46 -07:00
|
|
|
}
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
private void MovePlayerToConnector(string name)
|
|
|
|
{
|
|
|
|
// find the first connector with the specified name
|
2023-08-01 23:49:48 -07:00
|
|
|
// TODO: replace this with event buses
|
|
|
|
//var connector = CurrentMap.Areas.GetChildren().First((child) =>
|
|
|
|
//{
|
|
|
|
// if (child is BoundingBoxes.ConnectorBox connector)
|
|
|
|
// {
|
|
|
|
// return connector.Identifier == name;
|
|
|
|
// }
|
|
|
|
// return false;
|
|
|
|
//}) as BoundingBoxes.ConnectorBox;
|
|
|
|
|
|
|
|
//CurrentPlayer.GlobalPosition = connector.GlobalPosition;
|
|
|
|
CurrentPlayer.GlobalPosition = Vector2.Zero;
|
2023-06-03 18:21:46 -07:00
|
|
|
}
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
public void MoveToArea(string path, string connector)
|
|
|
|
{
|
|
|
|
_currentConnector = connector;
|
|
|
|
if (path != _currentMapResourcePath)
|
2023-03-25 10:21:24 -07:00
|
|
|
{
|
2023-06-03 18:21:46 -07:00
|
|
|
var scene = ResourceLoader.Load<PackedScene>(path);
|
2023-08-01 23:49:48 -07:00
|
|
|
LoadScene(path);
|
2023-06-03 18:21:46 -07:00
|
|
|
_currentMapResourcePath = path;
|
2023-03-26 10:53:45 -07:00
|
|
|
}
|
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
// after finished loading, move our player to the connector
|
|
|
|
MovePlayerToConnector(connector);
|
|
|
|
}
|
2023-03-26 10:53:45 -07:00
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
public void _on_area_2d_requested_enter(
|
|
|
|
BoundingBoxes.ConnectorBox box,
|
|
|
|
Player player)
|
|
|
|
{
|
|
|
|
GD.Print("Requesting to enter " + box.ToConnector);
|
|
|
|
MoveToArea(box.ToArea, box.ToConnector);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SaveGame()
|
|
|
|
{
|
2023-08-05 23:50:08 -07:00
|
|
|
ResourceSaver.Save(GlobalState.Progression, "user://progression.save");
|
|
|
|
ResourceSaver.Save(GlobalState.MapState, "user://map-state.save");
|
2023-06-03 18:21:46 -07:00
|
|
|
throw new System.NotImplementedException();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void LoadGame()
|
|
|
|
{
|
2023-08-05 23:50:08 -07:00
|
|
|
var prog = ResourceLoader.Load<Progression>("user://progression.save");
|
|
|
|
var mapState = ResourceLoader.Load<MapState>("user://map-state.save");
|
|
|
|
GlobalState.Progression = prog;
|
|
|
|
GlobalState.MapState = mapState;
|
|
|
|
|
|
|
|
// load the player scene
|
|
|
|
// TODO: implement
|
|
|
|
|
2023-06-03 18:21:46 -07:00
|
|
|
throw new System.NotImplementedException();
|
2023-03-22 21:22:51 -07:00
|
|
|
}
|
2023-06-10 22:15:28 -07:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Sets the player's saved spawn position.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="position">The position to save and spawn the player in</param>
|
|
|
|
/// <param name="mapKey">
|
|
|
|
/// The map to spawn the player in. If <see langword="null" />, use the
|
|
|
|
/// <c>World</c>'s <c>CurrentMap</c>
|
|
|
|
/// </param>
|
|
|
|
public void SetSpawn(Vector2 position, string mapKey = null)
|
|
|
|
{
|
|
|
|
GD.Print("Set spawn");
|
|
|
|
if (mapKey is null)
|
|
|
|
{
|
|
|
|
mapKey = CurrentMap.SceneFilePath;
|
|
|
|
SaveLocation = position;
|
|
|
|
SaveMapKey = mapKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void SpawnPlayer()
|
|
|
|
{
|
|
|
|
// TODO: add max health property
|
2023-06-13 02:55:30 -07:00
|
|
|
//CurrentPlayer.Health = 100;
|
|
|
|
//CurrentPlayer.Sprite.Visible = true;
|
2023-06-10 22:15:28 -07:00
|
|
|
if (CurrentMap.SceneFilePath != SaveMapKey)
|
|
|
|
{
|
|
|
|
LoadScene(SaveMapKey);
|
|
|
|
}
|
2023-06-13 02:55:30 -07:00
|
|
|
CurrentPlayer.GlobalPosition = SaveLocation;
|
|
|
|
CurrentPlayer.Spawn();
|
2023-06-10 22:15:28 -07:00
|
|
|
}
|
2023-07-25 03:47:31 -07:00
|
|
|
|
|
|
|
public Node FindEntity(string name) => CurrentMap.Entities.GetNode(name);
|
2023-03-22 21:22:51 -07:00
|
|
|
}
|