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.pyThis 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).

### 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. #############################################################################################

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

*YourAge*PageDefs.pyThis 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.

# 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

################################################################################ 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. ################################################################################

################################################################################################ 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. ################################################################################################

################################################################################ 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. ################################################################################

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

*YourAge*Journals.pyOptional. 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).

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.