cultist npc + buttons wip

godot-4.1.1
John Montagu, the 4th Earl of Sandvich 2023-08-05 23:50:08 -07:00
parent b1840a63ef
commit 6b29cbf8fe
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
72 changed files with 3503 additions and 121 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,38 @@
[remap]
importer="font_data_dynamic"
type="FontFile"
uid="uid://6bvgjbmqovau"
path="res://.godot/imported/calamity.ttf-a5cf9ddf9de733f9de8155c59043bcbb.fontdata"
[deps]
source_file="res://Assets/Fonts/calamity/calamity.ttf"
dest_files=["res://.godot/imported/calamity.ttf-a5cf9ddf9de733f9de8155c59043bcbb.fontdata"]
[params]
Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=0
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[{
"chars": [],
"glyphs": [],
"name": "New Configuration",
"size": Vector2i(16, 0)
}]
language_support={}
script_support={}
opentype_features={}

View File

@ -0,0 +1,4 @@
The FontStruction “calamity,”
(https://fontstruct.com/fontstructions/show/2158964) by “Doph” is licensed
under a Creative Commons Attribution license
(http://creativecommons.org/licenses/by/3.0/).

View File

@ -0,0 +1,16 @@
The font file in this archive was created using Fontstruct the free, online
font-building tool.
This font was created by “Doph”.
This font has a homepage where this archive and other versions may be found:
https://fontstruct.com/fontstructions/show/2158964
Try Fontstruct at https://fontstruct.com
Its easy and its fun.
Fontstruct is copyright ©2022-2023 Rob Meek
LEGAL NOTICE:
In using this font you must comply with the licensing terms described in the
file “license.txt” included with this archive.
If you redistribute the font file in this archive, it must be accompanied by all
the other files from this archive, including this one.

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://dryqvdw6cffvf"
path="res://.godot/imported/switch-off.wav-0024f6c2bcc11e1a011aeb566d001d1f.sample"
[deps]
source_file="res://Assets/Sounds/switch-off.wav"
dest_files=["res://.godot/imported/switch-off.wav-0024f6c2bcc11e1a011aeb566d001d1f.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://djs15wmc7c77f"
path="res://.godot/imported/switch-on.wav-15db37d94b60bcbb1f01bd22cc4f0da4.sample"
[deps]
source_file="res://Assets/Sounds/switch-on.wav"
dest_files=["res://.godot/imported/switch-on.wav-15db37d94b60bcbb1f01bd22cc4f0da4.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://b1p5eylqc2bsy"
path="res://.godot/imported/ui-tick.wav-d0cf7e35255cfa69e990d4acd2ae6b0b.sample"
[deps]
source_file="res://Assets/Sounds/ui-tick.wav"
dest_files=["res://.godot/imported/ui-tick.wav-d0cf7e35255cfa69e990d4acd2ae6b0b.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cynlarq6mmvmd"
path="res://.godot/imported/doc-cultist.png-26cf20be254e797e5619dcf399e1e92a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/Characters/doc-cultist.png"
dest_files=["res://.godot/imported/doc-cultist.png-26cf20be254e797e5619dcf399e1e92a.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

View File

@ -0,0 +1,43 @@
[gd_resource type="ParticleProcessMaterial" load_steps=7 format=3 uid="uid://2tsvsp45elru"]
[sub_resource type="Gradient" id="Gradient_6k7fi"]
offsets = PackedFloat32Array(0.103704, 0.488889, 0.592593, 1)
colors = PackedColorArray(0.501961, 0.345098, 0.631373, 1, 0.501961, 0.345098, 0.631373, 1, 1, 1, 1, 1, 1, 1, 1, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_1phkb"]
gradient = SubResource("Gradient_6k7fi")
[sub_resource type="Gradient" id="Gradient_3tax5"]
offsets = PackedFloat32Array(0, 0.533333, 1)
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_13jjx"]
gradient = SubResource("Gradient_3tax5")
[sub_resource type="Curve" id="Curve_0565g"]
_data = [Vector2(0, 0.5), 0.0, 5.0, 0, 1, Vector2(0.1, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), -1.11111, 0.0, 1, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_k4txv"]
curve = SubResource("Curve_0565g")
[resource]
emission_shape = 2
emission_sphere_radius = 8.0
particle_flag_disable_z = true
direction = Vector3(0, -1, 0)
spread = 90.0
gravity = Vector3(0, 0, 0)
initial_velocity_min = 128.0
initial_velocity_max = 256.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
tangential_accel_min = -16.0
tangential_accel_max = 16.0
scale_min = 0.25
scale_max = 0.25
scale_curve = SubResource("CurveTexture_k4txv")
color_ramp = SubResource("GradientTexture1D_13jjx")
color_initial_ramp = SubResource("GradientTexture1D_1phkb")
turbulence_enabled = true
turbulence_noise_scale = 4.0

View File

@ -0,0 +1,10 @@
[gd_resource type="NoiseTexture2D" load_steps=2 format=3 uid="uid://dejwdw7or8c"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_udpsv"]
frequency = 0.1
[resource]
width = 256
height = 256
seamless = true
noise = SubResource("FastNoiseLite_udpsv")

View File

@ -0,0 +1,9 @@
[gd_resource type="NoiseTexture2D" load_steps=2 format=3 uid="uid://dngclnqt7pe3k"]
[sub_resource type="FastNoiseLite" id="FastNoiseLite_24q81"]
[resource]
width = 256
height = 256
seamless = true
noise = SubResource("FastNoiseLite_24q81")

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://crddevohy65we"
path="res://.godot/imported/arena-gate.png-ca0820a90b0e6a5968263b742bb1862a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/Props/arena-gate.png"
dest_files=["res://.godot/imported/arena-gate.png-ca0820a90b0e6a5968263b742bb1862a.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: 152 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://88iqlixjutsn"
path="res://.godot/imported/switch.png-f1a5070bd0995b912e6a24e1c48f03da.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/Props/switch.png"
dest_files=["res://.godot/imported/switch.png-f1a5070bd0995b912e6a24e1c48f03da.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: 202 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dqat7fjm20yie"
path="res://.godot/imported/arrow.png-8e07c35d14a15694847eda7a334fbb50.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Sprites/UI/arrow.png"
dest_files=["res://.godot/imported/arrow.png-8e07c35d14a15694847eda7a334fbb50.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

View File

@ -14,10 +14,21 @@ public partial class InteractionRay : RayCast2D
if (_trigger != value)
{
EmitSignal(SignalName.TriggerHit, value);
if (value is not null)
{
// focus on the new trigger
value.Focus();
}
}
if (_trigger is not null)
{
if (_trigger != value)
{
// unfocus from the old trigger
_trigger.Unfocus();
}
LastValidTrigger = value;
}

View File

@ -14,6 +14,20 @@ public partial class InteractionTrigger : Area2D
[Signal]
public delegate void UntargetEventHandler();
[Export]
public string PopupText { get; set; }
private Control _popup;
public override void _Ready()
{
base._Ready();
_popup = GetNode<Control>("Popup");
_popup.Visible = false;
_popup.GetNode<Label>("Label").Text = PopupText;
}
/// <summary>
/// Invokes or triggers an interaction to occur.
/// </summary>
@ -21,4 +35,14 @@ public partial class InteractionTrigger : Area2D
{
EmitSignal(SignalName.Interaction);
}
public void Focus()
{
_popup.Visible = true;
}
public void Unfocus()
{
_popup.Visible = false;
}
}

View File

@ -1,9 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://dldnp8eunxj3q"]
[gd_scene load_steps=7 format=3 uid="uid://dldnp8eunxj3q"]
[ext_resource type="Script" path="res://BoundingBoxes/InteractionTrigger.cs" id="1_uoemj"]
[ext_resource type="Theme" uid="uid://cksjbu3vrup5" path="res://UI/Themes/supalidl.tres" id="2_75ngm"]
[ext_resource type="Texture2D" uid="uid://dqat7fjm20yie" path="res://Assets/Sprites/UI/arrow.png" id="3_yx2aa"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_dfj3a"]
[sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_v3m5k"]
light_mode = 1
[sub_resource type="AtlasTexture" id="AtlasTexture_n00hm"]
atlas = ExtResource("3_yx2aa")
region = Rect2(0, 0, 12, 12)
[node name="InteractionTrigger" type="Area2D"]
collision_layer = 64
collision_mask = 0
@ -12,3 +21,53 @@ script = ExtResource("1_uoemj")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_dfj3a")
debug_color = Color(0.905882, 0, 0.745098, 0.419608)
[node name="Popup" type="Control" parent="."]
light_mask = 0
z_index = 255
z_as_relative = false
material = SubResource("CanvasItemMaterial_v3m5k")
layout_mode = 3
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -128.0
offset_top = -36.0
offset_right = 128.0
grow_horizontal = 2
grow_vertical = 0
[node name="Label" type="Label" parent="Popup"]
light_mask = 0
use_parent_material = true
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -23.0
offset_right = 23.0
offset_bottom = 19.0
grow_horizontal = 2
theme = ExtResource("2_75ngm")
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 15
text = "Okayeg"
horizontal_alignment = 1
[node name="TextureRect" type="TextureRect" parent="Popup"]
light_mask = 0
use_parent_material = true
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -8.0
offset_top = -16.0
offset_right = 8.0
grow_horizontal = 2
grow_vertical = 0
texture = SubResource("AtlasTexture_n00hm")

View File

@ -13,7 +13,7 @@ public partial class Character : CharacterBody2D, IFaction
public float Speed { get; protected set; } = 32.0f;
[Export]
public float Friction { get; set; } = 4.0f;
public float Friction { get; protected set; } = 4.0f;
[Export]
public float Mass
@ -26,6 +26,9 @@ public partial class Character : CharacterBody2D, IFaction
}
}
[Export]
public float Stealth { get; protected set; } = 0;
[Signal]
public delegate void HurtEventHandler(Events.HealthChangedArgs args);
@ -89,13 +92,16 @@ public partial class Character : CharacterBody2D, IFaction
public AnimationPlayer StunAnimation { get; set; }
public AnimationPlayer AttackAnimation { get; set; }
public override void _Ready()
{
// TODO: 80+ char line
MovementAnimation = GetNode<AnimationPlayer>("Animations/Movement");
HurtAnimation = GetNode<AnimationPlayer>("Animations/Hurt");
StunAnimation = GetNode<AnimationPlayer>("Animations/Stun");
GD.Print(Name + " " + MovementAnimation.CurrentAnimation);
AttackAnimation = GetNode<AnimationPlayer>("Animations/Attack");
Hurtbox.ReceivedDamage += OnReceivedDamage;
}
@ -318,4 +324,23 @@ public partial class Character : CharacterBody2D, IFaction
player.Play();
}
}
public bool HasLineOfSight(Character character, bool excludeClip = false)
{
var exclude = new Godot.Collections.Array<Godot.Rid>();
exclude.Add(GetRid());
var rayParams = new PhysicsRayQueryParameters2D
{
Exclude = exclude,
From = GlobalPosition,
To = character.GlobalPosition,
//CollisionMask = 1 + (uint)(excludeClip ? 0 : 16),
CollisionMask = 1,
};
var spaceState = GetWorld2D().DirectSpaceState;
var result = spaceState.IntersectRay(rayParams);
if (result.Count > 0)
GD.Print(result["collider"]);
return result.Count == 0;
}
}

View File

@ -38,7 +38,7 @@
[sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"]
resource_local_to_scene = true
shader = ExtResource("2_5jxom")
shader_parameter/color = Quaternion(1, 1, 1, 1)
shader_parameter/color = Vector4(1, 1, 1, 1)
shader_parameter/intensity = 0.0
shader_parameter/alpha_modulate = 1.0
@ -661,6 +661,12 @@ TelegraphAnimationPlayer = NodePath("../../Animations/Telegraph")
TelegraphState = NodePath("../Telegraph")
NPC = NodePath("../..")
[node name="ThinkerStateMachine" type="Node" parent="."]
[node name="Attack" type="Node" parent="ThinkerStateMachine"]
[node name="DashAttack" type="Node" parent="ThinkerStateMachine"]
[node name="Animations" type="Node" parent="."]
script = ExtResource("16_bsvls")
@ -752,10 +758,10 @@ Faction = 2
position = Vector2(0, -3.5)
shape = SubResource("RectangleShape2D_8lxmf")
[node name="Inventory" type="Node2D" parent="."]
[node name="Inventory" type="Node2D" parent="." node_paths=PackedStringArray("Items")]
y_sort_enabled = true
script = ExtResource("8_r8ejq")
Items = Array[Node2D]([])
Items = []
[node name="DocLance" parent="Inventory" instance=ExtResource("24_2es2r")]
unique_name_in_owner = true
@ -763,6 +769,7 @@ unique_name_in_owner = true
[node name="DocLanceHold" parent="Inventory" instance=ExtResource("26_0tntj")]
[node name="InteractionTrigger" parent="." instance=ExtResource("33_08dyq")]
PopupText = ""
[node name="CollisionShape2D" parent="InteractionTrigger" index="0"]
position = Vector2(0, -6)

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=50 format=3 uid="uid://ckxelxak8dko7"]
[gd_scene load_steps=48 format=3 uid="uid://ckxelxak8dko7"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="1_1xpe6"]
[ext_resource type="Script" path="res://Characters/Enemy.cs" id="2_jq8f8"]
@ -18,7 +18,6 @@
[ext_resource type="AudioStream" uid="uid://cruylv4pu2fo1" path="res://Assets/Sounds/footstep-tile.wav" id="14_2ql70"]
[ext_resource type="Texture2D" uid="uid://bej8thq7ruyty" path="res://Assets/Sprites/Characters/forsen2.png" id="16_lr46v"]
[ext_resource type="Script" path="res://Items/Inventory.cs" id="17_q8tne"]
[ext_resource type="PackedScene" uid="uid://dvqap2uhcah63" path="res://Items/Weapons/Sword.tscn" id="18_dqppu"]
[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="20_7qskd"]
[ext_resource type="AudioStream" uid="uid://k6kpdj1kv0jg" path="res://Assets/Sounds/splat.ogg" id="21_8714l"]
@ -166,8 +165,8 @@ tracks/0/keys = {
}
[sub_resource type="Animation" id="Animation_3w3u1"]
resource_name = "sword"
length = 0.3
resource_name = "attack"
length = 0.5
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@ -175,10 +174,10 @@ tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2),
"transitions": PackedFloat32Array(1, 1, 1),
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
"update": 1,
"values": [12, 13, 14]
"values": [1, 2, 3, 4, 5]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_73mj7"]
@ -244,8 +243,6 @@ states/stop/position = Vector2(438, 100)
transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_sorqc"), "idle", "move", SubResource("AnimationNodeStateMachineTransition_ujrp0"), "move", "stop", SubResource("AnimationNodeStateMachineTransition_kjkm8"), "stop", "idle", SubResource("AnimationNodeStateMachineTransition_1ywlq"), "idle", "roll", SubResource("AnimationNodeStateMachineTransition_abs7t"), "roll", "idle", SubResource("AnimationNodeStateMachineTransition_qlka8"), "roll", "move", SubResource("AnimationNodeStateMachineTransition_ql2f3"), "move", "roll", SubResource("AnimationNodeStateMachineTransition_g1yba")]
graph_offset = Vector2(-335.315, -63.5708)
[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_jy6hr"]
[sub_resource type="CanvasTexture" id="CanvasTexture_pited"]
diffuse_texture = ExtResource("10_qbgyb")
@ -255,19 +252,26 @@ size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_cjk6b"]
size = Vector2(8, 8)
[node name="Enemy" type="CharacterBody2D" node_paths=PackedStringArray("DefaultSelectedItem", "Sprite", "Inventory", "StateMachine", "Hurtbox")]
[node name="Enemy" type="CharacterBody2D" node_paths=PackedStringArray("Sprite", "Inventory", "StateMachine", "Hurtbox")]
y_sort_enabled = true
texture_filter = 3
material = SubResource("ShaderMaterial_h78y7")
collision_layer = 6
collision_mask = 17
script = ExtResource("2_jq8f8")
DefaultSelectedItem = NodePath("Inventory/Sword")
PreferredWeightDistance = null
MaxWeightDistance = null
ShouldMoveWhenUsingItem = null
Speed = 64.0
Friction = null
Mass = null
Stealth = null
Health = null
Sprite = NodePath("Sprites/Node2D/Character")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
Hurtbox = NodePath("Hurtbox")
Faction = null
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")]
script = ExtResource("3_n5adw")
@ -323,7 +327,6 @@ libraries = {
[node name="AnimationTree" type="AnimationTree" parent="Animations"]
tree_root = SubResource("AnimationNodeStateMachine_0ukul")
anim_player = NodePath("../Movement")
parameters/playback = SubResource("AnimationNodeStateMachinePlayback_jy6hr")
parameters/conditions/idle = false
parameters/conditions/move = false
parameters/conditions/roll = false
@ -379,18 +382,14 @@ hframes = 35
position = Vector2(0, -4)
shape = SubResource("RectangleShape2D_bfqew")
[node name="Inventory" type="Node2D" parent="."]
[node name="Inventory" type="Node2D" parent="." node_paths=PackedStringArray("Items")]
position = Vector2(0, -4)
script = ExtResource("17_q8tne")
InventoryMap = {
"equip_1": 0,
"equip_2": 1
}
[node name="Sword" parent="Inventory" instance=ExtResource("18_dqppu")]
Items = []
[node name="Hurtbox" parent="." instance=ExtResource("20_7qskd")]
visible = false
Faction = null
[node name="CollisionShape2D" parent="Hurtbox" index="0"]
visible = false

View File

@ -46,10 +46,18 @@ public partial class NPC : Character
[Export]
public Items.Item DefaultSelectedItem { get; set; }
[Export]
public bool ShouldMoveWhenUsingItem { get; set; } = true;
[Export]
public State.Thinker.ThinkerStateMachine ThinkerStateMachine { get; set; }
public bool ShouldMove { get; set; } = true;
public bool CanAttack { get; set; } = true;
public Vector2 LastSeenPosition { get; set; }
protected float[] _weights = new float[16];
protected int _bestWeightIdx;
protected double _thinkTimeElapsed = 0;
@ -75,6 +83,20 @@ public partial class NPC : Character
{
Inventory.SelectedItem = DefaultSelectedItem;
}
Inventory.UsedItem += (Items.Item item) =>
{
if (item is Items.Weapon)
{
if (AttackAnimation is not null)
{
if (AttackAnimation.HasAnimation("attack"))
{
AttackAnimation.Play("attack");
}
}
}
};
}
public override void _Draw()
@ -102,8 +124,9 @@ public partial class NPC : Character
public virtual Character FindBestTarget()
{
float bestDist = float.MaxValue;
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)
@ -114,10 +137,24 @@ public partial class NPC : Character
continue;
}
float dist = Position.DistanceTo(character.Position);
if (dist < bestDist)
float score = 0;
score += Position.DistanceTo(character.Position);
score *= (character.Stealth + 1);
// if the character has enough stealth, the dot product of the
// enemy's current direction and to the character will affect
// the score
// TODO: implement
if (score < bestScore)
{
bestDist = dist;
// if the character has enough stealth, they won't be
// targeted if the NPC is not able to see
if (!HasLineOfSight(character) && character.Stealth >= 1)
{
continue;
}
bestScore = score;
bestChar = character;
}
}
@ -125,6 +162,18 @@ public partial class NPC : Character
return bestChar;
}
public override void _Process(double delta)
{
ThinkerStateMachine.Process(delta);
base._Process(delta);
}
public override void _PhysicsProcess(double delta)
{
ThinkerStateMachine.PhysicsProcess(delta);
base._PhysicsProcess(delta);
}
public void ThinkProcess(double delta)
{
if ((_thinkTimeElapsed += delta) > ThinkTime)
@ -136,13 +185,13 @@ public partial class NPC : Character
#endif
}
if (ShouldMove)
if (!ShouldMove || (!ShouldMoveWhenUsingItem && Inventory.IsUsingItem))
{
Direction = _weightDirs[_bestWeightIdx];
Direction = Vector2.Zero;
}
else
{
Direction = Vector2.Zero;
Direction = _weightDirs[_bestWeightIdx];
}
}

View File

@ -22,8 +22,6 @@ public sealed partial class Player : Character
public InteractionRay InteractionRay { get; private set; }
public AnimationPlayer AttackAnimation { get; set; }
public override void _Ready()
{
InteractionRay = GetNode<InteractionRay>("Direction2D/InteractionRay");
@ -34,8 +32,6 @@ public sealed partial class Player : Character
Visible = false;
};
AttackAnimation = GetNode<AnimationPlayer>("Animations/Attack");
base._Ready();
Inventory.UsedItem += (Items.Item item) =>

View File

@ -2,6 +2,7 @@
[ext_resource type="Script" path="res://Characters/Player.cs" id="1_flygr"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_ngsgt"]
[ext_resource type="Texture2D" uid="uid://dpepm54hjuyga" path="res://Assets/Sprites/Characters/forsen-hand.png" id="3_3dqh7"]
[ext_resource type="Texture2D" uid="uid://bej8thq7ruyty" path="res://Assets/Sprites/Characters/forsen2.png" id="4_5vird"]
[ext_resource type="PackedScene" uid="uid://cl56eadpklnbo" path="res://Utils/PlayerCamera.tscn" id="4_ym125"]
[ext_resource type="Script" path="res://State/Character/CharacterStateMachine.cs" id="5_rgckv"]
@ -280,8 +281,6 @@ states/stop/position = Vector2(438, 100)
transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_sorqc"), "idle", "move", SubResource("AnimationNodeStateMachineTransition_ujrp0"), "move", "stop", SubResource("AnimationNodeStateMachineTransition_kjkm8"), "stop", "idle", SubResource("AnimationNodeStateMachineTransition_1ywlq"), "idle", "roll", SubResource("AnimationNodeStateMachineTransition_abs7t"), "roll", "idle", SubResource("AnimationNodeStateMachineTransition_qlka8"), "roll", "move", SubResource("AnimationNodeStateMachineTransition_ql2f3"), "move", "roll", SubResource("AnimationNodeStateMachineTransition_g1yba")]
graph_offset = Vector2(-335.315, -63.5708)
[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_jln87"]
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_852jj"]
particle_flag_disable_z = true
spread = 180.0
@ -321,6 +320,7 @@ script = ExtResource("1_flygr")
Camera = NodePath("Camera2D")
DirectionMarker = NodePath("Direction2D")
Speed = 80.0
HandTexture = ExtResource("3_3dqh7")
Sprite = NodePath("Sprites/Node2D/Character")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
@ -391,7 +391,6 @@ libraries = {
[node name="AnimationTree" type="AnimationTree" parent="Animations"]
tree_root = SubResource("AnimationNodeStateMachine_0ukul")
anim_player = NodePath("../Movement")
parameters/playback = SubResource("AnimationNodeStateMachinePlayback_jln87")
parameters/conditions/idle = false
parameters/conditions/move = false
parameters/conditions/roll = false
@ -476,9 +475,10 @@ text = "lol"
label_settings = SubResource("LabelSettings_q5h1n")
horizontal_alignment = 1
[node name="Inventory" type="Node2D" parent="."]
[node name="Inventory" type="Node2D" parent="." node_paths=PackedStringArray("Items")]
position = Vector2(0, -4)
script = ExtResource("7_xyenu")
Items = []
InventoryMap = {
"equip_1": 0,
"equip_2": 1
@ -486,6 +486,13 @@ InventoryMap = {
[node name="Node2D" parent="Inventory" instance=ExtResource("7_4rxuv")]
visible = false
InitialVelocity = 0.0
ShouldFreezeAngleOnUse = true
MinDistanceHint = 0.0
MaxDistanceHint = 0.0
ItemName = ""
Description = ""
CanStack = false
[node name="Railgun" parent="Inventory" instance=ExtResource("21_n8w32")]
UseTime = 0.2

View File

@ -0,0 +1,560 @@
[gd_scene load_steps=43 format=3 uid="uid://3bcudbixirkj"]
[ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_2lfeo"]
[ext_resource type="Script" path="res://Characters/Enemy.cs" id="2_l16dp"]
[ext_resource type="Script" path="res://State/Character/CharacterStateMachine.cs" id="3_lj2a2"]
[ext_resource type="Script" path="res://State/Character/NPCIdleState.cs" id="4_38uyt"]
[ext_resource type="Script" path="res://State/Character/NPCMoveState.cs" id="5_0peb6"]
[ext_resource type="Script" path="res://Utils/AnimationManager.cs" id="6_1a373"]
[ext_resource type="Script" path="res://State/Thinker/ThinkerStateMachine.cs" id="6_8y4xc"]
[ext_resource type="Script" path="res://State/Thinker/PursueState.cs" id="7_q01ij"]
[ext_resource type="Animation" uid="uid://8e8r3y1imvsx" path="res://Assets/Animations/stun.res" id="8_n0iqj"]
[ext_resource type="Script" path="res://State/Thinker/AttackState.cs" id="8_woh6n"]
[ext_resource type="Material" uid="uid://bat28samf7ukd" path="res://Assets/Sprites/Particles/NPCDamageProcessMaterial.tres" id="9_x36vb"]
[ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="10_io6bw"]
[ext_resource type="Material" uid="uid://2tsvsp45elru" path="res://Assets/Sprites/Particles/NPCDeathParticles.tres" id="10_yyggy"]
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="12_vfix1"]
[ext_resource type="AudioStream" uid="uid://k6kpdj1kv0jg" path="res://Assets/Sounds/splat.ogg" id="15_luroj"]
[ext_resource type="Texture2D" uid="uid://cynlarq6mmvmd" path="res://Assets/Sprites/Characters/doc-cultist.png" id="16_licfs"]
[ext_resource type="PackedScene" uid="uid://bgavhkdtbx2o6" path="res://Items/Weapons/ProjectileSpawner.tscn" id="17_dmlbb"]
[ext_resource type="Script" path="res://Items/Inventory.cs" id="17_sjq8t"]
[ext_resource type="PackedScene" uid="uid://cjgxyhgcyvsv7" path="res://BoundingBoxes/Hurtbox.tscn" id="18_ajs2x"]
[ext_resource type="PackedScene" uid="uid://1y5r6sklwgrp" path="res://Entities/UnwantedFrequency.tscn" id="18_lwg36"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_2fq6c"]
resource_local_to_scene = true
shader = ExtResource("2_2lfeo")
shader_parameter/color = Vector4(1, 1, 1, 1)
shader_parameter/intensity = 0.0
shader_parameter/alpha_modulate = 1.0
[sub_resource type="Animation" id="Animation_rqtrh"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Sprites/Node2D/Character:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, -8)]
}
[sub_resource type="Animation" id="Animation_qws2q"]
resource_name = "idle"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Sprites/Node2D/Character:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [Vector2(0, -9), Vector2(0, -7), Vector2(0, -9)]
}
[sub_resource type="Animation" id="Animation_dwyme"]
resource_name = "move"
length = 0.8
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = false
tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Sprites/Node2D/Character:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.4, 0.8),
"transitions": PackedFloat32Array(-2, -2, -2),
"update": 0,
"values": [Vector2(0, -9), Vector2(0, -7), Vector2(0, -9)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hvti5"]
_data = {
"RESET": SubResource("Animation_rqtrh"),
"idle": SubResource("Animation_qws2q"),
"move": SubResource("Animation_dwyme")
}
[sub_resource type="Animation" id="Animation_adxyh"]
resource_local_to_scene = true
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Effects/SpawnParticles:emitting")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_3w3u1"]
resource_name = "attack"
length = 2.0
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("../Sprites/Node2D/Character:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("../Effects/SpawnParticles:emitting")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 2),
"transitions": PackedFloat32Array(1, 1),
"update": 1,
"values": [true, false]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6wkji"]
_data = {
"RESET": SubResource("Animation_adxyh"),
"attack": SubResource("Animation_3w3u1")
}
[sub_resource type="Animation" id="Animation_k6l16"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:material:shader_parameter/alpha_modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Effects/DeathParticles:emitting")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Effects/HurtParticles:emitting")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("Sprites/Node2D/Character:frame")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [8]
}
[sub_resource type="Animation" id="Animation_lhc4c"]
resource_name = "death"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Effects/DeathParticles:emitting")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:material:shader_parameter/alpha_modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [1.0, 0.0]
}
[sub_resource type="Animation" id="Animation_0vgmg"]
resource_local_to_scene = true
resource_name = "hurt"
length = 0.2
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:material:shader_parameter/intensity")
tracks/0/interp = 2
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.2),
"transitions": PackedFloat32Array(4, 4, 4, 4),
"update": 0,
"values": [1.0, 0.0, 1.0, 0.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Effects/HurtParticles:emitting")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
tracks/2/type = "method"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Effects/HurtParticles")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0.1),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"restart"
}]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = false
tracks/3/path = NodePath("Sprites/Node2D/Character:frame")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [8]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_rc55s"]
_data = {
"RESET": SubResource("Animation_k6l16"),
"death": SubResource("Animation_lhc4c"),
"hurt": SubResource("Animation_0vgmg")
}
[sub_resource type="Animation" id="Animation_7j54f"]
length = 0.001
[sub_resource type="AnimationLibrary" id="AnimationLibrary_kks2p"]
_data = {
"RESET": SubResource("Animation_7j54f"),
"stun": ExtResource("8_n0iqj")
}
[sub_resource type="CanvasTexture" id="CanvasTexture_pited"]
diffuse_texture = ExtResource("12_vfix1")
[sub_resource type="Gradient" id="Gradient_b2o0f"]
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_iyaih"]
gradient = SubResource("Gradient_b2o0f")
[sub_resource type="Curve" id="Curve_30p4b"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.5), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_5uulw"]
curve = SubResource("Curve_30p4b")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_qdhau"]
particle_flag_disable_z = true
spread = 180.0
gravity = Vector3(0, 0, 0)
initial_velocity_min = 32.0
initial_velocity_max = 32.0
angular_velocity_min = 90.0
angular_velocity_max = 90.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
linear_accel_min = -64.0
linear_accel_max = -32.0
tangential_accel_min = 8.0
tangential_accel_max = 8.0
scale_min = 0.13
scale_max = 0.25
scale_curve = SubResource("CurveTexture_5uulw")
color = Color(1, 0, 0, 1)
color_ramp = SubResource("GradientTexture1D_iyaih")
[sub_resource type="RectangleShape2D" id="RectangleShape2D_bfqew"]
size = Vector2(12, 8)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1gjgc"]
size = Vector2(12, 16)
[node name="Cultist" type="CharacterBody2D" node_paths=PackedStringArray("DefaultSelectedItem", "ThinkerStateMachine", "Sprite", "Inventory", "StateMachine", "Hurtbox")]
y_sort_enabled = true
texture_filter = 3
material = SubResource("ShaderMaterial_2fq6c")
collision_layer = 6
collision_mask = 17
script = ExtResource("2_l16dp")
PreferredWeightDistance = null
MaxWeightDistance = null
DefaultSelectedItem = NodePath("Inventory/ProjectileSpawner")
ShouldMoveWhenUsingItem = false
ThinkerStateMachine = NodePath("ThinkerStateMachine")
Speed = 40.0
Friction = 8.0
Mass = 0.5
Stealth = null
Health = 170.0
Sprite = NodePath("Sprites/Node2D/Character")
Inventory = NodePath("Inventory")
StateMachine = NodePath("StateMachine")
Hurtbox = NodePath("Hurtbox")
Faction = null
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState", "Character")]
script = ExtResource("3_lj2a2")
InitialState = NodePath("Idle")
Character = NodePath("..")
[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("MoveState", "Character")]
script = ExtResource("4_38uyt")
MoveState = NodePath("../Move")
Character = NodePath("../..")
[node name="Move" type="Node" parent="StateMachine" node_paths=PackedStringArray("IdleState", "Character")]
script = ExtResource("5_0peb6")
IdleState = NodePath("../Idle")
Character = NodePath("../..")
[node name="ThinkerStateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
script = ExtResource("6_8y4xc")
InitialState = NodePath("Pursue")
[node name="Pursue" type="Node" parent="ThinkerStateMachine" node_paths=PackedStringArray("NavigationAgent", "AttackState", "NPC")]
script = ExtResource("7_q01ij")
NavigationAgent = NodePath("../../NavigationAgent2D")
AttackState = NodePath("../Attack")
MinDistanceToTarget = 96.0
MaxDistanceFromOrigin = null
LastSeenPosition = null
ThinkDelta = 0.05
NPC = NodePath("../..")
[node name="Attack" type="Node" parent="ThinkerStateMachine" node_paths=PackedStringArray("PassiveState", "PursueState", "NPC")]
script = ExtResource("8_woh6n")
PreferredWeightDistance = null
MaxWeightDistance = null
MaxDistanceToTarget = 128.0
PassiveState = NodePath("../Pursue")
PursueState = NodePath("../Pursue")
ThinkDelta = null
NPC = NodePath("../..")
[node name="Idle" type="Node" parent="ThinkerStateMachine"]
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="."]
path_postprocessing = 1
debug_enabled = true
[node name="Animations" type="Node" parent="."]
script = ExtResource("6_1a373")
[node name="Movement" type="AnimationPlayer" parent="Animations"]
libraries = {
"": SubResource("AnimationLibrary_hvti5")
}
[node name="Attack" type="AnimationPlayer" parent="Animations"]
libraries = {
"": SubResource("AnimationLibrary_6wkji")
}
[node name="Hurt" type="AnimationPlayer" parent="Animations"]
root_node = NodePath("../..")
libraries = {
"": SubResource("AnimationLibrary_rc55s")
}
[node name="Stun" type="AnimationPlayer" parent="Animations"]
libraries = {
"": SubResource("AnimationLibrary_kks2p")
}
[node name="Effects" type="Node2D" parent="."]
[node name="HurtParticles" type="GPUParticles2D" parent="Effects"]
position = Vector2(0, -8)
emitting = false
process_material = ExtResource("9_x36vb")
texture = ExtResource("10_io6bw")
lifetime = 0.4
one_shot = true
explosiveness = 1.0
[node name="DeathParticles" type="GPUParticles2D" parent="Effects"]
emitting = false
amount = 32
process_material = ExtResource("10_yyggy")
texture = SubResource("CanvasTexture_pited")
lifetime = 2.0
one_shot = true
preprocess = 0.1
explosiveness = 0.9
[node name="SpawnParticles" type="GPUParticles2D" parent="Effects"]
emitting = false
amount = 24
process_material = SubResource("ParticleProcessMaterial_qdhau")
texture = ExtResource("12_vfix1")
[node name="HurtSound" type="AudioStreamPlayer2D" parent="Effects"]
stream = ExtResource("15_luroj")
[node name="Sprites" type="Node2D" parent="."]
y_sort_enabled = true
use_parent_material = true
rotation = 6.28319
[node name="Node2D" type="Node2D" parent="Sprites"]
use_parent_material = true
[node name="Character" type="Sprite2D" parent="Sprites/Node2D"]
use_parent_material = true
position = Vector2(0, -8)
texture = ExtResource("16_licfs")
offset = Vector2(0, -4)
hframes = 6
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -4)
shape = SubResource("RectangleShape2D_bfqew")
[node name="Inventory" type="Node2D" parent="." node_paths=PackedStringArray("Items")]
position = Vector2(0, -4)
script = ExtResource("17_sjq8t")
Items = []
[node name="ProjectileSpawner" parent="Inventory" instance=ExtResource("17_dmlbb")]
Projectile = ExtResource("18_lwg36")
ShouldOverrideProjectileDamage = false
ShouldRotate = false
AngleDeviation = null
ChargeTime = null
Damage = null
UseTime = 2.0
Knockback = null
InitialVelocity = null
ShouldHideIdle = null
ShouldFreezeAngleOnUse = null
MinDistanceHint = null
MaxDistanceHint = null
ItemName = null
Description = null
CanStack = null
[node name="Hurtbox" parent="." instance=ExtResource("18_ajs2x")]
Faction = null
[node name="CollisionShape2D" parent="Hurtbox" index="0"]
position = Vector2(0, -8)
shape = SubResource("RectangleShape2D_1gjgc")
[editable path="Hurtbox"]

View File

@ -0,0 +1,64 @@
using Godot;
using SupaLidlGame.Extensions;
namespace SupaLidlGame.Entities;
public partial class DynamicDoor : StaticBody2D
{
[Export]
public string MapStateKey { get; set; }
[Export]
public Godot.Collections.Array<Node2D> VisibleOnToggle { get; set; } = new();
[Export]
public bool DefaultState { get; set; }
private AnimationPlayer _animPlayer;
public override void _Ready()
{
_animPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
var globalState = this.GetGlobalState();
globalState.MapState.MapStateBoolChanged += OnMapStateChanged;
RefreshMapState((bool)globalState.MapState[MapStateKey]);
}
public virtual void OnMapStateChanged(string key, bool value)
{
GD.Print("Map state changed");
if (key == MapStateKey)
{
foreach (Node2D node in VisibleOnToggle)
{
// this is so extra effects are not played or showed when the
// door opens/closes from loading the map state.
node.Visible = true;
}
RefreshMapState(value);
}
}
private void RefreshMapState(bool value)
{
if (value)
{
Open();
}
else
{
Close();
}
}
public virtual void Open()
{
_animPlayer?.TryPlay("open");
}
public virtual void Close()
{
_animPlayer?.TryPlay("cose");
}
}

View File

@ -0,0 +1,64 @@
using Godot;
using SupaLidlGame.Extensions;
namespace SupaLidlGame.Entities;
public partial class DynamicDoorSwitch : StaticBody2D
{
[Export]
public BoundingBoxes.InteractionTrigger InteractionTrigger { get; set; }
[Export]
public string MapStateKey { get; set; }
[Export]
public Godot.Collections.Array<Node2D> VisibleOnToggle { get; set; } = new();
private AnimationPlayer _animPlayer;
public override void _Ready()
{
_animPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
var globalState = this.GetGlobalState();
var doorState = globalState.MapState[MapStateKey];
if (!doorState.Equals(default))
{
if (!(bool)doorState)
{
InteractionTrigger.Interaction += OnInteraction;
}
}
}
private void RefreshMapState(Variant value)
{
if (value.Equals(default))
{
return;
}
if ((bool)value)
{
_animPlayer?.TryPlay("on");
}
else
{
_animPlayer?.TryPlay("off");
}
}
public void OnInteraction()
{
var globalState = this.GetGlobalState();
globalState.MapState[MapStateKey] = true;
RefreshMapState(true);
GD.Print($"{MapStateKey} is now on");
foreach (Node2D node in VisibleOnToggle)
{
node.Visible = true;
}
}
}

View File

@ -10,13 +10,19 @@ public partial class UnwantedFrequency : Projectile, Utils.ITarget
[Export]
public float HomingVelocity { get; set; } = 1;
public Utils.Trail Trail { get; set; }
public Node2D TrailRotation { get; set; }
public Node2D TrailPosition { get; set; }
public GpuParticles2D DeathParticles { get; set; }
public GpuParticles2D SpawnParticles { get; set; }
public Timer DeferDeathTimer { get; set; }
public SceneTreeTimer DeferNeutralTeamTimer { get; set; }
public Utils.Trail Trail { get; private set; }
public Node2D TrailRotation { get; private set; }
public Node2D TrailPosition { get; private set; }
public GpuParticles2D DeathParticles { get; private set; }
public GpuParticles2D SpawnParticles { get; private set; }
public Timer DeferDeathTimer { get; private set; }
public SceneTreeTimer DeferNeutralTeamTimer { get; private set; }
private double _currentLifetime = 0;
@ -66,6 +72,7 @@ public partial class UnwantedFrequency : Projectile, Utils.ITarget
};
DeferDeathTimer.Start();
DeathParticles.Emitting = true;
SpawnParticles.Emitting = false;
GetNode<AudioStreamPlayer2D>("Sound").Stop();
GetNode<AnimationPlayer>("AnimationPlayer").Play("death");
}

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=19 format=3 uid="uid://1y5r6sklwgrp"]
[gd_scene load_steps=22 format=3 uid="uid://1y5r6sklwgrp"]
[ext_resource type="Script" path="res://Entities/UnwantedFrequency.cs" id="1_6sbe0"]
[ext_resource type="PackedScene" uid="uid://du5vhccg75nrq" path="res://BoundingBoxes/Hitbox.tscn" id="2_gxtvd"]
[ext_resource type="PackedScene" uid="uid://cojxmcin13ihm" path="res://Utils/Trail.tscn" id="3_67uhs"]
[ext_resource type="AudioStream" uid="uid://cn2wop7rfxku8" path="res://Assets/Sounds/karabast.mp3" id="4_pbgsi"]
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="5_qbbx7"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_30y8q"]
size = Vector2(8, 8)
@ -23,46 +24,52 @@ colors = PackedColorArray(1, 1, 1, 1, 1, 0.00784314, 0.215686, 0.784314, 1, 0, 0
[sub_resource type="GradientTexture1D" id="GradientTexture1D_yfhnr"]
gradient = SubResource("Gradient_2q0ut")
[sub_resource type="Curve" id="Curve_8kv0q"]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.5, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_es0lb"]
curve = SubResource("Curve_8kv0q")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_eh1hw"]
particle_flag_disable_z = true
spread = 180.0
gravity = Vector3(0, 0, 0)
initial_velocity_max = 100.0
angular_velocity_min = 45.0
angular_velocity_max = 90.0
orbit_velocity_min = 0.0
initial_velocity_min = 25.0
initial_velocity_max = 50.0
orbit_velocity_min = 1.0
orbit_velocity_max = 2.0
linear_accel_min = -8.0
tangential_accel_max = 8.0
scale_min = 0.1
scale_max = 0.2
scale_curve = SubResource("CurveTexture_es0lb")
color_ramp = SubResource("GradientTexture1D_yfhnr")
[sub_resource type="Gradient" id="Gradient_5hy7c"]
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
offsets = PackedFloat32Array(0, 0.4, 1)
colors = PackedColorArray(1, 1, 1, 1, 1, 0.784314, 0.784314, 0.25098, 1, 0, 0, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_iyaih"]
[sub_resource type="GradientTexture1D" id="GradientTexture1D_1bgot"]
gradient = SubResource("Gradient_5hy7c")
[sub_resource type="Curve" id="Curve_wt1cb"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.2, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.5), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_5uulw"]
[sub_resource type="CurveTexture" id="CurveTexture_n73if"]
curve = SubResource("Curve_wt1cb")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_olfm2"]
particle_flag_disable_z = true
spread = 180.0
gravity = Vector3(0, 0, 0)
initial_velocity_min = 32.0
initial_velocity_max = 32.0
angular_velocity_min = 90.0
angular_velocity_max = 90.0
initial_velocity_min = 8.0
initial_velocity_max = 16.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
tangential_accel_min = 8.0
tangential_accel_max = 8.0
scale_max = 2.0
scale_curve = SubResource("CurveTexture_5uulw")
color = Color(1, 0, 0, 1)
color_ramp = SubResource("GradientTexture1D_iyaih")
scale_curve = SubResource("CurveTexture_n73if")
color_ramp = SubResource("GradientTexture1D_1bgot")
[sub_resource type="Animation" id="Animation_w1abs"]
length = 0.001
@ -109,10 +116,12 @@ Speed = 124.0
Direction = Vector2(1, 1)
Hitbox = NodePath("Hitbox")
Lifetime = 4.0
Delay = 1.0
[node name="Hitbox" parent="." instance=ExtResource("2_gxtvd")]
collision_layer = 0
monitorable = false
priority = 5
Damage = 12.0
Knockback = 324.0
@ -145,19 +154,22 @@ autoplay = true
max_distance = 64.0
attenuation = 8.0
[node name="DeathParticles" type="GPUParticles2D" parent="."]
emitting = false
process_material = SubResource("ParticleProcessMaterial_eh1hw")
lifetime = 2.0
one_shot = true
explosiveness = 0.8
[node name="SpawnParticles" type="GPUParticles2D" parent="."]
emitting = false
amount = 16
process_material = SubResource("ParticleProcessMaterial_eh1hw")
texture = ExtResource("5_qbbx7")
lifetime = 2.0
explosiveness = 0.1
[node name="DeathParticles" type="GPUParticles2D" parent="."]
emitting = false
amount = 12
process_material = SubResource("ParticleProcessMaterial_olfm2")
texture = ExtResource("5_qbbx7")
lifetime = 2.0
one_shot = true
preprocess = 0.1
explosiveness = 1.0
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]

View File

@ -0,0 +1,24 @@
using Godot;
public static class AnimationPlayerExtensions
{
public static bool TryPlay(this AnimationPlayer player, string name)
{
var hasAnimation = player.HasAnimation(name);
if (hasAnimation)
{
player.Play(name);
}
return hasAnimation;
}
public static bool TryQueue(this AnimationPlayer player, string name)
{
var hasAnimation = player.HasAnimation(name);
if (hasAnimation)
{
player.Queue(name);
}
return hasAnimation;
}
}

View File

@ -0,0 +1,45 @@
using Godot;
namespace SupaLidlGame.Items.Weapons;
public partial class ProjectileSpawner : Ranged
{
[Export]
public PackedScene Projectile { get; set; }
[Export]
public bool ShouldOverrideProjectileDamage { get; set; } = true;
[Export]
public bool ShouldRotate { get; set; } = true;
public override void Attack()
{
var map = Utils.World.Instance.CurrentMap;
var projectile = map.SpawnEntity<Entities.Projectile>(Projectile);
projectile.Hitbox.Faction = Character.Faction;
projectile.Direction = Character.Target.Normalized();
projectile.GlobalPosition = GlobalPosition;
if (ShouldRotate)
{
projectile.GlobalRotation = projectile.Direction.Angle();
}
if (ShouldOverrideProjectileDamage)
{
if (projectile.Hitbox is not null)
{
projectile.Hitbox.Damage = Damage;
}
}
if (projectile is Utils.ITarget target)
{
if (Character is Characters.NPC npc)
{
target.CharacterTarget = npc.FindBestTarget();
}
}
}
}

View File

@ -0,0 +1,24 @@
[gd_scene load_steps=5 format=3 uid="uid://bgavhkdtbx2o6"]
[ext_resource type="Script" path="res://Items/Weapons/ProjectileSpawner.cs" id="1_8b4lf"]
[ext_resource type="Script" path="res://State/Weapon/RangedIdleState.cs" id="2_cm0yp"]
[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="2_mjoh2"]
[ext_resource type="Script" path="res://State/Weapon/RangedFireState.cs" id="3_uigar"]
[node name="ProjectileSpawner" type="Node2D" node_paths=PackedStringArray("StateMachine")]
script = ExtResource("1_8b4lf")
StateMachine = NodePath("StateMachine")
[node name="StateMachine" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
script = ExtResource("2_mjoh2")
InitialState = NodePath("Idle")
[node name="Idle" type="Node" parent="StateMachine" node_paths=PackedStringArray("FireState", "Weapon")]
script = ExtResource("2_cm0yp")
FireState = NodePath("../Fire")
Weapon = NodePath("../..")
[node name="Fire" type="Node" parent="StateMachine" node_paths=PackedStringArray("Weapon", "IdleState")]
script = ExtResource("3_uigar")
Weapon = NodePath("../..")
IdleState = NodePath("../Idle")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=36 format=3 uid="uid://dvqap2uhcah63"]
[gd_scene load_steps=35 format=3 uid="uid://dvqap2uhcah63"]
[ext_resource type="Script" path="res://Items/Weapons/Sword.cs" id="1_mlo73"]
[ext_resource type="Script" path="res://State/Weapon/WeaponStateMachine.cs" id="2_vwirq"]
@ -351,8 +351,6 @@ states/use/position = Vector2(609, 75)
transitions = ["Start", "anticipate", SubResource("AnimationNodeStateMachineTransition_esyoj"), "use", "RESET", SubResource("AnimationNodeStateMachineTransition_kg3rd"), "RESET", "anticipate", SubResource("AnimationNodeStateMachineTransition_twtoe"), "anticipate", "anticipate_bot", SubResource("AnimationNodeStateMachineTransition_73wvy"), "anticipate_bot", "use", SubResource("AnimationNodeStateMachineTransition_4wst0"), "anticipate", "use", SubResource("AnimationNodeStateMachineTransition_2lfol")]
graph_offset = Vector2(0, -104.073)
[sub_resource type="AnimationNodeStateMachinePlayback" id="AnimationNodeStateMachinePlayback_o5g2u"]
[node name="Sword" type="Node2D" node_paths=PackedStringArray("Hitbox", "AnimationPlayer", "ParryParticles", "StateMachine", "Anchor", "HandAnchor")]
y_sort_enabled = true
texture_filter = 3
@ -368,8 +366,15 @@ Anchor = NodePath("Anchor")
Damage = 20.0
UseTime = 0.55
Knockback = 64.0
InitialVelocity = null
ShouldHideIdle = true
ShouldFreezeAngleOnUse = null
MinDistanceHint = null
MaxDistanceHint = null
HandAnchor = NodePath("Anchor/Node2D/Sprite2D/Hand")
ItemName = null
Description = null
CanStack = null
[node name="State" type="Node" parent="." node_paths=PackedStringArray("InitialState")]
script = ExtResource("2_vwirq")
@ -384,11 +389,13 @@ Sword = NodePath("../..")
script = ExtResource("4_j3cud")
Sword = NodePath("../..")
AttackState = NodePath("../Attack")
HasAlternateAninmation = null
[node name="Attack" type="Node" parent="State" node_paths=PackedStringArray("Sword", "IdleState")]
script = ExtResource("5_hmisb")
Sword = NodePath("../..")
IdleState = NodePath("../Idle")
HasAlternateAnimation = null
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_72txp")
@ -402,6 +409,7 @@ position = Vector2(2.40734, -0.55655)
rotation = 0.945464
width_curve = SubResource("Curve_4cxtp")
gradient = SubResource("Gradient_2ablm")
Frequency = null
[node name="Node2D" type="Node2D" parent="Anchor"]
y_sort_enabled = true
@ -439,11 +447,14 @@ libraries = {
tree_root = SubResource("AnimationNodeStateMachine_q4hbp")
anim_player = NodePath("../AnimationPlayer")
active = true
parameters/playback = SubResource("AnimationNodeStateMachinePlayback_o5g2u")
parameters/conditions/is_player = false
[node name="Hitbox" parent="." instance=ExtResource("3_up3ob")]
priority = 5
Damage = null
IsDisabled = true
Knockback = null
Faction = null
[node name="CollisionShape2D" parent="Hitbox" index="0"]
position = Vector2(4, 0)

View File

@ -0,0 +1,154 @@
[gd_scene load_steps=14 format=3 uid="uid://c5i3cq1kewljv"]
[ext_resource type="Script" path="res://Entities/DynamicDoor.cs" id="1_t6mj1"]
[ext_resource type="Texture2D" uid="uid://crddevohy65we" path="res://Assets/Sprites/Props/arena-gate.png" id="2_kvtjv"]
[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="3_i2hr3"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_yrdxe"]
size = Vector2(32, 25)
[sub_resource type="Gradient" id="Gradient_r12k6"]
colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_8saft"]
gradient = SubResource("Gradient_r12k6")
[sub_resource type="Curve" id="Curve_fbk1d"]
_data = [Vector2(0.5, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
point_count = 2
[sub_resource type="CurveTexture" id="CurveTexture_scj30"]
curve = SubResource("Curve_fbk1d")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_5k2ug"]
emission_shape = 3
emission_box_extents = Vector3(16, 1, 1)
particle_flag_disable_z = true
direction = Vector3(0, -1, 0)
gravity = Vector3(0, 0, 0)
initial_velocity_min = 4.0
initial_velocity_max = 8.0
orbit_velocity_min = 0.0
orbit_velocity_max = 0.0
scale_min = 0.25
scale_max = 0.25
scale_curve = SubResource("CurveTexture_scj30")
color = Color(1, 1, 1, 0.498039)
color_ramp = SubResource("GradientTexture1D_8saft")
[sub_resource type="Animation" id="Animation_ylaba"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Gate:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("CollisionShape2D:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_unbll"]
resource_name = "close"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Gate:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("CollisionShape2D:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [false]
}
[sub_resource type="Animation" id="Animation_1nbqx"]
resource_name = "open"
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Gate:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("CollisionShape2D:disabled")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [true]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3eva7"]
_data = {
"RESET": SubResource("Animation_ylaba"),
"close": SubResource("Animation_unbll"),
"open": SubResource("Animation_1nbqx")
}
[node name="ArenaDoor" type="StaticBody2D" node_paths=PackedStringArray("VisibleOnToggle")]
collision_mask = 0
script = ExtResource("1_t6mj1")
MapStateKey = "b_arena_depths_door_1"
VisibleOnToggle = [NodePath("GPUParticles2D"), NodePath("AudioStreamPlayer2D")]
[node name="Gate" type="Sprite2D" parent="."]
texture = ExtResource("2_kvtjv")
offset = Vector2(0, -16)
hframes = 2
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -12.5)
shape = SubResource("RectangleShape2D_yrdxe")
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
emitting = false
process_material = SubResource("ParticleProcessMaterial_5k2ug")
texture = ExtResource("3_i2hr3")
one_shot = true
explosiveness = 1.0
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_3eva7")
}
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]

View File

@ -0,0 +1,122 @@
[gd_scene load_steps=11 format=3 uid="uid://bs6xuujve2tsf"]
[ext_resource type="Script" path="res://Entities/DynamicDoorSwitch.cs" id="1_78qab"]
[ext_resource type="PackedScene" uid="uid://dldnp8eunxj3q" path="res://BoundingBoxes/InteractionTrigger.tscn" id="2_7j8p7"]
[ext_resource type="Texture2D" uid="uid://88iqlixjutsn" path="res://Assets/Sprites/Props/switch.png" id="3_pgkt4"]
[ext_resource type="AudioStream" uid="uid://djs15wmc7c77f" path="res://Assets/Sounds/switch-on.wav" id="4_cxkmr"]
[ext_resource type="AudioStream" uid="uid://dryqvdw6cffvf" path="res://Assets/Sounds/switch-off.wav" id="5_8lkd0"]
[sub_resource type="CircleShape2D" id="CircleShape2D_1i8i0"]
radius = 12.0
[sub_resource type="Animation" id="Animation_jkd42"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
[sub_resource type="Animation" id="Animation_rntmq"]
resource_name = "off"
length = 0.25
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [0]
}
tracks/1/type = "audio"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("AudioStreamPlayer2D")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"clips": [{
"end_offset": 0.25,
"start_offset": 0.0,
"stream": ExtResource("5_8lkd0")
}],
"times": PackedFloat32Array(0)
}
tracks/1/use_blend = true
[sub_resource type="Animation" id="Animation_0yjbt"]
resource_name = "on"
length = 0.25
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [1]
}
tracks/1/type = "audio"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("AudioStreamPlayer2D")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"clips": [{
"end_offset": 0.0,
"start_offset": 0.0,
"stream": ExtResource("4_cxkmr")
}],
"times": PackedFloat32Array(0)
}
tracks/1/use_blend = true
[sub_resource type="AnimationLibrary" id="AnimationLibrary_6ywhx"]
_data = {
"RESET": SubResource("Animation_jkd42"),
"off": SubResource("Animation_rntmq"),
"on": SubResource("Animation_0yjbt")
}
[node name="ArenaDoorSwitch" type="StaticBody2D"]
script = ExtResource("1_78qab")
[node name="InteractionTrigger" parent="." instance=ExtResource("2_7j8p7")]
PopupText = null
[node name="CollisionShape2D" parent="InteractionTrigger" index="0"]
shape = SubResource("CircleShape2D_1i8i0")
[node name="Popup" parent="InteractionTrigger" index="1"]
offset_top = -44.0
offset_bottom = -8.0
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("3_pgkt4")
centered = false
offset = Vector2(-2, -8)
hframes = 2
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_6ywhx")
}
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."]
[editable path="InteractionTrigger"]

