[26 Mar 2008] Classlib files updates and runequest (work in progress) roleplaying game uploaded

Contains all messages from the Hollywood mailing list between 01/2006 and 08/2012

[26 Mar 2008] Classlib files updates and runequest (work in progress) roleplaying game uploaded

Post by Dwayne »

Note: This is an archived post that was originally sent to the Hollywood mailing list on Wed, 26 Mar 2008 01:13:22 +1100

Hi everyone,

Firstly I would like to thank Andreas for his latest update as it has made my job of converting the classes framework much easier although the bulk of the work had already been done.

Secondly I have updated the classlib files but have not overwritten the ones in the classlib folder on the website. Instead I have uploaded these to the runequest/classlib folder as I am starting to put this up on the web for people to learn from and hopefully help out with.

The changes to classlib.inc include:

* completeley re-written to utilise the : symbol as per the lua implementation of object oriented programming. Thanks to Andreas for including the use of the : symbol
* debugged and re-wrote the routines for the __set and __get metamethods that can now be used in the classes to get and set attributes strangely enough.
* as per the original source I have also included the automatic creation of global variables representing each of the classes therefore eliminating the need to reference the global variable in the class building method. This is due to Andreas fixing the _G case sensitivity _G points to the global variable table.
* emptyendif=0 lines have removed as the bug in the virtual machine has been resolved by Andreas (thanks again).
* this version includes p_debugprint lines these can be removed or commented out if you wish

The changes to constants.inc include:

* modified p_typeof to accept to variables (value, name) value is the variable being tested and name is the name of table field so you can now test to see whether a field exists in a table before using it. i.e. t1={x=100} if (p_typeof (t1,x) <> #nil$) then if ((t1.x) > 100) then etc. etc.; if (p_typeof (t1, y)=#nil$ then t1.y=10; etc.

previously I had written p_typeof (rawget (t1, x)) <> #nil$) etc... these lines have been replaced in classlib.inc and each of the class files under the runequest folder. Note that you must compare against the string constants I have created in the constants.inc file.

I would be very interested if somebody is able to re-write the routines in the constants.inc file using the standard constants rather than the ones I converted to $'s as I am sure that number comparisons are less computationally heavy than string comparisons but it may be not that much difference in time.

In the runequest folder you will find a characters folder and the classlib folder (new verion of classlib). The characters folder has two class files. character.class is a base class that sets up basc attributes for a character in a roleplaying game it inherits the modifier.class file (mentioned below). The other is human.class which inherits from character.class but adds no additional attributes yet.

get and set methods are used in these classes to get and set values unique to the classes. Each of the attributes from the classes also have a generic get and set named method i.e. getstrength, setstrength, getintelligence, setintelligence etc. These methods are used to reference the current value of each of the named attributes. In fact 4 values will be returned (the total value, the current value set, the original value and the total of any modifiers-see below)

In the root of runequest is modifier.class it is the base class which character.class and subsequently human.class are derived from. It is used to store the attributes that are created by the inherited classes. These attributes are stored in a table called current and original and must be unique to the class and any that inherit from it. the original table stores the original value of any of the attributes that are set aside from -1 (the attributes are initialised to -1 intentionally as nil will not create the actual field) once set the original values for that attribute will not change. Current stores the current value set by either any of the set methods that reference that attribute i.e. setstrength etc.

There is another table in modifier called modifiers. Each of the attributes when initialised for the first time have their own table within modifiers. Basically you then use a method from the modifiers class to add modifiers to the attributes. this method is called addmod and you pass it the attribute name and either a value or a function, the index relating to the newly added value/function is returned to caller. To remove the modifier you must supply the attribute name and the index referencing the modifier you wish to remove.

Other methods available in the class are getattr and setattr which set and get the attributes and their values in current, original and the modifiers table when necessary. getattr will actually return 4 values (the getstrength, setstrength etc. methods from the character class call the methods with their unique name i.e. strength is referenced by ch_str, intelligent by ch_int etc.) the total value of the attribute which is found by adding all of the modifiers for this attribute and it's current value, the current value, the original value and the total sum of the modifiers for the attribute.

a short example of using the ch_str to represent the characters strength might have something like this.

original.ch_str=12 current.ch_str=16 (has been increased by magic during the course of the adventure)

andthe character may have various modifiers applied one which is a modifier from a spell that had been cast bull strength?? that adds +2) and the other may be a racial modifier based on the opponent the character is fighting i.e. (this is a simple example the spell system which will incorporate an events class for spell duration etc still needs to be created. and so will the environment class.

modifiers[0].ch_str=2 ; this is the first modifier that was added to the attributes list and relates to the spell that was cast. eventually after a certain time (being the duration of the spell - which is where the events class will come into it) the modifier would be removed.

modifiers[1].ch_str=function () return (if (self.getrace (self.environment.getcurrentopponent ())="halfling") then return (5) endfunction ; this is the second modifier that was added by the human class as it is a racial modifier that adds 2 to strength if the current opponent that the character is fighting is a halfling (note that this would rely on the environment class and the getrace method and getcurrentopponent methods to be created and is an example only as it very well may work differently but this is what I am working toward).

The getattr method relies on getcurr, getorig methods that retrieve the current and original values from the respective table holding the attribute values. getmods will return the total sum of values from the modifiers table by iterating a for loop and calling getmod which will get the actual indexed value. Note that getmod tests to see whether the value stored is an actual number or a function. If it is a number it returns this and if it is a function it will call the function and return the result from the call.

At the moment when a modifier is removed it will move the index above it below. i.e. if you remove modifier 3 then 4 will become 3 5 will become 4 and so forth until the last index which will become nil as it would have been moved already. This was ok to work with in practice but if I am to use other tables to store events then the index cant change but the reference to the indexes needs to be known by those methods and tables adding the modifiers. Obviously fixed modifiers won't need to be recalled or removed. So the system will need to change and will be in flux whilst I devise a better scheme.

Hopefully it being in a class structure will limit the impact of any changes that are made by the underlying structures if the creation and deleting is handled appropriately by the methods.

I would also like to have a priority or weighted system where one modifier is added before another and possibly some sort of conflict resolution where one modifier can possibly negate another but am uncertain of how to do this. At the moment modifiers obviously stack and this could lead to problems down the track especially if the system becomes flexible enough to allow other people to add new characters etc. Where rules to balance power and play would need to be incorporated.

Anyway suggestions are very much welcomed.

Since I have not updated the original classlib files and have only updated those under the classlib folder in runequest you will need to experiment or learn from the classes created under this location.

Feel free to drop me a line. Once I have the details of how the events, enviroment, items, weapons, spells, skills etc classes are going to be fleshed out I will eventually document this better. If you wish to help me along the way with these classes I would also be delighted to hear from you. It will be a little difficult at first to understand where this is heading especially without the runequest rules (remember this is currently being based on an existing game) but if you are interested to hear of my progress, simply ask me and I will be more than happy to explain things as this sometimes helps me clarify things in my own mind as I am not an experienced programmer by any stretch of the imagination and a lot of this has so far been done by trial and error. I am more than happy to share my experience so that you want have to fall into the same traps as I have.

Happy coding.