Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Classes/Relics/Assets/Relic_Auroboros.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_Bandage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_Breakfast.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_Chips.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_Colorboros.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_EnergyDrink.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_GoodVibes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_Medkit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_PaperCut.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Classes/Relics/Assets/Relic_VinylRecord.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions Globals/FunkEngineNameSpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,12 @@ public enum Stages

public enum Rarity
{
Common,
Uncommon,
Rare,
Epic,
Legendary,
Breakfast,
Breakfast = 5,
Common = 4,
Uncommon = 3,
Rare = 2,
Epic = 1,
Legendary = 0,
}
#endregion

Expand Down
127 changes: 111 additions & 16 deletions Globals/Scribe.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System.Collections.Generic;
using System.Linq;
using FunkEngine;
using FunkEngine.Classes.MidiMaestro;
using Godot;

// ReSharper disable UnusedParameter.Local

/**
* Catch all for storing defined data. Catch all as single source of truth for items and battles.
*/
Expand Down Expand Up @@ -353,39 +356,131 @@ public partial class Scribe : Node
),
};

//TODO: Item pool(s)
//Needs to be strictly maintained based on what the player has obtained.
private static List<int>[] _relicRarityPools = null;

public static RelicTemplate[] GetRandomRelics(RelicTemplate[] excludedRelics, int count)
public static void InitRelicPools()
{
var availableRelics = Scribe
.RelicDictionary.Where(r => excludedRelics.All(o => o.Name != r.Name))
.ToArray();
_relicRarityPools = new List<int>[(int)Rarity.Breakfast + 1];
for (int i = 0; i <= (int)Rarity.Breakfast; i++)
{
_relicRarityPools[i] = new List<int>();
}

foreach (RelicTemplate relic in RelicDictionary)
{
_relicRarityPools[(int)relic.Rarity].Add(relic.Id);
}
}

//TODO: Keep sorted by Id for faster binary search.
private static void AddRelicToPool(RelicTemplate relic)
{
if (relic.Rarity == Rarity.Breakfast)
return;
int indexRelic = _relicRarityPools[(int)relic.Rarity].IndexOf(relic.Id);
if (indexRelic == -1)
{
_relicRarityPools[(int)relic.Rarity].Add(relic.Id);
}
}

public static void RemoveRelicFromPool(RelicTemplate relic)
{
if (relic.Rarity == Rarity.Breakfast)
return;
int indexRelic = _relicRarityPools[(int)relic.Rarity].IndexOf(relic.Id);
if (indexRelic == -1)
{
GD.PushWarning(
"Attempting to remove relic " + relic.Id + " from the Relic Pool, not found!"
);
return;
}
_relicRarityPools[(int)relic.Rarity].RemoveAt(indexRelic);
}

/// <summary>
/// Return an array of relics for reward selection.
/// Intended usage of rarity. Player Stats has the rarity distribution. Do rolls in descending order of rarity.
/// Get a relic for the rolled rarity, continue for count.
/// If the relic pool is out of the rolled rarity, be nice to player and give them a relic of higher rarity.
/// Continue through ascending rarities until no new relics are acquirable, then give Breakfast.
/// </summary>
/// <param name="count">Number of relics to generate.</param>
/// <param name="lootOffset">An offset for the loot rng seed.</param>
/// <param name="odds">An array of the int odds out of 100 for each typical rarity (Common through Legendary).</param>
/// <returns></returns>
public static RelicTemplate[] GetRandomRelics(int count, int lootOffset, int[] odds)
{
RelicTemplate[] result = new RelicTemplate[count];

RandomNumberGenerator lootRng = new RandomNumberGenerator();
lootRng.SetSeed(StageProducer.GlobalRng.Seed + (ulong)StageProducer.CurRoom);
lootRng.SetSeed(StageProducer.GlobalRng.Seed + (ulong)lootOffset);

availableRelics = availableRelics
.OrderBy(_ => lootRng.Randi())
.Take(count)
.Select(r => r.Clone())
.ToArray();
for (int i = 0; i < count; i++)
{
Rarity rarity = RollRarities(odds, lootRng);
RelicTemplate relic = H_GetRandomRelic(rarity, lootRng);
result[i] = relic;
}
//Re-add relics back to pools.
foreach (RelicTemplate relic in result)
{
_relicRarityPools[(int)relic.Rarity].Add(relic.Id);
}

return result;
}

