Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,26 @@ func shatter_string() -> void:
## While pulling, the player is allowed to go through non-walkable floor.
func pull_string() -> void:
pulling = true

# While pulling, this class takes control over the player movement.
if character.has_method("take_control"):
character.take_control(self)
character.set_collision_mask_value(Enums.CollisionLayers.NON_WALKABLE_FLOOR, false)

# If the entity has a got_pulled handler, call it and connect to the pull_released signal
# of the HookableArea. The entity is responsible to call it.
var ending_area := get_ending_area()
if ending_area.controlled_entity.has_method("got_pulled"):
ending_area.pull_released.connect(_on_pull_released, CONNECT_ONE_SHOT)
var direction := hook_string.points[0].direction_to(hook_string.points[1])
ending_area.controlled_entity.got_pulled(direction)


func _on_pull_released(cancelled: bool) -> void:
if cancelled and hook_string:
shatter_string()
stop_pulling()


## Stop pulling and remove the [member hook_string].
## [br][br]
Expand Down Expand Up @@ -332,7 +347,7 @@ func _process_pulling(_delta: float) -> void:
return

var target := ending_area.controlled_entity
var weight := ending_area.weight if target is CharacterBody2D else 1.0
var weight := ending_area.weight

# Vector from player to first point:
var player_distance: Vector2 = hook_string.points[-2] - hook_string.points[-1]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
[ext_resource type="Script" uid="uid://b7704hdflt5t8" path="res://scenes/game_elements/characters/player/components/player_hook.gd" id="1_40sye"]
[ext_resource type="PackedScene" uid="uid://b0dehcnfo68j1" path="res://scenes/game_elements/props/hook_control/hook_control.tscn" id="2_5svv0"]

[node name="PlayerHook" type="Node2D" unique_id=1972626703 node_paths=PackedStringArray("character") groups=["hook_listener"]]
[node name="PlayerHook" type="Node2D" unique_id=1972626703 groups=["hook_listener"]]
script = ExtResource("1_40sye")
character = NodePath("")

[node name="HookControl" parent="." unique_id=1022482491 instance=ExtResource("2_5svv0")]
state = 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
[ext_resource type="PackedScene" uid="uid://covsdqqsd6rsy" path="res://scenes/game_elements/props/sign/sign.tscn" id="13_hmcpk"]
[ext_resource type="PackedScene" uid="uid://cuu65vogubwxd" path="res://scenes/game_elements/props/repellable_lever/repellable_lever.tscn" id="14_84lgk"]
[ext_resource type="PackedScene" uid="uid://cl06pid826dtg" path="res://scenes/game_elements/characters/player/components/player_repel.tscn" id="15_wn1pr"]
[ext_resource type="PackedScene" uid="uid://dkpelgxwtvcxd" path="res://scenes/game_elements/props/hookable_box/hookable_box.tscn" id="17_61qjx"]
[ext_resource type="PackedScene" uid="uid://dohb701lxbe5s" path="res://scenes/game_elements/props/hookable_needle/hookable_needle.tscn" id="20_euc4w"]

[node name="CustomRepellableObjectsTest" type="Node2D" unique_id=324172432]
script = ExtResource("1_pxtmd")
Expand Down Expand Up @@ -83,6 +85,10 @@ position = Vector2(416, 608)
constrain_layer = NodePath("../../TileMapLayers/Paths")
metadata/_edit_group_ = true

[node name="HookableBox" parent="OnTheGround" unique_id=1813344410 node_paths=PackedStringArray("constrain_layer") instance=ExtResource("17_61qjx")]
position = Vector2(414, 417)
constrain_layer = NodePath("../../TileMapLayers/Paths")

[node name="RepellableBall" parent="OnTheGround" unique_id=916389317 instance=ExtResource("10_584di")]
position = Vector2(320, 1088)

Expand All @@ -105,6 +111,15 @@ targets = [NodePath("../../ToggleableTileMapLayer")]
[node name="RepellableLever2" parent="OnTheGround" unique_id=632125149 instance=ExtResource("14_84lgk")]
position = Vector2(1090, 614)

[node name="HookableNeedle" parent="OnTheGround" unique_id=1182662384 instance=ExtResource("20_euc4w")]
position = Vector2(273, 270)

[node name="HookableNeedle2" parent="OnTheGround" unique_id=386123252 instance=ExtResource("20_euc4w")]
position = Vector2(559, 270)

[node name="HookableNeedle3" parent="OnTheGround" unique_id=1541754292 instance=ExtResource("20_euc4w")]
position = Vector2(419, 99)

