Initiative (Savage): Difference between revisions
No edit summary |
|||
Line 61: | Line 61: | ||
After putting the above code into place, we can test our data files. Create a portfolio with a number of different characters in it, then show the Tactical Console. Every time we start a new combat, each character is randomly issued a new initiative value in the range of 0 to 53. There are never any duplicates due to the use of the set mechanism. | After putting the above code into place, we can test our data files. Create a portfolio with a number of different characters in it, then show the Tactical Console. Every time we start a new combat, each character is randomly issued a new initiative value in the range of 0 to 53. There are never any duplicates due to the use of the set mechanism. | ||
=== | ===Configuring the Initiative Behavior=== | ||
When we did our testing above, there were a few things you probably noticed. First of all, a new initiative is only generated at the start of a new combat. Savage Worlds issues a new initiative at the start of each round, so we need to change that behavior. This is controlled via the "initperturn" attribute within the "behavior" element of the definition file. The default value is "no", so we need to specify a value of "yes". | |||
While we're here, we should also impose an appropriate minimum and maximum value on the initiative range. The user is allowed to adjust the value freely within the TacCon, so negative values are possible and so are values larger than the number of cards in the deck. If we only have a deck of 54 cards to work with, we need to specify a minimum value of zero and maximum of 54. This is done via the "initminimum" and "initmaximum" attributes. | |||
Applying these changes to the "behavior" element results in something that looks like below. | |||
<pre> | |||
<behavior | |||
initperturn="yes" | |||
initminimum="0" | |||
initmaximum="53"> | |||
</pre> | |||
===Forcing a Re-Shuffle=== | ===Forcing a Re-Shuffle=== |
Revision as of 05:29, 27 January 2009
Context: HL Kit … Authoring Examples … Savage Worlds Walk-Through
Overview
As mentioned in the previous section on the Tactical Console, initiative is usually pretty simple to implement. However, Savage Worlds uses a deck of playing cards for initiative. That requires a bit more work, so this topic works through the various steps involved in setting up such an initiative mechanism within HL.
Orientation
Before we launch into the changes that need to be made, we'll start with a quick orientation to how initiative is managed within the Kit.
Every game system possesses some sort of mechanic for determining the order in which characters act during conflicts. Consequently, the Kit provides a built-in framework for handling the process. The most common term used for the game mechanic is "initiative", so the Kit uses the same terminology.
The specifics of initiative range from the simple to the complex. To handle the full spectrum of games, the initiative framework within the Kit provide a fair amount of sophistication. Game systems that don't require all that sophistication can simply ignore what they don't need.
Internally, every character possesses an assortment of fields that are specific to initiative management. However, only two of these fields are exposed to you, as the author, for control. These fields track the primary initiative score for the character and a secondary tie-breaker score. As its name suggests, the tie-breaker is used to resolve situations where two characters possess the same primary initiative score. In many game systems, it's usual for ties to arise, so a mechanic is introduce to decide which character goes first.
The HL engine maintains the initiative for all characters. It automatically sorts characters into appropriate order based on the established rules for the game system. It also will automatically assign initiative values to characters, including the use of random die rolls when the game system calls for it. Provisions are made to allow users to either accept the assigned values or assign their own values. All of this is orchestrated via the Tactical Console, which is described in the User Manual for the product.
The data files are responsible for defining how the initiative score is determined for each character, as well as the tie-breaker. This is achieved via the Initiative script, which is defined within the file "definition.def". The script is invoked whenever an initiative score is needed for a character.
Two additional scripts can be defined for a game system. The "NewCombat" script is invoked for each character at the start of each new combat, while the "NewTurn" script is invoked for each character at the start of each combat turn. Both of these scripts provide the author with the opportunity to control state information for the characters. For example, many game systems have the concept of "holding" an action (although it may be called "delaying", "waiting", or something else). This state must be reset either at the start of a new combat or at the start of a new turn, and the two scripts make it easy to accomplish this.
You can dictate various characteristics of initiative for the game system. This is done via a number of attributes on the "behavior" element within the definition file. For example, you can control whether the game system generates new initiative values at the start of each turn or once at the start of the combat.
Lastly, there is a fourth script that can be defined for initiative. The vast majority of game systems use a simple numeric value to indicate the initiative score. Sometimes the score is generated randomly via a die roll, while other times it is calculated, but it is usually a number. In the few cases where the initiative score is not a number, you can define an "InitFinalize" script. This script behaves as a standard Finalize script that is applied to the initiative score for the character. This makes it possible to display the initiative to the user in whatever fashion is most appropriate for the game system.
Modeling a Deck of Cards
Savage Worlds used a deck of cards for initiative. This presents a number of wrinkles that we need to handle, the first of which is how to even model a deck of cards. There are 52 cards in a standard deck, plus the two jokers, for a total of 54 cards. This means that we can use a value in the range of 1 through 54 to represent the entire deck, with each value corresponding to a single card.
But we can't just use a random number generator, since all the cards in the deck must be unique and random numbers can be duplicated. We also need to effectively "shuffle" the deck to get all 54 values in a random order. Fortunately, the Kit provides a mechanism to generate a random set of values within a fixed range. This mechanism can be used for a variety of different purposes, but it's perfect for what we need.
Within the "state" script context, there are a number of target references that specifically pertain to managing random sets of values. The "setrandom" target reference allows us to create a new random set of values, giving it a name and the number of values to hold. We can use this to create a "deck" with 54 values in it, ranging from 0 to 53. The "setextract" target reference pulls a value (card) from the set (deck).
In the NewCombat script, we can create a newly shuffled deck of cards. In the Initiative script for each character, we can extract a card from the deck as our initiative value. The only consideration we have to worry about is that the NewCombat script is invoked for every character and we only want to shuffle a new deck once. This can be handled by keying on the "@isfirst" special symbol, which indicated when the first character is being processed.
Within the Initiative script, there are two special symbols that we need to assign. The "@initiative" special symbol represents that actual initiative value, so we extract a value from the set for that purpose. The "@tiebreaker" special symbol is used by HL to differentiate when two characters have the same initiative. Since a deck of cards is used, all values are guaranteed unique, so there is no tie-breaker in Savage Worlds. Consequently, we can set this symbol to zero.
Putting this together yields an initial two scripts as shown below.
<newcombat><![CDATA[ ~if this is the first actor, shuffle a new deck for initiative if (@isfirst <> 0) then perform state.setrandom[deck,54] endif ~reset the abandon state in case it's still set from the previous combat herofield[acAbandon].value = 0 ]]></newcombat> <initiative><![CDATA[ ~generate the primary initiative rating by drawing a card from the deck @initiative = state.setextract[deck] ~we have no tiebreaker initiative rating since the cards are always unique @tiebreaker = 0 ]]></initiative>
After putting the above code into place, we can test our data files. Create a portfolio with a number of different characters in it, then show the Tactical Console. Every time we start a new combat, each character is randomly issued a new initiative value in the range of 0 to 53. There are never any duplicates due to the use of the set mechanism.
Configuring the Initiative Behavior
When we did our testing above, there were a few things you probably noticed. First of all, a new initiative is only generated at the start of a new combat. Savage Worlds issues a new initiative at the start of each round, so we need to change that behavior. This is controlled via the "initperturn" attribute within the "behavior" element of the definition file. The default value is "no", so we need to specify a value of "yes".
While we're here, we should also impose an appropriate minimum and maximum value on the initiative range. The user is allowed to adjust the value freely within the TacCon, so negative values are possible and so are values larger than the number of cards in the deck. If we only have a deck of 54 cards to work with, we need to specify a minimum value of zero and maximum of 54. This is done via the "initminimum" and "initmaximum" attributes.
Applying these changes to the "behavior" element results in something that looks like below.
<behavior initperturn="yes" initminimum="0" initmaximum="53">