for (int i = availableRelics.Length; i < count; i++)
private static Rarity RollRarities(int[] rarityOdds, RandomNumberGenerator rng)
{
int rarityRoll = rng.RandiRange(1, 100);
for (int i = 0; i < rarityOdds.Length; i++)
{
availableRelics = availableRelics.Append(RelicDictionary[0].Clone()).ToArray();
if (rarityRoll < rarityOdds[i])
{
return (Rarity)i;
}
}

return availableRelics;
return Rarity.Common;
}

private static RelicTemplate H_GetRandomRelic(Rarity startingRarity, RandomNumberGenerator rng)
{
int countOfRarity = 0;
Rarity currentRarity = startingRarity;

while (countOfRarity <= 0) //While there are no options of current rarity selected
{
countOfRarity = _relicRarityPools[(int)currentRarity].Count;

if (countOfRarity > 0) //There are relics of a rarity
{ //Select a random relic of rarity.
int relicIndex = rng.RandiRange(0, countOfRarity - 1);
int selectedRelicId = _relicRarityPools[(int)currentRarity][relicIndex];
RelicTemplate result = RelicDictionary[selectedRelicId].Clone();
RemoveRelicFromPool(result); //Prevent same relic being selected in same selection process.
return result;
}

//Rotate through, in increasing rarity. Technically right now it will go Legendary -> Common before Uncommon, this is ok for now, but should be noted.
currentRarity = (Rarity)Mathf.PosMod((int)(currentRarity - 1), (int)Rarity.Breakfast);
if (currentRarity == startingRarity)
countOfRarity = 1; //Gone through all rarities, found no valid relic, exit loop to throw Breakfast.
}
return RelicDictionary[0].Clone();
}

public static Note[] GetRandomRewardNotes(int count)
public static Note[] GetRandomRewardNotes(int count, int lootOffset)
{
var availableNotes = Scribe
.NoteDictionary.Where(r => r.Name.Contains("Player")) //TODO: Classifications/pools
.ToArray();

RandomNumberGenerator lootRng = new RandomNumberGenerator();
lootRng.SetSeed(StageProducer.GlobalRng.Seed + (ulong)StageProducer.CurRoom);
lootRng.SetSeed(StageProducer.GlobalRng.Seed + (ulong)lootOffset);

availableNotes = availableNotes
.OrderBy(_ => lootRng.Randi())
Expand Down
5 changes: 4 additions & 1 deletion Globals/StageProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ private void StartNewGame()
PlayerStats = new PlayerStats();

CurRoom = Map.GetRooms()[0].Idx;
Scribe.InitRelicPools();
IsInitialized = true;
}

Expand All @@ -80,8 +81,10 @@ private bool LoadGame()
GlobalRng.State = sv.RngState;
CurRoom = sv.LastRoomIdx;

Scribe.InitRelicPools();

