-
Notifications
You must be signed in to change notification settings - Fork 289
Add powerup for abilities #2073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e53a1dd
c48735e
413a7bc
da1ccc9
d8cc4c4
7f1c245
55220c9
676f3da
a6a6462
0ed1ec0
fbedc10
b7d88cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| [gd_scene format=3 uid="uid://xbgo0b3f50mw"] | ||
|
|
||
| [ext_resource type="Script" uid="uid://bofv3bcwj3rx2" path="res://scenes/game_elements/props/projectile/components/projectile.gd" id="1_6uc4b"] | ||
| [ext_resource type="PackedScene" uid="uid://clgisducnnh0a" path="res://scenes/game_elements/fx/liquid_small_splat/liquid_small_splat.tscn" id="2_3cevt"] | ||
| [ext_resource type="PackedScene" uid="uid://b4qu6wml5gd7a" path="res://scenes/game_elements/fx/liquid_big_splat/liquid_big_splat.tscn" id="3_vc4n7"] | ||
| [ext_resource type="PackedScene" uid="uid://bgce3qns72g3m" path="res://scenes/game_elements/fx/liquid_trail.tscn" id="4_kxf4x"] | ||
| [ext_resource type="SpriteFrames" uid="uid://bhamin2pby7tq" path="res://scenes/game_elements/props/projectile/components/inkblob_spriteframes.tres" id="5_tb5uj"] | ||
| [ext_resource type="AudioStream" uid="uid://7jlv4wqpihl7" path="res://scenes/game_elements/props/projectile/components/blob_hit.wav" id="6_lff8h"] | ||
|
|
||
| [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_tbgi4"] | ||
| friction = 0.0 | ||
| bounce = 1.0 | ||
|
|
||
| [sub_resource type="RectangleShape2D" id="RectangleShape2D_o6xl0"] | ||
| size = Vector2(44, 44) | ||
|
|
||
| [node name="InkBlobProjectile" type="RigidBody2D" unique_id=1611529190 groups=["projectiles"]] | ||
| collision_layer = 256 | ||
| collision_mask = 80 | ||
| mass = 0.3 | ||
| physics_material_override = SubResource("PhysicsMaterial_tbgi4") | ||
| gravity_scale = 0.0 | ||
| lock_rotation = true | ||
| continuous_cd = 2 | ||
| contact_monitor = true | ||
| max_contacts_reported = 1 | ||
| script = ExtResource("1_6uc4b") | ||
| hit_speed = 40.0 | ||
| duration = 30.0 | ||
| small_fx_scene = ExtResource("2_3cevt") | ||
| big_fx_scene = ExtResource("3_vc4n7") | ||
| trail_fx_scene = ExtResource("4_kxf4x") | ||
|
|
||
| [node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1499726276] | ||
| shape = SubResource("RectangleShape2D_o6xl0") | ||
|
|
||
| [node name="VisibleThings" type="Node2D" parent="." unique_id=1129773837] | ||
| unique_name_in_owner = true | ||
| position = Vector2(-3, 0) | ||
|
|
||
| [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="VisibleThings" unique_id=1816818143] | ||
| unique_name_in_owner = true | ||
| sprite_frames = ExtResource("5_tb5uj") | ||
| autoplay = "default" | ||
|
|
||
| [node name="TrailFXMarker" type="Marker2D" parent="VisibleThings" unique_id=771420475] | ||
| unique_name_in_owner = true | ||
| position = Vector2(-40, 0) | ||
|
|
||
| [node name="DurationTimer" type="Timer" parent="." unique_id=259732970] | ||
| unique_name_in_owner = true | ||
|
|
||
| [node name="HitSound" type="AudioStreamPlayer2D" parent="." unique_id=1862098516] | ||
| unique_name_in_owner = true | ||
| stream = ExtResource("6_lff8h") | ||
| bus = &"SFX" | ||
|
|
||
| [connection signal="body_entered" from="." to="." method="_on_body_entered"] | ||
| [connection signal="timeout" from="DurationTimer" to="." method="_on_duration_timer_timeout"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # SPDX-FileCopyrightText: The Threadbare Authors | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| ~ start | ||
| [wave amp=25 freq=5]You got a new ability! [b]{{ability_name}}[/b][/wave] | ||
| => END |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| [remap] | ||
|
|
||
| importer="dialogue_manager" | ||
| importer_version=15 | ||
| type="Resource" | ||
| uid="uid://cj0i5jwlv8idi" | ||
| path="res://.godot/imported/default_powerup.dialogue-7b4f95958377611890379db90e1904ef.tres" | ||
|
|
||
| [deps] | ||
|
|
||
| source_file="res://scenes/game_elements/props/powerup/components/default_powerup.dialogue" | ||
| dest_files=["res://.godot/imported/default_powerup.dialogue-7b4f95958377611890379db90e1904ef.tres"] | ||
|
|
||
| [params] | ||
|
|
||
| defaults=true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| # SPDX-FileCopyrightText: The Threadbare Authors | ||
| # SPDX-License-Identifier: MPL-2.0 | ||
| @tool | ||
| extends CharacterBody2D | ||
| ## A powerup that, when interacted, enables a player ability. | ||
| ## | ||
| ## By default it also displays a dialogue telling the player that an ability | ||
| ## has been obtained. | ||
|
|
||
| ## Emitted when this powerup is collected. | ||
| signal collected | ||
|
|
||
| ## The player ability to enable. | ||
| @export var ability: Enums.PlayerAbilities = Enums.PlayerAbilities.ABILITY_A | ||
|
|
||
| ## Name for the ability to display if using the default dialogue. | ||
| @export var ability_name: String | ||
|
|
||
| ## Text to display in the label when the player gets close to interact with this powerup. | ||
| @export var interact_action: String: | ||
| set = _set_interact_action | ||
|
|
||
| ## Asset of this powerup. | ||
| @export var sprite_frames: SpriteFrames: | ||
| set = _set_sprite_frames | ||
|
|
||
| ## The powerup shines with this color through a shader. | ||
| @export var highlight_color: Color = Color.WHITE: | ||
| set = _set_highlight_color | ||
|
|
||
| ## Dialogue to display when collecting the powerup. | ||
| @export var dialogue: DialogueResource = preload("uid://cj0i5jwlv8idi") | ||
|
|
||
| var _tween: Tween | ||
|
|
||
| @onready var interact_area: InteractArea = %InteractArea | ||
| @onready var highlight_effect: Sprite2D = %HighlightEffect | ||
| @onready var sprite: AnimatedSprite2D = %Sprite | ||
| @onready var interact_collision: CollisionShape2D = %InteractCollision | ||
| @onready var ground_collision: CollisionShape2D = %GroundCollision | ||
| @onready var hookable_collision: CollisionShape2D = %HookableCollision | ||
|
|
||
|
|
||
| func _set_interact_action(new_interact_action: String) -> void: | ||
| interact_action = new_interact_action | ||
| if is_node_ready(): | ||
| interact_area.action = interact_action | ||
|
|
||
|
|
||
| func _set_sprite_frames(new_sprite_frames: SpriteFrames) -> void: | ||
| sprite_frames = new_sprite_frames | ||
| if is_node_ready(): | ||
| sprite.sprite_frames = sprite_frames | ||
| sprite.play("default") | ||
|
|
||
|
|
||
| func _set_highlight_color(new_highlight_color: Color) -> void: | ||
| highlight_color = new_highlight_color | ||
| if is_node_ready(): | ||
| highlight_effect.modulate = highlight_color | ||
|
|
||
|
|
||
| func _ready() -> void: | ||
| _set_interact_action(interact_action) | ||
| _set_sprite_frames(sprite_frames) | ||
| _set_highlight_color(highlight_color) | ||
| if Engine.is_editor_hint(): | ||
| return | ||
| GameState.abilities_changed.connect(_on_abilities_changed) | ||
| _on_abilities_changed() | ||
|
|
||
|
|
||
| func _notification(what: int) -> void: | ||
| match what: | ||
| NOTIFICATION_EDITOR_PRE_SAVE: | ||
| # Since this is a tool script that plays the animations in the | ||
| # editor, reset the frame progress before saving the scene. | ||
| sprite.frame_progress = 0 | ||
|
|
||
|
|
||
| func _on_abilities_changed() -> void: | ||
| var has_ability := GameState.has_ability(ability) | ||
| ground_collision.disabled = has_ability | ||
| interact_collision.disabled = has_ability | ||
| hookable_collision.disabled = has_ability | ||
| highlight_effect.visible = not has_ability | ||
| var alpha: float = 0.5 if has_ability else 1.0 | ||
| sprite.modulate = Color(Color.WHITE, alpha) | ||
| _set_highlight_color(highlight_color) | ||
| var highlight_material := highlight_effect.material as ShaderMaterial | ||
| if highlight_material: | ||
| highlight_material.set_shader_parameter(&"width", 0.4) | ||
|
|
||
|
|
||
| func _on_interact_area_interaction_started( | ||
| _player: Player, _from_right: bool, source: InteractArea | ||
| ) -> void: | ||
| if _tween: | ||
| _tween.kill() | ||
| _tween = create_tween() | ||
| _tween.tween_property(highlight_effect, "modulate", Color.WHITE, 0.5) | ||
| _tween.tween_property(highlight_effect, "material:shader_parameter/width", 1.0, 1.0) | ||
| await _tween.finished | ||
| if dialogue: | ||
| DialogueManager.show_dialogue_balloon(dialogue, "", [self]) | ||
| await DialogueManager.dialogue_ended | ||
| source.end_interaction() | ||
| GameState.set_ability(ability, true) | ||
| collected.emit() | ||
|
|
||
|
|
||
| func _on_interact_area_observers_changed() -> void: | ||
| if _tween: | ||
| _tween.kill() | ||
| _tween = create_tween() | ||
| var width: float = 0.8 if interact_area.is_being_observed else 0.4 | ||
| _tween.tween_property(highlight_effect, "material:shader_parameter/width", width, 1.0) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because the material is not local to scene, observing any powerup causes every powerup to glow: Screencast.From.2026-03-27.10-38-25.mp4I'll push a fixup.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch!
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the fixup. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| uid://bhmae3daygmqh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| [remap] | ||
|
|
||
| importer="texture" | ||
| type="CompressedTexture2D" | ||
| uid="uid://dr1cdu5ien6jq" | ||
| path="res://.godot/imported/powerup.png-a4ee45e73209b83508bc25ff7865937f.ctex" | ||
| metadata={ | ||
| "vram_texture": false | ||
| } | ||
|
|
||
| [deps] | ||
|
|
||
| source_file="res://scenes/game_elements/props/powerup/components/powerup.png" | ||
| dest_files=["res://.godot/imported/powerup.png-a4ee45e73209b83508bc25ff7865937f.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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| [remap] | ||
|
|
||
| importer="texture" | ||
| type="CompressedTexture2D" | ||
| uid="uid://bbo1nd3usbxnr" | ||
| path="res://.godot/imported/powerup_highlight.png-deef463ba3599bc39e64667d2828727c.ctex" | ||
| metadata={ | ||
| "vram_texture": false | ||
| } | ||
|
|
||
| [deps] | ||
|
|
||
| source_file="res://scenes/game_elements/props/powerup/components/powerup_highlight.png" | ||
| dest_files=["res://.godot/imported/powerup_highlight.png-deef463ba3599bc39e64667d2828727c.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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping to see this. I have been sceptical of objects in the world that you can walk through (e.g. arguing that the collectible threads should have a collider) but in this case I think it makes sense for the powerup to become a ghost once you have collected it, because it lets us barricade a pathway with a mandatory powerup.