signalis-eb/godot/src/door.gd

79 lines
1.8 KiB
GDScript

class_name Door extends StaticBody3D
signal opened
signal closed
signal locked
signal unlocked
@export var is_open: bool = false
@export var is_locked: bool = false
@export var key: Item
var requires_key: bool:
get: return key != null
class UnopenableDoorError:
static var name:
get: return "UnopenableDoorError"
class NodeNoInventoryError:
static var name:
get: return "NodeNoInventoryError"
class MissingKeyError:
static var name:
get: return "MissingKeyError"
class LockedError:
static var name:
get: return "LockedError"
func check_requirements(interactor: Node) -> Result:
if not is_locked: return Result.Unit
elif not requires_key: return Result.err(UnopenableDoorError)
match NodeExt.find_child_variant(interactor, ItemContainer):
var opt when opt.is_none(): return Result.err(NodeNoInventoryError)
var opt: match opt.unwrap():
var inv when inv.has_item(key): return Result.Unit
_: return Result.err(MissingKeyError)
func open() -> Result:
if is_locked: return Result.err(LockedError)
if not is_open:
is_open = true
opened.emit()
return Result.Unit
func close() -> Result:
if is_open:
is_open = false
closed.emit()
return Result.Unit
func unlock() -> Result:
if is_locked:
is_locked = false
unlocked.emit()
return Result.Unit
func lock() -> Result:
if not is_locked:
is_locked = true
locked.emit()
return Result.Unit
func try_unlock(node: Node) -> Result:
match check_requirements(node):
var result when result.is_ok(): return unlock()
var err: return err
func try_open(node: Node) -> Result:
if is_locked: return try_unlock(node)
else: return open()
func try_interact(node: Node) -> Result:
if is_open: return close()
else: return try_open(node)
func _on_interact(interactor: Interactor):
match try_interact(interactor.root_node):
var ok when ok.is_ok(): pass
var err: push_error(err.unwrap_err().name)