-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: adds turn based nodes
- Loading branch information
Showing
14 changed files
with
512 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
addons/godot_gameplay_systems/turn_based/autoloads/turn_manager.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
extends Node | ||
|
||
|
||
## The [TurnBasedGame] node. | ||
var turn_based_game: TurnBasedGame = null | ||
|
||
|
||
## Called when the node enters the scene tree for the first time. | ||
func _ready() -> void: | ||
get_turn_based_game() | ||
|
||
|
||
## Ends the current turn sequence. | ||
func end_turn_sequence() -> void: | ||
if get_turn_based_game(): | ||
get_turn_based_game().end_turn_sequence() | ||
|
||
|
||
## Gets the [TurnBasedGame] node. | ||
func get_turn_based_game() -> TurnBasedGame: | ||
if turn_based_game: | ||
return turn_based_game | ||
|
||
for child in get_tree().get_nodes_in_group("ggs.turnbased"): | ||
if child is TurnBasedGame: | ||
turn_based_game = child | ||
return turn_based_game | ||
|
||
return null | ||
|
||
|
||
## Starts a new turn sequence (aka, starts the turn based mode). | ||
func start_turn_sequence() -> void: | ||
if get_turn_based_game(): | ||
get_turn_based_game().start_turn_sequence() | ||
|
124 changes: 124 additions & 0 deletions
124
addons/godot_gameplay_systems/turn_based/nodes/TurnBasedGame.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
class_name TurnBasedGame extends Node | ||
|
||
|
||
## Emitted when a turn changes. | ||
signal turn_changed(manager: TurnBasedGame) | ||
## Emitted when the turn based game starts. | ||
signal turn_game_started() | ||
## Emitted when the turn based game stops. | ||
signal turn_game_stopped() | ||
## Emitted when a subscriber is added. | ||
signal subscriber_added(subscriber: TurnSubscriber) | ||
## Emitted when a subscriber is removed. | ||
signal subscriber_removed(subscriber: TurnSubscriber) | ||
|
||
|
||
## The current turn. | ||
var current_turn: int = 0 | ||
## The current turn subscriber. | ||
var current_turn_subscriber: TurnSubscriber: | ||
get: | ||
if subscribers.size() == 0: | ||
return null | ||
|
||
return subscribers[current_turn] | ||
## The turn subscribers. | ||
var subscribers: Array[TurnSubscriber] = [] | ||
|
||
|
||
func _ready() -> void: | ||
add_to_group("ggs.turnbased") | ||
|
||
|
||
func _sort_subscribers() -> void: | ||
subscribers.sort_custom(func (a, b): | ||
return a.priority < b.priority | ||
) | ||
|
||
|
||
## Called when a [TurnSubscriber] is subscribed. | ||
## [br]This is a virtual method | ||
func _subscriber_added(sub: TurnSubscriber) -> void: | ||
pass | ||
|
||
|
||
## Called when a [TurnSubscriber] is unsubscribed. | ||
## [br]This is a virtual method | ||
func _subscriber_removed(sub: TurnSubscriber) -> void: | ||
pass | ||
|
||
|
||
## Adds a [TurnSubscriber] | ||
func add_subscriber(sub: TurnSubscriber) -> bool: | ||
if subscribers.has(sub): | ||
return false | ||
|
||
subscribers.append(sub) | ||
subscriber_added.emit(sub) | ||
|
||
_sort_subscribers() | ||
|
||
return true | ||
|
||
|
||
## Ends the current turn | ||
func end_turn_sequence() -> void: | ||
if subscribers.size() == 0: | ||
return | ||
|
||
subscribers[current_turn].end_turn() | ||
|
||
current_turn += 1 | ||
|
||
if current_turn >= subscribers.size(): | ||
current_turn = 0 | ||
|
||
subscribers[current_turn].turn_started.emit() | ||
subscribers[current_turn]._turn_started() | ||
|
||
turn_game_stopped.emit() | ||
|
||
|
||
## Calls next turn | ||
func next_turn() -> void: | ||
var subscribers_count := subscribers.size() | ||
|
||
if current_turn < subscribers_count: | ||
subscribers[current_turn].turn_ended.emit() | ||
subscribers[current_turn]._turn_ended() | ||
|
||
current_turn += 1 | ||
|
||
if current_turn >= subscribers_count: | ||
current_turn = 0 | ||
|
||
subscribers[current_turn].turn_started.emit() | ||
subscribers[current_turn]._turn_started() | ||
|
||
|
||
## Removes a [TurnSubscriber] | ||
func remove_subscriber(sub: TurnSubscriber) -> bool: | ||
if not subscribers.has(sub): | ||
return false | ||
|
||
var sub_turn_index = subscribers.find(func (x): return x == sub) | ||
|
||
subscribers.remove_at(sub_turn_index) | ||
subscriber_removed.emit(sub) | ||
|
||
_sort_subscribers() | ||
|
||
return true | ||
|
||
|
||
## Starts the turn based game. | ||
func start_turn_sequence() -> void: | ||
if subscribers.size() == 0: | ||
return | ||
|
||
current_turn = 0 | ||
|
||
subscribers[current_turn]._turn_started() | ||
subscribers[current_turn].turn_started.emit() | ||
|
||
turn_game_started.emit() |
54 changes: 54 additions & 0 deletions
54
addons/godot_gameplay_systems/turn_based/nodes/TurnSubscriber.gd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
class_name TurnSubscriber extends Node | ||
|
||
## A turn based participant | ||
## | ||
## It represents a scene which can partecipate to a turn based game | ||
|
||
|
||
## Emitted when this subscriber turn ends | ||
signal turn_ended() | ||
## Emitted when this subscriber turn starts | ||
signal turn_started() | ||
## Emitter when the turn round ended, | ||
signal turn_round_ended() | ||
|
||
|
||
@export_group("Turn based game") | ||
## Priority of this subscriber. The higher the priority, the sooner the turn starts. | ||
@export var priority: int = 0 | ||
|
||
|
||
func _enter_tree() -> void: | ||
if TurnManager.get_turn_based_game() != null: | ||
TurnManager.get_turn_based_game().add_subscriber(self) | ||
|
||
|
||
func _exit_tree() -> void: | ||
if TurnManager.get_turn_based_game() != null: | ||
TurnManager.get_turn_based_game().remove_subscriber(self) | ||
|
||
|
||
func _ready() -> void: | ||
add_to_group("ggs.turnbased") | ||
|
||
if TurnManager.get_turn_based_game() != null: | ||
TurnManager.get_turn_based_game().add_subscriber(self) | ||
|
||
|
||
## Called when the turn round ended | ||
## [br]It's a virtual method, it can be overrided | ||
func _turn_ended() -> void: | ||
pass | ||
|
||
|
||
## Called when the turn round started | ||
## [br]It's a virtual method, it can be overrided | ||
func _turn_started() -> void: | ||
pass | ||
|
||
|
||
## Ends the turn of this subscriber | ||
func end_turn() -> void: | ||
if TurnManager.get_turn_based_game() != null: | ||
TurnManager.get_turn_based_game().next_turn() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
extends EditorPlugin | ||
|
||
|
||
const TurnBasedGameScript = preload("res://addons/godot_gameplay_systems/turn_based/nodes/TurnBasedGame.gd") | ||
const TurnSubscriberScript = preload("res://addons/godot_gameplay_systems/turn_based/nodes/TurnSubscriber.gd") | ||
|
||
|
||
func _enter_tree() -> void: | ||
add_autoload_singleton("TurnManager", "res://addons/godot_gameplay_systems/turn_based/autoloads/turn_manager.gd") | ||
add_custom_type("TurnBasedGame", "Node", TurnBasedGameScript, null) | ||
add_custom_type("TurnSubscriber", "Node", TurnSubscriberScript, null) | ||
|
||
|
||
func _exit_tree() -> void: | ||
remove_autoload_singleton("TurnManager") | ||
remove_custom_type("TurnBasedGame") | ||
remove_custom_type("TurnSubscriber") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
Turn based nodes | ||
================ | ||
|
||
Turn based nodes are nodes that can be used to create turn based games. | ||
|
||
To start adding functionalities to your game, you can add a `TurnBasedGame` node to your scene. This node should be at the highest level of your hierarchy. It will be used to manage the turns properly. | ||
|
||
Then you should add a `TurnSubscriber` to each node which should be notified when a turn starts or ends. | ||
|
||
This node has a priority property. The nodes with the highest priority will start their turns first. If two nodes have the same priority, the one that was added first will start its turn first. | ||
|
||
To get the `TurnBasedGame` node, you have to use the singleton `TurnManager`. | ||
|
||
This has a method which returns the `TurnBasedGame` node. You can use it like this: | ||
|
||
```gdscript | ||
# To start a turn sequence | ||
var turn_based_game = TurnManager.get_turn_based_game() | ||
turn_based_game.start_turn_sequence(); | ||
# To end a turn sequence | ||
turn_based_game.end_turn_sequence(); | ||
``` | ||
|
||
Each `TurnSubscriber` can terminate it's own turn by calling their `end_turn` method. | ||
|
||
```gdscript | ||
# To end a turn | ||
self.end_turn(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
extends CharacterBody3D | ||
|
||
|
||
@export var turn_priority: int = 0 | ||
@onready var point_and_click_3d: PointAndClick3D = $PointAndClick3D | ||
@onready var turn_subscriber: TurnSubscriber = $TurnSubscriber | ||
@onready var current_turn_indicator: MeshInstance3D = $CurrentTurnIndicator | ||
|
||
|
||
func _ready() -> void: | ||
turn_subscriber.priority = turn_priority | ||
current_turn_indicator.visible = false | ||
|
||
set_process_input(false) | ||
|
||
turn_subscriber.turn_started.connect(func (): | ||
set_process_input(true) | ||
current_turn_indicator.visible = true | ||
) | ||
|
||
turn_subscriber.turn_ended.connect(func (): | ||
set_process_input(false) | ||
current_turn_indicator.visible = false | ||
) | ||
|
||
|
||
func _input(event: InputEvent) -> void: | ||
if event.is_action_pressed("diablo_like_move_to"): | ||
point_and_click_3d.set_new_movement_position() | ||
|
Oops, something went wrong.