Welcome to Planewalker Games! We are the home of The Broken Hourglass, a new CRPG in development for Windows, Macintosh, and Linux computers.
Inside the Engine: On-the-fly creature customization PDF Print

On the fourth Monday of each month, we explore the code underneath The Broken Hourglass, the game environment called "WeiNGINE." This month, we look at the _encounter function, a way to quickly generate semi-random, tailored groups of creatures.

WeiNGINE can generate and place creatures in numerous ways. We have already discussed the placement of static creatures in an earlier installment of our engine tutorials. Any CREATURETEMPLATE may also be deployed at will, any number of times, using the _create_creature command. It is possible to customize a creature as it is generated with selective attribute upgrades, but a more convenient and automated way to do this is the _encounter statement.

_encounter provides an extremely powerful and flexible system to generate anything from random, "wandering monster"-type encounters, to heavily customized variations on established creature types. As such, it can be useful both for incidental combat situations, as well as for planned, "fixed-piece" encounters which simply could benefit from scaling or on-the-fly flexibility. _encounter can create one or more instances of a creature, from one or two CREATURETEMPLATEs. This means _encounter can be used to build a random encounter of "pick one of these six monsters, make four of them, and send them after the party", or to build a "Unique 'captain' and pack of soldiers" fight.

For purposes of illustration, we will stick with something simple—a comfortable cliché, even—a fight with giant spiders. Our sample spiders have a CREATURETEMPLATE which looks like this:

<<<<<<<< creaturetemplate/spider
<xml>
<Name value=~Spider~/>
<Appearance value="spider"/>
<Starting_Item value="bite"/>
<Strength value="10"/>
<Agility value="20"/>
<Toughness value="10"/>
<Health value="20"/>
<Brawl_Precision value="10"/>
<Movement value="10"/>
<Cannot_Loot value="0"/>
<Cannot_Manipulate value="0"/>
</xml>

The function arguments for _encounter make quite a formidable list—as most of them are optional and not strictly necessary to create a garden variety encounter, we will not exhaustively discuss each one.

Here goes. Don't be frightened.

_encounter

?hostile = bool? ->  
?size = point? ->  
?challenge = float? ->  
?join_party = string? ->  
?hiding = bool? ->  
?max_power_factor = float? ->  
?items = string list? ->  
?traits = string list? ->  
?paths = string list? ->  
?may_increase = string list? ->  
?maynot_increase = string list? ->  
?attribute_bias = int? ->  
?do_not_fail = bool? ->  
?power_split2 = float? ->  
?size2 = point? ->  
?max_power_factor2 = float? ->  
?items2 = string list? ->  
?traits2 = string list? ->  
?paths2 = string list? ->  
?may_increase2 = string list? ->  
?maynot_increase2 = string list? ->  
?attribute_bias2 = int? ->  
?templates2 = string list? ->  
?common_items = bool? ->  
?magic_items = bool? ->  
?visual_effects = string list? ->  
 area  : thing ->  
 xy  : point ->  
templates  : string list ->  
thing list

It looks like a lot, but most of the arguments are optional (bracketed in ??) and are not necessary to creating a simple encounter.

Here's a partial explanation of the optional arguments.

?hostile? : (default true) Determines whether the generated creatures should be hostile or neutral.

?size?: (default 1-1) The desired range of creatures this function should output, expressed like a point coordinate: asking for 1-3 creatures is expressed as ?size= 1::3?

?challenge?: (defaults to challenge rating of the player party) How powerful the encounter should be. Note that this allows us to make encounters both of fixed (predefined) challenge rating, as well as with a dynamic (scaled) challenge rating.

?join_party?: If set to a party, the newly generated creatures will join that party. Useful for situations where a fixed, predefined CREATURE needs flexibly defined minions/support staff.

?hiding?: (default false) If true, the newly generated creatures will (try to) be hiding.

?max_power_factor?: (default 3) This amount caps the power multiplier any single creature generated by the _encounter statement. In other words, with the default value, you will never get an _encounter-boosted spider more powerful than the base spider CREATURETEMPLATE. Tweaking this value upward will tend to reduce the size of the encounter (at the risk of creating spiders as powerful as Odin), tweaking it downward will tend to increase the size of the encounter.

?items?, ?traits?, ?paths?, ?attribute_bias? : Masterclass _encounter stuff. We will explore these another time.

