Dynamic Book Template (version 4.1)

Help bring our custom Ages to life! Share tips and tricks, as well as code samples with other developers.

Dynamic Book Template (version 4.1)

Postby D'Lanor » Sat Apr 11, 2009 11:05 am

Here is a version 4.1 of my book template. It can be used for both linking books and journals. The first version of this template was included in my test age Prad which was released for a short period through UAM in 2005. Since then I have been adding bits to it from time to time.

Since this is a template all you have to do is define your variables and it will automagically generate the pages of the book. You can mix and match multiple linking pages and journals into the same book in any order you like. The template supports multiple books (clickable objects).

New in version 4.1
  • Added example for animated linking panels
  • Better Uru version check (for public ages)
New in version 4.0
  • Avatar link animations
  • Child age link properly implemented
  • Public ages are now supported
Changes in version 3.0
  • Notebook GUI implemented
  • Book size implemented
  • Linking panels or other clickable images can also be used for other actions than linking
  • Easier customizing: *YourAge*PageDefs only needs to be replaced once now
For each Python file you have to replace *YourAge* in the filename and in the code with the actual name of your age. I left comments in the code to explain why I did things the way I did.


*YourAge*BookGUI.py
This is the python file that the Alcscript of your clickable object points to. The main variables to adapt here are: modPageDefs, ageBooks, bookPages. For advanced options you will also have to adapt the variables parentAge, kLinkDelay, uruVersion or the functions IConvertAgeInstanceName and IDoSpecialAction (see comments).

Code: Select all
###########################################
#                                         #
#  Dynamic Book Template v4.1 by D'Lanor  #
#                                         #
###########################################

# Change each occurrence of *YourAge* to the actual name of your age.
# Do the same with the file names.

from Plasma import *
from PlasmaTypes import *
from PlasmaKITypes import *
from PlasmaNetConstants import *
import xLinkingBookDefs
actClickableObject = ptAttribActivator(1, 'Act: Clickable Object')
strObject = ptAttribString(2, 'Object String')
Behavior = ptAttribBehavior(3, 'Avatar link animation (optional)')

### DO NOT CHANGE THESE VARIABLES/CONSTANTS! ###
ourBook = None
bkLinks = []
ageLinkStruct = None
kLinkID = 1
publicAges = []
kPublicAgeLink = 6
kPublicAgesMOUL = ['city',
 'Neighborhood',
 'Neighborhood02',
 'GreatTreePub',
 'GuildPub-Cartographers',
 'GuildPub-Greeters',
 'GuildPub-Maintainers',
 'GuildPub-Messengers',
 'GuildPub-Writers',
 'philRelto',
 'Kveer']

### CHANGE THE GLOBAL CONSTANTS BELOW TO FIT YOUR AGE ######################################
#                                                                                          #
# modPageDefs: Replace *YourAge*PageDefs with the name of the module that contains your    #
#              page definitions.                                                           #
# 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.                         #
#              Always keep the nesting structure [[double square brackets]] intact!        #
# parentAge    If you are using the kChildAgeBook linking rule you can set a parent age.   #
#              Child ages are only useful for ages which have multiple owners (currently   #
#              only Neighborhood!). All parent age owners share the same instance of the   #
#              child age. Using any other parent age than Neighborhood makes no sense.     #
# kLinkDelay   Delay for the optional avatar link animation to finish. You may have to     #
#              tweak it since 3.5 is an estimate.                                          #
# vOpenSource  For future Uru Open Source support. For now keep this set to false.         #
#                                                                                          #
# 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 = '*YourAge*PageDefs'
ageBooks = ['Journal01', 'Journal02']
bookPages = [['PradJournal', 'CleftSpecial'], ['FontTest']]
parentAge = 'Neighborhood'
kLinkDelay = 3.5
vOpenSource = false

