Choose Your Language

Saturday, 26 December 2020

Episode 38: Coding Monsters!

Let me say straight from the start that this post is not about actually scripting monster AI, or even a tutorial about how to design a monster in a toolset. In this case, I am simply referring to those technical "monsters" builders face when trying to produce their modules. From applying animations to writing scripts, they all seem to come at various levels of difficulty, just like those "real" monsters we face in the game itself. So while some such encounters may occasionally appear as "simple" as a goblin to beat, others feel like dragons! Even builders skills can be thought of as in classes and levels themselves, so what may appear simple to one builder becomes a real challenge to another ... and haunt them for years! Read on for my latest XP gains in building ... 

The Patrolling Guard

A couple of posts back, I described how I had been wrestling with some animations and how they may or may not work within conversations. Recently, however, the issue with animations has extended into the area of walk paths for me. In the past, the official WalkWayPoints function (and accompanying scripts) had always been a bit hit and miss for me, and so a few years back I decided to write my own version of them so that I could have more understanding and control with what was going on, especially when considering scripted waypoints: those that allow additional animations for a "walking" creature. This venture was a reasonable success, as it did allow me to ensure the creatures I setup worked as expected ... but only "most of the time".

I still continued to encounter issues where walkers would sometimes become stuck in the environment; a problem exacerbated if a PC blocked a walkers path in a limited space. Previously, I had tried to alleviate the issue by forcing the creature to try to move somewhere else before continuing their walk path. The problem with this, however, was it could cause the creature to constantly reposition themselves if the path was blocked by a PC. It looked like they had the jitters! Thankfully, in the end, I figured a way to smash that long standing monster, by using a ClearAllActions that now simply pauses the walker in their walk until the path is clear again. It was a relatively simple fix to a long time issue I had been struggling with. The only caveat I learned at this time was also to ensure any WPs laid down MUST be done in such a way as to clearly be guided around any placeables. For if a WP guide line even slightly clipped a placeable, the engine did not appear clever enough to always be able to walk around the placeable object.

XP GAINED: 100

The Random Monster

Once again, I am not talking about a random wandering monster, but the monster of trying to work with random probabilities in the game ... or with any probabilities for that matter. Twice over the last few months, I have had to face some maths to do with probabilities. As many will likely know, trying to deal with any kind of randomness on a computer is difficult. (Do some background research if need be.) My first issue was trying to determine the probability of a drop to ensure I was giving the player the right odds at acquiring certain items and the second encounter was trying to ensure treasure drops randomized their location fairly. For the latter, I learned a bit about the dangers of naivete.

XP GAINED: 100

The Persistent Monster

I have certainly had my share of these critters! Those who have been following my campaign build of the last few years will have seen some of the types I mean. I can even include The Patrolling Guard issue as one of these types of issues, but as I have already covered that above, I will give an example of a couple of others I have had to deal with recently.

An example of the kind of thing I mean is the usage of a variable string instead of a variable name. So rather than GetLocalString(OBJECT_SELF, sVariable), I will have done something like GetLocalString(OBJECT_SELF, "sVariable"). The issue with this kind of problem is that both lines of code will happily compile as neither is a compiler error. The error is purely one of my own making using "sVariable" instead of simply sVariable. The last one I had one of these, I was stuck for quite some time trying to locate why my script was not working.

Another example of an issue I can encounter of my own making, is if I should happen to change a ResRef of an item, which I have previously added to a store with its old ResRef. This again has caused me all sorts of issues when I am trying to reproduce an item from the original store bought ResRef, which fails to do anything because all that I have there now is the newer reference. Thankfully, now I have been stricter in my approach, I believe I must be near the end of any such issues moving forward.

XP GAINED: 100

The Deep Rooters

When I hit one of these issues, I can usually write off an entire session trying to get to the bottom of it - sometimes even multiple sessions. These type of issues tend to rear their ugly heads somewhat further down the coding path, and often even after a module release. The reason being, these type of coding monsters often only show themselves under unusual (or rare) situations.

For someone who has coded their module in the way I have, this means I am more likely (I believe) to hit these types of issues more than most, simply because I have a number of deeply integrated systems that allow multiple paths and diversity for the player. As an example, even the way "Death" is handled in my campaign has multiple paths. I can thank my wife who has been able to test the module a number of different ways and offer feedback in some areas of the code, which even I have not been able to fully test due to time limitations. I hasten to add this is why feedback from players is invaluable to builders, as we simply do not have enough time to do everything.

As an example of one of these deep rooted monsters, in her latest testing, my wife discovered that if she had abandoned a dead PC in the Sanctuary (while playing hard-core death mode, being abandoned meant the PC could no longer be raised from the dead), if she now brought another dead PC to the same area, the code had not yet been considering such a situation where a player (like she had done), now tried to raise another PC that was still able to be raised within the same area. I had to trawl through multiple death scripts to finally locate the one which needed a simple variable check added to fix it. A simple fix in itself, but one that required a lot of code searching.