View File

@ -1,10 +1,12 @@
[gd_scene load_steps=3 format=3 uid="uid://hm3ek8vqt1d4"]
[gd_scene load_steps=4 format=3 uid="uid://hm3ek8vqt1d4"]
[ext_resource type="Texture2D" uid="uid://dwbrymm3ud5xu" path="res://Assets/Sprites/Props/bookshelf.png" id="1_cnrpk"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_wc4oe"]
size = Vector2(28, 8)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_tsfmt"]
[node name="Bookshelf" type="StaticBody2D"]
y_sort_enabled = true
@ -45,3 +47,6 @@ frame = 1
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, -4)
shape = SubResource("RectangleShape2D_wc4oe")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = SubResource("NavigationPolygon_tsfmt")

View File

@ -5,3 +5,12 @@ Forsen-related game
![](./Assets/Sprites/Characters/forsen2-portrait.png)
![](https://i.ibb.co/t367kD4/baj.gif)
## Attributions
The FontStruction "calamity,"
(https://fontstruct.com/fontstructions/show/2158964) by "Doph" is licensed
under a Creative Commons Attribution license
(http://creativecommons.org/licenses/by/3.0/).
![](https://i.redd.it/fcy6t049yzr91.png)

View File

@ -1878,6 +1878,11 @@ script = ExtResource("2_4m0a1")
Entities = NodePath("Entities")
Areas = NodePath("Areas")
Spawners = NodePath("Spawners")
CameraLowerBound = null
CameraUpperBound = null
ClearColor = null
AreaName = null
MapName = null
[node name="CanvasModulate" type="CanvasModulate" parent="."]

View File

@ -1,7 +1,6 @@
[gd_scene load_steps=7 format=3 uid="uid://1pb3mpmrl7lc"]
[gd_scene load_steps=6 format=3 uid="uid://1pb3mpmrl7lc"]
[ext_resource type="Script" path="res://Utils/World.cs" id="1_1k6ew"]
[ext_resource type="PackedScene" uid="uid://c72uqjjtxpi3g" path="res://Scenes/Maps/ArenaExterior.tscn" id="2_pksaj"]
[ext_resource type="PackedScene" uid="uid://bxo553hblp6nf" path="res://UI/HealthBar.tscn" id="3_5rhge"]
[ext_resource type="Script" path="res://UI/UIController.cs" id="3_fe62s"]
[ext_resource type="PackedScene" uid="uid://01d24ij5av1y" path="res://UI/BossBar.tscn" id="5_8njq4"]
@ -9,7 +8,6 @@
[node name="World" type="Node2D" node_paths=PackedStringArray("UIController", "MusicPlayer", "DialogueBalloon")]
script = ExtResource("1_1k6ew")
StartingArea = ExtResource("2_pksaj")
UIController = NodePath("CanvasLayer/SubViewportContainer/UIViewport/CanvasLayer/UI")
MusicPlayer = NodePath("MusicPlayer")
DialogueBalloon = NodePath("CanvasLayer/SubViewportContainer/UIViewport/DialogBalloon")

View File

@ -11,10 +11,10 @@
[ext_resource type="PackedScene" uid="uid://dldnp8eunxj3q" path="res://BoundingBoxes/InteractionTrigger.tscn" id="9_3401j"]
[ext_resource type="Script" path="res://BoundingBoxes/ConnectorBox.cs" id="9_fg062"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_keqip"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_lrfoy"]
resource_local_to_scene = true
shader = ExtResource("5_h8k5p")
shader_parameter/color = Quaternion(1, 1, 1, 1)
shader_parameter/color = Vector4(1, 1, 1, 1)
shader_parameter/intensity = 0.0
shader_parameter/alpha_modulate = 1.0
@ -111,7 +111,7 @@ visible = false
position = Vector2(120, -112)
[node name="Doc" parent="Entities" index="0" instance=ExtResource("4_ej0f3")]
material = SubResource("ShaderMaterial_keqip")
material = SubResource("ShaderMaterial_lrfoy")
[node name="PointLight2D" type="PointLight2D" parent="Entities" index="1"]
position = Vector2(168, -42)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,23 @@
[gd_resource type="TileSet" load_steps=6 format=3 uid="uid://l61kbx31ug4p"]
[gd_resource type="TileSet" load_steps=10 format=3 uid="uid://l61kbx31ug4p"]
[ext_resource type="Texture2D" uid="uid://b0yiy7w8nxmas" path="res://Assets/Sprites/arena-tileset.png" id="1_kud44"]
[ext_resource type="Texture2D" uid="uid://j1ekk1ppenm4" path="res://Assets/Sprites/grass-tileset.png" id="2_lihbs"]
[sub_resource type="NavigationPolygon" id="NavigationPolygon_7lhug"]
vertices = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)])
[sub_resource type="NavigationPolygon" id="NavigationPolygon_d0snv"]
vertices = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)])
[sub_resource type="NavigationPolygon" id="NavigationPolygon_m43r7"]
vertices = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)])
[sub_resource type="CanvasTexture" id="CanvasTexture_3n6aa"]
diffuse_texture = ExtResource("1_kud44")
@ -21,6 +36,7 @@ texture = SubResource("CanvasTexture_3n6aa")
0:0/0/terrains_peering_bit/top_left_corner = 0
0:0/0/terrains_peering_bit/top_side = 0
0:0/0/terrains_peering_bit/top_right_corner = 0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_7lhug")
1:1/0 = 0
1:1/0/terrain_set = 0
1:1/0/terrain = 0
@ -34,6 +50,7 @@ texture = SubResource("CanvasTexture_3n6aa")
1:1/0/terrains_peering_bit/top_left_corner = 0
1:1/0/terrains_peering_bit/top_side = 0
1:1/0/terrains_peering_bit/top_right_corner = 0
1:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_7lhug")
2:1/0 = 0
2:1/0/terrain_set = 0
2:1/0/terrain = 1
@ -69,6 +86,7 @@ texture = SubResource("CanvasTexture_3n6aa")
1:0/0/terrains_peering_bit/top_left_corner = 0
1:0/0/terrains_peering_bit/top_side = 0
1:0/0/terrains_peering_bit/top_right_corner = 0
1:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_7lhug")
0:1/0 = 0
0:1/0/terrain_set = 0
0:1/0/terrain = 0
@ -82,6 +100,7 @@ texture = SubResource("CanvasTexture_3n6aa")
0:1/0/terrains_peering_bit/top_left_corner = 0
0:1/0/terrains_peering_bit/top_side = 0
0:1/0/terrains_peering_bit/top_right_corner = 0
0:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_7lhug")
0:2/0 = 0
0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:2/0/physics_layer_0/angular_velocity = 0.0
@ -98,10 +117,12 @@ texture = SubResource("CanvasTexture_3n6aa")
2:0/0/terrain_set = 0
2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:0/0/physics_layer_0/angular_velocity = 0.0
2:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_m43r7")
3:0/0 = 0
3:0/0/terrain_set = 0
3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:0/0/physics_layer_0/angular_velocity = 0.0
3:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_m43r7")
4:0/0 = 0
4:0/0/terrain_set = 0
4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
@ -287,18 +308,22 @@ texture = SubResource("CanvasTexture_3n6aa")
10:1/0/terrain_set = 1
10:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
10:1/0/physics_layer_0/angular_velocity = 0.0
10:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_d0snv")
11:1/0 = 0
11:1/0/terrain_set = 1
11:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
11:1/0/physics_layer_0/angular_velocity = 0.0
11:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_d0snv")
11:2/0 = 0
11:2/0/terrain_set = 1
11:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
11:2/0/physics_layer_0/angular_velocity = 0.0
11:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_d0snv")
10:2/0 = 0
10:2/0/terrain_set = 1
10:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
10:2/0/physics_layer_0/angular_velocity = 0.0
10:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_d0snv")
8:1/0 = 0
8:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
8:1/0/physics_layer_0/angular_velocity = 0.0
@ -472,128 +497,173 @@ texture = SubResource("CanvasTexture_3n6aa")
13:0/0/physics_layer_0/angular_velocity = 0.0
13:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 2, 8, 2, 8, 8, -8, 8)
[sub_resource type="NavigationPolygon" id="NavigationPolygon_que0c"]
vertices = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
polygons = Array[PackedInt32Array]([PackedInt32Array(0, 1, 2, 3)])
outlines = Array[PackedVector2Array]([PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)])
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_mdfpe"]
texture = ExtResource("2_lihbs")
0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_0/angular_velocity = 0.0
0:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
1:0/0 = 0
1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:0/0/physics_layer_0/angular_velocity = 0.0
1:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
2:0/0 = 0
2:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:0/0/physics_layer_0/angular_velocity = 0.0
2:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
3:0/0 = 0
3:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:0/0/physics_layer_0/angular_velocity = 0.0
3:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
4:0/0 = 0
4:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
4:0/0/physics_layer_0/angular_velocity = 0.0
4:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
5:0/0 = 0
5:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
5:0/0/physics_layer_0/angular_velocity = 0.0
5:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
6:0/0 = 0
6:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:0/0/physics_layer_0/angular_velocity = 0.0
6:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
7:0/0 = 0
7:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:0/0/physics_layer_0/angular_velocity = 0.0
7:0/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
7:1/0 = 0
7:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:1/0/physics_layer_0/angular_velocity = 0.0
7:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
7:2/0 = 0
7:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:2/0/physics_layer_0/angular_velocity = 0.0
7:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
7:3/0 = 0
7:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:3/0/physics_layer_0/angular_velocity = 0.0
7:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
7:4/0 = 0
7:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
7:4/0/physics_layer_0/angular_velocity = 0.0
7:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
6:4/0 = 0
6:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:4/0/physics_layer_0/angular_velocity = 0.0
6:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
5:4/0 = 0
5:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
5:4/0/physics_layer_0/angular_velocity = 0.0
5:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
4:4/0 = 0
4:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
4:4/0/physics_layer_0/angular_velocity = 0.0
4:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
3:4/0 = 0
3:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:4/0/physics_layer_0/angular_velocity = 0.0
3:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
2:4/0 = 0
2:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:4/0/physics_layer_0/angular_velocity = 0.0
2:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
1:4/0 = 0
1:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:4/0/physics_layer_0/angular_velocity = 0.0
1:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
0:4/0 = 0
0:4/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:4/0/physics_layer_0/angular_velocity = 0.0
0:4/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
0:3/0 = 0
0:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:3/0/physics_layer_0/angular_velocity = 0.0
0:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
1:2/0 = 0
1:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:2/0/physics_layer_0/angular_velocity = 0.0
1:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
1:1/0 = 0
1:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:1/0/physics_layer_0/angular_velocity = 0.0
1:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
0:1/0 = 0
0:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:1/0/physics_layer_0/angular_velocity = 0.0
0:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
0:2/0 = 0
0:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:2/0/physics_layer_0/angular_velocity = 0.0
0:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
2:3/0 = 0
2:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:3/0/physics_layer_0/angular_velocity = 0.0
2:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
3:3/0 = 0
3:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:3/0/physics_layer_0/angular_velocity = 0.0
3:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
1:3/0 = 0
1:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:3/0/physics_layer_0/angular_velocity = 0.0
1:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
2:2/0 = 0
2:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:2/0/physics_layer_0/angular_velocity = 0.0
2:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
3:1/0 = 0
3:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:1/0/physics_layer_0/angular_velocity = 0.0
3:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
4:1/0 = 0
4:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
4:1/0/physics_layer_0/angular_velocity = 0.0
4:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
2:1/0 = 0
2:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
2:1/0/physics_layer_0/angular_velocity = 0.0
2:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
4:2/0 = 0
4:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
4:2/0/physics_layer_0/angular_velocity = 0.0
4:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
5:2/0 = 0
5:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
5:2/0/physics_layer_0/angular_velocity = 0.0
5:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
3:2/0 = 0
3:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
3:2/0/physics_layer_0/angular_velocity = 0.0
3:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
6:3/0 = 0
6:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:3/0/physics_layer_0/angular_velocity = 0.0
6:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
5:3/0 = 0
5:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
5:3/0/physics_layer_0/angular_velocity = 0.0
5:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
4:3/0 = 0
4:3/0/physics_layer_0/linear_velocity = Vector2(0, 0)
4:3/0/physics_layer_0/angular_velocity = 0.0
4:3/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
6:2/0 = 0
6:2/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:2/0/physics_layer_0/angular_velocity = 0.0
6:2/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
6:1/0 = 0
6:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
6:1/0/physics_layer_0/angular_velocity = 0.0
6:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
5:1/0 = 0
5:1/0/physics_layer_0/linear_velocity = Vector2(0, 0)
5:1/0/physics_layer_0/angular_velocity = 0.0
5:1/0/navigation_layer_0/polygon = SubResource("NavigationPolygon_que0c")
0:5/0 = 0
0:5/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:5/0/physics_layer_0/angular_velocity = 0.0
@ -635,5 +705,6 @@ terrain_set_1/terrain_0/name = "carpet"
terrain_set_1/terrain_0/color = Color(0.5, 0.34375, 0.25, 1)
terrain_set_1/terrain_1/name = "carpet vertical"
terrain_set_1/terrain_1/color = Color(0.5, 0.4375, 0.25, 1)
navigation_layer_0/layers = 1
sources/0 = SubResource("TileSetAtlasSource_fcd6d")
sources/1 = SubResource("TileSetAtlasSource_mdfpe")

