diff --git a/project.godot b/project.godot index 92bed9d..159c46b 100644 --- a/project.godot +++ b/project.godot @@ -70,6 +70,11 @@ _global_script_classes=[ { "path": "res://scripts/ItemType.gd" }, { "base": "Resource", +"class": "ItemTypeCount", +"language": "GDScript", +"path": "res://scripts/ItemTypeCount.gd" +}, { +"base": "Resource", "class": "Recipe", "language": "GDScript", "path": "res://scripts/Recipe.gd" @@ -92,6 +97,7 @@ _global_script_class_icons={ "DialogicUtil": "", "HistoryRow": "", "ItemType": "", +"ItemTypeCount": "", "Recipe": "", "RecipeDB": "" } diff --git a/scenes/item_dump.tscn b/scenes/item_dump.tscn new file mode 100644 index 0000000..2b1ab34 --- /dev/null +++ b/scenes/item_dump.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://scripts/item_dump.gd" type="Script" id=1] + +[sub_resource type="BoxShape" id=1] + +[node name="item_dump" type="Area"] +script = ExtResource( 1 ) + +[node name="CollisionShape" type="CollisionShape" parent="."] +shape = SubResource( 1 ) diff --git a/scenes/oven.tscn b/scenes/oven.tscn index 079f05c..3d35415 100644 --- a/scenes/oven.tscn +++ b/scenes/oven.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=9 format=2] [ext_resource path="res://scenes/item_holder.tscn" type="PackedScene" id=1] [ext_resource path="res://scripts/oven/oven.gd" type="Script" id=2] [ext_resource path="res://scenes/coin_machine.tscn" type="PackedScene" id=3] +[ext_resource path="res://scenes/item_dump.tscn" type="PackedScene" id=4] +[ext_resource path="res://scenes/status_light.tscn" type="PackedScene" id=5] [sub_resource type="SpatialMaterial" id=1] albedo_color = Color( 0, 0, 0, 1 ) @@ -22,6 +24,7 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0063355, 0.00319374, -0.004 script = ExtResource( 2 ) [node name="CSGBox" type="CSGBox" parent="."] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.497031, 0 ) use_collision = true width = 1.36825 height = 1.04121 @@ -50,10 +53,18 @@ mesh = SubResource( 3 ) skeleton = NodePath("../..") [node name="coin_machine" parent="." instance=ExtResource( 3 )] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.621351, 0 ) + +[node name="item_dump" parent="." instance=ExtResource( 4 )] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.733121, 0 ) + +[node name="status_light" parent="." instance=ExtResource( 5 )] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.232042, 0.967385 ) [node name="cook_timer" type="Timer" parent="."] one_shot = true [connection signal="item_changed" from="CSGBox/coil/item_holder" to="." method="_on_item_holder_item_changed"] [connection signal="coin_requirement_met" from="coin_machine" to="." method="_on_coin_machine_coin_requirement_met"] +[connection signal="item_dump_completed" from="item_dump" to="." method="_on_item_dump_item_dump_completed"] [connection signal="timeout" from="cook_timer" to="." method="_on_cook_timer_timeout"] diff --git a/scenes/status_light.tscn b/scenes/status_light.tscn new file mode 100644 index 0000000..4d8949c --- /dev/null +++ b/scenes/status_light.tscn @@ -0,0 +1,184 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://scripts/status_light.gd" type="Script" id=1] + +[sub_resource type="Animation" id=1] +length = 0.001 +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ 1.0 ] +} + +[sub_resource type="Animation" id=2] +resource_name = "activate" +length = 0.6 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 0.196078, 0.807843, 0.176471, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 0.3, 0.6 ), +"transitions": PoolRealArray( 1, 1, 1 ), +"update": 0, +"values": [ 1.0, 0.1, 1.0 ] +} + +[sub_resource type="Animation" id=6] +resource_name = "fail" +length = 0.001 +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 0, 0, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ 1.0 ] +} + +[sub_resource type="Animation" id=3] +resource_name = "idle" +length = 0.001 +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ 1.0 ] +} + +[sub_resource type="Animation" id=4] +resource_name = "prime" +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 0.5, 1 ), +"transitions": PoolRealArray( 1, 1, 1 ), +"update": 0, +"values": [ 1.0, 0.1, 1.0 ] +} + +[sub_resource type="Animation" id=5] +resource_name = "warn" +length = 0.001 +tracks/0/type = "value" +tracks/0/path = NodePath(".:light_color") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ Color( 1, 0.960784, 0, 1 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:light_energy") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 1 ), +"update": 0, +"values": [ 0.5 ] +} + +[node name="status_light" type="OmniLight"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.400717, 0.897655 ) +omni_range = 1.03219 +script = ExtResource( 1 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +anims/RESET = SubResource( 1 ) +anims/activate = SubResource( 2 ) +anims/fail = SubResource( 6 ) +anims/idle = SubResource( 3 ) +anims/prime = SubResource( 4 ) +anims/warn = SubResource( 5 ) diff --git a/scripts/ItemTypeCount.gd b/scripts/ItemTypeCount.gd new file mode 100644 index 0000000..d06c4c9 --- /dev/null +++ b/scripts/ItemTypeCount.gd @@ -0,0 +1,5 @@ +extends Resource +class_name ItemTypeCount + +export var item_type: Resource +export var count: int diff --git a/scripts/item_dump.gd b/scripts/item_dump.gd new file mode 100644 index 0000000..3872d66 --- /dev/null +++ b/scripts/item_dump.gd @@ -0,0 +1,52 @@ +extends Spatial +signal item_dump_completed +signal item_dumped + +# Godot is not configurable enough (without great pains) +# to make this look less dumb +export var item_type_0: Resource +export var item_count_0: int +export var item_type_1: Resource +export var item_count_1: int +export var item_type_2: Resource +export var item_count_2: int + +var remaining := {} +export var enabled = true + +func _ready(): + reset() + +func reset(): + remaining.clear() + if item_type_0 and item_count_0 > 0: + remaining[item_type_0] = item_count_0 + if item_type_1 and item_count_1 > 0: + remaining[item_type_1] = item_count_1 + if item_type_2 and item_count_2 > 0: + remaining[item_type_2] = item_count_2 + +func on_player_interact(player) -> bool: + if not enabled: + return false + if remaining.empty(): + return false + if not player.has_item(): + return false + if not remaining.has(player.item_in_hand.item_type): + return false + assert(remaining[player.item_in_hand.item_type] > 0, "remaining dictionary should always erase keys with a value of 0") + + # Remove the player's item and mark off the item on the remaining list + var item = player.drop_item_in_hand() + remaining[item.item_type] -= 1 + if remaining[item.item_type] <= 0: + remaining.erase(item.item_type) + item.queue_free() + emit_signal("item_dumped") + + # Check if everything's been checked off + if remaining.empty(): + emit_signal("item_dump_completed") + + return true diff --git a/scripts/oven/oven.gd b/scripts/oven/oven.gd index 5cf0462..f6d5772 100644 --- a/scripts/oven/oven.gd +++ b/scripts/oven/oven.gd @@ -3,18 +3,28 @@ extends Spatial const StateIdle = preload("res://scripts/oven/state/idle.gd") const StateCooking = preload("res://scripts/oven/state/cooking.gd") const StateHoldingItem = preload("res://scripts/oven/state/holding_item.gd") +const StateBroken = preload("res://scripts/oven/state/broken.gd") export var cook_time: float = 2.0 +export var broken: bool = false setget set_broken var state = null func _ready(): $cook_timer.wait_time = cook_time - - state = StateIdle.new() + if broken: + state = StateBroken.new() + else: + state = StateIdle.new() state.ctx = self state.enter_from(null) print("oven: NULL -> ", state.NAME) +func set_broken(new_value: bool): + if broken == new_value: + return + broken == new_value + state.on_broken(broken) + func change_state(new_state): print("oven: ", state.NAME, " -> ", new_state.NAME) new_state.ctx = self @@ -30,3 +40,7 @@ func _on_cook_timer_timeout(): func _on_item_holder_item_changed(item): state.on_item_holder_item_changed(item) + + +func _on_item_dump_item_dump_completed(): + pass # Replace with function body. diff --git a/scripts/oven/state/broken.gd b/scripts/oven/state/broken.gd new file mode 100644 index 0000000..feccc40 --- /dev/null +++ b/scripts/oven/state/broken.gd @@ -0,0 +1,34 @@ +extends Reference + +const NAME = "broken" + +var ctx = null + +func _init(): + pass + +func enter_from(state): + ctx.get_node("item_dump").enabled = true + ctx.get_node("item_dump").reset() + ctx.get_node("coin_machine").enabled = false + ctx.get_node("%item_holder").add_enabled = false + ctx.get_node("%item_holder").remove_enabled = false + ctx.get_node("status_light").fail() + +func exit_to(state): + pass + +func on_break(): + assert(false, "should be impossible while broken") + +func on_fix(): + ctx.change_state(ctx.StateIdle.new()) + +func on_coin_machine_coin_requirement_met(player): + assert(false, "should be impossible while broken") + +func on_cook_timer_timeout(): + assert(false, "should be impossible while broken") + +func on_item_holder_item_changed(item): + assert(false, "should be impossible while broken") diff --git a/scripts/oven/state/cooking.gd b/scripts/oven/state/cooking.gd index c6ac4a3..12612d0 100644 --- a/scripts/oven/state/cooking.gd +++ b/scripts/oven/state/cooking.gd @@ -16,6 +16,8 @@ func enter_from(state): ctx.get_node("cook_timer").start() ctx.get_node("%coil").set_surface_material(0, mat) + ctx.get_node("status_light").light_color = Color.green + ctx.get_node("status_light").activate() func exit_to(state): ctx.get_node("%coil").set_surface_material(0, null) diff --git a/scripts/oven/state/holding_item.gd b/scripts/oven/state/holding_item.gd index 42dea1c..02cdd63 100644 --- a/scripts/oven/state/holding_item.gd +++ b/scripts/oven/state/holding_item.gd @@ -13,10 +13,12 @@ func enter_from(state): ctx.get_node("coin_machine").enabled = true ctx.get_node("%item_holder").add_enabled = false ctx.get_node("%item_holder").remove_enabled = false + ctx.get_node("status_light").prime() else: ctx.get_node("coin_machine").enabled = false ctx.get_node("%item_holder").add_enabled = true ctx.get_node("%item_holder").remove_enabled = true + ctx.get_node("status_light").warn() func exit_to(state): pass diff --git a/scripts/oven/state/idle.gd b/scripts/oven/state/idle.gd index b04a82b..bfe59a6 100644 --- a/scripts/oven/state/idle.gd +++ b/scripts/oven/state/idle.gd @@ -11,6 +11,7 @@ func enter_from(state): ctx.get_node("coin_machine").enabled = false ctx.get_node("%item_holder").add_enabled = true ctx.get_node("%item_holder").remove_enabled = false # not possible + ctx.get_node("status_light").light_color = Color.white func exit_to(state): pass diff --git a/scripts/status_light.gd b/scripts/status_light.gd new file mode 100644 index 0000000..1e81bfc --- /dev/null +++ b/scripts/status_light.gd @@ -0,0 +1,19 @@ +extends OmniLight + +func _ready(): + idle() + +func idle(): + $AnimationPlayer.play("idle") + +func prime(): + $AnimationPlayer.play("prime") + +func activate(): + $AnimationPlayer.play("activate") + +func warn(): + $AnimationPlayer.play("warn") + +func fail(): + $AnimationPlayer.play("fail")