Refactor rhythm action architecture

This commit is contained in:
wxm
2026-07-02 09:47:52 -07:00
parent fc941cf08d
commit e62ed84518
124 changed files with 7516 additions and 2440 deletions

33
resources/action_data.gd Normal file
View File

@@ -0,0 +1,33 @@
class_name ActionData
extends Resource
@export var id: StringName
@export var display_name: String
@export var input_pattern: Array[StringName] = []
@export var required_state: StringName = &"any"
@export var base_cost := 0.0
@export var damage_mult := 1.0
@export var move_mult_x := 0.0
@export var move_mult_y := 0.0
@export var action_beats := 1.0
@export var hit_type: StringName = &"melee"
@export var range := 0.0
@export var target_type: StringName = &"single"
@export var armor_level := 0
@export var clear_window := true
@export var can_chain := false
@export var special: StringName = &""
@export var startup_beats := 0.25
@export var active_beats := 0.25
@export var recovery_beats := 0.5
@export_range(0.0, 1.0, 0.05) var cancel_from := 0.5
@export var animation: StringName
@export var energy_cost := 0.0
@export var energy_reward := 0.0
@export var spawns_projectile := false
@export var projectile_scene: PackedScene
@export var damage := 10
@export var cancel_window := Vector2(0.3, 0.6)
@export var has_super_armor := false
@export var displacement: StringName = &""

View File

