D'Lanor and I were discussing the use of chronicles in the vault, and the method to which they can be added for fan created ages in the current system we have.
For those who don't know, Chronicles are created via python scripts and written to the vault. A chronicle is a variable or string that is set into a specific node in the vault. Chronicles have multiple uses as they can A. Save a players progress in an age. B. Can be used to save variables for later updating. C. Can be used for cross age puzzles so that one can journey to one age, and then to another that are interconnected in their story, but have separate SDL, prp and age files.
D'Lanor suggested awhile ago using this system that he sent a proposal to Cyan about: Fan made age and vault chronicles. He has not heard back from Cyan yet. As I was planning on using this system in several of my ages. He proposed a more viable method in those discussions:
D'Lanor wrote:Happy holidays
I never heard back from Cyan. In the mean time I have also been using this idea for an age I am doing the wiring for. I made a global xChronHandler.py module and simplified the concept somewhat.
I am now handling the creation of both the Base and Age chronicle layers in the main Python file of the age(s) which use(s) them. In my original concept for MORE the Base chronicle would have been created in another age. To be more precise: in a Cyan age, which is not a desirable option anymore.
Here is the code from xChronHandler.py
- Code: Select all
from Plasma import *
from PlasmaTypes import *
kChronicleUserAgeType = 4
def ISetBaseChron():
vault = ptVault()
entry = vault.findChronicleEntry('UserAges')
if (type(entry) == type(None)):
PtDebugPrint('ISetBaseChron: Create UserAges base chronicle')
vault.addChronicleEntry('UserAges', kChronicleUserAgeType, '')
return 1
PtDebugPrint('ISetBaseChron: UserAges base chronicle found, do nothing...')
return 0
def ISetSubChron(ageName):
if (not ageName):
return
ourChild = None
vault = ptVault()
entry = vault.findChronicleEntry('UserAges')
if (type(entry) == type(None)):
PtDebugPrint('DEBUG: No UserAges chronicle')
return
chronRefList = entry.getChildNodeRefList()
for subChron in chronRefList:
theChild = subChron.getChild()
theChild = theChild.upcastToChronicleNode()
if (theChild.chronicleGetName() == ageName):
ourChild = theChild
break
if (type(ourChild) == type(None)):
PtDebugPrint(('ISetSubChron: Create subchronicle %s' % ageName))
newNode = ptVaultChronicleNode(0)
newNode.chronicleSetName(ageName)
newNode.chronicleSetType(kChronicleUserAgeType)
newNode.chronicleSetValue('')
entry.addNode(newNode)
def IWriteAgeChron(ageName, chronName, chronVal):
chronVal = str(chronVal)
ourChild = None
vault = ptVault()
entry = vault.findChronicleEntry('UserAges')
if (type(entry) == type(None)):
PtDebugPrint('DEBUG: No UserAges chronicle')
return
chronRefList = entry.getChildNodeRefList()
for ageChron in chronRefList:
theChild = ageChron.getChild()
theChild = theChild.upcastToChronicleNode()
if (theChild.chronicleGetName() == ageName):
PtDebugPrint(('IWriteAgeChron: %s chronicle found' % ageName))
chronRefList2 = theChild.getChildNodeRefList()
for ageChron2 in chronRefList2:
theChild2 = ageChron2.getChild()
theChild2 = theChild2.upcastToChronicleNode()
if (theChild2.chronicleGetName() == chronName):
ourChild = theChild2
break
if (type(ourChild) == type(None)):
PtDebugPrint(('IWriteAgeChron: Create chronicle %s, value=%s' % (chronName,
chronVal)))
newNode = ptVaultChronicleNode(0)
newNode.chronicleSetName(chronName)
newNode.chronicleSetType(kChronicleUserAgeType)
newNode.chronicleSetValue(chronVal)
theChild.addNode(newNode)
else:
if (ourChild.chronicleGetValue() == chronVal):
PtDebugPrint('IWriteAgeChron: Chronicle value already correct, do nothing')
return
PtDebugPrint(('IWriteAgeChron: Change chronicle %s value to %s' % (chronName,
chronVal)))
ourChild.chronicleSetValue(chronVal)
ourChild.save()
def IReadAgeChron(ageName, chronName):
vault = ptVault()
entry = vault.findChronicleEntry('UserAges')
if (type(entry) == type(None)):
PtDebugPrint('DEBUG: No UserAges chronicle')
return 0
chronRefList = entry.getChildNodeRefList()
for ageChron in chronRefList:
theChild = ageChron.getChild()
theChild = theChild.upcastToChronicleNode()
if (theChild.chronicleGetName() == ageName):
PtDebugPrint(('IReadAgeChron: %s chronicle found' % ageName))
chronRefList2 = theChild.getChildNodeRefList()
for ageChron2 in chronRefList2:
theChild2 = ageChron2.getChild()
theChild2 = theChild2.upcastToChronicleNode()
if (theChild2.chronicleGetName() == chronName):
chronVal = theChild2.chronicleGetValue()
PtDebugPrint(('IReadAgeChron: %s chronicle found, value=%s' % (chronName,
chronVal)))
return chronVal
PtDebugPrint(('IReadAgeChron: Chronicle %s missing' % chronName))
return 0
And here is an example of how the Base and Age chronicle layers are created upon link in. The trick was to create them one by one in way the vault (especially the online one) can handle.
- Code: Select all
from Plasma import *
from PlasmaTypes import *
import xChronHandler
class SomeAge(ptResponder,):
def __init__(self):
ptResponder.__init__(self)
self.version = '1'
print ('__init__%s v.%s' % (self.__class__.__name__,
self.version))
def OnFirstUpdate(self):
pass
def Load(self):
pass
def OnServerInitComplete(self):
kTime = 0.1
if xChronHandler.ISetBaseChron():
kTime = 5
PtAtTimeCallback(self.key, kTime, 1)
def OnNotify(self, state, id, events):
pass
def OnTimer(self, id):
if (id == 1):
xChronHandler.ISetSubChron('SomeAge')
#glue section here
If the base chronicle already exists the age subchronicle is created immediately. If neither exists the vault is given some time to add the base chronicle before the age subchronicle is placed inside of it.
Our discussion touched upon a subject that, to me, would be a great addition to the GoW's and future age creation projects. A global system of python files. Such as xChronHandler.py. These would be stored in a PAK file, and distributed via the Offline KI. What could be done is someone submits an idea for a global python file, (any python file that can be used in multiple ages would fall into this category. This is how Cyan does it, which is why you find a great deal of their python files starting with "x" and then the name of the file. With this system, we would be able to avoid having multiple python files that do basically the same thing. We already call Cyan's python files for certain things, and I see no reason that Fan Created Ages can't use a more global system that is kept up to date by the GoW and distributed via the OfflineKI, or if we prefer a link on the Wiki.