Added the ability to create prefabs.

This commit is contained in:
Patrick Marsee 2021-11-14 22:25:30 -05:00
parent 871646fccc
commit 18595087ff
5 changed files with 304 additions and 59 deletions

View file

@ -62,11 +62,7 @@ class Thing(object):
self.playerx = playerx
if playery:
self.playery = playery
self.passable = bool(flags & 1)
self.talkable = bool(flags & 2)
self.lookable = bool(flags & 4)
self.takeable = bool(flags & 8)
self.useable = bool(flags & 16)
self.flags = flags
self.graphic = ThingGraphic('clear', '#7F7F7F', ' ')
self.thingID = -1 # ID not assigned
@ -79,6 +75,82 @@ class Thing(object):
return False
return self.name == other.name
@property
def passable(self):
return bool(self.flags & 1)
@property
def talkable(self):
return bool(self.flags & 2)
@property
def lookable(self):
return bool(self.flags & 4)
@property
def takeable(self):
return bool(self.flags & 8)
@property
def useable(self):
return bool(self.flags & 16)
def fromPrefab(self, prefab):
"""This only exists as a catch-all in case an unsupported thing type is prefabed."""
parts = prefab.details
# set default values for optional arguments
name = self.name
description = self.description
playerx = prefab.x + (self.playerx - self.x)
playery = prefab.y + (self.playery - self.y)
bgc = self.graphic.background
fgc = self.graphic.foreground
shape = self.graphic.shape
if parts != None:
if 'name' in parts:
name = parts['name']
if 'description' in parts:
description = parts['description']
# load graphic
if 'graphic' in parts:
if 'bgc' in parts['graphic']:
bgc = parts['graphic']['bgc']
if 'fgc' in parts['graphic']:
fgc = parts['graphic']['fgc']
if 'shape' in parts['graphic']:
shape = parts['graphic']['shape']
if 'useLocation' in parts:
playerx, playery = parts['useLocation']
graphic = ThingGraphic(bgc, fgc, shape)
return Thing(self.thingType, name, prefab.x, prefab.y, description, self.flags, playerx, playery)
class Prefab(Thing):
"""Basically a placeholder for a predefined prefab. This is for reading in YAML."""
yaml_flag = u'!Prefab'
defaultGraphic = ThingGraphic('clear', 'clear', 'x')
def __init__(self, name: str, x: int, y: int, **kwargs):
super(Prefab, self).__init__('z', name, x, y, '', 1) # 'p' is already taken by the player.
self.details = None # This is so that custom overrides can be made for specific instances.
if "details" in kwargs:
self.details = kwargs["details"]
@classmethod
def to_yaml(cls, representer, node):
# save usual things
ret = {'name': node.name, 'location': (node.x, node.y), 'details': self.details}
return representer.represent_mapping(cls.yaml_flag, ret)
@classmethod
def from_yaml(cls, constructor, node):
parts = CommentedMap()
constructor.construct_mapping(node, parts, True)
# set default values for optional arguments
mdetails = None
if 'details' in parts:
mdetails = dict(parts['details'])
return cls(parts['name'], parts['location'][0], parts['location'][1], details = mdetails)
class Observer(Thing):
"""ABC for things that have a dict of events that they should listen to."""
@ -162,7 +234,7 @@ class Item(Thing):
if isinstance(customValues[v], tuple):
customValues[v] = list(customValues[v])
if 'ranged' in parts:
useOnFunc = parts['ranged']
ranged = parts['ranged']
return cls(parts['name'], parts['location'][0], parts['location'][1],
parts['description'], useFunc, useOnFunc, customValues, ranged, graphic)
@ -171,6 +243,46 @@ class Item(Thing):
def useOn(self, user, gameBase, thing, args) -> float:
pass
def fromPrefab(self, prefab):
parts = prefab.details
# set default values for optional arguments
name = self.name
useFunc = self.useFunc
useOnFunc = self.useOnFunc
customValues = dict(self.customValues)
ranged = self.ranged
bgc = self.graphic.background
fgc = self.graphic.foreground
shape = self.graphic.shape
description = self.description
if parts:
if 'name' in parts:
name = parts['name']
if 'description' in parts:
description = parts['description']
# load graphic
if 'graphic' in parts:
if 'bgc' in parts['graphic']:
bgc = parts['graphic']['bgc']
if 'fgc' in parts['graphic']:
fgc = parts['graphic']['fgc']
if 'shape' in parts['graphic']:
shape = parts['graphic']['shape']
# load use functions
if 'useFunc' in parts:
useFunc = parts['useFunc']
if 'useOnFunc' in parts:
useOnFunc = parts['useOnFunc']
if 'customValues' in parts:
customValues = dict(parts['customValues'])
for v in customValues:
if isinstance(customValues[v], tuple):
customValues[v] = list(customValues[v])
if 'ranged' in parts:
ranged = parts['ranged']
graphic = ThingGraphic(bgc, fgc, shape)
return Item(name, prefab.x, prefab.y, description, useFunc, useOnFunc, customValues, ranged, graphic)
class Useable(Thing):
yaml_flag = u'!Useable'
@ -240,6 +352,44 @@ class Useable(Thing):
def use(self, user, gameBase, args) -> float:
pass
def fromPrefab(self, prefab):
parts = prefab.details
# set default values for optional arguments
name = self.name
description = self.description
useFunc = self.useFunc
customValues = dict(self.customValues)
playerx = prefab.x + (self.playerx - self.x)
playery = prefab.y + (self.playery - self.y)
bgc = self.graphic.background
fgc = self.graphic.foreground
shape = self.graphic.shape
if parts != None:
if 'name' in parts:
name = parts['name']
if 'description' in parts:
description = parts['description']
# load graphic
if 'graphic' in parts:
if 'bgc' in parts['graphic']:
bgc = parts['graphic']['bgc']
if 'fgc' in parts['graphic']:
fgc = parts['graphic']['fgc']
if 'shape' in parts['graphic']:
shape = parts['graphic']['shape']
# load use functions
if 'useFunc' in parts:
useFunc = parts['useFunc']
if 'customValues' in parts:
customValues = dict(parts['customValues'])
for v in customValues:
if isinstance(customValues[v], tuple):
customValues[v] = list(customValues[v])
if 'useLocation' in parts:
playerx, playery = parts['useLocation']
graphic = ThingGraphic(bgc, fgc, shape)
return Useable(name, prefab.x, prefab.y, description, useFunc, customValues, playerx, playery, graphic)
class Character(Thing):
defaultGraphic = ThingGraphic('clear', '#000000', 'o')
@ -352,7 +502,6 @@ class NPC(Character, Observer):
parts = CommentedMap()
constructor.construct_mapping(node, parts, True)
# set default values for optional arguments
following = False
minventory = []
mcustomValues = {}
mplayerx, mplayery = parts['location']
@ -381,6 +530,48 @@ class NPC(Character, Observer):
return cls(name = parts['name'], x = parts['location'][0], y = parts['location'][1],
description = parts['description'], behaviors = parts['behaviors'], tempInventory = minventory, customValues = mcustomValues,
playerx = mplayerx, plyery = mplayery, graphic = mgraphic)
def fromPrefab(self, prefab):
parts = prefab.details
# set default values for optional arguments
mname = self.name
mdescription = self.description
minventory = list(self.tempInventory)
mcustomValues = dict(self.customValues)
mbehaviors = dict(self.behaviors)
mplayerx = prefab.x + (self.playerx - self.x)
mplayery = prefab.y + (self.playery - self.y)
bgc = self.graphic.background
fgc = self.graphic.foreground
shape = self.graphic.shape
if prefab != None:
if 'name' in parts:
mname = parts['name']
if 'description' in parts:
mdescription = parts['description']
# load graphic
if 'graphic' in parts:
if 'bgc' in parts['graphic']:
bgc = parts['graphic']['bgc']
if 'fgc' in parts['graphic']:
fgc = parts['graphic']['fgc']
if 'shape' in parts['graphic']:
shape = parts['graphic']['shape']
# load use functions
if 'inventory' in parts:
inventory = parts['inventory']
if 'customValues' in parts:
mcustomValues = dict(parts['customValues'])
for v in mcustomValues:
if isinstance(mcustomValues[v], tuple):
mcustomValues[v] = list(mcustomValues[v])
if 'useLocation' in parts:
playerx, playery = parts['useLocation']
if 'behaviors' in parts:
mbehaviors = dict(parts['behaviors'])
mgraphic = ThingGraphic(bgc, fgc, shape)
return NPC(name = mname, x = prefab.x, y = prefab.y, description = mdescription, behaviors = mbehaviors, tempInventory = minventory, customValues = mcustomValues,
playerx = mplayerx, plyery = mplayery, graphic = mgraphic)
class Door(Thing):
yaml_flag = u'!Door'