Introduction 1 Preface 1 Document Organization 1 Conventions 2 Getting Help 2 Basic Information 3 What is a script? 3 What is a script used for? 3 Character scripts 3 Object scripts 4 World script. 5 Control script 5 Magic Spells 5 Game Initialization Script 6 Dead and Resurrection 6 Basic Script Elements 7 Keywords 7 Keywords Table 8 Comments 8 Numbers 9 Tokens 9 Variables 10 Generic Variables (Local and Global) 10 String Variables 10 World Variables and Attributes 11 Object Variables and Attributes 11 Character Variables and Attributes 13 Group Variables and Attributes 14 Types of Scripts 15 Introduction Script 15 Character Script 16 Object Script 17 World Script 18 Control Script 18 Resurrection Script 18 Writing Scripts 19 Script Files 19 Expressions and Assignments 20 Function Table 21 Statements 22 Conditional Statements 22 Flow Control Statements 23 Flow control using if 23 Flow control using on-goto 23 Loop Control Statements 24 The while statement 24 The for statement 24 The foreach statement 24 Object Manipulation Statements 25 Move and Copy 25 Drop 25 Output Statements 25 Write and Writeln 25 Display 26 Input Statements 26 Getstr and Getnum 26 Select 26 Going Places 26 Animation 27 Entering Doors 27 Teleportation 27 Advanced Topics 27 Entry Points 27 Calling A DOS program 28 Creating New Types and Classes 29 New Character Types 29 New Character Classes 29 New Object Types 30 New Object Classes 30 New Object Modifiers 31 New World Types 32 Shareware Opportunities 33 Extending the magic system 33 MS-DOS based extensions 33 Writing a whole new system 34 D C - G A M E S Version 4.0 SCRIPT LANGUAGE USER'S GUIDE August 1995 (c) DC Software, 1989-1995 7908 Kettlewood Court Plano TX 75025 (214) 491-1579 Introduction Preface One of the goals of the DCGAMES adventure and role-playing game building system is to provide an environment in which you can create adventure games without having to know anything about computer programming, and without having to maintain a zillion lists of cryptic numbers. If you want to draw a river, you just do it. If you want to create a dragon, just grab the right picture and do it. The idea is to have a large enough set of objects, characters, monsters and landscaping to allow you to concentrate on the story. While this works fine most of the time, it is almost inevitable that there will be a few things you need to do that I didn't think of, or which need to work slightly different. You may need a new type of character or object, or some new magic spells. Maybe the wizards are too wimpy or elves and dwarfs should not exist in your adventure. Most of the features in the DCGAMES system are handled by scripts. The script language is a simple yet powerful language that the game driver understands, and which control the behavior of most parts of the game system. The scripts are created using a standard text editor, and can be as simple or complex as you need them to be. While you can write a complete game without writing a single line of script, a small effort on your part to learn how to write script will result in significantly better games, since you can fine-tune your creation to work exactly the way you want it to work. Document Organization This manual is organized in several sections. The first one is an introduction to the elements of the DCGAMES system. It explains each of the building blocks used to create an adventure, and how (and why) you would want to customize them. Everyone should read this section! The second section is a Reference Manual, which is a list of the features of the script language in a logical order. You will need a printed copy of that section of the manual when you are actually writing a script. Conventions In this document, the following conventions are used: UPPER-CASE-WORDS represent tokens that have a specific value and are typed exactly as shown. italic-words are used when a new concept is being introduced, and the world in italics is the name of that concept. They are also used to indicate that you should be replace the word with an appropriate name or value. bold-words represent names or values that should be typed exactly as shown. text1 | text2 items separated by a vertical bar (|) mean you get to choose one of them. [text1 ] items enclosed in square brackets are optional. If multiple items are listed, separated by a vertical bar, then you may choose one of them or none. { text1 | text2 } items enclosed in curly braces are NOT optional. You must select one of the items listed. ... three dots (ellipsis) indicate that the previous item can be repeated multiple times. If there is a limit to the number of times an item can be repeated, it will be indicated in a note near the area where the ellipsis were used. Getting Help Registered users of DCGAMES get free telephone assistance evenings and weekends. This assistance may range from explaining how a certain feature works to guidance in how to add a new feature. I might even write some specialized scripts for you (within reason). Non-registered users are welcome to call also. I will try to answer questions over the phone, but please keep your questions simple and organized. If you feel you can't afford to pay for the game, I've been known to accept a smaller amount or even waive the fee in exchange for some serious feed back or some outstanding artwork or sound recordings that I may incorporate into the shareware product. Basic Information Who should read this guide? You need to read this guide if you are already familiar with the DCGAMES system and are ready to extend or modify the system to suit a particular game's requierments. It is very important that you be familiar with the world builder program (DCWORLD) before you try to modify the scripts. What is a script? A script is a text file, created using a simple text editor (If you use a word processor, be sure to store the file in 'ASCII' or 'PLAIN TEXT' format). The script file contains the instructions that tell the game driver (DCPLAY program) how to handle most aspects of the game. The system includes a large number of predefined scripts to handle objects, characters, worlds, etc. You can modify these scripts to meet your game's individual requirements, and you can write whole new scripts to extend the number of options you have. The DCGAMES system includes a large set of predefined scripts which are used to handle your game. While these scripts are complete, you may want to modify them or write new scripts to handle your specific needs. The type of script you write depends on the aspect of the game that you want to control. The script language was designed to be easy to learn and use. The documentation was written specifically for people that have no prior exposure to programming, and the predefined scripts have extensive annotations to help you understand them and learn from them. A good thing to remember is that you cannot cause any damage through experimentation. The worst you can do is to make some changes to a script that prevent it from operating properly. All you have to do is retrieve a copy of the original script (which you saved before you modified the script, right? right!) or at worst, you can give me a call and I will help you fix it. Don't be afraid to try! What types of scripts are there? Every aspect of the game is controled by scripts to a large extent. These scripts call other scripts which in turn may call other scripts themselves. Control scripts The CONTROL script is called every time you click with the mouse or press a key on the keyboard. This script decides what action to take based on your input. Thus, while the default control script interprets the letter A to mean 'attack' and a click in the view area with the left mouse button to mean 'look-at', you can modify the complete interface to do whatever you want. The control script is also called every 'minute' of game play. Using the world builder you can specify how time flows in your game (# of moves per minute, # of minutes per hours, # of hours per day, # of days per month, # of months per year, current date, etc.). The game driver then invokes the control script to keep track of time and allow it to take time dependent actions. Game Initialization Script When the game first starts, the INITGAME script will be invoked. This script is used to present the game's story. You can use voice, music, graphics, text, animation, etc. Within this script you also have the chance to create and customize the player's character or even the whole party. The default character stored in record 0 of the statistics file (PLAYERS.DTA) will be used if you don't create one. Dead and Resurrection The RESURECT script is invoked whenever all members of the party die. In this script you have the chance to load a saved game, restart the game from the begining or even resurect the party members. The default resurection script will restore the party members a limited number of times by comparing the number of times they have been resurected with the current experience level. It then transports the party to the place where the game started. Remember that you can set the rules and do whatever you want. Some games I've seen will reduce an individual's experience as a penalty for resurection but leave them where they were. Others will teleport the party to a different location for resurection. Character scripts. When the control script determines that you want to interact with another character, it invokes the character's script to handle the interaction. Every character in your game has a character type that determines it's behaviour. The list of character types is defined in the DCCTOKEN.DAT file and the behaviour is handled by a script with the same name as the character type. DCGAMES includes a full set of character types with their respective scripts: Regular, Bartender, Beggar, Civilian, Guard, Healer, Merchant, Prisoner, Teller and Trainer. The behavior of these character types is described in detail in the DCGAMES Player's Guide. One of the best ways to become quickly familiar with the script language is to compare the description of the character type as documented in the Player's Guide with the actual script that makes the character behave that way. To create your own character types, you add the name of the character type to the list in DCCTOKEN.DAT and then create a script with that name to handle it's behaviour. If a name is longer than 8 characters, you use the first 8 characters for the script name. Note: individual characters can have their own individual script to override some or all of the character's standard behaviour. When a character has it's own script, the driver allows the character's script to handle the behaviour and invokes the default script for the character's type only if the individual script does not handle a particular action. Object scripts. When the control script determines that you want to use an object in some way, it invokes the object's script to handle the action. If the action is on an object you are carrying, the CURRITEM script is invoked. If the action is on an object you are not carrying, the OBJECT script is invoked. These two scripts handle the standard behaviour for all of the object types defined in DCCTOKEN.DAT. You can add new types to the list and modify these scripts to handle actions on the new object types. The default scritps handle Food, Weapon, Ammunition, Armor, Shield, Amulet, Ring, Potion, Scroll, Staff, Chest, Keys, Gems, Book, Gold Sack, Torch, Lantern, Rope, Hooks, Mirror, Sign, Vehicle, Thing, Door and Fence objects. You can also override an object's default behaviour by providing a tailor-made script for that particular object. Any action that is not handled by your script will be handed over to the default script for handling. You can alter the behavior of an object in several ways. You may modify the OBJECT.SCR to alter the way existing objects types work, or define new object types; You can also create a brand new script file to control the behavior of a specific object. World scripts. When the player enters or exists a world, the world's script is executed. The predefined script WORLDDEF.SCR is executed if you don't provide one of your own. The world's script can deny access to the world, or send the character to a different destination within the same world or in any other world. The file DCCTOKEN.DAT contains a list of world types (Outdoors, City, Town, Dungeon, Hideout, House, Castle, Arena, Haunted and End-Game) which you can modify at will. The world script handles entry and exit from each world, but other scripts are also involved. For example, the CONTROL script will generate random monsters only in OUTDOORS, DUNGEON and HAUNTED worlds. It also handles walking of the 'edge' of the world (if outdoors you wrap around to the other edge of the world, but in cities and towns you 'leave' the world). Magic Spells When you invoke magic by using an object, the OBJECT and CURRITEM scripts handle the action, but when a magic users 'casts' a spell, no object is involved, so a separate script is used. The CASTING script handles the casting of magic spells. For more information on magic, see the Player's Guide and the World Builder User's Guide. Basic Script Elements This section introduces the basic elements that form the script language. Just like in English you use words to build sentences, and those words are classified into verbs, adjectives, etc, so does the script language use a basic set of elements to build it's sentences. The script language contains the following basic elements: Keywords, Tokens, Constants, Variables, Structures, Statements, Functions, Procedures, Comments. Let's look at each one in turn. Keywords A keyword is a word that has a special meaning in the script language. You cannot change the spelling or meaning of the keyword, because the game system has a specific meaning for it and depends on that meaning. A primary keyword is equivalent to a verb in the English language. It indicates the action taking place. These keywords form the basis of the script language. For example, if, goto, write, etc. A secondary keyword exists only to complement a primary keyword, and has no meaning by itself. For example, the if primary keyword has four secondary keywords associated with itself, namely: then, elsif, else and endif. For example: if player.name = "Henry" and fighting then write("Go Away"); endif; In the above line, the if and write keywords are primary,while then, and endif are secondary because they have a meaning only in relation to the if keyword. (Note that and is also a secondary keyword, but has nothing to do with if I didn't highlight it). A function keyword is used to examine or modify a system value. This is a value that has a meaning to the game system, but you can examine and sometimes modify it to change the way the system behaves. For example, if the keyword fighting in the previous example has a TRUE value if the game system is currently in combat mode (a fight is taking place), so the script displays the words 'Go Away' if the current player's name is Henry and you are fighting. Note that words such as player, npc, object, world,group, etc., are called variables and their qualifiers (like player.name or world.landscape) are called attributes. These are covered elsewhere in this manual. The section Writing Scripts in this manual introduces most of the keywords using simple examples. A detailed description of each keyword can be found in the Script Language Reference Guide. List of Primary, Secondary and Function Keywords1 Comments A comment is a sequence of characters beginning with the character '!'. The exclamation point tells the script language compiler that the text that follows is a comment and should be ignored. Comments are used to document your scripts so they are easier to understand. For example: ! This is a comment ! This is also a comment! All of it.. !!! This is another comment. Note that all text following first ! is part of the comment, including any other ! character. Numbers Numbers are very important in DCGAMES. They are used extensively to identify the attributes of objects and characters. As a rule, numbers can be values between -2147483647 and 2147483647. While this is true for constants, when using numbers, you will usually have to restrict them to be within the range of values allowed for the purpose you are using the number for. For example, a ring object has an attribute called charges which holds the number of times the ring can be used. This attribute can have a value between 0 (no charges left) and 255. Trying to set the charges attribute to 500 will result in a warning message, and assign the maximum allowed value of 255. The range of values that an attribute can take are documented along with each attribute in the section entitled STRUCTURES further on in this chapter. Tokens When you write a script, you frequently need to examine and modify the attributes of objects and characters, or to perform different actions depending on the values of the same. While most of these attributes are numeric, you don't need to remember what each number means. Instead, tokens have been defined that represent the numeric values. In this document, tokens are shown in UPPER CASE. Any name shown in upper case letters can be considered to be a token. For example. The standard product includes a set of pre-defined object types such as FOOD, WEAPON, ARMOR, etc. The game uses a number to represent the object's type (0, 1, 2, 3, etc), but it would be difficult to remember that if you want to create a WEAPON, you need to set the object's type to 1. Thus, a token (namely WEAPON) can be used. A complete list of predefined tokens, their values and their usage can be found in the appendix. If you modify or extend the set of pre-defined element types, you will also add new tokens to the file DCCTOKEN.DAT, which associates the token name with the actual value it is going to represent. Once the name has been added to the file, you no longer have to remember what value you were using for your new 'type' or 'class' or whatever. Variables A variable is a name used to represent a value, just like a token, but the difference is that the variable holds a value, and the value can be modified. For example, an object could have a weight of 100, but you can change that value any time. Variables are shown in bold letters in this document. A variable may have more than one value associated with it (for example, an object has a name, a value, a weight, etc.). The values associated with the variable are called the attributes of the variable. The following paragraphs hold a complete list of all variables, their names, attributes, values and a brief description of the meaning of the associated value. Generic Variables (Local and Global) There are 2048 local variables, named L0 through L2047. They can hold values between -32768 and +32767. They are called local because they exist only during execution of the script. Once the script has been executed, any value you placed in them is lost. Every time a script starts execution, it's local variables are initialized to zero. These variables are used mostly for control purposes and to hold intermediate values. There are 2048 global variables, named G0 through G2047. These variables can hold values between -32768 and +32767. They are called global because they exist for the entire duration of the game. If you set one of these variables to a certain value, it will retain that value until you change it again. These variables are used to hold values that are important throughout the life of the game. For example, you might use one of these variables to indicate that a certain action has taken place. Other scripts could then check the value of the variable and take different actions depending on whether the action has taken place or not. String Variables There are 17 string variables, named S0 through S16. They are different from other variables in that they hold TEXT instead of numbers. They are also different in that they are used for some specific purposes, and so, are not "generic". Variable S0 can contain up to 255 characters. While you can use it for any purpose, it is also used to store any text that the player types during conversations, as well as other values. The getstr() script function asks the user to type something, and stores that value in this variable (among other things). Variables S1 through S16 can contain up to 64 characters. These variables hold the 16 lines of text associated with the current object or character. The loadtext() script function will load a given text record and place each of the lines in the corresponding variable. Character Variables and Attributes A character in the adventure can be a simple 'extra', with no other function than to flesh out a story, or it can be an integral part of it. Every character is controlled by a script, and the system includes a large number of predefined scripts to handle different types of characters. Amongst the different types of characters are: Regular, Bartender, Merchant, Civilian, Quester, Beggar, etc. Each of these character types has it's own script, and when you create a character, you will usually select one of these scripts to handle it's behavior. You may extend the functionality of each character type by modifying the scripts, or you can create brand new scripts to handle a brand new type of character. For those characters that are central to the story, you may even want to create a special script that handles their unique behavior. When referring to characters, you may talk about the player or the npc. In any interaction, the player is a member of the game player's party. The npc is the member with which the player is interacting. Character Attributes Description name Name of the character (15 characters max). index* For players, the order in the party. For npcs their location in the list of npcs. type Character Type: (0-255). See tokens in DCCTOKEN.DAT [Character Types] class Character Class (0-255). See tokens in DCCTOKEN.DAT [Character Class] block Tile # from the DCPEOPLE.nnn graphics blocks file used for this character block2 Alternate Tile # used in some instances (under script control only) picture Image file (0-999). If given, the file CPICTnnn.PCX contains the picture. voice Voice file (0-999). If given, the file VOICEnnn.RSP contains the voices. x Character's current horizontal location in the current world. y Character's current vertical locatioin in the current world. count For NPCs only, it's the # of npcs represented by the individual NPC. script Optional SCRIPT for this character. Uses the character type as default. text Optioinal text record (0-n). load/mload Current/Maximum load (how much weight can be carried) str/mstr Current/Normal strength aim/maim Current/Normal aim dex/mdex Current/Normal dexterity spd/mspd Current/Normal speed pwr/mpwr Current/Normal magical power points hp/mhp Current/Normal Hit Points iq/miq Current/Normal intelligence ac/mac Current/Normal Armor Class luk/mluk Current/Normal Luck chr/mchr Current/Normal Charisma exp Current experience points level Current character level poisoned Character is poisoned scared Character is scared paralyzed Character is paralyzed confused Character is confused invisible Character is invisible energy Current energy level (From food. See group.energy for energy from sleep). stats Character statistics record. v0 - v7 Extra variables to be used for any purpose you need. weapon Currently wielded weapon (if any) armor Currently worn armor (if any) shield Currently worn shield (if any) ring Currently worn ring (if any) amulet Currently worn amulet (if any) staff Currently wielded staff (if any) bp Currently selected backpack object (The backpack can hold 16) body Currently selected body object (if any, one of the following 6 objects). Object Variables and Attributes An object is an item that can be manipulated in many different ways during game play. The object's TYPE and CLASS determine what can be done with the object. Most of the behavior of objects is controlled from the predefined script OBJECT. This script can handle objects of type food, weapon, ammunition, shield, armor, ring, amulet, scroll, staff, chest, vehicles, etc. Object Variables Description player.weapon The weapon wielded by the current player (if any). player.armor The armor worn by the current player (if any). player.shield The shield being used by the current player (if any). player.ring The ring being worn by the current player (if any). player.amulet The amulet being worn by the current player (if any). player.staff The staff being used by the current player (if any). player.body The last selected body item (represents one of player.weapon, player.armor, player.shield, player.ring, player.amulet or player.staff. player.bp The last selected backpack item for the current player. The backpack can hold up to 16 items, but only one of them is selected at a time. npc.weapon The weapon wielded by the current npc (if any). npc.armor The armor worn by the current npc (if any). npc.shield The shield being used by the current npc (if any). npc.ring The ring being worn by the current npc (if any). npc.amulet The amulet being worn by the current npc (if any). npc.staff The staff being used by the current npc (if any). npc.body The last selected body item (represents one of npc.weapon, npc.armor, npc.shield, npc.ring, npc.amulet or npc.staff. npc.bp The last selected backpack item for the current npc. The backpack can hold up to 16 items, but only one of them is selected at a time. group.vehicle The vehicle the group is currently on (if any). object The object represented by this variable is not being carried by anyone. It exists on it's own in the current world. curritem The object represented by this variable is being carried by either the player or the npc character, either in the backpack or being worn. It is used when the exact location of the object is not important. Each of the objects listed above has the following attributes associated with it. Thus, you can type: npc.weapon.name, player.bp.count, group.vehicle.type, curritem.class, etc. Object Attributes Description name Name of the object (15 characters max). index* Current position of the object in it's place (world, backpack, etc.) type Object Type (0-255). See DCCTOKEN.DAT section [OBJECT TYPES] class Object Class (0-255). See DCCTOKEN.DAT sections [OBJECT CLASS: x, y] block Tile # from file DCOBJECT.mde used to display the object. picture Image file # (000-999). If given, file OPICTnnn.PCX contains the picture. voice Vioce file # (000-999). Objects can have a sound file also VOICEnnn.RSC weight Current weight of the object. value Current value of the object in Silver Pieces (10sp = 1gp). x Object's horizontal location (when not being carried). y Object's vertical location (when not being carried). count Number of objects represented by this single instance. script Optional script file. Uses OBJECT.SCR and CURRITEM.SCR by default. text Object's text record (if any). endgame For compatibility with DCGAMES 1.x/2.x.. 0=No, 1=on GET, 2=Give. endtext Text block # to be displayed when the game ends due to 'endgame'. v0 - v7 Extra attributes, use for anything you want. m0 - m4 Extra attributes, but you can have a token name associated with one of these. See file DCCTOKEN.DAT for more info. World Variables and Attributes Each world has a certain number of attributes which you can examine and in some cases modify. You can only access the attributes for the world you are currently in. Attribute Description name Name of the current world, text, 15 chars. index* Current world number. type World's type, 0 - 255. Tokens: OUTDOORS, CITY, TOWN, DUNGEON, HIDEOUT, HOUSE, CASTLE, ARENA and ENDGAME. x* Horizontal size (width) of the current world y* Vertical size (height) of the current world block(x,y) Landscaping block # displayed at position x,y density(x,y) Density of landscaping block at position x,y level Minimum player level needed to enter this world. landscape Landscaping file being used (0 to 9) door the door through which you entered the current world. doorx(door#) Horizontal location of the door in the current world. doory(door#) Vertical location of the door in the current world. destinationworld(door#) Destination world # . destinationdoor(door#) Destination door in the destination world. (non-trap doors only) destinationx(door#) Horizontal location in the destination world (trap doors only) destinationy(door#) Vertical location in the destination world (trap doors only) trapdoorswitch(door#) Is non-zero if the door is a TRAP (destinationx/y instead of destinationdoor). entrytext(door#) Text block # displayed when the player enters the world through the door. entrytextswitch(door#) If non-zero, the text is displayed only the first time the door is used. exittext(door#) Text block # displayed when the player exits the world through the door exittextswitch(door#) If non-zero, the text is displayed only the first time the door is used. edgedoor The door through which the player exits the current world by walking 'of-the-edge' of the world, or casting the standard 'exit' spell. Group Variables and Attributes Durng game play, your group can contain anywhere from 1 to 6 characters. Group Attributes Description size* Current number of characters in the group. current Currently selected 'spokesbeing' for the group (0-5). gold Amount of gold being carried (given in silver pieces, 10sp = 1gp). food The total amount of normal (non-magical) food being carried by the party. energy The group's energy, which is replenished with sleep. dead_count Number of times that everyone in the group has died (and thus, how many times they have been resurrected). x Current horizontal location in the current world. y Current vertical location in the current world. moves Total number of moves since the game started. block Tile # from DCSYSTEM.mde (type 'SYS_PARTY') to represent the party during normal game play. vehicle Current vehicle (if any). If the group is riding a vehicle, the vehicle's graphics block is displayed instead of the group's regular block. Types of Scripts This section talks about the different TYPES of scripts you may want to write, and tries to point out WHY you would want to write that kind of script, instead of HOW. The actual script language is presented in the section Script Language Programming Guide later in this manual. Introduction Script The introduction script (INITGAME.SCR) is a script that is executed only the first time you start playing. Like most games, you must start of by telling the game player what the story is about, give some background information, set the mood for the game. Before this script is invoked, a group with a single player is created, taking the attributes from record 0 of the statistics file (PLAYERS.DTA) as created using the DCWORLD program. The INITGAME script is free to modify the default character, as well as add other characters to the group at this time. It can also invoke the edit_character function to allow the player to select a name, character type, character block and starting attributes. You can also modify the group's starting position by seting the X and Y attributes of the group variable, or by using the teleport or enter commands. A typical introductory script would look like this: ! ! FILE : initgame.scr ! readtext( "intro.txt" ); ! Read some text viewpcx ( "intro2" ); ! Show a nice picture music ( "intro2" ); ! Play background music wait ( 120 ); ! Wait until music ends or is pressed ! ! Now, create the player's character by using 'edit_player' ! edit_player( 1, 30, ! points to distribute 9, ! Minimum start attribute value is 9 25, ! Maximum start attribute value is 25 1, ! Allow name to be changed 0, ! Don't allow character class to be changed 1 ! Allow character image to be changed ); ! Allow all stats to be changed (strenght, dexterity, etc.) CONTINUE; ! Continue with normal character creation Note that the READTEXT command has some voice, music and graphics capabilities also. The 'intro.txt' file does not necessarily display a single page of text. Character Script Every character in the game has a script to control it's behavior, except for monsters (type HOSTILE), whose behavior consists of chasing the player and fighting. The world builder assumes that the first 8 characters of the character TYPE can be used as the name of the character's script. Thus a BARTENDER's script is BARTENDE.SCR, and a BEGGAR's script is BEGGAR.SCR. The system provides 11 predefined character scripts, each of which has a unique function. A full explanation of each character 'type' as implemented by the scripts can be found in the DCGAMES User's Guide. Usually, a character script handles conversation. When the player 'talks' to a character, the character takes control of the conversation by means of the script. A merchant, for example, asks if you wish to buy or sell something, while a healer asks if you need to be cured, healed, etc. Special characters may have their own unique script, as is the case of JIMMY in the example adventure. That script does a bit of animation when the character is asked to join the adventurer, and handles special needs of that character. You should print out the character scripts and compare each of them with the description of the character type as given in the User's Guide. You will then understand how the given script implements the behavior. There are three ways of working with character scripts. You can modify the default scripts to alter the behavior of existing character types, you can create a brand new character type, with it's own script, or you can create a unique script for a unique character. Object Script Unlike characters, objects are not requried to have a script associated with them. If they do have one associated, it is invoked first to allow it to handle the interaction. If the script does not handle the interaction, or it does handle it but ends with CONTINUE instead of STOP, or there is no script at all, the system invokes one of the default object handling scripts: OBJECT.SCR is invoked for objects laying around while CURRITEM.SCR is invoked for objects being carried by the player or npc. Every time you create a new object type or even a new class within an object type, you will need to modify the OBJECT and CURRITEM scripts to handle the new object. For example, mirrors currently don't do anything. If you wanted to have a mirror that shows you an area around you, you could create mirror classes. Class 0 would be a normal mirror, while class 1 would invoke a 'view' spell. You can then modify the two scripts to check the class attribute for mirrors and behave accordingly. Note: Since version 4.0 allows one script to call another, this description is not entirely correct. The CONTROL script calls the OBJECT or CURRITEM scripts as needed, and these scripts may call others, like the CASTING script or the DESCOBJ script. Now, if you need to have a given object behave differently, you need to write a separate script for it. The script does not need to handle all actions on that object, just the ones that are different. For example: You want to create a magic ring, but this ring can cast more than one spell. You could write a special script that has an entry point for the @WEAR action (see the programming guide section at the end of this document). When the character wears the ring, your script might display the image of a genie, and ask the player what spell is desired. The script would then perform the appropriate spell. Remember that if a script does not have an entry point for a given action, then a default action is taken. In this case, the default action is to call the CURRITEM script. Thus, all actions would be handled by the CURRITEM script except for WEAR. Remember also that if your script ends with CONTINUE instead of STOP, the default action is taken anyway, so your script doesn't really have to handle the situation. For example, your 'ring' may have a 'random' effect (i.e. you never know what is going to happen when you wear it). To do this, your script would just set the ring's class (which determines it's magical effect) and terminate with CONTINUE. The default action would be taken, and the CURRITEM script would handle the actual magical effect! World Script World scripts are executed whenever you ENTER or EXIT the world. The default world script, WORLDDEF.SCR, is invoked if your world does not have it's own script. The world type and other attributes configured using DCWORLD allow the WORLDDEF script to handle most normal situations. World scripts can be very powerful tools to introduce some amount of 'sequencing' into the game. From within a script you can change landscaping, doors, etc. You can also examine and change every single object and character in that world. You could have a character that exists only after you have performed a certain action. The world script could check to see if you have performed that action every time you enter the world, and create the character only when you have done so. You can even re-route the player to a different destination within the same world, or in a totally different one. See the comments in the WORLDDEF script for a detailed discussion of entering and exiting worlds. Control Script The control script is the most sensitive script of all. It is called under different circumstances and it invokes most of the other scripts itself as needed. This script is invoked: Every 'minute' of game play (as defined in the MovesPerMinute control variable) to keep track of time and handle healing, getting tired, resting, the appearance of random monsters, etc. Every time you press a key or click with the mouse to handle the interaction between the player and the game system. Once for every player during a fight, to handle a player's TURN. Once for every monster during a fight, to handle the monster's TURN. Note: Version 3.x had entry points in the control script for handling a player leaving the party, winning a fight (for experience and random treasure), etc. These entrypoints are no longer needed because version 4.0 is more fully under script control, so these events happen in their appropriate places without special "hooks". Resurrection Script The resurrection script (RESURECT.SCR) is called whenever all members of the playing party die. From this script you have the option to give the player a second chance. Once again, you have complete control over the situation. You can terminate the game, give the player the option to restart, restore or quit, or just restore the player's hit points and continue the game. You can also transport the party to another location, and perform some cleanup activities. Writing Scripts Script Files A script can be written using any regular text editor or word processor. If you use a word processor, you should save the script in ASCII or TEXT format (with no special controls like fonts or page formatting). The script file name should have an extension of .SCR, to indicate it contains a script. Once the script has been saved, you will use the script compiler to translate the script from human readable form (text) into a compact code that the game driver understands. The translated code is written into a file with the same name as the original file, but with extension of .SCO (for SCript Object). For example: C:\DCGAME> edit myscript.scr ... you create the script using some editor ... C:\DCGAME> dir myscript.* Volume in drive C is MYVOLUME Directory of C:\DCGGAME MYSCRIPT SCR 1208 10-29-92 1:25p 1 file(s) 1208 bytes 6920192 bytes free C:\DCGAME> dcc myscript DCGAMES Script Compiler Version 4.0, August 1995 Copyright (c) 1992 DC Software, 7908 Kettlewood Court, Plano TX 75025 Compiling Script Code Size = 179 Data Size = 367 Labels = 25 Compilation successful C:\DCGAME> dir myscript.* Volume in drive C is MYVOLUME Directory of C:\DCGGAME MYSCRIPT SCO 604 10-29-92 1:28p MYSCRIPT SCR 1208 10-29-92 1:25p 1 file(s) 1208 bytes 6920192 bytes free The script MYSCRIPT is now ready to be used in your adventure. Now, every script must be translated in the above manner whenever you modify it, or the changes will not be seen by the game driver. The game driver uses the .SCO file only. To compile ALL the scripts in your current directory, type: C:\DCGAME> for %i in (*.scr) do dcc %i If you are familiar with any programming language at all, the script language will be quite easy to learn, but even if you have never learned any programming language, you should be able to learn how to write scripts without to much trouble. To assist you, the following section sections try to present the script language in easy incremental steps, so you may learn at your own pace. If you get hopelessly lost, give me a call and I will try to assist over the phone, but please give it your best shot and try to have specific questions written down when you call. It will help keep the phone call as short as possible. I urge you to annotate this document wherever you see think something being presented poorly, in the wrong order, or just plain wrong. This section is the most important one because it is the one that enables YOU to write your games. Send me a copy of the pages on which you have made notes and I will gladly correct the problem and send you back a new copy with corrections as soon as they are made. Expressions and Assignments An expression is a list of one or more symbols that represent a single value. The symbols may be variables, attributes, constants, functions or operands. We already know what variables, attributes and constants are. An operand is a symbol that tells the computer that an operation should take place. For example, in the expression 3 * 5 + 2, the * operand tells the computer to multiply the constants 3 and 5, and the symbol + tells the computer to add two values together.. In DCGAMES there are 3 types of expressions, arithmetic, relational. An arithmetic expression is one which takes numeric values (from variables, attributes, constant or functions) and performs an arithmetic operation on them. The arithmetic operands are: *, /, +, - and % (this last representing a modulo operation, or the 'remainder' portion of an integer division). A relational expression is one which compares two numerical expressions and results in a logical value (to be specific, a relational expression will always result in either a zero or a one). A logical value is either zero (meaning FALSE) or non-zero meaning true. Expressions are used in many places, but the most common use of expressions is on the right side of an assignment statement. The second most common use for expressions is as part of a flow control statement, such as if or on, which are examined a bit later. Note that the function keywords listedat the begining of this document can be used almost anywhere that you can use an expresion. A function has a value which is replaced in the position that you use the function itself. It also may have parameters that change the value of the function itself. For example, the function abs( - 3 ) has a value of 3, while the function max(-5,7,2) has a value of 7. This table presents a more detailed description of the functions, but a detailed explanation of each of them is found in the Script Language Reference Manual. Function Table Function Description General General purpose functions abs(expr) Returns the value of the expression without a sign (removes negative signs) adjustments(expr,...) Returns the sum of the attribute adjustments indicated by the expressions find(where,what,type) Find an object or character getnum(str,low,high) Display a message and get a value between low and high from the player. getstr(str,...) Get a string from the player and return the index of the matching one. locate(what) Locate an object or npc character by allowing the player to point to it. Time Related Used to control time during game play MovesPerMinute Number of moves that can be made in one minute of game play. MinutesInAnHour Number of minutes in one hour of game play. HoursInADay Number of hours in a day of game play. DaysInAMonth Number of days in a month of game play. MonthsInAYear Number of months in a year of game play. Year The current year. Month The current month of the current year. Day The current day of the current month. Hour The current hour of the current day. Minute The current minute of the current hour. SunRise The hour of the day at which the sun rises SunSet The hour of the day at which the sun sets Monster Related Used to create random monsters DefStat(0-2) Backpacks that contain likely treasure (usually Potions, Rings and Staffs). DefPack(0-3) The statistics records for SMALL, MEDIUM, LARGE and PIRATE monsters. DefLandBlk(0-4) Graphics blocks for land based monsters (ordered, 0=Easy,4=Very Hard) DefCaveBlk(0-4) Graphics blocks for cave dwelling monsters (ordered) DefWaterBlk(0-4) Graphics blocks for water dwelling monsters. (ordered, 4=Pirate Ship) DefSpookBlk(0-4) Graphics blocks of skeletons, ghosts, etc. (ordered) expr represents any expression that results in a numeric value ... means that any number of the preceding may be listed, separated by commas (up to 255 maximum) The numeric range (0-N) means that a value in the given range must be provided when referring to this variable Examples: ! Increase a player's current level player.level = player.level + 1; ! same as "inc(player.level);" ! When selling an object, increase the group's gold by half the value of the object. group.gold = group.gold - player.bp.value / 2; ! same as "dec( group.gold,player.bp.value/2);" ! Compute the amount of damage done by a weapon, taking into account the wielder's ! strength (assumes this is not a missile weapon), where strength is not important. L25 = npc.weapon.damage + adjustments(npc.str); ! NOTE: Since relational expressions return 0 if false and 1 if true, the following ! expression returns a value between 0 and 7, which is the number of attributes ! of the current npc that exceed 25 points. L7 = npc.str > 25 + npc.aim > 25 + npc.dex > 25 + npc.spd > 25 + npc.pwr > 25 + npc.iq > 25 + npc.chr > 25 + npc.luk > 25; ! Change the character's name to "Henry" player.name = "Henry"; Please note that the last assignment statement assigns a string value to the name attribute. The name and script attributes may only hold string values. Statements Just like the English language, the script language uses words and symbols to build sentences or statements which tell the game driver what to do. A statement is a complete sequence of words and symbols that tell the game driver how to perform a single given action. A complex statement consists of a one or more statements that are grouped together in some fashion to create a more complex one. You are already acquainted with the assignment statement, now let's look at some other ones, grouped by their nature or intended usage. Conditional Statements In most cases, rather than just assign values to variables, what you want to do is take different action depending on certain conditions: ! Compute the amount of damage done by a weapon, taking into account the wielder's ! strength IF the weapon is a contact weapon (i.e. not a missile weapon). if npc.weapon.class = BLUNT or npc.weapon.class = EDGED then L25 = npc.weapon.damage + adjustments(npc.str); else L25 = npc.weapon.damage; ! No adjustment for strength endif; ! The above might also be accomplished as follows L25 = npc.weapon.damage; if npc.weapon.class = BLUNT or npc.weapon.class = EDGED then L25 = L25 + adjustments(npc.str); endif; ! Now, the following statement displays the current health status of a player if player.hp = 0 then writeln( player.name, " is dead!" ); elsif player.hp = 1 then writeln( player.name, " is unconscious" ); elsif player.hp < player.mhp writeln( player.name, " is hurt, but still able to function" ); else writeln( player.name, " is healthy" ); endif; Flow Control Statements Sometimes, the if statement can result in long and difficult to read statements. In some cases, it is more appropriate to use one of the various forms of the goto or gosub statements to accomplish the same goal. In order to use these statements, you must first declare one or more labels to which the flow of the execution may be transferred. The following examples are equivalent. Flow control using if :AGAIN L3 = getstr( "Sell", "Buy", "Talk" ); if L3 = 0 then ! script for selling goes here elsif L3 = 1 then ! script for buying goes here elsif L3 = 2 then ! script for talking goes here else writeln( "What did you say?" ); endif; goto AGAIN; ! do it again and again, forever. Flow control using on-goto :AGAIN L3 = getstr( "Sell", "Buy", "Talk" ); on L3 goto XSELL, XBUY, XTALK; writeln( "What did you say?" ); goto AGAIN; :XSELL ! script for selling goes here goto AGAIN; :XBUY ! script for buying goes here goto AGAIN; :XTALK ! script for talking goes here goto AGAIN; When a script is large, a single if statement may be several pages long. It is easy to loose track of what you were trying to accomplish. The on-goto statement has the advantage of breaking the logic into separate sections, each self contained and self explanatory. A more complete analysis of the goto, gosub, on-goto and on-gosub statements can be found in the reference guide. Loop Control Statements Whenever you need to perform the same operation multiple times, a loop statement may come in handy. The following code shows a player giving a copy of everything in his/her backpack to the npc character: L6 = 0; ! Start with the first backpack object; :DOIT setbp(player.bp, L6); ! Select the Nth backpack object if player.bp.count then ! If count non-zero, there is an object copy(player.bp,npc); ! Give a copy of the object endif; inc( L6 ); ! Same as L6 = L6 + 1; if L6 < 16 goto DOIT; ! Repeat 16 times The above code uses the goto statement to create a loop that examines the 16 backpack locations for an object and then copies the objects (if they exist) to the npc. The while statement The while statement simplifies loops by providing an easy way of defining a loop without having to declare a label or writing an IF statement. Note that the test for L6 < 16 is made before the statements inside the loop are executed. L6 = 0; while L6 < 16 do setbp( player.bp, L6 ); if player.bp.count then copy( player.bp, npc ); endif; inc( L6 ); endwhile; The for statement The for statement simplifies the loop even more by allowing you to specify both the initial value, the final value and the amount by which the control variable (L6) is to be incremented (or decremented). Thus, the loop becomes: for L6 = 0 to 15 do setbp( player.bp, L6 ); if player.bp.count then copy( player.bp, npc ); endif; endfor; The foreach statement To top it of, the foreach statement allows you to select in sequence every element of a group. In this case, the group is the set of objects in the backpack. The foreach loop is executed once for each element in the player's backpack. Empty slots are not even selected, so no test is needed. Note that if the backpack has NO elements, then the statements inside the loop not executed. This is the best way of examining all the elements of a group. foreach player.bp do copy( player.bp, npc ); endfor; The foreach statement can select: a) All the characters in the player's group, b) All the objects in a character's backpack, c) All the objects a character is wearing, d) All the character's in the current world (but not in the player's group) and e) All the objects in the current world (but not in anyone's backpack). Object Manipulation Statements As you saw in the examples above, sometimes you want to move or copy objects from one place to another. Move and Copy When you move an object, it is removed from it's current place and inserted in the destination, as long as the destination has enough room for it. If there is not enough room or the destination character cannot carry the object, the object is not moved. The copy statement works the same way, but does not delete the object from the source, thus making a copy instead of moving the object. In both cases, you can specify how many objects you want to move. The command will move as many as the destination can possibly hold. If you specify that you want to move or copy more objects than are available in the source, additional objects are created. Drop When you drop an object, it is added to the list of objects in the world that you are in. The object will remain where you put it. There are no temporary objects in DCGAMES. Output Statements Write and Writeln When you want to display a value, you have several ways of doing it. The most simple one is the write or writeln statement. With this statement you can display all attributes and variables as well as text. The following example displays the time of day in the text window (assuming that the day has an even number of hours). if hour < HoursInADay / 2 + 1 then writeln( "The time is ", Hour, ":", Minute, "am" ); else L7 = Hour - HoursInADay / 2; writeln( "The time is ", L7, ":", Minute, "pm" ); endif; Display The display statement will show a list of items in the menu window, with or without numbers or values associated with it. It is useful when you need to show a list of items but are not requesting user input. The many forms of the display statement are documented in the reference guide. Input Statements Frequently, when you display something you are asking the player for directions; During a conversation, you ask the player what they want to talk about; A merchant might display a list of items and ask which you want to buy. Getstr and Getnum The getstr and getnum functions both return a number. The getstr function asks the user to type a string and searches the list of strings you provided. If a match is found, the command returns the index of the matching string (i.e. which one matched). If no match is found, the function returns a -1. In any case, the string is stored in the string variable s0. The getnum function displays a string and asks the user to enter a value in a given range. Only values in the range are allowed. If the user presses Esc instead of typing a number, the function returns -1. Select The select function displays a menu identical to the one displayed by display, but allows the user to select one of the entries by using the arrow keys. This function is used extensively, and you should study it with care in the reference guide. Going Places There are several ways in which characters and objects may move under script control. Animation All characters and any object that is not being carried by a character has a location within the world reflected by the x and y attributes of that character or object. From a script you may modify these attributes and effectively move the characters or objects within the limits of the world they are in. You can also change the block attribute to provide some additional visual feed back (as long as the character is on screen). A small example of animation is presented in the JIMMY.SCR file in the example game. When asked to join the party, Jimmy will walk over to his chest and retrieve his weapons, armor and money. He will then walk back towards the player and join the party. Automatic animation WILL be eventually handled by the system, so don't go writing animation routines for every character in your game. This kind of animation should be used in specific instances where you want things to happen that the user must not be able to prevent or should not have to do him/herself. Entering Doors The player's party may move from one location to another in several ways. The simplest one is to use the Enter command to enter a door. The party will be transferred to the world and destination that the door leads to. NOTE: The party will NOT be transferred to the new location until the script finishes execution. Teleportation If you wish to transfer the player to a specific world, you may use the Teleport command. This command allows you to specify a destination world (by number) as well as either a door in the destination world through which you wish to enter, or the actual x and y location at which the party should appear. Thus, a door need not be present in the destination world. Advanced Topics Entry Points Whenever a script is invoked, execution of the script will begin at a special label which is called an Entry Point. The entry points are labels of the form :@# where # is a number between 0 and 20, but, to make life easier, the labels have specific names associated with them, which make it easier to remember them. The entry points and the names associated with them are different for each type of script, and are shown below: You should use the name form of the entry points unless you have a very good reason for using the numbers. For Character Scripts @TALK (0) - Talk to the character @DROP (2) - Character is being asked to leave the party @CAST (11) - Character will try to cast a given spell. For Object Scripts @TALK (0) - Talk to an object. @GET (1) - Move an object into the player's backpack. @DROP (2) - Drop an object being carried. @WEAR (3) - Wear an object. @REMOVE (4) - Remove an object being worn. @LOOK (5) - Look at an object. @EXAMINE (6) - Examine an object carefully. @INVOKE (7) - Invoke the magic in a magical object (ring, amulet, etc) @USE (9) - Use a generic object for whatever purpose it is intended. @EXIT (10) - The player's party wants to get out of a vehicle. For World Scripts @ENTER (9) - The player's party is entering the current world @EXIT (10) - The player's party is leaving the current world For Control Scripts n/a (0) - Time Control Entry Point. n/a (1) - Party wants to rest for the night. n/a (2) - A member of the party wants to leave the group. For Magic Spells @CAST (11) - A magic user has casts a spell. For Game Initialization n/a (0) - Invoked at game initialization For Dead and Resurrection n/a (0) - Invoked when everyone in the party dies. Calling A DOS program From within a script, you may execute a DOS program by using the system command. This command works exactly like the writeln command, except that instead of sending a line of text to the text window, the text is formed into an MS-DOS command and executed. When the command ends execution, the MS-DOS error level is stored in the failure variable. A value of 0 usually indicates success. See the reference guide entry for additional information. Creating New Types and Classes When the current types and classes of characters, objects or worlds is not enough, you may create your own types and classes as needed. The procedure for doing this is highlighted here, the assumption is made that you have read the manuals and are familiar with the script language before you attempt to add a new type or class. New Character Types To create a new character type, you should edit the file DCCTOKEN.DAT, look for the section [CHARACTER TYPES and add an entry after the last character type in the file: [CHARACTER TYPES] REGULAR 0 ! REGULAR.SCR - Will join the party if asked to.. HOSTILE 1 ! HOSTILE.SCR - Will attack on sight and follow you.. MERCHANT 2 ! MERCHANT.SCR - Buys and Sells stuff.. BARTENDER 3 ! BARTENDE.SCR - Sells beer. Good source of information. HEALER 4 ! HEALER.SCR - Cure, Heal, Resurrect, Remove Curse,.. CIVILIAN 5 ! CIVILIAN.SCR - Will talk, but won't join.. TELLER 6 ! TELLER.SCR - Fortune Teller or Oracle type.. QUESTER 7 ! QUESTER.SCR - Asks you to find an object or person. BEGGAR 8 ! BEGGAR.SCR - Want's money. Might give you a tip. TRAINER 9 ! TRAINER.SCR - Will train someone (STR,DEX,AIM,IQ) GUARD 10 ! GUARD.SCR - Blocks your way unless given the password. PRISONER 11 ! PRISONER.SCR - Will join your party temporarily (to escape). LAWYER 12 In the above segment, the new character type LAWYER has number 12 assigned to it (the next available number). You may now write a script file called LAWYER.SCR to handle the default behaviour of lawyers. New Character Classes Character classes in the current implementation apply only to characters that join the party. The class of the character is used to determine what kind of weapons and armor they can use, what kind of magic they have, how fast they recover, etc. To create a new character class, just edit the DCCTOKEN.DAT file and add the new class to the [CHARACTER CLASSES] section: [CHARACTER CLASSES] HUMAN 0 ! standard stuff, no power ELF 1 ! fast, magical power, not strong DWARF 2 ! slow, STRONG, no magic, no missiles or shields WIZARD 3 ! slow, lot's of magic, not strong ARCHER 4 ! fast, no magic, + on missile weapons FIGHTER 5 ! fast, strong, no magic of any kind THIEF 6 In the above segment, the new character class THIEF has a number 6 (next available one). The DCBLOCK, DCWORLD, DCPLAY and DCREPORT programs will now recognize thieves as a valid character type. You may also want to modify the OBJECT and CASTING scripts to give a thief certain advantages when dealing with traps, and to enable or restrict the kinds of weapons, magic, etc, that the character can handle. New Object Types Creating a new object type is again started by adding the new type to the DCCTOKEN.DAT file. The section [OBJECT TYPES] contains the names and numbers for all object types. Unlike characters, a single script handles all object types and classes. The OBJECT script should be extended to handle the new object type for all it's entry points. The object types Food, Weapon, Armor, Shield, Amulet, Ring and Staff have special treatment because they can be worn by the characters. The Vehicle object type also has special handling because it can be used for transportation. Other than these special handling, you can modify the OBJECT script file as much as you want. New Object Classes An object class is also represented by a section in the DCCTOKEN.DAT file. It is different from other sections in that multiple object types may have the same class (for example: rings, amulets, food, potions and gems all have the same class set). If your new object is going to have the same set of class items that already exists for another type, just add the name to the list, for example: ! ! Magical Effects, Type 1 ! [OBJECT CLASS: FOOD, POTION, RING, AMULET, GEMS, WIDGET] NONE 0 ! No magical effect CURE 1 ! Remove POISON HEAL 2 ! Restore some HP POISON 3 ! (Trap) POISON drinker RESTORE 4 ! Restore ALL HP PLUS_STR 5 ! Increase STRENGTH PLUS_DEX 6 ! Increase DEXTERITY PLUS_SPD 7 ! Increase SPEED PLUS_AIM 8 ! Increase AIM PLUS_AC 9 ! Increase AC PLUS_HP 10 ! Increase HP PLUS_IQ 11 ! Increase IQ PLUS_PWR 12 ! Increase POWER Here, we have added the new object type WIDGET to the set of objects that have personal magic. You still have to modify the OBJECT script to handle the object's class. For example, on object.type goto USE_FOOD, USE_WEAPON, USE_AMMO, USE_ARMOR, USE_SHIELD, USE_AMULET, USE_RING, USE_POTION, USE_SCROLL, USE_STAFF, USE_CHEST, USE_KEYS, USE_GEMS, USE_BOOK, USE_GOLDSACK, USE_TORCH, USE_LANTERN, USE_ROPE, USE_HOOKS, USE_MIRROR, USE_SIGN, USE_VEHICLE, USE_WIDGET; . . . :USE_AMULET :USE_RING :USE_ARMOR :USE_WEAPON :USE_SHIELD :USE_STAFF writeln( "You must first 'get' it, then 'wear' or 'wield' it.." ); STOP; :USE_WIDGET writeln( "If you want to use it, you must first 'get' it.." ); STOP; . . Here, we have decided that a WIDGET must be in the player's backpack before it can be used. If your new object is different from all other objects, you can create a brand new section for it's classes in the DCCTOKEN.DAT file: ! ! My WIDGET object classes ! [OBJECT CLASS: widget] ROUND 0 ! A round widget SQUARE 1 ! A square widget OVAL 2 ! An oval widget At this point, you may create graphics blocks with type widget and class round, square or oval. You may also write script code like this: if object.type = widget then on object.class goto XROUND, XSQUARE, XOVAL; writeln( "Unknown widget class.." ); stop; endif; :XROUND ! Handle a round widget .... STOP; :XSQUARE ! Handle a square widget .... STOP; :XOVAL ! Handle an oval widget .... STOP; New Object Modifiers Each object has 5 attributes that can be used to implement it's differences from other objects. These attributes have names m0 through m4, but the object modifiers section in the DCCTOKEN.DAT file allows you to call them by other names. When you create a new object type and/or class, you may want to create new names for those fields that you might use to differentiate between them For example: [OBJECT MODIFIERS] ! Object Type: FOOD ! 0 Is not used UNITS 1 ! If magical, how many units are affected PERMANENT 2 ! If magical, how long does effect last? (0=one day, 1=permanent) ! 3 Is not used ! 4 Is not used ! Object Type: WEAPON HANDS 0 ! # of hands needed to use the weapon RANGE 1 ! Range of this weapon DAMAGE 2 ! Damage done when using this weapon. AMMONEEDED 3 ! Type of ammunition needed (See AMMOTYPE below..) ! 4 Is not used ! Object Type: WIDGET SIDES 0 ! # of sides that the widget has RANGE 1 ! Range of this widget Note that if you want to use a token that already has a value assigned, like range in the example, which has a value 1 assigned for weapons, you MUST use the same value for the token. Tokens are replaced by their numeric value during compilation, so the following two lines are equivalent: if object.hands = 7 then ... if object.sides = 7 then ... Both lines are comparing the m0 modifier of the object with the value 7. The type of the object is not checked to see that the token you are using belongs to the object's type. New World Types Perhaps the easiest to create would be a new world type. Again, just add the entry to the DCCTOKEN.DAT file, section world types, and then edit the WORLDDEF script file to handle the new world type. Note that many of the currently defined world types have no actual differences between them. For example, Cities, Towns, Hideouts, Houses and Castles are all the same.. You can change that by modifying the appropriate scripts. For example: If you want to make opening a locked chest a crime in Castles and Houses, you can add a check in the OBJECT script to verify the type of world you are in when the character tries to break a lock. Shareware Opportunities While most users will use the script language to make small changes to the game system, with a few customized scripts to handle special characters or objects, the true power of scripts lies in the ability to completely change the way everything works. Here are a few example of some more complex projects that you may want to attempt once you are comfortable writing scripts: Extending the magic system The current magic system allows a character to cast a spell if it has the required number of power points. There is no requirement to learn the spells, or to be at a certain level before you can cast it. You can change the OBJECT and CASTING scripts to handle a magic book, which can be either a class of book (currently, books don't have classes) or a whole new type of object (Magic Book). You can also change the scripts to handle a lot more spells (up to 255 of each type), or add a level requirement for each spell. MS-DOS based extensions The system command allows you to run DOS programs from within a script. The following DOS programs could be called from a script to extend the functionality of the system. Writing these extensions requires knowledge about internal structures of the game files, which I will be glad to provide on a case by case basis. Save/Restore/Restart Replace the prompts that perform this function with a window that shows saved games along with comments and let's you choose which one you want to restore, or lets you specify which slot you want to save in, and what comment you want to associate with the saved game. Character Editor Allows you to examine/modify (i.e. cheat) the PARTY file. Arcade/Casino extensions A completely separate sub-game that is executed when you enter a world. For example, when you enter a casino, you can run a DOS game that allows the user to play poker or some other games in order to make money. The program may read the PARTY file to get the names of the characters and the amount of gold they have. It would update the gold amount when the characters leave the casino. Stand Alone Utilities A nice utility would be one that can take the game and create PCX graphics files for each world, optionally including the objects and characters that appear in it. The PCX file can then be scaled and manipulated by other utilities to print maps or include the graphics in documentation. Writing a whole new system It is perfectly feasible to take the rules, character types, magic system, etc of game systems such as Dungeons and Dragonstm or Man, Myth and Magictm and write them as scripts. You would have to throw away all of the current scripts and write them from scratch, but it's perfectly feasible. Of course, these systems are copyrighted by their respective publishers, so it wouldn't be possible to distribute such a system as shareware (I think, but I'm not a copyright expert). Primary Keywords continue copy dec display drop endgame enter fight find for foreach frame getaction1 getnum getstr goto gosub if inc join leave loadhint loadtext locate move on paint pause readtext restart restore return runscript1 save savepcx1 select setbody setbp stats stop teleport vanish viewfli1 viewpcx voice vplay wait while write writeln Secondary Keywords if - then, elsif, else, endif expression - and, or, xor, not for - to, by, do, endfor foreach - do, endfor while - endwhile select, display - matching paint - screen, window Function Keywords abs action adjustments Day DaysInAMonth DefCaveBlk DefLandBlk DefPack DefSpookBlk DefStat DefWaterBlk fighting failure Hour HoursInADay keypress1 max min Minute MinutesInAnHour Month MonthsInAYear MovesPerMinute pointx1 pointy1 random success SunSet SunRise version Year 1 Keywords marked with a (1) are new in version 4.0 of DCGAMES!