79 lines
1.8 KiB
GDScript
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)
|