PlayerStats = new PlayerStats();
PlayerStats.CurNotes = Array.Empty<Note>();
PlayerStats.CurNotes = [];
foreach (int noteId in sv.NoteIds)
{
PlayerStats.AddNote(Scribe.NoteDictionary[noteId]);
Expand Down
1 change: 1 addition & 0 deletions Globals/Translations/Translations.csv
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ESCAPE_MENU_TITLE,Quit to Title,返回标题
CHEST_ROOM_REWARDS,Reward Selection!,奖励!
CHEST_ROOM_SKIP,Skip,跳过
CHEST_ROOM_ACCEPT,Accept,接受
CHEST_ROOM_REROLL,Rerolls: ,重刷:
BATTLE_ROOM_BEGIN_BUTTON,"Begin Battle [Enter]","开始战斗 [Enter]"
BATTLE_ROOM_PERFECT,Perfect,精准
BATTLE_ROOM_GOOD,Good,良好
Expand Down
2 changes: 1 addition & 1 deletion Scenes/BattleDirector/NotePoofParticles.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ scale_curve = SubResource("CurveTexture_h7u0t")
[node name="NotePoof" type="GPUParticles2D"]
emitting = false
amount = 10
process_material = SubResource("ParticleProcessMaterial_k0qar")
texture = ExtResource("1_hjrch")
lifetime = 0.75
one_shot = true
preprocess = 0.1
explosiveness = 1.0
process_material = SubResource("ParticleProcessMaterial_k0qar")
6 changes: 3 additions & 3 deletions Scenes/ChartViewport/ChartViewport.tscn
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[gd_scene load_steps=7 format=3 uid="uid://dfevfib11kou1"]

[ext_resource type="Script" path="res://Scenes/ChartViewport/Scripts/ChartManager.cs" id="1_ruh2l"]
[ext_resource type="Script" uid="uid://btgmfxqoe2wqx" path="res://Scenes/ChartViewport/Scripts/ChartManager.cs" id="1_ruh2l"]
[ext_resource type="Texture2D" uid="uid://cp78odda2doab" path="res://Scenes/ChartViewport/LoopMarker.png" id="2_q5cjc"]
[ext_resource type="Script" path="res://Scenes/ChartViewport/Scripts/Loopable.cs" id="3_5u57h"]
[ext_resource type="Script" uid="uid://cf58ep1c2o0q2" path="res://Scenes/ChartViewport/Scripts/Loopable.cs" id="3_5u57h"]
[ext_resource type="PackedScene" uid="uid://bn8txx53xlguw" path="res://Scenes/NoteManager/NoteManager.tscn" id="4_fd5fw"]
[ext_resource type="Shader" path="res://SharedAssets/StarryNight.gdshader" id="5_kqrxg"]
[ext_resource type="Shader" uid="uid://dp36iuuy414k1" path="res://SharedAssets/StarryNight.gdshader" id="5_kqrxg"]

[sub_resource type="ShaderMaterial" id="ShaderMaterial_5uw0y"]
shader = ExtResource("5_kqrxg")
Expand Down
2 changes: 1 addition & 1 deletion Scenes/ChartViewport/HitParticles.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://bcf6vs4aqoxr5"]

[ext_resource type="Script" path="res://Scenes/ChartViewport/Scripts/HitParticles.cs" id="1_7gkj5"]
[ext_resource type="Script" uid="uid://bjj3132iu8lrc" path="res://Scenes/ChartViewport/Scripts/HitParticles.cs" id="1_7gkj5"]

[node name="HitParticles" type="CPUParticles2D"]
z_index = -1
Expand Down
2 changes: 1 addition & 1 deletion Scenes/NoteManager/HoldArrow.tscn
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://b3owchvgq1l87"]

[ext_resource type="Texture2D" uid="uid://hfxynr5jdgsp" path="res://Scenes/NoteManager/Assets/New_Arrow.png" id="1_nn8ao"]
[ext_resource type="Script" path="res://Scenes/NoteManager/Scripts/HoldArrow.cs" id="2_hehcu"]
[ext_resource type="Script" uid="uid://ci5tt447bivmk" path="res://Scenes/NoteManager/Scripts/HoldArrow.cs" id="2_hehcu"]
[ext_resource type="Texture2D" uid="uid://cgq2ar3pdmkac" path="res://Scenes/NoteManager/Assets/Arrow_Outline.png" id="3_pvvea"]
[ext_resource type="Texture2D" uid="uid://dbnvl0gbhl5b4" path="res://Scenes/NoteManager/Assets/Arrow_Trail.png" id="4_xgcwb"]

Expand Down
2 changes: 1 addition & 1 deletion Scenes/NoteManager/NoteArrow.tscn
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://ck3bfqy30rjbq"]

[ext_resource type="Texture2D" uid="uid://hfxynr5jdgsp" path="res://Scenes/NoteManager/Assets/New_Arrow.png" id="1_wq1hy"]
[ext_resource type="Script" path="res://Scenes/NoteManager/Scripts/NoteArrow.cs" id="2_lbl4b"]
[ext_resource type="Script" uid="uid://cfdthf532wby7" path="res://Scenes/NoteManager/Scripts/NoteArrow.cs" id="2_lbl4b"]
[ext_resource type="Texture2D" uid="uid://cgq2ar3pdmkac" path="res://Scenes/NoteManager/Assets/Arrow_Outline.png" id="3_5g4ja"]

[node name="Right-arrow" type="Sprite2D" node_paths=PackedStringArray("OutlineSprite", "IconSprite")]
Expand Down
4 changes: 2 additions & 2 deletions Scenes/NoteManager/NoteManager.tscn
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[gd_scene load_steps=7 format=3 uid="uid://bn8txx53xlguw"]

[ext_resource type="Script" path="res://Scenes/NoteManager/Scripts/InputHandler.cs" id="1_2oeuf"]
[ext_resource type="Script" uid="uid://bok6bnyemsgck" path="res://Scenes/NoteManager/Scripts/InputHandler.cs" id="1_2oeuf"]
[ext_resource type="Texture2D" uid="uid://hfxynr5jdgsp" path="res://Scenes/NoteManager/Assets/New_Arrow.png" id="2_pb1qk"]
[ext_resource type="Script" path="res://Scenes/NoteManager/Scripts/NoteChecker.cs" id="3_0cioe"]
[ext_resource type="Script" uid="uid://coukobemtvmah" path="res://Scenes/NoteManager/Scripts/NoteChecker.cs" id="3_0cioe"]
[ext_resource type="Texture2D" uid="uid://cgq2ar3pdmkac" path="res://Scenes/NoteManager/Assets/Arrow_Outline.png" id="4_3mttx"]
[ext_resource type="Texture2D" uid="uid://b0tvsewgnf2x7" path="res://icon.svg" id="4_foklt"]
[ext_resource type="PackedScene" uid="uid://bcf6vs4aqoxr5" path="res://Scenes/ChartViewport/HitParticles.tscn" id="5_jv1tr"]
Expand Down
6 changes: 6 additions & 0 deletions Scenes/Puppets/Scripts/PlayerStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ public partial class PlayerStats : Resource
public int MaxHealth = 100;
public int CurrentHealth = 100;
public int MaxComboBar = 80;
public int RewardAmountModifier = 0;
public int Rerolls = 0;

//Array in order of descending rarities, Legendary -> ... Common. Int odds out of 100.
public int[] RarityOdds = [1, 5, 10, 20, 100];
public Note[] CurNotes = new Note[]
{
Scribe.NoteDictionary[1].Clone(),
Expand All @@ -29,6 +34,7 @@ public void AddRelic(RelicTemplate relic)
}
}
CurRelics = CurRelics.Append(relic).ToArray();
Scribe.RemoveRelicFromPool(relic);
}

