Main Menu

Site Home Page

Glossary of Terms

Current Class Mod Package

Divider

Help! My mod is corrupted!

Divider

Week of June 15th, 2009

Topics:

  • Getting Help
    • The "Assistance" windows
    • The Lexicon
    • The Forums
  • Variables
    • Type-casting and the types
    • Conventions
    • Constants
  • Who Dun' It?
    • Who Spoke?
    • Who Used the Placeable?
    • Who Activated the Item?
    • Who Crossed the Trigger? Who Entered the Area?
    • Was it a Player? a DM?
  • Creating Objects
    • Preparing the Object
      • The Resref
      • The Object Type
    • At a Waypoint
      • Find the Waypoint
      • Find the Location
    • Where the player is
      • Find the Location
    • Create the Object
      • Deciding on a Tag
      • Spawning in the Object
      • Doing Things to the Object after Creation
  • Tracking Variables
    • Local Variables
    • Persistent Variables
  • Some Useful Scripts
    • Making Changes to the Avatar When It Enters the Game
    • Fiddling with the Avatar's Inventory
    • Destroying the Inventory Items
    • Destroying "Non-Destroyable" Items
    • Taking Gold From the Player
    • Giving Gold To the Player
    • Giving General Inventory Items to the Player
    • Giving Equipable Items and Forcing an Equip Action
    • Random Walk

Homework: Dungeon and Quest

Divider

Week of June 7th, 2009

Topics:

  • Items
    • Properties
    • Building your own items
    • How to make an item have a conversation.
  • Creatures
    • Properties
    • Building your own
  • Triggers
    • Choosing the right one
    • Drawing a trigger
    • Trigger Properties
    • Trigger Events and Scripting Preview
    • Examples of Trigger Use
  • Waypoints
    • Waypoint Properties
    • Waypoint Directions
    • Uses for Waypoints
    • Scripting Preview
    • How to Set Up a Patrol Route
  • Conversations
    • How they're used
    • The basic tree.
    • Branching
    • Links (or "Loop backs")
    • Tokens: Built-in and Custom
    • Colorizing the Text
    • Including Other Speakers
    • "Actions Taken" and other events
    • Conditional Nodes
  • The Journal
    • Categories
    • Entries
    • Updating the Journal through Conversations
    • Updating the Journal through Scripting
  • How to Test Your Mod
    • The Build Module Option.
    • The Real Way
    • The Test Module Option

Homework:


Divider

Week of June 1st, 2009

Topics:

  • Areas
    • Area Properties
    • Module Properties
  • Tiles
    • Tile Properties
  • Names
    • Blueprint / Resref
    • Tag
    • Display Name
  • Doors
    • Door Properties
    • Transitions between doors
    • How to make a door close itself
    • How to have a transition without a door
  • Placeables
    • Placeable properties
    • Spawning placeables.
    • How to stack placeables
    • How to have a placeable hold a conversation

Homework:

Divider

May 27, 2009

Topics

Homework

 

 

GAME CONCEPT AND DESIGN
COSC 320.101_SU09
SUMMER 2009


Events

