Data Mentor Lesson 2
LESSON 2:
Let's hear a round of applause for Eidam who successfully completed his homework assignment ;)
However, nobody has gotten back to me about their schedule... So another round of email lesson's.
Today we'll discuss coding techniques, debugging issues and of course another hands-on assignment.
By now you should have a text editor to manage your text files, and syntax highlighter. The highlighter makes your debugging and spelling checks MUCH MUCH easier!
Okay, Coding techniques isn't a big topic since I'm not here to dictate HOW you code, but what you code. There is writing code for your own use, and then there is writing code for public use. I'm going to focus on public use:
When writing code, it is best to follow the best practices for the project you follow. For example, in the data team our best practice is to 'DEFINE' an object at base value 0. We actually had a bunch of bugs arise because this standard was not followed.
DEFINE:MyVar|10 is a no-no. Instead we should use DEFINE:MyVar|0 <> BONUS:VAR|MyVar|10
For all future sets this is VERY important as we will shortly be transitioning to the New Formula Parser system. And any DEFINE with a non-zero value will cause issues for the transitioning.
Some of you might be going "What is a DEFINE?" - Great question. DEFINE sets the value of a 'word' into a numerical value, and then allows us to change the value of that word in later references. This is done through our JEP (Java Expression Parser). Tom Parker is re-writing a more powerful JEP replacement for reasons stated on the wiki. All I can say is WOW.
Since we talked about it, let's put it in a practical application.
CLASS:My Class <> TYPE:PC.Base 1 <> SAB:To Hit Bonus +%|MyVar DEFINE:MyVar|0 BONUS:VAR|MyVar|CL
Now, I've added a few old school elements to make this a bit easier to follow.
MyVar is 0, CL is special code in class files which equates to "thisClassLevel". If we do not DEFINE the value the BONUS will not work.
At level 1 MyVar is 1 (If we include the previous example it would +11, but we will ignore the previous example unless told otherwise).
The display then for level 5 on the character sheet would 'To Hit Bonus +5'
Now, in proper parlance this example would be better coded up as such:
# Class CLASS:My Class <> TYPE:PC.Base <> DEFINE:MyClassLVL|0 <> BONUS:VAR|MyClassLVL|CL 1 <> ABILITY:My Class Class Feature|AUTOMATIC|My Class ~ Attack Bonus
# Ability Attack Bonus KEY:My Class ~ Attack Bonus CATEGORY:Special Ability TYPE:Class Features.My ClassClassFeatures.SpecialAttack DESC:To Hit Bonus +%1|MyVar DEFINE:MyVar|0 BONUS:VAR|MyVar|MyClassLVL
Now, the bonus is tightly wrapped into it's own ability object. The Class calls up the Ability, and the ability holds everything. Class is now cleaner. Also, note, this makes working with newer features down the road a bit easier to transition too as Classes become less necessary.
You will notice there is a pattern - that class feature is coded up using common data naming practices. KEY follows a grouping pattern, which is very crucial as many names get re-used often.
Which leads me to our next topic - Debugging. If you failed to create the abilitycategory 'My Class Class Feature', all abilities you are trying to stick in there will fail. You will get an "Unconstructed Reference" Error. Cannot find My Class Class Feature My Class ~ Attack Bonus - followed by the object trying to make this call.
An Unconstructed Reference means the name either doesn't match, or a category is not set up correctly. Any of these need to be dealt with. In this case, I need to go to the abilitycategory file.
ABILITYCATEGORY:My Class Class Feature CATEGORY:Special Ability TYPE:My ClassClassFeatures VISIBLE:QUALIFY DISPLAYLOCATION:Class Features EDITABLE:NO EDITPOOL:NO PLURAL:My Class Class Features FRACTIONALPOOL:NO
Once that is entered, saved and reloaded, the unconstructed reference will go away.
Real quick recap - An unconstructed reference is merely the system saying that the object cannot be found (or in layman's terms - You are asking for something that doesn't exist for me. This means either you forgot to assign the correct TYPE (Our above example requires each ability have "My ClassClassFeatures" to be legally assigned to the My Class Class Feature group; you didn't reference the object by it's true KEY name; or the file holding the object isn't being loaded, or you never created the object in the first place.
The true key to understanding an error is to look at where it comes from - file references are clickable in the log (F10) which opens the file calling for the object. Then search for the name it is saying. This will give you a clue as to what needs to be done. Misspelled, missing proper type, not loaded.
If you encounter an NPE - Null Pointer Exception - Immediately stop everything. Copy the log. You've tried to do something that broke the program. Do not open any characters, save/load anything. At this point the program is unstable and anything beyond this point is not trustworthy. You should save the log to a text file and read the message. At this point it is usually wise to post the error in a Help Support file if you need help deciphering it, or you can open a Code bug. However, the code team will not always fix an NPE if it arises from bad syntax.
We expect they will fix NPEs when they arise from correct syntax. Common causes of NPEs for me in the past usually involved improper CHOOSE syntax.
Today, instead of making up an assignment, we will instead focus on something more useful. Navigate to the JIRA system for PCGen (jira.pcgen.org). You'll want to hang out in NEW SOURCE. Find a book that appeals to you and preferably have a copy of. Find ONE item that you really want. Class, Feat, Archetype, Spell, Equipment, etc.. On a blank lst file of your creating, code up the object as completely as you can to the public style we were discussing earlier.
For a recap of public style - We use pcgen naming standards, we include a SOURCEPAGE for where the object first appears in the book (Table of Contents, and Tables do not count), we also code up tempbonuses or permanent bonuses.
Each assignment will be reviewed and feedback given. Try not to choose anything too difficult or beyond you, however, if you really want to jump in the deep end, don't get to a point of frustration, instead contact me and we'll talk through it.
Cheers, Andrew