public void AddNote(Note nSelection)
Expand Down
15 changes: 12 additions & 3 deletions Scenes/UI/RewardSelectionUI.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
[ext_resource type="Theme" uid="uid://d37e3tpsbxwak" path="res://Scenes/UI/Assets/GeneralTheme.tres" id="4_gfac6"]
[ext_resource type="Texture2D" uid="uid://burj10os057fx" path="res://Scenes/UI/Assets/UI_CrystalFrameInset.png" id="4_gufce"]

[node name="CanvasLayer" type="CanvasLayer" node_paths=PackedStringArray("ButtonContainer", "_description", "_acceptButton", "_skipButton")]
[node name="CanvasLayer" type="CanvasLayer" node_paths=PackedStringArray("ButtonContainer", "_description", "_acceptButton", "_skipButton", "_rerollButton")]
process_mode = 3
script = ExtResource("1_1m6an")
ButtonContainer = NodePath("MarginContainer/PanelContainer/VBoxContainer/ScrollContainer/CenterContainer/HBoxContainer")
ButtonContainer = NodePath("MarginContainer/PanelContainer/VBoxContainer/ScrollContainer/CenterContainer/SelectionButtonContainer")
_description = NodePath("MarginContainer/PanelContainer/VBoxContainer/DescBox/DescMargin/Description")
_acceptButton = NodePath("MarginContainer/PanelContainer/VBoxContainer/MarginContainer/HBoxContainer/AcceptButton")
_skipButton = NodePath("MarginContainer/PanelContainer/VBoxContainer/MarginContainer/HBoxContainer/SkipButton")
_rerollButton = NodePath("MarginContainer/PanelContainer/VBoxContainer/MarginContainer/HBoxContainer/RerollButton")

[node name="Background" type="NinePatchRect" parent="."]
self_modulate = Color(1, 1, 1, 0.75)
Expand Down Expand Up @@ -70,6 +71,7 @@ horizontal_alignment = 1
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/PanelContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
follow_focus = true

[node name="CenterContainer" type="CenterContainer" parent="MarginContainer/PanelContainer/VBoxContainer/ScrollContainer"]
layout_mode = 2
Expand All @@ -88,7 +90,7 @@ patch_margin_top = 6
patch_margin_right = 6
patch_margin_bottom = 7

[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/PanelContainer/VBoxContainer/ScrollContainer/CenterContainer"]
[node name="SelectionButtonContainer" type="HBoxContainer" parent="MarginContainer/PanelContainer/VBoxContainer/ScrollContainer/CenterContainer"]
layout_mode = 2
size_flags_vertical = 3

Expand Down Expand Up @@ -131,6 +133,13 @@ theme_override_constants/margin_bottom = 8
layout_mode = 2
size_flags_vertical = 3

[node name="RerollButton" type="Button" parent="MarginContainer/PanelContainer/VBoxContainer/MarginContainer/HBoxContainer"]
visible = false
layout_mode = 2
size_flags_horizontal = 3
theme = ExtResource("4_gfac6")
text = "CHEST_ROOM_REROLL"

[node name="SkipButton" type="Button" parent="MarginContainer/PanelContainer/VBoxContainer/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
Expand Down
Loading