init
4
max-effort/.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
2
max-effort/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Normalize EOL for all files that Git considers text files.
|
||||||
|
* text=auto eol=lf
|
||||||
3
max-effort/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Godot 4+ specific ignores
|
||||||
|
.godot/
|
||||||
|
/android/
|
||||||
14
max-effort/MaxEffort.gdextension
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[configuration]
|
||||||
|
entry_symbol = "gdext_rust_init"
|
||||||
|
compatibility_minimum = 4.5
|
||||||
|
reloadable = true
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
linux.debug.x86_64 = "res://../rust/target/debug/libmax_effort_lib.so"
|
||||||
|
linux.release.x86_64 = "res://../rust/target/release/libmax_effort_lib.so"
|
||||||
|
windows.debug.x86_64 = "res://../rust/target/debug/max-effort-lib.dll"
|
||||||
|
windows.release.x86_64 = "res://../rust/target/release/max-effort-lib.dll"
|
||||||
|
macos.debug = "res://../rust/target/debug/libmax_effort_lib.dylib"
|
||||||
|
macos.release = "res://../rust/target/release/libmax_effort_lib.dylib"
|
||||||
|
macos.debug.arm64 = "res://../rust/target/debug/libmax_effort_lib.dylib"
|
||||||
|
macos.release.arm64 = "res://../rust/target/release/libmax_effort_lib.dylib"
|
||||||
1
max-effort/MaxEffort.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://ddxl1hldnuqrv
|
||||||
30
max-effort/Objects/bench_press.tscn
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://dxq2510ywj1hy"]
|
||||||
|
|
||||||
|
[ext_resource type="GameState" uid="uid://2gma8vvisnqo" path="res://Resources/GameState.tres" id="1_tik8c"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dn8y3bgovnh4a" path="res://Objects/bench_press_stickman.tscn" id="2_0c1tm"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dsovna2tmb4o3" path="res://Sprites/bench.png" id="2_ky8t4"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cbgn8aspf7oi0" path="res://Sprites/barbell.png" id="3_ky8t4"]
|
||||||
|
|
||||||
|
[node name="BenchPress" type="Node"]
|
||||||
|
|
||||||
|
[node name="System" type="BenchPressSystem" parent="."]
|
||||||
|
game_state = ExtResource("1_tik8c")
|
||||||
|
|
||||||
|
[node name="Bench" type="Sprite2D" parent="."]
|
||||||
|
position = Vector2(11, 1)
|
||||||
|
scale = Vector2(2.086, 2.086)
|
||||||
|
texture = ExtResource("2_ky8t4")
|
||||||
|
|
||||||
|
[node name="BenchPressStickman" parent="." instance=ExtResource("2_0c1tm")]
|
||||||
|
|
||||||
|
[node name="Barbell" type="Sprite2D" parent="."]
|
||||||
|
position = Vector2(22, -5)
|
||||||
|
scale = Vector2(2.432, 2.432)
|
||||||
|
texture = ExtResource("3_ky8t4")
|
||||||
|
|
||||||
|
[node name="LiftSyncController" type="LiftSyncController" parent="." node_paths=PackedStringArray("player_anim", "barbell")]
|
||||||
|
player_anim = NodePath("../BenchPressStickman")
|
||||||
|
barbell = NodePath("../Barbell")
|
||||||
|
game_state = ExtResource("1_tik8c")
|
||||||
|
animation_name = "default"
|
||||||
|
bar_positions = Array[Vector2]([Vector2(19, -5), Vector2(19, -19), Vector2(21, -36), Vector2(21, -15), Vector2(23, 3), Vector2(22, 11), Vector2(22, -1), Vector2(22, -1)])
|
||||||
46
max-effort/Objects/bench_press_stickman.tscn
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
[gd_scene load_steps=10 format=3 uid="uid://dn8y3bgovnh4a"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dci4cuavfc4la" path="res://Sprites/bench_press0.png" id="1_8snp0"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dya801bkqxdpa" path="res://Sprites/bench_press1.png" id="2_ckjrk"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bbxviq4c0pyju" path="res://Sprites/bench_press2.png" id="3_s2d21"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://biu7q8mfw62be" path="res://Sprites/bench_press3.png" id="4_e1c5r"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bg06qtcl207do" path="res://Sprites/bench_press4.png" id="5_pwixy"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bkypgv8rfcd8k" path="res://Sprites/bench_press5.png" id="6_6piga"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://warnmdoebwht" path="res://Sprites/bench_press6.png" id="7_ex7t0"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://yrorih7pbt0q" path="res://Sprites/bench_press7.png" id="8_as8xi"]
|
||||||
|
|
||||||
|
[sub_resource type="SpriteFrames" id="SpriteFrames_edqll"]
|
||||||
|
animations = [{
|
||||||
|
"frames": [{
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("1_8snp0")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("2_ckjrk")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("3_s2d21")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("4_e1c5r")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("5_pwixy")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("6_6piga")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("7_ex7t0")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("8_as8xi")
|
||||||
|
}],
|
||||||
|
"loop": true,
|
||||||
|
"name": &"default",
|
||||||
|
"speed": 12.0
|
||||||
|
}]
|
||||||
|
|
||||||
|
[node name="BenchPressStickman" type="AnimatedSprite2D"]
|
||||||
|
sprite_frames = SubResource("SpriteFrames_edqll")
|
||||||
|
speed_scale = 0.0
|
||||||
16
max-effort/Objects/deadlift.tscn
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://dx1k40qfioaas"]
|
||||||
|
|
||||||
|
[ext_resource type="GameState" uid="uid://2gma8vvisnqo" path="res://Resources/GameState.tres" id="1_n6ace"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://cbgn8aspf7oi0" path="res://Sprites/barbell.png" id="2_ltxro"]
|
||||||
|
|
||||||
|
[node name="Deadlift" type="Node"]
|
||||||
|
|
||||||
|
[node name="System" type="DeadliftSystem" parent="." node_paths=PackedStringArray("bar_visual")]
|
||||||
|
bar_height = 7.0
|
||||||
|
bar_visual = NodePath("../Barbell")
|
||||||
|
end_pos = Vector2(0, -30)
|
||||||
|
game_state = ExtResource("1_n6ace")
|
||||||
|
|
||||||
|
[node name="Barbell" type="Sprite2D" parent="."]
|
||||||
|
scale = Vector2(2, 2)
|
||||||
|
texture = ExtResource("2_ltxro")
|
||||||
15
max-effort/Objects/hazard_animated.tscn
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bqxc62tofqger"]
|
||||||
|
|
||||||
|
[ext_resource type="GameState" uid="uid://2gma8vvisnqo" path="res://Resources/GameState.tres" id="1_strkh"]
|
||||||
|
|
||||||
|
[node name="HazardAnimated" type="HazardController" node_paths=PackedStringArray("anim_sprite", "click_area", "click_shape")]
|
||||||
|
anim_sprite = NodePath("AnimatedSprite2D")
|
||||||
|
click_area = NodePath("Area2D")
|
||||||
|
click_shape = NodePath("Area2D/CollisionShape2D")
|
||||||
|
game_state = ExtResource("1_strkh")
|
||||||
|
|
||||||
|
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Area2D" type="Area2D" parent="."]
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||||
9
max-effort/Resources/Day_Day1.tres
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[gd_resource type="DayConfig" load_steps=3 format=3 uid="uid://d30pwvrr7m72j"]
|
||||||
|
|
||||||
|
[ext_resource type="HazardDef" uid="uid://pgmnp6ev1ark" path="res://Resources/Hazard_GymBro.tres" id="1_qov1i"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dxq2510ywj1hy" path="res://Objects/bench_press.tscn" id="2_ilyy2"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
target_weight = 25.0
|
||||||
|
mini_game_scene = ExtResource("2_ilyy2")
|
||||||
|
available_hazards = Array[HazardDef]([ExtResource("1_qov1i")])
|
||||||
11
max-effort/Resources/Day_Day2.tres
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[gd_resource type="DayConfig" load_steps=3 format=3 uid="uid://b0j1f8h6tioaf"]
|
||||||
|
|
||||||
|
[ext_resource type="HazardDef" uid="uid://pgmnp6ev1ark" path="res://Resources/Hazard_GymBro.tres" id="1_x1txs"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://dx1k40qfioaas" path="res://Objects/deadlift.tscn" id="2_x1txs"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
day_number = 1
|
||||||
|
day_title = "Day 2"
|
||||||
|
target_weight = 7.0
|
||||||
|
mini_game_scene = ExtResource("2_x1txs")
|
||||||
|
available_hazards = Array[HazardDef]([ExtResource("1_x1txs")])
|
||||||
3
max-effort/Resources/GameState.tres
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gd_resource type="GameState" format=3 uid="uid://2gma8vvisnqo"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
72
max-effort/Resources/Hazard_GymBro.tres
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
[gd_resource type="HazardDef" load_steps=14 format=3 uid="uid://pgmnp6ev1ark"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c43wo6u2c0d43" path="res://Sprites/chad_walk0.png" id="1_v1id6"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dt5i4j2gvqso" path="res://Sprites/chad_walk1.png" id="2_xcd3t"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://by265t6kx8us4" path="res://Sprites/chad_walk2.png" id="3_57x2g"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dway2w8pbk5lp" path="res://Sprites/chad_walk3.png" id="4_s8hf6"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://bunfddn1pa8pj" path="res://Sprites/chad_walk4.png" id="5_tdncn"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://664m2cxtmmur" path="res://Sprites/chad_wave0.png" id="6_twq7w"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://tu8ph6cjdwhv" path="res://Sprites/chad_wave1.png" id="7_jshom"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://b28aaketyf0t1" path="res://Sprites/chad_wave2.png" id="8_hejui"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://jyr4f2p7jbk8" path="res://Sprites/chad_wave3.png" id="9_envil"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://f013utfdsqqe" path="res://Sprites/chad_wave4.png" id="10_tcjtc"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://duryxgc54alp5" path="res://Sprites/chad_wave5.png" id="11_i0i8i"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://yy2yrm4gq6w4" path="res://Sprites/chad_wave6.png" id="12_seh7d"]
|
||||||
|
|
||||||
|
[sub_resource type="SpriteFrames" id="SpriteFrames_44y3n"]
|
||||||
|
animations = [{
|
||||||
|
"frames": [{
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("1_v1id6")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("2_xcd3t")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("3_57x2g")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("4_s8hf6")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("5_tdncn")
|
||||||
|
}],
|
||||||
|
"loop": true,
|
||||||
|
"name": &"walking",
|
||||||
|
"speed": 12.0
|
||||||
|
}, {
|
||||||
|
"frames": [{
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("6_twq7w")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("7_jshom")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("8_hejui")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("9_envil")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("10_tcjtc")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("11_i0i8i")
|
||||||
|
}, {
|
||||||
|
"duration": 1.0,
|
||||||
|
"texture": ExtResource("12_seh7d")
|
||||||
|
}],
|
||||||
|
"loop": true,
|
||||||
|
"name": &"waving",
|
||||||
|
"speed": 12.0
|
||||||
|
}]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
hazard_type = "GymBro"
|
||||||
|
display_name = "Chad"
|
||||||
|
animations = SubResource("SpriteFrames_44y3n")
|
||||||
|
idle_anim_name = "waving"
|
||||||
|
walk_anim_name = "walking"
|
||||||
|
time_to_fail = 3.0
|
||||||
|
min_focus_to_spawn = 0.3
|
||||||
3
max-effort/Resources/SoundBank.tres
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[gd_resource type="SoundBank" format=3 uid="uid://b8ouri8tqw8vp"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
15
max-effort/Scenes/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/.idea.Scenes.iml
|
||||||
|
/modules.xml
|
||||||
|
/contentModel.xml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
6
max-effort/Scenes/.idea/copilot.data.migration.ask2agent.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Ask2AgentMigrationStateService">
|
||||||
|
<option name="migrationStatus" value="COMPLETED" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
max-effort/Scenes/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
max-effort/Scenes/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
max-effort/Scenes/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
147
max-effort/Scenes/main.tscn
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
[gd_scene load_steps=11 format=3 uid="uid://xtm08af0e82g"]
|
||||||
|
|
||||||
|
[ext_resource type="GameState" uid="uid://2gma8vvisnqo" path="res://Resources/GameState.tres" id="1_bo1nx"]
|
||||||
|
[ext_resource type="Shader" uid="uid://dndm4jfifooyk" path="res://Shaders/TunnelVision.gdshader" id="1_jjgbg"]
|
||||||
|
[ext_resource type="DayConfig" uid="uid://d30pwvrr7m72j" path="res://Resources/Day_Day1.tres" id="2_8gbba"]
|
||||||
|
[ext_resource type="SoundBank" uid="uid://b8ouri8tqw8vp" path="res://Resources/SoundBank.tres" id="2_21xkr"]
|
||||||
|
[ext_resource type="HazardDef" uid="uid://pgmnp6ev1ark" path="res://Resources/Hazard_GymBro.tres" id="3_kry3j"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bg4uaukekjbx" path="res://Scenes/main_menu.tscn" id="4_6bp64"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bqxc62tofqger" path="res://Objects/hazard_animated.tscn" id="4_21xkr"]
|
||||||
|
|
||||||
|
[sub_resource type="Curve" id="Curve_bo1nx"]
|
||||||
|
_data = [Vector2(0, 0), 0.0, 1.4, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
|
||||||
|
point_count = 2
|
||||||
|
|
||||||
|
[sub_resource type="TunnelConfig" id="TunnelConfig_8gbba"]
|
||||||
|
max_tunnel_intensity = 0.7
|
||||||
|
vision_curve = SubResource("Curve_bo1nx")
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id="ShaderMaterial_bo1nx"]
|
||||||
|
shader = ExtResource("1_jjgbg")
|
||||||
|
shader_parameter/vignette_intensity = 0.0
|
||||||
|
shader_parameter/vignette_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="Main" type="Node"]
|
||||||
|
|
||||||
|
[node name="Systems" type="Node" parent="."]
|
||||||
|
|
||||||
|
[node name="PlayerInputSystem" type="PlayerInputSystem" parent="Systems"]
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
|
||||||
|
[node name="TunnelSystem" type="TunnelSystem" parent="Systems" node_paths=PackedStringArray("vignette_overlay")]
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
config = SubResource("TunnelConfig_8gbba")
|
||||||
|
vignette_overlay = NodePath("../../Ui/Vignette")
|
||||||
|
|
||||||
|
[node name="SoundManager" type="SoundManager" parent="Systems"]
|
||||||
|
bank = ExtResource("2_21xkr")
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
|
||||||
|
[node name="GameManager" type="GameManager" parent="Systems" node_paths=PackedStringArray("hazard_system", "minigame_container", "win_screen", "lose_screen")]
|
||||||
|
days = Array[DayConfig]([ExtResource("2_8gbba")])
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
hazard_system = NodePath("../HazardSystem")
|
||||||
|
minigame_container = NodePath("../../GameContainer")
|
||||||
|
win_screen = NodePath("../../Ui/Win")
|
||||||
|
lose_screen = NodePath("../../Ui/Lose")
|
||||||
|
main_menu_scene = ExtResource("4_6bp64")
|
||||||
|
|
||||||
|
[node name="CameraShakeSystem" type="CameraShakeSystem" parent="Systems" node_paths=PackedStringArray("camera")]
|
||||||
|
camera = NodePath("../../Camera2D")
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
min_focus_for_shake = 0.7
|
||||||
|
|
||||||
|
[node name="HazardSystem" type="HazardSystem" parent="Systems" node_paths=PackedStringArray("spawn_locations")]
|
||||||
|
possible_hazards = Array[HazardDef]([ExtResource("3_kry3j")])
|
||||||
|
spawn_locations = [NodePath("../../HazardSpots/Right"), NodePath("../../HazardSpots/Left")]
|
||||||
|
hazard_prefab = ExtResource("4_21xkr")
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
|
||||||
|
[node name="GameContainer" type="Node" parent="."]
|
||||||
|
|
||||||
|
[node name="HazardSpots" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="Right" type="Marker2D" parent="HazardSpots"]
|
||||||
|
position = Vector2(502, 0)
|
||||||
|
|
||||||
|
[node name="Left" type="Marker2D" parent="HazardSpots"]
|
||||||
|
position = Vector2(-500, 0)
|
||||||
|
|
||||||
|
[node name="Ui" type="CanvasLayer" parent="."]
|
||||||
|
|
||||||
|
[node name="Vignette" type="ColorRect" parent="Ui"]
|
||||||
|
material = SubResource("ShaderMaterial_bo1nx")
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="LiftProgressBar" type="LiftProgressBar" parent="Ui"]
|
||||||
|
game_state = ExtResource("1_bo1nx")
|
||||||
|
anchors_preset = 12
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_top = -27.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 0
|
||||||
|
|
||||||
|
[node name="Win" type="ColorRect" parent="Ui"]
|
||||||
|
visible = false
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
color = Color(0, 1, 0, 1)
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="Ui/Win"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -20.0
|
||||||
|
offset_top = -11.5
|
||||||
|
offset_right = 20.0
|
||||||
|
offset_bottom = 11.5
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_font_sizes/font_size = 72
|
||||||
|
text = "Light Weight"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
uppercase = true
|
||||||
|
|
||||||
|
[node name="Lose" type="ColorRect" parent="Ui"]
|
||||||
|
visible = false
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
color = Color(1, 0, 0, 1)
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="Ui/Lose"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -20.0
|
||||||
|
offset_top = -11.5
|
||||||
|
offset_right = 20.0
|
||||||
|
offset_bottom = 11.5
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_font_sizes/font_size = 72
|
||||||
|
text = "Failure"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
uppercase = true
|
||||||
|
|
||||||
|
[node name="Camera2D" type="Camera2D" parent="."]
|
||||||
62
max-effort/Scenes/main_menu.tscn
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bg4uaukekjbx"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://xtm08af0e82g" path="res://Scenes/main.tscn" id="1_28flt"]
|
||||||
|
|
||||||
|
[node name="MainMenu" type="MainMenu" node_paths=PackedStringArray("mute_button")]
|
||||||
|
game_scene = ExtResource("1_28flt")
|
||||||
|
mute_button = NodePath("VBoxContainer/MuteButton")
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="ColorRect" type="ColorRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
color = Color(0.14117648, 0.14117648, 0.14117648, 1)
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 10
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_bottom = 67.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
theme_override_font_sizes/font_size = 48
|
||||||
|
text = "max effort"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
vertical_alignment = 1
|
||||||
|
uppercase = true
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -20.0
|
||||||
|
offset_top = -20.0
|
||||||
|
offset_right = 20.0
|
||||||
|
offset_bottom = 20.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="PlayButton" type="Button" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Play"
|
||||||
|
|
||||||
|
[node name="QuitButton" type="Button" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Quit"
|
||||||
|
|
||||||
|
[node name="MuteButton" type="CheckButton" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Mute"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="VBoxContainer/PlayButton" to="." method="on_play_pressed"]
|
||||||
|
[connection signal="pressed" from="VBoxContainer/QuitButton" to="." method="on_quit_pressed"]
|
||||||
20
max-effort/Shaders/TunnelVision.gdshader
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform float vignette_intensity : hint_range(0.0, 1.0) = 0.0;
|
||||||
|
uniform vec4 vignette_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec2 center = vec2(0.5, 0.5);
|
||||||
|
|
||||||
|
float dist = distance(UV, center);
|
||||||
|
|
||||||
|
float radius = 0.8 - (vignette_intensity * 0.7);
|
||||||
|
|
||||||
|
float softness = 0.2;
|
||||||
|
|
||||||
|
float vignette = smoothstep(radius, radius - softness, dist);
|
||||||
|
|
||||||
|
float alpha = 1.0 - vignette;
|
||||||
|
|
||||||
|
COLOR = vec4(vignette_color.rgb, alpha * vignette_intensity * 1.5);
|
||||||
|
}
|
||||||
1
max-effort/Shaders/TunnelVision.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dndm4jfifooyk
|
||||||
BIN
max-effort/Sprites/barbell.png
Normal file
|
After Width: | Height: | Size: 935 B |
40
max-effort/Sprites/barbell.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cbgn8aspf7oi0"
|
||||||
|
path="res://.godot/imported/barbell.png-18c805fdd277089a294c3e4ab4576f9d.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/barbell.png"
|
||||||
|
dest_files=["res://.godot/imported/barbell.png-18c805fdd277089a294c3e4ab4576f9d.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
|
||||||
BIN
max-effort/Sprites/bench.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/bench.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dsovna2tmb4o3"
|
||||||
|
path="res://.godot/imported/bench.png-7eaea02148a24455b27861ad276687ec.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench.png"
|
||||||
|
dest_files=["res://.godot/imported/bench.png-7eaea02148a24455b27861ad276687ec.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
|
||||||
BIN
max-effort/Sprites/bench_press0.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
40
max-effort/Sprites/bench_press0.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dci4cuavfc4la"
|
||||||
|
path="res://.godot/imported/bench_press0.png-ba9ac58cf50cb63dff601e4a9d25d02e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press0.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press0.png-ba9ac58cf50cb63dff601e4a9d25d02e.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
|
||||||
BIN
max-effort/Sprites/bench_press1.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
40
max-effort/Sprites/bench_press1.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dya801bkqxdpa"
|
||||||
|
path="res://.godot/imported/bench_press1.png-5e3c7fb368ba97d9829feb84755273cb.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press1.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press1.png-5e3c7fb368ba97d9829feb84755273cb.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
|
||||||
BIN
max-effort/Sprites/bench_press2.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/bench_press2.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bbxviq4c0pyju"
|
||||||
|
path="res://.godot/imported/bench_press2.png-26912d86e95ea594a6ede3ddf7d888d5.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press2.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press2.png-26912d86e95ea594a6ede3ddf7d888d5.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
|
||||||
BIN
max-effort/Sprites/bench_press3.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/bench_press3.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://biu7q8mfw62be"
|
||||||
|
path="res://.godot/imported/bench_press3.png-151702054f4fa5ae7f646f944338650b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press3.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press3.png-151702054f4fa5ae7f646f944338650b.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
|
||||||
BIN
max-effort/Sprites/bench_press4.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
40
max-effort/Sprites/bench_press4.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bg06qtcl207do"
|
||||||
|
path="res://.godot/imported/bench_press4.png-6bdb5e12c718169046447626c4f714d2.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press4.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press4.png-6bdb5e12c718169046447626c4f714d2.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
|
||||||
BIN
max-effort/Sprites/bench_press5.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
40
max-effort/Sprites/bench_press5.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bkypgv8rfcd8k"
|
||||||
|
path="res://.godot/imported/bench_press5.png-14c7049e4522e703552beeb21c54b5d3.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press5.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press5.png-14c7049e4522e703552beeb21c54b5d3.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
|
||||||
BIN
max-effort/Sprites/bench_press6.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
40
max-effort/Sprites/bench_press6.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://warnmdoebwht"
|
||||||
|
path="res://.godot/imported/bench_press6.png-fbb03a505d8811ac5e307f534e60a936.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press6.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press6.png-fbb03a505d8811ac5e307f534e60a936.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
|
||||||
BIN
max-effort/Sprites/bench_press7.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
40
max-effort/Sprites/bench_press7.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://yrorih7pbt0q"
|
||||||
|
path="res://.godot/imported/bench_press7.png-f40d47f75275caf6823ff7e34d3d17bb.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/bench_press7.png"
|
||||||
|
dest_files=["res://.godot/imported/bench_press7.png-f40d47f75275caf6823ff7e34d3d17bb.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
|
||||||
BIN
max-effort/Sprites/chad_walk0.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
40
max-effort/Sprites/chad_walk0.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c43wo6u2c0d43"
|
||||||
|
path="res://.godot/imported/chad_walk0.png-8e4fc165652b5af437c3106b59f93650.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_walk0.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_walk0.png-8e4fc165652b5af437c3106b59f93650.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
|
||||||
BIN
max-effort/Sprites/chad_walk1.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_walk1.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dt5i4j2gvqso"
|
||||||
|
path="res://.godot/imported/chad_walk1.png-33816be91d7ff97b4b5f437f937fae6e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_walk1.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_walk1.png-33816be91d7ff97b4b5f437f937fae6e.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
|
||||||
BIN
max-effort/Sprites/chad_walk2.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
40
max-effort/Sprites/chad_walk2.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://by265t6kx8us4"
|
||||||
|
path="res://.godot/imported/chad_walk2.png-6275d1149cbf6b3a53f8cc57ae4023c9.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_walk2.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_walk2.png-6275d1149cbf6b3a53f8cc57ae4023c9.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
|
||||||
BIN
max-effort/Sprites/chad_walk3.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_walk3.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dway2w8pbk5lp"
|
||||||
|
path="res://.godot/imported/chad_walk3.png-83f190047fc9396d428eeeadc1ee67bb.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_walk3.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_walk3.png-83f190047fc9396d428eeeadc1ee67bb.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
|
||||||
BIN
max-effort/Sprites/chad_walk4.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
40
max-effort/Sprites/chad_walk4.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bunfddn1pa8pj"
|
||||||
|
path="res://.godot/imported/chad_walk4.png-e04181ba7df8daa1c7400ecfa9120b36.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_walk4.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_walk4.png-e04181ba7df8daa1c7400ecfa9120b36.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
|
||||||
BIN
max-effort/Sprites/chad_wave0.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
40
max-effort/Sprites/chad_wave0.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://664m2cxtmmur"
|
||||||
|
path="res://.godot/imported/chad_wave0.png-7452b570847815d288a291f1ec8574e6.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave0.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave0.png-7452b570847815d288a291f1ec8574e6.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
|
||||||
BIN
max-effort/Sprites/chad_wave1.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_wave1.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://tu8ph6cjdwhv"
|
||||||
|
path="res://.godot/imported/chad_wave1.png-f0592da2a6c2b61ba47c87e39b1a9a35.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave1.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave1.png-f0592da2a6c2b61ba47c87e39b1a9a35.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
|
||||||
BIN
max-effort/Sprites/chad_wave2.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
40
max-effort/Sprites/chad_wave2.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b28aaketyf0t1"
|
||||||
|
path="res://.godot/imported/chad_wave2.png-2c28d86e420f732e4cc32daf20b49920.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave2.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave2.png-2c28d86e420f732e4cc32daf20b49920.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
|
||||||
BIN
max-effort/Sprites/chad_wave3.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_wave3.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://jyr4f2p7jbk8"
|
||||||
|
path="res://.godot/imported/chad_wave3.png-c5f30d3e0f297bd9fc2597ab6e730b5a.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave3.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave3.png-c5f30d3e0f297bd9fc2597ab6e730b5a.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
|
||||||
BIN
max-effort/Sprites/chad_wave4.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_wave4.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://f013utfdsqqe"
|
||||||
|
path="res://.godot/imported/chad_wave4.png-d9dcca2f7e8dd0d27166f8047669505f.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave4.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave4.png-d9dcca2f7e8dd0d27166f8047669505f.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
|
||||||
BIN
max-effort/Sprites/chad_wave5.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
40
max-effort/Sprites/chad_wave5.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://duryxgc54alp5"
|
||||||
|
path="res://.godot/imported/chad_wave5.png-aa21a1c7a76438f4a886d5f1b68bbcc5.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave5.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave5.png-aa21a1c7a76438f4a886d5f1b68bbcc5.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
|
||||||
BIN
max-effort/Sprites/chad_wave6.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
40
max-effort/Sprites/chad_wave6.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://yy2yrm4gq6w4"
|
||||||
|
path="res://.godot/imported/chad_wave6.png-3d42c992783b312c1ab7802034e07a03.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/chad_wave6.png"
|
||||||
|
dest_files=["res://.godot/imported/chad_wave6.png-3d42c992783b312c1ab7802034e07a03.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
|
||||||
BIN
max-effort/Sprites/stick-bench-bend.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
40
max-effort/Sprites/stick-bench-bend.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://mc8luxtg4rio"
|
||||||
|
path="res://.godot/imported/stick-bench-bend.png-7c99c74f55cf267d5d337b54b20aa912.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/stick-bench-bend.png"
|
||||||
|
dest_files=["res://.godot/imported/stick-bench-bend.png-7c99c74f55cf267d5d337b54b20aa912.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
|
||||||
BIN
max-effort/Sprites/stick-bench-straight.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
40
max-effort/Sprites/stick-bench-straight.png.import
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cqkxhms26hdx2"
|
||||||
|
path="res://.godot/imported/stick-bench-straight.png-d6eb50859d8b64f084f45e07fee5f895.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Sprites/stick-bench-straight.png"
|
||||||
|
dest_files=["res://.godot/imported/stick-bench-straight.png-d6eb50859d8b64f084f45e07fee5f895.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
|
||||||
1
max-effort/icon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 995 B |
43
max-effort/icon.svg.import
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://d1exufucxsjrq"
|
||||||
|
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://icon.svg"
|
||||||
|
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
||||||
30
max-effort/project.godot
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
; Engine configuration file.
|
||||||
|
; It's best edited using the editor UI and not directly,
|
||||||
|
; since the parameters that go here are not all obvious.
|
||||||
|
;
|
||||||
|
; Format:
|
||||||
|
; [section] ; section goes between []
|
||||||
|
; param=value ; assign values to parameters
|
||||||
|
|
||||||
|
config_version=5
|
||||||
|
|
||||||
|
[application]
|
||||||
|
|
||||||
|
config/name="max-effort"
|
||||||
|
run/main_scene="uid://bg4uaukekjbx"
|
||||||
|
config/features=PackedStringArray("4.5", "GL Compatibility")
|
||||||
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[input]
|
||||||
|
|
||||||
|
lift_action={
|
||||||
|
"deadzone": 0.2,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||||
|
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
[rendering]
|
||||||
|
|
||||||
|
renderer/rendering_method="gl_compatibility"
|
||||||
|
renderer/rendering_method.mobile="gl_compatibility"
|
||||||
1
rust/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
203
rust/Cargo.lock
generated
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdextension-api"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc8107360153162c579a6d44503710720b55f6686fec83aa14750a3e60a55274"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glam"
|
||||||
|
version = "0.30.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5599d03afd17a511e11d0bf9e06c88d4095a9120f10cf00a74f50b300f53413e"
|
||||||
|
dependencies = [
|
||||||
|
"godot-core",
|
||||||
|
"godot-macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-bindings"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f38b6e65306c05e3c3f0131ee8dbf7394691e53268d72019007ec20687f2280f"
|
||||||
|
dependencies = [
|
||||||
|
"gdextension-api",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-cell"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "738efef92fdcf1d92f0ed5a29c6f3cdce58e64029d08928c20e08771e1239c16"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-codegen"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b9a59f603f354c54d83fb74071209203d0ebe396b2419acc731c90ebf94680"
|
||||||
|
dependencies = [
|
||||||
|
"godot-bindings",
|
||||||
|
"heck",
|
||||||
|
"nanoserde",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-core"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "989e80dfb58d2048ae0dca60bec32129dc1f96510f904b992ad170d84e950c33"
|
||||||
|
dependencies = [
|
||||||
|
"glam",
|
||||||
|
"godot-bindings",
|
||||||
|
"godot-cell",
|
||||||
|
"godot-codegen",
|
||||||
|
"godot-ffi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-ffi"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6237b26c52c5baa6566705a73cd8804ea4ef83a666540939dd5a4e068c242666"
|
||||||
|
dependencies = [
|
||||||
|
"godot-bindings",
|
||||||
|
"godot-codegen",
|
||||||
|
"godot-macros",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "godot-macros"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d696b67ba99ff7d75e07546b04c3a711651d2c9e5851c9225dea3b64f8bb5af6"
|
||||||
|
dependencies = [
|
||||||
|
"godot-bindings",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"venial",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.180"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "max-effort-lib"
|
||||||
|
version = "1.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"godot",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanoserde"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a36fb3a748a4c9736ed7aeb5f2dfc99665247f1ce306abbddb2bf0ba2ac530a4"
|
||||||
|
dependencies = [
|
||||||
|
"nanoserde-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanoserde-derive"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a846cbc04412cf509efcd8f3694b114fc700a035fb5a37f21517f9fb019f1ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "venial"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a42528baceab6c7784446df2a10f4185078c39bf73dc614f154353f1a6b1229"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
10
rust/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "max-effort-lib"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
godot = "0.4.5"
|
||||||
161
rust/src/core/game_state.rs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
use godot::prelude::*;
|
||||||
|
use std::sync::RwLock;
|
||||||
|
|
||||||
|
use crate::data::hazard_def::HazardType;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum GameEvent {
|
||||||
|
HazardSpawned,
|
||||||
|
HazardResolved,
|
||||||
|
TraumaApplied(f32),
|
||||||
|
LiftCompleted(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct InnerState {
|
||||||
|
pub current_focus: f32, // 0.0 to 1.0
|
||||||
|
pub lift_effort: f32, // 0.0 to 1.0
|
||||||
|
pub is_lifting: bool,
|
||||||
|
pub active_hazards: Vec<HazardType>,
|
||||||
|
pub lift_progress: f32, // 0.0 to 1.0
|
||||||
|
pub visual_height: f32,
|
||||||
|
pub is_lift_complete: bool,
|
||||||
|
pub is_lift_failed: bool,
|
||||||
|
pub camera_trauma: f32,
|
||||||
|
pub event_queue: Vec<GameEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Resource)]
|
||||||
|
pub struct GameState {
|
||||||
|
pub inner: RwLock<InnerState>,
|
||||||
|
|
||||||
|
base: Base<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IResource for GameState {
|
||||||
|
fn init(base: Base<Resource>) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: RwLock::new(InnerState::default()),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl GameState {
|
||||||
|
// --- WRITERS (Updated to push events) ---
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn apply_effort(&self, delta: f32) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.is_lifting = true;
|
||||||
|
guard.lift_effort += delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn release_focus(&self) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.is_lifting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn set_focus_intensity(&self, intensity: f32) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.current_focus = intensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn set_lift_state(&self, progress: f32, visual_height: f32) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.lift_progress = progress;
|
||||||
|
guard.visual_height = visual_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn set_complete(&self, complete: bool) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
if complete {
|
||||||
|
guard.is_lift_complete = true;
|
||||||
|
} else {
|
||||||
|
guard.is_lift_failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
guard.event_queue.push(GameEvent::LiftCompleted(complete));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn add_trauma(&self, amount: f32) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.camera_trauma = (guard.camera_trauma + amount).clamp(0.0, 1.0);
|
||||||
|
guard.event_queue.push(GameEvent::TraumaApplied(amount));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn add_active_hazard(&self, type_: HazardType) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
guard.active_hazards.push(type_);
|
||||||
|
guard.event_queue.push(GameEvent::HazardSpawned);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn remove_active_hazard(&self, type_: HazardType) {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
if let Some(index) = guard.active_hazards.iter().position(|t| *t == type_) {
|
||||||
|
guard.active_hazards.remove(index);
|
||||||
|
guard.event_queue.push(GameEvent::HazardResolved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- READERS ---
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn consume_effort(&self) -> f32 {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
let effort = guard.lift_effort;
|
||||||
|
guard.lift_effort = 0.0;
|
||||||
|
effort
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn get_active_hazard_count(&self) -> i32 {
|
||||||
|
self.inner.read().unwrap().active_hazards.len() as i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn get_focus(&self) -> f32 {
|
||||||
|
self.inner.read().unwrap().current_focus
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn consume_trauma(&self, decay: f32) -> f32 {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
let t = guard.camera_trauma;
|
||||||
|
guard.camera_trauma = (t - decay).max(0.0);
|
||||||
|
t
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_events(&self) -> Vec<GameEvent> {
|
||||||
|
let mut guard = self.inner.write().unwrap();
|
||||||
|
let events = guard.event_queue.clone();
|
||||||
|
guard.event_queue.clear();
|
||||||
|
events
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_lift_progress(&self) -> f32 {
|
||||||
|
self.inner.read().unwrap().lift_progress
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_is_lifting(&self) -> bool {
|
||||||
|
self.inner.read().unwrap().is_lifting
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_is_lift_complete(&self) -> bool {
|
||||||
|
self.inner.read().unwrap().is_lift_complete
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_is_lift_failed(&self) -> bool {
|
||||||
|
self.inner.read().unwrap().is_lift_failed
|
||||||
|
}
|
||||||
|
}
|
||||||
1
rust/src/core/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod game_state;
|
||||||
37
rust/src/data/day_config.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use godot::prelude::*;
|
||||||
|
|
||||||
|
use crate::data::hazard_def::HazardDef;
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Resource)]
|
||||||
|
pub struct DayConfig {
|
||||||
|
#[export]
|
||||||
|
pub day_number: i32,
|
||||||
|
#[export]
|
||||||
|
pub day_title: GString,
|
||||||
|
#[export]
|
||||||
|
pub target_weight: f32,
|
||||||
|
#[export]
|
||||||
|
pub gravity: f32,
|
||||||
|
#[export]
|
||||||
|
pub mini_game_scene: Option<Gd<PackedScene>>,
|
||||||
|
#[export]
|
||||||
|
pub available_hazards: Array<Gd<HazardDef>>,
|
||||||
|
|
||||||
|
base: Base<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IResource for DayConfig {
|
||||||
|
fn init(base: Base<Resource>) -> Self {
|
||||||
|
Self {
|
||||||
|
day_number: 0,
|
||||||
|
day_title: "Day 1".into(),
|
||||||
|
target_weight: 100.0,
|
||||||
|
gravity: 2.0,
|
||||||
|
mini_game_scene: None,
|
||||||
|
available_hazards: Array::new(),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
rust/src/data/hazard_def.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use godot::{classes::SpriteFrames, prelude::*};
|
||||||
|
|
||||||
|
#[derive(GodotConvert, Export, Var, Default, Clone, PartialEq, Eq, Debug)]
|
||||||
|
#[godot(via=GString)]
|
||||||
|
pub enum HazardType {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
GymBro,
|
||||||
|
LoosePlate,
|
||||||
|
PhoneDistraction,
|
||||||
|
Manager,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Resource)]
|
||||||
|
pub struct HazardDef {
|
||||||
|
#[export]
|
||||||
|
pub hazard_type: HazardType,
|
||||||
|
#[export]
|
||||||
|
pub display_name: GString,
|
||||||
|
#[export]
|
||||||
|
pub animations: Option<Gd<SpriteFrames>>,
|
||||||
|
#[export]
|
||||||
|
pub idle_anim_name: GString,
|
||||||
|
#[export]
|
||||||
|
pub walk_anim_name: GString,
|
||||||
|
#[export]
|
||||||
|
pub time_to_fail: f32,
|
||||||
|
#[export]
|
||||||
|
pub spawn_weight: f32,
|
||||||
|
#[export]
|
||||||
|
pub min_focus_to_spawn: f32,
|
||||||
|
#[export]
|
||||||
|
pub clicks_to_resolve: i32,
|
||||||
|
|
||||||
|
base: Base<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IResource for HazardDef {
|
||||||
|
fn init(base: Base<Resource>) -> Self {
|
||||||
|
Self {
|
||||||
|
hazard_type: HazardType::None,
|
||||||
|
display_name: "Unnamed Hazard".into(),
|
||||||
|
animations: None,
|
||||||
|
idle_anim_name: "idle".into(),
|
||||||
|
walk_anim_name: "walk".into(),
|
||||||
|
time_to_fail: 5.0,
|
||||||
|
spawn_weight: 1.0,
|
||||||
|
min_focus_to_spawn: 0.0,
|
||||||
|
clicks_to_resolve: 1,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
rust/src/data/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pub mod day_config;
|
||||||
|
pub mod hazard_def;
|
||||||
|
pub mod sound_bank;
|
||||||
|
pub mod tunnel_config;
|
||||||
48
rust/src/data/sound_bank.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use godot::{classes::AudioStream, prelude::*};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Resource)]
|
||||||
|
pub struct SoundBank {
|
||||||
|
#[export]
|
||||||
|
pub strain_loop: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub effort_exhale: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub win_stinger: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub fail_stinger: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub heartbeat_loop: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub hazard_spawn: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub hazard_resolve: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub camera_trauma: Option<Gd<AudioStream>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
pub menu_music: Option<Gd<AudioStream>>,
|
||||||
|
#[export]
|
||||||
|
pub game_music: Option<Gd<AudioStream>>,
|
||||||
|
|
||||||
|
base: Base<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IResource for SoundBank {
|
||||||
|
fn init(base: Base<Resource>) -> Self {
|
||||||
|
Self {
|
||||||
|
strain_loop: None,
|
||||||
|
effort_exhale: None,
|
||||||
|
win_stinger: None,
|
||||||
|
fail_stinger: None,
|
||||||
|
heartbeat_loop: None,
|
||||||
|
hazard_spawn: None,
|
||||||
|
hazard_resolve: None,
|
||||||
|
camera_trauma: None,
|
||||||
|
menu_music: None,
|
||||||
|
game_music: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
rust/src/data/tunnel_config.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use godot::{classes::Curve, prelude::*};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Resource)]
|
||||||
|
pub struct TunnelConfig {
|
||||||
|
#[export]
|
||||||
|
pub vision_narrow_rate: f32,
|
||||||
|
#[export]
|
||||||
|
pub vision_recover_rate: f32,
|
||||||
|
#[export]
|
||||||
|
pub max_tunnel_intensity: f32,
|
||||||
|
#[export]
|
||||||
|
pub vision_curve: Option<Gd<Curve>>,
|
||||||
|
|
||||||
|
base: Base<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IResource for TunnelConfig {
|
||||||
|
fn init(base: Base<Resource>) -> Self {
|
||||||
|
Self {
|
||||||
|
vision_narrow_rate: 0.5,
|
||||||
|
vision_recover_rate: 2.0,
|
||||||
|
max_tunnel_intensity: 0.95,
|
||||||
|
vision_curve: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
rust/src/lib.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
use godot::prelude::*;
|
||||||
|
|
||||||
|
mod core;
|
||||||
|
mod data;
|
||||||
|
mod systems;
|
||||||
|
mod ui;
|
||||||
|
mod visuals;
|
||||||
|
|
||||||
|
struct MaxEffort;
|
||||||
|
|
||||||
|
#[gdextension]
|
||||||
|
unsafe impl ExtensionLibrary for MaxEffort {}
|
||||||
70
rust/src/systems/bench_press_system.rs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
use crate::core::game_state::GameState;
|
||||||
|
use godot::prelude::*;
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct BenchPressSystem {
|
||||||
|
#[export]
|
||||||
|
power_per_click: f32,
|
||||||
|
#[export]
|
||||||
|
gravity: f32,
|
||||||
|
#[export]
|
||||||
|
target_value: f32,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
current_progress: f32,
|
||||||
|
is_lift_complete: bool,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for BenchPressSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
power_per_click: 5.0,
|
||||||
|
gravity: 2.0,
|
||||||
|
target_value: 100.0,
|
||||||
|
game_state: None,
|
||||||
|
current_progress: 0.0,
|
||||||
|
is_lift_complete: false,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
if self.is_lift_complete {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let dt = delta as f32;
|
||||||
|
|
||||||
|
let state_bind = state.bind();
|
||||||
|
let effort = state_bind.consume_effort();
|
||||||
|
let hazard_count = state_bind.get_active_hazard_count();
|
||||||
|
drop(state_bind);
|
||||||
|
|
||||||
|
if self.current_progress > 0.0 {
|
||||||
|
self.current_progress -= self.gravity * dt;
|
||||||
|
self.current_progress = self.current_progress.max(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if hazard_count == 0 {
|
||||||
|
self.current_progress += self.power_per_click * effort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.current_progress >= self.target_value {
|
||||||
|
self.is_lift_complete = true;
|
||||||
|
state.bind().set_complete(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ratio = self.current_progress / self.target_value;
|
||||||
|
|
||||||
|
state.bind().set_lift_state(ratio, ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
86
rust/src/systems/camera_shake_system.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
use crate::core::game_state::GameState;
|
||||||
|
use godot::{
|
||||||
|
classes::{Camera2D, RandomNumberGenerator},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct CameraShakeSystem {
|
||||||
|
#[export]
|
||||||
|
camera: Option<Gd<Camera2D>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
decay_rate: f32,
|
||||||
|
#[export]
|
||||||
|
max_offset: f32,
|
||||||
|
#[export]
|
||||||
|
max_roll: f32,
|
||||||
|
#[export]
|
||||||
|
min_focus_for_shake: f32,
|
||||||
|
|
||||||
|
trauma: f32,
|
||||||
|
rng: Gd<RandomNumberGenerator>,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for CameraShakeSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
camera: None,
|
||||||
|
game_state: None,
|
||||||
|
decay_rate: 0.8,
|
||||||
|
max_offset: 20.0,
|
||||||
|
max_roll: 0.1,
|
||||||
|
trauma: 0.0,
|
||||||
|
min_focus_for_shake: 0.1,
|
||||||
|
rng: RandomNumberGenerator::new_gd(),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
let Some(camera) = &mut self.camera else {
|
||||||
|
godot_error!("CameraShakeSystem: No camera assigned");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
godot_error!("CameraShakeSystem: No game state assigned");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let dt = delta as f32;
|
||||||
|
|
||||||
|
let focus = state.bind().get_focus();
|
||||||
|
|
||||||
|
if focus > self.min_focus_for_shake {
|
||||||
|
state.bind().add_trauma(1.5 * dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_trauma = state.bind().consume_trauma(self.decay_rate * dt);
|
||||||
|
self.trauma = new_trauma;
|
||||||
|
|
||||||
|
if self.trauma > 0.0 {
|
||||||
|
let shake = self.trauma * self.trauma;
|
||||||
|
|
||||||
|
let offset_x = self.max_offset * shake * self.rng.randf_range(-1.0, 1.0);
|
||||||
|
let offset_y = self.max_offset * shake * self.rng.randf_range(-1.0, 1.0);
|
||||||
|
let rotation = self.max_roll * shake * self.rng.randf_range(-1.0, 1.0);
|
||||||
|
|
||||||
|
camera.set_offset(Vector2::new(offset_x, offset_y));
|
||||||
|
camera.set_rotation(rotation);
|
||||||
|
} else {
|
||||||
|
if camera.get_offset() != Vector2::ZERO {
|
||||||
|
let curr_off = camera.get_offset();
|
||||||
|
let curr_rot = camera.get_rotation();
|
||||||
|
camera.set_offset(curr_off.lerp(Vector2::ZERO, dt * 5.0));
|
||||||
|
camera.set_rotation(curr_rot.lerp(0.0, dt * 5.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
rust/src/systems/deadlift_system.rs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
use crate::core::game_state::GameState;
|
||||||
|
use godot::prelude::*;
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct DeadliftSystem {
|
||||||
|
#[export]
|
||||||
|
power_per_click: f32,
|
||||||
|
#[export]
|
||||||
|
gravity: f32,
|
||||||
|
#[export]
|
||||||
|
target_value: f32,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
bar_height: f32,
|
||||||
|
#[export]
|
||||||
|
hold_zone_threshold: f32,
|
||||||
|
#[export]
|
||||||
|
bar_visual: Option<Gd<Node2D>>,
|
||||||
|
#[export]
|
||||||
|
start_pos: Vector2,
|
||||||
|
#[export]
|
||||||
|
end_pos: Vector2,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
current_bar_height: f32,
|
||||||
|
hold_timer: f32,
|
||||||
|
is_lift_complete: bool,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for DeadliftSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
power_per_click: 5.0,
|
||||||
|
gravity: 2.0,
|
||||||
|
target_value: 5.0,
|
||||||
|
|
||||||
|
bar_height: 100.0,
|
||||||
|
hold_zone_threshold: 0.8,
|
||||||
|
bar_visual: None,
|
||||||
|
start_pos: Vector2::ZERO,
|
||||||
|
end_pos: Vector2::ZERO,
|
||||||
|
|
||||||
|
game_state: None,
|
||||||
|
|
||||||
|
current_bar_height: 0.0,
|
||||||
|
hold_timer: 0.0,
|
||||||
|
is_lift_complete: false,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
if self.is_lift_complete {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let dt = delta as f32;
|
||||||
|
|
||||||
|
let state_bind = state.bind();
|
||||||
|
let effort = state_bind.consume_effort();
|
||||||
|
let hazard_count = state_bind.get_active_hazard_count();
|
||||||
|
drop(state_bind);
|
||||||
|
|
||||||
|
if self.current_bar_height > 0.0 {
|
||||||
|
self.current_bar_height -= self.gravity * dt;
|
||||||
|
self.current_bar_height = self.current_bar_height.max(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if hazard_count == 0 {
|
||||||
|
self.current_bar_height += self.power_per_click * effort;
|
||||||
|
self.current_bar_height = self.current_bar_height.min(self.bar_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
let visual_ratio = self.current_bar_height / self.bar_height;
|
||||||
|
|
||||||
|
if visual_ratio >= self.hold_zone_threshold && hazard_count == 0 {
|
||||||
|
self.hold_timer += dt;
|
||||||
|
|
||||||
|
state.bind().add_trauma(0.15 * dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(visual) = &mut self.bar_visual {
|
||||||
|
let new_pos = self.start_pos.lerp(self.end_pos, visual_ratio);
|
||||||
|
visual.set_position(new_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
let progress = self.hold_timer / self.target_value;
|
||||||
|
state.bind().set_lift_state(progress, visual_ratio);
|
||||||
|
|
||||||
|
if self.hold_timer >= self.target_value {
|
||||||
|
self.is_lift_complete = true;
|
||||||
|
state.bind().add_trauma(1.0);
|
||||||
|
state.bind().set_complete(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
207
rust/src/systems/game_manager.rs
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
use crate::{
|
||||||
|
core::game_state::GameState, data::day_config::DayConfig, systems::hazard_system::HazardSystem,
|
||||||
|
};
|
||||||
|
use godot::{
|
||||||
|
classes::{Control, Label},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct GameManager {
|
||||||
|
#[export]
|
||||||
|
days: Array<Gd<DayConfig>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
hazard_system: Option<Gd<HazardSystem>>,
|
||||||
|
#[export]
|
||||||
|
minigame_container: Option<Gd<Node>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
win_screen: Option<Gd<Control>>,
|
||||||
|
#[export]
|
||||||
|
lose_screen: Option<Gd<Control>>,
|
||||||
|
#[export]
|
||||||
|
game_complete_screen: Option<Gd<Control>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
day_label: Option<Gd<Label>>,
|
||||||
|
#[export]
|
||||||
|
main_menu_scene: Option<Gd<PackedScene>>,
|
||||||
|
|
||||||
|
current_day_index: i32,
|
||||||
|
current_mini_game: Option<Gd<Node>>,
|
||||||
|
|
||||||
|
level_ended: bool,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for GameManager {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
days: Array::new(),
|
||||||
|
game_state: None,
|
||||||
|
hazard_system: None,
|
||||||
|
minigame_container: None,
|
||||||
|
win_screen: None,
|
||||||
|
lose_screen: None,
|
||||||
|
game_complete_screen: None,
|
||||||
|
day_label: None,
|
||||||
|
main_menu_scene: None,
|
||||||
|
current_day_index: 0,
|
||||||
|
current_mini_game: None,
|
||||||
|
level_ended: false,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready(&mut self) {
|
||||||
|
let idx = self.current_day_index;
|
||||||
|
self.base_mut()
|
||||||
|
.call_deferred("start_day", &[idx.to_variant()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, _delta: f64) {
|
||||||
|
if self.level_ended {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (won, lost) = if let Some(state) = &self.game_state {
|
||||||
|
let bind = state.bind();
|
||||||
|
(bind.get_is_lift_complete(), bind.get_is_lift_failed())
|
||||||
|
} else {
|
||||||
|
(false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
if won {
|
||||||
|
self.handle_win();
|
||||||
|
self.level_ended = true;
|
||||||
|
} else if lost {
|
||||||
|
self.handle_loss();
|
||||||
|
self.level_ended = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl GameManager {
|
||||||
|
#[func]
|
||||||
|
fn start_day(&mut self, index: i32) {
|
||||||
|
self.level_ended = false;
|
||||||
|
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
let bind = state.bind();
|
||||||
|
|
||||||
|
if let Ok(mut inner) = bind.inner.write() {
|
||||||
|
inner.is_lift_complete = false;
|
||||||
|
inner.is_lift_failed = false;
|
||||||
|
|
||||||
|
inner.lift_progress = 0.0;
|
||||||
|
inner.visual_height = 0.0;
|
||||||
|
inner.lift_effort = 0.0;
|
||||||
|
inner.active_hazards.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if index >= self.days.len() as i32 {
|
||||||
|
self.cleanup_level();
|
||||||
|
if let Some(s) = &mut self.game_complete_screen {
|
||||||
|
s.set_visible(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cleanup_level();
|
||||||
|
|
||||||
|
let config = self.days.get(index as usize).expect("Invalid Day Index");
|
||||||
|
let config_bind = config.bind();
|
||||||
|
|
||||||
|
if let Some(prefab) = &config_bind.mini_game_scene {
|
||||||
|
if let Some(instance) = prefab.instantiate() {
|
||||||
|
if let Some(container) = &mut self.minigame_container {
|
||||||
|
container.add_child(&instance.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut system) = instance.get_node_or_null("System") {
|
||||||
|
system.set("target_value", &config_bind.target_weight.to_variant());
|
||||||
|
system.set("gravity", &config_bind.gravity.to_variant());
|
||||||
|
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
system.set("game_state", &state.to_variant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.current_mini_game = Some(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(hs) = &mut self.hazard_system {
|
||||||
|
hs.bind_mut()
|
||||||
|
.set_available_hazards(config_bind.available_hazards.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(l) = &mut self.day_label {
|
||||||
|
l.set_text(&config_bind.day_title);
|
||||||
|
}
|
||||||
|
if let Some(s) = &mut self.win_screen {
|
||||||
|
s.set_visible(false);
|
||||||
|
}
|
||||||
|
if let Some(s) = &mut self.lose_screen {
|
||||||
|
s.set_visible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cleanup_level(&mut self) {
|
||||||
|
if let Some(game) = &mut self.current_mini_game {
|
||||||
|
game.queue_free();
|
||||||
|
self.current_mini_game = None;
|
||||||
|
}
|
||||||
|
if let Some(hs) = &mut self.hazard_system {
|
||||||
|
hs.bind_mut().clear_hazards();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_win(&mut self) {
|
||||||
|
if let Some(s) = &mut self.win_screen {
|
||||||
|
s.set_visible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_loss(&mut self) {
|
||||||
|
if let Some(s) = &mut self.lose_screen {
|
||||||
|
s.set_visible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn on_next_day_pressed(&mut self) {
|
||||||
|
self.current_day_index += 1;
|
||||||
|
let idx = self.current_day_index;
|
||||||
|
self.base_mut()
|
||||||
|
.call_deferred("start_day", &[idx.to_variant()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn on_retry_pressed(&mut self) {
|
||||||
|
let idx = self.current_day_index;
|
||||||
|
self.base_mut()
|
||||||
|
.call_deferred("start_day", &[idx.to_variant()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn on_menu_pressed(&mut self) {
|
||||||
|
if let Some(menu) = &self.main_menu_scene {
|
||||||
|
let menu_ref = menu.clone();
|
||||||
|
self.base()
|
||||||
|
.get_tree()
|
||||||
|
.unwrap()
|
||||||
|
.change_scene_to_packed(&menu_ref);
|
||||||
|
} else {
|
||||||
|
self.base().get_tree().unwrap().quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
209
rust/src/systems/hazard_controller.rs
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
use godot::{
|
||||||
|
classes::{
|
||||||
|
AnimatedSprite2D, Area2D, CollisionShape2D, InputEvent, InputEventMouseButton, Label,
|
||||||
|
RectangleShape2D,
|
||||||
|
},
|
||||||
|
global::MouseButton,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{core::game_state::GameState, data::hazard_def::HazardDef};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node2D)]
|
||||||
|
pub struct HazardController {
|
||||||
|
#[export]
|
||||||
|
anim_sprite: Option<Gd<AnimatedSprite2D>>,
|
||||||
|
#[export]
|
||||||
|
click_area: Option<Gd<Area2D>>,
|
||||||
|
#[export]
|
||||||
|
click_shape: Option<Gd<CollisionShape2D>>,
|
||||||
|
#[export]
|
||||||
|
name_label: Option<Gd<Label>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
data: Option<Gd<HazardDef>>,
|
||||||
|
time_active: f32,
|
||||||
|
is_resolved: bool,
|
||||||
|
current_health: i32,
|
||||||
|
|
||||||
|
base: Base<Node2D>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode2D for HazardController {
|
||||||
|
fn init(base: Base<Node2D>) -> Self {
|
||||||
|
Self {
|
||||||
|
anim_sprite: None,
|
||||||
|
click_area: None,
|
||||||
|
click_shape: None,
|
||||||
|
name_label: None,
|
||||||
|
game_state: None,
|
||||||
|
data: None,
|
||||||
|
time_active: 0.0,
|
||||||
|
is_resolved: false,
|
||||||
|
current_health: 1,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready(&mut self) {
|
||||||
|
if let Some(mut area) = self.click_area.clone() {
|
||||||
|
let callable = self.base_mut().callable("on_input_event");
|
||||||
|
area.connect("input_event", &callable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
if self.is_resolved {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(data) = &self.data.clone() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let data_bind = data.bind();
|
||||||
|
|
||||||
|
self.time_active += delta as f32;
|
||||||
|
|
||||||
|
if self.time_active >= data_bind.time_to_fail {
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
state.bind().set_complete(false);
|
||||||
|
}
|
||||||
|
self.base_mut().queue_free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl HazardController {
|
||||||
|
#[func]
|
||||||
|
pub fn initialize(&mut self, data: Gd<HazardDef>) {
|
||||||
|
let data_bind = data.bind();
|
||||||
|
self.current_health = data_bind.clicks_to_resolve;
|
||||||
|
|
||||||
|
if let Some(sprite) = &mut self.anim_sprite {
|
||||||
|
if let Some(frames) = &data_bind.animations {
|
||||||
|
sprite.set_sprite_frames(frames);
|
||||||
|
|
||||||
|
let anim_name = StringName::from(&data_bind.idle_anim_name);
|
||||||
|
|
||||||
|
if let Some(texture) = frames.get_frame_texture(&anim_name, 0) {
|
||||||
|
if let Some(shape) = &mut self.click_shape {
|
||||||
|
let mut rect = RectangleShape2D::new_gd();
|
||||||
|
rect.set_size(texture.get_size());
|
||||||
|
shape.set_shape(&rect.upcast::<RectangleShape2D>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.play_ex().name(&anim_name).done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(label) = &mut self.name_label {
|
||||||
|
label.set_text(&data_bind.display_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.base_mut().set_scale(Vector2::ZERO);
|
||||||
|
|
||||||
|
let node = self.base().clone();
|
||||||
|
|
||||||
|
if let Some(mut tween) = self.base_mut().create_tween() {
|
||||||
|
tween
|
||||||
|
.set_trans(godot::classes::tween::TransitionType::BACK)
|
||||||
|
.unwrap()
|
||||||
|
.set_ease(godot::classes::tween::EaseType::OUT);
|
||||||
|
|
||||||
|
tween.tween_property(
|
||||||
|
&node.upcast::<Object>(),
|
||||||
|
"scale",
|
||||||
|
&Vector2::ONE.to_variant(),
|
||||||
|
0.4,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(data_bind);
|
||||||
|
self.data = Some(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn on_input_event(&mut self, _viewport: Gd<Node>, event: Gd<InputEvent>, _shape_idx: i64) {
|
||||||
|
if self.is_resolved {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(mouse_event) = event.try_cast::<InputEventMouseButton>() {
|
||||||
|
if mouse_event.is_pressed() && mouse_event.get_button_index() == MouseButton::LEFT {
|
||||||
|
self.take_damage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_damage(&mut self) {
|
||||||
|
self.current_health -= 1;
|
||||||
|
|
||||||
|
if let Some(sprite) = &mut self.anim_sprite {
|
||||||
|
sprite.set_modulate(Color::RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = self.base().clone();
|
||||||
|
let sprite_opt = self.anim_sprite.clone();
|
||||||
|
|
||||||
|
if let Some(mut tween) = self.base_mut().create_tween() {
|
||||||
|
tween.tween_property(
|
||||||
|
&node.clone().upcast::<Object>(),
|
||||||
|
"scale",
|
||||||
|
&Vector2::new(1.2, 0.8).to_variant(),
|
||||||
|
0.05,
|
||||||
|
);
|
||||||
|
tween.tween_property(
|
||||||
|
&node.clone().upcast::<Object>(),
|
||||||
|
"scale",
|
||||||
|
&Vector2::ONE.to_variant(),
|
||||||
|
0.05,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Flash Red
|
||||||
|
if let Some(sprite) = sprite_opt {
|
||||||
|
if let Some(mut parallel) = tween.parallel() {
|
||||||
|
parallel.tween_property(
|
||||||
|
&sprite.upcast::<Object>(),
|
||||||
|
"modulate",
|
||||||
|
&Color::WHITE.to_variant(),
|
||||||
|
0.1,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.current_health <= 0 {
|
||||||
|
self.resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve(&mut self) {
|
||||||
|
self.is_resolved = true;
|
||||||
|
|
||||||
|
if let Some(data) = &self.data {
|
||||||
|
let hazard_type = data.bind().hazard_type.clone();
|
||||||
|
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
state.bind().remove_active_hazard(hazard_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = self.base().clone();
|
||||||
|
|
||||||
|
if let Some(mut tween) = self.base_mut().create_tween() {
|
||||||
|
tween.tween_property(
|
||||||
|
&node.clone().upcast::<Object>(),
|
||||||
|
"scale",
|
||||||
|
&Vector2::ZERO.to_variant(),
|
||||||
|
0.2,
|
||||||
|
);
|
||||||
|
tween.tween_callback(&node.callable("queue_free"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
rust/src/systems/hazard_system.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use godot::{classes::RandomNumberGenerator, prelude::*};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
core::game_state::GameState, data::hazard_def::HazardDef,
|
||||||
|
systems::hazard_controller::HazardController,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct HazardSystem {
|
||||||
|
#[export]
|
||||||
|
possible_hazards: Array<Gd<HazardDef>>,
|
||||||
|
#[export]
|
||||||
|
spawn_locations: Array<Gd<Node2D>>,
|
||||||
|
#[export]
|
||||||
|
hazard_prefab: Option<Gd<PackedScene>>,
|
||||||
|
#[export]
|
||||||
|
check_interval: f32,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
timer: f32,
|
||||||
|
rng: Gd<RandomNumberGenerator>,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for HazardSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
possible_hazards: Array::new(),
|
||||||
|
spawn_locations: Array::new(),
|
||||||
|
hazard_prefab: None,
|
||||||
|
check_interval: 1.0,
|
||||||
|
game_state: None,
|
||||||
|
timer: 0.0,
|
||||||
|
rng: RandomNumberGenerator::new_gd(),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
self.timer += delta as f32;
|
||||||
|
if self.timer >= self.check_interval {
|
||||||
|
self.timer = 0.0;
|
||||||
|
self.try_spawn_hazard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl HazardSystem {
|
||||||
|
#[func]
|
||||||
|
pub fn clear_hazards(&mut self) {
|
||||||
|
for location in self.spawn_locations.iter_shared() {
|
||||||
|
for mut child in location.get_children().iter_shared() {
|
||||||
|
child.queue_free();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.timer = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
pub fn set_available_hazards(&mut self, hazards: Array<Gd<HazardDef>>) {
|
||||||
|
self.possible_hazards = hazards;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_spawn_hazard(&mut self) {
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let current_focus = state.bind().get_focus();
|
||||||
|
|
||||||
|
if current_focus < 0.2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let spawn_chance = current_focus * 0.5;
|
||||||
|
if self.rng.randf() < spawn_chance {
|
||||||
|
self.spawn_random_hazard(current_focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn spawn_random_hazard(&mut self, current_focus: f32) {
|
||||||
|
if self.possible_hazards.is_empty()
|
||||||
|
|| self.spawn_locations.is_empty()
|
||||||
|
|| self.hazard_prefab.is_none()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let empty_locations: Vec<Gd<Node2D>> = self
|
||||||
|
.spawn_locations
|
||||||
|
.iter_shared()
|
||||||
|
.filter(|loc| loc.get_child_count() == 0)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if empty_locations.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let loc_idx = self.rng.randi() as usize % empty_locations.len();
|
||||||
|
let mut target_loc = empty_locations[loc_idx].clone();
|
||||||
|
|
||||||
|
let valid_hazards: Vec<Gd<HazardDef>> = self
|
||||||
|
.possible_hazards
|
||||||
|
.iter_shared()
|
||||||
|
.filter(|h| h.bind().min_focus_to_spawn <= current_focus)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if valid_hazards.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let haz_idx = self.rng.randi() as usize % valid_hazards.len();
|
||||||
|
let selected_hazard = valid_hazards[haz_idx].clone();
|
||||||
|
let hazard_type = selected_hazard.bind().hazard_type.clone();
|
||||||
|
|
||||||
|
if let Some(prefab) = &self.hazard_prefab {
|
||||||
|
if let Some(instance) = prefab.instantiate() {
|
||||||
|
if let Ok(mut hazard_node) = instance.try_cast::<HazardController>() {
|
||||||
|
hazard_node
|
||||||
|
.clone()
|
||||||
|
.upcast::<Node2D>()
|
||||||
|
.set_position(Vector2::ZERO);
|
||||||
|
|
||||||
|
target_loc.add_child(&hazard_node.clone().upcast::<Node>());
|
||||||
|
|
||||||
|
hazard_node.bind_mut().initialize(selected_hazard);
|
||||||
|
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
hazard_node.bind_mut().set_game_state(Some(state.clone()));
|
||||||
|
state.bind().add_active_hazard(hazard_type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
godot_print!("Error: Hazard Prefab root is not a HazardController!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
rust/src/systems/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
pub mod bench_press_system;
|
||||||
|
pub mod camera_shake_system;
|
||||||
|
pub mod deadlift_system;
|
||||||
|
pub mod game_manager;
|
||||||
|
pub mod hazard_controller;
|
||||||
|
pub mod hazard_system;
|
||||||
|
pub mod player_input_system;
|
||||||
|
pub mod sound_manager;
|
||||||
|
pub mod tunnel_system;
|
||||||
40
rust/src/systems/player_input_system.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use godot::{classes::Input, prelude::*};
|
||||||
|
|
||||||
|
use crate::core::game_state::GameState;
|
||||||
|
|
||||||
|
const LIFT_ACTION: &str = "lift_action";
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct PlayerInputSystem {
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for PlayerInputSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
game_state: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let state_bind = state.bind();
|
||||||
|
|
||||||
|
let input = Input::singleton();
|
||||||
|
|
||||||
|
if input.is_action_pressed(LIFT_ACTION) {
|
||||||
|
state_bind.apply_effort(delta as f32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.is_action_just_released(LIFT_ACTION) {
|
||||||
|
state_bind.release_focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
213
rust/src/systems/sound_manager.rs
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
use crate::{
|
||||||
|
core::game_state::{GameEvent, GameState},
|
||||||
|
data::sound_bank::SoundBank,
|
||||||
|
};
|
||||||
|
use godot::{
|
||||||
|
classes::{AudioStream, AudioStreamPlayer},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct SoundManager {
|
||||||
|
#[export]
|
||||||
|
bank: Option<Gd<SoundBank>>,
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
pool_size: i32,
|
||||||
|
|
||||||
|
sfx_pool: Vec<Gd<AudioStreamPlayer>>,
|
||||||
|
strain_player: Option<Gd<AudioStreamPlayer>>,
|
||||||
|
heartbeat_player: Option<Gd<AudioStreamPlayer>>,
|
||||||
|
music_player: Option<Gd<AudioStreamPlayer>>,
|
||||||
|
|
||||||
|
was_lifting: bool,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for SoundManager {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
bank: None,
|
||||||
|
game_state: None,
|
||||||
|
pool_size: 8,
|
||||||
|
sfx_pool: Vec::new(),
|
||||||
|
strain_player: None,
|
||||||
|
heartbeat_player: None,
|
||||||
|
music_player: None,
|
||||||
|
was_lifting: false,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready(&mut self) {
|
||||||
|
self.initialize_pool();
|
||||||
|
|
||||||
|
// FIX: Clone bank to release borrow on self
|
||||||
|
if let Some(bank) = self.bank.clone() {
|
||||||
|
if let Some(music) = &bank.bind().game_music {
|
||||||
|
self.play_music(music.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, _delta: f64) {
|
||||||
|
let Some(state) = self.game_state.clone() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let events = state.bind().pop_events();
|
||||||
|
|
||||||
|
for event in events {
|
||||||
|
match event {
|
||||||
|
GameEvent::HazardSpawned => self.play_bank_sfx(|b| b.hazard_spawn.clone()),
|
||||||
|
GameEvent::HazardResolved => self.play_bank_sfx(|b| b.hazard_resolve.clone()),
|
||||||
|
GameEvent::LiftCompleted(success) => {
|
||||||
|
self.stop_strain();
|
||||||
|
if success {
|
||||||
|
self.play_bank_sfx(|b| b.win_stinger.clone());
|
||||||
|
} else {
|
||||||
|
self.play_bank_sfx(|b| b.fail_stinger.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameEvent::TraumaApplied(amount) => {
|
||||||
|
if amount > 0.5 {
|
||||||
|
self.play_bank_sfx(|b| b.camera_trauma.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_lifting = state.bind().get_is_lifting();
|
||||||
|
let progress = state.bind().get_lift_progress();
|
||||||
|
let focus = state.bind().get_focus();
|
||||||
|
|
||||||
|
if is_lifting != self.was_lifting {
|
||||||
|
if is_lifting {
|
||||||
|
self.play_strain_loop();
|
||||||
|
} else {
|
||||||
|
self.stop_strain();
|
||||||
|
self.play_bank_sfx(|b| b.effort_exhale.clone());
|
||||||
|
}
|
||||||
|
self.was_lifting = is_lifting;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_lifting {
|
||||||
|
self.update_strain_pitch(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_heartbeat(focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SoundManager {
|
||||||
|
fn initialize_pool(&mut self) {
|
||||||
|
for _ in 0..self.pool_size {
|
||||||
|
let mut p = AudioStreamPlayer::new_alloc();
|
||||||
|
p.set_bus("Sfx");
|
||||||
|
self.base_mut().add_child(&p.clone().upcast::<Node>());
|
||||||
|
self.sfx_pool.push(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut strain = AudioStreamPlayer::new_alloc();
|
||||||
|
strain.set_bus("Sfx");
|
||||||
|
self.base_mut().add_child(&strain.clone().upcast::<Node>());
|
||||||
|
self.strain_player = Some(strain);
|
||||||
|
|
||||||
|
let mut hb = AudioStreamPlayer::new_alloc();
|
||||||
|
hb.set_bus("Sfx");
|
||||||
|
self.base_mut().add_child(&hb.clone().upcast::<Node>());
|
||||||
|
self.heartbeat_player = Some(hb);
|
||||||
|
|
||||||
|
let mut mus = AudioStreamPlayer::new_alloc();
|
||||||
|
mus.set_bus("Music");
|
||||||
|
self.base_mut().add_child(&mus.clone().upcast::<Node>());
|
||||||
|
self.music_player = Some(mus);
|
||||||
|
|
||||||
|
if let Some(bank) = self.bank.clone() {
|
||||||
|
let bank_bind = bank.bind();
|
||||||
|
if let Some(clip) = &bank_bind.heartbeat_loop {
|
||||||
|
if let Some(hb_player) = &mut self.heartbeat_player {
|
||||||
|
hb_player.set_stream(&clip.clone());
|
||||||
|
hb_player.set_volume_db(-80.0);
|
||||||
|
hb_player.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_music(&mut self, clip: Gd<AudioStream>) {
|
||||||
|
if let Some(p) = &mut self.music_player {
|
||||||
|
p.set_stream(&clip);
|
||||||
|
p.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_bank_sfx<F>(&mut self, selector: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&SoundBank) -> Option<Gd<AudioStream>>,
|
||||||
|
{
|
||||||
|
let clip = self.bank.as_ref().and_then(|b| selector(&b.bind()));
|
||||||
|
|
||||||
|
if let Some(c) = clip {
|
||||||
|
self.play_sfx(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_sfx(&mut self, clip: Gd<AudioStream>) {
|
||||||
|
for p in &mut self.sfx_pool {
|
||||||
|
if !p.is_playing() {
|
||||||
|
p.set_stream(&clip);
|
||||||
|
p.set_pitch_scale(1.0);
|
||||||
|
p.play();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(p) = self.sfx_pool.first_mut() {
|
||||||
|
p.set_stream(&clip);
|
||||||
|
p.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn play_strain_loop(&mut self) {
|
||||||
|
if let Some(bank) = self.bank.clone() {
|
||||||
|
if let Some(clip) = &bank.bind().strain_loop {
|
||||||
|
if let Some(p) = &mut self.strain_player {
|
||||||
|
p.set_stream(&clip.clone());
|
||||||
|
p.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_strain(&mut self) {
|
||||||
|
if let Some(p) = &mut self.strain_player {
|
||||||
|
p.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_strain_pitch(&mut self, progress: f32) {
|
||||||
|
if let Some(p) = &mut self.strain_player {
|
||||||
|
let pitch = 1.0 + (progress * 0.3);
|
||||||
|
p.set_pitch_scale(pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_heartbeat(&mut self, focus: f32) {
|
||||||
|
if let Some(p) = &mut self.heartbeat_player {
|
||||||
|
if focus < 0.1 {
|
||||||
|
p.set_volume_db(-80.0);
|
||||||
|
} else {
|
||||||
|
let t = (focus - 0.1) / 0.9;
|
||||||
|
let vol = -30.0 + (t * (5.0 - (-30.0)));
|
||||||
|
let pitch = 1.0 + (t * 0.4);
|
||||||
|
p.set_volume_db(vol);
|
||||||
|
p.set_pitch_scale(pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
82
rust/src/systems/tunnel_system.rs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
use godot::{
|
||||||
|
classes::{ColorRect, ShaderMaterial},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{core::game_state::GameState, data::tunnel_config::TunnelConfig};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct TunnelSystem {
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
#[export]
|
||||||
|
config: Option<Gd<TunnelConfig>>,
|
||||||
|
#[export]
|
||||||
|
vignette_overlay: Option<Gd<ColorRect>>,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for TunnelSystem {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
game_state: None,
|
||||||
|
config: None,
|
||||||
|
vignette_overlay: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(config) = &self.config else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let state_bind = state.bind();
|
||||||
|
let is_lifting = state_bind.get_is_lifting();
|
||||||
|
let current_focus = state_bind.get_focus();
|
||||||
|
|
||||||
|
drop(state_bind);
|
||||||
|
|
||||||
|
let config_bind = config.bind();
|
||||||
|
let dt = delta as f32;
|
||||||
|
|
||||||
|
let mut new_focus = current_focus;
|
||||||
|
|
||||||
|
if is_lifting {
|
||||||
|
new_focus += config_bind.vision_narrow_rate * dt;
|
||||||
|
} else {
|
||||||
|
new_focus -= config_bind.vision_recover_rate * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_focus = new_focus.clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
let max_intensity = config_bind.max_tunnel_intensity;
|
||||||
|
|
||||||
|
let visual_raw = if let Some(curve) = &config_bind.vision_curve {
|
||||||
|
curve.sample(new_focus)
|
||||||
|
} else {
|
||||||
|
new_focus
|
||||||
|
};
|
||||||
|
|
||||||
|
let visual_value = visual_raw * max_intensity;
|
||||||
|
|
||||||
|
if let Some(overlay) = &mut self.vignette_overlay {
|
||||||
|
if let Some(material) = overlay
|
||||||
|
.get_material()
|
||||||
|
.and_then(|m| Some(m.try_cast::<ShaderMaterial>()))
|
||||||
|
{
|
||||||
|
if let Ok(mut mat) = material {
|
||||||
|
mat.set_shader_parameter("vignette_intensity", &visual_value.to_variant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.bind().set_focus_intensity(new_focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
37
rust/src/ui/lift_progress_bar.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
use crate::core::game_state::GameState;
|
||||||
|
use godot::{
|
||||||
|
classes::{IProgressBar, ProgressBar},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=ProgressBar)]
|
||||||
|
pub struct LiftProgressBar {
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
base: Base<ProgressBar>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IProgressBar for LiftProgressBar {
|
||||||
|
fn init(base: Base<ProgressBar>) -> Self {
|
||||||
|
Self {
|
||||||
|
game_state: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready(&mut self) {
|
||||||
|
self.base_mut().set_min(0.0);
|
||||||
|
self.base_mut().set_max(1.0);
|
||||||
|
self.base_mut().set_value(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, _delta: f64) {
|
||||||
|
if let Some(state) = &self.game_state {
|
||||||
|
let progress = state.bind().get_lift_progress();
|
||||||
|
self.base_mut().set_value(progress as f64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
rust/src/ui/main_menu.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use godot::{
|
||||||
|
classes::{AudioServer, CheckButton, Control, IControl},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Control)]
|
||||||
|
pub struct MainMenu {
|
||||||
|
#[export]
|
||||||
|
game_scene: Option<Gd<PackedScene>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
mute_button: Option<Gd<CheckButton>>,
|
||||||
|
|
||||||
|
base: Base<Control>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl IControl for MainMenu {
|
||||||
|
fn init(base: Base<Control>) -> Self {
|
||||||
|
Self {
|
||||||
|
game_scene: None,
|
||||||
|
mute_button: None,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ready(&mut self) {
|
||||||
|
let mut audio_server = AudioServer::singleton();
|
||||||
|
let master_bus = audio_server.get_bus_index("Master");
|
||||||
|
audio_server.set_bus_mute(master_bus, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl MainMenu {
|
||||||
|
#[func]
|
||||||
|
fn on_play_pressed(&mut self) {
|
||||||
|
if let Some(scene) = &self.game_scene {
|
||||||
|
if let Some(mut tree) = self.base().get_tree() {
|
||||||
|
tree.change_scene_to_packed(&scene.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn on_quit_pressed(&mut self) {
|
||||||
|
if let Some(mut tree) = self.base().get_tree() {
|
||||||
|
tree.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[func]
|
||||||
|
fn on_mute_toggled(&mut self, toggled_on: bool) {
|
||||||
|
let mut audio_server = AudioServer::singleton();
|
||||||
|
let master_bus = audio_server.get_bus_index("Master");
|
||||||
|
audio_server.set_bus_mute(master_bus, toggled_on);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
rust/src/ui/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod lift_progress_bar;
|
||||||
|
pub mod main_menu;
|
||||||
107
rust/src/visuals/lift_sync_controller.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use crate::core::game_state::GameState;
|
||||||
|
use godot::{
|
||||||
|
classes::{AnimatedSprite2D, Sprite2D},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(GodotClass)]
|
||||||
|
#[class(base=Node)]
|
||||||
|
pub struct LiftSyncController {
|
||||||
|
#[export]
|
||||||
|
player_anim: Option<Gd<AnimatedSprite2D>>,
|
||||||
|
#[export]
|
||||||
|
barbell: Option<Gd<Sprite2D>>,
|
||||||
|
#[export]
|
||||||
|
game_state: Option<Gd<GameState>>,
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
animation_name: GString,
|
||||||
|
#[export]
|
||||||
|
bar_positions: Array<Vector2>,
|
||||||
|
#[export]
|
||||||
|
simulate_reps: bool,
|
||||||
|
#[export]
|
||||||
|
rep_speed: f32,
|
||||||
|
|
||||||
|
current_rep_progress: f32,
|
||||||
|
|
||||||
|
base: Base<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[godot_api]
|
||||||
|
impl INode for LiftSyncController {
|
||||||
|
fn init(base: Base<Node>) -> Self {
|
||||||
|
Self {
|
||||||
|
player_anim: None,
|
||||||
|
barbell: None,
|
||||||
|
game_state: None,
|
||||||
|
animation_name: "lift".into(),
|
||||||
|
bar_positions: Array::new(),
|
||||||
|
simulate_reps: true,
|
||||||
|
rep_speed: 2.0,
|
||||||
|
current_rep_progress: 0.0,
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, delta: f64) {
|
||||||
|
let Some(state) = &self.game_state else {
|
||||||
|
godot_error!("LiftSyncController: No game state assigned");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let state_bind = state.bind();
|
||||||
|
let is_lifting = state_bind.get_is_lifting();
|
||||||
|
|
||||||
|
let visual_height = state_bind.inner.read().unwrap().visual_height;
|
||||||
|
drop(state_bind);
|
||||||
|
|
||||||
|
let dt = delta as f32;
|
||||||
|
|
||||||
|
if self.simulate_reps {
|
||||||
|
if is_lifting {
|
||||||
|
self.current_rep_progress += self.rep_speed * dt;
|
||||||
|
} else {
|
||||||
|
if self.current_rep_progress > 0.0 {
|
||||||
|
self.current_rep_progress -= self.rep_speed * dt;
|
||||||
|
self.current_rep_progress = self.current_rep_progress.max(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ping_pong_val =
|
||||||
|
godot::global::pingpong(self.current_rep_progress as f64, 1.0) as f32;
|
||||||
|
self.update_visuals(ping_pong_val);
|
||||||
|
} else {
|
||||||
|
self.update_visuals(visual_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiftSyncController {
|
||||||
|
fn update_visuals(&mut self, normalized_height: f32) {
|
||||||
|
if self.player_anim.is_none() || self.barbell.is_none() || self.bar_positions.is_empty() {
|
||||||
|
godot_error!("LiftSyncController: Missing visuals or bar positions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let total_frames = self.bar_positions.len() as i32;
|
||||||
|
let frame_index_f = normalized_height * (total_frames as f32 - 0.01);
|
||||||
|
let frame_index = (frame_index_f.floor() as i32).clamp(0, total_frames - 1);
|
||||||
|
|
||||||
|
if let Some(anim) = &mut self.player_anim {
|
||||||
|
anim.set_frame(frame_index);
|
||||||
|
|
||||||
|
let current_anim = anim.get_animation();
|
||||||
|
if current_anim != StringName::from(&self.animation_name) {
|
||||||
|
let anim_name_sn = StringName::from(&self.animation_name);
|
||||||
|
anim.play_ex().name(&anim_name_sn).done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bar) = &mut self.barbell {
|
||||||
|
if let Some(pos) = self.bar_positions.get(frame_index as usize) {
|
||||||
|
bar.set_position(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
rust/src/visuals/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod lift_sync_controller;
|
||||||