Implement Vendor NPCs (#37)
* Add WIP vendors * Add TimerExtensions * chore: Update dialogue manager version * Add Inventory.EquippedItem signal * Move files to UI.Inventory namespace * Modify Hotbar and InventorySlot organization Made InventorySlot a bit more modular. * Modify hotbar icons * Implement request to display shop * Add forsenLevel placeholder icon * Add shop UI * Update UI to use theme and click through * Update item metadata Added placeholder icons for items without an icon. * Add Snus Dealer example vendor NPC * Implement factions with bitflags instead * Fix typo in Doc dialogue * Hide and show shop menu * Add shaders * Add newline to console output * Add modal interfacepull/36/merge
parent
516d79d86f
commit
b8a5e641b6
|
@ -1,6 +1,6 @@
|
||||||
[remap]
|
[remap]
|
||||||
|
|
||||||
importer="dialogue_manager_compiler_11"
|
importer="dialogue_manager_compiler_12"
|
||||||
type="Resource"
|
type="Resource"
|
||||||
uid="uid://dilmuoilweoeh"
|
uid="uid://dilmuoilweoeh"
|
||||||
path="res://.godot/imported/books.dialogue-cc272ebae322ae3ca46820dca11a3437.tres"
|
path="res://.godot/imported/books.dialogue-cc272ebae322ae3ca46820dca11a3437.tres"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[remap]
|
[remap]
|
||||||
|
|
||||||
importer="dialogue_manager_compiler_11"
|
importer="dialogue_manager_compiler_12"
|
||||||
type="Resource"
|
type="Resource"
|
||||||
uid="uid://c2om4y0fm81yr"
|
uid="uid://c2om4y0fm81yr"
|
||||||
path="res://.godot/imported/clone-machine.dialogue-8810934a67eacdad52469e9ef5f970fb.tres"
|
path="res://.godot/imported/clone-machine.dialogue-8810934a67eacdad52469e9ef5f970fb.tres"
|
||||||
|
|
|
@ -18,11 +18,10 @@ Doc, The Two Time: Nothing but success.
|
||||||
Doc, The Two Time: That's what my life's about. Period.
|
Doc, The Two Time: That's what my life's about. Period.
|
||||||
Doc, The Two Time: And the arena today, ladies and gentlemen...
|
Doc, The Two Time: And the arena today, ladies and gentlemen...
|
||||||
Doc, The Two Time: is wide open, and the crowds are flooding in. VIP seating. Skybox section. Reserved for the Slick Daddy Club.
|
Doc, The Two Time: is wide open, and the crowds are flooding in. VIP seating. Skybox section. Reserved for the Slick Daddy Club.
|
||||||
Doc, The Two Time: The Slick Daddy Club lofoking so damn good today. I'm feeling so damn good. It's obvious.
|
Doc, The Two Time: The Slick Daddy Club looking so damn good today. I'm feeling so damn good. It's obvious.
|
||||||
Doc, The Two Time: The V of success.
|
|
||||||
Challenge [b]Doc, The Two Time[/b] to a duel?
|
Challenge [b]Doc, The Two Time[/b] to a duel?
|
||||||
- Yes
|
- Yes
|
||||||
do emit("SummonBoss", "Doc")
|
do emit("SummonBoss", "Doc")
|
||||||
- No => END
|
- No, I'm a little chubby cheek wannabe punk kid. => END
|
||||||
|
|
||||||
=> END
|
=> END
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[remap]
|
[remap]
|
||||||
|
|
||||||
importer="dialogue_manager_compiler_11"
|
importer="dialogue_manager_compiler_12"
|
||||||
type="Resource"
|
type="Resource"
|
||||||
uid="uid://dntkvjjr8mrgf"
|
uid="uid://dntkvjjr8mrgf"
|
||||||
path="res://.godot/imported/doc.dialogue-8f95f6a09d3ac685b71d7e07c49df1c6.tres"
|
path="res://.godot/imported/doc.dialogue-8f95f6a09d3ac685b71d7e07c49df1c6.tres"
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 189 B |
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dc1gcsbhkchvg"
|
||||||
|
path="res://.godot/imported/hotbar-active.png-7657e1b4001be05323aa0d0697509f58.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Sprites/UI/hotbar-active.png"
|
||||||
|
dest_files=["res://.godot/imported/hotbar-active.png-7657e1b4001be05323aa0d0697509f58.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 153 B |
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 832 B |
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://uhmowtsi3wfh"
|
||||||
|
path="res://.godot/imported/menu-rect-no-bg-white.png-5ea2d275879af97991070fb370031211.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Sprites/UI/menu-rect-no-bg-white.png"
|
||||||
|
dest_files=["res://.godot/imported/menu-rect-no-bg-white.png-5ea2d275879af97991070fb370031211.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 579 B |
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://vjdyrv8wp7gl"
|
||||||
|
path="res://.godot/imported/forsenLevel.png-ffd03264deccb9275d087fadbb57e56f.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Sprites/forsenLevel.png"
|
||||||
|
dest_files=["res://.godot/imported/forsenLevel.png-ffd03264deccb9275d087fadbb57e56f.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
|
@ -5,6 +5,6 @@ namespace SupaLidlGame.BoundingBoxes;
|
||||||
|
|
||||||
public abstract partial class BoundingBox : Area2D, IFaction
|
public abstract partial class BoundingBox : Area2D, IFaction
|
||||||
{
|
{
|
||||||
[Export]
|
[Export(PropertyHint.Flags)]
|
||||||
public ushort Faction { get; set; }
|
public FactionName Faction { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,8 +93,8 @@ public partial class Character : CharacterBody2D, IFaction
|
||||||
[Export]
|
[Export]
|
||||||
public BoundingBoxes.Hurtbox Hurtbox { get; set; }
|
public BoundingBoxes.Hurtbox Hurtbox { get; set; }
|
||||||
|
|
||||||
[Export]
|
[Export(PropertyHint.Flags)]
|
||||||
public ushort Faction { get; set; }
|
public FactionName Faction { get; set; }
|
||||||
|
|
||||||
public AnimationPlayer MovementAnimation { get; set; }
|
public AnimationPlayer MovementAnimation { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -573,6 +573,7 @@ Sprite = NodePath("Sprite")
|
||||||
Inventory = NodePath("Inventory")
|
Inventory = NodePath("Inventory")
|
||||||
StateMachine = NodePath("StateMachine")
|
StateMachine = NodePath("StateMachine")
|
||||||
Hurtbox = NodePath("Hurtbox")
|
Hurtbox = NodePath("Hurtbox")
|
||||||
|
Faction = 2
|
||||||
|
|
||||||
[node name="Stats" type="Node" parent="."]
|
[node name="Stats" type="Node" parent="."]
|
||||||
script = ExtResource("5_a7fiw")
|
script = ExtResource("5_a7fiw")
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using SupaLidlGame.Extensions;
|
using SupaLidlGame.Extensions;
|
||||||
using SupaLidlGame.Items;
|
using SupaLidlGame.Items;
|
||||||
|
using SupaLidlGame.Utils;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace SupaLidlGame.Characters;
|
namespace SupaLidlGame.Characters;
|
||||||
|
@ -127,6 +128,37 @@ public partial class NPC : Character
|
||||||
return bestChar;
|
return bestChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the best character whose faction aligns with this character's.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Character FindBestNeutral()
|
||||||
|
{
|
||||||
|
float bestScore = float.MaxValue;
|
||||||
|
Character bestChar = null;
|
||||||
|
// NOTE: this relies on all Characters being under the Entities node
|
||||||
|
foreach (Node node in GetParent().GetChildren())
|
||||||
|
{
|
||||||
|
if (node is Character character)
|
||||||
|
{
|
||||||
|
bool isFriendly = ((IFaction)this).AlignsWith(character);
|
||||||
|
if (isFriendly || character.Health <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float score = 0;
|
||||||
|
score -= Position.DistanceTo(character.Position);
|
||||||
|
|
||||||
|
if (score < bestScore)
|
||||||
|
{
|
||||||
|
bestScore = score;
|
||||||
|
bestChar = character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestChar;
|
||||||
|
}
|
||||||
|
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
ThinkerStateMachine.Process(delta);
|
ThinkerStateMachine.Process(delta);
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
[gd_scene load_steps=11 format=3 uid="uid://rd08pot25h00"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://Characters/NPC.cs" id="1_04gcf"]
|
||||||
|
[ext_resource type="Script" path="res://State/Character/CharacterStateMachine.cs" id="2_kynkg"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bej8thq7ruyty" path="res://Assets/Sprites/Characters/forsen2.png" id="2_s5nik"]
|
||||||
|
[ext_resource type="Script" path="res://State/Character/NPCIdleState.cs" id="3_pcrll"]
|
||||||
|
[ext_resource type="Script" path="res://State/Thinker/ThinkerStateMachine.cs" id="4_mo4wj"]
|
||||||
|
[ext_resource type="Script" path="res://State/Thinker/VendorIdle.cs" id="5_oau5d"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dldnp8eunxj3q" path="res://BoundingBoxes/InteractionTrigger.tscn" id="5_sjs24"]
|
||||||
|
[ext_resource type="Script" path="res://Utils/InteractionTriggerDialogue.cs" id="5_yknpw"]
|
||||||
|
[ext_resource type="Resource" uid="uid://c4n7vhoxybu70" path="res://Dialogue/snus-dealer.dialogue" id="6_isvnq"]
|
||||||
|
[ext_resource type="Script" path="res://Items/Inventory.cs" id="7_vip6b"]
|
||||||
|
|
||||||
|
[node name="SnusDealer" type="CharacterBody2D" node_paths=PackedStringArray("ThinkerStateMachine", "Sprite", "Inventory", "StateMachine")]
|
||||||
|
script = ExtResource("1_04gcf")
|
||||||
|
ThinkerStateMachine = NodePath("Thinker")
|
||||||
|
Sprite = NodePath("Sprites/Sprite")
|
||||||
|
Inventory = NodePath("Inventory")
|
||||||
|
StateMachine = NodePath("StateMachine")
|
||||||
|
|
||||||
|
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")]
|
||||||
|
script = ExtResource("2_kynkg")
|
||||||
|
InitialState = NodePath("Idle")
|
||||||
|
Character = NodePath("..")
|
||||||
|
|
||||||
|
[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("Character")]
|
||||||
|
script = ExtResource("3_pcrll")
|
||||||
|
Character = NodePath("../..")
|
||||||
|
|
||||||
|
[node name="Thinker" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
||||||
|
script = ExtResource("4_mo4wj")
|
||||||
|
InitialState = NodePath("Idle")
|
||||||
|
|
||||||
|
[node name="Idle" type="Node" parent="Thinker" node_paths=PackedStringArray("NPC")]
|
||||||
|
script = ExtResource("5_oau5d")
|
||||||
|
NPC = NodePath("../..")
|
||||||
|
|
||||||
|
[node name="Animations" type="Node" parent="."]
|
||||||
|
|
||||||
|
[node name="Movement" type="AnimationPlayer" parent="Animations"]
|
||||||
|
|
||||||
|
[node name="Hurt" type="AnimationPlayer" parent="Animations"]
|
||||||
|
|
||||||
|
[node name="Stun" type="AnimationPlayer" parent="Animations"]
|
||||||
|
|
||||||
|
[node name="Attack" type="AnimationPlayer" parent="Animations"]
|
||||||
|
|
||||||
|
[node name="Stats" type="Node" parent="."]
|
||||||
|
|
||||||
|
[node name="Sprites" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Sprite" type="Sprite2D" parent="Sprites"]
|
||||||
|
texture = ExtResource("2_s5nik")
|
||||||
|
centered = false
|
||||||
|
offset = Vector2(-12, -20)
|
||||||
|
hframes = 46
|
||||||
|
|
||||||
|
[node name="Inventory" type="Node2D" parent="." node_paths=PackedStringArray("Hotbar")]
|
||||||
|
script = ExtResource("7_vip6b")
|
||||||
|
Hotbar = []
|
||||||
|
|
||||||
|
[node name="Interaction" type="Node2D" parent="." node_paths=PackedStringArray("InteractionTrigger")]
|
||||||
|
position = Vector2(0, -4)
|
||||||
|
script = ExtResource("5_yknpw")
|
||||||
|
InteractionTrigger = NodePath("InteractionTrigger")
|
||||||
|
DialogueResource = ExtResource("6_isvnq")
|
||||||
|
DialogueTitle = "start"
|
||||||
|
|
||||||
|
[node name="InteractionTrigger" parent="Interaction" instance=ExtResource("5_sjs24")]
|
||||||
|
|
||||||
|
[node name="Label" parent="Interaction/InteractionTrigger/Popup" index="0"]
|
||||||
|
text = "Listen"
|
||||||
|
|
||||||
|
[editable path="Interaction/InteractionTrigger"]
|
|
@ -0,0 +1,27 @@
|
||||||
|
//using Godot;
|
||||||
|
//using SupaLidlGame.BoundingBoxes;
|
||||||
|
//using SupaLidlGame.Extensions;
|
||||||
|
//
|
||||||
|
//namespace SupaLidlGame.Characters;
|
||||||
|
//
|
||||||
|
//public partial class Vendor : NPC
|
||||||
|
//{
|
||||||
|
// [Export]
|
||||||
|
// public InteractionTrigger InteractionTrigger { get; set; }
|
||||||
|
//
|
||||||
|
// [Export(PropertyHint.File, "*.dialogue")]
|
||||||
|
// public Resource DialogueResource { get; set; }
|
||||||
|
//
|
||||||
|
// [Export]
|
||||||
|
// public string DialogueTitle { get; set; }
|
||||||
|
//
|
||||||
|
// public override void _Ready()
|
||||||
|
// {
|
||||||
|
// InteractionTrigger.Interaction += OnInteraction;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void OnInteraction()
|
||||||
|
// {
|
||||||
|
// this.GetWorld().DialogueBalloon.Start(DialogueResource, DialogueTitle);
|
||||||
|
// }
|
||||||
|
//}
|
|
@ -34,6 +34,8 @@ public sealed partial class DebugConsole : Control
|
||||||
|
|
||||||
private Node ctx => Context;
|
private Node ctx => Context;
|
||||||
|
|
||||||
|
public const double DEBUG_REFRESH_INTERVAL = 0.25;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_entry = GetNode<Entry>("%Entry");
|
_entry = GetNode<Entry>("%Entry");
|
||||||
|
@ -61,6 +63,39 @@ public sealed partial class DebugConsole : Control
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GD.Print("DebugConsole init");
|
||||||
|
// TODO: put this in a separate class
|
||||||
|
// watch godot.log
|
||||||
|
bool isFileLoggingEnabled = ProjectSettings
|
||||||
|
.GetSetting("debug/file_logging/enable_file_logging.pc")
|
||||||
|
.AsBool();
|
||||||
|
|
||||||
|
if (isFileLoggingEnabled)
|
||||||
|
{
|
||||||
|
GD.Print("File logging is enabled.");
|
||||||
|
string logPath = ProjectSettings
|
||||||
|
.GetSetting("debug/file_logging/log_path")
|
||||||
|
.AsString();
|
||||||
|
var fs = FileAccess.Open(logPath, FileAccess.ModeFlags.Read);
|
||||||
|
|
||||||
|
var timer = new Timer();
|
||||||
|
AddChild(timer);
|
||||||
|
timer.Timeout += () =>
|
||||||
|
{
|
||||||
|
// push
|
||||||
|
while (fs.GetPosition() < fs.GetLength())
|
||||||
|
{
|
||||||
|
string line = fs.GetLine();
|
||||||
|
_output.Text += line + "\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timer.Start(DEBUG_REFRESH_INTERVAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GD.PushWarning("File logging is not enabled.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<NodePathToken> SplitPath(NodePath path)
|
public IEnumerable<NodePathToken> SplitPath(NodePath path)
|
||||||
|
@ -209,13 +244,21 @@ public sealed partial class DebugConsole : Control
|
||||||
|
|
||||||
Godot.Expression exp = new();
|
Godot.Expression exp = new();
|
||||||
|
|
||||||
string[] reserved = { "from", "set_context", "context", "set_prop", "to_node_path" };
|
string[] reserved = {
|
||||||
|
"from",
|
||||||
|
"set_context",
|
||||||
|
"context",
|
||||||
|
"set_prop",
|
||||||
|
"to_node_path",
|
||||||
|
"load",
|
||||||
|
};
|
||||||
Godot.Collections.Array reservedMap = new();
|
Godot.Collections.Array reservedMap = new();
|
||||||
reservedMap.Add(new Callable(this, MethodName.From));
|
reservedMap.Add(new Callable(this, MethodName.From));
|
||||||
reservedMap.Add(new Callable(this, MethodName.SetContext));
|
reservedMap.Add(new Callable(this, MethodName.SetContext));
|
||||||
reservedMap.Add(Context);
|
reservedMap.Add(Context);
|
||||||
reservedMap.Add(new Callable(this, MethodName.SetProp));
|
reservedMap.Add(new Callable(this, MethodName.SetProp));
|
||||||
reservedMap.Add(new Callable(this, MethodName.ToNodePath));
|
reservedMap.Add(new Callable(this, MethodName.ToNodePath));
|
||||||
|
reservedMap.Add(new Callable(this, MethodName.Load));
|
||||||
|
|
||||||
var err = exp.Parse(str, reserved);
|
var err = exp.Parse(str, reserved);
|
||||||
if (err != Error.Ok)
|
if (err != Error.Ok)
|
||||||
|
@ -246,4 +289,9 @@ public sealed partial class DebugConsole : Control
|
||||||
{
|
{
|
||||||
Context = node;
|
Context = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Resource Load(string path)
|
||||||
|
{
|
||||||
|
return ResourceLoader.Load(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
~ start
|
||||||
|
|
||||||
|
Snus Dealer: Hey kid, wanna buy some snus?
|
||||||
|
- Alright. => shop
|
||||||
|
- No, I don't think so. => END
|
||||||
|
- Snus? => dont_snus
|
||||||
|
|
||||||
|
=> END
|
||||||
|
|
||||||
|
~ dont_snus
|
||||||
|
|
||||||
|
Snus Dealer: You know what they say.
|
||||||
|
Snus Dealer: If you don't snus...
|
||||||
|
Snus Dealer: you lose.
|
||||||
|
- Pepepains
|
||||||
|
|
||||||
|
=> start
|
||||||
|
|
||||||
|
~ shop
|
||||||
|
|
||||||
|
do emit("EnterShop", "res://Items/Shops/SnusDealer.tres")
|
||||||
|
|
||||||
|
=> END
|
|
@ -0,0 +1,15 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="dialogue_manager_compiler_12"
|
||||||
|
type="Resource"
|
||||||
|
uid="uid://c4n7vhoxybu70"
|
||||||
|
path="res://.godot/imported/snus-dealer.dialogue-69dbddee28632f18888364bae03f393d.tres"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Dialogue/snus-dealer.dialogue"
|
||||||
|
dest_files=["res://.godot/imported/snus-dealer.dialogue-69dbddee28632f18888364bae03f393d.tres"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
defaults=true
|
|
@ -58,7 +58,7 @@ public partial class DynamicDoor : StaticBody2D
|
||||||
foreach (var navmesh in Rebake)
|
foreach (var navmesh in Rebake)
|
||||||
{
|
{
|
||||||
// rebake navmesh so NPCs can correctly travel conditionally
|
// rebake navmesh so NPCs can correctly travel conditionally
|
||||||
GD.Print("rebaking");
|
GD.Print("Dynamic door updated; rebaking navmeshes...");
|
||||||
navmesh.BakeNavigationPolygon();
|
navmesh.BakeNavigationPolygon();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,12 +102,12 @@ y_sort_enabled = true
|
||||||
texture_filter = 1
|
texture_filter = 1
|
||||||
sprite_frames = SubResource("SpriteFrames_gf7ku")
|
sprite_frames = SubResource("SpriteFrames_gf7ku")
|
||||||
autoplay = "default"
|
autoplay = "default"
|
||||||
frame = 6
|
frame = 9
|
||||||
frame_progress = 0.743234
|
frame_progress = 0.966501
|
||||||
offset = Vector2(0, -12)
|
offset = Vector2(0, -12)
|
||||||
|
|
||||||
[node name="PointLight2D" type="PointLight2D" parent="."]
|
[node name="PointLight2D" type="PointLight2D" parent="."]
|
||||||
color = Color(1, 0.9525, 0.85, 1)
|
color = Color(1, 0.811765, 0.537255, 1)
|
||||||
energy = 1.2
|
energy = 1.2
|
||||||
blend_mode = 2
|
blend_mode = 2
|
||||||
shadow_filter_smooth = 3.0
|
shadow_filter_smooth = 3.0
|
||||||
|
|
|
@ -51,6 +51,9 @@ public partial class EventBus : Node
|
||||||
[Signal]
|
[Signal]
|
||||||
public delegate void ExitTransitionEventHandler();
|
public delegate void ExitTransitionEventHandler();
|
||||||
|
|
||||||
|
[Signal]
|
||||||
|
public delegate void EnterShopEventHandler(string shopResourcePath);
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
ProcessMode = ProcessModeEnum.Always;
|
ProcessMode = ProcessModeEnum.Always;
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.Extensions;
|
||||||
|
|
||||||
|
public static class TimerExtensions
|
||||||
|
{
|
||||||
|
public static void Restart(this Timer timer, double timeSec = -1)
|
||||||
|
{
|
||||||
|
timer.Stop();
|
||||||
|
timer.Start(timeSec);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace SupaLidlGame.Items;
|
||||||
|
|
||||||
|
public interface IItemCollection
|
||||||
|
{
|
||||||
|
public System.Collections.Generic.IEnumerable<ItemMetadata> GetItems();
|
||||||
|
|
||||||
|
public int Capacity { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IItemCollection<T> : IItemCollection
|
||||||
|
{
|
||||||
|
public bool Add(T item);
|
||||||
|
|
||||||
|
public bool Remove(T item);
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ using Godot.Collections;
|
||||||
|
|
||||||
namespace SupaLidlGame.Items;
|
namespace SupaLidlGame.Items;
|
||||||
|
|
||||||
public partial class Inventory : Node2D
|
public partial class Inventory : Node2D, IItemCollection<ItemMetadata>
|
||||||
{
|
{
|
||||||
public Character Character { get; private set; }
|
public Character Character { get; private set; }
|
||||||
|
|
||||||
|
@ -20,7 +20,15 @@ public partial class Inventory : Node2D
|
||||||
[Signal]
|
[Signal]
|
||||||
public delegate void UsedItemEventHandler(Item item);
|
public delegate void UsedItemEventHandler(Item item);
|
||||||
|
|
||||||
public const int MaxCapacity = 3;
|
[Signal]
|
||||||
|
public delegate void EquippedItemEventHandler(Item newItem, Item prevItem);
|
||||||
|
|
||||||
|
[Signal]
|
||||||
|
public delegate void ItemAddedEventHandler(ItemMetadata newItemMetadata);
|
||||||
|
|
||||||
|
public int Capacity { get; set; } = 30;
|
||||||
|
|
||||||
|
public const int HotbarCapacity = 3;
|
||||||
|
|
||||||
private Item _selectedItem;
|
private Item _selectedItem;
|
||||||
|
|
||||||
|
@ -87,7 +95,8 @@ public partial class Inventory : Node2D
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectedItem?.Unequip(Character);
|
Item prevItem = _selectedItem;
|
||||||
|
prevItem?.Unequip(Character);
|
||||||
_selectedIndex = index;
|
_selectedIndex = index;
|
||||||
|
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
|
@ -100,6 +109,8 @@ public partial class Inventory : Node2D
|
||||||
_selectedItem = null;
|
_selectedItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmitSignal(SignalName.EquippedItem, prevItem, _selectedItem);
|
||||||
|
|
||||||
GD.Print($"Inventory: {index} is new selected index.");
|
GD.Print($"Inventory: {index} is new selected index.");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -135,8 +146,9 @@ public partial class Inventory : Node2D
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item AddItemToHotbar(ItemMetadata metadata)
|
public Item AddToHotbar(ItemMetadata metadata)
|
||||||
{
|
{
|
||||||
|
//AddItemMetadata(metadata);
|
||||||
var item = metadata.Instance.Instantiate<Item>();
|
var item = metadata.Instance.Instantiate<Item>();
|
||||||
AddItem(item);
|
AddItem(item);
|
||||||
AddChild(item);
|
AddChild(item);
|
||||||
|
@ -146,7 +158,7 @@ public partial class Inventory : Node2D
|
||||||
|
|
||||||
public Item AddItem(Item item)
|
public Item AddItem(Item item)
|
||||||
{
|
{
|
||||||
if (Hotbar.Count >= MaxCapacity)
|
if (Hotbar.Count >= HotbarCapacity)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -157,9 +169,32 @@ public partial class Inventory : Node2D
|
||||||
{
|
{
|
||||||
Hotbar.Add(item);
|
Hotbar.Add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public System.Collections.Generic.IEnumerable<ItemMetadata> GetItems()
|
||||||
|
{
|
||||||
|
return Items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Add(ItemMetadata item)
|
||||||
|
{
|
||||||
|
if (Items.Count >= Capacity)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Items.Add(item);
|
||||||
|
EmitSignal(SignalName.ItemAdded, item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(ItemMetadata item)
|
||||||
|
{
|
||||||
|
return Items.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
public Item DropItem(Item item)
|
public Item DropItem(Item item)
|
||||||
{
|
{
|
||||||
item.CharacterOwner = null;
|
item.CharacterOwner = null;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
using GodotUtilities.Collections;
|
||||||
|
using System.Linq;
|
||||||
|
using SupaLidlGame.Utils;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.Items;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class Shop : Resource, IItemCollection<ShopEntry>
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
protected Godot.Collections.Array<ShopEntry> Entries { get; private set; }
|
||||||
|
|
||||||
|
public System.Collections.Generic.IEnumerable<ItemMetadata> GetItems()
|
||||||
|
{
|
||||||
|
var mapState = World.Instance.GlobalState.MapState;
|
||||||
|
return Entries
|
||||||
|
.Where(
|
||||||
|
(entry) =>
|
||||||
|
{
|
||||||
|
var condition = entry.MapStateCondition;
|
||||||
|
if (string.IsNullOrEmpty(condition))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return mapState.GetBoolean(condition) ?? false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.Select((entry) => entry.Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Add(ShopEntry entry)
|
||||||
|
{
|
||||||
|
Entries.Add(entry);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(ShopEntry entry)
|
||||||
|
{
|
||||||
|
return Entries.Remove(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Capacity => Entries.Count;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.Items;
|
||||||
|
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ShopEntry : Resource
|
||||||
|
{
|
||||||
|
public ShopEntry() : base()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShopEntry(ItemMetadata item) : base()
|
||||||
|
{
|
||||||
|
Item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public ItemMetadata Item { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public string MapStateCondition { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
[gd_resource type="Resource" script_class="Shop" load_steps=16 format=3 uid="uid://djqd88vdkoi6d"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://Items/Shop.cs" id="1_betbc"]
|
||||||
|
[ext_resource type="Resource" uid="uid://cjsh0dcgbfn77" path="res://Items/Weapons/Bow.tres" id="1_ntroj"]
|
||||||
|
[ext_resource type="Script" path="res://Items/ShopEntry.cs" id="2_xgvwu"]
|
||||||
|
[ext_resource type="Resource" uid="uid://iqe6rgnb3jur" path="res://Items/Weapons/Pugio.tres" id="3_nfeft"]
|
||||||
|
[ext_resource type="Resource" uid="uid://dkm216ug0vj2h" path="res://Items/Weapons/Shotgun.tres" id="4_aw0ju"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_jdx0p"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
Item = ExtResource("1_ntroj")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_min4b"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
Item = ExtResource("3_nfeft")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_t0x08"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
Item = ExtResource("4_aw0ju")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_exmab"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_jlgb3"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_8rd47"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_pqgh5"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_8mift"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_4e8it"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_jp7ms"]
|
||||||
|
script = ExtResource("2_xgvwu")
|
||||||
|
MapStateCondition = ""
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_betbc")
|
||||||
|
Entries = Array[Object]([SubResource("Resource_jdx0p"), SubResource("Resource_min4b"), SubResource("Resource_t0x08"), SubResource("Resource_exmab"), SubResource("Resource_jlgb3"), SubResource("Resource_8rd47"), SubResource("Resource_pqgh5"), SubResource("Resource_8mift"), SubResource("Resource_4e8it"), SubResource("Resource_jp7ms")])
|
|
@ -1,5 +1,6 @@
|
||||||
[gd_resource type="Resource" script_class="ItemMetadata" load_steps=4 format=3 uid="uid://cjsh0dcgbfn77"]
|
[gd_resource type="Resource" script_class="ItemMetadata" load_steps=5 format=3 uid="uid://cjsh0dcgbfn77"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://vjdyrv8wp7gl" path="res://Assets/Sprites/forsenLevel.png" id="1_5blro"]
|
||||||
[ext_resource type="Script" path="res://Utils/ScenePath.cs" id="1_haiji"]
|
[ext_resource type="Script" path="res://Utils/ScenePath.cs" id="1_haiji"]
|
||||||
[ext_resource type="Script" path="res://Items/ItemMetadata.cs" id="2_hjbs0"]
|
[ext_resource type="Script" path="res://Items/ItemMetadata.cs" id="2_hjbs0"]
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ Path = "res://Items/Weapons/Bow.tscn"
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_hjbs0")
|
script = ExtResource("2_hjbs0")
|
||||||
Instance = SubResource("Resource_mjj1w")
|
Instance = SubResource("Resource_mjj1w")
|
||||||
|
Icon = ExtResource("1_5blro")
|
||||||
Name = "Bow"
|
Name = "Bow"
|
||||||
Description = "A bow and arrow."
|
Description = "A bow and arrow."
|
||||||
BuyPrice = 0
|
BuyPrice = 0
|
||||||
|
|
|
@ -24,6 +24,15 @@ public partial class ProjectileSpawner : Ranged
|
||||||
[Export]
|
[Export]
|
||||||
public float ProjectileAngleDeviation { get; set; }
|
public float ProjectileAngleDeviation { get; set; }
|
||||||
|
|
||||||
|
public string ProjectilePath
|
||||||
|
{
|
||||||
|
get => Projectile?.ResourcePath;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Projectile = GD.Load<PackedScene>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void SpawnProjectile(Scenes.Map map,
|
protected virtual void SpawnProjectile(Scenes.Map map,
|
||||||
Vector2 direction, float velocityModifier = 1)
|
Vector2 direction, float velocityModifier = 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[gd_resource type="Resource" script_class="ItemMetadata" load_steps=4 format=3 uid="uid://iqe6rgnb3jur"]
|
[gd_resource type="Resource" script_class="ItemMetadata" load_steps=5 format=3 uid="uid://iqe6rgnb3jur"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://vjdyrv8wp7gl" path="res://Assets/Sprites/forsenLevel.png" id="1_3ptey"]
|
||||||
[ext_resource type="Script" path="res://Utils/ScenePath.cs" id="1_o026a"]
|
[ext_resource type="Script" path="res://Utils/ScenePath.cs" id="1_o026a"]
|
||||||
[ext_resource type="Script" path="res://Items/ItemMetadata.cs" id="2_j4tmu"]
|
[ext_resource type="Script" path="res://Items/ItemMetadata.cs" id="2_j4tmu"]
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ Path = "res://Items/Weapons/Pugio.tscn"
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("2_j4tmu")
|
script = ExtResource("2_j4tmu")
|
||||||
Instance = SubResource("Resource_abrg1")
|
Instance = SubResource("Resource_abrg1")
|
||||||
|
Icon = ExtResource("1_3ptey")
|
||||||
Name = "Pugio"
|
Name = "Pugio"
|
||||||
Description = "A sidearm dagger."
|
Description = "A sidearm dagger."
|
||||||
BuyPrice = 0
|
BuyPrice = 0
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[gd_resource type="Resource" script_class="ItemMetadata" load_steps=5 format=3 uid="uid://dkm216ug0vj2h"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://Utils/ScenePath.cs" id="1_owc5r"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://vjdyrv8wp7gl" path="res://Assets/Sprites/forsenLevel.png" id="1_v76vk"]
|
||||||
|
[ext_resource type="Script" path="res://Items/ItemMetadata.cs" id="1_vtlr1"]
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_6sxq7"]
|
||||||
|
script = ExtResource("1_owc5r")
|
||||||
|
Path = "res://Items/Weapons/Shotgun.tscn"
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_vtlr1")
|
||||||
|
Instance = SubResource("Resource_6sxq7")
|
||||||
|
Icon = ExtResource("1_v76vk")
|
||||||
|
Name = "Shotgun"
|
||||||
|
Description = ""
|
||||||
|
BuyPrice = 1887
|
||||||
|
SellPrice = 0
|
|
@ -1,9 +1,10 @@
|
||||||
[gd_scene load_steps=26 format=3 uid="uid://d1d4vg7we5rjr"]
|
[gd_scene load_steps=27 format=3 uid="uid://d1d4vg7we5rjr"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_4xyyt"]
|
[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_4xyyt"]
|
||||||
[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="2_ag6rd"]
|
[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="2_ag6rd"]
|
||||||
[ext_resource type="PackedScene" uid="uid://da1do2r2pbayb" path="res://Entities/ShotgunPellet.tscn" id="2_p3wx2"]
|
[ext_resource type="PackedScene" uid="uid://da1do2r2pbayb" path="res://Entities/ShotgunPellet.tscn" id="2_p3wx2"]
|
||||||
[ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="3_dd6bh"]
|
[ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="3_dd6bh"]
|
||||||
|
[ext_resource type="Resource" uid="uid://dkm216ug0vj2h" path="res://Items/Weapons/Shotgun.tres" id="3_ju036"]
|
||||||
[ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="4_bwqd6"]
|
[ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="4_bwqd6"]
|
||||||
[ext_resource type="Texture2D" uid="uid://b1omx2kdb2x1n" path="res://Assets/Sprites/Items/shotgun.png" id="5_g8d45"]
|
[ext_resource type="Texture2D" uid="uid://b1omx2kdb2x1n" path="res://Assets/Sprites/Items/shotgun.png" id="5_g8d45"]
|
||||||
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="6_va8ee"]
|
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="6_va8ee"]
|
||||||
|
@ -216,11 +217,9 @@ curve = SubResource("Curve_mqgo6")
|
||||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_uexo4"]
|
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_uexo4"]
|
||||||
particle_flag_disable_z = true
|
particle_flag_disable_z = true
|
||||||
flatness = 1.0
|
flatness = 1.0
|
||||||
gravity = Vector3(0, -4, 0)
|
|
||||||
initial_velocity_min = -8.0
|
initial_velocity_min = -8.0
|
||||||
initial_velocity_max = 24.0
|
initial_velocity_max = 24.0
|
||||||
orbit_velocity_min = 0.0
|
gravity = Vector3(0, -4, 0)
|
||||||
orbit_velocity_max = 0.0
|
|
||||||
scale_min = 0.75
|
scale_min = 0.75
|
||||||
scale_curve = SubResource("CurveTexture_3omj5")
|
scale_curve = SubResource("CurveTexture_3omj5")
|
||||||
color_ramp = SubResource("GradientTexture1D_83h4s")
|
color_ramp = SubResource("GradientTexture1D_83h4s")
|
||||||
|
@ -236,13 +235,11 @@ gradient = SubResource("Gradient_jks7f")
|
||||||
particle_flag_disable_z = true
|
particle_flag_disable_z = true
|
||||||
direction = Vector3(-1, -2, 0)
|
direction = Vector3(-1, -2, 0)
|
||||||
spread = 10.0
|
spread = 10.0
|
||||||
gravity = Vector3(0, 64, 0)
|
|
||||||
initial_velocity_min = 16.0
|
initial_velocity_min = 16.0
|
||||||
initial_velocity_max = 32.0
|
initial_velocity_max = 32.0
|
||||||
angular_velocity_min = 30.0
|
angular_velocity_min = 30.0
|
||||||
angular_velocity_max = 60.0
|
angular_velocity_max = 60.0
|
||||||
orbit_velocity_min = 0.0
|
gravity = Vector3(0, 64, 0)
|
||||||
orbit_velocity_max = 0.0
|
|
||||||
scale_min = 2.0
|
scale_min = 2.0
|
||||||
scale_max = 2.0
|
scale_max = 2.0
|
||||||
color_ramp = SubResource("GradientTexture1D_eeskk")
|
color_ramp = SubResource("GradientTexture1D_eeskk")
|
||||||
|
@ -259,6 +256,7 @@ Damage = 12.0
|
||||||
UseTime = 1.5
|
UseTime = 1.5
|
||||||
InitialVelocity = 220.0
|
InitialVelocity = 220.0
|
||||||
PlayerLevelGain = 0.5
|
PlayerLevelGain = 0.5
|
||||||
|
Metadata = ExtResource("3_ju036")
|
||||||
|
|
||||||
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
|
||||||
script = ExtResource("2_ag6rd")
|
script = ExtResource("2_ag6rd")
|
||||||
|
|
|
@ -3,11 +3,10 @@
|
||||||
[ext_resource type="Script" path="res://Utils/World.cs" id="1_1k6ew"]
|
[ext_resource type="Script" path="res://Utils/World.cs" id="1_1k6ew"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c271rdjhd1gfo" path="res://UI/Base.tscn" id="2_mm0qt"]
|
[ext_resource type="PackedScene" uid="uid://c271rdjhd1gfo" path="res://UI/Base.tscn" id="2_mm0qt"]
|
||||||
|
|
||||||
[node name="World" type="Node2D" node_paths=PackedStringArray("MusicPlayer", "DialogueBalloon")]
|
[node name="World" type="Node2D" node_paths=PackedStringArray("MusicPlayer")]
|
||||||
process_mode = 3
|
process_mode = 3
|
||||||
script = ExtResource("1_1k6ew")
|
script = ExtResource("1_1k6ew")
|
||||||
MusicPlayer = NodePath("MusicPlayer")
|
MusicPlayer = NodePath("MusicPlayer")
|
||||||
DialogueBalloon = NodePath("CanvasLayer/SubViewportContainer/UIViewport/DialogBalloon")
|
|
||||||
|
|
||||||
[node name="CanvasLayer" parent="." instance=ExtResource("2_mm0qt")]
|
[node name="CanvasLayer" parent="." instance=ExtResource("2_mm0qt")]
|
||||||
|
|
||||||
|
@ -21,6 +20,7 @@ anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
[node name="MusicPlayer" type="AudioStreamPlayer" parent="."]
|
[node name="MusicPlayer" type="AudioStreamPlayer" parent="."]
|
||||||
bus = &"Music"
|
bus = &"Music"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[gd_scene load_steps=22 format=3 uid="uid://cumi1cbg6xfdd"]
|
[gd_scene load_steps=23 format=3 uid="uid://cumi1cbg6xfdd"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://clwv2owvk6abe" path="res://Scenes/BaseMap.tscn" id="1_oy3cp"]
|
[ext_resource type="PackedScene" uid="uid://clwv2owvk6abe" path="res://Scenes/BaseMap.tscn" id="1_oy3cp"]
|
||||||
[ext_resource type="Texture2D" uid="uid://c70cn53osy56w" path="res://Assets/Sprites/dev-tileset.png" id="2_2gdry"]
|
[ext_resource type="Texture2D" uid="uid://c70cn53osy56w" path="res://Assets/Sprites/dev-tileset.png" id="2_2gdry"]
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
[ext_resource type="Texture2D" uid="uid://chwwo6vmf8iri" path="res://Assets/Sprites/Props/tree-autumn-leaves-2.png" id="8_4laic"]
|
[ext_resource type="Texture2D" uid="uid://chwwo6vmf8iri" path="res://Assets/Sprites/Props/tree-autumn-leaves-2.png" id="8_4laic"]
|
||||||
[ext_resource type="Texture2D" uid="uid://dhf2f5a1ty502" path="res://Assets/Sprites/Props/tree-autumn-leaves-1.png" id="8_hyhpu"]
|
[ext_resource type="Texture2D" uid="uid://dhf2f5a1ty502" path="res://Assets/Sprites/Props/tree-autumn-leaves-1.png" id="8_hyhpu"]
|
||||||
[ext_resource type="Texture2D" uid="uid://crvbsxrda5gcj" path="res://Assets/Sprites/Props/tree-autumn-leaves-3.png" id="9_exvkw"]
|
[ext_resource type="Texture2D" uid="uid://crvbsxrda5gcj" path="res://Assets/Sprites/Props/tree-autumn-leaves-3.png" id="9_exvkw"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://rd08pot25h00" path="res://Characters/SnusDealer.tscn" id="12_eyny2"]
|
||||||
|
|
||||||
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_s1h2f"]
|
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_s1h2f"]
|
||||||
texture = ExtResource("2_2gdry")
|
texture = ExtResource("2_2gdry")
|
||||||
|
@ -458,8 +459,8 @@ cell_size = 16.0
|
||||||
agent_radius = 8.0
|
agent_radius = 8.0
|
||||||
|
|
||||||
[sub_resource type="NavigationPolygon" id="NavigationPolygon_8xwo5"]
|
[sub_resource type="NavigationPolygon" id="NavigationPolygon_8xwo5"]
|
||||||
vertices = PackedVector2Array(280, -232, 280, -120, 276, -120, 216, -232, 216, -40, 276, -72, 296, -72, 296, -88, 392, -88, 392, -136, 472, -136, 472, -40, 440, -40, 440, 8, 488, 8, 488, 24, 440, 24, 440, 72, 424, 72, 424, 24, 424, 8, 376, 24, 376, 8, 424, -40, 296, -40, 296, -56, 276, -56, 276, -40)
|
vertices = PackedVector2Array(392, -88, 392, -136, 472, -136, 472, -40, 440, -40, 440, 8, 488, 8, 488, 24, 440, 24, 440, 72, 424, 72, 424, 24, 424, 8, 376, 24, 376, 8, 424, -40, 216, -40, 280, -88, 216, -232, 280, -232)
|
||||||
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3), PackedInt32Array(4, 3, 2, 5), PackedInt32Array(6, 7, 8), PackedInt32Array(8, 9, 10, 11, 12), PackedInt32Array(13, 14, 15, 16), PackedInt32Array(16, 17, 18, 19), PackedInt32Array(13, 16, 19, 20), PackedInt32Array(19, 21, 22, 20), PackedInt32Array(12, 13, 20, 23), PackedInt32Array(8, 12, 23), PackedInt32Array(8, 23, 24, 25), PackedInt32Array(6, 8, 25), PackedInt32Array(5, 6, 25, 26), PackedInt32Array(4, 5, 26), PackedInt32Array(4, 26, 27)])
|
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3, 4), PackedInt32Array(5, 6, 7, 8), PackedInt32Array(8, 9, 10, 11), PackedInt32Array(5, 8, 11, 12), PackedInt32Array(11, 13, 14, 12), PackedInt32Array(4, 5, 12, 15), PackedInt32Array(0, 4, 15), PackedInt32Array(0, 15, 16, 17), PackedInt32Array(17, 16, 18, 19)])
|
||||||
outlines = Array[PackedVector2Array]([PackedVector2Array(208, -240, 208, -32, 416, -32, 416.001, -15.9759, 368.001, -15.9787, 368, 32, 416, 32, 416, 80, 448, 80, 448, 32, 496, 32, 496.001, -15.9713, 448.001, -15.9741, 448, -32, 480, -32, 480.008, -143.972, 384.008, -143.978, 384.006, -95.9778, 288, -96, 288, -240)])
|
outlines = Array[PackedVector2Array]([PackedVector2Array(208, -240, 208, -32, 416, -32, 416.001, -15.9759, 368.001, -15.9787, 368, 32, 416, 32, 416, 80, 448, 80, 448, 32, 496, 32, 496.001, -15.9713, 448.001, -15.9741, 448, -32, 480, -32, 480.008, -143.972, 384.008, -143.978, 384.006, -95.9778, 288, -96, 288, -240)])
|
||||||
source_geometry_mode = 1
|
source_geometry_mode = 1
|
||||||
source_geometry_group_name = &"navigation"
|
source_geometry_group_name = &"navigation"
|
||||||
|
@ -479,6 +480,9 @@ Markers = NodePath("Markers")
|
||||||
AreaName = "Forest"
|
AreaName = "Forest"
|
||||||
MapName = "Forest"
|
MapName = "Forest"
|
||||||
|
|
||||||
|
[node name="CanvasModulate" parent="." index="7"]
|
||||||
|
position = Vector2(0, 1)
|
||||||
|
|
||||||
[node name="StaticBody2D" type="StaticBody2D" parent="Props" index="0"]
|
[node name="StaticBody2D" type="StaticBody2D" parent="Props" index="0"]
|
||||||
y_sort_enabled = true
|
y_sort_enabled = true
|
||||||
position = Vector2(0, -96)
|
position = Vector2(0, -96)
|
||||||
|
@ -843,7 +847,14 @@ position = Vector2(1272, 0)
|
||||||
[node name="Campfire" parent="Entities" index="0" instance=ExtResource("3_ve4i2")]
|
[node name="Campfire" parent="Entities" index="0" instance=ExtResource("3_ve4i2")]
|
||||||
position = Vector2(-24, -8)
|
position = Vector2(-24, -8)
|
||||||
|
|
||||||
[node name="Areas" parent="." index="3"]
|
[node name="SnusDealer" parent="Entities" index="1" node_paths=PackedStringArray("ThinkerStateMachine", "Sprite", "Inventory", "StateMachine") instance=ExtResource("12_eyny2")]
|
||||||
|
position = Vector2(79, -6)
|
||||||
|
ThinkerStateMachine = NodePath("Thinker")
|
||||||
|
Sprite = NodePath("Sprites/Sprite")
|
||||||
|
Inventory = NodePath("Inventory")
|
||||||
|
StateMachine = NodePath("StateMachine")
|
||||||
|
|
||||||
|
[node name="Areas" parent="." index="10"]
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
[node name="Main" type="NavigationRegion2D" parent="Areas" index="0"]
|
[node name="Main" type="NavigationRegion2D" parent="Areas" index="0"]
|
||||||
|
|
|
@ -3,9 +3,5 @@ shader_type canvas_item;
|
||||||
uniform float amount : hint_range(0.5, 1.0, 0.01) = 1;
|
uniform float amount : hint_range(0.5, 1.0, 0.01) = 1;
|
||||||
|
|
||||||
void fragment() {
|
void fragment() {
|
||||||
// Place fragment code here.
|
COLOR.a *= step(UV.x, amount) * step(1.0 - amount, UV.x);
|
||||||
//COLOR = texture(TEXTURE, UV);
|
|
||||||
if (UV.x > amount || UV.x < 1.0 - amount) {
|
|
||||||
COLOR.a = 0.0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform float x_amount : hint_range(0.5, 1.0, 0.01) = 1;
|
||||||
|
uniform float y_amount : hint_range(0.5, 1.0, 0.01) = 0.5;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
COLOR.a *= step(UV.x, x_amount) * step(1.0 - x_amount, UV.x);
|
||||||
|
//COLOR.a *= step(1.0 - y_amount, UV.y) * step(UV.y, y_amount);
|
||||||
|
COLOR.a *= 1.0 - (step(1.0 - y_amount, UV.y) * step(UV.y, y_amount));
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ public partial class GlobalState : Node
|
||||||
[Export]
|
[Export]
|
||||||
public Stats Stats { get; set; }
|
public Stats Stats { get; set; }
|
||||||
|
|
||||||
|
public static GlobalState Instance { get; private set; }
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public GameSettings Settings { get; set; }
|
public GameSettings Settings { get; set; }
|
||||||
|
|
||||||
|
@ -30,6 +32,13 @@ public partial class GlobalState : Node
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
if (Instance != null)
|
||||||
|
{
|
||||||
|
throw new MultipleSingletonsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
ProcessMode = ProcessModeEnum.Always;
|
ProcessMode = ProcessModeEnum.Always;
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,13 @@ public partial class MapState : Resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool? GetBoolean(string key)
|
||||||
|
{
|
||||||
|
if (_state[key].VariantType == Variant.Type.Bool)
|
||||||
|
{
|
||||||
|
return (bool)_state[key];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Godot;
|
||||||
|
using GodotUtilities;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.State.Thinker;
|
||||||
|
|
||||||
|
public partial class VendorIdle : ThinkerState
|
||||||
|
{
|
||||||
|
public override ThinkerState Think()
|
||||||
|
{
|
||||||
|
var bestNeutral = NPC.FindBestNeutral();
|
||||||
|
if (bestNeutral is not null)
|
||||||
|
{
|
||||||
|
NPC.Target = bestNeutral.Position - NPC.Position;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
72
UI/Base.tscn
72
UI/Base.tscn
|
@ -1,13 +1,13 @@
|
||||||
[gd_scene load_steps=14 format=3 uid="uid://c271rdjhd1gfo"]
|
[gd_scene load_steps=14 format=3 uid="uid://c271rdjhd1gfo"]
|
||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://73jm5qjy52vq" path="res://Dialogue/balloon.tscn" id="1_atjb1"]
|
|
||||||
[ext_resource type="Script" path="res://UI/UIController.cs" id="2_b4b6l"]
|
[ext_resource type="Script" path="res://UI/UIController.cs" id="2_b4b6l"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bxo553hblp6nf" path="res://UI/HealthBar.tscn" id="3_j1j6h"]
|
[ext_resource type="PackedScene" uid="uid://bxo553hblp6nf" path="res://UI/HealthBar.tscn" id="3_j1j6h"]
|
||||||
[ext_resource type="PackedScene" uid="uid://01d24ij5av1y" path="res://UI/BossBar.tscn" id="4_igi28"]
|
[ext_resource type="PackedScene" uid="uid://01d24ij5av1y" path="res://UI/BossBar.tscn" id="4_igi28"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cr7tkxctmyags" path="res://UI/LevelBar.tscn" id="4_rcekd"]
|
[ext_resource type="PackedScene" uid="uid://cr7tkxctmyags" path="res://UI/LevelBar.tscn" id="4_rcekd"]
|
||||||
[ext_resource type="PackedScene" uid="uid://c77754nvmckn" path="res://UI/LocationDisplay.tscn" id="5_cr6vo"]
|
[ext_resource type="PackedScene" uid="uid://c77754nvmckn" path="res://UI/LocationDisplay.tscn" id="5_cr6vo"]
|
||||||
[ext_resource type="PackedScene" uid="uid://sfs8dpfitpdu" path="res://UI/Hotbar.tscn" id="5_mmp18"]
|
[ext_resource type="PackedScene" uid="uid://sfs8dpfitpdu" path="res://UI/Inventory/Hotbar.tscn" id="5_mmp18"]
|
||||||
[ext_resource type="PackedScene" uid="uid://d3q1yu3n7cqfj" path="res://UI/SceneTransition.tscn" id="6_j0nhv"]
|
[ext_resource type="PackedScene" uid="uid://d3q1yu3n7cqfj" path="res://UI/SceneTransition.tscn" id="6_j0nhv"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cyggkyqosjk36" path="res://UI/Inventory/ShopMenu.tscn" id="8_ep3ae"]
|
||||||
[ext_resource type="PackedScene" uid="uid://2afbrf8asy2a" path="res://UI/PostProcessing/Vignette.tscn" id="9_p1ubd"]
|
[ext_resource type="PackedScene" uid="uid://2afbrf8asy2a" path="res://UI/PostProcessing/Vignette.tscn" id="9_p1ubd"]
|
||||||
[ext_resource type="PackedScene" uid="uid://b1wsryv4bn0cn" path="res://UI/PostProcessing/StunEffect.tscn" id="10_646ma"]
|
[ext_resource type="PackedScene" uid="uid://b1wsryv4bn0cn" path="res://UI/PostProcessing/StunEffect.tscn" id="10_646ma"]
|
||||||
[ext_resource type="Shader" path="res://Shaders/Grayscale.gdshader" id="11_w4gn1"]
|
[ext_resource type="Shader" path="res://Shaders/Grayscale.gdshader" id="11_w4gn1"]
|
||||||
|
@ -20,6 +20,26 @@ shader_parameter/grayscale_intensity = 0.0
|
||||||
[node name="BaseUI" type="CanvasLayer"]
|
[node name="BaseUI" type="CanvasLayer"]
|
||||||
process_mode = 3
|
process_mode = 3
|
||||||
|
|
||||||
|
[node name="PostProcessing" type="CanvasLayer" parent="."]
|
||||||
|
|
||||||
|
[node name="Vignette" parent="PostProcessing" instance=ExtResource("9_p1ubd")]
|
||||||
|
|
||||||
|
[node name="StunEffect" parent="PostProcessing" instance=ExtResource("10_646ma")]
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="TextureRect" parent="PostProcessing"]
|
||||||
|
visible = false
|
||||||
|
material = SubResource("ShaderMaterial_kbd61")
|
||||||
|
anchors_preset = 3
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -128.0
|
||||||
|
offset_top = -128.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
texture = ExtResource("12_tyv35")
|
||||||
|
|
||||||
[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
|
[node name="SubViewportContainer" type="SubViewportContainer" parent="."]
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
|
@ -36,9 +56,6 @@ handle_input_locally = false
|
||||||
size = Vector2i(640, 360)
|
size = Vector2i(640, 360)
|
||||||
render_target_update_mode = 4
|
render_target_update_mode = 4
|
||||||
|
|
||||||
[node name="DialogBalloon" parent="SubViewportContainer/UIViewport" instance=ExtResource("1_atjb1")]
|
|
||||||
layer = 4
|
|
||||||
|
|
||||||
[node name="MainUILayer" type="CanvasLayer" parent="SubViewportContainer/UIViewport"]
|
[node name="MainUILayer" type="CanvasLayer" parent="SubViewportContainer/UIViewport"]
|
||||||
layer = 3
|
layer = 3
|
||||||
|
|
||||||
|
@ -52,6 +69,7 @@ grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
mouse_filter = 2
|
||||||
script = ExtResource("2_b4b6l")
|
script = ExtResource("2_b4b6l")
|
||||||
|
|
||||||
[node name="Top" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
[node name="Top" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
||||||
|
@ -78,7 +96,6 @@ layout_mode = 2
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="Margin2" type="MarginContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Left/VBoxContainer"]
|
[node name="Margin2" type="MarginContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main/Top/Left/VBoxContainer"]
|
||||||
visible = false
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
theme_override_constants/margin_left = 16
|
theme_override_constants/margin_left = 16
|
||||||
theme_override_constants/margin_top = 16
|
theme_override_constants/margin_top = 16
|
||||||
|
@ -92,6 +109,23 @@ theme_override_constants/margin_right = 16
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_slots = [NodePath("InventorySlot"), NodePath("InventorySlot2"), NodePath("InventorySlot3")]
|
_slots = [NodePath("InventorySlot"), NodePath("InventorySlot2"), NodePath("InventorySlot3")]
|
||||||
|
|
||||||
|
[node name="BoxContainer" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 11
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -236.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 2
|
||||||
|
alignment = 2
|
||||||
|
|
||||||
|
[node name="ShopMenu" parent="SubViewportContainer/UIViewport/MainUILayer/Main/BoxContainer" node_paths=PackedStringArray("_inventoryGrid") instance=ExtResource("8_ep3ae")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
_inventoryGrid = NodePath("PanelContainer/VBoxContainer/ScrollContainer/InventoryGrid")
|
||||||
|
|
||||||
[node name="Bottom" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
[node name="Bottom" type="HBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 12
|
anchors_preset = 12
|
||||||
|
@ -107,27 +141,13 @@ alignment = 1
|
||||||
visible = false
|
visible = false
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="SubViewportContainer/UIViewport/MainUILayer/Main"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 0
|
||||||
|
offset_right = 40.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
|
||||||
[node name="LocationDisplay" parent="SubViewportContainer/UIViewport/MainUILayer" instance=ExtResource("5_cr6vo")]
|
[node name="LocationDisplay" parent="SubViewportContainer/UIViewport/MainUILayer" instance=ExtResource("5_cr6vo")]
|
||||||
|
|
||||||
[node name="SceneTransition" parent="SubViewportContainer/UIViewport/MainUILayer" instance=ExtResource("6_j0nhv")]
|
[node name="SceneTransition" parent="SubViewportContainer/UIViewport/MainUILayer" instance=ExtResource("6_j0nhv")]
|
||||||
z_index = 1
|
z_index = 1
|
||||||
|
|
||||||
[node name="PostProcessing" type="CanvasLayer" parent="."]
|
|
||||||
|
|
||||||
[node name="Vignette" parent="PostProcessing" instance=ExtResource("9_p1ubd")]
|
|
||||||
|
|
||||||
[node name="StunEffect" parent="PostProcessing" instance=ExtResource("10_646ma")]
|
|
||||||
|
|
||||||
[node name="Sprite2D" type="TextureRect" parent="PostProcessing"]
|
|
||||||
visible = false
|
|
||||||
material = SubResource("ShaderMaterial_kbd61")
|
|
||||||
anchors_preset = 3
|
|
||||||
anchor_left = 1.0
|
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_left = -128.0
|
|
||||||
offset_top = -128.0
|
|
||||||
grow_horizontal = 0
|
|
||||||
grow_vertical = 0
|
|
||||||
texture = ExtResource("12_tyv35")
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
[gd_scene load_steps=3 format=3 uid="uid://sfs8dpfitpdu"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://UI/Hotbar.cs" id="1_2sak2"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://ctad0dkoyw8ad" path="res://UI/InventorySlot.tscn" id="1_ct3cn"]
|
|
||||||
|
|
||||||
[node name="Hotbar" type="GridContainer" node_paths=PackedStringArray("_slots")]
|
|
||||||
anchors_preset = 1
|
|
||||||
anchor_left = 1.0
|
|
||||||
anchor_right = 1.0
|
|
||||||
offset_left = -112.0
|
|
||||||
offset_bottom = 32.0
|
|
||||||
grow_horizontal = 0
|
|
||||||
theme_override_constants/h_separation = 8
|
|
||||||
columns = 3
|
|
||||||
script = ExtResource("1_2sak2")
|
|
||||||
_slots = [NodePath("InventorySlot"), NodePath("InventorySlot2"), NodePath("InventorySlot3")]
|
|
||||||
|
|
||||||
[node name="InventorySlot" parent="." instance=ExtResource("1_ct3cn")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="InventorySlot2" parent="." instance=ExtResource("1_ct3cn")]
|
|
||||||
layout_mode = 2
|
|
||||||
|
|
||||||
[node name="InventorySlot3" parent="." instance=ExtResource("1_ct3cn")]
|
|
||||||
layout_mode = 2
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace SupaLidlGame.UI;
|
||||||
|
|
||||||
|
public interface IModal
|
||||||
|
{
|
||||||
|
public void HideModal();
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
using SupaLidlGame.Items;
|
|
||||||
|
|
||||||
namespace SupaLidlGame.UI;
|
namespace SupaLidlGame.UI.Inventory;
|
||||||
|
|
||||||
public partial class Hotbar : GridContainer
|
public partial class Hotbar : GridContainer
|
||||||
{
|
{
|
||||||
|
@ -13,7 +12,7 @@ public partial class Hotbar : GridContainer
|
||||||
Events.EventBus.Instance.PlayerInventoryUpdate += OnInventoryUpdate;
|
Events.EventBus.Instance.PlayerInventoryUpdate += OnInventoryUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnInventoryUpdate(Inventory inventory)
|
public void OnInventoryUpdate(Items.Inventory inventory)
|
||||||
{
|
{
|
||||||
GD.Print($"UPDATE: {inventory.SelectedIndex} is selected index.");
|
GD.Print($"UPDATE: {inventory.SelectedIndex} is selected index.");
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
|
@ -0,0 +1,30 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://sfs8dpfitpdu"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://UI/Inventory/Hotbar.cs" id="1_2sak2"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dmvu2hjyrwc1y" path="res://UI/Inventory/HotbarSlot.tscn" id="2_3axfe"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6jbma"]
|
||||||
|
|
||||||
|
[node name="Hotbar" type="GridContainer" node_paths=PackedStringArray("_slots")]
|
||||||
|
anchors_preset = 1
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_left = -112.0
|
||||||
|
offset_bottom = 32.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
theme_override_constants/h_separation = 8
|
||||||
|
columns = 3
|
||||||
|
script = ExtResource("1_2sak2")
|
||||||
|
_slots = [NodePath("InventorySlot"), NodePath("InventorySlot2"), NodePath("InventorySlot3")]
|
||||||
|
|
||||||
|
[node name="InventorySlot" parent="." instance=ExtResource("2_3axfe")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_6jbma")
|
||||||
|
|
||||||
|
[node name="InventorySlot2" parent="." instance=ExtResource("2_3axfe")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_6jbma")
|
||||||
|
|
||||||
|
[node name="InventorySlot3" parent="." instance=ExtResource("2_3axfe")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_6jbma")
|
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://dmvu2hjyrwc1y"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ctad0dkoyw8ad" path="res://UI/Inventory/InventorySlot.tscn" id="1_fb62b"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dp7osg05ip5oo" path="res://Assets/Sprites/sword.png" id="2_aqbyo"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dc1gcsbhkchvg" path="res://Assets/Sprites/UI/hotbar-active.png" id="2_bcv71"]
|
||||||
|
|
||||||
|
[node name="InventorySlot" instance=ExtResource("1_fb62b")]
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="." index="0"]
|
||||||
|
texture = ExtResource("2_aqbyo")
|
||||||
|
expand_mode = 3
|
||||||
|
|
||||||
|
[node name="SelectedFrame" type="NinePatchRect" parent="." index="2"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("2_bcv71")
|
|
@ -0,0 +1,172 @@
|
||||||
|
using Godot;
|
||||||
|
using GodotUtilities;
|
||||||
|
using SupaLidlGame.Items;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.UI.Inventory;
|
||||||
|
|
||||||
|
public partial class InventoryGrid : GridContainer
|
||||||
|
{
|
||||||
|
private SupaLidlGame.Items.IItemCollection _source;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
private PackedScene _slotScene;
|
||||||
|
|
||||||
|
public ButtonGroup ButtonGroup { get; private set; }
|
||||||
|
|
||||||
|
public SupaLidlGame.Items.IItemCollection Source
|
||||||
|
{
|
||||||
|
get => _source;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
GD.Print("Set InventoryGrid source");
|
||||||
|
_source = value;
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Signal]
|
||||||
|
public delegate void SlotFocusedEventHandler(InventorySlot slot);
|
||||||
|
|
||||||
|
[Signal]
|
||||||
|
public delegate void SlotUnfocusedEventHandler(InventorySlot slot);
|
||||||
|
|
||||||
|
[Signal]
|
||||||
|
public delegate void SlotSelectedEventHandler(InventorySlot slot);
|
||||||
|
|
||||||
|
public InventoryGrid()
|
||||||
|
{
|
||||||
|
ButtonGroup = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Redraw()
|
||||||
|
{
|
||||||
|
GD.Print("Redrawing inventory grid...");
|
||||||
|
|
||||||
|
if (_source is null)
|
||||||
|
{
|
||||||
|
this.QueueFreeChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
var children = GetChildren();
|
||||||
|
|
||||||
|
for (int i = children.Count; i < _source.Capacity; i++)
|
||||||
|
{
|
||||||
|
AddInventorySlot();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = children.Count - 1; i >= _source.Capacity; i--)
|
||||||
|
{
|
||||||
|
children[i].QueueFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
children = GetChildren();
|
||||||
|
|
||||||
|
// iterate through items and update the grid
|
||||||
|
using (var items = _source.GetItems().GetEnumerator())
|
||||||
|
{
|
||||||
|
GD.Print("Updating items...");
|
||||||
|
int i;
|
||||||
|
for (i = 0; items.MoveNext(); i++)
|
||||||
|
{
|
||||||
|
InventorySlot slot = children[i] as InventorySlot;
|
||||||
|
|
||||||
|
ItemMetadata item = items.Current;
|
||||||
|
slot.Item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make remaining slots display empty
|
||||||
|
for (; i < _source.Capacity; i++)
|
||||||
|
{
|
||||||
|
InventorySlot slot = children[i] as InventorySlot;
|
||||||
|
|
||||||
|
slot.Item = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < children.Count; i++)
|
||||||
|
{
|
||||||
|
var child = children[i] as Control;
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
child.FocusPrevious = child.GetPathTo(children[i - 1]);
|
||||||
|
}
|
||||||
|
if (i < children.Count - 1)
|
||||||
|
{
|
||||||
|
child.FocusNext = child.GetPathTo(children[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children.Count > 0)
|
||||||
|
{
|
||||||
|
var button = children[0] as Button;
|
||||||
|
button.ButtonPressed = true;
|
||||||
|
button.GrabFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InventorySlot AddInventorySlot()
|
||||||
|
{
|
||||||
|
var slot = _slotScene.Instantiate<InventorySlot>();
|
||||||
|
AddChild(slot);
|
||||||
|
slot.ButtonGroup = ButtonGroup;
|
||||||
|
|
||||||
|
void focusedHandler()
|
||||||
|
{
|
||||||
|
EmitSignal(SignalName.SlotFocused, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unfocusedHandler()
|
||||||
|
{
|
||||||
|
EmitSignal(SignalName.SlotUnfocused, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggledHandler()
|
||||||
|
{
|
||||||
|
EmitSignal(SignalName.SlotSelected, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
slot.Connect(
|
||||||
|
InventorySlot.SignalName.FocusEntered,
|
||||||
|
Callable.From(focusedHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
slot.Connect(
|
||||||
|
InventorySlot.SignalName.FocusExited,
|
||||||
|
Callable.From(unfocusedHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
slot.Connect(
|
||||||
|
InventorySlot.SignalName.MouseEntered,
|
||||||
|
Callable.From(focusedHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
slot.Connect(
|
||||||
|
InventorySlot.SignalName.MouseExited,
|
||||||
|
Callable.From(unfocusedHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
slot.Connect(
|
||||||
|
InventorySlot.SignalName.Pressed,
|
||||||
|
Callable.From(toggledHandler)
|
||||||
|
);
|
||||||
|
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveInventorySlot(InventorySlot slot)
|
||||||
|
{
|
||||||
|
RemoveChild(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GrabSlotFocus()
|
||||||
|
{
|
||||||
|
var children = GetChildren();
|
||||||
|
if (children.Count > 0)
|
||||||
|
{
|
||||||
|
var button = children[0] as Button;
|
||||||
|
button.GrabFocus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://chmokkxsy5vas"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://UI/Inventory/InventoryGrid.cs" id="1_7128g"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ctad0dkoyw8ad" path="res://UI/Inventory/InventorySlot.tscn" id="2_b6vp8"]
|
||||||
|
|
||||||
|
[node name="InventoryGrid" type="GridContainer"]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
columns = 5
|
||||||
|
script = ExtResource("1_7128g")
|
||||||
|
_slotScene = ExtResource("2_b6vp8")
|
|
@ -0,0 +1,95 @@
|
||||||
|
using Godot;
|
||||||
|
using GodotUtilities;
|
||||||
|
using GodotUtilities.SourceGenerators;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.UI.Inventory;
|
||||||
|
|
||||||
|
public partial class InventorySlot : Button
|
||||||
|
{
|
||||||
|
private bool _isSelected = false;
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get => _isSelected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isSelected = value;
|
||||||
|
if (_selectedFrame is not null)
|
||||||
|
{
|
||||||
|
//_selectedFrame.Visible = _isSelected;
|
||||||
|
//_frame.Visible = !_isSelected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool UseFocusAsSelected { get; set; } = true;
|
||||||
|
|
||||||
|
private TextureRect _textureRect;
|
||||||
|
|
||||||
|
private NinePatchRect _frame;
|
||||||
|
|
||||||
|
private NinePatchRect _selectedFrame;
|
||||||
|
|
||||||
|
private static Texture2D _placeholderTexture;
|
||||||
|
|
||||||
|
private Items.ItemMetadata _item;
|
||||||
|
|
||||||
|
public Items.ItemMetadata Item
|
||||||
|
{
|
||||||
|
get => _item;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_item = value;
|
||||||
|
|
||||||
|
if (_item is null)
|
||||||
|
{
|
||||||
|
//_textureRect.Texture = null;
|
||||||
|
Icon = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//_textureRect.Texture = _item.Icon;
|
||||||
|
Icon = _item.Icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static InventorySlot()
|
||||||
|
{
|
||||||
|
_placeholderTexture = ResourceLoader.Load<Texture2D>(
|
||||||
|
"res://Assets/Sprites/UI/hotbar-inactive.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_textureRect = GetNode<TextureRect>("TextureRect");
|
||||||
|
_frame = GetNode<NinePatchRect>("Frame");
|
||||||
|
_selectedFrame = GetNode<NinePatchRect>("SelectedFrame");
|
||||||
|
|
||||||
|
if (Item is null)
|
||||||
|
{
|
||||||
|
// do this to reset the icon
|
||||||
|
Item = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UseFocusAsSelected)
|
||||||
|
{
|
||||||
|
void focusEntered()
|
||||||
|
{
|
||||||
|
IsSelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void focusExited()
|
||||||
|
{
|
||||||
|
IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connect(SignalName.FocusEntered, Callable.From(focusEntered));
|
||||||
|
Connect(SignalName.FocusExited, Callable.From(focusExited));
|
||||||
|
|
||||||
|
Connect(SignalName.MouseEntered, Callable.From(focusEntered));
|
||||||
|
Connect(SignalName.MouseExited, Callable.From(focusExited));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
[gd_scene load_steps=8 format=3 uid="uid://ctad0dkoyw8ad"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://UI/Inventory/InventorySlot.cs" id="1_fju5i"]
|
||||||
|
[ext_resource type="Theme" uid="uid://cksjbu3vrup5" path="res://UI/Themes/supalidl.tres" id="1_wnu7u"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://nvb4etac7ee2" path="res://UI/Themes/InventorySlotButtonFocus.tres" id="2_3wx0v"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dc1gcsbhkchvg" path="res://Assets/Sprites/UI/hotbar-active.png" id="2_m56j3"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://pqtn0115bqtp" path="res://UI/Themes/InventorySlotButtonPressed.tres" id="3_46bp6"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://cfqp0ycwvwx7c" path="res://UI/Themes/InventorySlotButtonNormal.tres" id="4_cc2jo"]
|
||||||
|
|
||||||
|
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_ajutj"]
|
||||||
|
size = Vector2(24, 24)
|
||||||
|
|
||||||
|
[node name="InventorySlot" type="Button"]
|
||||||
|
custom_minimum_size = Vector2(32, 32)
|
||||||
|
theme = ExtResource("1_wnu7u")
|
||||||
|
theme_type_variation = &"InventorySlotButton"
|
||||||
|
theme_override_styles/focus = ExtResource("2_3wx0v")
|
||||||
|
theme_override_styles/pressed = ExtResource("3_46bp6")
|
||||||
|
theme_override_styles/normal = ExtResource("4_cc2jo")
|
||||||
|
toggle_mode = true
|
||||||
|
action_mode = 0
|
||||||
|
icon_alignment = 1
|
||||||
|
script = ExtResource("1_fju5i")
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
offset_right = 32.0
|
||||||
|
offset_bottom = 32.0
|
||||||
|
mouse_filter = 2
|
||||||
|
texture = SubResource("PlaceholderTexture2D_ajutj")
|
||||||
|
expand_mode = 2
|
||||||
|
stretch_mode = 3
|
||||||
|
|
||||||
|
[node name="Frame" type="NinePatchRect" parent="."]
|
||||||
|
visible = false
|
||||||
|
self_modulate = Color(1, 1, 1, 0.5)
|
||||||
|
layout_mode = 2
|
||||||
|
offset_right = 32.0
|
||||||
|
offset_bottom = 32.0
|
||||||
|
texture = ExtResource("2_m56j3")
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Godot;
|
||||||
|
using SupaLidlGame.Items;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.UI.Inventory;
|
||||||
|
|
||||||
|
public partial class ItemTooltip : Control
|
||||||
|
{
|
||||||
|
private ItemMetadata _item;
|
||||||
|
|
||||||
|
public ItemMetadata Item
|
||||||
|
{
|
||||||
|
get => _item;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_item = value;
|
||||||
|
if (IsNodeReady())
|
||||||
|
{
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render()
|
||||||
|
{
|
||||||
|
if (_item is null)
|
||||||
|
{
|
||||||
|
GetNode<Label>("%ItemLabel").Text = "Nothing here";
|
||||||
|
GetNode<TextureRect>("%ItemTexture").Texture = null;
|
||||||
|
GetNode<RichTextLabel>("%ItemDescription").Text = "We are ready for My Summer Car";
|
||||||
|
GetNode<Label>("%Ingredients/Label").Text = "0 Shillings";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetNode<Label>("%ItemLabel").Text = _item.Name;
|
||||||
|
GetNode<TextureRect>("%ItemTexture").Texture = _item.Icon;
|
||||||
|
GetNode<RichTextLabel>("%ItemDescription").Text = _item.Description;
|
||||||
|
GetNode<Label>("%Ingredients/Label").Text = _item.BuyPrice + " Shillings";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
[gd_scene load_steps=12 format=3 uid="uid://bsheehtfcdwhh"]
|
||||||
|
|
||||||
|
[ext_resource type="Theme" uid="uid://cksjbu3vrup5" path="res://UI/Themes/supalidl.tres" id="1_elbte"]
|
||||||
|
[ext_resource type="Script" path="res://UI/Inventory/ItemTooltip.cs" id="2_entlu"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="2_mcttf"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cd8ak8gu0104t" path="res://Assets/Sprites/UI/border.png" id="2_sxqyx"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dc1gcsbhkchvg" path="res://Assets/Sprites/UI/hotbar-active.png" id="2_vjw5e"]
|
||||||
|
|
||||||
|
[sub_resource type="Animation" id="Animation_mmh32"]
|
||||||
|
resource_name = "wipe"
|
||||||
|
|
||||||
|
[sub_resource type="AnimationLibrary" id="AnimationLibrary_4bp3t"]
|
||||||
|
_data = {
|
||||||
|
"wipe": SubResource("Animation_mmh32")
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_xhduc"]
|
||||||
|
content_margin_left = 0.0
|
||||||
|
content_margin_top = 0.0
|
||||||
|
content_margin_right = 0.0
|
||||||
|
content_margin_bottom = 0.0
|
||||||
|
texture = ExtResource("2_mcttf")
|
||||||
|
texture_margin_left = 16.0
|
||||||
|
texture_margin_top = 16.0
|
||||||
|
texture_margin_right = 16.0
|
||||||
|
texture_margin_bottom = 16.0
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_rhjxi"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
texture = ExtResource("2_vjw5e")
|
||||||
|
texture_margin_left = 8.0
|
||||||
|
texture_margin_top = 8.0
|
||||||
|
texture_margin_right = 8.0
|
||||||
|
texture_margin_bottom = 8.0
|
||||||
|
|
||||||
|
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_qnr6k"]
|
||||||
|
size = Vector2(24, 24)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_idehr"]
|
||||||
|
bg_color = Color(0.976471, 0.956863, 0.956863, 1)
|
||||||
|
|
||||||
|
[node name="ItemTooltip" type="BoxContainer"]
|
||||||
|
offset_right = 92.0
|
||||||
|
offset_bottom = 161.0
|
||||||
|
theme = ExtResource("1_elbte")
|
||||||
|
script = ExtResource("2_entlu")
|
||||||
|
|
||||||
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
|
libraries = {
|
||||||
|
"": SubResource("AnimationLibrary_4bp3t")
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxTexture_xhduc")
|
||||||
|
|
||||||
|
[node name="Margin" type="MarginContainer" parent="VBoxContainer/PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer/Margin"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 8
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 0
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxTexture_rhjxi")
|
||||||
|
|
||||||
|
[node name="ItemTexture" type="TextureRect" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer/HBoxContainer/PanelContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
texture = SubResource("PlaceholderTexture2D_qnr6k")
|
||||||
|
stretch_mode = 2
|
||||||
|
|
||||||
|
[node name="ItemLabel" type="Label" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer/HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "Really long item name"
|
||||||
|
autowrap_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer/HBoxContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="NinePatchRect" type="NinePatchRect" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer/HBoxContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("2_sxqyx")
|
||||||
|
region_rect = Rect2(0, 6, 48, 5)
|
||||||
|
patch_margin_left = 16
|
||||||
|
patch_margin_top = 5
|
||||||
|
patch_margin_right = 16
|
||||||
|
|
||||||
|
[node name="ItemDescription" type="RichTextLabel" parent="VBoxContainer/PanelContainer/Margin/VBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_colors/default_color = Color(0.937255, 0.854902, 0.854902, 1)
|
||||||
|
text = "Speed, violence, momentum"
|
||||||
|
fit_content = true
|
||||||
|
|
||||||
|
[node name="PanelContainer2" type="PanelContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_idehr")
|
||||||
|
|
||||||
|
[node name="Ingredients" type="MarginContainer" parent="VBoxContainer/PanelContainer2"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/margin_top = 2
|
||||||
|
theme_override_constants/margin_bottom = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="VBoxContainer/PanelContainer2/Ingredients"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_colors/font_color = Color(0, 0, 0, 1)
|
||||||
|
text = "250 Shillings"
|
|
@ -0,0 +1,100 @@
|
||||||
|
using Godot;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace SupaLidlGame.UI.Inventory;
|
||||||
|
|
||||||
|
public partial class ShopMenu : Control, IModal
|
||||||
|
{
|
||||||
|
private Items.IItemCollection<Items.ShopEntry> _source;
|
||||||
|
|
||||||
|
public Items.IItemCollection<Items.ShopEntry> Source
|
||||||
|
{
|
||||||
|
get => _source;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_source = value;
|
||||||
|
_inventoryGrid.Source = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
private InventoryGrid _inventoryGrid;
|
||||||
|
|
||||||
|
private InventorySlot _selected;
|
||||||
|
|
||||||
|
public void ShowModal()
|
||||||
|
{
|
||||||
|
Show();
|
||||||
|
var animPlayer = GetNode<AnimationPlayer>("%AnimationPlayer");
|
||||||
|
animPlayer.Play("open");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideModal()
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
_source = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Close()
|
||||||
|
{
|
||||||
|
var animPlayer = GetNode<AnimationPlayer>("%AnimationPlayer");
|
||||||
|
animPlayer.Play("close");
|
||||||
|
await ToSignal(animPlayer, AnimationPlayer.SignalName.AnimationFinished);
|
||||||
|
HideModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_inventoryGrid.SlotFocused += (InventorySlot slot) =>
|
||||||
|
{
|
||||||
|
if (slot.Item is not null)
|
||||||
|
{
|
||||||
|
SetTooltipItem(slot);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_inventoryGrid.SlotUnfocused += (InventorySlot slot) =>
|
||||||
|
{
|
||||||
|
SetTooltipItem(_selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
_inventoryGrid.SlotSelected += (InventorySlot slot) =>
|
||||||
|
{
|
||||||
|
_selected = slot;
|
||||||
|
SetTooltipItem(slot);
|
||||||
|
GetNode<Button>("%BuyButton").GrabFocus();
|
||||||
|
};
|
||||||
|
|
||||||
|
GetNode<Button>("%BuyButton").GuiInput += (InputEvent @event) =>
|
||||||
|
{
|
||||||
|
if (@event.IsActionPressed("ui_cancel"))
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
_selected?.GrabFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTooltipItem(InventorySlot slot)
|
||||||
|
{
|
||||||
|
GetNode<ItemTooltip>("%ItemTooltip").Item = slot?.Item;
|
||||||
|
|
||||||
|
if (slot == _selected)
|
||||||
|
{
|
||||||
|
GetNode<Button>("%BuyButton").Disabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetNode<Button>("%BuyButton").Disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
|
{
|
||||||
|
if (@event.IsActionPressed("ui_cancel"))
|
||||||
|
{
|
||||||
|
GetViewport().SetInputAsHandled();
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,217 @@
|
||||||
|
[gd_scene load_steps=15 format=3 uid="uid://cyggkyqosjk36"]
|
||||||
|
|
||||||
|
[ext_resource type="StyleBox" uid="uid://bqhotx2ogucye" path="res://UI/Themes/Panel.tres" id="1_2ffty"]
|
||||||
|
[ext_resource type="Script" path="res://UI/Inventory/ShopMenu.cs" id="1_8c1y7"]
|
||||||
|
[ext_resource type="Shader" path="res://Shaders/WipeXY.gdshader" id="2_jqery"]
|
||||||
|
[ext_resource type="FontFile" uid="uid://cgwa8bjiyv534" path="res://Assets/Fonts/alagard.ttf" id="3_aj4jx"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bsheehtfcdwhh" path="res://UI/Inventory/ItemTooltip.tscn" id="4_n61n7"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://chmokkxsy5vas" path="res://UI/Inventory/InventoryGrid.tscn" id="4_sl632"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://baawkwo8aiwbu" path="res://UI/Inventory/ShopSlot.tscn" id="5_kfyl0"]
|
||||||
|
[ext_resource type="Theme" uid="uid://cksjbu3vrup5" path="res://UI/Themes/supalidl.tres" id="7_rvp1r"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gm1xk"]
|
||||||
|
bg_color = Color(0, 0, 0, 0.784314)
|
||||||
|
border_width_left = 16
|
||||||
|
border_width_top = 16
|
||||||
|
border_width_right = 16
|
||||||
|
border_width_bottom = 16
|
||||||
|
border_color = Color(0.145098, 0.145098, 0.145098, 0)
|
||||||
|
border_blend = true
|
||||||
|
corner_radius_top_left = 16
|
||||||
|
corner_radius_top_right = 16
|
||||||
|
corner_radius_bottom_right = 16
|
||||||
|
corner_radius_bottom_left = 16
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2hdh3"]
|
||||||
|
shader = ExtResource("2_jqery")
|
||||||
|
shader_parameter/x_amount = 1.0
|
||||||
|
shader_parameter/y_amount = 0.5
|
||||||
|
|
||||||
|
[sub_resource type="Animation" id="Animation_yj24f"]
|
||||||
|
length = 0.001
|
||||||
|
tracks/0/type = "value"
|
||||||
|
tracks/0/imported = false
|
||||||
|
tracks/0/enabled = true
|
||||||
|
tracks/0/path = NodePath(".:modulate")
|
||||||
|
tracks/0/interp = 1
|
||||||
|
tracks/0/loop_wrap = true
|
||||||
|
tracks/0/keys = {
|
||||||
|
"times": PackedFloat32Array(0),
|
||||||
|
"transitions": PackedFloat32Array(1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [Color(1, 1, 1, 1)]
|
||||||
|
}
|
||||||
|
tracks/1/type = "value"
|
||||||
|
tracks/1/imported = false
|
||||||
|
tracks/1/enabled = true
|
||||||
|
tracks/1/path = NodePath("PanelContainer:material:shader_parameter/y_amount")
|
||||||
|
tracks/1/interp = 1
|
||||||
|
tracks/1/loop_wrap = true
|
||||||
|
tracks/1/keys = {
|
||||||
|
"times": PackedFloat32Array(0),
|
||||||
|
"transitions": PackedFloat32Array(1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [0.5]
|
||||||
|
}
|
||||||
|
tracks/2/type = "value"
|
||||||
|
tracks/2/imported = false
|
||||||
|
tracks/2/enabled = true
|
||||||
|
tracks/2/path = NodePath("PanelContainer:material:shader_parameter/x_amount")
|
||||||
|
tracks/2/interp = 1
|
||||||
|
tracks/2/loop_wrap = true
|
||||||
|
tracks/2/keys = {
|
||||||
|
"times": PackedFloat32Array(0),
|
||||||
|
"transitions": PackedFloat32Array(1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [1.0]
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="Animation" id="Animation_tm2as"]
|
||||||
|
resource_name = "close"
|
||||||
|
length = 0.5
|
||||||
|
step = 0.05
|
||||||
|
tracks/0/type = "value"
|
||||||
|
tracks/0/imported = false
|
||||||
|
tracks/0/enabled = true
|
||||||
|
tracks/0/path = NodePath(".:modulate")
|
||||||
|
tracks/0/interp = 1
|
||||||
|
tracks/0/loop_wrap = true
|
||||||
|
tracks/0/keys = {
|
||||||
|
"times": PackedFloat32Array(0, 0.4),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
|
||||||
|
}
|
||||||
|
tracks/1/type = "value"
|
||||||
|
tracks/1/imported = false
|
||||||
|
tracks/1/enabled = true
|
||||||
|
tracks/1/path = NodePath("PanelContainer:material:shader_parameter/y_amount")
|
||||||
|
tracks/1/interp = 1
|
||||||
|
tracks/1/loop_wrap = true
|
||||||
|
tracks/1/keys = {
|
||||||
|
"times": PackedFloat32Array(0, 0.1),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [0.5, 1.0]
|
||||||
|
}
|
||||||
|
tracks/2/type = "value"
|
||||||
|
tracks/2/imported = false
|
||||||
|
tracks/2/enabled = true
|
||||||
|
tracks/2/path = NodePath("PanelContainer:material:shader_parameter/x_amount")
|
||||||
|
tracks/2/interp = 1
|
||||||
|
tracks/2/loop_wrap = true
|
||||||
|
tracks/2/keys = {
|
||||||
|
"times": PackedFloat32Array(0.05, 0.15),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [1.0, 0.5]
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="Animation" id="Animation_fgj27"]
|
||||||
|
resource_name = "open"
|
||||||
|
length = 0.5
|
||||||
|
tracks/0/type = "value"
|
||||||
|
tracks/0/imported = false
|
||||||
|
tracks/0/enabled = true
|
||||||
|
tracks/0/path = NodePath(".:modulate")
|
||||||
|
tracks/0/interp = 1
|
||||||
|
tracks/0/loop_wrap = true
|
||||||
|
tracks/0/keys = {
|
||||||
|
"times": PackedFloat32Array(0, 0.3),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1)]
|
||||||
|
}
|
||||||
|
tracks/1/type = "value"
|
||||||
|
tracks/1/imported = false
|
||||||
|
tracks/1/enabled = true
|
||||||
|
tracks/1/path = NodePath("PanelContainer:material:shader_parameter/y_amount")
|
||||||
|
tracks/1/interp = 1
|
||||||
|
tracks/1/loop_wrap = true
|
||||||
|
tracks/1/keys = {
|
||||||
|
"times": PackedFloat32Array(0, 0.5),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [1.0, 0.5]
|
||||||
|
}
|
||||||
|
tracks/2/type = "value"
|
||||||
|
tracks/2/imported = false
|
||||||
|
tracks/2/enabled = true
|
||||||
|
tracks/2/path = NodePath("PanelContainer:material:shader_parameter/x_amount")
|
||||||
|
tracks/2/interp = 1
|
||||||
|
tracks/2/loop_wrap = true
|
||||||
|
tracks/2/keys = {
|
||||||
|
"times": PackedFloat32Array(0, 0.3),
|
||||||
|
"transitions": PackedFloat32Array(1, 1),
|
||||||
|
"update": 0,
|
||||||
|
"values": [0.5, 1.0]
|
||||||
|
}
|
||||||
|
|
||||||
|
[sub_resource type="AnimationLibrary" id="AnimationLibrary_0glcp"]
|
||||||
|
_data = {
|
||||||
|
"RESET": SubResource("Animation_yj24f"),
|
||||||
|
"close": SubResource("Animation_tm2as"),
|
||||||
|
"open": SubResource("Animation_fgj27")
|
||||||
|
}
|
||||||
|
|
||||||
|
[node name="Panel" type="PanelContainer" node_paths=PackedStringArray("_inventoryGrid")]
|
||||||
|
anchors_preset = 6
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -236.0
|
||||||
|
offset_top = -175.5
|
||||||
|
offset_bottom = 175.5
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_gm1xk")
|
||||||
|
script = ExtResource("1_8c1y7")
|
||||||
|
_inventoryGrid = NodePath("PanelContainer/VBoxContainer/ScrollContainer/InventoryGrid")
|
||||||
|
|
||||||
|
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||||
|
material = SubResource("ShaderMaterial_2hdh3")
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = ExtResource("1_2ffty")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_fonts/font = ExtResource("3_aj4jx")
|
||||||
|
text = "Snus Dealer"
|
||||||
|
|
||||||
|
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
follow_focus = true
|
||||||
|
horizontal_scroll_mode = 0
|
||||||
|
|
||||||
|
[node name="InventoryGrid" parent="PanelContainer/VBoxContainer/ScrollContainer" instance=ExtResource("4_sl632")]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
_slotScene = ExtResource("5_kfyl0")
|
||||||
|
|
||||||
|
[node name="ItemTooltip" parent="PanelContainer/VBoxContainer" instance=ExtResource("4_n61n7")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="BuyButton" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer2"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme = ExtResource("7_rvp1r")
|
||||||
|
text = "Buy"
|
||||||
|
|
||||||
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
libraries = {
|
||||||
|
"": SubResource("AnimationLibrary_0glcp")
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://baawkwo8aiwbu"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://ctad0dkoyw8ad" path="res://UI/Inventory/InventorySlot.tscn" id="1_tdkv2"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="2_af1qu"]
|
||||||
|
|
||||||
|
[node name="ShopSlot" instance=ExtResource("1_tdkv2")]
|
||||||
|
|
||||||
|
[node name="Frame" parent="." index="1"]
|
||||||
|
texture = ExtResource("2_af1qu")
|
||||||
|
|
||||||
|
[node name="SelectedFrame" type="NinePatchRect" parent="." index="2"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
texture = ExtResource("2_af1qu")
|
|
@ -1,74 +0,0 @@
|
||||||
using Godot;
|
|
||||||
using GodotUtilities;
|
|
||||||
using GodotUtilities.SourceGenerators;
|
|
||||||
|
|
||||||
namespace SupaLidlGame.UI;
|
|
||||||
|
|
||||||
[Scene]
|
|
||||||
public partial class InventorySlot : ColorRect
|
|
||||||
{
|
|
||||||
[Node("TextureRect")]
|
|
||||||
private TextureRect _textureRect;
|
|
||||||
|
|
||||||
[Node("Selected")]
|
|
||||||
private NinePatchRect _selected;
|
|
||||||
|
|
||||||
[Node("Unselected")]
|
|
||||||
private NinePatchRect _unselected;
|
|
||||||
|
|
||||||
private static Texture2D _placeholderTexture;
|
|
||||||
|
|
||||||
private Items.ItemMetadata _item;
|
|
||||||
|
|
||||||
public Items.ItemMetadata Item
|
|
||||||
{
|
|
||||||
get => _item;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_item = value;
|
|
||||||
|
|
||||||
if (_item is null)
|
|
||||||
{
|
|
||||||
//_textureRect.Texture = _placeholderTexture;
|
|
||||||
_textureRect.Texture = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_textureRect.Texture = _item.Icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isSelected = false;
|
|
||||||
|
|
||||||
public bool IsSelected
|
|
||||||
{
|
|
||||||
get => _isSelected;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_isSelected = value;
|
|
||||||
_selected.Visible = _isSelected;
|
|
||||||
_unselected.Visible = !_isSelected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static InventorySlot()
|
|
||||||
{
|
|
||||||
_placeholderTexture = ResourceLoader.Load<Texture2D>(
|
|
||||||
"res://Assets/Sprites/UI/hotbar-inactive.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Notification(int what)
|
|
||||||
{
|
|
||||||
if (what == NotificationSceneInstantiated)
|
|
||||||
{
|
|
||||||
WireNodes();
|
|
||||||
}
|
|
||||||
base._Notification(what);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
[gd_scene load_steps=4 format=3 uid="uid://ctad0dkoyw8ad"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://UI/InventorySlot.cs" id="1_llonk"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://bd81g8aivb2ql" path="res://Assets/Sprites/UI/menu-rect-no-bg-32.png" id="2_vvog5"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="3_jr23q"]
|
|
||||||
|
|
||||||
[node name="InventorySlot" type="ColorRect"]
|
|
||||||
custom_minimum_size = Vector2(32, 32)
|
|
||||||
color = Color(1, 1, 1, 0)
|
|
||||||
script = ExtResource("1_llonk")
|
|
||||||
|
|
||||||
[node name="TextureRect" type="TextureRect" parent="."]
|
|
||||||
layout_mode = 1
|
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
stretch_mode = 3
|
|
||||||
|
|
||||||
[node name="Selected" type="NinePatchRect" parent="."]
|
|
||||||
visible = false
|
|
||||||
layout_mode = 1
|
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
texture = ExtResource("2_vvog5")
|
|
||||||
|
|
||||||
[node name="Unselected" type="NinePatchRect" parent="."]
|
|
||||||
self_modulate = Color(1, 1, 1, 0.5)
|
|
||||||
layout_mode = 1
|
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
texture = ExtResource("3_jr23q")
|
|
|
@ -151,6 +151,7 @@ anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
script = ExtResource("1_g1mdf")
|
script = ExtResource("1_g1mdf")
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
|
|
@ -107,6 +107,7 @@ anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
script = ExtResource("1_mx0ay")
|
script = ExtResource("1_mx0ay")
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="."]
|
[node name="ColorRect" type="ColorRect" parent="."]
|
||||||
|
@ -117,6 +118,7 @@ anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
color = Color(0, 0, 0, 1)
|
color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
[gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://nvb4etac7ee2"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="1_el8jk"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
texture = ExtResource("1_el8jk")
|
||||||
|
texture_margin_left = 4.0
|
||||||
|
texture_margin_top = 4.0
|
||||||
|
texture_margin_right = 4.0
|
||||||
|
texture_margin_bottom = 4.0
|
|
@ -0,0 +1,15 @@
|
||||||
|
[gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://cfqp0ycwvwx7c"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="1_r3gsw"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
texture = ExtResource("1_r3gsw")
|
||||||
|
texture_margin_left = 4.0
|
||||||
|
texture_margin_top = 4.0
|
||||||
|
texture_margin_right = 4.0
|
||||||
|
texture_margin_bottom = 4.0
|
||||||
|
modulate_color = Color(1, 1, 1, 0.498039)
|
|
@ -0,0 +1,15 @@
|
||||||
|
[gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://pqtn0115bqtp"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="1_1ahpp"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
texture = ExtResource("1_1ahpp")
|
||||||
|
texture_margin_left = 4.0
|
||||||
|
texture_margin_top = 4.0
|
||||||
|
texture_margin_right = 4.0
|
||||||
|
texture_margin_bottom = 4.0
|
||||||
|
modulate_color = Color(0.941176, 0.843137, 0.470588, 1)
|
|
@ -0,0 +1,14 @@
|
||||||
|
[gd_resource type="StyleBoxTexture" load_steps=2 format=3 uid="uid://bqhotx2ogucye"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://uhmowtsi3wfh" path="res://Assets/Sprites/UI/menu-rect-no-bg-white.png" id="1_cb20l"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 16.0
|
||||||
|
content_margin_top = 16.0
|
||||||
|
content_margin_right = 16.0
|
||||||
|
content_margin_bottom = 16.0
|
||||||
|
texture = ExtResource("1_cb20l")
|
||||||
|
texture_margin_left = 32.0
|
||||||
|
texture_margin_top = 32.0
|
||||||
|
texture_margin_right = 32.0
|
||||||
|
texture_margin_bottom = 32.0
|
|
@ -1,10 +1,58 @@
|
||||||
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://cksjbu3vrup5"]
|
[gd_resource type="Theme" load_steps=11 format=3 uid="uid://cksjbu3vrup5"]
|
||||||
|
|
||||||
[ext_resource type="FontFile" uid="uid://6bvgjbmqovau" path="res://Assets/Fonts/calamity/calamity.ttf" id="1_334fe"]
|
[ext_resource type="FontFile" uid="uid://6bvgjbmqovau" path="res://Assets/Fonts/calamity/calamity.ttf" id="1_334fe"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://nvb4etac7ee2" path="res://UI/Themes/InventorySlotButtonFocus.tres" id="2_3w5h1"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b16461tjso0j7" path="res://Assets/Sprites/UI/hotbar-inactive.png" id="2_6sv27"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://bqhotx2ogucye" path="res://UI/Themes/Panel.tres" id="2_jlgx8"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://cfqp0ycwvwx7c" path="res://UI/Themes/InventorySlotButtonNormal.tres" id="3_nuiio"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://pqtn0115bqtp" path="res://UI/Themes/InventorySlotButtonPressed.tres" id="4_mllnb"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxTexture" id="StyleBoxTexture_wk5ww"]
|
||||||
|
content_margin_left = 4.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
texture = ExtResource("2_6sv27")
|
||||||
|
texture_margin_left = 16.0
|
||||||
|
texture_margin_top = 16.0
|
||||||
|
texture_margin_right = 16.0
|
||||||
|
texture_margin_bottom = 16.0
|
||||||
|
modulate_color = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5w4ck"]
|
||||||
|
bg_color = Color(0.937255, 0.854902, 0.854902, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_2qibe"]
|
||||||
|
content_margin_left = 2.0
|
||||||
|
content_margin_top = 2.0
|
||||||
|
content_margin_right = 2.0
|
||||||
|
content_margin_bottom = 2.0
|
||||||
|
bg_color = Color(0.976471, 0.956863, 0.956863, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_iyd8w"]
|
||||||
|
bg_color = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
default_font = ExtResource("1_334fe")
|
default_font = ExtResource("1_334fe")
|
||||||
default_font_size = 15
|
default_font_size = 15
|
||||||
/colors/background = Color(0.105882, 0.0470588, 0.117647, 1)
|
/colors/background = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
/font_sizes/Normal = 16
|
/font_sizes/Normal = 15
|
||||||
/fonts/Calamity = ExtResource("1_334fe")
|
/fonts/Calamity = ExtResource("1_334fe")
|
||||||
|
Button/colors/font_color = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
|
Button/colors/font_focus_color = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
|
Button/colors/font_hover_color = Color(0.105882, 0.0470588, 0.117647, 1)
|
||||||
|
Button/colors/font_pressed_color = Color(0.976471, 0.956863, 0.956863, 1)
|
||||||
|
Button/styles/focus = SubResource("StyleBoxTexture_wk5ww")
|
||||||
|
Button/styles/hover = SubResource("StyleBoxFlat_5w4ck")
|
||||||
|
Button/styles/normal = SubResource("StyleBoxFlat_2qibe")
|
||||||
|
Button/styles/pressed = SubResource("StyleBoxFlat_iyd8w")
|
||||||
|
InventorySlotButton/base_type = &"Button"
|
||||||
|
InventorySlotButton/styles/focus = ExtResource("2_3w5h1")
|
||||||
|
InventorySlotButton/styles/hover = ExtResource("2_3w5h1")
|
||||||
|
InventorySlotButton/styles/normal = ExtResource("3_nuiio")
|
||||||
|
InventorySlotButton/styles/pressed = ExtResource("4_mllnb")
|
||||||
|
MarginContainer/constants/margin_bottom = 8
|
||||||
|
MarginContainer/constants/margin_left = 8
|
||||||
|
MarginContainer/constants/margin_right = 8
|
||||||
|
MarginContainer/constants/margin_top = 8
|
||||||
|
PanelContainer/styles/panel = ExtResource("2_jlgx8")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace SupaLidlGame.UI;
|
namespace SupaLidlGame.UI;
|
||||||
|
|
||||||
|
@ -9,4 +10,17 @@ public partial class UIController : Control
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public BossBar BossBar { get; set; }
|
public BossBar BossBar { get; set; }
|
||||||
|
|
||||||
|
private Stack<IModal> _modals;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
Events.EventBus.Instance.EnterShop += (string path) =>
|
||||||
|
{
|
||||||
|
var shop = ResourceLoader.Load<Items.Shop>(path);
|
||||||
|
var shopMenu = GetNode<Inventory.ShopMenu>("%ShopMenu");
|
||||||
|
shopMenu.Source = shop;
|
||||||
|
shopMenu.ShowModal();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using SupaLidlGame.Extensions;
|
||||||
|
|
||||||
namespace SupaLidlGame.Utils;
|
namespace SupaLidlGame.Utils;
|
||||||
|
|
||||||
|
@ -52,8 +53,7 @@ public partial class CharacterStats : Node
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_shouldDecayStagger = false;
|
_shouldDecayStagger = false;
|
||||||
_staggerDecayTimer.Stop();
|
_staggerDecayTimer.Restart(1);
|
||||||
_staggerDecayTimer.Start(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,20 @@ using Godot;
|
||||||
|
|
||||||
namespace SupaLidlGame.Utils;
|
namespace SupaLidlGame.Utils;
|
||||||
|
|
||||||
|
[System.Flags]
|
||||||
|
public enum FactionName
|
||||||
|
{
|
||||||
|
Player = 1,
|
||||||
|
Doc = 2,
|
||||||
|
}
|
||||||
|
|
||||||
public interface IFaction
|
public interface IFaction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The faction index that this entity belongs to.
|
/// The faction index that this entity belongs to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Export]
|
[Export]
|
||||||
public ushort Faction { get; set; }
|
public FactionName Faction { get; set; }
|
||||||
|
|
||||||
public bool AlignsWith(IFaction other)
|
public bool AlignsWith(IFaction other)
|
||||||
{
|
{
|
||||||
|
|
|
@ -206,6 +206,13 @@ namespace DialogueManagerRuntime
|
||||||
|
|
||||||
public partial class DialogueLine : RefCounted
|
public partial class DialogueLine : RefCounted
|
||||||
{
|
{
|
||||||
|
private string id = "";
|
||||||
|
public string Id
|
||||||
|
{
|
||||||
|
get => id;
|
||||||
|
set => id = value;
|
||||||
|
}
|
||||||
|
|
||||||
private string type = "dialogue";
|
private string type = "dialogue";
|
||||||
public string Type
|
public string Type
|
||||||
{
|
{
|
||||||
|
|
|
@ -70,26 +70,28 @@ func _ready() -> void:
|
||||||
|
|
||||||
|
|
||||||
func _gui_input(event: InputEvent) -> void:
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
# Handle shortcuts that come from the editor
|
||||||
if event is InputEventKey and event.is_pressed():
|
if event is InputEventKey and event.is_pressed():
|
||||||
match event.as_text():
|
var shortcut: String = Engine.get_meta("DialogueManagerPlugin").get_editor_shortcut(event)
|
||||||
"Ctrl+Equal", "Command+Equal":
|
match shortcut:
|
||||||
self.font_size += 1
|
"toggle_comment":
|
||||||
get_viewport().set_input_as_handled()
|
|
||||||
"Ctrl+Minus", "Command+Minus":
|
|
||||||
self.font_size -= 1
|
|
||||||
get_viewport().set_input_as_handled()
|
|
||||||
"Ctrl+0", "Command+0":
|
|
||||||
self.font_size = theme_overrides.font_size
|
|
||||||
get_viewport().set_input_as_handled()
|
|
||||||
"Ctrl+K", "Command+K":
|
|
||||||
toggle_comment()
|
toggle_comment()
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
"Alt+Up":
|
"move_up":
|
||||||
move_line(-1)
|
move_line(-1)
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
"Alt+Down":
|
"move_down":
|
||||||
move_line(1)
|
move_line(1)
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
"text_size_increase":
|
||||||
|
self.font_size += 1
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
"text_size_decrease":
|
||||||
|
self.font_size -= 1
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
"text_size_reset":
|
||||||
|
self.font_size = theme_overrides.font_size
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
elif event is InputEventMouse:
|
elif event is InputEventMouse:
|
||||||
match event.as_text():
|
match event.as_text():
|
||||||
|
|
|
@ -26,11 +26,11 @@ var regex_dict: RegEx = RegEx.create_from_string("^\\{((?>[^\\{\\}]+|(?R))*)\\}$
|
||||||
var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$")
|
var regex_kvdict: RegEx = RegEx.create_from_string("^\\s*(?<left>.*?)\\s*(?<colon>:|=)\\s*(?<right>[^\\/]+)$")
|
||||||
var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?")
|
var regex_commas: RegEx = RegEx.create_from_string("([^,]+)(?:\\s*,\\s*)?")
|
||||||
var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$")
|
var regex_assignment: RegEx = RegEx.create_from_string("^\\s*(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*(?<op>(?:\\/|\\*|-|\\+)?=)\\s*(?<val>.*)$")
|
||||||
var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$")
|
var regex_varname: RegEx = RegEx.create_from_string("^\\s*(?!true|false|and|or|&&|\\|\\|not|in|null)(?<var>[a-zA-Z_][a-zA-Z_0-9]*)(?:(?<attr>(?:\\.[a-zA-Z_][a-zA-Z_0-9]*)+)|(?:\\[(?<key>[^\\]]+)\\]))?\\s*$")
|
||||||
var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$")
|
var regex_keyword: RegEx = RegEx.create_from_string("^\\s*(true|false|null)\\s*$")
|
||||||
var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(")
|
var regex_function: RegEx = RegEx.create_from_string("^\\s*([a-zA-Z_][a-zA-Z_0-9]*\\s*)\\(")
|
||||||
var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$")
|
var regex_comparison: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s*(?<op>==|>=|<=|<|>|!=)\\s*(?<right>.*)$")
|
||||||
var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in)\\s+(?<right>.*)$")
|
var regex_blogical: RegEx = RegEx.create_from_string("^(?<left>.*?)\\s+(?<op>and|or|in|&&|\\|\\|)\\s+(?<right>.*)$")
|
||||||
var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$")
|
var regex_ulogical: RegEx = RegEx.create_from_string("^\\s*(?<op>not)\\s+(?<right>.*)$")
|
||||||
var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)")
|
var regex_paren: RegEx = RegEx.create_from_string("\\((?<paren>((?:[^\\(\\)]*)|(?:\\((?1)\\)))*?)\\)")
|
||||||
|
|
||||||
|
@ -186,9 +186,9 @@ func _get_dialogue_syntax_highlighting(start_index: int, text: String) -> Dictio
|
||||||
for goto_match in goto_matches:
|
for goto_match in goto_matches:
|
||||||
colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color}
|
colors[start_index + goto_match.get_start(0)] = {"color": text_edit.theme_overrides.jumps_color}
|
||||||
if "file" in goto_match.names:
|
if "file" in goto_match.names:
|
||||||
colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.members_color}
|
colors[start_index + goto_match.get_start("file")] = {"color": text_edit.theme_overrides.jumps_color}
|
||||||
colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color}
|
colors[start_index + goto_match.get_end("file")] = {"color": text_edit.theme_overrides.symbols_color}
|
||||||
colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.titles_color}
|
colors[start_index + goto_match.get_start("title")] = {"color": text_edit.theme_overrides.jumps_color}
|
||||||
colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color}
|
colors[start_index + goto_match.get_end("title")] = {"color": text_edit.theme_overrides.jumps_color}
|
||||||
colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color}
|
colors[start_index + goto_match.get_end(0)] = {"color": text_edit.theme_overrides.text_color}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ var TOKEN_DEFINITIONS: Dictionary = {
|
||||||
DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."),
|
DialogueConstants.TOKEN_DOT: RegEx.create_from_string("^\\."),
|
||||||
DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"),
|
DialogueConstants.TOKEN_STRING: RegEx.create_from_string("^(\".*?\"|\'.*?\')"),
|
||||||
DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"),
|
DialogueConstants.TOKEN_NOT: RegEx.create_from_string("^(not( |$)|!)"),
|
||||||
DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or)( |$)"),
|
DialogueConstants.TOKEN_AND_OR: RegEx.create_from_string("^(and|or|&&|\\|\\|)( |$)"),
|
||||||
DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"),
|
DialogueConstants.TOKEN_VARIABLE: RegEx.create_from_string("^[a-zA-Z_][a-zA-Z_0-9]*"),
|
||||||
DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"),
|
DialogueConstants.TOKEN_COMMENT: RegEx.create_from_string("^#.*"),
|
||||||
DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"),
|
DialogueConstants.TOKEN_CONDITION: RegEx.create_from_string("^(if|elif|else)"),
|
||||||
|
@ -230,6 +230,7 @@ func parse(text: String, path: String) -> Error:
|
||||||
line["character"] = first_child.character
|
line["character"] = first_child.character
|
||||||
line["character_replacements"] = first_child.character_replacements
|
line["character_replacements"] = first_child.character_replacements
|
||||||
line["text"] = first_child.text
|
line["text"] = first_child.text
|
||||||
|
line["text_replacements"] = extract_dialogue_replacements(line.text, indent_size + 2)
|
||||||
line["translation_key"] = first_child.translation_key
|
line["translation_key"] = first_child.translation_key
|
||||||
parsed_lines[str(id) + ".2"] = first_child
|
parsed_lines[str(id) + ".2"] = first_child
|
||||||
line["next_id"] = str(id) + ".2"
|
line["next_id"] = str(id) + ".2"
|
||||||
|
@ -691,11 +692,6 @@ func get_line_after_line(id: int, indent_size: int, line: Dictionary) -> String:
|
||||||
var next_nonempty_line_id = get_next_nonempty_line_id(id)
|
var next_nonempty_line_id = get_next_nonempty_line_id(id)
|
||||||
if next_nonempty_line_id != DialogueConstants.ID_NULL \
|
if next_nonempty_line_id != DialogueConstants.ID_NULL \
|
||||||
and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]):
|
and indent_size <= get_indent(raw_lines[next_nonempty_line_id.to_int()]):
|
||||||
# The next line is a title so we need the next nonempty line after that
|
|
||||||
if is_title_line(raw_lines[next_nonempty_line_id.to_int()]):
|
|
||||||
return get_next_nonempty_line_id(next_nonempty_line_id.to_int())
|
|
||||||
# Otherwise it's a normal line
|
|
||||||
else:
|
|
||||||
return next_nonempty_line_id
|
return next_nonempty_line_id
|
||||||
# Otherwise, we grab the ID from the parents next ID after children
|
# Otherwise, we grab the ID from the parents next ID after children
|
||||||
elif line.has("parent_id") and parsed_lines.has(line.parent_id):
|
elif line.has("parent_id") and parsed_lines.has(line.parent_id):
|
||||||
|
@ -927,8 +923,8 @@ func find_next_line_after_responses(line_number: int) -> String:
|
||||||
if get_indent(line) <= expected_indent:
|
if get_indent(line) <= expected_indent:
|
||||||
return str(line_number)
|
return str(line_number)
|
||||||
|
|
||||||
# EOF so must be end of conversation
|
# EOF so it's also the end of a block
|
||||||
return DialogueConstants.ID_END_CONVERSATION
|
return DialogueConstants.ID_END
|
||||||
|
|
||||||
|
|
||||||
## Get the names of any autoloads in the project
|
## Get the names of any autoloads in the project
|
||||||
|
@ -1529,10 +1525,15 @@ func build_token_tree(tokens: Array[Dictionary], line_type: String, expected_clo
|
||||||
DialogueConstants.TOKEN_ASSIGNMENT, \
|
DialogueConstants.TOKEN_ASSIGNMENT, \
|
||||||
DialogueConstants.TOKEN_OPERATOR, \
|
DialogueConstants.TOKEN_OPERATOR, \
|
||||||
DialogueConstants.TOKEN_AND_OR, \
|
DialogueConstants.TOKEN_AND_OR, \
|
||||||
DialogueConstants.TOKEN_VARIABLE: \
|
DialogueConstants.TOKEN_VARIABLE:
|
||||||
|
var value = token.value.strip_edges()
|
||||||
|
if value == "&&":
|
||||||
|
value = "and"
|
||||||
|
elif value == "||":
|
||||||
|
value = "or"
|
||||||
tree.append({
|
tree.append({
|
||||||
type = token.type,
|
type = token.type,
|
||||||
value = token.value.strip_edges()
|
value = value
|
||||||
})
|
})
|
||||||
|
|
||||||
DialogueConstants.TOKEN_STRING:
|
DialogueConstants.TOKEN_STRING:
|
||||||
|
|
|
@ -142,6 +142,7 @@ func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) ->
|
||||||
for replacement in data.text_replacements:
|
for replacement in data.text_replacements:
|
||||||
var value = await resolve(replacement.expression.duplicate(true), extra_game_states)
|
var value = await resolve(replacement.expression.duplicate(true), extra_game_states)
|
||||||
var index: int = text.find(replacement.value_in_text)
|
var index: int = text.find(replacement.value_in_text)
|
||||||
|
if index > -1:
|
||||||
text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length())
|
text = text.substr(0, index) + str(value) + text.substr(index + replacement.value_in_text.length())
|
||||||
|
|
||||||
var parser: DialogueManagerParser = DialogueManagerParser.new()
|
var parser: DialogueManagerParser = DialogueManagerParser.new()
|
||||||
|
@ -218,6 +219,7 @@ func get_resolved_character(data: Dictionary, extra_game_states: Array = []) ->
|
||||||
for replacement in data.get(&"character_replacements", []):
|
for replacement in data.get(&"character_replacements", []):
|
||||||
var value = await resolve(replacement.expression.duplicate(true), extra_game_states)
|
var value = await resolve(replacement.expression.duplicate(true), extra_game_states)
|
||||||
var index: int = character.find(replacement.value_in_text)
|
var index: int = character.find(replacement.value_in_text)
|
||||||
|
if index > -1:
|
||||||
character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length())
|
character = character.substr(0, index) + str(value) + character.substr(index + replacement.value_in_text.length())
|
||||||
|
|
||||||
# Resolve random groups
|
# Resolve random groups
|
||||||
|
@ -359,6 +361,10 @@ func get_line(resource: DialogueResource, key: String, extra_game_states: Array)
|
||||||
|
|
||||||
var data: Dictionary = resource.lines.get(key)
|
var data: Dictionary = resource.lines.get(key)
|
||||||
|
|
||||||
|
# This title key points to another title key so we should jump there instead
|
||||||
|
if data.type == DialogueConstants.TYPE_TITLE and data.next_id in resource.titles.values():
|
||||||
|
return await get_line(resource, data.next_id + id_trail, extra_game_states)
|
||||||
|
|
||||||
# Check for weighted random lines
|
# Check for weighted random lines
|
||||||
if data.has(&"siblings"):
|
if data.has(&"siblings"):
|
||||||
var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0))
|
var target_weight: float = randf_range(0, data.siblings.reduce(func(total, sibling): return total + sibling.weight, 0))
|
||||||
|
@ -454,7 +460,7 @@ func translate(data: Dictionary) -> String:
|
||||||
|
|
||||||
TranslationSource.Guess:
|
TranslationSource.Guess:
|
||||||
var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations")
|
var translation_files: Array = ProjectSettings.get_setting(&"internationalization/locale/translations")
|
||||||
if translation_files.filter(func(f: String): return f.get_extension() == &"po").size() > 0:
|
if translation_files.filter(func(f: String): return f.get_extension() in [&"po", &"mo"]).size() > 0:
|
||||||
# Assume PO
|
# Assume PO
|
||||||
return tr(data.text, StringName(data.translation_key))
|
return tr(data.text, StringName(data.translation_key))
|
||||||
else:
|
else:
|
||||||
|
@ -745,6 +751,16 @@ func resolve(tokens: Array, extra_game_states: Array):
|
||||||
token["type"] = "value"
|
token["type"] = "value"
|
||||||
token["value"] = Quaternion(args[0], args[1], args[2], args[3])
|
token["value"] = Quaternion(args[0], args[1], args[2], args[3])
|
||||||
found = true
|
found = true
|
||||||
|
&"Callable":
|
||||||
|
token["type"] = "value"
|
||||||
|
match args.size():
|
||||||
|
0:
|
||||||
|
token["value"] = Callable()
|
||||||
|
1:
|
||||||
|
token["value"] = Callable(args[0])
|
||||||
|
2:
|
||||||
|
token["value"] = Callable(args[0], args[1])
|
||||||
|
found = true
|
||||||
&"Color":
|
&"Color":
|
||||||
token["type"] = "value"
|
token["type"] = "value"
|
||||||
match args.size():
|
match args.size():
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
@icon("./assets/responses_menu.svg")
|
@icon("./assets/responses_menu.svg")
|
||||||
|
|
||||||
## A VBoxContainer for dialogue responses provided by [b]Dialogue Manager[/b].
|
## A [Container] for dialogue responses provided by [b]Dialogue Manager[/b].
|
||||||
class_name DialogueResponsesMenu extends VBoxContainer
|
class_name DialogueResponsesMenu extends Container
|
||||||
|
|
||||||
|
|
||||||
## Emitted when a response is selected.
|
## Emitted when a response is selected.
|
||||||
|
@ -14,8 +14,10 @@ signal response_selected(response)
|
||||||
## The action for accepting a response (is possibly overridden by parent dialogue balloon).
|
## The action for accepting a response (is possibly overridden by parent dialogue balloon).
|
||||||
@export var next_action: StringName = &""
|
@export var next_action: StringName = &""
|
||||||
|
|
||||||
# The list of dialogue responses.
|
## The list of dialogue responses.
|
||||||
var responses: Array = []:
|
var responses: Array = []:
|
||||||
|
get:
|
||||||
|
return responses
|
||||||
set(value):
|
set(value):
|
||||||
responses = value
|
responses = value
|
||||||
|
|
||||||
|
@ -64,11 +66,25 @@ func _ready() -> void:
|
||||||
response_template.hide()
|
response_template.hide()
|
||||||
|
|
||||||
|
|
||||||
# This is deprecated.
|
## Get the selectable items in the menu.
|
||||||
|
func get_menu_items() -> Array:
|
||||||
|
var items: Array = []
|
||||||
|
for child in get_children():
|
||||||
|
if not child.visible: continue
|
||||||
|
if "Disallowed" in child.name: continue
|
||||||
|
items.append(child)
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
## [b]DEPRECATED[/b]. Do not use.
|
||||||
func set_responses(next_responses: Array) -> void:
|
func set_responses(next_responses: Array) -> void:
|
||||||
self.responses = next_responses
|
self.responses = next_responses
|
||||||
|
|
||||||
|
|
||||||
|
#region Internal
|
||||||
|
|
||||||
|
|
||||||
# Prepare the menu for keyboard and mouse navigation.
|
# Prepare the menu for keyboard and mouse navigation.
|
||||||
func _configure_focus() -> void:
|
func _configure_focus() -> void:
|
||||||
var items = get_menu_items()
|
var items = get_menu_items()
|
||||||
|
@ -100,18 +116,9 @@ func _configure_focus() -> void:
|
||||||
items[0].grab_focus()
|
items[0].grab_focus()
|
||||||
|
|
||||||
|
|
||||||
## Get the selectable items in the menu.
|
#endregion
|
||||||
func get_menu_items() -> Array:
|
|
||||||
var items: Array = []
|
|
||||||
for child in get_children():
|
|
||||||
if not child.visible: continue
|
|
||||||
if "Disallowed" in child.name: continue
|
|
||||||
items.append(child)
|
|
||||||
|
|
||||||
return items
|
#region Signals
|
||||||
|
|
||||||
|
|
||||||
### Signals
|
|
||||||
|
|
||||||
|
|
||||||
func _on_response_mouse_entered(item: Control) -> void:
|
func _on_response_mouse_entered(item: Control) -> void:
|
||||||
|
@ -129,3 +136,6 @@ func _on_response_gui_input(event: InputEvent, item: Control, response) -> void:
|
||||||
response_selected.emit(response)
|
response_selected.emit(response)
|
||||||
elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items():
|
elif event.is_action_pressed(&"ui_accept" if next_action.is_empty() else next_action) and item in get_menu_items():
|
||||||
response_selected.emit(response)
|
response_selected.emit(response)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
|
@ -105,6 +105,21 @@ namespace DialogueManagerRuntime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async void _Notification(int what)
|
||||||
|
{
|
||||||
|
// Detect a change of locale and update the current dialogue line to show the new language
|
||||||
|
if (what == NotificationTranslationChanged)
|
||||||
|
{
|
||||||
|
float visibleRatio = dialogueLabel.VisibleRatio;
|
||||||
|
DialogueLine = await DialogueManager.GetNextDialogueLine(resource, DialogueLine.Id, temporaryGameStates);
|
||||||
|
if (visibleRatio < 1.0f)
|
||||||
|
{
|
||||||
|
dialogueLabel.Call("skip_typing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null)
|
public async void Start(Resource dialogueResource, string title, Array<Variant> extraGameStates = null)
|
||||||
{
|
{
|
||||||
temporaryGameStates = extraGameStates ?? new Array<Variant>();
|
temporaryGameStates = extraGameStates ?? new Array<Variant>();
|
||||||
|
|
|
@ -89,6 +89,15 @@ func _unhandled_input(_event: InputEvent) -> void:
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
|
|
||||||
|
func _notification(what: int) -> void:
|
||||||
|
# Detect a change of locale and update the current dialogue line to show the new language
|
||||||
|
if what == NOTIFICATION_TRANSLATION_CHANGED:
|
||||||
|
var visible_ratio = dialogue_label.visible_ratio
|
||||||
|
self.dialogue_line = await resource.get_next_dialogue_line(dialogue_line.id)
|
||||||
|
if visible_ratio < 1:
|
||||||
|
dialogue_label.skip_typing()
|
||||||
|
|
||||||
|
|
||||||
## Start some dialogue
|
## Start some dialogue
|
||||||
func start(dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []) -> void:
|
func start(dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []) -> void:
|
||||||
temporary_game_states = [self] + extra_game_states
|
temporary_game_states = [self] + extra_game_states
|
||||||
|
@ -102,7 +111,7 @@ func next(next_id: String) -> void:
|
||||||
self.dialogue_line = await resource.get_next_dialogue_line(next_id, temporary_game_states)
|
self.dialogue_line = await resource.get_next_dialogue_line(next_id, temporary_game_states)
|
||||||
|
|
||||||
|
|
||||||
### Signals
|
#region Signals
|
||||||
|
|
||||||
|
|
||||||
func _on_mutated(_mutation: Dictionary) -> void:
|
func _on_mutated(_mutation: Dictionary) -> void:
|
||||||
|
@ -139,3 +148,6 @@ func _on_balloon_gui_input(event: InputEvent) -> void:
|
||||||
|
|
||||||
func _on_responses_menu_response_selected(response: DialogueResponse) -> void:
|
func _on_responses_menu_response_selected(response: DialogueResponse) -> void:
|
||||||
next(response.next_id)
|
next(response.next_id)
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
|
@ -8,7 +8,7 @@ signal compiled_resource(resource: Resource)
|
||||||
const DialogueResource = preload("./dialogue_resource.gd")
|
const DialogueResource = preload("./dialogue_resource.gd")
|
||||||
const DialogueManagerParseResult = preload("./components/parse_result.gd")
|
const DialogueManagerParseResult = preload("./components/parse_result.gd")
|
||||||
|
|
||||||
const compiler_version = 11
|
const compiler_version = 12
|
||||||
|
|
||||||
|
|
||||||
func _get_importer_name() -> String:
|
func _get_importer_name() -> String:
|
||||||
|
|
|
@ -4,7 +4,7 @@ msgstr ""
|
||||||
"POT-Creation-Date: \n"
|
"POT-Creation-Date: \n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: penghao123456、憨憨羊の宇航鸽鸽\n"
|
"Language-Team: penghao123456、憨憨羊の宇航鸽鸽、ABShinri\n"
|
||||||
"Language: zh\n"
|
"Language: zh\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
@ -29,6 +29,9 @@ msgstr "清空历史记录"
|
||||||
msgid "save_all_files"
|
msgid "save_all_files"
|
||||||
msgstr "保存所有文件"
|
msgstr "保存所有文件"
|
||||||
|
|
||||||
|
msgid "find_in_files"
|
||||||
|
msgstr "在文件中查找"
|
||||||
|
|
||||||
msgid "test_dialogue"
|
msgid "test_dialogue"
|
||||||
msgstr "测试对话"
|
msgstr "测试对话"
|
||||||
|
|
||||||
|
@ -51,10 +54,10 @@ msgid "docs"
|
||||||
msgstr "文档"
|
msgstr "文档"
|
||||||
|
|
||||||
msgid "insert.wave_bbcode"
|
msgid "insert.wave_bbcode"
|
||||||
msgstr "BBCode [lb]wave[rb]"
|
msgstr "波浪效果"
|
||||||
|
|
||||||
msgid "insert.shake_bbcode"
|
msgid "insert.shake_bbcode"
|
||||||
msgstr "BBCode [lb]wave[rb]"
|
msgstr "抖动效果"
|
||||||
|
|
||||||
msgid "insert.typing_pause"
|
msgid "insert.typing_pause"
|
||||||
msgstr "输入间隔"
|
msgstr "输入间隔"
|
||||||
|
@ -95,6 +98,9 @@ msgstr "结束对话"
|
||||||
msgid "generate_line_ids"
|
msgid "generate_line_ids"
|
||||||
msgstr "生成行 ID"
|
msgstr "生成行 ID"
|
||||||
|
|
||||||
|
msgid "save_characters_to_csv"
|
||||||
|
msgstr "保存角色到 CSV"
|
||||||
|
|
||||||
msgid "save_to_csv"
|
msgid "save_to_csv"
|
||||||
msgstr "生成 CSV"
|
msgstr "生成 CSV"
|
||||||
|
|
||||||
|
@ -134,6 +140,9 @@ msgstr "在 Godot 侧边栏中显示"
|
||||||
msgid "settings.revert_to_default_test_scene"
|
msgid "settings.revert_to_default_test_scene"
|
||||||
msgstr "重置测试场景设定"
|
msgstr "重置测试场景设定"
|
||||||
|
|
||||||
|
msgid "settings.default_balloon_hint"
|
||||||
|
msgstr "设置调用 \"DialogueManager.show_balloon()\" 时使用的对话框"
|
||||||
|
|
||||||
msgid "settings.autoload"
|
msgid "settings.autoload"
|
||||||
msgstr "Autoload"
|
msgstr "Autoload"
|
||||||
|
|
||||||
|
@ -150,10 +159,10 @@ msgid "settings.missing_keys_hint"
|
||||||
msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。"
|
msgstr "如果你使用静态键,这将会帮助你寻找未添加至翻译文件的键。"
|
||||||
|
|
||||||
msgid "settings.characters_translations"
|
msgid "settings.characters_translations"
|
||||||
msgstr "在翻译文件中导出角色名。"
|
msgstr "在翻译文件中导出角色名"
|
||||||
|
|
||||||
msgid "settings.wrap_long_lines"
|
msgid "settings.wrap_long_lines"
|
||||||
msgstr "自动折行"
|
msgstr "文本编辑器自动换行"
|
||||||
|
|
||||||
msgid "settings.include_failed_responses"
|
msgid "settings.include_failed_responses"
|
||||||
msgstr "在判断条件失败时仍显示回复选项"
|
msgstr "在判断条件失败时仍显示回复选项"
|
||||||
|
@ -176,9 +185,39 @@ msgstr "当一个 Autoload 在这里被勾选,他的所有成员会被映射
|
||||||
msgid "settings.states_hint"
|
msgid "settings.states_hint"
|
||||||
msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。"
|
msgstr "比如,当你开启对于“Foo”的映射时,你可以将“Foo.bar”简写成“bar”。"
|
||||||
|
|
||||||
|
msgid "settings.recompile_warning"
|
||||||
|
msgstr "更改这些选项会强制重新编译所有的对话框,当你清楚在做什么的时候更改。"
|
||||||
|
|
||||||
|
msgid "settings.create_lines_for_responses_with_characters"
|
||||||
|
msgstr "回复项带角色名时(- char: response),会自动生成为选择后的下一句对话"
|
||||||
|
|
||||||
|
msgid "settings.include_characters_in_translations"
|
||||||
|
msgstr "导出 CSV 时包括角色名"
|
||||||
|
|
||||||
|
msgid "settings.include_notes_in_translations"
|
||||||
|
msgstr "导出 CSV 时包括注释(## comments)"
|
||||||
|
|
||||||
|
msgid "settings.check_for_updates"
|
||||||
|
msgstr "检查升级"
|
||||||
|
|
||||||
msgid "n_of_n"
|
msgid "n_of_n"
|
||||||
msgstr "第{index}个,共{total}个"
|
msgstr "第{index}个,共{total}个"
|
||||||
|
|
||||||
|
msgid "search.find"
|
||||||
|
msgstr "查找:"
|
||||||
|
|
||||||
|
msgid "search.find_all"
|
||||||
|
msgstr "查找全部..."
|
||||||
|
|
||||||
|
msgid "search.placeholder"
|
||||||
|
msgstr "请输入查找的内容"
|
||||||
|
|
||||||
|
msgid "search.replace_placeholder"
|
||||||
|
msgstr "请输入替换的内容"
|
||||||
|
|
||||||
|
msgid "search.replace_selected"
|
||||||
|
msgstr "替换勾选"
|
||||||
|
|
||||||
msgid "search.previous"
|
msgid "search.previous"
|
||||||
msgstr "查找上一个"
|
msgstr "查找上一个"
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ msgstr ""
|
||||||
"POT-Creation-Date: \n"
|
"POT-Creation-Date: \n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: 憨憨羊の宇航鴿鴿\n"
|
"Language-Team: 憨憨羊の宇航鴿鴿、ABShinri\n"
|
||||||
"Language: zh_TW\n"
|
"Language: zh_TW\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
@ -29,6 +29,9 @@ msgstr "清空歷史記錄"
|
||||||
msgid "save_all_files"
|
msgid "save_all_files"
|
||||||
msgstr "儲存所有檔案"
|
msgstr "儲存所有檔案"
|
||||||
|
|
||||||
|
msgid "find_in_files"
|
||||||
|
msgstr "在檔案中查找"
|
||||||
|
|
||||||
msgid "test_dialogue"
|
msgid "test_dialogue"
|
||||||
msgstr "測試對話"
|
msgstr "測試對話"
|
||||||
|
|
||||||
|
@ -51,10 +54,10 @@ msgid "docs"
|
||||||
msgstr "文檔"
|
msgstr "文檔"
|
||||||
|
|
||||||
msgid "insert.wave_bbcode"
|
msgid "insert.wave_bbcode"
|
||||||
msgstr "BBCode [lb]wave[rb]"
|
msgstr "波浪特效"
|
||||||
|
|
||||||
msgid "insert.shake_bbcode"
|
msgid "insert.shake_bbcode"
|
||||||
msgstr "BBCode [lb]wave[rb]"
|
msgstr "震動特效"
|
||||||
|
|
||||||
msgid "insert.typing_pause"
|
msgid "insert.typing_pause"
|
||||||
msgstr "輸入間隔"
|
msgstr "輸入間隔"
|
||||||
|
@ -95,6 +98,9 @@ msgstr "結束對話"
|
||||||
msgid "generate_line_ids"
|
msgid "generate_line_ids"
|
||||||
msgstr "生成行 ID"
|
msgstr "生成行 ID"
|
||||||
|
|
||||||
|
msgid "save_characters_to_csv"
|
||||||
|
msgstr "保存角色到 CSV"
|
||||||
|
|
||||||
msgid "save_to_csv"
|
msgid "save_to_csv"
|
||||||
msgstr "生成 CSV"
|
msgstr "生成 CSV"
|
||||||
|
|
||||||
|
@ -134,6 +140,9 @@ msgstr "在 Godot 側邊欄中顯示"
|
||||||
msgid "settings.revert_to_default_test_scene"
|
msgid "settings.revert_to_default_test_scene"
|
||||||
msgstr "重置測試場景設定"
|
msgstr "重置測試場景設定"
|
||||||
|
|
||||||
|
msgid "settings.default_balloon_hint"
|
||||||
|
msgstr "設置使用 \"DialogueManager.show_balloon()\" 时的对话框"
|
||||||
|
|
||||||
msgid "settings.autoload"
|
msgid "settings.autoload"
|
||||||
msgstr "Autoload"
|
msgstr "Autoload"
|
||||||
|
|
||||||
|
@ -176,9 +185,39 @@ msgstr "當一個 Autoload 在這裏被勾選,他的所有成員會被映射
|
||||||
msgid "settings.states_hint"
|
msgid "settings.states_hint"
|
||||||
msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。"
|
msgstr "比如,當你開啓對於“Foo”的映射時,你可以將“Foo.bar”簡寫成“bar”。"
|
||||||
|
|
||||||
|
msgid "settings.recompile_warning"
|
||||||
|
msgstr "更改這些選項會強制重新編譯所有的對話框,當你清楚在做什麼的時候更改。"
|
||||||
|
|
||||||
|
msgid "settings.create_lines_for_responses_with_characters"
|
||||||
|
msgstr "回覆項目帶角色名稱時(- char: response),會自動產生為選擇後的下一句對話"
|
||||||
|
|
||||||
|
msgid "settings.include_characters_in_translations"
|
||||||
|
msgstr "匯出 CSV 時包含角色名"
|
||||||
|
|
||||||
|
msgid "settings.include_notes_in_translations"
|
||||||
|
msgstr "匯出 CSV 時包括註解(## comments)"
|
||||||
|
|
||||||
|
msgid "settings.check_for_updates"
|
||||||
|
msgstr "檢查升級"
|
||||||
|
|
||||||
msgid "n_of_n"
|
msgid "n_of_n"
|
||||||
msgstr "第{index}個,共{total}個"
|
msgstr "第{index}個,共{total}個"
|
||||||
|
|
||||||
|
msgid "search.find"
|
||||||
|
msgstr "搜尋:"
|
||||||
|
|
||||||
|
msgid "search.find_all"
|
||||||
|
msgstr "搜尋全部..."
|
||||||
|
|
||||||
|
msgid "search.placeholder"
|
||||||
|
msgstr "請輸入搜尋的內容"
|
||||||
|
|
||||||
|
msgid "search.replace_placeholder"
|
||||||
|
msgstr "請輸入替換的內容"
|
||||||
|
|
||||||
|
msgid "search.replace_selected"
|
||||||
|
msgstr "替換勾選"
|
||||||
|
|
||||||
msgid "search.previous"
|
msgid "search.previous"
|
||||||
msgstr "搜尋上一個"
|
msgstr "搜尋上一個"
|
||||||
|
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
name="Dialogue Manager"
|
name="Dialogue Manager"
|
||||||
description="A simple but powerful branching dialogue system"
|
description="A simple but powerful branching dialogue system"
|
||||||
author="Nathan Hoad"
|
author="Nathan Hoad"
|
||||||
version="2.38.0"
|
version="2.39.1"
|
||||||
script="plugin.gd"
|
script="plugin.gd"
|
||||||
|
|
|
@ -145,6 +145,80 @@ func _build() -> bool:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
## Get the shortcuts used by the plugin
|
||||||
|
func get_editor_shortcuts() -> Dictionary:
|
||||||
|
var shortcuts: Dictionary = {
|
||||||
|
toggle_comment = [
|
||||||
|
_create_event("Ctrl+K"),
|
||||||
|
_create_event("Ctrl+Slash")
|
||||||
|
],
|
||||||
|
move_up = [
|
||||||
|
_create_event("Alt+Up")
|
||||||
|
],
|
||||||
|
move_down = [
|
||||||
|
_create_event("Alt+Down")
|
||||||
|
],
|
||||||
|
save = [
|
||||||
|
_create_event("Ctrl+Alt+S")
|
||||||
|
],
|
||||||
|
close_file = [
|
||||||
|
_create_event("Ctrl+W")
|
||||||
|
],
|
||||||
|
find_in_files = [
|
||||||
|
_create_event("Ctrl+Shift+F")
|
||||||
|
],
|
||||||
|
|
||||||
|
run_test_scene = [
|
||||||
|
_create_event("Ctrl+F5")
|
||||||
|
],
|
||||||
|
text_size_increase = [
|
||||||
|
_create_event("Ctrl+Equal")
|
||||||
|
],
|
||||||
|
text_size_decrease = [
|
||||||
|
_create_event("Ctrl+Minus")
|
||||||
|
],
|
||||||
|
text_size_reset = [
|
||||||
|
_create_event("Ctrl+0")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var paths = get_editor_interface().get_editor_paths()
|
||||||
|
var settings = load(paths.get_config_dir() + "/editor_settings-4.tres")
|
||||||
|
|
||||||
|
if not settings: return shortcuts
|
||||||
|
|
||||||
|
for s in settings.get("shortcuts"):
|
||||||
|
for key in shortcuts:
|
||||||
|
if s.name == "script_text_editor/%s" % key or s.name == "script_editor/%s" % key:
|
||||||
|
shortcuts[key] = []
|
||||||
|
for event in s.shortcuts:
|
||||||
|
if event is InputEventKey:
|
||||||
|
shortcuts[key].append(event)
|
||||||
|
|
||||||
|
return shortcuts
|
||||||
|
|
||||||
|
|
||||||
|
func _create_event(string: String) -> InputEventKey:
|
||||||
|
var event: InputEventKey = InputEventKey.new()
|
||||||
|
var bits = string.split("+")
|
||||||
|
event.keycode = OS.find_keycode_from_string(bits[bits.size() - 1])
|
||||||
|
event.shift_pressed = bits.has("Shift")
|
||||||
|
event.alt_pressed = bits.has("Alt")
|
||||||
|
if bits.has("Ctrl") or bits.has("Command"):
|
||||||
|
event.command_or_control_autoremap = true
|
||||||
|
return event
|
||||||
|
|
||||||
|
|
||||||
|
## Get the editor shortcut that matches an event
|
||||||
|
func get_editor_shortcut(event: InputEventKey) -> String:
|
||||||
|
var shortcuts: Dictionary = get_editor_shortcuts()
|
||||||
|
for key in shortcuts:
|
||||||
|
for shortcut in shortcuts.get(key, []):
|
||||||
|
if event.is_match(shortcut):
|
||||||
|
return key
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
## Get the current version
|
## Get the current version
|
||||||
func get_version() -> String:
|
func get_version() -> String:
|
||||||
var config: ConfigFile = ConfigFile.new()
|
var config: ConfigFile = ConfigFile.new()
|
||||||
|
|
|
@ -176,9 +176,5 @@ static func has_dotnet_solution() -> bool:
|
||||||
var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name])
|
var has_dotnet_solution: bool = FileAccess.file_exists("res://%s/%s.sln" % [directory, file_name])
|
||||||
set_user_value("has_dotnet_solution", has_dotnet_solution)
|
set_user_value("has_dotnet_solution", has_dotnet_solution)
|
||||||
return has_dotnet_solution
|
return has_dotnet_solution
|
||||||
else:
|
|
||||||
var plugin_path: String = new().get_script().resource_path.get_base_dir()
|
|
||||||
if not ResourceLoader.exists(plugin_path + "/DialogueManager.cs"): return false
|
|
||||||
if load(plugin_path + "/DialogueManager.cs") == null: return false
|
|
||||||
|
|
||||||
return true
|
return false
|
||||||
|
|
|
@ -11,7 +11,8 @@ const SUPPORTED_BUILTIN_TYPES = [
|
||||||
TYPE_DICTIONARY,
|
TYPE_DICTIONARY,
|
||||||
TYPE_QUATERNION,
|
TYPE_QUATERNION,
|
||||||
TYPE_COLOR,
|
TYPE_COLOR,
|
||||||
TYPE_SIGNAL
|
TYPE_SIGNAL,
|
||||||
|
TYPE_CALLABLE
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -181,19 +181,20 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||||
if not visible: return
|
if not visible: return
|
||||||
|
|
||||||
if event is InputEventKey and event.is_pressed():
|
if event is InputEventKey and event.is_pressed():
|
||||||
match event.as_text():
|
var shortcut: String = Engine.get_meta("DialogueManagerPlugin").get_editor_shortcut(event)
|
||||||
"Ctrl+Alt+S", "Command+Alt+S":
|
match shortcut:
|
||||||
get_viewport().set_input_as_handled()
|
"close_file":
|
||||||
save_file(current_file_path)
|
|
||||||
"Ctrl+W", "Command+W":
|
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
close_file(current_file_path)
|
close_file(current_file_path)
|
||||||
"Ctrl+F5", "Command+F5":
|
"save":
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
_on_test_button_pressed()
|
save_file(current_file_path)
|
||||||
"Ctrl+Shift+F", "Command+Shift+F":
|
"find_in_files":
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
_on_find_in_files_button_pressed()
|
_on_find_in_files_button_pressed()
|
||||||
|
"run_test_scene":
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
_on_test_button_pressed()
|
||||||
|
|
||||||
|
|
||||||
func apply_changes() -> void:
|
func apply_changes() -> void:
|
||||||
|
@ -1044,9 +1045,11 @@ func _on_files_list_file_middle_clicked(path: String):
|
||||||
func _on_files_popup_menu_about_to_popup() -> void:
|
func _on_files_popup_menu_about_to_popup() -> void:
|
||||||
files_popup_menu.clear()
|
files_popup_menu.clear()
|
||||||
|
|
||||||
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, KEY_MASK_CTRL | KEY_MASK_ALT | KEY_S)
|
var shortcuts: Dictionary = Engine.get_meta("DialogueManagerPlugin").get_editor_shortcuts()
|
||||||
|
|
||||||
|
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save"), ITEM_SAVE, OS.find_keycode_from_string(shortcuts.get("save")[0].as_text_keycode()))
|
||||||
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS)
|
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.save_as"), ITEM_SAVE_AS)
|
||||||
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, KEY_MASK_CTRL | KEY_W)
|
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close"), ITEM_CLOSE, OS.find_keycode_from_string(shortcuts.get("close_file")[0].as_text_keycode()))
|
||||||
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL)
|
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_all"), ITEM_CLOSE_ALL)
|
||||||
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS)
|
files_popup_menu.add_item(DialogueConstants.translate(&"buffer.close_other_files"), ITEM_CLOSE_OTHERS)
|
||||||
files_popup_menu.add_separator()
|
files_popup_menu.add_separator()
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 36625398e3ad45306521926c5190141a7ac925b0
|
Subproject commit b265f5cebab07f3af55c92f642b458db9c973a7c
|
|
@ -17,17 +17,16 @@ config/icon="res://icon.svg"
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
|
|
||||||
GlobalState="*res://State/Global/GlobalState.cs"
|
GlobalState="*res://State/Global/GlobalState.cs"
|
||||||
EventBus="*res://Events/EventBus.cs"
|
EventBus="*res://Events/EventBus.cs"
|
||||||
BaseUI="*res://UI/Base.tscn"
|
|
||||||
World="*res://Scenes/Level.tscn"
|
World="*res://Scenes/Level.tscn"
|
||||||
AudioManager="*res://Audio/AudioManager.cs"
|
AudioManager="*res://Audio/AudioManager.cs"
|
||||||
DebugUi="*res://UI/Debug/DebugUI.tscn"
|
DebugUi="*res://UI/Debug/DebugUI.tscn"
|
||||||
|
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
|
||||||
|
|
||||||
[dialogue_manager]
|
[dialogue_manager]
|
||||||
|
|
||||||
general/states=["GlobalState"]
|
general/states=["GlobalState", "World", "EventBus"]
|
||||||
general/wrap_lines=true
|
general/wrap_lines=true
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
|
@ -201,7 +200,7 @@ cast={
|
||||||
|
|
||||||
[internationalization]
|
[internationalization]
|
||||||
|
|
||||||
locale/translations_pot_files=PackedStringArray("res://Assets/Dialog/doc.dialogue", "res://Assets/Dialogue/doc.dialogue", "res://Assets/Dialogue/spellbook.dialogue", "res://Assets/Dialogue/books.dialogue", "res://Assets/Dialogue/clone-machine.dialogue")
|
locale/translations_pot_files=PackedStringArray("res://Assets/Dialogue/doc.dialogue", "res://Assets/Dialogue/books.dialogue", "res://Assets/Dialogue/clone-machine.dialogue", "res://Dialogue/snus-dealer.dialogue")
|
||||||
|
|
||||||
[layer_names]
|
[layer_names]
|
||||||
|
|
||||||
|
@ -215,6 +214,10 @@ locale/translations_pot_files=PackedStringArray("res://Assets/Dialog/doc.dialogu
|
||||||
2d_physics/layer_6="Interaction Receiver"
|
2d_physics/layer_6="Interaction Receiver"
|
||||||
2d_physics/layer_7="Interaction Trigger"
|
2d_physics/layer_7="Interaction Trigger"
|
||||||
|
|
||||||
|
[navigation]
|
||||||
|
|
||||||
|
2d/default_cell_size=16.0
|
||||||
|
|
||||||
[physics]
|
[physics]
|
||||||
|
|
||||||
2d/default_gravity=0.0
|
2d/default_gravity=0.0
|
||||||
|
@ -222,7 +225,5 @@ locale/translations_pot_files=PackedStringArray("res://Assets/Dialog/doc.dialogu
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
textures/canvas_textures/default_texture_filter=0
|
textures/canvas_textures/default_texture_filter=0
|
||||||
renderer/rendering_method="gl_compatibility"
|
|
||||||
renderer/rendering_method.mobile="gl_compatibility"
|
|
||||||
environment/defaults/default_clear_color=Color(0.301961, 0.301961, 0.301961, 1)
|
environment/defaults/default_clear_color=Color(0.301961, 0.301961, 0.301961, 1)
|
||||||
viewport/hdr_2d=true
|
viewport/hdr_2d=true
|
||||||
|
|
Loading…
Reference in New Issue