Add sleeping

This commit is contained in:
snider committed 2022-08-17 05:46:36 -07:00
1 parent 22e2fc0067
commit 30f171f3d9
28 files changed
+1677 -221

No files matched your search

+124
View File
@@ -0,0 +1,124 @@
extends KinematicBody
signal starved_to_death
const StateDefault = preload("res://scripts/player/state/default.gd")
const StateInteracting = preload("res://scripts/player/state/interacting.gd")
const StateSleeping = preload("res://scripts/player/state/sleeping.gd")
const SPEED = 10.0
const MAX_HEALTH = 4
export var hunger_tick_time = 30.0
export var inventory = {}
var health: int = 4 setget set_health
var item_in_hand
var move_enabled: bool = true
onready var anim_tree = $model_transform/DungMan/AnimationTree
onready var move_playback = anim_tree["parameters/Move/playback"]
onready var hunger_timer = $"%hunger_timer"
var state = null
func _ready():
$hitbox.set_meta("owner", self)
move_playback.travel("idle")
hunger_timer.wait_time = hunger_tick_time
hunger_timer.start()
state = StateDefault.new()
state.ctx = self
state.enter_from(null)
print("player: NULL -> ", state.NAME)
func change_state(new_state):
print("player: ", state.NAME, " -> ", new_state.NAME)
new_state.ctx = self
state.exit_to(new_state)
new_state.enter_from(state)
state = new_state
func _physics_process(delta):
state.physics_process(delta)
func _on_hunger_timer_timeout():
set_health(health - 1)
print("player: lost health to hunger tick")
func set_health(new_value):
health = min(new_value, MAX_HEALTH)
for child in $"%stomachs".get_children():
child.visible = child.get_index() < health
if health <= 0:
emit_signal("starved_to_death")
func consume_food(item : Resource):
set_health(MAX_HEALTH)
print("player: Hunger Satisfied! Ate %s" % item.name)
func can_afford(item_name, item_amount):
assert(item_amount > 0)
var current_amount : int = 0
if(inventory.has(item_name)):
current_amount = inventory[item_name]
return current_amount >= item_amount
func modify_inventory(item_name, item_amount):
if item_amount == 0:
return true
var is_op_valid : bool = true
# Note(asr): check if you can afford the item if we are removing
# for item grants op is always valid
if item_amount < 0:
is_op_valid = can_afford(item_name, abs(item_amount))
if not is_op_valid:
return false
var current_amount : int = 0
if inventory.has(item_name):
current_amount = inventory[item_name]
# Note(asr): clamp to 0. can't have negative items
var new_amount : int = max(current_amount + item_amount, 0)
inventory[item_name] = new_amount
print("inventory updated: ", item_name, " : ", new_amount)
return true
func _unhandled_input(event):
state.unhandled_input(event)
func drop_item_in_hand():
print("player dropped ", item_in_hand.item_name)
var item_dropped = item_in_hand
$"%ItemSpawn".remove_child(item_in_hand)
item_in_hand = null
return item_dropped
func pick_up_item(item):
var item_dropped = null
if item_in_hand != null:
item_dropped = drop_item_in_hand()
item_in_hand = item
$"%ItemSpawn".add_child(item_in_hand)
print("player picked up ", item_in_hand.item_name)
return item_dropped
func has_item() -> bool:
return item_in_hand != null
func get_item_in_hand():
var item_to_return = null
if item_in_hand != null:
item_to_return = drop_item_in_hand()
return item_to_return
func _on_blink_timer_timeout():
anim_tree["parameters/Blink/active"] = true
$"%blink_timer".wait_time = rand_range(0.5, 3.0)
func sleep(made_it_to_bed: bool, hop_position: Spatial):
state.on_sleep(made_it_to_bed, hop_position)
+36
View File
@@ -0,0 +1,36 @@
extends Reference
const NAME = "default"
const EPSILON = 0.0001
var ctx = null
var anim_tree: AnimationTree
var move_playback
func _init():
pass
func enter_from(state):
anim_tree = ctx.get_node("model_transform/DungMan/AnimationTree")
move_playback = anim_tree["parameters/Move/playback"]
func exit_to(state):
pass
func physics_process(delta):
var input = Vector3(Input.get_axis("left", "right"), 0.0, Input.get_axis("up", "down"))
var motion = Plane.PLANE_XZ.project(ctx.get_viewport().get_camera().global_transform.basis.xform(input)).normalized() * ctx.SPEED
if motion.length_squared() > EPSILON:
ctx.get_node("model_transform").look_at(ctx.global_transform.origin - motion, Vector3.UP)
ctx.move_playback.travel("run")
else:
ctx.move_playback.travel("idle")
ctx.move_and_slide(motion)
func unhandled_input(event):
if event.is_action_pressed("action"):
ctx.get_tree().set_input_as_handled()
ctx.change_state(ctx.StateInteracting.new())
func on_sleep(made_it_to_bed: bool, hop_position: Spatial):
ctx.change_state(ctx.StateSleeping.new(made_it_to_bed, hop_position))
+54
View File
@@ -0,0 +1,54 @@
extends Reference
const NAME = "interacting"
var ctx: KinematicBody = null
var anim_tree: AnimationTree
var timer: SceneTreeTimer
func _init():
pass
func enter_from(state):
anim_tree = ctx.get_node("model_transform/DungMan/AnimationTree")
anim_tree["parameters/Move/playback"].travel("idle")
anim_tree["parameters/Activate/active"] = true
timer = ctx.get_tree().create_timer(0.2)
timer.connect("timeout", self, "_on_timeout", [], CONNECT_ONESHOT)
func exit_to(state):
pass
func physics_process(delta):
pass
func unhandled_input(event):
pass
func _on_timeout():
for area in ctx.get_node("%TriggerVolume").get_overlapping_areas():
if try_trigger_interact(area):
break
if ctx.state == self:
ctx.change_state(ctx.StateDefault.new())
func try_trigger_interact(area) -> bool:
var owner = area
if area.has_meta("owner"):
owner = area.get_meta("owner")
if not owner.has_method("on_player_interact"):
return false
var result = owner.on_player_interact(ctx)
if not result:
print("player failed to interacted with ", owner)
return false
print("player interacted with ", owner)
return true
func on_sleep(made_it_to_bed: bool, hop_position: Spatial):
timer.disconnect("timeout", self, "_on_timeout")
ctx.change_state(ctx.StateSleeping.new(made_it_to_bed, hop_position))
+99
View File
@@ -0,0 +1,99 @@
extends Reference
const NAME = "sleeping"
var ctx: KinematicBody = null
var hop_position: Spatial
var made_it_to_bed: bool
var model_transform: Spatial
var anim_player: AnimationPlayer
var old_model_origin: Vector3
var waiting := false
func _init(p_made_it_to_bed: bool, p_hop_position: Spatial = null):
hop_position = p_hop_position
made_it_to_bed = p_made_it_to_bed
func enter_from(state):
hop_position = hop_position if hop_position else ctx.get_tree().get_nodes_in_group("bed_hop_position")[0]
model_transform = ctx.get_node("model_transform")
anim_player = ctx.get_node("model_transform/node_animations")
# Pause everything but the player
ctx.get_tree().paused = true
ctx.get_node("hunger_timer").pause_mode = ctx.PAUSE_MODE_STOP
ctx.pause_mode = ctx.PAUSE_MODE_PROCESS
# Drop any carried item
if ctx.has_item():
ctx.drop_item_in_hand()
# Prepare to play animation
if made_it_to_bed:
# Slide the player to the front of the bed
old_model_origin = model_transform.global_transform.origin
var tween = model_transform.create_tween()
tween.tween_property(model_transform, "global_transform:origin", hop_position.global_transform.origin, .1)
yield(tween, "finished")
# Warp the player to the right position & orientation
model_transform.global_transform = hop_position.global_transform
else:
# Harm the player and show message
ctx.set_health(ctx.health - 1)
var node = Dialogic.start("day_end")
node.pause_mode = ctx.PAUSE_MODE_PROCESS
ctx.add_child(node)
yield(node, "timeline_end")
# Warp the player to the right position & orientation
ctx.global_transform.origin = hop_position.global_transform.origin
model_transform.global_transform = hop_position.global_transform
old_model_origin = model_transform.global_transform.origin
# Play hop animation
ctx.get_node("model_transform/DungMan/AnimationTree")["parameters/Move/playback"].travel("idle")
anim_player.call_deferred("play", "hop_into_bed")
yield(anim_player, "animation_finished")
waiting = true
# Reset the day timer
for game_manager in ctx.get_tree().get_nodes_in_group("game_manager"):
game_manager.reset_day_timer()
func exit_to(state):
ctx.pause_mode = ctx.PAUSE_MODE_INHERIT
ctx.get_node("hunger_timer").pause_mode = ctx.PAUSE_MODE_INHERIT
ctx.get_tree().paused = false
func physics_process(delta):
pass
func unhandled_input(event: InputEvent):
if not waiting:
return
if not event.is_action_pressed("action"):
return
ctx.get_tree().set_input_as_handled()
# Play hop out animation
anim_player.call_deferred("play", "hop_out_of_bed")
yield(anim_player, "animation_finished")
# Slide the player back to the front of the bed
var tween = model_transform.create_tween()
tween.tween_property(model_transform, "global_transform:origin", old_model_origin, .1)
yield(tween, "finished")
# Show message
var node = Dialogic.start("wake_up")
node.pause_mode = ctx.PAUSE_MODE_PROCESS
ctx.add_child(node)
yield(node, "timeline_end")
ctx.change_state(ctx.StateDefault.new())
func on_sleep(made_it_to_bed: bool, hop_position: Spatial):
assert(false, "shouldn't be able to sleep while sleeping")