View File

@ -0,0 +1,33 @@
using Godot;
namespace SupaLidlGame.State.Character.Animation;
public abstract partial class AnimationState : Node, IState<AnimationState>
{
[Export]
public AnimationPlayer AnimationPlayer { get; set; }
//[Export]
//public
public virtual IState<AnimationState> Enter(IState<AnimationState> prev) => null;
//public bool AdvanceCondition
public virtual void Exit(IState<AnimationState> next)
{
}
public virtual AnimationState Process(double delta)
{
return null;
}
public virtual AnimationState PhysicsProcess(double delta)
{
return null;
}
public virtual AnimationState Input(InputEvent @event) => null;
}

View File

@ -0,0 +1,39 @@
using Godot;
namespace SupaLidlGame.State.Character.Animation;
public partial class AnimationStateMachine : StateMachine<AnimationState>
{
[Export]
public override AnimationState InitialState { get; set; }
[Export]
public AnimationPlayer Character { get; set; }
public void Process(double delta)
{
var state = CurrentState.Process(delta);
if (state is AnimationState)
{
ChangeState(state);
}
}
public void PhysicsProcess(double delta)
{
var state = CurrentState.PhysicsProcess(delta);
if (state is AnimationState)
{
ChangeState(state);
}
}
public void Input(InputEvent @event)
{
var state = CurrentState.Input(@event);
if (state is AnimationState)
{
ChangeState(state);
}
}
}

