diff --git a/assets/first_party/wildlife/sheep/sheep_annoy.png b/assets/first_party/wildlife/sheep/sheep_annoy.png new file mode 100644 index 0000000000..5eb530c3da --- /dev/null +++ b/assets/first_party/wildlife/sheep/sheep_annoy.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94a863d3ee4e6149ef51d40dc6d6be88e1d00afbdf4cc6e585f5dfcf1b239c9b +size 6602 diff --git a/assets/first_party/wildlife/sheep/sheep_annoy.png.import b/assets/first_party/wildlife/sheep/sheep_annoy.png.import new file mode 100644 index 0000000000..231c2be703 --- /dev/null +++ b/assets/first_party/wildlife/sheep/sheep_annoy.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://kv4vsg7f23o8" +path="res://.godot/imported/sheep_annoy.png-aaa698387d0174ec52776aa822d2e175.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/first_party/wildlife/sheep/sheep_annoy.png" +dest_files=["res://.godot/imported/sheep_annoy.png-aaa698387d0174ec52776aa822d2e175.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/scenes/game_elements/characters/components/sprite_frames/sheep.tres b/scenes/game_elements/characters/components/sprite_frames/sheep.tres index d0b5beb596..267610f772 100644 --- a/scenes/game_elements/characters/components/sprite_frames/sheep.tres +++ b/scenes/game_elements/characters/components/sprite_frames/sheep.tres @@ -1,6 +1,7 @@ [gd_resource type="SpriteFrames" format=3 uid="uid://b0ba41utstkyk"] [ext_resource type="Texture2D" uid="uid://cgjgqji5js05i" path="res://assets/first_party/wildlife/sheep/sheep_idle.png" id="1_5aro1"] +[ext_resource type="Texture2D" uid="uid://kv4vsg7f23o8" path="res://assets/first_party/wildlife/sheep/sheep_annoy.png" id="1_63h84"] [sub_resource type="AtlasTexture" id="AtlasTexture_9t40y"] atlas = ExtResource("1_5aro1") @@ -118,6 +119,54 @@ region = Rect2(3456, 0, 128, 128) atlas = ExtResource("1_5aro1") region = Rect2(3584, 0, 128, 128) +[sub_resource type="AtlasTexture" id="AtlasTexture_2x7nr"] +atlas = ExtResource("1_63h84") +region = Rect2(0, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_6evyf"] +atlas = ExtResource("1_63h84") +region = Rect2(128, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_a6pty"] +atlas = ExtResource("1_63h84") +region = Rect2(256, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_wvgmw"] +atlas = ExtResource("1_63h84") +region = Rect2(384, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_d1gs1"] +atlas = ExtResource("1_63h84") +region = Rect2(512, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_lqadr"] +atlas = ExtResource("1_63h84") +region = Rect2(640, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_uahbe"] +atlas = ExtResource("1_63h84") +region = Rect2(768, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_ablkt"] +atlas = ExtResource("1_63h84") +region = Rect2(896, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_78rur"] +atlas = ExtResource("1_63h84") +region = Rect2(1024, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_kfy2s"] +atlas = ExtResource("1_63h84") +region = Rect2(1152, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_5kpjk"] +atlas = ExtResource("1_63h84") +region = Rect2(1280, 0, 128, 128) + +[sub_resource type="AtlasTexture" id="AtlasTexture_6jekj"] +atlas = ExtResource("1_63h84") +region = Rect2(1408, 0, 128, 128) + [resource] animations = [{ "frames": [{ @@ -211,4 +260,45 @@ animations = [{ "loop": 1, "name": &"idle", "speed": 10.0 +}, { +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_2x7nr") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_6evyf") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_a6pty") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_wvgmw") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_d1gs1") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_lqadr") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_uahbe") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_ablkt") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_78rur") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_kfy2s") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_5kpjk") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_6jekj") +}], +"loop": 0, +"name": &"pet", +"speed": 10.0 }] diff --git a/scenes/game_elements/characters/npcs/cat/cat.tscn b/scenes/game_elements/characters/npcs/cat/cat.tscn index 078360e4c5..b77c2273a2 100644 --- a/scenes/game_elements/characters/npcs/cat/cat.tscn +++ b/scenes/game_elements/characters/npcs/cat/cat.tscn @@ -75,11 +75,13 @@ debug_color = Color(0.6, 0.545, 0, 0.42) stream = SubResource("AudioStreamRandomizer_8kxh7") bus = &"SFX" -[node name="PetInteraction" type="Node" parent="." unique_id=929067504 node_paths=PackedStringArray("interact_area", "sound_effect_player", "fact_counter")] +[node name="PetInteraction" type="Node" parent="." unique_id=929067504 node_paths=PackedStringArray("interact_area", "sound_effect_player", "animated_sprite", "fact_counter", "behaviors_to_disable")] script = ExtResource("4_t04tf") interact_area = NodePath("../InteractArea") sound_effect_player = NodePath("../AudioStreamPlayer2D") +animated_sprite = NodePath("../AnimatedSprite2D") fact_counter = NodePath("../FactCounter") +behaviors_to_disable = [NodePath("../AnimatedSprite2D/CharacterSpriteBehavior")] [node name="FactCounter" type="Node" parent="." unique_id=539544383] script = ExtResource("6_0bwy3") diff --git a/scenes/game_elements/characters/npcs/cat/components/cat.tres b/scenes/game_elements/characters/npcs/cat/components/cat.tres index 816155ba86..acf8919158 100644 --- a/scenes/game_elements/characters/npcs/cat/components/cat.tres +++ b/scenes/game_elements/characters/npcs/cat/components/cat.tres @@ -2,6 +2,7 @@ [ext_resource type="Texture2D" uid="uid://dywvbod2hs33q" path="res://scenes/world_map/components/cat-idle.png" id="1_jyuim"] [ext_resource type="Texture2D" uid="uid://di4qwtf4ioswt" path="res://scenes/world_map/components/cat-walk.png" id="2_166jg"] +[ext_resource type="Texture2D" uid="uid://bmp221stnkio5" path="res://scenes/game_elements/characters/npcs/cat/components/cat_pet.png" id="2_tenf8"] [sub_resource type="AtlasTexture" id="AtlasTexture_tenf8"] atlas = ExtResource("1_jyuim") @@ -43,6 +44,78 @@ region = Rect2(576, 192, 192, 192) atlas = ExtResource("1_jyuim") region = Rect2(768, 192, 192, 192) +[sub_resource type="AtlasTexture" id="AtlasTexture_o8oyq"] +atlas = ExtResource("2_tenf8") +region = Rect2(0, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_2s82j"] +atlas = ExtResource("2_tenf8") +region = Rect2(192, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_gdn0v"] +atlas = ExtResource("2_tenf8") +region = Rect2(384, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_fr5ui"] +atlas = ExtResource("2_tenf8") +region = Rect2(576, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_33sh3"] +atlas = ExtResource("2_tenf8") +region = Rect2(768, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_fra8p"] +atlas = ExtResource("2_tenf8") +region = Rect2(960, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_p4pwa"] +atlas = ExtResource("2_tenf8") +region = Rect2(1152, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_kv3x5"] +atlas = ExtResource("2_tenf8") +region = Rect2(1344, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_tjbji"] +atlas = ExtResource("2_tenf8") +region = Rect2(1536, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_jecg1"] +atlas = ExtResource("2_tenf8") +region = Rect2(1728, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_fqu7j"] +atlas = ExtResource("2_tenf8") +region = Rect2(1920, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_w7mll"] +atlas = ExtResource("2_tenf8") +region = Rect2(2112, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_illha"] +atlas = ExtResource("2_tenf8") +region = Rect2(2304, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_og32c"] +atlas = ExtResource("2_tenf8") +region = Rect2(2496, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_adt2d"] +atlas = ExtResource("2_tenf8") +region = Rect2(2688, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_jhyj1"] +atlas = ExtResource("2_tenf8") +region = Rect2(2880, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_av30e"] +atlas = ExtResource("2_tenf8") +region = Rect2(3072, 0, 192, 192) + +[sub_resource type="AtlasTexture" id="AtlasTexture_ox5sq"] +atlas = ExtResource("2_tenf8") +region = Rect2(3264, 0, 192, 192) + [sub_resource type="AtlasTexture" id="AtlasTexture_80j4i"] atlas = ExtResource("2_166jg") region = Rect2(0, 0, 192, 192) @@ -122,6 +195,65 @@ animations = [{ }, { "frames": [{ "duration": 1.0, +"texture": SubResource("AtlasTexture_o8oyq") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_2s82j") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_gdn0v") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_fr5ui") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_33sh3") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_fra8p") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_p4pwa") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_kv3x5") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_tjbji") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_jecg1") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_fqu7j") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_w7mll") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_illha") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_og32c") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_adt2d") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_jhyj1") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_av30e") +}, { +"duration": 1.0, +"texture": SubResource("AtlasTexture_ox5sq") +}], +"loop": 0, +"name": &"pet", +"speed": 10.0 +}, { +"frames": [{ +"duration": 1.0, "texture": SubResource("AtlasTexture_80j4i") }, { "duration": 1.0, diff --git a/scenes/game_elements/characters/npcs/cat/components/cat_pet.png b/scenes/game_elements/characters/npcs/cat/components/cat_pet.png new file mode 100644 index 0000000000..edd876174c --- /dev/null +++ b/scenes/game_elements/characters/npcs/cat/components/cat_pet.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25a1aa7cb7cf4d41a81912e8f17aa8e8fd1156b611464222eaaa5c5960627a72 +size 10116 diff --git a/scenes/game_elements/characters/npcs/cat/components/cat_pet.png.import b/scenes/game_elements/characters/npcs/cat/components/cat_pet.png.import new file mode 100644 index 0000000000..0036100334 --- /dev/null +++ b/scenes/game_elements/characters/npcs/cat/components/cat_pet.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmp221stnkio5" +path="res://.godot/imported/cat_pet.png-cb33f43198a3d2267827b9ed0ae1eb0e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://scenes/game_elements/characters/npcs/cat/components/cat_pet.png" +dest_files=["res://.godot/imported/cat_pet.png-cb33f43198a3d2267827b9ed0ae1eb0e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +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/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +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/scenes/game_elements/characters/npcs/components/pet_interaction.gd b/scenes/game_elements/characters/npcs/components/pet_interaction.gd index 0750f9645e..4df4d7d39f 100644 --- a/scenes/game_elements/characters/npcs/components/pet_interaction.gd +++ b/scenes/game_elements/characters/npcs/components/pet_interaction.gd @@ -1,31 +1,107 @@ # SPDX-FileCopyrightText: The Threadbare Authors # SPDX-License-Identifier: MPL-2.0 +@tool +class_name PetInteraction extends Node +## A simple "no code" way to react to an interaction. +## +## - Play a sound effect.[br] +## - Play an animation.[br] +## - Shake.[br] +## - Increment a fact counter.[br][br] +## +## The interact area will be re-enabled after the sound or animation (or both) finish playing. ## The area to interact with the pet. @export var interact_area: InteractArea -## Sound effect to play when interacted. +## If set, this sound effect will play when interacted. @export var sound_effect_player: AudioStreamPlayer2D +## If set, it will play the [code]"pet"[/code] animation when interacted. +@export var animated_sprite: AnimatedSprite2D: + set = _set_animated_sprite + ## If set, it will shake when interacted. @export var shaker: Shaker ## If set, it will increment when interacted. @export var fact_counter: FactCounter +## Behaviors to disable during the interaction. +## When the interaction ends, they will go back to their previous +## [member Node.process_mode]. +@export var behaviors_to_disable: Array[Node] + +var _previous_behavior_modes: Dictionary[Node, Node.ProcessMode] + + +func _set_animated_sprite(new_animated_sprite: AnimatedSprite2D) -> void: + animated_sprite = new_animated_sprite + update_configuration_warnings() + + +func _get_configuration_warnings() -> PackedStringArray: + var warnings: PackedStringArray + if ( + animated_sprite + and not ( + animated_sprite.sprite_frames and animated_sprite.sprite_frames.has_animation(&"pet") + ) + ): + warnings.append("animated_sprite is missing the following animation: pet") + return warnings + func _ready() -> void: + if Engine.is_editor_hint(): + return interact_area.interaction_started.connect(_on_interact_area_interaction_started) func _on_interact_area_interaction_started(_player: Player, _from_right: bool) -> void: interact_area.end_interaction() interact_area.disabled = true - sound_effect_player.play() + for behavior in behaviors_to_disable: + _previous_behavior_modes[behavior] = behavior.process_mode + behavior.process_mode = Node.PROCESS_MODE_DISABLED + if sound_effect_player: + sound_effect_player.finished.connect(_on_sound_effect_player_finished, CONNECT_ONE_SHOT) + sound_effect_player.play() + if animated_sprite: + animated_sprite.animation_finished.connect( + _on_animated_sprite_animation_finished, CONNECT_ONE_SHOT + ) + animated_sprite.play(&"pet") if shaker: shaker.shake() if fact_counter: fact_counter.increment() - await sound_effect_player.finished + + +func _check_finished() -> void: + if ( + sound_effect_player + and sound_effect_player.finished.is_connected(_on_sound_effect_player_finished) + ): + return + if ( + animated_sprite + and animated_sprite.animation_finished.is_connected(_on_animated_sprite_animation_finished) + ): + return + if animated_sprite: + animated_sprite.play(&"idle") + + for behavior in behaviors_to_disable: + behavior.process_mode = _previous_behavior_modes[behavior] + interact_area.disabled = false + + +func _on_sound_effect_player_finished() -> void: + _check_finished() + + +func _on_animated_sprite_animation_finished() -> void: + _check_finished() diff --git a/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd b/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd new file mode 100644 index 0000000000..e75d0892f0 --- /dev/null +++ b/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: The Threadbare Authors +# SPDX-License-Identifier: MPL-2.0 +extends Node +## Behavior to face a character in the opposite direction when interacted. +## +## + +@onready var animated_sprite_2d: AnimatedSprite2D = %AnimatedSprite2D +@onready var character: CharacterBody2D = get_parent() + + +func _on_interact_area_interaction_started(_player: Player, from_right: bool) -> void: + var parent_is_flipped := character.global_transform.x.x < 0.0 + animated_sprite_2d.flip_h = from_right != parent_is_flipped diff --git a/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd.uid b/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd.uid new file mode 100644 index 0000000000..880a307b1f --- /dev/null +++ b/scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd.uid @@ -0,0 +1 @@ +uid://beqwrk30lk8bc diff --git a/scenes/game_elements/props/decoration/sheep/sheep.tscn b/scenes/game_elements/props/decoration/sheep/sheep.tscn index 93aa5c2ae3..1d4dd44a03 100644 --- a/scenes/game_elements/props/decoration/sheep/sheep.tscn +++ b/scenes/game_elements/props/decoration/sheep/sheep.tscn @@ -8,6 +8,7 @@ [ext_resource type="Script" uid="uid://dy68p7gf07pi3" path="res://scenes/game_logic/sprite_behaviors/character_sprite_behavior.gd" id="4_tsjbs"] [ext_resource type="AudioStream" uid="uid://dtf82j11434vb" path="res://scenes/game_elements/props/decoration/sheep/components/sheep_baa.wav" id="5_5wm27"] [ext_resource type="Script" uid="uid://dxvv340yej4py" path="res://scenes/game_logic/fact_counter/fact_counter.gd" id="7_1k1ft"] +[ext_resource type="Script" uid="uid://beqwrk30lk8bc" path="res://scenes/game_elements/props/decoration/sheep/components/face_away_behavior.gd" id="9_3vki4"] [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_hj6il"] radius = 6.0 @@ -70,13 +71,20 @@ debug_color = Color(0.6, 0.545, 0, 0.42) stream = SubResource("AudioStreamRandomizer_3vki4") bus = &"SFX" -[node name="PetInteraction" type="Node" parent="." unique_id=1162035923 node_paths=PackedStringArray("interact_area", "sound_effect_player", "shaker", "fact_counter")] +[node name="PetInteraction" type="Node" parent="." unique_id=1162035923 node_paths=PackedStringArray("interact_area", "sound_effect_player", "animated_sprite", "shaker", "fact_counter", "behaviors_to_disable")] script = ExtResource("4_pcfmk") interact_area = NodePath("../InteractArea") sound_effect_player = NodePath("../AudioStreamPlayer2D") +animated_sprite = NodePath("../AnimatedSprite2D") shaker = NodePath("../AnimatedSprite2D/Shaker") fact_counter = NodePath("../FactCounter") +behaviors_to_disable = [NodePath("../AnimatedSprite2D/CharacterSpriteBehavior")] [node name="FactCounter" type="Node" parent="." unique_id=2116673480] script = ExtResource("7_1k1ft") prefix = "sheeps_annoyed" + +[node name="FaceAwayBehavior" type="Node" parent="." unique_id=1519515067] +script = ExtResource("9_3vki4") + +[connection signal="interaction_started" from="InteractArea" to="FaceAwayBehavior" method="_on_interact_area_interaction_started"]