tsahvkotsahBookGUI.py
Code: Select all
#########################################
# #
# Dynamic Book Template v2 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 PlasmaNetConstants import *
import xLinkingBookDefs
import tsahvkotsahPageDefs
actClickableObject = ptAttribActivator(1, 'Act: Clickable Object')
ObjectMsg = ptAttribString(2, 'Object String')
### DO NOT CHANGE THESE ###
ourBook = None
bkLinks = []
### CHANGE THE GLOBAL CONSTANTS BELOW TO FIT YOUR AGE ######################################
# #
# ageBooks: These are your clickable objects.They must be defined in tsahvkotsahPageDefs #
# in the AgeBooks Dictionary Section by the same name(s). #
# bookPages: Names in bookPages must be defined in the tsahvkotsahPageDefs 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. #
############################################################################################
ageBooks = ['GeneratorJournal','Dummy']
bookPages = [['genJournal01', 'genJournal02'],['Dummy']]
class tsahvkotsahBookGUI(ptModifier,):
def __init__(self):
ptModifier.__init__(self)
self.version = '2'
print ('__init__%s v.%s' % (self.__class__.__name__, self.version))
def OnNotify(self, state, id, events):
global ourBook
global bkLinks
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 ('Try book %s with page(s) %s' % (a, b))
if (ObjectMsg.value == a):
print 'Match found! start opening...'
self.IOpenBook(a, b)
break
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):
if (event[2] >= xLinkingBookDefs.kFirstLinkPanelID):
print('BookNotify: hit linking panel %s' % event[2])
ourBook.hide()
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])
except Exception, detail:
print('ERROR: Unable to initialize link - %s' % (detail))
break
elif (event[1] == PtBookEventTypes.kNotifyShow):
print('Show Book')
PtSendKIMessage(kDisableKIandBB, 0)
elif (event[1] == PtBookEventTypes.kNotifyHide):
print('Hide Book')
PtSendKIMessage(kEnableKIandBB, 0)
elif (event[1] == PtBookEventTypes.kNotifyNextPage):
print('To Next Page %d' % (ourBook.getCurrentPage()))
elif (event[1] == PtBookEventTypes.kNotifyPreviousPage):
print('To Previous Page %d' % (ourBook.getCurrentPage()))
elif (event[1] == PtBookEventTypes.kNotifyCheckUnchecked):
print('Relto Page Toggled')
elif (event[1] == PtBookEventTypes.kNotifyClose):
print('Close Book')
def IOpenBook(self, ageBook, bkPages = None):
global ourBook
global bkLinks
print ('%s: IOpenBook: Page request for %s' % (self.__class__.__name__, bkPages))
if (type(bkPages) == type(None)):
print 'ERROR: no pages defined'
return
if (not ageBook in tsahvkotsahPageDefs.AgeBooks):
print ('ERROR: Definition %s does not exist' % ageBook)
return
bkParams = tsahvkotsahPageDefs.AgeBooks[ageBook]
(bkCover, bkFont, startOpen, forceOwned,) = 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 tsahvkotsahPageDefs.LinkDestinations):
print ('Skipping %s because definition does not exist' % bkPage)
continue
pgParams = tsahvkotsahPageDefs.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 page for %s' % bkAge)
if (type(bkAge) != type(None)):
t = (PageCount, bkAge, spawnPoint, spTitle, linkRule)
bkLinks.append(t)
PageDef = PageDef + tsahvkotsahPageDefs.BookPages[bkPage] % (PageCount) + '<pb>'
else:
PageDef = PageDef + tsahvkotsahPageDefs.BookPages[bkPage] + '<pb>'
PageCount = PageCount + 1
else:
print ('No %s book on your shelf so we are not showing the link' % bkAge)
if (PageCount == xLinkingBookDefs.kFirstLinkPanelID):
print 'No pages created...'
return
print ('Linking pages created: %d' % (len(bkLinks)))
PageDef = PageDef[:-4]
ourBook = ptBook(PageDef, self.key)
ourBook.setSize(1.0, 1.0)
ourBook.setGUI('BkBook')
ourBook.show(startOpen)
def IsThereACover(self, bookHtml):
idx = bookHtml.find('<cover')
if (idx >= 0):
return 1
return 0
def IlinkToAge(self, ageName, spawnPoint, theTitle = None, linkRule = PtLinkingRules.kBasicLink):
print ('%s: ILinkToAge: Link request for age %s' % (self.__class__.__name__, ageName))
als = ptAgeLinkStruct()
ainfo = ptAgeInfoStruct()
ainfo.setAgeFilename(ageName)
ainfo.setAgeInstanceName(self.IConvertAgeInstanceName(ageName))
als.setAgeInfo(ainfo)
if (type(theTitle) != type(None)):
spTitle = theTitle
else:
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 'Empty spawnpoint title not allowed, check your linking page definitions!'
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
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
tsahvkotsahPageDefs.py
Code: Select all
# For each occurance of tsahvkotsah 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 tsahvkotsahJournals import *
# General layout elements that can be used in BookPages:
plyrName = PtGetLocalPlayer().getPlayerName() # Retrieves local player name in case you want to fake a "personal" note
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>'
###############################################################################
# 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 #
# #
# Notes: - The cover can have the same texture as the book object itself. #
# - You can set the book cover to an empty string if startOpen is 1. #
# - 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. #
###############################################################################
AgeBooks = {'GeneratorJournal': ('<cover src=""><margin right=32 left=32>', '<font size=12 face=Atrus color=000000>', 1, 0),
'Dummy': ('', '', 1, 0)}
###############################################################################################
# BookPages Dictionary Section: #
# 1 = Same names as used under 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 not used by a Blender object #
# (not sure if Blender handles that: use PRP Explorer). #
# 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. #
###############################################################################################
BookPages = {'BevinBalcony01': (PageStart + ImgStart + 'xLinkPanelBevinBalc01*1#0.hsm' + ImgEnd + AlignCenter),
'CleftDefault': (PageStart + ImgStart + 'xLinkPanelCleftDesert*1#0.hsm' + ImgEnd + AlignCenter),
'CleftDrop': (PageStart + ImgStart + 'xLinkPanelTomahnaDesert*1#0.hsm' + ImgEnd + '<font size=26 face=Uru color=221166>' + AlignCenter + 'Don\'t even think about it'),
'KadishPyramid': (PageStart + ImgStart + 'xLinkPanelKadishGlowBalc*1#0.hsm' + ImgEnd + AlignCenter), 'FontTest': (PageStart + DefFontTest), 'genJournal01': (PageStart + (DefgenJournal01)), 'genJournal02': (PageStart + (DefgenJournal02)),
'Dummy': (PageStart + (DefDummy))}
###############################################################################
# LinkDestinations Dictionary Section: #
# 1 = any name (this is used to call the definitions) #
# 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' in that case). #
# - CleftDrop in this example will deliberately fail (see above). #
###############################################################################
LinkDestinations = {'BevinBalcony01': ('Neighborhood', 'LinkInPointBevinBalcony01', 'nb01BevinBalcony01', PtLinkingRules.kOriginalBook),
'CleftDefault': ('Cleft', 'LinkInPointDefault', None, PtLinkingRules.kOriginalBook),
'CleftDrop': ('Cleft', 'LinkInPointFissureDrop', None, PtLinkingRules.kOriginalBook),
'KadishPyramid': ('Kadish', 'LinkInPointGlowRmBalcony', 'kdshGlowRmBalcony', PtLinkingRules.kOwnedBook),
'FontTest': (None, None, None, None),
'genJournal01': (None, None, None, None),
'genJournal02': (None, None, None, None)}
tsahvkotsahJournals.py
Code: Select all
# Examples of journals. DefFontTest shows the fonts available in the offline Uru version.
DefFontTest = '<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'
DefgenJournal01='<font size=30 face=Atrus><p align=center>Generator Design notes\n\n<p align=left>\tThe scource generator here on this island is unlike anything else that I have ever seen. It uses the power of magnetics to turn it\'s inner mechanism unlike the normal forces. (Water, wind, steam, ect.)\n\tThe magnetic force is caused by loadstones that generate a magnetic flow. Normaly this flow is very weak, however, if you put an electrical force through the stones, the flow streagthens 100 fold. Tests provide that the charge lasts for about 2-3 years. Further experimentation is required before I am able to understand fully how these stones work.\n\tThese stones are placed in a variation that makes the flow move in a sideways eight, or infinity symbol, motion, and with the flow, it pulls along stones that are connected to poles that are geared together to turn the generator\'s inner mechanism. The electrical current to increase the magneticism of the stones is provided by a turn crank that is attached to small magnet stones inside of a copper wire coil. Wires extruding from the coil pass through the loadstones.'
DefgenJournal02='<font size=30 face=Atrus><p align=center>Operation Guide\n\n<p align=left>The generator itself is mainly self-efficient, though you have to recharge the loadstones if the flow gets to low. To do so, the process is described in these highly scientific steps:\n\t\t1.) Turn the crank.\n\t\t2.) Step back and let the generator do its thing.\n\n\n\n\t\t\t\tDah\'kree'
DefDummy='Dummy.'