View File

@ -6,7 +6,7 @@ public abstract partial class NPCState : CharacterState
public override CharacterState Process(double delta)
{
_npc.ThinkProcess(delta);
//_npc.ThinkProcess(delta);
return base.Process(delta);
}
}

View File

@ -6,7 +6,11 @@ public partial class GlobalState : Node
{
//public Utils.World World { get; set; }
public Progression Progression { get; set; }
[Export]
public Progression Progression { get; set; } = new();
[Export]
public MapState MapState { get; set; } = new();
[Signal]
public delegate void SummonBossEventHandler(string bossName);

View File

@ -0,0 +1,45 @@
using Godot;
using Godot.Collections;
public partial class MapState : Resource
{
[Export]
private Dictionary<string, Variant> _state = new();
[Signal]
public delegate void MapStateChangedEventHandler(string key, Variant value);
[Signal]
public delegate void MapStateBoolChangedEventHandler(string key, bool value);
public Variant this[string key]
{
get
{
if (_state.ContainsKey(key))
{
return _state[key];
}
return default;
}
set
{
if (_state.ContainsKey(key))
{
_state[key] = value;
}
else
{
_state.Add(key, value);
}
EmitSignal(SignalName.MapStateChanged, key, value);
switch (value.VariantType)
{
case Variant.Type.Bool:
EmitSignal(SignalName.MapStateBoolChanged, key, (bool)value);
break;
}
}
}
}

View File

@ -50,4 +50,10 @@ public abstract partial class StateMachine<T> : Node where T : Node, IState<T>
state = this.FindChildOfType<U>();
return ChangeState(state);
}
public bool ChangeState(string name, out T state)
{
state = GetNode<T>(name);
return ChangeState(state);
}
}