?may_increase?: A list of all attributes and skills _encounter may boost in order to create the final CREATURE. By default, this is all of the attributes with nonzero values provided by the CREATURETEMPLATE.

?may_not_increase?: A list of attributes and skills _encounter should specifically not boost to create the final CREATURE. By default, this is any attribute with a zero value in the CREATURETEMPLATE.

?do_not_fail?: (default false) If true, _encounter will always produce some sort of creature on the screen (typically the base CREATURETEMPLATE). If not set true, the _encounter statement could fail to produce any result.

?power_split2? (and other arguments ending in 2): Used for the second creature group to be generated by _encounter. Also masterclass material.

?common_items? (default false): If true, the _encounter-generated creatures may be equipped with items designated with the Common_Item attribute—typically mundane weapons, light armor, and miscellaneous items of clothing.

?magic_items? (default false): If true, _encounter-generated creatures may spend some of their extra character points on uncommon items which have positive Experience_Value scores—generally "magical" items but could include rare objects of nonmagical construction

?visual_effect?: If defined, each _encounter-generated creature will be created with a visual effect atop it. This can be used for "summoning gates" and so forth. 

Area: The area the _encounter creatures should be spawned in.

xy: The point at which the _encounter creatures should appear.

templates: A list of CREATURETEMPLATEs to be considered by _encounter. One will be selected randomly to create the opposing party.

With those extensive preliminaries out of the way, we can get back to creating our harrowing spider encounter. In our scenario, the spider attack will be spawned by the PC crossing an invisible areatrigger. Despite the laundry list of options, for this encounter we only need to decide three things—how many spiders we want, how difficult we want the overall encounter to be, and which attributes are fair game to make the spiders more powerful.

Size is defined as a range. We could use a straight numerical range, such as ?size=1::5? and request between one and five spiders. More interesting may be to ensure that we have at least one spider per member of the party, while allowing for an even bigger clan. The _party_alive function returns the number of party members (other than the PC) who are currently living members of the player party. ?size=(_party_alive + 1)::(_party_alive +5)? will give us an encounter with at least one spider per living party member, up to the total party size plus four additional spiders.

Next we set the challenge level of the encounter. Challenge is expressed as a floating point number—relatively small numbers for starting characters. By default, _encounter makes a group of creatures roughly equal in power to the total power rating of the player party. There are pre-defined functions which also provide challenge ratings for simple encounters. We will use one here, and call for a challenge rating of ?challenge=_challenge_easy ()? . We could just as easily ask for ?challenge=20?, or a challenge rating based on some other computation. But _challenge_easy () will give us a group of spiders about half as powerful as the player_party—a fight the party is "expected to win." _challenge_hard (), on the other hand, is roughly twice as powerful as the player party and would provide a tactical workout for players.

Lastly, we should decide which attributes are fair game to "spend up" in order to make our spider more powerful. Recall from the spider CREATURETEMPLATE that there are six attributes with positive values:

<Strength value="10"/>
<Agility value="20"/>
<Toughness value="10"/>
<Health value="20"/>
<Brawl_Precision value="10"/>
<Movement value="10"/>

By default, _encounter will only spend up attributes with nonzero values, so we need not fear that we will suddenly end up with brainy spiders given 30 points of Judgment. However, perhaps we want to keep things very simple and assert that a "more powerful spider" can only move faster, hit with more accuracy, or be able to soak up more damage. So we will limit the legal attributes to increase to health, brawl_precision, and movement.

Our resulting _encounter will look like this:

_encounter // Start the _encounter function call
?size=(_party_alive +1)::(_party_alive +5)? // We want no fewer than one spider per party member, up to the total party size plus four (remember, _party_alive doesn't include the PC)
?may_increase=["health","brawl_precision","movement"]? // Only spend points to buy more health, brawl_precision, or movement for each spider generated
_area_shown (_xy_of _player1) // Make the spiders in the currently-displayed area, and place them as close to the PC as possible
["spider"] // We only want spiders, so that's the only creaturetemplate we ask for here. If we would accept spiders or beetles, we could ask for ["spider", "beetle"]

And that is how killer spiders (or muggers, or murderous rogue Illuminated) are born!

Last Updated ( Monday, 28 May 2007 )
< Previous   Next >