In the Glossary (if you've wadded through it) and in the previous section, I talked about the term event. For the programmers in the group, this will not be anything new; for the non-programmers, however, it might be. So let's take this time to once again briefly discuss what an event is, why it's important to us, how we interact with them, and what some of the more common events are.

In the most common parlance, an event is when "something happens." That may seem pretty vague but it's actually quite accurate. Let's consider a non-NWN example.

When you move the mouse on the screen and then click on an icon that click generated an event. What was the event? A mouseclick. A mouseclick happened. To be even more honest, a whole bunch of events took place:

  • mouse-move occurred when you moved the mouse.
  • roll-over happened when the mouse pointer rolled onto the icon.
  • mouse-down happened when the mouse button was pressed down
  • mouse-up happened when the mouse button was released, and
  • button-click happened if the mouse button was pressed and released within a certain time-frame.

So, just to beat the idea into the ground, an event is when "something happens."

Hand-in-hand with that notion is that you'll hear programmers talk about a "message being sent." It's really just the same thing. When the mouse rolls over an icon, the roll-over event happens...but it really happened to the icon, right? So we say that the "roll-over message was sent to the icon." In a sort of converse mode of speaking, we might also say that the icon is "listening for a roll-over message." Any way that helps the concept stick in your mind works.

Events are important to us because all NWN objects (areas, creatures, placeables, even the module itself) "listen" for certain events. If the object receives an event message it then checks to see if it should run a script in response to the message. It's those scripts that cause the game to come to life.

We interact with events in two ways. First, we learn what events an object listens for. Then we provide the script that we want to have run in response to the event. Not every object listens for every event. You can find out what events an object listens for by opening the object's properties sheet and clicking on the Scripts or Events tab. There you will see a list of the events that the object will respond to and what script will be run in response.

It should also be noted that you do not have to have a response for every message. If an object receives a message but has not been provided with a script, then the object will respond by doing...nothing.

You will also find that in many circumstances--particularly with monsters--that Bioware will have already provided a default script. Right now, at our level of expertise, you will probably never have to replace, change, or remove any of the default scripts. (You might...but you probably won't have to.)

I'll probably say it again (because I tend to beat things to death that way) but I'll outline it here so that it can sit in the back of your mind and percolate. Many creatures have the same script for the same event. For example: because most of the monsters are hostile to the player, the onPerception script tends to be the same for every monster, ie: attack the player.

The danger is this: Suppose you have 24 orcs waiting for the players to show up. 23 are going to attack the player...1 will run away. The first inclination is to open the coward's onPerception script and alter it so that he'll run away. However, because they all share that script...all 24 of them will run away when the players show up! Not only that, but all the monsters everywhere in the game that share the script will run away when they see the players! In situations like that, it's best to make a new script called "cowardlyorc," write the run away code, and assign the new script to the runner's onPerception event. If you're going to use all of the default script--"but make one tiny change"--then copy the old script, rename the copy, alter the copy, then assign the copy to the one monster that's going to behave "just a bit differently."

Now let's look at some events (located in various places) that will probably be of importance when you are creating your Serious Game mod.

Module Events

  • onAcquireItem - This message is sent to the module everytime a player puts something in his inventory. Gamers amongst us might think that it might make more sense to have the item run a script when it is added to a player's inventory, but that's not how Bioware did it. (In the Item Events section, I'll explain the reasoning behind this.) What this means for you, however, is that if you want something to happen when a particular item is picked up, you must write your script in such a way as to identify the item that was picked up, then run the rest of the script only if it's the item you're looking for. This isn't really as hard as it seems...it's just a bit counter-intuitive for us.
  • onUnAcquireItem - This message is sent to the module when a player loses something from his inventory.
  • onPlayerEquipItem - There are two inventory areas. General inventory is when it's just being carried around. "Equipped" is when it's worn. Armor, for example, can be equipped. When a player equips an item, this message is sent to the module. This is typically used when you want to have something happen when an item is put on. For instance....when a ring is worn you drop the player's Dexterity score to 3 making him very clumsy. (It's a cursed ring, you see.) Just like above, your script has to identify the item.
  • onPlayerUnEquipItem - When a player removes an item from an "equip" slot this message is sent, and just like the above, your script will have to identify the item that caused the message. This message is used to either (a) set the player's Dexterity back to his original number or (b) automatically force a re-equip of the ring because....cursed items typically don't come off once they're put on.....not without a lengthy quest anyway....
  • onActivateItem - It's D&D...many items are magical! When a player uses an item, this message is sent to the module for evaluation. Again, your script will have to identify the item that was used so you can run the correct section of your script. (Again, most of us would think that the item would run the script...but it doesn't...and for the same reasons that will be described in the Item Events section.)
  • onClientEnter - Occurs when a player logs in to the module. Many of us will want to do things to the avatar at this point (change his armor or move him to a new location, etc). However, this won't work because although the account has logged in, the actual avatar has not yet appeared in the world when the message is sent.
  • onClientLeave - Occurs when the player exits the module.
  • onHeartbeat - The heartbeat happens every 6 seconds. The common advice is to use heartbeat scripts sparingly. Nearly every object in the game listens to the heartbeat and having several dozen objects all running scripts every 6 seconds can cause the computer / server to bog down.
  • onModuleLoad - When the game is first loaded into the computer and made "ready to run" this script is run. As you might presume, this script runs just once, and so is the perfect place to set up default values for an variables. (This is what I used before there was a "variables" section on the object's themselves.)
  • onPlayerDeath - Anytime a player dies anywhere...what do you want to have happen?
  • onPlayerRespawn - After a player dies, he re-enters the game. What happens when he respawns?

Area Events

  • onEnter - This event fires when a creature enters the area. It is frequently used to keep an area empty until a player enters...then to populate the area with creatures. Here is the reasoning behind that process.
    • A creature that is placed "on the map" executes his programming as long as he is on the map. If he is programmed to walk a patrol, or has heartbeat scripts, or anything similar, he will execute those scripts even if no one is around to see it happen. This means that the computer/server must take time out from whatever it is doing to run those scripts and update those unseen creatures. So, a clever programmer will keep areas empty of creatures--thus saving processing time--and only populate an area when a player enters the area. He knows when a player enters because the onEnter message will be sent to the area, so he uses that handler to put his monsters on the map. The trap is that onEnter fires every time "a creature" enters the area. Not just a player---any creature at all. So the player enters and the script fires and starts laying down creatures...except that each time a creature lands on the map onEnter fires again and more creatures are put on the map...which causes onEnter to fire again..and again..and again.... The computer will lock up because you're now in an infinite loop.
    • The solution to this is the wrap the monster-spawning code inside an if( ) test that checks to see if the entering creature is a player. If so, then the monsters get spawned. Once again, each monster causes onEnter to run, except the if ( ) test checks that creature, discovers it is not a player, so doesn't start creating the next round of beasties.
  • onExit - This fires when a creature leaves the area. Just like above, it fires for any creature that leaves. I believe that even when a monster dies and fades from the map the game considers that to be an "exit" and will send the onExit message to the area.

Creature Events

Most of these should be self-evident. Here's a couple of interesting ones.

  • onConversation - By default if a player tries to start a conversation with an NPC, the script runs the conversation it finds in the NPC's conversation property. However, it may be that you want the NPC to do something other than chat with the player in that situation. Or--more often--the NPC has several conversations that can be run so you have it run the onConversation handler, check a few game variables, then run the appropriate conversation.
  • onPerception - The computer keeps track of distances between objects. Each monster has an unseen circle drawn around it that defines how far it can "see." So, the player might be able to see the dragon, but as long as he's outside that circle, the dragon won't see him. However, if the player takes one more step forward (for example), he crosses into the monster's perception range, the monster sees him, and the onPerception event fires.
  • onSpawn - This event fires when the creature appears in the world. Unlike the module's onClienEnter, a creature's onSpawn fires when the creature is fully in the world. This is typically used when you want to do something special to the monster. You might want to give him special equipment or treasure. Frequently this is used to create corpses by spawning them and having their spawn code immediately kill them (and making sure thier properties are set so that they don't fade away). Or, you can create nice statues by spawning the creature and then having the code paralyze them, make them immobile, and cast the "Turn To Stone" spell on them. Viola! Instant statue. If you want the statue to be in a particular pose, you start the appropriate animation then delay the casting of the other effects so that you catch the NPC in mid-animation.

Placeable Events

  • onConversation - Yes, in NWN inanimate objects can have conversations. Typically, this is how signs with lots of information are used. Or you provide the player with a choice. For instance, the player clicks on the alter and you begin a conversation that says, "Do you want to make a sacrifiice?" and offers the replies of "Yes" and "No." So you build this choice as a conversation and tell the script to run that conversation. Just like creatures, the script can check game variables and then play any of a number of conversations.
  • onUsed - This is pretty much what we'd call a button-click. In NWN, it can all be a bit confusing.
    • For monsters, a click defaults to attack, unless the monster is of a compatible faction, at which point a click defaults to start a conversation.
    • For NPCs, a click defaults to conversation, unless the NPCs is of a hostile faction, at which point the click defaults to attack.
    • For placeables, a click defaults to nothing, unless the object is set to "usable." If the object is usable, a click defaults to use. If the object is usuable and is set to have inventory, then a click will open the object's inventory.

So if you want something special to happen when the user clicks on an object, make it "usable" and write a script to handle it.

If an object is set to "usable" and "has inventory" then the following events can occur:

  • onOpen - When the inventory is opened.
  • onClose - When the inventory is closed.
  • onDisturbed - When the contents of the inventory are fiddled with.
  • onLock - When the inventory space is "locked."
  • onUnLock - When the inventory space is unlocked.

Door Events

  • onAreaTransitionClick - After a door opens, the player can click on the "blue panel" to start the transition to a new area. If you want to have something happen before they transition...or have a "magic" door that connects to different areas depending on circumstances, you can run a script here to make your decision and then kick off the transition as part of your script.
  • onDamage - Players may try to bash down doors that are locked. You might want to write a script that would cause nearby monsters to attack because they "heard" the bashing going on.
  • onDeath - If a door is destroyed completly, this event fires.

Item Events

There are no item events. Items do not listen for any events. Items do not execute any scripts. It's a complete and utter pain in the behind, but here's the reason why.

It's all about the host's computer security and game security. But it's also a bit complicated and long-winded.

First, you know that if you click on a door you can transistion to another area. But did you know that if the door is set up properly, I can actually transition you to a different server entirely? You're playing the game on my computer in Baltimore, but you click the door and I can send your character to my friend Bob's game on his computer is Germany!

Secondly, you are probably aware that as the host of a game, I can say that your character will be saved on my server's hard-drive and that is the only character you are allowed to play. You might not be aware that I could tell my server that I will allow you to play any character that exists on your hard drive. So...do you have a level 22 Paladin from some other game that you want to bring into my world? Go right ahead and bring him in!

Of course, if I do that, you're going to want to bring in his Wondrous Sword of Slaying Everything I See +8.

And if I allow that, then I'd have to let it run its scripts so that it can do all its wondrous feats.

...and there lies the problem. If I--as the host of the game--allowed your items from your computer or from someone else's world to enter my world and run their scripts, all sorts of havoc could break out. How do I know that your sword doesn't have a script that automatically kills all the monsters in my game, gives you ridiculous amounts of experience points and gold, and then "steals" all the equipment from all the other players in the game, gives it to yourself, kills them, then teleports them to someone else's server? Or worse?

I don't. So Bioware's solution is to say that no items can carry scripts. This protects the host of the game, but also makes it more difficult for him to script the behaviours of special items. When a player "uses" a special item, then onItemActivated script runs. The first part of that script must identify the item that was used, then branch off and run the proper section of code. For example (and using not-real-code as an example)

ObjectUsed = GetItemActivated( );
if(ObjectUsed == "Teleport Ring")
{
   //code to teleport the player
}
else if(ObjectUsed == "Wand of Slaying")
{
   //code to slay the target
}
else if(ObjectUsed == "Cloak of Invisibility")
{
   //code to make the player invisible
}

...and so forth. If you have dozens and dozens of magic items, you'd have to have a section like this for each item which could make your script very long and ugly.