Hexen RPG specs v0.9 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=TABLE OF CONTENTS=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -=Part 1: The Fundamentals=- -<[Chapter 1: Architecture]>- -<[Chapter 2: Player Stats]>- -=Part 2: Creating Hexen RPGs=- -<[Chapter 1: Developing Plotline]>- -<[Chapter 2: Creating NPCs]>- -<[Chapter 3: Compression: A Summary, and RPGLIB.ACS]>- -=Part 3: Tips and Techniques=- -<[Chapter 1: Stats and how to use them]>- -<[Chapter 2: Spells and how hard to make your RPG WAD]>- -<[Chapter 3: New Concepts]>- -<[Chapter 4: Sleeping in for the Night]>- -<[Chapter 5: Treasures]>- -=Part 5: The Spec=- -<[Chapter 1: Compatibility Issues & Spec Version]>- -<[Chapter 2: Definition of an RPG WAD]>- -<[Chapter 3: The Reservations]>- -<[Chapter 4: World Vars]>- -=Part 99: The Addendum=- <--- This contains last minute information! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=TABLE OF CONTENTS=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -=Part 1: The Fundamentals=- -<[Chapter 1: Architecture]>- In theory, you don't need to know how it works in order to use it. However, here it is: The Hexen RPG architecture is built upon the following proven principles: 1) Hexen only saves and maintains the current cluster. Therefor, any other clusters can change as long as the CURRENT cluster remains the same. 2) Players "carry" their global variables with them. This allows them the keep their "stats" as they move from cluster to cluster, and from level to level. Principle 1 allows for the first part of the Hexen RPG architecture. It allows for a "layering" of WADfiles. In other words, say that you have three WADfiles: WAD_A, WAD_B, and WAD_C. WAD_A & WAD_C both, in their MAPINFO lumps have an 8th cluster that contains only one level: MAP64. However, only WAD_B contains a level for that map. Now, lets say the player types in the following: Hexen -file WAD_B.wad WAD_A.wad Then the player starts the game. WAD_A replaces level 1, so the player starts in WAD_A. Then, when the player is finished, he is teleported to level 64 IN WAD_B! Now, the player saves, quits, and then types in the following: Hexen -file WAD_B.wad WAD_C.wad Lets say that he restores his game, and then walks through a porthole which takes him to level 1, which WAD_C replaces. Now, the player has managed to travel FROM ONE WAD TO ANOTHER. Also, thanks to principle 2, the player has been able to keep his experience, gold, weapons, artifacts, etc! This is the Hexen RPG architecture. -<[Chapter 2: Player Stats]>- If you read Chapter 1, then you know that Principle 2 states that a player can basically carry all of his stuff with him. These, then, are the "stats" of a player encoded into world vars... The first four stats are actual concrete things that speak for themselves, and although used often in a Hexen RPG, are more of "measures" then of semi- perminant properties, and change often as the player plays: [Experience] (exp) - Think of this as the equivilent of how many "points" a player has. Players recieve these points, also called experience, by killing monsters, doing good deeds, etc. [Gold] (gp) - Gold, money, they're both the same. A player can find gold, get paid for doing something, sell a treasure, etc. Players can spend gold on buying various items. [Level] (level) - A level is a form of rank given to the player when he has recieved a certain amount of experience. The proccess of gaining levels is called "advancement" [Magic Level] (Magic level) - A player's "Magic" level a measuremnt of how adept a player is at magic. It also measures how powerful the player's spells can be. These next and last six stats are "properties" and are rarely increased except during advancement, and are assigned by rolling dice: [Strength] (str) - How strong a player is. This is used, say, to see how well a player can move heavy boulders blocking caves. [Constitution] (con) - Basically a measure of stamina. It measures how long a player can hold on without dieing. This is used, say, to see how long a player can walk across a desert before getting tired. [Intelligence] (int) - How smart a player is. This is used in spellcasting and in finding secret doors. [Charm] (chr) - This is an overall index that takes into account looks, politeness, how well you get along with other people, etc. [Wisdom] (wis) - How wise you are. Used when praying to the gods. [Dexterity] (dex) - How agile you are. Used when, say, walking on a narrow ledge. -=Part 2: Creating Hexen RPGs=- -<[Chapter 1: Developing Plotline]>- RPG is an abbreviation for Role-Playing-Game, not Shoot-All-The-Monsters-And- Move-On-Game. RPGs should have a well thought out plotline in which the player plays an important role: The Hero. As such, you need to think in terms of both quests for the missing whatevers and interacting with charactors such as the Cleric Boss. Here is a draft of a plotline I am working on entitled, "The Doomsday Clock": -=SNIP=- Cog walks into the Plane of Garbunzi, where the Apocalypse is about to take place. A clock stands in the middle, ticking away the remaining seconds of the Plane. Also, a path leads to the Desert of the Sands of Time, which, apparently, has nothing in it. Cog will talk to the merchant, maybe haggle on some prices, learning about the clock, etc. However, nothing REALLY special will happen until the player enters the Caverns of Zharn. He will look around, and eventually stumble across a wall with an impression of a mask on it. He will then leave the Cavern and look around some more, noticing a cave entrance that has risen in the Desert. He will walk in, and the Guy* there immidiately starts talking. He tells the player that if he can find Yorik's Skull, he will be rewarded. He also gives the player Zharn's Mask. The player takes the mask and puts it in its proper place on the wall in the Cavern. Immediatly, an Earthquake starts and the player manages to leave just in time (for which he recieves experience). A mysterious voice tells the player that its name is Zharn, and thanks the player for the awakening. Zharn rewards the player with Yorik's Skull. The player takes the skull to the Guy in the Desert and the Guy gives the player a 200 gp reward. He then sends the player into the clock. * for that's what the person called himself The player is then attacked by the Guardian, an Ice Guy. Upon its defeat, each of the four gods test the player. After each test, the player is teleported to the next one. One test is a test of skill. If the player is a fighter, he must move a boulder then kill a room full of Ettins. If the player is a mage, he must walk across a narrow walkway, and then recieves experience. He must then choose one of two books, the correct one being pointed to thanks to an intelligence check (if the player fails, the wrong one is pointed to.) If he fails, he is teleported back to the beginning of the test. (He does not recieve the experience from crossing the second time.) If the player is a cleric, he must walk across a gigantic chasm. If he passes a wisdom check, then a magical path- way appears. Otherwise, he falls... Another test is a test of the player's fighting ability. He must destroy a room full of Reivers. Yet another test is a magical maze. In the forth and final test, the player must choose between deliverance (for which he is killed) and risking his life to save the Plane (for which he must kill another Ice Guy, and then is teleported into the Clock.) In the clock the player must destroy the four gear shafts of the clock and pick up the removed gears. He then exits. -=SNIP=- Although this is far from the "ultimate RPG", I admit, it does contain several interactive charactors, especially the Merchant. Although Raven and ID write plots to match levels, RPG WAD authorers need to match levels to plots. In fact, I almost wrote the entire plotline without a single monster except for the "guardian" IceGuy! A thing I shall get into in more detail later is the use of interactive NPCs. Put simply, an interactive NPC is a dormant monster that is rigged in such a way that the player can talk to it (in limited Multiple-Choice speech), and that the player can fight with it if he/she wants. This should be another major plotline, allowing players to perform quests for actual charactors, instead of just for their own purposes (e.g. quest for the gear to sell to the NPC, not just quest for the gear to put in the clock. A mixture of the two kinds of quests is your best option). Note: From now on, when I refer to an "interactive NPC", I will simply refer to it as an NPC. -<[Chapter 2: Creating NPCs]>- NPCs take a quite bit of scripting and level design to create, but its worth it. This section is a form of how-to guide to making NPCs. Note: NPC stands for Non-Playing-Charactor. Using a different but similar anocrym (which I never use), the player can be called the PC, or Playing- Charactor. First off, put an ettin (or some other creature) wherever you want it in the level and make it dormant. Now, draw three "boxes" around it. They should all be pointing (e.g. their 1st sidedefs should be pointing) away from the ettin. Make the distance from the inner one to the ettin 2 units, and the distance between the sides of the boxes to units each. Now the player will barely know that they are there. Make the inner box Impassible, and set its use type to "Projectile Impact" (Impact, for all of you Hck users out there). Make the 2nd closest box's use type "Projectile Cross", and the outer box's use type "Use". Now, set the inner two boxes' linespecials to Line_SetIdentification, and then tag them with, say 51 (although any unique number will do). Set the outer box's linespecials to Line_SetIdentification as well, but instead tag it with, say, 52. (again, any unique number will do) Now write an open script to set the inner two boxes' linespecials to ACS_Execute, and have it execute whatever script you want it to execute. Do the same with the outer box, but have it execute a different script. The inner two scripts should do the following: A) setlineblocking(51/*or whatever*/,OFF); - this frees the NPC so it can attack the player. B) Thing_Activate({Insert_NPC_Thing_Number_Here}); - this has the NPC actually attack the player C) clearlinespecial(51); - this is so the player D) clearlinespecial(52); can't accidently start a conversation with the guy after he gets killed (if he gets killed...) The outer box I'll get to later. But, at the moment we have an NPC who won't attack the player when he approaches it, but which will respond to an attack. If you want, you can have the attack a little more complex. I like to give the player five warnings before the attack, but its YOUR WAD, do what you want. Also, another idea is that the Impassible lines could stay Impassible, and instead of clearing the linespecials, the player has the chance to actually talk to the NPC and try to make peace. By now, hopefully, you should have already written a "script" (movie type script, not Hexen script) for the charactor that includes what he/she says, and the various choices that the player has to respond. For example, here is another draft, only this time of the Healer I was planning to put in my WAD. -=SNIP=- -<{([charactor: Healer Thing_Type = Cleric Boss 1-"Hello"- "WE ARE DOOMED! WE ARE ALL DOOMED! WOULD YOU CARE TO BUY ANYTHING?" ^1-"Hello"- "HELLO. WHAT IS IT YOU WISH TO CHEAT ME OUT OF TODAY?" 2-"What do you sell?"- "VITALITY ENHANCEMENT PRODUCTS INCLUDING HEALTH VIALS, POTIONS, AND URNS." 3-"'HAGGLE!'"--- branches 3.1-"Umm, about your prices..."- "WHAT ABOUT THEM?" "They are a little, well, steep." PASSED- "A MAN'S GOT TO MAKE A LIVING! OH WHAT'S THE BOTHER, THE WORLD'S GOING TO END ANYWAY. I'LL LOWERED EACH PRICE BY 50 GP." FAILED-"WELL, TIMES ARE HARD, NOW AREN'T THEY?" 3.2-"I demand that you lower your prices, now!" PASSED-"*CHUCKLES* WELL, WE CAN'T ALWAYS GET WHAT WE WANT, NOW CAN WE?" FAILED-"YOU GREEDY MAN, GET OUT OF MY SHOP! THE PRICES HAVE JUST BEEN RAISED BY 200 GP APIECE! HA! NOW CONTEMPLATE YOUR LIFE AS THE WORLD DISSOLVES INTO LAVA..." ^3.1-"That we can't. PLEASE!! PLEASE!!!"- PASSED-"SIGH, ALL RIGHT ALREADY! HERE, THE PRICES HAVE BEEN LOWERED BY 100 GP EACH EXCEPT FOR THE VIAL." FAILED-"YOU'RE A GROWN MAN, SO STOP BEGGING ALREADY!" 4-"Tell me about..."-branched 4.1-"The Clock." "THE CLOCK HAS BEEN HERE SINCE THE BEGINNING OF TIME. HOWEVER, IT HAS ONLY STARTED RECENTLY. UNTIL NOW, IT WAS NEVER KNOWN WHAT IT WOULD DO. BUT, THEN, THE KORAX CAME. HE OFFERED US GREAT POWERS, BUT AT TOO GREAT A PRICE. WE TURNED HIM DOWN. HE LEFT THEN, BUT RIGHT BEFORE HE LEFT HE TOLD US:" "HAHAHAHAHA! THE APOCALYPSE, ONCE DORMANT, TICKS DOWN AGAIN! HAHAHAHAHA!" 4.2-"The Cavern" "ZHARN, THE ANCIENT HIGH PRIEST, WAS BURIED IN THE CAVERN, BUT HIS SOUL HAS NEVER DEPARTED THE PLACE. IT IS RUMORED THAT THE MAGICAL MASK OF ZHARN CAN AND WILL AWAKEN HIM AND RELEASE HIS SOUL FROM THE CAVERN." 4.3-"The Skull of Yorik" "LEGEND SAYS THAT THERE WAS ONCE A FORTH SERPENT RIDER, NAMED YORIK, BUT HE BETRAYED AND WAS EXECUTED BY THE OTHER THREE. HIS SKULL, ONCE HELD BY ZHARN, IS AN ANCIENT AND PRICELESS ARTIFACT. IT IS SAID THAT ONCE REUNITED WITH HIS BODY, HIS SPIRIT SHALL INHABIT IT ONCE MORE. OR SO LEGEND SAYS..." -=SNIP=- Now, lets say that your NPC's conversation, at the moment, gives the player five choices (four + the "END CONVERSATION" choice). This is something like how your conversation script (the one run by the outer line) should start out with: TalkL_1 = "Choice 1" TalkL_2 = "Choice 2" TalkL_3 = "Choice 3" TalkL_4 = "Choice 4" TalkL_5 = "END CONVERSATION" Now, place five switches in front of the NPC. They should be 32 pixels lengthwise and 8 or so wide. The side of the switch that is the switch should be the one that will face towards the player and away from the NPC. It should have the "mouth" switch texture, and the line special should be Line_SetIdentification. Also, the use type should be "use" on all switches, and their floor height should be 0. Unfortunately, at the moment all switches HAVE to be at floor height 0 (so that it blends into the floor, you don't want the player to know that they are there!) for this to work. Sorry, but there are reasons why this is. Now, "number" each switch consecutively from the leftmost (from the player's point of view) switch to the rightmost switch, so that if the leftmost's number is, say, 1, then the 2nd leftmost's number would be 2, the 3rd 3, etc. Note: By number I mean to "tag" (using Line_SetIdentification and setting arg1) both the line and the sector of the switch with the same number. Now, add this line to your conversation script: ACS_Execute(C_MultiChoice,X_MapID,1,5,{Insert_Script_Number_Here}); The ACS_Execute part is obvious, and the X_MapID part I'll get to later in the file. C_MultiChoice is a script that will do the following: 1) Raise each switch, from the switch number 1 to the switch number 5, to a floor height of 32, tag them to execute an internal script, and display the preposed choice string to the player. 2) When the choice is made, it is shown to the player as all the switches lower. It clears the switches' linespecials, and runs the {Insert_Script_Number_Here} script with the choice number chosen by the player as the script's first argument. Note: Allow me to clarify something here. The 1 and 5 are the numbers of the switches. The number passed to your script is based on which switch is the 1st (in this case, number 1) and which is last (in this case, number 5). If the first switch's number was 99, and the last switch's number 104, then if switch 99 was used it would be passed on as choice 1, switch 100 choice 2, etc. This is to make things easier on you. So, as a summary, this is what the script C_MultiChoice takes. The first script arg (right after X_MapID) is the number of the first switch, the 2nd script is the number of the last switch, and the 3rd is the number of the script that you want called with the choice number when the player makes his choice. From that point on, its all up to you. -<[Chapter 3: Compression: A Summary, and RPGLIB.ACS]>- Picture this: You have written a plotline for the ULTIMATE RPG, with tons of stuff that NPCs do, and plenty of story, background, flexibility, etc. One problem: You've run out of variables. "AARRRGGGHH!" you scream, and you start to work on another ideal. You murmer to yourself about how its so pointless to waste precious variables on things like flags and stuff. WELL WORRY NOT! Did you know that all Hexen vars are 31 bits long? (Well, actually 32, but the 32nd is used to find out whether is positive or negative, so that's close enough...) Now think about this carefully, if you use a whole variable for a flag (a number that will be either 1 or 0), you have only used 1 of the bits, and wasted the other 30! However, thats where Compression comes in. Through use of a series of powerful yet simple algorithms, you can encode other things INTO THOSE OTHER 30 BITS! For information on the routines that use this, see the API Docs in Chapter 4. There is a chart in RPGLIB.ACS that illustrates how many variables you can compress with how many bits, and the maximum number that each compressed var can hold. NOTE: There is only one serious disadvantage to using my compression routines, which is that the variable you want compressed into another CAN'T BE LARGER THEN 255 (8 bits)! If you need to compress anything larger than that, you will need to incorporate the compression code directly into your source VIA copy and paste. Fortunately, the code is very easy to understand*, and all you need to do is replace a couple of the variables with hard-coded numbers. Put simply, directly incorporating the code is no big deal. * some of it is even documented via. comments! :) In order to make your RPG scripting life easier, I have taken the liberty of writing several routines that remove a large burden off of your back. One such routine is the C_MultiChoice script. Also, it includes a script that does the work of displaying the player's gold, experience, and level number for you! Each routine has a define. Except in your WAD file*, where you need to know the actual script numbers, this gives you two powerful advantages: 1) You don't have to memorize script numbers, you can just memorize the names! 2) Added portability. In order words, I can change the numbers of all the scripts AND YOUR CODE WON'T NOTICE THE DIFFERENCE! * as opposed to your script file Now, in order to use this library of scripts, you need to have the following lines of code AT THE VERY BEGINNING OF YOUR SOURCE CODE: #define X_MapID #### #include "rpglib.acs" Two points. First, the #### is filled in with the number of the map of the script file. This is used in RPGLIB to call other RPGLIB scripts. Use this, and you can, for the most part, change your MAP number from 1 to 50 and your scripts will never notice the difference! Second, you do not need to include COMMONS.ACS, this is already done for you. -<[Chapter 4: The API]>- The API is comprised of over 25 scripts that should make your scripting life easier. In the near future (I don't have the time now) I plan on releasing a version which will rename all of the scripts and seperate several of them in order to be able to ease the restrictions placed on script numbers (see Part 3). These are in no kind of order, and sometime perhaps I'll catagorize them. IMPORTANT WARNING: As you probably already know (took me weeks to figure out :), the ACS_Execute special DOES NOT LIKE SCRIPT ARGUMENTS OVER 255! Therefore, if you EVER need to pass along a number larger then 255, you may need to directly copy and paste the code into your script. Usually, this will be no big deal, and there are few scripts that will ever need arguments over 255. #define 99=C_SampleScript(arg1,arg2,0) returns arg3 This is only an example. As you can see, the C_SampleScript is the name of the script, and represents the number 99. The returns word, often not used, means that some kind of result will be placed in the variable C_Result. It then gives that result an arbitrary name (not a real one, just a name for the purposes of description). The 0 means: put a zero here 'cause I mean nothing. [arg1] - Put a special value in me. [arg2] - Put an even specialer value in me! [arg3] - When its done, you'll get a special value out of me! #define 1=C_GiveExp(exp,sm,0) This script, most useful in thing specials, gives the player some experience and displays a message to the player. [exp] - The amount of experience to be given to the player. Note: You cannot give the player more then 250 experience in this argument. However, there is an "extended experience set" availuable if you need to give the player more experience then 250. This is based on the monsters that give more then 250 experience: 251: 300 exp 252: 350 exp 253: 1000 exp 254: 5000 exp 255: 20000 exp [sm] - Put a 1 in here if you want to suppress, or not show the message to the player. Otherwise, put 0. #define 2=C_GiveGold(gp,sm,0) Same as C_GiveExp, only gives gold instead of experience. [gp] - The amount of gold to be given to the player. [sm] - Put a 1 in here if you want to suppress, or not show the message to the player. Otherwise, put 0. #define 3=C_GiveBoth(exp,gp,sm) This script gives the player both gold and experience. [exp] - The amount of experience to be given to the player. [gp] - The amount of gold to be given to the player. [sm] - Put a... ...0 in here and it will display both messages with a one second pause between them. ...1 in here to only suppress the experience message ...2 in here to only suppress the gold message ...3 in here to suppress both messages #define 4=C_MultiChoice(ss,es,callscript) See the section on creating NPCs in chapter 2. [ss] - The number of the first switch. [es] - The number of the last switch. [callscript] - The number of the script you want called when the player makes his choice. #define 7=C_Speech(wait,0,0) This simplifies drawing conversation. Put the name of the charactor (say, "HEALER") into the variable TalkC, the line you want him to say (say, "HELLO") into TalkL, run C_Speech, and the following will be displayed: HEALER: 'HELLO' [wait] - The amount of time, in tics, you want C_Speech to wait before terminating. Put a 0 in here to have it wait 70 tics (2 seconds) #define 8=C_SpeechFromLineNum(wait,lines,0) This is like C_SpeechFromLineNum, only instead of using TalkL, it uses TalkL_#, where #= the number of the line you want used. At the moment, its limited to TalkL_1 through TalkL_5. The code is fairly simple, so if you've got the spare map vars you can add more. [wait] - The amount of time, in tics, you want to wait before terminating. Put a 0 in here to have it wait 70 tics (2 seconds) [lines] - The # of the TalkL_# you want used instead of TalkL. #define 9=C_DiceTest(stat,hilow,0) returns STAT_Result This is used in "checks". "Checks" are times when the player must roll below his stat (or in some cases above) in order to pass a test. Moving a large boulder requires a Strength check, for example. This returns whether the player passed the check or not. [stat] - The number of the stat that you want tested. Look in RPGLIB under the V_ defines. This routine shares these defines with the compression scripts C_GetVar and C_SetVar. [hilow] - Put a 1 here if the die roll needs to be higher then the stat for the player to pass the test, otherwise put a 0 here if the player needs a lower die roll. [STAT_Result] - returns a 1 if the player passed, a 0 if he didn't #define 10=C_DiceRoll(count,sides,0) returns DICE_Result This simulates rolling COUNT, SIDES sided dice, totaling the rolls, and returning it. [count] - the number of electronic dice you want thrown [sides] - the number of sides per die [DICE_Result] - the total roll of the electronic dice #define 11=C_Dialogue(wait,sl,lc) This script automatically prints several lines (TalkL_s) of dialogue. Basically ends up running C_SpeechFromLineNum several times. [wait] - the number of electronic dice you want thrown [sl] - the number of the first TalkL_ you want printed [lc] - the number of lines after and including the the first TalkL_ to be printed #define 18=C_SecretDoor(linenum,0,0) Put this as an ACS_Execute on a line that you want to open the secret door. This script automates the process. See Part 3 for more information on this routine. [linenum] - The number of the sector & line of the secret door. #define 19=C_Grunt(0,0,0) Each charactor class has a different grunt, and this routine plays the grunt of the charactor class of the player. #define 21=C_BuyItem(gpCost,spawnSpot,spawnItem) This automates the process of having the player buy something. It will make sure that the player has enough gold, and then will spawn the spawnable thing SPAWNITEM at SPAWNSPOT. If the player doesn't have enough gold, it will inform the player of that. [gpcost] - The price of the item. Note: This must be 250 or less. Otherwise, you need to incorporate this code directly into your routine. Considering it is less then ten lines of code long, and that it is very simple, this should be no real problem... [spawnSpot] - The TID of the place you want the item spawned at. [spawnItem] - The number of the spawnable thing you want spawned. #define 22=C_SellItem(gpCost,0,0) This is, of course, only meant to be used for treasures and puzzle items. Run this script using Use_PuzzItem, and it will automate the process of selling an item of the player. [gpCost] - The price of the item. Note: This must be 250 or less. Otherwise, you need to incorporate this code directly into your routine. Considering it is less then ten lines of code long, and that it is very simple, this should be no real problem... #define 23=C_InitSecretDoor(lineID,0,0) This prepares your secret door to be used by the player. [lineID] - The number of the line & sector of the secret door. #define 6=C_TellSpellType(spellNum,typeNum,chargeCount) This tells the player what kind of magical item he has picked up. Attach this as a thingspecial to an item (preferably ALL ITEMs, but one will usually suffice), and the player will see what he has picked up when he picks it up. Note: This shouldn't be used on fletchetts! See Part 3 for more information on how this script should be used. [spellNum] - the number of the spell, see RPGLIB.ACS for the list [typeNum] - the type of the artifact, see RPGLIB.ACS for the list [chargeCount] - the number of charges in the artifact #define 24=C_FTalkOn(0,0,0) F_Talking is a special flag which temperarily turns off the stat display on the top of the screen. This script turns this flag on. See Part 3 for more information. #define 25=C_FTalkOff(0,0,0) F_Talking is a special flag which temperarily turns off the stat display on the top of the screen. This script turns this flag off. See Part 3 for more information. #define 26=C_SleptYet(int sleepTeleSpot,0,0) This determines whether the player has slept recently or not, and if he hasn't slept recently, he is teleported to sleepTeleSpot and a flag is set so that he can't sleep again for ten minutes. #define 12=C_EncodeVar(newVar,bitNum,varNum) input var; returns theNewVar This script will "compress" a variable into another variable. This script is a rare one that actually requires you to put something INTO C_Result before running the script. As you can see, I will refer to that number as "newVar". See Chapter 4 for more information. [var] - the original var; the var you want newVar compressed into [bitNum] - the number of bits per compressed variable in VAR [varNum] - the number of the position (1 through maximum_number) you want newVar encoded into [newVar] - the var you want encoded into VAR [theNewVar] - the result; the original var with newVar compressed into it. #define 13=C_DecodeVar(0,bitNum,varNum) input var; returns aVar This script does the opposite of C_EncodeVar. It takes VAR, and decompresses a compressed var from it. See Chapter 4 for more information [var] - the original var; the var you want newVar decompressed from [bitNum] - the number of bits per compressed variable in VAR [varNum] - the number of the position (1 through maximum_number) you want newVar decoded from [aVar] - the var decompressed from VAR #define 14=C_EncodeBit(0,bitNum,newBit) input var; returns newVar This script encodes a bit into VAR. [var] - the original var; the var you want newBit encoded into [bitNum] - the number of the bit you want newBit encoded into [newBit] - the bit you want encoded into var [theNewVar] - the result; the original var with newBit encoded into it. #define 15=C_DecodeBit(0,bitNum,0) input var; returns theBit This script decodes a bit from VAR. [var] - the original var; the var you want newBit decoded from [bitNum] - the number of the bit you want newBit decoded from [theBit] - the result; the bit decoded from VAR #define 16=C_SetVar(varNum,newVar) This script automatically encodes vars that are used often. For more information, see Chapter 4. [varNum] - the ID of the var you want to encode (see RPGLIB for the list) [newVar] - the var you want to replace the variable number varNum with #define 17=C_GetVar(varNum) returns var This script automatically decodes vars that are used often. For more information, see Chapter 4. [varNum] - the ID of the var you want to decode (see RPGLIB for the list) [var] - the variable that was decoded -=Part 3: Tips and Techniques=- By now, you probably know just enough to make an RPG WAD, but if you want to learn to take advantage of the more powerful features of RPG WAD authoring, read on! Also, make sure to read the addendum (Part 99) either way. -<[Chapter 1: Stats and how to use them]>- Several times in this document, I mention "checks". A "check" is when you roll a twenty sided die (from here on referred to as 1d20, or 1 x 20 sided dice). If the roll is LESS then the player's stat being checked, then the player succeeds, passes, etc. Otherwise, the player fails. There are tons of places where this can be used. Moving a boulder out from in front of a cave, walking along a VERY NARROW pathway (if the player fails the check, cue very slight earthquake that makes a hard walk impossible, when the player is on the middle of the pathway. heh heh heh...), praying to the gods, haggling with a merchant, reading a book of an ancient language you don't know, and seeing if a player can walk across a large desert without dieing, growing tired, etc. Use checks often in your RPG WAD. Also, if the player is about to control some really powerful magic force, try making a magic level check, only instead of rolling a 1d20, roll a 1d10. Note: At this time C_DiceTest does not support any magic level checks, so you will need to implement this manually. -<[Chapter 2: Spells and how hard to make your RPG WAD]>- First off, when you go to make your RPG WAD, try to think about what level charactor it will be designed for. If its going to be a low level (like, say, level 1) it should be fairly easy considering the player will go through it with only his fist! Also, because the RPG WADs are going to be fairly easy (but not too easy!), don't put tons of riches, treasures, gold, artifacts, and weapons into a RPG WAD meant for a level 1 charactor unless it is REALLY HARD and meant to advance a charactor SEVERAL LEVELS ON EXPERIENCE FROM KILLING MONSTERS ALONE! Even then, remember that it should be extremly unusual for a charactor to manage to find HIS SECOND WEAPON before LEVEL 4! Even then, players have to earn their weapons, so always remember: The number of goodies in your level should be just enough with little excess, if any, to conquer your RPG WAD. However, when the RPG WAD is being written for, say a level 13 charactor, the rules have changed significantly. The player, by then, expects some great challenges to gain large amounts of experience. Also, by that time the player has probably gained the second and third weapons, and possibly one piece of the forth weapon. At that point, you should be able to make TOUGH WADS. Don't just put tons of bad guys in it, make the puzzles more complex as well, and the quests and NPCs harder to deal with. Don't just count on monsters making an RPG WAD hard. Also, feel free to leave plenty of goodies around, but don't be too generous and leave, say, more then 1, maybe 2 Icons around! In fact, even though you have more of a liberty of leaving goodies around, do not take that to mean that you should leave large amounts of treasures, artifacts, etc. Also, by this level the player should have picked up some excess from other RPG WADs. Note: At the time of this release there will be NO RPG WADS IN EXISTANCE! Therefore, I would reccommend that RPG WAD authors start by writing WADs meant for level 1 and/or level 2 players. Only when there are plenty of these should people start writing WADs for level 3-20 players. -<[Chapter 3: New Concepts]>- This chapter deals with new standerds of doing things in RPG WADs. To add variety in the RPG WAD, it is recommended that instead of thinking of artifacts as just artifacts, think of them as spells. In your RPG WAD, don't think of artifacts as simple artifacts think of them as spell charges. One spell charge is equal to one use of a spell. Note: There are two types of artifacts that I will refer to here. One is the artifact mentioned in the Hexen manual (e.g. anything, save puzzle items, that is picked up and put in the inventory), the other is a kind of spell container which I will refer to as an "artifact". When you go to put artifacts in your RPG WAD, think of them not as artifacts, but as scrolls, "artifacts", wands, and staffs. Scrolls are spells which are written down on paper, and once read the writing fades away. "Artifacts" are magical objects that contain a spell, and which are usually more powerful (some spells only appear as "artifacts"*) and are rarer than scrolls. Wands are enchanted columns of wood that are "waved" to perform the spell inside them. 99% of the time wand spells are only long range (e.g. they shoot something, they perform some action against someone else, etc), so the spells, when cast, usually must to be aimed at something. Staffs are, well, staffs that contain spells. They are usually considered more powerful than wands (some spells only appearing as staffs*), rarer then wands, and 99% of the time contain spells which either have a short range effect (something that only affects the user) or shoots something out in all directions (e.g. a repulser). Scrolls and "artifacts" are simple, and all you need to do is add script C_TellSpellType to the artifact to tell the player what he/she has picked up. Wands and Staffs, however, are slightly more complex. To make them, you have to place several artifacts in the same place, and add to one or all of them the C_TellSpellType script. * as opposed to appearing as scrolls or wands Usually, when you make secret doors, you simply make a door and then add the "Secret Door" flag to it. Well, in the Hexen RPG you need to do more then that. You see, in the Hexen RPG secret doors can only be found with a successful intelligence check, at which point the door will become obviously visible, and the player will get a small amount of experience. In order to automate this, you simply need to do the following to each of your secret doors: 1) Create the door and add the "Secret Door" flag. 2) Change the linespecial of the door's line that is the secret line that must be found by the player, to "Line_SetIdentification" 3) Tag both the line mentioned previously and the sector with any number you choose, providing that the two have the same number. 4) Add the following line of code to one of your OPEN scripts: ACS_Execute(C_InitSecretDoor,X_MapID,insert_number_here,0,0); scriptwait(C_InitSecretDoor); -<[Chapter 4: Sleeping in for the Night]>- It would be a good idea to include a place in your adventure where the player can "sleep in for the night". "Sleeping in for the night" is basically when a player can either completely heal, or can rememorize a spell. To accomplish this, place a "bed" somewhere in a room (maybe a merchant will sell keys to such a room), and when the player walks onto the bed, have it teleport the player to a room. At that room, he should be given two choices, complete healing, or rememorization. If he chooses complete healing then he is teleported to a room with tons of health vials, then teleported back to the bed. If the player chooses rememorization, he is teleported to a room with one artifact for each spell ("spells" including all artifacts except for puzzle items, healing items, and fletchetts), and the player is offered a choice between all of the spells within his spell level (see GIVAWAYS.ACS for the list of spells & spell levels). The player receives the spell of his choice, and then is teleported back to the bed. Two things to note. First, the player can only sleep about once every ten minutes. Instead of directly teleporting the player, run C_SleptYet* with the teleport landing spot you want the player teleported to. It will handle that automatically. Second, it might not always be a good idea to allow the player to "Sleep in", if, say, either the player will always be kept on his toes, or if the RPG WAD is so small that it is not worth it. * In essense, C_SleptYet checks the V_sleptyet flag, and if it is 0, sets it to 1 and teleports the player. -<[Chapter 5: Treasures]>- Globally excepted treasures (treasures that can be carried with the player from RPG WAD to RPG WAD) are the following Puzzle Items: ZZ_GemBlue1, ZZ_GemGreen1,ZZ_GemRed,ZZ_GemPedestal. They are the ONLY puzzle items at this time that the player is allowed to take with him when he exits an RPG WAD. All others must be either used, or the RPG WAD must run several UsePuzzleItems to rid the player of them. Each gem has a certain price, and the higher the price, the rarer the gem. For the list of gem prices, see GIVAWAYS.ACS. These treasures can be a reward, found, bought, and sold. ZZ_GemBlue2 and ZZ_GemGreen2 may NOT be used as the same kind of gems that ZZ_GemBlue1,ZZ_GemGreen1, and ZZ_GemPedestal are! -=Part 5: The Spec=- This section is just a lot of technical information on the spec itself. All the same, it is worth reading. Also, it contains IMPORTANT information on reservations made on world variables, map variables, and script numbers. -<[Chapter 1: Compatibility Issues & Spec Version]>- The current version of this spec is 0.9. It is, in a sense, a prerelease version that will allow me to see if anything major needs to be changed. However, unless there is reason to make EXTREME CHANGES, all new versions of the spec should be BACKWARDS COMPATIBLE. In theory, the only changes that shall ever need to be made are changes in the style of RPG WADs, and other related things. As long as the hard core remains the same (and there is no real reason why it shouldn't), or at least nothing is removed, then the RPG WAD system will still continue to work, as the player will still be able to use his old charactor in the new version. I plan on going to v1.0, providing there is enough interest, support, and WAD development, by the end of August. One of the main reasons that this is only v0.9, is because I was pressed for time to get this released. (BTW, I will not be able to read e-mail replies until Mid-August, but all the same you should be able to send them, and they should remain in my mailbox until I get back, but no guarantees.) I plan on making the following changes to the spec: 1) I will run some experiments, and will quite potentially REORGANIZE all of the script numbers! Unfortunately, I did not have enough time to do this before the release of 0.9. If you use the defines I gave you instead of directly calling script numbers, then you probably will barely notice the change. Also, I intend on keeping any scripts that are meant to be called by line specials the same, so don't worry about it, it should be a harmless little change. 2) I will probably also redo the BASE WAD in order to allow sleeping for the night before the next departure. A transition WAD will be included to help the player make the transition. 3) As I am able to perform more experiments on the limits of Hexen, I will probably release some of the reservations I made. -<[Chapter 2: Definition of an RPG WAD]>- An RPG WAD is any WAD that conforms to the RPG WAD technical specs and guidelines, and is "swappable" (e.g. starts on level 1, upon ending teleports player to level 64. In both cases, Player Start Spot number 0 is used.) Also, it SHOULD include the RPGLIB.ACS file, but if it doesn't, then it MUST include the code that runs the status display. Also, it MUST include the "BASESTUB.LMP" file in its MAPINFO lump. -<[Chapter 3: The Reservations]>- All reservations are version-dated. 0.9 -=<{([ All scripts from 1-50, and scripts 900 and above are RESERVED. 0.9 -=<{([ At minimum, RPGLIB needs only 1 map var to run. However, in order to access the speech & MultiChoice NPC interaction features, you should have at lease 8 map vars. You will literally have to comment out routines if you want to get rid of map vars, but NEVER comment out C_Result! 0.9 -=<{([ All MAPs from 60-64 are RESERVED. 0.9 -=<{([ Clusters 8 and above are RESERVED. 0.9 -=<{([ All world variables except for 48-64 are RESERVED. 0.9 -=<{([ Puzzle items: ZZ_GemBlue1,ZZ_GemGreen1,ZZ_GemRed,ZZ_GemPedestal are RESERVED. -<[Chapter 4: World Vars]>- World variables truely are a player's perminant stats. The player will carry them around FOREVER. As such, there are only a certain amount to go around, but they are indeed available on request (although requests will have to wail until Mid-Augusts). In your request you must include the following information: NAME E-MAIL ADDRESS NUMBER OF BITS NEEDED SOURCE CODE THAT WILL USE WORLD VAR (it must prove that you can get by with no less then the number of bits you need) WHY THE WORLD VAR IS NEEDED HOW IT WILL BENEFIT THE RPG COMMUNITY There is no guarantee that the bits will be designated, so A) Be SURE that there is no other way. B) Be SURE that there is a REALLY GOOD REASON! Unless the world vars fill up to quickly, if you follow the above two guidelines, you probably will get your bits. -=Part 99: The Addendum=- <--- This contains last minute information! First off, I would like to apologize if there is something really dumb that I missed. I figured that during the two weeks in August I would be gone, that more work could be done by others then if I had waited those two weeks and then perfected the system. At the moment, I can't find anything wrong with it, but then again, there might have been something I missed. Also, I will try to finish "The Doomsday Clock", my first stab at writing an RPG WAD, as soon as I get back. Thank you for your patience. Because these specs are v0.9, and Therefore are destined for improvment, if you write an RPG WAD for these specs, or start playing the Hexen RPG, then consider yourself a beta tester. If you have a VERY useful script that you think should be part of the RPGLIB API, e-mail me. Note: 99% of the information in this document is tried and true*. Unfortunately, some of it may need some tweaking to get to its full potential. The only completely untester/untried thing is the C_SleptYet script. * RPGDEMO was both a last minute demonstration WAD and an API tester/ concept tester. My e-mail address is: cogmc@prodigy.com My snail mail address is: Gregory Crosswhite 4022 Foreston Rd Beltsville, MD 20705-2825 USA