View File

View File

@ -0,0 +1,202 @@
using Godot;
using SupaLidlGame.Extensions;
using System;
namespace SupaLidlGame.State.Thinker;
public partial class AttackState : ThinkerState
{
[Export]
public float PreferredWeightDistance
{
get => _preferredWeightDistance;
protected set
{
_preferredWeightDistance = value;
_preferredWeightDistanceSq = value * value;
}
}
[Export]
public float MaxWeightDistance
{
get => _maxWeightDistance;
protected set
{
_maxWeightDistance = value;
_maxWeightDistanceSq = value * value;
}
}
[Export]
public float MaxDistanceToTarget { get; set; }
[Export]
public ThinkerState PassiveState { get; set; }
[Export]
public ThinkerState PursueState { get; set; }
protected float _preferredWeightDistance = 64.0f;
protected float _maxWeightDistance = 8.0f;
protected float _preferredWeightDistanceSq = 4096.0f;
protected float _maxWeightDistanceSq = 64.0f;
public float[] Weights => _weights;
protected float[] _weights = new float[16];
protected int _bestWeightIdx;
protected static readonly Vector2[] _weightDirs = new Vector2[16];
static AttackState()
{
for (int i = 0; i < 16; i++)
{
float y = Mathf.Sin(Mathf.Pi * i * 2 / 16);
float x = Mathf.Cos(Mathf.Pi * i * 2 / 16);
_weightDirs[i] = new Vector2(x, y);
}
}
public void UpdateWeights(Vector2 pos)
{
// FIXME: TODO: remove all the spaghetti
Vector2 dir = NPC.Target.Normalized();
float distSq = NPC.GlobalPosition.DistanceSquaredTo(pos);
var spaceState = NPC.GetWorld2D().DirectSpaceState;
var exclude = new Godot.Collections.Array<Godot.Rid>();
exclude.Add(NPC.GetRid());
// calculate weights based on distance
for (int i = 0; i < 16; i++)
{
float directDot = _weightDirs[i].Dot(dir);
// clamp dot from [-1, 1] to [0, 1]
directDot = (directDot + 1) / 2;
float strafeDot = Math.Abs(_weightDirs[i].Dot(dir.Clockwise90()));
float currDirDot = (_weightDirs[i].Dot(NPC.Direction) + 1) / 16;
strafeDot = Mathf.Pow((strafeDot + 1) / 2, 2) + currDirDot;
// favor strafing when getting closer
if (distSq > _preferredWeightDistanceSq)
{
_weights[i] = directDot;
}
else if (distSq > _maxWeightDistanceSq)
{
float dDotWeight = Mathf.Sqrt(distSq / 4096);
float sDotWeight = 1 - dDotWeight;
_weights[i] = (dDotWeight * directDot) +
(sDotWeight * strafeDot);
}
else
{
_weights[i] = strafeDot;
}
}
// subtract weights that collide
for (int i = 0; i < 16; i++)
{
var rayParams = new PhysicsRayQueryParameters2D
{
Exclude = exclude,
CollideWithBodies = true,
From = NPC.GlobalPosition,
To = NPC.GlobalPosition + (_weightDirs[i] * 24),
CollisionMask = 1 + 2 + 16
};
var result = spaceState.IntersectRay(rayParams);
// if we hit something
if (result.Count > 0)
{
// then we subtract the value of this from the other weights
float oldWeight = _weights[i];
for (int j = 0; j < 16; j++)
{
if (i == j)
{
_weights[i] = 0;
}
else
{
float dot = _weightDirs[i].Dot(_weightDirs[j]);
if (dot >= 0)
{
_weights[j] -= _weights[j] * dot;
}
}
}
}
}
float bestWeight = 0;
for (int i = 0; i < 16; i++)
{
if (_weights[i] > bestWeight)
{
_bestWeightIdx = i;
bestWeight = _weights[i];
}
}
}
public override ThinkerState Think()
{
// TODO: the entity should wander if it doesn't find a best target
var bestTarget = NPC.FindBestTarget();
if (bestTarget is not null)
{
Vector2 pos = NPC.LastSeenPosition = bestTarget.GlobalPosition;
NPC.Target = pos - NPC.GlobalPosition;
Vector2 dir = NPC.Target;
float dist = NPC.GlobalPosition.DistanceTo(pos);
if (PursueState is not null)
{
// pursue the player if they can not be seen or is too far away
if (dist > MaxDistanceToTarget || !NPC.HasLineOfSight(bestTarget))
{
return PursueState;
}
}
UpdateWeights(pos);
if (dist < 40 && NPC.CanAttack)
{
if (NPC.Inventory.SelectedItem is Items.Weapon weapon)
{
NPC.UseCurrentItem();
}
}
}
else
{
return PassiveState;
}
return base.Think();
}
public override ThinkerState Process(double delta)
{
if (!NPC.ShouldMove ||
(!NPC.ShouldMoveWhenUsingItem && NPC.Inventory.IsUsingItem))
{
NPC.Direction = Vector2.Zero;
}
else
{
NPC.Direction = _weightDirs[_bestWeightIdx];
}
return base.Process(delta);
}
}