@@ -0,0 +1 @@
uid://cooudhoob8dn4

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_a"
display_name = "A"
input_pattern = Array[StringName]([&"A"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a"
energy_reward = 1.0
displacement = &"left"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_a_space"
display_name = "A+SP"
input_pattern = Array[StringName]([&"A", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space"
displacement = &"left"
clear_window = true

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_aa"
display_name = "A+A"
input_pattern = Array[StringName]([&"A", &"A"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_aa"
energy_reward = 1.0
displacement = &"left"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_aa_space"
display_name = "A+A+SP"
input_pattern = Array[StringName]([&"A", &"A", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space_space"
displacement = &"left"
clear_window = true

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_aaa"
display_name = "A+A+A"
input_pattern = Array[StringName]([&"A", &"A", &"A"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_aaa"
energy_reward = 1.0
displacement = &"left"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_ad_space"
display_name = "A+D+SP"
input_pattern = Array[StringName]([&"A", &"D", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space_space"
displacement = &"right"
clear_window = true

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_d"
display_name = "D"
input_pattern = Array[StringName]([&"D"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a"
energy_reward = 1.0
displacement = &"right"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_d_space"
display_name = "D+SP"
input_pattern = Array[StringName]([&"D", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space"
displacement = &"right"
clear_window = true

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_d_space_space"
display_name = "D+SP+SP"
input_pattern = Array[StringName]([&"D", &"SP", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space_space"
displacement = &"right"
clear_window = true

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_da_space"
display_name = "D+A+SP"
input_pattern = Array[StringName]([&"D", &"A", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space_space"
displacement = &"left"
clear_window = true

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_dd"
display_name = "D+D"
input_pattern = Array[StringName]([&"D", &"D"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_aa"
energy_reward = 1.0
displacement = &"right"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_dd_space"
display_name = "D+D+SP"
input_pattern = Array[StringName]([&"D", &"D", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_a_space_space"
displacement = &"right"
clear_window = true

View File

@@ -0,0 +1,17 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_ddd"
display_name = "D+D+D"
input_pattern = Array[StringName]([&"D", &"D", &"D"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_aaa"
energy_reward = 1.0
displacement = &"right"
clear_window = false

View File

@@ -0,0 +1,15 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_s"
display_name = "S"
input_pattern = Array[StringName]([&"S"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s"
clear_window = false

View File

@@ -0,0 +1,20 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[ext_resource type="PackedScene" path="res://scenes/combat/player_projectile.tscn" id="2"]
[resource]
script = ExtResource("1")
id = &"skill_s_projectile_1"
display_name = "S+SP"
input_pattern = Array[StringName]([&"S", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s_projectile"
energy_cost = 3.0
spawns_projectile = true
projectile_scene = ExtResource("2")
clear_window = false
can_chain = true

View File

@@ -0,0 +1,20 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[ext_resource type="PackedScene" path="res://scenes/combat/player_projectile.tscn" id="2"]
[resource]
script = ExtResource("1")
id = &"skill_s_projectile_2"
display_name = "S+SP+SP"
input_pattern = Array[StringName]([&"S", &"SP", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s_projectile"
energy_cost = 2.0
spawns_projectile = true
projectile_scene = ExtResource("2")
clear_window = false
can_chain = true

View File

@@ -0,0 +1,20 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[ext_resource type="PackedScene" path="res://scenes/combat/player_projectile.tscn" id="2"]
[resource]
script = ExtResource("1")
id = &"skill_s_projectile_3"
display_name = "S+SP+SP+SP"
input_pattern = Array[StringName]([&"S", &"SP", &"SP", &"SP"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s_projectile"
energy_cost = 1.0
spawns_projectile = true
projectile_scene = ExtResource("2")
clear_window = false
can_chain = true

View File

@@ -0,0 +1,15 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_s"
display_name = "S"
input_pattern = Array[StringName]([&"S", &"S"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s"
clear_window = false

View File

@@ -0,0 +1,15 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_s"
display_name = "S"
input_pattern = Array[StringName]([&"S", &"S", &"S"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s"
clear_window = false

View File

@@ -0,0 +1,15 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_s"
display_name = "S"
input_pattern = Array[StringName]([&"S", &"S", &"S", &"S"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_s"
clear_window = false

View File

@@ -0,0 +1,15 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_w"
display_name = "W"
input_pattern = Array[StringName]([&"W"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_w"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_wa"
display_name = "W+A"
input_pattern = Array[StringName]([&"W", &"A"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_wa"
displacement = &"left"
clear_window = false

View File

@@ -0,0 +1,16 @@
[gd_resource type="Resource" script_class="ActionData" load_steps=2 format=3]
[ext_resource type="Script" path="res://resources/action_data.gd" id="1"]
[resource]
script = ExtResource("1")
id = &"skill_wd"
display_name = "W+D"
input_pattern = Array[StringName]([&"W", &"D"])
startup_beats = 0.25
active_beats = 0.25
recovery_beats = 0.5
cancel_from = 0.5
animation = &"warrior_wa"
displacement = &"right"
clear_window = false

27
resources/beat_chart.gd Normal file
View File

@@ -0,0 +1,27 @@
class_name BeatChart
extends Resource
@export var chart_id: StringName = &""
@export var total_beats := 0
@export var tracks: Array = []
func all_events() -> Array:
var result: Array = []
for track in tracks:
if not track is Resource:
continue
for event in track.call("sorted_events"):
result.append(event)
result.sort_custom(func(a: Resource, b: Resource) -> bool:
var a_position := float(a.call("beat_position"))
var b_position := float(b.call("beat_position"))
if is_equal_approx(a_position, b_position):
return str(a.get("event_type")) < str(b.get("event_type"))
return a_position < b_position
)
return result
func is_empty() -> bool:
return all_events().is_empty()

View File

@@ -0,0 +1 @@
uid://b0jn7bu4w1co7

26
resources/chart_event.gd Normal file
View File

@@ -0,0 +1,26 @@
class_name ChartEvent
extends Resource
@export var event_id: StringName = &""
@export var beat_index := 0
@export var subdivision := 0
@export var subdivisions_per_beat := 1
@export var event_type: StringName = &""
@export var target_id: StringName = &""
@export var payload: Dictionary = {}
@export var lead_beats := 1.0
func beat_position() -> float:
var safe_subdivisions := maxi(1, subdivisions_per_beat)
return float(beat_index) + float(subdivision) / float(safe_subdivisions)
func time_seconds(beat_time: float) -> float:
return beat_position() * maxf(0.001, beat_time)
func key() -> StringName:
if not event_id.is_empty():
return event_id
return StringName("%s:%s:%d:%d" % [event_type, target_id, beat_index, subdivision])

View File

@@ -0,0 +1 @@
uid://bsbmwl7n6uil5

17
resources/chart_track.gd Normal file
View File

@@ -0,0 +1,17 @@
class_name ChartTrack
extends Resource
@export var track_id: StringName = &""
@export var track_type: StringName = &""
@export var events: Array = []
func sorted_events() -> Array:
var result: Array = []
for event in events:
if event is Resource:
result.append(event)
result.sort_custom(func(a: Resource, b: Resource) -> bool:
return float(a.call("beat_position")) < float(b.call("beat_position"))
)
return result

View File

@@ -0,0 +1 @@
uid://t7etuk7uw3ns