[node name="Decoration" type="Node2D" parent="OnTheGround" unique_id=1499875127]
y_sort_enabled = true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ var _hook_angle: float
## diagonal directions when releasing the input actions.
@onready var d_pad_timer: Timer = %DPadTimer

@onready var mouse_aiming_timer: Timer = %MouseAimingTimer


func _unhandled_input(_event: InputEvent) -> void:
if _event is InputEventMouseMotion:
mouse_aiming_timer.start()
var axis := get_global_mouse_position() - global_position
if not axis.is_zero_approx():
_hook_angle = axis.angle()
Expand All @@ -102,7 +105,8 @@ func _unhandled_input(_event: InputEvent) -> void:
# there is always one that is released first so the aim direction ends up being either left or
# down, not left AND down.
if (
_event is InputEventKey
mouse_aiming_timer.is_stopped()
and _event is InputEventKey
and (
_event.is_action_released(&"aim_left")
or _event.is_action_released(&"aim_right")
Expand All @@ -113,7 +117,8 @@ func _unhandled_input(_event: InputEvent) -> void:
d_pad_timer.start()
return

_update_hook_angle()
if mouse_aiming_timer.is_stopped():
_update_hook_angle()

if Input.is_action_just_pressed(&"throw"):
pressing_throw_action = true
Expand Down
5 changes: 5 additions & 0 deletions scenes/game_elements/props/hook_control/hook_control.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ unique_name_in_owner = true
wait_time = 0.2
one_shot = true

[node name="MouseAimingTimer" type="Timer" parent="." unique_id=405211158]
unique_name_in_owner = true
wait_time = 3.0
one_shot = true

[connection signal="timeout" from="DPadTimer" to="." method="_on_d_pad_timer_timeout"]
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ extends Area2D
## This script automatically configures the correct [member collision_layer] and
## [member collision_mask] values to enable interaction with the grappling hook.

## Use this signal to release itself from a grappling hook pull.
signal pull_released(cancelled: bool)

## The game entity that becomes hookable.
## [br][br]
## [b]Note:[/b] If the parent node is a Node2D and this isn't set,
Expand Down Expand Up @@ -70,6 +73,11 @@ func get_anchor_position() -> Vector2:
return anchor_point.global_position if anchor_point else global_position


## Emit the [signal pull_released] signal.
func release_from_pull(cancelled: bool = false) -> void:
pull_released.emit(cancelled)


func _get_configuration_warnings() -> PackedStringArray:
var warnings: PackedStringArray
if not controlled_entity:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# SPDX-FileCopyrightText: The Threadbare Authors
# SPDX-License-Identifier: MPL-2.0
extends AnimatableBody2D

const NEIGHBORS_FOR_AXIS: Dictionary[Vector2i, TileSet.CellNeighbor] = {
Vector2i.DOWN: TileSet.CELL_NEIGHBOR_BOTTOM_SIDE,
Vector2i.LEFT: TileSet.CELL_NEIGHBOR_LEFT_SIDE,
Vector2i.UP: TileSet.CELL_NEIGHBOR_TOP_SIDE,
Vector2i.RIGHT: TileSet.CELL_NEIGHBOR_RIGHT_SIDE,
}

@export var constrain_layer: TileMapLayer

var tween: Tween

@onready var hookable_area: HookableArea = %HookableArea
@onready var shaker: Shaker = %Shaker


func global_position_to_tile_coordinate(global_pos: Vector2) -> Vector2i:
return constrain_layer.local_to_map(constrain_layer.to_local(global_pos))


func tile_coordinate_to_global_position(coord: Vector2i) -> Vector2:
return constrain_layer.to_global(constrain_layer.map_to_local(coord))


func _ready() -> void:
# Put this object on the grid:
var coord := global_position_to_tile_coordinate(global_position)
global_position = tile_coordinate_to_global_position(coord)


func get_closest_axis(vector: Vector2) -> Vector2i:
if abs(vector.x) > abs(vector.y):
# Closer to Horizontal (X-axis)
return Vector2i(sign(vector.x), 0)

# Closer to Vertical (Y-axis)
return Vector2i(0, sign(vector.y))


func got_pulled(direction: Vector2) -> void:
var axis := get_closest_axis(direction)
if axis == Vector2i.ZERO:
shaker.shake()
await Engine.get_main_loop().create_timer(0.1).timeout
hookable_area.release_from_pull(true)
return

var neighbor := NEIGHBORS_FOR_AXIS[axis]
var coord := global_position_to_tile_coordinate(global_position)
assert(constrain_layer.get_cell_tile_data(coord) != null)
var new_coord := constrain_layer.get_neighbor_cell(coord, neighbor)
var data := constrain_layer.get_cell_tile_data(new_coord)

if not data:
shaker.shake()
await Engine.get_main_loop().create_timer(0.1).timeout
hookable_area.release_from_pull(true)
return

if tween:
if tween.is_running():
return
tween.kill()

tween = create_tween()
tween.set_ease(Tween.EASE_OUT)
# Assuming that the tile size is square:
var new_position := position + Vector2(axis) * constrain_layer.tile_set.tile_size.x
tween.tween_property(self, "position", new_position, .2)
await tween.finished
hookable_area.release_from_pull()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://gvjhy1uvsqpc
63 changes: 63 additions & 0 deletions scenes/game_elements/props/hookable_box/hookable_box.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[gd_scene format=3 uid="uid://dkpelgxwtvcxd"]

[ext_resource type="Script" uid="uid://gvjhy1uvsqpc" path="res://scenes/game_elements/props/hookable_box/components/hookable_box.gd" id="1_34j61"]
[ext_resource type="Texture2D" uid="uid://dslom0xbe1if7" path="res://assets/third_party/tiny-swords/Terrain/Ground/Shadows.png" id="2_f8qwn"]
[ext_resource type="Texture2D" uid="uid://c7oht7wudd8wa" path="res://assets/first_party/tiles/Cliff_Tiles.png" id="3_u0gye"]
[ext_resource type="Script" uid="uid://dabvr3pqmyya4" path="res://scenes/game_elements/props/hookable_area/components/hookable_area.gd" id="4_ml4a5"]
[ext_resource type="Script" uid="uid://dunsvrhq42214" path="res://scenes/game_elements/fx/shaker/components/shaker.gd" id="4_to7a4"]

[sub_resource type="AtlasTexture" id="AtlasTexture_bu3x1"]
atlas = ExtResource("3_u0gye")
region = Rect2(192, 256, 64, 128)

[sub_resource type="RectangleShape2D" id="RectangleShape2D_8dti7"]
size = Vector2(64, 64)

[sub_resource type="RectangleShape2D" id="RectangleShape2D_ml4a5"]
size = Vector2(96, 160)

[node name="HookableBox" type="AnimatableBody2D" unique_id=1805651676]
editor_description = "A hookable box that moves in a fixed grid.

Almost the same as the repellable box example, but instead has a HookableArea and defines a got_hooked() handler method."
collision_layer = 768
collision_mask = 531
script = ExtResource("1_34j61")

[node name="Sprite2D2" type="Sprite2D" parent="." unique_id=1393129317]
texture = ExtResource("2_f8qwn")

[node name="Sprite2D" type="Sprite2D" parent="." unique_id=898668959]
position = Vector2(0, -32)
texture = SubResource("AtlasTexture_bu3x1")

[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=363689712]
rotation = -1.5707964
shape = SubResource("RectangleShape2D_8dti7")

[node name="Shaker" type="Node2D" parent="." unique_id=103380831 node_paths=PackedStringArray("target")]
unique_name_in_owner = true
script = ExtResource("4_to7a4")
target = NodePath("..")
shake_intensity = 60.0
duration = 0.5
frequency = 30.0
metadata/_custom_type_script = "uid://dunsvrhq42214"

[node name="HookableArea" type="Area2D" parent="." unique_id=1417858664 node_paths=PackedStringArray("controlled_entity", "anchor_point")]
unique_name_in_owner = true
collision_layer = 4096
collision_mask = 0
script = ExtResource("4_ml4a5")
controlled_entity = NodePath("..")
anchor_point = NodePath("Marker2D")
weight = 0.0
metadata/_custom_type_script = "uid://dabvr3pqmyya4"

[node name="CollisionShape2D" type="CollisionShape2D" parent="HookableArea" unique_id=68720889]
position = Vector2(0, -32)
shape = SubResource("RectangleShape2D_ml4a5")
debug_color = Color(0.689707, 0.288376, 1, 0.42)

[node name="Marker2D" type="Marker2D" parent="HookableArea" unique_id=1758696959]
position = Vector2(0, -16)
2 changes: 1 addition & 1 deletion scenes/globals/mouse_manager/mouse_manager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func _ready() -> void:
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
hide_timer.start(3)
hide_timer.start()


func _on_hide_timer_timeout() -> void:
Expand Down
Loading