View File

@ -0,0 +1,28 @@
using Godot;
namespace SupaLidlGame.State.Thinker;
public partial class IdleState : ThinkerState
{
[Export]
public ThinkerState PursueState { get; set; }
[Export]
public float MinTargetDistance { get; set; }
public override ThinkerState Think()
{
var bestTarget = NPC.FindBestTarget();
if (bestTarget is not null)
{
var pos = bestTarget.GlobalPosition;
var dist = NPC.GlobalPosition.DistanceTo(pos);
if (dist < MinTargetDistance)
{
return PursueState;
}
}
return base.Think();
}
}

View File

@ -0,0 +1,70 @@
using Godot;
namespace SupaLidlGame.State.Thinker;
public partial class PursueState : ThinkerState
{
[Export]
public NavigationAgent2D NavigationAgent { get; set; }
[Export]
public ThinkerState AttackState { get; set; }
[Export]
public ThinkerState PassiveState { get; set; }
/// <summary>
/// Minimum distance the NPC should be, otherwise entering attack state
/// </summary>
[Export]
public float MinDistanceToTarget { get; set; }
/// <summary>
/// Maximum distance the NPC should be, otherwise entering passive state
/// </summary>
[Export]
public float MaxDistanceFromOrigin { get; set; }
public override ThinkerState Think()
{
var bestTarget = NPC.FindBestTarget();
if (bestTarget is not null)
{
// navigate towards the best target
var pos = bestTarget.GlobalPosition;
NavigationAgent.TargetPosition = pos;
NPC.Target = NPC.GlobalPosition.DirectionTo(pos);
NPC.LastSeenPosition = pos;
if (NPC.GlobalPosition.DistanceTo(pos) < MinDistanceToTarget)
{
if (NPC.HasLineOfSight(bestTarget))
{
GD.Print("To attack state");
return AttackState;
}
}
}
else
{
// go to last seen position of last best target
GD.Print("Last seen " + NPC.LastSeenPosition);
NavigationAgent.TargetPosition = NPC.LastSeenPosition;
}
return PassiveState ?? base.Think();
}
public override ThinkerState PhysicsProcess(double delta)
{
if (!NavigationAgent.IsTargetReachable())
{
return PassiveState ?? base.PhysicsProcess(delta);
}
var navPos = NavigationAgent.GetNextPathPosition();
NPC.Direction = NPC.GlobalPosition.DirectionTo(navPos);
return base.PhysicsProcess(delta);
}
}

