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


No comments: