Well, I was wrong. I can’t get my book to work. In case someone is willing to look at my pythons, I would be very happy.
I do believe I have managed to make my book clickable, it does show the right icon. It’s just the book that will not open.
I have named my book: s309book. My clickregion: s309clickBook. In AlcScript I have set the pythonfile to be Pahts.
I have named my py-files: s309Journal, s309PageDefs and s309BookGuI.
When I want to add the files to the Paths.pak I get the option to decompile. I have tried both versions. No errors come when I press No to decompile. Pressing yes gives errors (syntax error glue thing) for several of the other py files in the Pahts pak. Not just mine. Referring to a post made by D’lanor , the glue is correct as far as I can see.
I have deleted the age and reinstalled it several times. I also tried Roberts link with the paging. That ended really badly. When I tested it before I loaded up my shell, I kept panic-linking approaching Roberts shell. After I had updated my shell with my things, there where black holes where the shells were supposed to be. So I deleted that version and went back to the version 0.8.c.
I now have the shells back, but when clicking on Roberts door nothing happens. (I seem to remember that some lights came on and I could pull the handle last time)
s309Journal The Defs309Journals is a name I just made up and put in to this file. Hope that is correct.
- Code: Select all
# # Examples of journals. DefFontTest shows the fonts available in the offline version.
Defs309Journals = '<font size=24 face=Courier><p align=center>Journal Test\n\n<font size=20 face=Atrus color=800000><p align=left>ATRUS\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=20 face=Uru color=008000><p align=left>URU\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=14 face=Nick color=000080><p align=left>NICK\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=14 face=Sam color=808000><p align=left>SAM\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=14 face=Tricia color=008080><p align=left>TRICIA\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=14 face=Michelle color=800080><p align=left>MICHELLE\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=12 face=DniFontDniHand color=000000><p align=left>DNI HAND\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9\n\n<font size=18 face=Yeesha color=404040><p align=left>YEESHA\nThe quick brown fox jumped over the lazy dog.\n0 1 2 3 4 5 6 7 8 9'
s309PageDefs The BookPages and linkDestination puzzles me a bit. I'm not sure what is correct to put there. The hint at bookages tells me to look at the linkDestination. But that only tells me to put in the same name as in BookPages
- Code: Select all
# # For each occurance of *YourAge* and *YourTexture* you have to replace this with
# the actual name of your age and your textures.
from Plasma import *
from PlasmaNetConstants import *
# Due to their length journal texts are usually stored in external Python files.
# The line below imports them. Remove this line if you do not use external journals.
from s309Journals import *
# Variables that can be used in BookPages:
PageStart = '<pb>'
ImgStart = '<img src="'
TransImgStart = '<img opacity=0.7 src="'
ImgEnd = '" align=center link=%d blend=alpha>'
ImgEndNoLink = '" align=center blend=alpha>'
AlignCenter = '<p align=center>'
AlignLeft = '<p align=left>'
AlignRight = '<p align=right>'
# Retrieve local player name in case you want to fake a "personal" note
plyrName = PtGetLocalPlayer().getPlayerName()
###############################################################################
# AgeBooks Dictionary Section: #
# 1 = same names as the clickable book objects! #
# 2 = book cover and margin #
# 3 = main font #
# 4 = start book open or closed. 0 closed book, 1 open book #
# 5 = force owned setting. 0 off, 1 on #
# 6 = book GUI. 'BkBook' or 'bkNotebook' #
# 7 = width #
# 8 - height #
# #
# Notes: - The cover can have the same texture as the book object itself. #
# - The main font can be changed later in the BookPages definition. #
# If you don't need a main font (because you are changing it later), #
# you can set an empty string. #
# - force owned: If set to 1 the code checks if the original book has #
# been found. A player who does not own the age will not see the #
# linking panel. If you need this restriction set force owned to 1. #
# - the 'bkBahroRockBook' GUI should work as well but it may not be a #
# good idea to use it with this multi-page template. #
###############################################################################
AgeBooks = {'s309book': ('<cover src="s309bookcover"><margin right=32 left=32>', '<font size=12 face=Arial color=000000>', 0, 0,)}
###############################################################################################
# BookPages Dictionary Section: #
# 1 = Same names as link destinations! #
# 2 = The page layout: for linking books insert the name of your linking panel image here. #
# This can be a seperate texture in your age prp file on a hidden Blender object. #
# (or use PRP Explorer to add a plain texture to the prp without modeling an object) #
# Once you get the hang of this you can mix and match layouts into your pages. #
# #
# Notes: - AlignCenter is used to center text, for example to place below a linking panel. #
# - Use ImgEndNoLink to add images without a hotspot. #
###############################################################################################
BookPages = {'s309Journals': (PageStart + Defs309Journals)}
###############################################################################
# LinkDestinations Dictionary Section: #
# 1 = Same names as book pages! #
# 2 = age name #
# 3 = spawnpoint #
# 4 = spawnpoint title #
# 5 = linkingrule #
# #
# Notes: - Variables for journals are dummies and must be set to None. #
# - Spawnpoint title None is only allowed for LinkInPointDefault #
# (although it would be better to set it to 'Default') #
# CleftFissureDrop in this example will fail due to a missing title #
# (the correct title is 'FissureDrop') #
# - You can tie special actions to linking panels or other journal #
# images by defining only the age name. The other definitions must #
# be set to None (see 'CleftSpecial') #
###############################################################################
LinkDestinations = {'s309Journals': (None, None, None, None)}
s309BookGUI
- Code: Select all
###########################################
# #
# Dynamic Book Template v3.0 by D'Lanor #
# #
###########################################
# For each occurance of *YourAge* you have to replace this with the actual name of your age.
from Plasma import *
from PlasmaTypes import *
from PlasmaKITypes import *
from PlasmaNetConstants import *
import xLinkingBookDefs
actClickableObject = ptAttribActivator(1, 'Act: Clickable Object')
ObjectMsg = ptAttribString(2, 'Object String')
### DO NOT CHANGE THESE 2 VARIABLES ###
ourBook = None
bkLinks = []
### CHANGE THE GLOBAL CONSTANTS BELOW TO FIT YOUR AGE ######################################
# #
# modPageDefs: Replace *YourAge*PageDefs with the name of the module that contains your #
# page definitions. Do not remove the quotes! #
# ageBooks: These are your clickable objects. They must be defined in *YourAge*PageDefs #
# in the AgeBooks Dictionary Section by the same name(s). #
# bookPages: Names in bookPages must be defined in the *YourAge*PageDefs file under #
# BookPages. An ageBook can have multiple bookPages as long as they are #
# enclosed together between the same square brackets. #
# Please keep the nesting structure [square brackets] intact! #
# #
# If there are multiple books in an age the code will find the right one automagically. #
# You can add as many books as you like. Just define them in the global variables ageBooks #
# and bookPages. The order is important here. The first book will be matched to the first #
# page list, the second book to the second page list etc. #
############################################################################################
modPageDefs = __import__('s309PageDefs')
ageBooks = ['s309book']
bookPages = [[s309Journals]]
class s309BookGUI(ptModifier,):
def __init__(self):
ptModifier.__init__(self)
self.version = '3.0'
print ('__init__%s v.%s' % (self.__class__.__name__, self.version))
def OnNotify(self, state, id, events):
print ('%s: OnNotify called' % self.__class__.__name__)
if ((id == actClickableObject.id) and state):
print ('Someone clicked on object %s' % ObjectMsg.value)
if PtWasLocallyNotified(self.key):
print 'It was you'
for (a, b,) in zip(ageBooks, bookPages):
print ('Trying book %s with page(s) %s' % (a, b))
if (ObjectMsg.value == a):
print 'Match found! Start opening book...'
self.IOpenBook(a, b)
break
else:
print 'No match'
else:
for event in events:
if ((event[0] == PtEventType.kBook) and PtWasLocallyNotified(self.key)):
#print('BookNotify: event=%d, id=%d' % (event[1], event[2]))
if (event[1] == PtBookEventTypes.kNotifyImageLink):
print ('BookNotify: Linking panel id=%d, event=%d' % (event[2], event[1]))
ourBook.hide()
if (event[2] == 0):
print 'Warning: No link id, define proper link destination or use non-clickable image'
elif (event[2] >= xLinkingBookDefs.kFirstLinkPanelID):
for i in range(0, len(bkLinks)):
if (event[2] == bkLinks[i][0]):
try:
self.IlinkToAge(bkLinks[i][1], bkLinks[i][2], bkLinks[i][3], bkLinks[i][4], bkLinks[i][5])
except Exception, detail:
print ('ERROR: Unable to initialize link - %s' % detail)
break
elif (event[1] == PtBookEventTypes.kNotifyShow):
print ('BookNotify: Show book, event=%d' % event[1])
PtToggleAvatarClickability(0)
elif (event[1] == PtBookEventTypes.kNotifyHide):
print ('BookNotify: Hide book, event=%d' % event[1])
PtToggleAvatarClickability(1)
elif (event[1] == PtBookEventTypes.kNotifyNextPage):
print ('BookNotify: To next page %d, event=%d' % (ourBook.getCurrentPage(), event[1]))
elif (event[1] == PtBookEventTypes.kNotifyPreviousPage):
print ('BookNotify: To previous page %d, event=%d' % (ourBook.getCurrentPage(), event[1]))
elif (event[1] == PtBookEventTypes.kNotifyCheckUnchecked):
print ('BookNotify: Relto page toggle, event=%d' % event[1])
elif (event[1] == PtBookEventTypes.kNotifyClose):
print ('BookNotify: Close book, event=%d' % event[1])
def IOpenBook(self, ageBook, bkPages = None):
global ourBook
global bkLinks
print ('%s: IOpenBook: Page(s) requested %s' % (self.__class__.__name__, bkPages))
if (type(bkPages) == type(None)):
print 'ERROR: no pages defined'
return
if (not (ageBook in modPageDefs.AgeBooks)):
print ('ERROR: Definition %s does not exist in AgeBooks' % ageBook)
return
bkParams = modPageDefs.AgeBooks[ageBook]
(bkCover, bkFont, startOpen, forceOwned, bookGUI, width, height,) = bkParams
PageDef = (bkCover + bkFont)
if (not startOpen):
if (not self.IsThereACover(PageDef)):
print 'Warning: Missing cover, forcing book open'
startOpen = 1
PageCount = xLinkingBookDefs.kFirstLinkPanelID
bkLinks = []
for bkPage in bkPages:
if (not (bkPage in modPageDefs.LinkDestinations)):
print ('Warning: %s skipped, definition does not exist in LinkDestinations' % bkPage)
continue
pgParams = modPageDefs.LinkDestinations[bkPage]
(bkAge, spawnPoint, spTitle, linkRule,) = pgParams
alink = 1
if ((type(bkAge) != type(None)) and forceOwned):
print ('Ownership check for %s book' % bkAge)
vault = ptVault()
ainfo = ptAgeInfoStruct()
ainfo.setAgeFilename(bkAge)
alink = vault.getOwnedAgeLink(ainfo)
if alink:
print ('Showing %s, link destination %s' % (bkPage, bkAge))
if (type(bkAge) != type(None)):
t = (PageCount, bkPage, bkAge, spawnPoint, spTitle, linkRule)
bkLinks.append(t)
PageDef = ((PageDef + (modPageDefs.BookPages[bkPage] % PageCount)) + '<pb>')
else:
PageDef = ((PageDef + modPageDefs.BookPages[bkPage]) + '<pb>')
PageCount = (PageCount + 1)
else:
print ('No owner of age %s so we are not showing %s' % (bkAge, bkPage))
if (PageCount == xLinkingBookDefs.kFirstLinkPanelID):
print 'No pages created...'
return
else:
TotalCount = (PageCount - xLinkingBookDefs.kFirstLinkPanelID)
print ('%d item(s) created, linking page(s): %d' % (TotalCount, len(bkLinks)))
PageDef = PageDef[:-4]
ourBook = ptBook(PageDef, self.key)
ourBook.setSize(width, height)
ourBook.setGUI(bookGUI)
ourBook.show(startOpen)
def IsThereACover(self, bookHtml):
idx = bookHtml.find('<cover')
if (idx >= 0):
return 1
return 0
def IlinkToAge(self, bookPage, ageName, spawnPoint, spTitle, linkRule = PtLinkingRules.kBasicLink):
print ('%s: ILinkToAge: Link request from page %s to age %s' % (self.__class__.__name__, bookPage, ageName))
if ((type(ageName) == type(None)) or (len(ageName) == 0)):
print 'ERROR: Cannot link to age without name'
return
if ((type(spawnPoint) == type(None)) or (len(spawnPoint) == 0)):
print 'No spawnpoint defined, checking special actions...'
self.IDoSpecialAction(bookPage)
return
als = ptAgeLinkStruct()
ainfo = ptAgeInfoStruct()
ainfo.setAgeFilename(ageName)
ainfo.setAgeInstanceName(self.IConvertAgeInstanceName(ageName))
als.setAgeInfo(ainfo)
if ((type(spTitle) == type(None)) or (len(spTitle) == 0)):
if ((linkRule == PtLinkingRules.kOriginalBook) or PtIsSinglePlayerMode()):
#################################################################################
# Linkingrule kOriginalBook writes spawnpoint and title to the agelink node, #
# so we must make absolutely sure that a proper title is given! #
# In singleplayer mode all linkingrules behave like kOriginalBook, no matter #
# which linkingrule is set in the definition. #
#################################################################################
if (spawnPoint == 'LinkInPointDefault'):
spTitle = 'Default'
#################################################################################
# We did not define a spawnpoint title, but since the spawnpoint is the default #
# it is safe to continue and write it to the agelink node with default title. #
#################################################################################
else:
print 'Warning: Empty spawnpoint title not allowed, check your link destinations!'
return
else:
print 'Empty spawnpoint title allowed, continue linking'
spTitle = ''
als.setLinkingRules(linkRule)
spPoint = ptSpawnPointInfo(spTitle, spawnPoint)
als.setSpawnPoint(spPoint)
linkMgr = ptNetLinkingMgr()
linkMgr.linkToAge(als)
print ('Linking to age %s, spawnpoint %s with title %s, using linkingrule %d' % (ageName, spawnPoint, spTitle, linkRule))
def IConvertAgeInstanceName(self, ageName):
#########################################################################################################################
# Optional: You can add a friendly name to this list for the age you link to. This is the name that shows up in the KI. #
# Ahra Pahts and Relto are used here only as examples. #
# Some Cyan age names are converted to friendly names in the KI but we cannot expect the KI to do that for user ages. #
# Beware: Age instance names are written to the vault if the kOriginalBook rule is used. That will happen whether you #
# set a name here or not. And it would happen regardless of this function. #
# By default the age instance name is the same as the age name. #
# btw, if you plan to link to Cyan ages you should set the correct age instance name here. Correct? You figure it out! #
#########################################################################################################################
if (ageName == 'Personal'):
return 'Relto'
if (ageName == 'Pahts'):
return 'Ahra Pahts'
return ageName
def IDoSpecialAction(self, bookPage):
#######################################################
# Replace *YourPage* with the bookPage that contains #
# the clickable image triggering the special action. #
#######################################################
if (bookPage == '*YourPage*'):
print ('Special action found for %s' % bookPage)
# Do some special action here
else:
print 'No special actions found'
glue_cl = None
glue_inst = None
glue_params = None
glue_paramKeys = None
try:
x = glue_verbose
except NameError:
glue_verbose = 0
def glue_getClass():
global glue_cl
if (glue_cl == None):
try:
cl = eval(glue_name)
if issubclass(cl, ptModifier):
glue_cl = cl
elif glue_verbose:
print ('Class %s is not derived from modifier' % cl.__name__)
except NameError:
if glue_verbose:
try:
print ('Could not find class %s' % glue_name)
except NameError:
print 'Filename/classname not set!'
return glue_cl
def glue_getInst():
global glue_inst
if (type(glue_inst) == type(None)):
cl = glue_getClass()
if (cl != None):
glue_inst = cl()
return glue_inst
def glue_delInst():
global glue_inst
global glue_cl
global glue_paramKeys
global glue_params
if (type(glue_inst) != type(None)):
del glue_inst
glue_cl = None
glue_params = None
glue_paramKeys = None
def glue_getVersion():
inst = glue_getInst()
ver = inst.version
glue_delInst()
return ver
def glue_findAndAddAttribs(obj, glue_params):
if isinstance(obj, ptAttribute):
if glue_params.has_key(obj.id):
if glue_verbose:
print 'WARNING: Duplicate attribute ids!'
print ('%s has id %d which is already defined in %s' % (obj.name,
obj.id,
glue_params[obj.id].name))
else:
glue_params[obj.id] = obj
elif (type(obj) == type([])):
for o in obj:
glue_findAndAddAttribs(o, glue_params)
elif (type(obj) == type({})):
for o in obj.values():
glue_findAndAddAttribs(o, glue_params)
elif (type(obj) == type(())):
for o in obj:
glue_findAndAddAttribs(o, glue_params)
def glue_getParamDict():
global glue_paramKeys
global glue_params
if (type(glue_params) == type(None)):
glue_params = {}
gd = globals()
for obj in gd.values():
glue_findAndAddAttribs(obj, glue_params)
glue_paramKeys = glue_params.keys()
glue_paramKeys.sort()
glue_paramKeys.reverse()
return glue_params
def glue_getClassName():
cl = glue_getClass()
if (cl != None):
return cl.__name__
if glue_verbose:
print ('Class not found in %s.py' % glue_name)
return None
def glue_getBlockID():
inst = glue_getInst()
if (inst != None):
return inst.id
if glue_verbose:
print ('Instance could not be created in %s.py' % glue_name)
return None
def glue_getNumParams():
pd = glue_getParamDict()
if (pd != None):
return len(pd)
if glue_verbose:
print ('No attributes found in %s.py' % glue_name)
return 0
def glue_getParam(number):
pd = glue_getParamDict()
if (pd != None):
if (type(glue_paramKeys) == type([])):
if ((number >= 0) and (number < len(glue_paramKeys))):
return pd[glue_paramKeys[number]].getdef()
else:
print ('glue_getParam: Error! %d out of range of attribute list' % number)
else:
pl = pd.values()
if ((number >= 0) and (number < len(pl))):
return pl[number].getdef()
elif glue_verbose:
print ('glue_getParam: Error! %d out of range of attribute list' % number)
if glue_verbose:
print 'GLUE: Attribute list error'
return None
def glue_setParam(id, value):
pd = glue_getParamDict()
if (pd != None):
if pd.has_key(id):
try:
pd[id].__setvalue__(value)
except AttributeError:
if isinstance(pd[id], ptAttributeList):
try:
if (type(pd[id].value) != type([])):
pd[id].value = []
except AttributeError:
pd[id].value = []
pd[id].value.append(value)
else:
pd[id].value = value
elif glue_verbose:
print "setParam: can't find id=",
print id
else:
print 'setParma: Something terribly has gone wrong. Head for the cover.'
def glue_isNamedAttribute(id):
pd = glue_getParamDict()
if (pd != None):
try:
if isinstance(pd[id], ptAttribNamedActivator):
return 1
if isinstance(pd[id], ptAttribNamedResponder):
return 2
except KeyError:
if glue_verbose:
print ('Could not find id=%d attribute' % id)
return 0
def glue_isMultiModifier():
inst = glue_getInst()
if isinstance(inst, ptMultiModifier):
return 1
return 0
def glue_getVisInfo(number):
pd = glue_getParamDict()
if (pd != None):
if (type(glue_paramKeys) == type([])):
if ((number >= 0) and (number < len(glue_paramKeys))):
return pd[glue_paramKeys[number]].getVisInfo()
else:
print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
else:
pl = pd.values()
if ((number >= 0) and (number < len(pl))):
return pl[number].getVisInfo()
elif glue_verbose:
print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
if glue_verbose:
print 'GLUE: Attribute list error'
return None
«Borders? I have never seen one, but I have heard they exist in the minds of some people.»
(Thor Heyerdahl)