View File

@ -0,0 +1,25 @@
using Godot;
namespace SupaLidlGame.State.Thinker;
public abstract partial class ThinkerState : Node, IState<ThinkerState>
{
[Export]
public double ThinkDelta { get; set; } = 0.125;
[Export]
public Characters.NPC NPC { get; set; }
public virtual IState<ThinkerState> Enter(IState<ThinkerState> prev) => null;
public virtual void Exit(IState<ThinkerState> next)
{
}
public virtual ThinkerState Process(double delta) => null;
public virtual ThinkerState PhysicsProcess(double delta) => null;
public virtual ThinkerState Think() => null;
}

View File

@ -0,0 +1,54 @@
using Godot;
namespace SupaLidlGame.State.Thinker;
public partial class ThinkerStateMachine : StateMachine<ThinkerState>
{
[Export]
public override ThinkerState InitialState { get; set; }
private double _thinkTime = 0;
public void Process(double delta)
{
var state = CurrentState.Process(delta);
if (state is ThinkerState)
{
ChangeState(state);
}
if ((_thinkTime -= delta) <= 0)
{
_thinkTime = CurrentState.ThinkDelta;
Think();
}
}
public void PhysicsProcess(double delta)
{
var state = CurrentState.PhysicsProcess(delta);
if (state is ThinkerState)
{
ChangeState(state);
}
}
public void Think()
{
var state = CurrentState.Think();
if (state is ThinkerState)
{
ChangeState(state);
}
}
public override bool ChangeState(ThinkerState nextState, bool isProxied = false)
{
if (base.ChangeState(nextState))
{
_thinkTime = CurrentState.ThinkDelta;
return true;
}
return false;
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Godot.NET.Sdk/4.1.0-dev">
<Project Sdk="Godot.NET.Sdk/4.1.0">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>

View File

@ -1,7 +1,10 @@
[gd_resource type="Theme" load_steps=2 format=3 uid="uid://cksjbu3vrup5"]
[ext_resource type="FontFile" uid="uid://cgwa8bjiyv534" path="res://Assets/Fonts/alagard.ttf" id="1_gdvg0"]
[ext_resource type="FontFile" uid="uid://6bvgjbmqovau" path="res://Assets/Fonts/calamity/calamity.ttf" id="1_334fe"]
[resource]
default_font = ExtResource("1_gdvg0")
/fonts/Alagard = ExtResource("1_gdvg0")
default_font = ExtResource("1_334fe")
default_font_size = 15
/colors/background = Color(0.105882, 0.0470588, 0.117647, 1)
/font_sizes/Normal = 16
/fonts/Calamity = ExtResource("1_334fe")

View File

@ -2,15 +2,13 @@ using Godot;
using SupaLidlGame.Characters;
using SupaLidlGame.Extensions;
using SupaLidlGame.Scenes;
using System.Collections.Generic;
using System.Linq;
using SupaLidlGame.State.Global;
namespace SupaLidlGame.Utils;
public partial class World : Node
{
[Export]
public PackedScene StartingArea { get; set; }
public static World Instance { get; private set; }
[Export]
public Map CurrentMap { get; protected set; }
@ -50,6 +48,14 @@ public partial class World : Node
public World()
{
_playerScene = ResourceLoader.Load<PackedScene>(PLAYER_PATH);
if (Instance is null)
{
Instance = this;
}
else
{
throw new System.Exception("Another World instance is running.");
}
}
public override void _Ready()
@ -60,11 +66,6 @@ public partial class World : Node
Godot.RenderingServer.SetDefaultClearColor(Godot.Colors.Black);
if (StartingArea is not null)
{
//LoadScene(StartingArea);
}
// create a player (currently unparented)
CreatePlayer();
@ -201,16 +202,6 @@ public partial class World : Node
private void InitTilemap(Map map)
{
// this is being replaced with interaction triggers
var children = map.Areas.GetChildren();
foreach (Node node in children)
{
if (node is BoundingBoxes.ConnectorBox connector)
{
// this reconnects the EventHandler if it is connected
//connector.RequestedEnter -= _on_area_2d_requested_enter;
//connector.RequestedEnter += _on_area_2d_requested_enter;
}
}
}
private void MovePlayerToConnector(string name)
@ -254,11 +245,21 @@ public partial class World : Node
public void SaveGame()
{
ResourceSaver.Save(GlobalState.Progression, "user://progression.save");
ResourceSaver.Save(GlobalState.MapState, "user://map-state.save");
throw new System.NotImplementedException();
}
public void LoadGame()
{
var prog = ResourceLoader.Load<Progression>("user://progression.save");
var mapState = ResourceLoader.Load<MapState>("user://map-state.save");
GlobalState.Progression = prog;
GlobalState.MapState = mapState;
// load the player scene
// TODO: implement
throw new System.NotImplementedException();
}

View File

@ -5,8 +5,6 @@ type="CompressedTexture2D"
uid="uid://d3lr2uas6ax8v"
path="res://.godot/imported/icon.svg-17eb5d3e2a3cfbe59852220758c5b7bd.ctex"
metadata={
"editor_dark_theme": true,
"editor_scale": 1.0,
"has_editor_variant": true,
"vram_texture": false
}

View File

@ -72,13 +72,13 @@ ui_down={
}
roll={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":3,"pressed":false,"double_click":false,"script":null)
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":3,"canceled":false,"pressed":false,"double_click":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
attack1={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"pressed":false,"double_click":false,"script":null)
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}
equip={