diff --git a/Assets/Fonts/alagard-spaced.tres b/Assets/Fonts/alagard-spaced.tres new file mode 100644 index 0000000..432e03f --- /dev/null +++ b/Assets/Fonts/alagard-spaced.tres @@ -0,0 +1,7 @@ +[gd_resource type="FontVariation" load_steps=2 format=3 uid="uid://ndkrorerbxft"] + +[ext_resource type="FontFile" uid="uid://cgwa8bjiyv534" path="res://Assets/Fonts/alagard.ttf" id="1_krbnd"] + +[resource] +base_font = ExtResource("1_krbnd") +spacing_glyph = 4 diff --git a/Assets/Fonts/compass-pro-spaced.tres b/Assets/Fonts/compass-pro-spaced.tres new file mode 100644 index 0000000..335a2f0 --- /dev/null +++ b/Assets/Fonts/compass-pro-spaced.tres @@ -0,0 +1,7 @@ +[gd_resource type="FontVariation" load_steps=2 format=3 uid="uid://bjnmfgt5yqle7"] + +[ext_resource type="FontFile" uid="uid://bo3obq6sos7lu" path="res://Assets/Fonts/compass-pro.ttf" id="1_brr65"] + +[resource] +base_font = ExtResource("1_brr65") +spacing_glyph = 4 diff --git a/Assets/Fonts/compass-pro.ttf b/Assets/Fonts/compass-pro.ttf new file mode 100644 index 0000000..5432d65 Binary files /dev/null and b/Assets/Fonts/compass-pro.ttf differ diff --git a/Assets/Fonts/compass-pro.ttf.import b/Assets/Fonts/compass-pro.ttf.import new file mode 100644 index 0000000..89ed156 --- /dev/null +++ b/Assets/Fonts/compass-pro.ttf.import @@ -0,0 +1,33 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://bo3obq6sos7lu" +path="res://.godot/imported/compass-pro.ttf-5e813dda823d14f9501edd94273a527c.fontdata" + +[deps] + +source_file="res://Assets/Fonts/compass-pro.ttf" +dest_files=["res://.godot/imported/compass-pro.ttf-5e813dda823d14f9501edd94273a527c.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=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/Assets/Music/gillette.mp3 b/Assets/Music/gillette.mp3 new file mode 100644 index 0000000..bdf52b0 Binary files /dev/null and b/Assets/Music/gillette.mp3 differ diff --git a/Assets/Music/gillette.mp3.import b/Assets/Music/gillette.mp3.import new file mode 100644 index 0000000..35c9a70 --- /dev/null +++ b/Assets/Music/gillette.mp3.import @@ -0,0 +1,19 @@ +[remap] + +importer="mp3" +type="AudioStreamMP3" +uid="uid://ipss4y2gkk3y" +path="res://.godot/imported/gillette.mp3-5dd6f93f1f9df01778f80e3dd2caeb1e.mp3str" + +[deps] + +source_file="res://Assets/Music/gillette.mp3" +dest_files=["res://.godot/imported/gillette.mp3-5dd6f93f1f9df01778f80e3dd2caeb1e.mp3str"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Assets/Sprites/Particles/DocIntroParticles.tres b/Assets/Sprites/Particles/DocIntroParticles.tres new file mode 100644 index 0000000..ab58291 --- /dev/null +++ b/Assets/Sprites/Particles/DocIntroParticles.tres @@ -0,0 +1,22 @@ +[gd_resource type="ParticleProcessMaterial" load_steps=3 format=3 uid="uid://rcjujd5dv7lm"] + +[sub_resource type="Gradient" id="Gradient_v7xci"] +offsets = PackedFloat32Array(0.525926, 0.6) +colors = PackedColorArray(0, 0, 0, 1, 1, 0, 0, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_pntll"] +gradient = SubResource("Gradient_v7xci") + +[resource] +particle_flag_disable_z = true +spread = 180.0 +gravity = Vector3(0, 0, 0) +initial_velocity_min = 64.0 +initial_velocity_max = 96.0 +orbit_velocity_min = 0.0 +orbit_velocity_max = 0.0 +linear_accel_min = -128.0 +linear_accel_max = -96.0 +scale_min = 0.1 +scale_max = 0.2 +color_initial_ramp = SubResource("GradientTexture1D_pntll") diff --git a/Assets/Sprites/UI/boss-bar.png b/Assets/Sprites/UI/boss-bar.png new file mode 100644 index 0000000..d6d935c Binary files /dev/null and b/Assets/Sprites/UI/boss-bar.png differ diff --git a/Assets/Sprites/UI/boss-bar.png.import b/Assets/Sprites/UI/boss-bar.png.import new file mode 100644 index 0000000..cde30dd --- /dev/null +++ b/Assets/Sprites/UI/boss-bar.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b07x1uedfexfi" +path="res://.godot/imported/boss-bar.png-14402f9e8d9c8a30b766d18572a90e44.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Assets/Sprites/UI/boss-bar.png" +dest_files=["res://.godot/imported/boss-bar.png-14402f9e8d9c8a30b766d18572a90e44.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 diff --git a/BoundingBoxes/Hurtbox.cs b/BoundingBoxes/Hurtbox.cs index ad4cb4b..0d661d5 100644 --- a/BoundingBoxes/Hurtbox.cs +++ b/BoundingBoxes/Hurtbox.cs @@ -43,6 +43,12 @@ public partial class Hurtbox : BoundingBox, IFaction Vector2 knockbackOrigin = default, Vector2 knockbackVector = default) { + if (!IsInstanceValid(this)) + { + // this should fix the error of the object being invalid + return; + } + Vector2 knockbackDir = knockbackVector; if (knockbackDir == default) { diff --git a/Characters/Boss.cs b/Characters/Boss.cs index b5c6a58..a4786dc 100644 --- a/Characters/Boss.cs +++ b/Characters/Boss.cs @@ -1,4 +1,5 @@ using Godot; +using GodotUtilities; namespace SupaLidlGame.Characters; @@ -7,8 +8,24 @@ public abstract partial class Boss : Enemy [Export] public State.NPC.NPCStateMachine BossStateMachine { get; set; } + [Export] + public string BossName { get; set; } + public abstract int Intensity { get; } + private bool _isActive; + [Export] - public bool IsActive { get; set; } + public bool IsActive + { + get => _isActive; + set + { + _isActive = value; + + // register or deregister ourselves when we are active/inactive + this.GetAncestor() + .RegisterBoss(_isActive ? this : null); + } + } } diff --git a/Characters/Doc.cs b/Characters/Doc.cs index 8292190..0e90ed2 100644 --- a/Characters/Doc.cs +++ b/Characters/Doc.cs @@ -50,6 +50,16 @@ public partial class Doc : Boss { TelegraphAnimation = GetNode("Animations/Telegraph"); base._Ready(); + + // when we are hurt, start the boss fight + Hurt += (Events.HealthChangedArgs args) => + { + if (!IsActive) + { + IsActive = true; + Inventory.SelectedItem = Inventory.Items[0]; + } + }; } public override void _Process(double delta) diff --git a/Characters/Doc.tscn b/Characters/Doc.tscn index 6752851..d64ab16 100644 --- a/Characters/Doc.tscn +++ b/Characters/Doc.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=47 format=3 uid="uid://d2skjvvx6fal0"] +[gd_scene load_steps=52 format=3 uid="uid://d2skjvvx6fal0"] [ext_resource type="Script" path="res://Characters/Doc.cs" id="2_3elet"] [ext_resource type="Shader" path="res://Shaders/Flash.gdshader" id="2_5jxom"] @@ -22,6 +22,9 @@ [ext_resource type="Script" path="res://Utils/AnimationManager.cs" id="16_bsvls"] [ext_resource type="Texture2D" uid="uid://bd8l8kafb42dt" path="res://Assets/Sprites/Particles/circle.png" id="16_x277j"] [ext_resource type="Material" uid="uid://bat28samf7ukd" path="res://Assets/Sprites/Particles/NPCDamageProcessMaterial.tres" id="17_iomdx"] +[ext_resource type="Texture2D" uid="uid://c1a7lvb4uuwfy" path="res://Assets/Sprites/Particles/circle-16.png" id="19_p0p6c"] +[ext_resource type="Material" uid="uid://rcjujd5dv7lm" path="res://Assets/Sprites/Particles/DocIntroParticles.tres" id="19_q4rt1"] +[ext_resource type="PackedScene" uid="uid://dvqap2uhcah63" path="res://Items/Weapons/Sword.tscn" id="24_y1go8"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_7n7iy"] resource_local_to_scene = true @@ -376,6 +379,14 @@ _data = { "hurt": SubResource("Animation_dxevc") } +[sub_resource type="Animation" id="Animation_uemm6"] +resource_name = "intro" + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_kjxam"] +_data = { +"intro": SubResource("Animation_uemm6") +} + [sub_resource type="Gradient" id="Gradient_lcoxi"] offsets = PackedFloat32Array(0.37037, 0.651852) colors = PackedColorArray(0.367549, 0.894801, 1, 1, 0.992095, 0.364069, 1, 1) @@ -429,6 +440,7 @@ collision_layer = 10 collision_mask = 17 script = ExtResource("2_3elet") BossStateMachine = NodePath("BossStateMachine") +BossName = "Doc, The Two-Time" Health = 1000.0 Sprite = NodePath("Sprite") Inventory = NodePath("Inventory") @@ -520,6 +532,11 @@ libraries = { "": SubResource("AnimationLibrary_xe5eq") } +[node name="Misc" type="AnimationPlayer" parent="Animations"] +libraries = { +"": SubResource("AnimationLibrary_kjxam") +} + [node name="Effects" type="Node2D" parent="."] [node name="UnwantedFrequenciesParticles" type="GPUParticles2D" parent="Effects"] @@ -539,6 +556,13 @@ lifetime = 0.4 one_shot = true explosiveness = 1.0 +[node name="IntroParticles" type="GPUParticles2D" parent="Effects"] +position = Vector2(0, -8) +emitting = false +amount = 32 +process_material = ExtResource("19_q4rt1") +texture = ExtResource("19_p0p6c") + [node name="Sprite" type="Sprite2D" parent="."] y_sort_enabled = true use_parent_material = true @@ -563,6 +587,8 @@ y_sort_enabled = true script = ExtResource("8_r8ejq") Items = Array[Node2D]([]) +[node name="Sword" parent="Inventory" instance=ExtResource("24_y1go8")] + [node name="HurtSound" type="AudioStreamPlayer2D" parent="."] stream = ExtResource("9_stm0e") diff --git a/Characters/NPC.cs b/Characters/NPC.cs index df1d9ea..f903d7e 100644 --- a/Characters/NPC.cs +++ b/Characters/NPC.cs @@ -45,6 +45,8 @@ public partial class NPC : Character public bool ShouldMove { get; set; } = true; + public bool CanAttack { get; set; } = true; + protected float[] _weights = new float[16]; protected int _bestWeightIdx; protected double _thinkTimeElapsed = 0; @@ -232,7 +234,7 @@ public partial class NPC : Character float dist = GlobalPosition.DistanceSquaredTo(pos); UpdateWeights(pos); - if (dist < 1024) + if (dist < 1600 && CanAttack) { if (Inventory.SelectedItem is Weapon weapon) { diff --git a/Items/Weapon.cs b/Items/Weapon.cs index 2afa5a3..26d74eb 100644 --- a/Items/Weapon.cs +++ b/Items/Weapon.cs @@ -108,7 +108,7 @@ public abstract partial class Weapon : Item } } - public virtual void _on_hitbox_hit(BoundingBox box) + public virtual void OnHitboxHit(BoundingBox box) { if (box is Hurtbox hurtbox) { diff --git a/Scenes/Level.tscn b/Scenes/Level.tscn index fed8edc..3ac7368 100644 --- a/Scenes/Level.tscn +++ b/Scenes/Level.tscn @@ -1,27 +1,57 @@ -[gd_scene load_steps=4 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://b2x17su05ou5w" path="res://Scenes/Maps/Arena.tscn" id="2_avsrq"] [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"] -[node name="World" type="Node2D" node_paths=PackedStringArray("Control")] +[node name="World" type="Node2D" node_paths=PackedStringArray("UIController")] script = ExtResource("1_1k6ew") StartingArea = ExtResource("2_avsrq") -Control = NodePath("CanvasLayer/UI") +UIController = NodePath("CanvasLayer/UI") [node name="CanvasLayer" type="CanvasLayer" parent="."] -[node name="UI" type="Control" parent="CanvasLayer"] +[node name="UI" type="Control" parent="CanvasLayer" node_paths=PackedStringArray("BossBar")] z_index = 128 layout_mode = 3 -anchors_preset = 0 -offset_right = 640.0 -offset_bottom = 480.0 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("3_fe62s") +BossBar = NodePath("Bottom/BossBar") -[node name="HealthBar" parent="CanvasLayer/UI" instance=ExtResource("3_5rhge")] +[node name="Top" type="HBoxContainer" parent="CanvasLayer/UI"] layout_mode = 1 -anchors_preset = 1 -anchor_left = 1.0 -anchor_bottom = 0.0 -grow_horizontal = 0 -grow_vertical = 1 +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 40.0 +grow_horizontal = 2 + +[node name="Margin" type="MarginContainer" parent="CanvasLayer/UI/Top"] +layout_mode = 2 +theme_override_constants/margin_left = 16 +theme_override_constants/margin_top = 16 + +[node name="HealthBar" parent="CanvasLayer/UI/Top/Margin" instance=ExtResource("3_5rhge")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Bottom" type="HBoxContainer" parent="CanvasLayer/UI"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -44.0 +grow_horizontal = 2 +grow_vertical = 0 +alignment = 1 + +[node name="BossBar" parent="CanvasLayer/UI/Bottom" instance=ExtResource("5_8njq4")] +layout_mode = 2 diff --git a/Scenes/Maps/Arena.tscn b/Scenes/Maps/Arena.tscn index 3a2ba13..7bf91d5 100644 --- a/Scenes/Maps/Arena.tscn +++ b/Scenes/Maps/Arena.tscn @@ -251,7 +251,7 @@ physics_layer_0/collision_layer = 1 sources/2 = SubResource("TileSetAtlasSource_5yxvt") sources/0 = SubResource("TileSetAtlasSource_fcd6d") -[sub_resource type="ShaderMaterial" id="ShaderMaterial_88hwc"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_spvk4"] resource_local_to_scene = true shader = ExtResource("5_h8k5p") shader_parameter/color = Quaternion(1, 1, 1, 1) @@ -342,7 +342,7 @@ visible = false position = Vector2(120, -112) [node name="Doc" parent="Entities" index="18" instance=ExtResource("4_ej0f3")] -material = SubResource("ShaderMaterial_88hwc") +material = SubResource("ShaderMaterial_spvk4") [node name="PointLight2D" type="PointLight2D" parent="Entities" index="19"] position = Vector2(168, -42) diff --git a/UI/BossBar.cs b/UI/BossBar.cs new file mode 100644 index 0000000..cc09fd6 --- /dev/null +++ b/UI/BossBar.cs @@ -0,0 +1,63 @@ +using Godot; +using SupaLidlGame.Characters; + +namespace SupaLidlGame.UI; + +public partial class BossBar : VBoxContainer +{ + public TextureProgressBar ProgressBar { get; set; } + public Label BossNameLabel { get; set; } + + private Boss _boss; + + public Boss Boss + { + get => _boss; + set + { + SetupBoss(value); + _boss = value; + } + } + + public override void _Ready() + { + ProgressBar = GetNode("BarMargin/BossBar"); + BossNameLabel = GetNode