class *YourAge*BookGUI(ptModifier,):

    def __init__(self):
        ptModifier.__init__(self)
        self.version = '4.1'
        self.me = self.__class__.__name__
        self.PageDefs = __import__(modPageDefs)
        print ('__init__%s v.%s' % (self.me, self.version))



    def OnNotify(self, state, id, events):
        if ((id == actClickableObject.id) and state):
            print ('%s: OnNotify: Someone clicked on object %s' % (self.me, strObject.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 (strObject.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)):
                    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])
                elif (event[0] == kVariableEvent):
                    AvatarID = int(event[3])
                    Avatar = ptSceneobject(PtGetAvatarKeyFromClientID(AvatarID), self.key)
                    print ('Notify: Avatar %d started to link, show animation' % AvatarID)
                    Behavior.run(Avatar)




    def OnTimer(self, id):
        if (id == kLinkID):
            if (type(ageLinkStruct) != type(None)):
                print ('%s: OnTimer: Really linking now...' % self.me)
                linkMgr = ptNetLinkingMgr()
                linkMgr.linkToAge(ageLinkStruct)



    def gotPublicAgeList(self, ages):
        global publicAges
        try:
            for age in ages:
                publicAges.append(age[0])

        except IndexError:
            pass


    def IOpenBook(self, ageBook, bkPages = None):
        global ourBook
        global bkLinks
        print ('%s: IOpenBook: Page(s) requested %s' % (self.me, bkPages))
        if (type(bkPages) == type(None)):
            print 'ERROR: no pages defined'
            return
        if (not (ageBook in self.PageDefs.AgeBooks)):
            print ('ERROR: Definition %s does not exist in AgeBooks' % ageBook)
            return
        bkParams = self.PageDefs.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 self.PageDefs.LinkDestinations)):
                print ('Warning: %s skipped, definition does not exist in LinkDestinations' % bkPage)
                continue
            pgParams = self.PageDefs.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 + (self.PageDefs.BookPages[bkPage] % PageCount)) + '<pb>')
                else:
                    PageDef = ((PageDef + self.PageDefs.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)
        if len(bkLinks):
            ageList = []
            for i in range(0, len(bkLinks)):
                if (bkLinks[i][5] == kPublicAgeLink):
                    ageList.append(bkLinks[i][2])

            if len(ageList):
                self.IGetPublicAges(ageList)



    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):
        global ageLinkStruct
        print ('%s: ILinkToAge: Link request from page %s to age %s' % (self.me, 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 = ''
        if (linkRule == PtLinkingRules.kChildAgeBook):
            als.setParentAgeFilename(parentAge)
        elif (linkRule == kPublicAgeLink):
            if (not PtIsSinglePlayerMode()):
                if (not len(publicAges)):
                    print 'No public ages found, link aborted'
                    return
                # remove and completely replace the current age link structure
                als = None
                # make new list without any other ages
                ageInstances = []
                for i in range(0, len(publicAges)):
                    if (publicAges[i].getAgeFilename() == ageName):
                        ageInstances.append(publicAges[i])

                # get age link structure from remaining age instance(s)
                if len(ageInstances):
                    als = self.IGetPublicLink(ageInstances)
                if (type(als) == type(None)):
                    print 'Missing age link structure, link aborted'
                    return
            # put back the proper linking rule: never pass kPublicAgeLink to the server!
            linkRule = PtLinkingRules.kBasicLink
        als.setLinkingRules(linkRule)
        spPoint = ptSpawnPointInfo(spTitle, spawnPoint)
        als.setSpawnPoint(spPoint)
        ageLinkStruct = als
        print ('Linking to age %s, spawnpoint %s with title %s, using linkingrule %d' % (ageName, spawnPoint, spTitle, linkRule))
        if (type(Behavior.value) != type(None)):
            # workaround... why doesn't netForce work here?
            myID = PtGetClientIDFromAvatarKey(PtGetLocalAvatar().getKey())
            note = ptNotify(self.key)
            note.clearReceivers()
            note.addReceiver(self.key)
            note.setActivate(1)
            note.addVarNumber('Avatar', myID)
            note.send()
            PtAtTimeCallback(self.key, kLinkDelay, kLinkID)
        else:
            PtAtTimeCallback(self.key, 0.1, kLinkID)



    def IGetPublicAges(self, ageList):
        global publicAges
        print ('%s: IGetPublicAges: %s' % (self.me, ageList))
        publicAges = []
        if (not self.HasPublicAges()):
            print 'ERROR: Public ages not supported in this Uru version!'
            return
        if vOpenSource:
          ################################################################################
          # Technically only city, Neighborhood02 and GreatTreePub were true public ages #
          # in MOUL (apart from public neighborhoods). The others had hard coded GUIDs!  #
          # These are: GuildPub-Cartographers, GuildPub-Greeters, GuildPub-Maintainers,  #
          # GuildPub-Messengers, GuildPub-Writers, philRelto and Kveer.                  #
          # GUIDs are normally generated by the vault. This means that for Open Source   #
          # the hard coded stuff will have to be ditched in favor of public ages.        #
          #                                                                              #
          # Kveer and city also had child age instances. Use the kChildAgeBook rule to   #
          # link to a child age.                                                         #
          ################################################################################
            for age in ageList:
                PtGetPublicAgeList(age, self)
                if (age not in kPublicAgesMOUL):
                    print ('Warning: Age %s is usually not public in MOUL Open Source' % age)
        else:
            for age in ageList:
                PtGetPublicAgeList(age, self)
                if ((age != 'city') and (age != 'Neighborhood')):
                    print ('Warning: Age %s is usually not public in UU' % age)



    def IGetPublicLink(self, instances, highest = 0):
      ############################################################################
      # If there are multiple public instances get the one with the lowest GUID! #
      # This is important to make everyone end up in the same instance.          #
      # In UU for example the city had 5 public instances. The lowest was the    #
      # Nexus city instance. Most ages have a single public instance though.     #                                             
      # This function can also get the highest GUID but we won't use that here.  #
      ############################################################################
        curGUID = instances[0].getAgeInstanceGuid()
        curInstance = 0
        if (not highest):
            for i in range(0, len(instances)):
                if (instances[i].getAgeInstanceGuid() < curGUID):
                    curGUID = instances[i].getAgeInstanceGuid()
                    curInstance = i

        else:
            for i in range(0, len(instances)):
                if (instances[i].getAgeInstanceGuid() > curGUID):
                    curGUID = instances[i].getAgeInstanceGuid()
                    curInstance = i

        try:
            als = ptAgeLinkStruct()
            als.getAgeInfo().copyFrom(instances[curInstance])
            print ('%s: IGetPublicLink: Age link structure found' % self.me)
            return als
        except Exception, detail:
            print ('%s: IGetPublicLink: Age link structure not found - %s' % (self.me, detail))
            return None



    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. Most 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 age name. However, an age instance  #
      # name does not have to be unique (Ae'gura).                                  #
      # If you plan to link to Cyan ages you must at least keep the age instance    #
      # names provided under ABM and TPOTS!                                         #
      ###############################################################################
        # ABM (UU)
        if (ageName == 'Personal'):
            return 'Relto'
        if (ageName == 'Cleft'):
            return "D'ni-Riltagamin"
        if (ageName == 'BahroCave'):
            return "D'ni-Rudenna"
        if (ageName == 'BaronCityOffice'):
            return "Ae'gura"
        if (ageName == 'city'):
            return "Ae'gura"
        if (ageName == 'Garden'):
            return 'Eder Kemo'
        if (ageName == 'Gira'):
            return 'Eder Gira'
        if (ageName == 'Garrison'):
            return 'Gahreesen'
        # TPOTS (Alcugs)
        if (ageName == 'Neighborhood02'):
            return 'DRC Neighborhood'
        if (ageName == 'RestorationGuild'):
            return "Watcher's Guild"
        if (ageName == 'AhnySphere01'):
            return 'Sphere 1'
        if (ageName == 'AhnySphere02'):
            return 'Sphere 2'
        if (ageName == 'AhnySphere03'):
            return 'Sphere 3'
        if (ageName == 'AhnySphere04'):
            return 'Sphere 4'
        # The KI always tried to convert this incorrectly from "Shaft"
        if (ageName == 'Descent'):
            return "D'ni-Tiwah"
        # missing KI conversions (probably better to add this in the KI)
        if (ageName == 'EderDelin'):
            return 'Eder Delin'
        if (ageName == 'EderTsogal'):
            return 'Eder Tsogal'
        if (ageName == 'GreatTreePub'):
            return "The Watcher's Pub"
        if (ageName == 'Ercana'):
            return "Er'cana"
        # fan ages examples
        if (ageName == 'Pahts'):
            return 'Ahra Pahts'
        if (ageName == 'Andy_Nexus'):
            return "Andy's Nexus"
        if (ageName == 'Dots_Office'):
            return "Dot's Office"
        if (ageName == 'The_Company_Nexus'):
            return 'The Company Nexus'
        # Drizzle examples
        if (ageName == 'KveerMOUL'):
            return "K'veer"
        if (ageName == 'KirelMOUL'):
            return 'Kirel'
        if (ageName == 'AhnonayMOUL'):
            return 'Ahnonay'
        if (ageName == 'MystMystV'):
            return 'Myst'
        if (ageName == 'MarshScene'):
            return 'Great Marsh'
        if (ageName == 'MountainScene'):
            return 'Rowan Green'
        return ageName



    def HasPublicAges(self):
        if vOpenSource:
            print 'HasPublicAges: Open Source = true'
            return true
        if PtIsSinglePlayerMode():
            print 'HasPublicAges: Offline = false'
            return false
        try:
            PtForceCursorShown()
        except:
            print 'HasPublicAges: UU = true'
            return true
        print 'HasPublicAges: Alcugs = false'
        return false



    def IDoSpecialAction(self, bookPage):
      ###########################################################
      # Replace 'CleftSpecial' with your bookPage that contains #
      # the clickable image triggering the special action.      #
      ###########################################################
        if (bookPage == 'CleftSpecial'):
            print ('Special action found for %s' % bookPage)
            # Do some special action here
        else:
            print ('No special action for %s' % bookPage)



# Insert the standard GLUE section for your Uru version here. You can copy this from another Python file.


The avatar linking animation requires the following Alcscript:

Code: Select all
<clickable book>:
    quickscript:
        simpleclick:
            pythonfile: *YourAge*BookGUI
            region: <click region>
            animation: LinkOut or FishBookLinkOut
            animtarget: <seekpoint>


*YourAge*PageDefs.py
This is the file that contains the definitions for your books and pages. You will do most of your editing here. *YourAge*PageDefs.py is imported into *YourAge*BookGUI.py. There are 4 sections: General layout elements, AgeBooks, BookPages and LinkDestinations. Replace the examples with your own definitions.

Code: Select all
# For each occurrence 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 *YourAge*Journals import *
kPublicAgeLink = 6

# 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>'
ImgEndNoResize = '" align=center link=%d blend=alpha resize=no>'
ImgEndNoLinkNoResize = '" align=center blend=alpha resize=no>'
AlignCenter = '<p align=center>'
AlignLeft = '<p align=left>'
AlignRight = '<p align=right>'
# Variables for animated linking panels. See BikTest. Does NOT work with UU!
MovieLinkStart = '<movie src="avi\\'
MovieLinkEnd = '.bik" align=center link=%d resize=yes>'
# 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 = {'Journal01': ('<cover src="*YourTexture*"><margin right=32 left=32>', '<font size=12 face=Arial color=000000>', 0, 0, 'BkBook', 0.8, 1.0),
 'Journal02': ('', '', 1, 0, 'bkNotebook', 1.0, 1.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 = {'BevinBalcony01': (PageStart + ImgStart + 'xLinkPanelBevinBalc01*1#0.hsm' + ImgEnd + AlignCenter),
 'CleftDefault': (PageStart + ImgStart + 'xLinkPanelCleftDesert*1#0.hsm' + ImgEnd + AlignCenter),
 'CleftFissureDrop': (PageStart + ImgStart + 'xLinkPanelCleftDesert*1#0.hsm' + ImgEnd + AlignCenter),
 'CleftSpecial': (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),
 'BikTest': (PageStart + MovieLinkStart + 'mystWithAlpha' + MovieLinkEnd + AlignCenter),
 'PradJournal': (PageStart + (DefPradJournal % plyrName))}

###############################################################################
# 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')                                #
#        - Linkingrules are only relevant for the online game. They are:      #
#            0 = PtLinkingRules.kBasicLink                                    #
#            1 = PtLinkingRules.kOriginalBook                                 #
#            2 = PtLinkingRules.kSubAgeBook                                   #
#            3 = PtLinkingRules.kOwnedBook                                    #
#            4 = PtLinkingRules.kVisitBook                                    #
#            5 = PtLinkingRules.kChildAgeBook                                 #
#          The offline game will treat all of these as kOriginalBook          #
#        - A new linkingrule is defined here for special (online) purposes:   #
#            6 = kPublicAgeLink                                               #
#          Use it without the prefix PtLinkingRules.                          #
###############################################################################

LinkDestinations = {'BevinBalcony01': ('Neighborhood', 'LinkInPointBevinBalcony01', 'nb01BevinBalcony01', PtLinkingRules.kOriginalBook),
 'CleftDefault': ('Cleft', 'LinkInPointDefault', None, PtLinkingRules.kOriginalBook),
 'CleftFissureDrop': ('Cleft', 'LinkInPointFissureDrop', None, PtLinkingRules.kOriginalBook),
 'CleftSpecial': ('Dummy', None, None, None),
 'KadishPyramid': ('Kadish', 'LinkInPointGlowRmBalcony', 'kdshGlowRmBalcony', PtLinkingRules.kOwnedBook),
 'FontTest': (None, None, None, None),
 'BikTest': ('MystMystV', 'LinkInPointDefault', 'Default', PtLinkingRules.kOriginalBook),
 'PradJournal': (None, None, None, None)}


More info about net linking rules here (user friendly version). A more technical (server side) explanation is included in the source download.

*YourAge*Journals.py
Optional. A file that contains journal texts. Journal texts are written in PBML. Since journal texts are usually rather long we can store them in one or more external files which are imported into *YourAge*PageDefs.py. Replace the examples with your own texts.

Note: The entire journal content must be placed on a single line since this is a Python code string. As an alternative you can enclose your strings within triple quotes to extend the string assignment over multiple lines (thanks Nadnerb).

Code: Select all
# Examples of journals. DefFontTest shows the fonts available in the offline 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'
DefPradJournal = '<font size=24 face=Uru color=221166><p align=left>Shorah %s,\n\nAn example which shows how to address players by their own names in a journal.'

dynamic_books_source_4.1.zip
(11.12 KiB) Downloaded 701 times
"It is in self-limitation that a master first shows himself." - Goethe
User avatar
D'Lanor
 
Posts: 1980
Joined: Sat Sep 29, 2007 4:24 am

Re: Dynamic Book Template (version 4.1)

Postby D'Lanor » Fri Mar 12, 2010 4:02 pm

*bump*

Updated to version 4.1.
"It is in self-limitation that a master first shows himself." - Goethe
User avatar
D'Lanor
 
Posts: 1980
Joined: Sat Sep 29, 2007 4:24 am

Re: Dynamic Book Template (version 4.1)

Postby tachzusamm » Fri Apr 02, 2010 12:45 am

Just to avoid the impression noone cares about this thread, I want to say thank you for your work and sharing it.
I have not used it yet, but I'm sure I will - when the time has come and I learned a bit more - when I need a linking book, that is.

Met vriendelijke groet,
tach
User avatar
tachzusamm
 
Posts: 575
Joined: Thu May 29, 2008 2:03 am
Location: Germany

Re: Dynamic Book Template (version 4.1)

Postby Egon » Fri Apr 02, 2010 1:33 am

tachzusamm wrote:Just to avoid the impression noone cares about this thread...


I will add, that I'm using this version, and it's working.
(although I'm using it now only to generate plain Jounrals)
Egon #2052375
Who You gonna call? Guild of Doorcallers! #5356672
Eder Tsogal/Delin Marathon
Image
User avatar
Egon
 
Posts: 284
Joined: Fri Nov 16, 2007 9:45 pm

Re: Dynamic Book Template (version 4.1)

Postby Grogyan » Fri Apr 02, 2010 9:45 pm

Cheers D'Lanor.

Downloaded and will play with the new version soon
Better to have loved and lost than never to have loved at all
User avatar
Grogyan
 
Posts: 1203
Joined: Thu Oct 11, 2007 1:27 am

Re: Dynamic Book Template (version 4.1)

Postby Itep Edor » Thu Aug 26, 2010 12:40 pm

Hi D'Lanor

Thanks a lot for the very good job you did here.
We will use your templates for our new age. :)

Hoping you had a good time at the CT in Rothenfels. ;)

Greetings

Itep Edor
User avatar
Itep Edor
 
Posts: 23
Joined: Wed Nov 07, 2007 5:32 pm
Location: Switzerland

Re: Dynamic Book Template (version 4.1)

Postby J'Kla » Tue Jun 12, 2018 4:43 am

Given that this is Python Scripting is there any way to make use of these templates in a Blender Korman environment and if so how would we go about implementing this?

Please Note: I am approaching this from the idiot side of the tracks.
User avatar
J'Kla
 
Posts: 1003
Joined: Wed Feb 20, 2008 3:16 pm
Location: Geordieland UK


Return to Scripting

Who is online

Users browsing this forum: No registered users and 0 guests