As a final example of a recent deep rooter, my wife discovered a situation where she could return to an area and the NPCs would not be there. She quickly discovered she could work around the issue by reloading, but it was still obviously an issue for me to have to resolve. Once again, the problem was hidden among a number of functions relating to the whereabouts of creatures subject to the time of day, and if they changed locations depending upon night and day habits. Now most people probably do not even worry about this area of module coding, but for me, who wanted to design a "realistic" environment where time mattered, I had to track down why certain NPCs had refused to jump to their relevant locations upon her arrival. This monster turned out to be quite an "end of level baddy" type, even requiring me to rename some functions to help avoid misuse due to their naming. Along the way, I was able to improve the scripts (as they go back quite some years), and finally add the relevant function call to the right script to ensure these lost NPCs would now return at the appropriate time.

I hasten to add that even when trying to improve some of these scripts, simply adding a GetIsDead check for some reason would crash the toolset! Again, it was only a minor condition I considered adding to help "improve" efficiency, but the toolset was not having it. The additional problem was, having added it during the process of the overall fix, trying to locate that it was the cause when the final test crashed, added more time to resolving the initial issue.

XP GAINED: 200

Gaining A Level

Anyway, after all this monster slaying, I can safely say that I have probably gained enough experience to go up a level now ... well, at least in some way. I am still not much better in area designs and such like, but maybe I have gained a point or two in conversations and some scripting. ;) And all this is being added up to hopefully bring to you module two one day ... speaking of which, here is a screenshot.

Let's Sit Down For A Talk


Tuesday, 8 December 2020

Episode 37: The Dungeon Environment!

As we all should know by now, dungeons come in many shapes and forms, fascinating us and piquing our curiosity, while at the same time, all too ready to do us harm! For those of us who enjoy both science fiction and fantasy, we are familiar with the many different environments of alien or bizarre objects we can expect to find, as well as the many denizens we are likely to encounter. This week, I have been trying to focus on some of those aspects, which I have found interesting to deal with in my own past gaming experiences ... and which I intend to include in my next module. Read on for all the latest updates ...

The Alarm System

Of all the games I have had the privilege to play, one of my favourites (as many of my regular readers will know) is System Shock 2. For me, it was the first time I experienced timed alarm systems, which could catch out the unwary player and send a horde of creatures their way if not handled correctly. I developed a system akin to this in my NWN1 module, Soul Shaker, where I employed "Watchers" to do something similar. In my next contribution with The Scroll: Predestinated Days, I hope to add another variation to a dungeon that players will need to negotiate.

Without going into too much detail that may spoil the experience, all I will say is that the alarm system I have devised has managed to capture all those elements I was after, including the ability for the player to be able to manipulate the system and gain an advantage if they play clever. If not, then there will be consequences ... The choice of play, however, will be left to the player.

Complementing Systems

Part of the joy of building a new module is being able to put together new ideas and systems that all work together to give the player a whole new gaming experience. For myself, it is not just about putting together a new story within the same fantasy world ... it is also about adding a new dimension to the game play itself. Please note that The Scroll series of modules are not as extreme in their design as my NWN1 Soul Shaker module is (as those who have played my modules will be able to confirm), but I hope those same players will also be able to attest to the many other new systems and options I have built within The Scroll to make it the unique playing experience I believe it is.

To this end, The Scroll: Predestinated Days will continue with some of those systems I have already developed in module one, but will also have a few new systems added to complement them. Hopefully, I have been able to incorporate them well enough to be reasonably intuitive to use, and most of all, a fun addition. New GUIs have been designed and included to make their inclusion easy to work with. At the moment, I have held back from showing screenshots that include them, but maybe in the future (and possibly nearer completion), I may be able to give one or two screenshots that I hope will tease the player with what to expect.

Conversations Overhaul

Some dungeons offer the opportunity to converse with its denizens, and so a good conversation goes a long way. Recently, I learned more about how animations work in conversations, and so ended up "fixing" (by removing broken animations) and "improving" (by adding some I knew that worked), not only for the second module, but also retrospectively for some of the conversations in the first module. Now, the NPCs respond more animated than before, benefiting both modules. NB: The first module will have access to these upon the next release (or update).

Code Improvements

Working on the second module, which shares the same core code as module one, allows me to continue to test and monitor the overall game play for the whole campaign of modules. As a consequence, I have had the opportunity to improve the code around journal updates, fix a minor auto-pause issue and improve overall efficiency.

These are all relatively small fixes to the code, and so I am holding back on any further module one release for now, and to also allow my wife to test these alterations before going public with it. It may even be that unless a critical problem is found that demands immediate attention, that the next release will not become available until the full release of module two anyway ... or perhaps when I am confidant that the changes are safe to release at any rate.

Chipping Away

I managed to finish another side quest, which ended up requiring more conversation nodes than I first realised would be needed. However, it was during this additional time that I learned about the conversation animations in more detail, and so it was time well spent.

I also managed to move the main quest further forward, reaching a new stage from where I can work from. This led me to working on an area where the next stage is to take place, and start to work on new conversations. The screenshot this week, however, is from a conversation I wrote last summer. Although, it does show a little bit about the "dungeon" environment ... in more ways than one.

A Dangerous Dungeon Environment?