diff --git a/Globals/FunkEngineNameSpace.cs b/Globals/FunkEngineNameSpace.cs
index a280d737..c73800f6 100644
--- a/Globals/FunkEngineNameSpace.cs
+++ b/Globals/FunkEngineNameSpace.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using FunkEngine.Classes.MidiMaestro;
using Godot;
@@ -251,6 +252,13 @@ public enum Stages
Quit,
Map,
Load,
+ Continue,
+}
+
+public enum Area
+{
+ Forest = 0,
+ City = 1,
}
public enum Rarity
@@ -308,59 +316,111 @@ public void AddChild(int newIdx)
}
}
+ //TODO: Make odds for rooms based on y-level, e.g. elites only spawn on y > 3
+ public struct MapConfig
+ {
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public int Paths { get; private set; }
+
+ ///
+ /// Rooms that exist at set levels, only one room can be set per y-level.
+ ///
+ public Dictionary SetRooms { get; private set; } =
+ new()
+ {
+ { 0, Stages.Battle }, //The first, e.g. y = 0 room, should always be a battle.
+ };
+
+ public const int NumStages = 2;
+
+ public static readonly Stages[] StagsToRoll = new[] { Stages.Battle, Stages.Chest };
+
+ ///
+ /// The odds for each stage to appear in a non-set room position.
+ ///
+ public float[] StageOdds = new float[2];
+
+ public MapConfig(int width, int height, int paths, float[] odds)
+ {
+ Width = width;
+ Height = height;
+ Paths = paths;
+ for (int i = 0; i < NumStages; i++)
+ {
+ StageOdds[i] = odds[i];
+ }
+ }
+
+ ///
+ /// Adds a set room type to be generated guaranteed. Additional entries in the same y-level are ignored.
+ ///
+ /// The y-level of the rooms
+ /// The room type to be set.
+ public MapConfig AddSetRoom(int height, Stages roomType)
+ {
+ SetRooms.TryAdd(height, roomType);
+ return this;
+ }
+ }
+
/**
* Initializes the map with max width, max height, and with number of paths.
*/
- public void InitMapGrid(int width, int height, int paths)
+ public void InitMapGrid(MapConfig curConfig)
{
_curIdx = 0;
- _rooms = Array.Empty();
- _map = new int[width, height]; //x,y
+ _rooms = [];
+ _map = new int[curConfig.Width, curConfig.Height]; //x,y
- int startX = (width / 2);
+ int startX = (curConfig.Width / 2);
_rooms = _rooms.Append(new Room(_curIdx, startX, 0)).ToArray();
_rooms[0].SetType(Stages.Battle);
_map[startX, 0] = _curIdx++;
- for (int i = 0; i < paths; i++)
+ for (int i = 0; i < curConfig.Paths; i++)
{
- GeneratePath_r(startX, 0, width, height);
+ GeneratePath_r(startX, 0, curConfig);
}
- CreateCommonChildren(width, height);
- AddBossRoom(width, height);
+ CreateCommonChildren(curConfig.Width, curConfig.Height);
+ AddBossRoom(curConfig.Width, curConfig.Height);
}
/**Start at x, y, assume prev room exists. Picks new x pos within +/- 1, attaches recursively*/
- private void GeneratePath_r(int x, int y, int width, int height)
+ private void GeneratePath_r(int x, int y, MapConfig curConfig)
{
int nextX = StageProducer.GlobalRng.RandiRange(
Math.Max(x - 1, 0),
- Math.Min(x + 1, width - 1)
+ Math.Min(x + 1, curConfig.Width - 1)
);
if (_map[nextX, y + 1] == 0)
{
_rooms = _rooms.Append(new Room(_curIdx, nextX, y + 1)).ToArray();
_map[nextX, y + 1] = _curIdx;
_rooms[_map[x, y]].AddChild(_curIdx++);
- _rooms[^1].SetType(PickRoomType(x, y));
+ _rooms[^1].SetType(PickRoomType(x, y, curConfig));
}
else
{
_rooms[_map[x, y]].AddChild(_map[nextX, y + 1]);
}
- if (y < height - 2)
+ if (y < curConfig.Height - 2)
{
- GeneratePath_r(nextX, y + 1, width, height);
+ GeneratePath_r(nextX, y + 1, curConfig);
}
}
- private Stages PickRoomType(int x, int y)
+ private Stages PickRoomType(int x, int y, MapConfig curConfig)
{
- if (y % 3 == 0)
- return Stages.Chest;
- if (StageProducer.GlobalRng.Randf() < .08)
- return Stages.Chest;
- return Stages.Battle;
+ //If the y has a set room return it.
+ if (curConfig.SetRooms.TryGetValue(y, out Stages result))
+ {
+ return result;
+ }
+
+ //Random roll for the room type.
+ int idx = (int)StageProducer.GlobalRng.RandWeighted(curConfig.StageOdds);
+ return MapConfig.StagsToRoll[idx];
}
//Asserts that if there is a room at the same x, but y+1 they are connected
diff --git a/Globals/StageProducer.cs b/Globals/StageProducer.cs
index 97770b5a..61679c45 100644
--- a/Globals/StageProducer.cs
+++ b/Globals/StageProducer.cs
@@ -13,10 +13,28 @@ public partial class StageProducer : Node
public static readonly RandomNumberGenerator GlobalRng = new();
- public static Vector2I MapSize { get; } = new(7, 6); //For now, make width an odd number
- public static MapGrid Map { get; } = new();
+ private static readonly MapGrid.MapConfig FirstMapConfig = new MapGrid.MapConfig(
+ 7,
+ 6,
+ 3,
+ [10, 1]
+ ).AddSetRoom(3, Stages.Chest);
+
+ private static readonly MapGrid.MapConfig TestMapConfig = new MapGrid.MapConfig(
+ 10,
+ 10,
+ 5,
+ [10, 2]
+ )
+ .AddSetRoom(3, Stages.Chest)
+ .AddSetRoom(6, Stages.Chest);
+
+ private static readonly MapGrid.MapConfig[] MapConfigs = new[] { FirstMapConfig };
+
+ public static MapGrid Map { get; private set; } = new();
private Stages _curStage = Stages.Title;
public static int CurRoom { get; private set; }
+ public static Area CurArea { get; private set; } = Area.Forest;
private Node _curScene;
private Node _preloadStage;
@@ -53,12 +71,13 @@ private void InitFromCfg()
private void GenerateMapConsistent()
{
GlobalRng.State = GlobalRng.Seed << 5 / 2; //Fudge seed state, to get consistent maps across new/loaded games
- Map.InitMapGrid(MapSize.X, MapSize.Y, 3);
+ Map.InitMapGrid(MapConfigs[(int)CurArea]);
}
private void StartNewGame()
{
GlobalRng.Randomize();
+ CurArea = Area.Forest;
GenerateMapConsistent();
PlayerStats = new PlayerStats();
@@ -112,10 +131,10 @@ public void TransitionFromRoom(int nextRoomIdx)
private Task _loadTask;
- /**
- * To be used from Cartographer. Preloads the scene during transition animation.
- * This removes the occasionally noticeable load time for the scene change.
- */
+ ///
+ /// To be used from Cartographer. Preloads the scene during transition animation. This removes the occasionally noticeable load time for the scene change.
+ ///
+ /// Index of the next room in the map to get the stage from.
public void PreloadScene(int nextRoomIdx)
{
Stages nextStage = Map.GetRooms()[nextRoomIdx].Type;
@@ -174,6 +193,10 @@ public void TransitionStage(Stages nextStage, int nextRoomIdx = -1)
case Stages.Quit:
GetTree().Quit();
return;
+ case Stages.Continue:
+ ProgressAreas();
+ GetTree().ChangeSceneToFile("res://Scenes/Maps/InBetween.tscn");
+ break;
default:
GD.PushError($"Error Scene Transition is {nextStage}");
break;
@@ -227,4 +250,26 @@ public override void _Input(InputEvent @event)
return;
}
}
+
+ #region Area Management
+
+ ///
+ /// There should always be a mapconfig for each area. It's preferable to crash later if there isn't even a placeholder config.
+ ///
+ /// True if there is another area.
+ public static bool IsMoreAreas()
+ {
+ return (int)CurArea + 1 < MapConfigs.Length;
+ }
+
+ public void ProgressAreas()
+ {
+ CurArea += 1;
+
+ Map = new();
+ GenerateMapConsistent();
+ CurRoom = Map.GetRooms()[0].Idx;
+ }
+
+ #endregion
}
diff --git a/Globals/Translations/Translations.csv b/Globals/Translations/Translations.csv
index 81994a67..6f9346d4 100644
--- a/Globals/Translations/Translations.csv
+++ b/Globals/Translations/Translations.csv
@@ -20,6 +20,7 @@ CONTROLS_CHOOSE_BUTTON,Choose new button,选择输入按钮
ESCAPE_MENU_RESUME,Resume,继续
ESCAPE_MENU_QUIT,Quit,退出
ESCAPE_MENU_TITLE,Quit to Title,返回标题
+INBETWEEN_CONTINUE,Continue,继续
CHEST_ROOM_REWARDS,Reward Selection!,奖励!
CHEST_ROOM_SKIP,Skip,跳过
CHEST_ROOM_ACCEPT,Accept,接受
@@ -65,15 +66,15 @@ RELIC_COLORBOROS_TOOLTIP,"Taste the rainbow. Charges the freestyle bar every rif
RELIC_CHIPS_NAME,"Chips",薯片
RELIC_CHIPS_TOOLTIP,"Hitting a note deals a bit of damage.","击中音符会造成少量伤害。"
RELIC_PAPERCUT_NAME,Paper Cut,纸割伤
-RELIC_PAPERCUT_TOOLTIP,"Deals damage each loop.","每轮造成伤害"
+RELIC_PAPERCUT_TOOLTIP,"Deals damage each riff.","每轮造成伤害"
RELIC_ENERGYDRINK_NAME,Energy Drink,"能量饮料"
RELIC_ENERGYDRINK_TOOLTIP,"Take a chance to cool down and sip an energy drink to increase your max energy bar.","碰碰运气,喝一口能量饮料来冷静下来并增加你的最大能量条。"
RELIC_BANDAGE_NAME,Bandage,"绷带"
RELIC_BANDAGE_TOOLTIP,"A clean strip of cloth. Use it after a fight to patch up and feel better.","一块干净的布条,战斗后使用来包扎并恢复一些健康。"
RELIC_MEDKIT_NAME,Medkit,"急救包"
-RELIC_MEDKIT_TOOLTIP,"A small kit with medical supplies. Heals you a bit after each loop.","包含一些医疗用品的小包,每次循环后恢复少量生命。"
+RELIC_MEDKIT_TOOLTIP,"A small kit with medical supplies. Heals you a bit after each riff.","包含一些医疗用品的小包,每次循环后恢复少量生命。"
RELIC_VINYLRECORD_NAME,Vinyl Record,"黑胶唱片"
-RELIC_VINYLRECORD_TOOLTIP,"Right round, right round. All loop effects trigger twice.","把我转起来,把我转起来。所有循环效果触发两次。"
+RELIC_VINYLRECORD_TOOLTIP,"Right round, right round. All riff effects trigger twice.","把我转起来,把我转起来。所有循环效果触发两次。"
INVENTORY_TAB_NOTES,Notes,乐谱
INVENTORY_TAB_RELICS,Relics,遗物
OPTIONS_VOLUME_LABEL,Master Volume,最终音量设置
diff --git a/Scenes/AreaBasedBackground.cs b/Scenes/AreaBasedBackground.cs
new file mode 100644
index 00000000..8a5275a2
--- /dev/null
+++ b/Scenes/AreaBasedBackground.cs
@@ -0,0 +1,16 @@
+using System;
+using FunkEngine;
+using Godot;
+
+public partial class AreaBasedBackground : TextureRect
+{
+ public override void _Ready()
+ {
+ Texture = StageProducer.CurArea switch
+ {
+ Area.Forest => GD.Load("res://SharedAssets/BackGround_Full.png"),
+ Area.City => GD.Load("res://icon.svg"),
+ _ => null,
+ };
+ }
+}
diff --git a/Scenes/AreaBasedBackground.cs.uid b/Scenes/AreaBasedBackground.cs.uid
new file mode 100644
index 00000000..6dd4683b
--- /dev/null
+++ b/Scenes/AreaBasedBackground.cs.uid
@@ -0,0 +1 @@
+uid://cp6t6haqyef7o
diff --git a/Scenes/BattleDirector/BattleScene.tscn b/Scenes/BattleDirector/BattleScene.tscn
index 40024205..4e373b4b 100644
--- a/Scenes/BattleDirector/BattleScene.tscn
+++ b/Scenes/BattleDirector/BattleScene.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=11 format=3 uid="uid://b0mrgr7h0ty1y"]
+[gd_scene load_steps=12 format=3 uid="uid://b0mrgr7h0ty1y"]
[ext_resource type="Script" uid="uid://bttu0wmy2fp64" path="res://Scenes/BattleDirector/Scripts/BattleDirector.cs" id="1_jmdo1"]
[ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="2_ka0ws"]
@@ -6,6 +6,7 @@
[ext_resource type="PackedScene" uid="uid://duhiilcv4tat3" path="res://Scenes/BattleDirector/NotePlacementBar.tscn" id="4_qk7om"]
[ext_resource type="PackedScene" uid="uid://dfevfib11kou1" path="res://Scenes/ChartViewport/ChartViewport.tscn" id="5_r2xh0"]
[ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="6_0jtpx"]
+[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="7_6k2qj"]
[ext_resource type="Texture2D" uid="uid://dbjotl0v1ymia" path="res://SharedAssets/BattleFrame1.png" id="7_klvil"]
[ext_resource type="Theme" uid="uid://d37e3tpsbxwak" path="res://Scenes/UI/Assets/GeneralTheme.tres" id="8_62qim"]
@@ -18,9 +19,10 @@ gradient = SubResource("Gradient_8uy3a")
fill_from = Vector2(1, 0)
fill_to = Vector2(0.738532, 1)
-[node name="ProtoBattleDirector" type="Node2D" node_paths=PackedStringArray("PuppetMarkers", "CD", "CM", "NPB", "Audio", "_focusedButton")]
+[node name="ProtoBattleDirector" type="Node2D" node_paths=PackedStringArray("BackgroundRect", "PuppetMarkers", "CD", "CM", "NPB", "Audio", "_focusedButton")]
process_mode = 1
script = ExtResource("1_jmdo1")
+BackgroundRect = NodePath("BackGround")
PuppetMarkers = [NodePath("PlayerMarker"), NodePath("Enemy1Marker"), NodePath("Enemy2Marker"), NodePath("Enemy3Marker")]
CD = NodePath("Conductor")
CM = NodePath("SubViewport")
@@ -73,6 +75,7 @@ z_index = -1
offset_right = 640.0
offset_bottom = 178.0
texture = ExtResource("6_0jtpx")
+script = ExtResource("7_6k2qj")
[node name="BattleFrame" type="TextureRect" parent="."]
z_index = 1
diff --git a/Scenes/ChestScene/ChestScene.tscn b/Scenes/ChestScene/ChestScene.tscn
index 96281b84..8b5f8993 100644
--- a/Scenes/ChestScene/ChestScene.tscn
+++ b/Scenes/ChestScene/ChestScene.tscn
@@ -1,8 +1,9 @@
-[gd_scene load_steps=10 format=3 uid="uid://c4vmb783d3v03"]
+[gd_scene load_steps=11 format=3 uid="uid://c4vmb783d3v03"]
[ext_resource type="Script" uid="uid://cetn71kolbrmg" path="res://Scenes/ChestScene/ChestScene.cs" id="1_ardd2"]
[ext_resource type="AudioStream" uid="uid://be5ial13ynf3o" path="res://Audio/Song1.ogg" id="2_x78jo"]
[ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="3_5uvci"]
+[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="5_u0wcg"]
[ext_resource type="Shader" uid="uid://dp36iuuy414k1" path="res://SharedAssets/StarryNight.gdshader" id="5_whthd"]
[ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="6_37nar"]
[ext_resource type="Texture2D" uid="uid://d0ywqw1j1k71v" path="res://Scenes/ChestScene/Assets/Chest.png" id="6_58hf4"]
@@ -16,11 +17,12 @@ shader_parameter/bg_bottom_color = Vector4(0.028, 0.008, 0.184, 0)
shader_parameter/gradient_ratio = 1.0
shader_parameter/time_scale = 1.0
-[node name="ChestScene" type="Node2D" node_paths=PackedStringArray("ChestButton", "PlayerMarker")]
+[node name="ChestScene" type="Node2D" node_paths=PackedStringArray("ChestButton", "PlayerMarker", "BackgroundRect")]
process_mode = 1
script = ExtResource("1_ardd2")
ChestButton = NodePath("CenterContainer/VBoxContainer/ChestButton")
PlayerMarker = NodePath("PlayerMarker")
+BackgroundRect = NodePath("BackGround")
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
stream = ExtResource("2_x78jo")
@@ -38,6 +40,7 @@ z_index = -1
offset_right = 640.0
offset_bottom = 178.0
texture = ExtResource("6_37nar")
+script = ExtResource("5_u0wcg")
[node name="BattleFrame" type="TextureRect" parent="."]
z_index = 1
diff --git a/Scenes/Maps/Cartographer.tscn b/Scenes/Maps/Cartographer.tscn
index f492aa8e..824eaa96 100644
--- a/Scenes/Maps/Cartographer.tscn
+++ b/Scenes/Maps/Cartographer.tscn
@@ -1,26 +1,38 @@
-[gd_scene load_steps=6 format=3 uid="uid://cydmo2lbnj1de"]
+[gd_scene load_steps=7 format=3 uid="uid://cydmo2lbnj1de"]
[ext_resource type="Script" uid="uid://dtlpiwt4n3pta" path="res://Scenes/Maps/Scripts/Cartographer.cs" id="1_u4q3n"]
[ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="2_5g6at"]
[ext_resource type="Script" uid="uid://pl57giqyhckb" path="res://Scenes/UI/Scripts/MenuModule.cs" id="2_cl7v0"]
[ext_resource type="Theme" uid="uid://bcejp4llrb3m0" path="res://Scenes/UI/Assets/EmptyButton.tres" id="2_rnj1y"]
[ext_resource type="Texture2D" uid="uid://cmc7gcplqnebx" path="res://SharedAssets/Player.png" id="3_qiprp"]
+[ext_resource type="Script" uid="uid://cp6t6haqyef7o" path="res://Scenes/AreaBasedBackground.cs" id="5_taedj"]
-[node name="Cartographer" type="Node2D" node_paths=PackedStringArray("PlayerSprite")]
+[node name="Cartographer" type="Node2D" node_paths=PackedStringArray("BackgroundSprite", "PlayerSprite", "Camera")]
process_mode = 1
script = ExtResource("1_u4q3n")
+BackgroundSprite = NodePath("")
PlayerSprite = NodePath("Player")
ButtonTheme = ExtResource("2_rnj1y")
+Camera = NodePath("TheView")
+
+[node name="TheView" type="Camera2D" parent="."]
+top_level = true
+anchor_mode = 0
+limit_top = -10
[node name="UI" type="CanvasLayer" parent="." node_paths=PackedStringArray("CurSceneNode")]
script = ExtResource("2_cl7v0")
CurSceneNode = NodePath("..")
-[node name="BG" type="Sprite2D" parent="."]
+[node name="BG" type="TextureRect" parent="."]
modulate = Color(0.462, 0.462, 0.66, 1)
-position = Vector2(-10, 229)
+offset_left = -557.0
+offset_top = -84.0
+offset_right = 83.0
+offset_bottom = 96.0
scale = Vector2(3, 3)
texture = ExtResource("2_5g6at")
+script = ExtResource("5_taedj")
[node name="Player" type="Sprite2D" parent="."]
z_index = 2
diff --git a/Scenes/Maps/InBetween.tscn b/Scenes/Maps/InBetween.tscn
new file mode 100644
index 00000000..d425f862
--- /dev/null
+++ b/Scenes/Maps/InBetween.tscn
@@ -0,0 +1,24 @@
+[gd_scene load_steps=4 format=3 uid="uid://djlperv5n75y1"]
+
+[ext_resource type="Texture2D" uid="uid://qhwve7fik4do" path="res://SharedAssets/BackGround_Full.png" id="1_74aj5"]
+[ext_resource type="Theme" uid="uid://d37e3tpsbxwak" path="res://Scenes/UI/Assets/GeneralTheme.tres" id="2_dapxv"]
+[ext_resource type="Script" uid="uid://cahjluc6v7ked" path="res://Scenes/UI/TitleScreen/Scripts/SceneChange.cs" id="3_35xdc"]
+
+[node name="Inbetween" type="Node2D"]
+
+[node name="Sprite2D" type="Sprite2D" parent="."]
+position = Vector2(197, 86)
+rotation = 3.72628
+scale = Vector2(3.81, 3.81)
+texture = ExtResource("1_74aj5")
+
+[node name="Button" type="Button" parent="."]
+offset_left = 263.0
+offset_top = 276.0
+offset_right = 271.0
+offset_bottom = 284.0
+theme = ExtResource("2_dapxv")
+text = "INBETWEEN_CONTINUE"
+script = ExtResource("3_35xdc")
+ScenePath = 5
+_startFocused = true
diff --git a/Scenes/Maps/Scripts/Cartographer.cs b/Scenes/Maps/Scripts/Cartographer.cs
index ae82b875..ebd07533 100644
--- a/Scenes/Maps/Scripts/Cartographer.cs
+++ b/Scenes/Maps/Scripts/Cartographer.cs
@@ -17,6 +17,9 @@ public partial class Cartographer : Node2D
[Export]
public Theme ButtonTheme;
+ [Export]
+ public Camera2D Camera;
+
private Button[] _validButtons = Array.Empty