And I've been getting into all manner of mess trying to keep track of where the player is, how many times he's been there, whether a passage is usable or not.
[edit]
Let's try that again. Now improved with actual working code.
Code: Select all
init python in navman:
#
# Represents locations on the map. Places the player can visit
#
class Place:
def __init__(self, name, desc, *args, **kw):
self.name = name # name used to form labels
self.desc = desc # human friendly version
self.links = [] # array of connections to other areas.
# Doors, corridors, teleport portals, whatever
self.visit_count = 0 # count how many times the player has been here
# user data, used here to find a key and unlock a door
def add_link(self, link):
self.links.append(link)
def find_link(self, name):
for l in self.links:
if l.there.name == name:
return l
return None
#
# represents the link between two locations.
# may be locked or hidden
#
class Link:
def __init__(self, here, there, locked, hidden):
self.here = here
self.there = there
self.locked = locked
self.hidden = hidden
#
# keeps track of all the places and has functions to determine
# if they're visible or not, and to return a smart label object
# when trying to move
#
class Layout:
def __init__(self, *args, **kw):
self.hash = {}
self.places = []
self.loc = kw.get("start", None)
self.last_loc = None
def add_place(self, place):
self.places.append(place)
self.hash[place.name] = place
self.hash[place.desc] = place
return place
def lookup(self, name):
return self.hash.get(name, None)
def unlock(self, s0, s1):
p0 = self.lookup(s0)
p1 = self.lookup(s1)
l0 = p0.find_link(s1)
l0.locked = False
l1 = p1.find_link(s0)
l1.locked = False
def link_to(self, name):
renpy.log(
"Looking for link from Here ({}) to {}".format(
self.loc, name
)
)
here = self.lookup(self.loc)
if here == None:
return False
l = here.find_link(name)
return l
def change_loc(self, name):
self.last_loc = self.loc
self.loc = name
def go_to(self, name):
l = self.link_to(name)
if l == None:
return NavLabel(self.loc, self.loc, self.loc, self)
if l.hidden:
return NavLabel(self.loc, self.loc, self.loc, self, hidden=True)
return self.loc
if l.locked:
return NavLabel("{}_locked".format(name), self.loc, self.loc, self, locked=True)
return NavLabel(name, name, self.loc, self)
def reachable(self, name):
renpy.log("*** Checking reachability ***")
#
# one thing I want from this is to determine which locations appear on an imagemap
# so we want the current location to be visible. Maybe "visible" would be a better
# name ...
#
if self.loc == name:
return True
l = self.link_to(name)
rv = (l != None)
renpy.log("*** returning {} ***".format(rv))
return rv
#
# This is the smart label. Has a label string to goto,
# plus a pile of other stuff that may come in useful
#
class NavLabel:
def __init__(self, label_str, new_str, old_str, layout, locked=False, hidden=False):
self.label_str = label_str
self.new_str = new_str
self.old_str = old_str
self.new_loc = layout.lookup(new_str)
self.old_loc = layout.lookup(old_str)
self.locked = locked
self.hidden = hidden
self.layout = layout
#
# List of places
#
spec = [
Place( "loadingbay", "Loading Bay" ),
Place( "engineering", "Engineering" ),
Place( "kitchens", "Kitchens" ),
Place( "bar", "Bar" ),
Place( "elite", "Elite Dining" ),
]
#
# create a layout and add in the places
#
layout = Layout(start = "loadingbay")
for p in spec:
layout.add_place(p)
#
# list of links. S1 is "here" and s1 is there.
# links are one way, but get added in pairs so you don't
# need to add them twice. If you want one way doors or
# doors that are only locked from one side, you'll need to
# tweak things a bit
#
# "locked" and "hidden" are optional fields.
# Both default to False, which is probably what you want most of the time.
#
link_list = [
{ "s0" : "loadingbay",
"s1" : "engineering",
"locked" : True,
},
{ "s0" : "loadingbay",
"s1" : "kitchens",
},
{ "s0" : "kitchens",
"s1" : "bar",
},
{ "s0" : "bar",
"s1" : "elite",
},
]
#
# create objects for those links and add them to the places
#
for d in link_list:
p0 = layout.lookup(d["s0"])
p1 = layout.lookup(d["s1"])
locked = d.get("locked", False)
hidden = d.get("hidden", False)
p0.add_link(Link(p0, p1, locked, hidden))
p1.add_link(Link(p1, p0, locked, hidden))
#
# import the navman namespace and set up a style for the meny
#
init python:
import store.navman as navman
style.my_menu_style = Style(style.default)
style.my_menu_style.background = Frame("my_frame.png", 20, 20, 20, 20)
#
# menu screen. The main advantage here is that we make it by looping over the place list.
#
# With a little tweaking it can make image maps and the like as well.
#
screen my_menu:
frame:
style "my_menu_style"
xpadding 40
ypadding 40
xalign 0.02
yalign 0.5
has vbox
for i in navman.spec:
if navman.layout.reachable(i.name):
textbutton(i.desc):
action Return(navman.layout.go_to(i.name))
image black = '#000000'
# The game starts here.
label start:
scene black
label map_loop:
#
# call the screen and get a menu choice
#
call screen my_menu
#
# if the passage wasn't locked, change the location
# and bumpt the visit count
#
if not _return.locked:
$ navman.layout.change_loc(_return.new_str)
$ _return.new_loc.visit_count += 1
#
# now we can jump to the label
#
call expression _return.label_str from _stuffy_funk
#
# and back to the map loop
#
jump map_loop
#
# labels to jump to - the names need to match the Place names
#
label loadingbay:
"loading bay"
return
label engineering:
"engineering"
return
#
# a label for the engineering door while it's locked
#
label engineering_locked:
"the door won't open"
return
label kitchens:
"kitchens"
return
label bar:
"bar"
return
#
# the third time you visit the Elite Dining room
# you spot the engineering room key that was
# staring you in the face the whole time -
# or whatever - this is just an illustration
#
label elite:
"Elite Dining"
if _return.new_loc.visit_count == 3:
"You find a key"
$ _return.layout.unlock("loadingbay", "engineering")
return