View Full Version : NWN Toolset help
Anonymous
06-21-2002, 11:39 AM
Just thought I'd start a thread for those of us messing around with the NWN toolset, so we can ask each other for help and see if anyone else has figured out how to do that thing we've been scratching our heads on.
Me, my problem is relatively simple: I've got an altar with a book in its "inventory". So far so good. I want to make it so that the quest journal is updated when it's actually TAKEN from the altar. I'd also like to know how to make it do that when it's actually READ, instead of just taken.
If I had one quick wish for the toolset, it would be for the scripting wizard to be accessible from more locations. Like the placeable objects properties-- you can easily trigger scripts "OnUse" and "OnOpen" and such, but you have to have the script made or edit it yourself right there. Where's my cool little wizard-hat icon? The wizard hat icon is my bestest friend!
Ben Sones
06-21-2002, 12:16 PM
I'll start. How do get an inanimate object to launch a conversation? I'm trying to get a well to speak (to simulate a person trapped at the bottom of the well). I can create and assign a conversation to it, but when I fire up the game and click on the well... nothing. If it's not tagged as "useable," I can't click on it at all. If it is tagged as "useable," I can click on it, but nothing happens. So what am I missing?
I'd also like to figure out how to get a line of conversation to make a new NPC appear in a specific location in another area (basically, you go to get help for the person trapped in the well; when you find the NPC that can help you (in another area), the well conversation goes away and the person trapped in the well is now standing next to it.
Suggestions?
Martinez
06-21-2002, 12:25 PM
Jason, do you have the World Builder Guide?
Page 22 explains what you may be trying to do using the "OnAcquireItem" handler.
You can have it update a PC's journal upon picking it up.
To make it so that it identifies if a book has been read, perhaps a creative use of the "OnActivateItem" handler can be used.
I haven't done much scripting myself. I'm still working on an outline! :roll:
Jason Lutes
06-21-2002, 12:46 PM
Anyone know if there's a way to stop those four or five company animations from playing when you fire up the game itself? I know I can hit escape five times, but it would be nice to be able to jump right to the main menu when I'm doing so much switching back and forth between building and testing.
Martinez
06-21-2002, 12:52 PM
I find that you can just <alt-tab> between the Main Menu and the toolset.
It's quicker than re-loading the game from the shortcut everytime.
Jason Lutes
06-21-2002, 04:21 PM
:oops: Duh -- thanks Martinez. Still, I find all those logos a pain to click through. They should just go away after the first five times or something.
Ben -- I've been trying to figure out your problem and have had little luck so far. The Worldbuilders' Guide makes it seem like it's as easy as editing the conversation from within the object's Advanced properties, but I can't get that to work.
Another approach might be to set up a generic trigger around the well that checks a local variable like "well_state" to see if the person is in it, and then initiates conversation from its OnEnter handler. Then, when you find the NPC, you can change the well_state variable to stop the conversation from triggering again.
Alternatively, you could use the trigger to perform a SpeakString over the well that says "Help!" so that the PC might then approach and examine or use the well.
Of course, how exactly to implement such a trigger has been as hard for me to figure out as most of the other scripting stuff. I finally got my guards to start walking their patrol routes, but can't figure out how to make them resume after being interrupted by the PC. Anyone? Anyone?
Jason Lutes
06-21-2002, 06:41 PM
Guys,
Found a useful page whre they're starting to build a database of working scripts:
http://nwn.lyoness.com/files/scripting.htm
Ben Sones
06-21-2002, 09:41 PM
It bugs me, though, because I know it CAN be done. BioWare did it in Chapter one (the person behind the door in the Prison Quarter of Neverwinter is actually a conversation attached to the door--you even get the door portrait). I haven't played enough to "unlock" that chapter in the toolset, though (got pretty far in the beta, but have been too busy messing with the editor to get far in the final).
Tom Chick
06-21-2002, 10:15 PM
Ben,
Here's a thread (http://nwn.bioware.com/forums/myviewtopic.html?topic=46674&forum=46) on how to get around the unlocking mechanism so you can see how Bioware did the talking door.
-Tom
Anonymous
06-22-2002, 08:20 AM
Martinez - ah, thanks. I looked but didn't see that... It's in the Module Properties that I have to set "onAquireItem" for the whole module in one big script. I was thinking it should be on the actual item's properties that one sets what happens onAcquire for that one item, but of course that's not there.
Which means I have to write the script by hand, since there's no nice little wizard-hat on that menu. GRR!
Ben - I didn't know you hadn't gotten that far in the campaign yet. I just opened it up and there's a conversation attached to the door (as with your well) and a script attached to "OnFailToOpen" that looks like this:
//::///////////////////////////////////////////////
//:: m1q2 Prison Door Conversation
//:: m1q2_PrisonDoor
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This script checks to see if Dhanis (the door
bouncer) is still near the door on the inside
of the prison. If so, the door starts
conversation with the player.
*/
//:://////////////////////////////////////////////
//:: Created By: Rob Bartel
//:: Created On: Dec 20, 2001
//:://////////////////////////////////////////////
void main()
{
object oPC = GetEnteringObject();
object oDhanis = GetObjectByTag("M1Q02Cdhanis");
object oInteriorDoor = GetObjectByTag("m1q2B_m1q2A");
float fDistance = GetDistanceBetween(oDhanis, oInteriorDoor);
if (!GetIsDead(oDhanis))
{
if (GetIsObjectValid(oDhanis))
{
if (GetIsObjectValid(oInteriorDoor))
{
if (fDistance < 15.0)
{
ActionStartConversation(oPC);
}
}
}
}
}
It looks as if most of that script is to see if Dhanis, the guard behind the door, is dead or near the door when you click on it. ActionStartConversation(oPC) seems to be the only command you really need to get it working, and then it'll trigger the conversation you already attached to it.
Of course, you're going to need to make YOUR script check to see if you've already rescued the girl, so the well doesn't still have the conversation with you after she's rescued. =)
Anonymous
06-22-2002, 08:22 AM
Oh, and the tabbing for the brackets got totally hosed in the copy/paste here. But you get the idea.
Matthew Gallant
06-22-2002, 08:31 AM
You can put code inside
tags and it will retain formatting.
Ben Sones
06-24-2002, 05:39 PM
I solved the talking object problem, and am on to bigger and better things (more on that in a bit). For the record, if you want to make an object talk, put this script in its OnUsed slot:
void main()
{
ActionStartConversation( GetLastUsedBy());
}
Of course you also need to link the object to a conversation in the "Advanced" tab.
Ben Sones
06-24-2002, 05:43 PM
Here is my new challenge. My C is pretty rusty, but I took a crack at putting together a script that will sometimes divert players to a random encounter area when they travel via an area transition.
Some background: I've set up an area exit with a conversation script, so when you click on it you get a message that says "The Western Region," and then a list of destinations (actually PC responses). That way, I can have a single exit lead to multiple possible locations, and I can add locations dynamically (via variables) when the PCs discover the location of new areas (so if an NPC tells them where to find the Lost Ruins in the Western Region, the next time they click on the Western Region exit, the Lost Ruins will appear as a possible destination).
All fine and well--I have that part working perfectly. The problem is that I decided to add a twist. I have a script that transports the PC to a waypoint in the selected region, but I wanted to add a random possibility that he would instead arrive at an encounter area, and be forced to fight some nasties before proceeding to the end destination. The random encounter area is a small area with one exit and a campfire in the middle (the PC appears next to the camp fire, to make it seem like the monsters attacked while the PC was camped). This is the script that I wrote to accomplish this (it's supposed to give a 1 in 6 chance for a random encounter):
void main()
{
int nEncounter;
object oPC = GetEnteringObject();
//Set the random encounter area
object oEncounter = GetWaypointByTag("WP_Encounter");
//Set the target destination
object oTarget = GetWaypointByTag("WP_Crossroads");
nEncounter = d6();
if(iEncounter = 6)
AssignCommand( oPC, JumpToObject( oEncounter));
else
AssignCommand( oPC, JumpToObject( oTarget));
}
It works... kind of. It does transport the PC to the random encounter area (WP_Encounter), but it does it ALL the time. Obviously, I am not understanding how the d6 function works. Or something. Any suggestions?
Anonymous
06-24-2002, 09:59 PM
I've got no idea about the d6 command, but there's one bug in your script. You need to change:
if(iEncounter = 6)
to
if(iEncounter == 6)
Because "=" is used to assign a numerical value to a variable, and "==" is a logical operator to see if something is equal. That might be all it is, I don't know.
But then you have another interesting thing. Unless you're going to make a seperate encounter location for each possible destination, you need to store the intended destination in a variable and make the exit for the encounter location area go there.
Tom Chick
06-24-2002, 11:14 PM
As soon as you guys get some stuff put together, let the rest of us know. I'm sure there are a bunch of us who'd love to test what you're doing.
As for me, I'm really intimidated by the depth of the toolset. I'm enjoying tinkering around with it, and I've been using the World Builder's Guide (aka $20 Manual Sold Separately) as a reference, but it's still mighty scary. And damned if I know what's going on with these scripts.
-Tom
mtkafka
06-25-2002, 02:29 AM
This should be retitled NWN scripting 101. I'm tired of learning new scripts for every damn game, just to script one stupid dialogue tree or merchant or m16 loadout. Actually I dont mind it if the game is good. NWN is good. So really I shouldnt be complaining since every game you want to mod or do stuff for these days, its pretty much neccesary to get C or C+ scripting under the belt.
yeah....
etc
Ben Sones
06-25-2002, 06:39 AM
Yep, thanks Jason--that was it. The typo that laid the script low. Now it's working.
Of course once I got it working I realized that it has one problem. Unlike Baldur's gate, NWN does not have players transition between areas together. So for a party travelling through that exit, it will make the random encounter check for each party member, and only some will end up at the encounter area (the rest will end up at the target destination, and wonder where everyone else went). That's kinda dumb.
So I think I'm going to create two local varables--call them nActive and nInactive. The first player that goes through the exit triggers the encounter check, and the game sets one of the two variables based on the result. If there is an encounter, the game sets nActive to 1. If there is not an encounter, the script sets nInactive to match today's in-game date (via a GetCalendarDay call).
The script will then check for sActive and sInactive before it makes the random encounter check. If the first PC triggers an encounter, then all PCs that use the exit henceforth will end up at the encounter area (beating the encounter resets sActive to 0). If the first PC does not trigger an encounter, then the game won't check for another random encounter until tomorrow (it will compare the value of nInactive to another GetCurrentDate call), so once the first PC travels through the exit safely, everyone else can also do so (until the next game day, at least).
Hmm... I'd better write all this down before I forget it.
Ben Sones
06-25-2002, 06:52 AM
Actually, you don't need to learn any scripting to make conversations (even if you want to use scripts in them, they have a script wizard) or merchants (which also have a wizard). It's just when you decide to do complicated things, like make exits that randomly transport you to encounter areas, that you need to get into the scripting language. And the language itself is pretty simple--it took me about a day to feel fairly comfortable with it. If you've ever dabbled in C before, even a little, you'll pick it up quickly. The biggest learning curve is remembering all the special NWN functions built into the scripting language, and those are all documented in the scripting editor.
For what it's worth, you don't have to make any scripts at all if you plan to run your game "hands on," as a DM. Most of the things that you do with scripting can be easily done on the fly, via the DM client interface. Handing out XP for performing quests, getting NPCs to say and do things, opening new areas, sending the PCs to specific places--all these things are easy to improvise when you are the DM.
On the other hand, I also think it's worthwhile to invest some time into learning the scripting language, because you can take some of the in-game workload off yourself by automating some things. This is much like a tabletop game--the more time you spend preparing, the less scrambling you have to do while you play.
And if you want to make modules that can stand alone as solo games, then scripting is pretty much a must if you want to do anything more complex than a dungeon crawl.
Ben Sones
06-25-2002, 07:55 AM
All right, I haven't tried this yet, but this is what I came up with:
void main()
{
//Roll the encounter die.
int nEncounter = d3();
object oPC = GetEnteringObject();
//Set the random encounter area.
object oEncounter = GetWaypointByTag("WP_EncounterFromWesternRegion");
//Set the target destination.
object oTarget = GetWaypointByTag("WP_CrossroadsFromWesternRegion");
//Encounter state variables are assigned to the party leader.
object oLeader = GetFirstPC();
//If an encounter is already active, the exit will automatically transport players to the encounter area until it is resolved.
if (GetLocalInt( oLeader, "nEncounterActive") == 1)
{
AssignCommand( oPC, JumpToObject( oEncounter));
}
//If a negative encounter check was already made today, the script will not make another check until tomorrow.
else if (GetLocalInt( oLeader, "nEncounterInactive") == GetCalendarDay())
{
AssignCommand( oPC, JumpToObject( oTarget));
}
//If neither encounter state variable checks out, the script makes a new encounter check.
else if (nEncounter < 3)
{
AssignCommand( oPC, JumpToObject( oTarget));
SetLocalInt( oLeader, "nEncounterInactive", GetCalendarDay());
}
else
{
AssignCommand( oPC, JumpToObject( oEncounter));
SetLocalInt( oLeader, "nEncounterActive", 1);
}
}
Bub, Andrew
06-25-2002, 08:01 AM
I agree with Tom, this World Building stuff is terrific (and I too have the $20 manual) but it's also confoundingly intimidating to me. Almost makes me wish I was 10 years younger. But I'd love to test what you guys are building. Particularly Lutes and Sones.
Ben Sones
06-25-2002, 08:19 AM
People are also doing some damn cool stuff for DMs, such as making special "DM items" that enhance the functions that you can access via the DM client. For instance, I pulled this one off the scripting forum on nwn.bioware.com...
"Not sure if this is a good place to put this, but since I haven't seen anything similiar yet... I've been creating a "DM's Helper" wand as I learn bits of scripting, as a way to do little things that aren't in the GUI. Currently the wand's choices for possible effects are:
If cast without a target object:
- Reload the current running module
- Change the area's weather (rainy, clear, snowy, default)
- Advance the current time of day by a number of hours
If cast on a PC or NPC:
- Display that character's stats to the wand's user
- Give that character the full area map
If cast on a door:
- Toggle the door's locked state
I have a zipfile with the exported resources here: www.why-bother-me.com/dms_helper.zip
To use:
- import the three files in the zipfile
- either set the module's OnActivateItem script to the imported dm_onactivate script or add the contents of dm_onactivate to the current OnActivateItem
- start a game, and give the DM a copy of the wand
I haven't solidified my naming conventions yet, but the scripts shouldn't overwrite anything. To be safe, import everything into a blank module first to see if there's anything that might need changing."
Jason Lutes
06-25-2002, 11:04 PM
Ben, that shit is *so* cool! I'm totally inspired by your creativity. The whole "jump to encounter area" thing is a great idea, and I'd love to see it in action. Sign me up...
I was totally intimidated by the serious scripting stuff and getting pretty frustrated (the last time I dabbled was in Basic circa 1984), until some cognitive spark fired and I suddenly started to get it. Now I'm blown away by how flexible the language is, and all of my actual game-playing has taken a back seat to worldbuilding. Having an idea and then being able to implement it is just incredibly satisfying.
I started out working on an urban thief module, which was biting off too much to chew, but it helped me learn the ropes. Now I've settled into and put a big dent in a single-player module built for a Good Paladin/Monk/Cleric PC, starting them off as a member of a religious order. One of the nice things about focusing that way is that I don't have to take into account all of the alignment/class possibilites and try to make a module that's interesting and fun for all of the permutations.
I've got two big challenges right now, both logistical:
One is that I want to use the same Area set (a keep) for two different chapters, populated by the same NPCs, but with a unique set of behaviors for each chapter. So mainly I need to do a lot of planning and bookkeeping so I can keep track of everyone.
The other is the orchestration and execution of a set piece, where a bunch of NPCs conduct a ritual centering on the PC. It's like trying to block movements and dialogue for a play or something! I've been kind of working around it because it seems like a big pain, but I know it can be done.
Anyway, I hope you keep posting your accomplishments, because they're inspiring.
Bub, Andrew
06-25-2002, 11:17 PM
I post this:
"But I'd love to test what you guys are building. Particularly Lutes and Sones."
And then Sones and Lutes make two posts that make me even more impatient. Keep at it guys. I'm working at it too. As soon as my wife leaves for her trip I'm going to sit down and make my own adventure. It'll be thrilling. You can play ANY class you want!
Dig it!
MONSTER IN THE CLOSET?
The adventure begins with a matronly NPC telling you to go to sleep. Then she says "Don't let the bed bugs bite!" and leaves the room. There's a room, a bed, a chest of drawers, and a chest. (Maybe a crate and a barrel... the crate will have 4 gold in it, just because.)
There's also a door. It's the closet. Dare you open it? Watch out! There might be a monster in there!
I'll randomize it somehow so each player meets a different monster. Maybe there'll be an orc or maybe a Red Dragon or maybe something much worse!
Nobody steal my idea...
mtkafka
06-25-2002, 11:19 PM
Oh yeah, found a link from GG forums to download a new winter tileset... looks Icewind Daleish. Very cool.
http://www.hypercubed.com/games/nwn/
etc
Jason Lutes
06-26-2002, 02:01 AM
Winter! Must. Download.
Desperate question before I hit the sack tonight: Has anyone gotten the PlaySound function to work, and under what conditions? I got a shrine to play one of the GUI noises when the PC prays at it, but now I'm trying to get Creature and Spell sounds to play (OnEnter on Triggers) and am having no luck at all. I have a trigger set up that does several things correctly (slam door, lock door, extinguish PC's torch), but I can't for the life of me get it to play two sounds along with the other functions.
Here's the script (pardon coding sloppiness):
void main()
{
object oPC;
object oTorch;
int Slammed;
object oDoor_01;
object oDoor_02;
object oDoor_03;
object oDoor_04;
string sSound_01 = "sim_pulswind";
string sSound_02 = "c_shadow_bat2";
oPC = GetEnteringObject();
oTorch = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC);
oDoor_01 = GetObjectByTag("StoneDoor_01");
oDoor_02 = GetObjectByTag("StoneDoor_02");
oDoor_03 = GetObjectByTag("StoneDoor_03");
oDoor_04 = GetObjectByTag("StoneDoor_04");
Slammed = (GetLocalInt(GetModule(), "Door_01_Slam"));
if (Slammed == 1)
{
DestroyObject(OBJECT_SELF);
}
else
{
ActionCloseDoor(oDoor_01);
ActionCloseDoor(oDoor_02);
ActionCloseDoor(oDoor_03);
ActionCloseDoor(oDoor_04);
SetLocked(oDoor_01, 40);
SetLocked(oDoor_02, 40);
SetLocked(oDoor_03, 40);
SetLocked(oDoor_04, 40);
if (oTorch == (GetObjectByTag("Torch01")))
{
DestroyObject(oTorch,0.5);
}
if (GetIsPC(oPC))
{
PlaySound(sSound_01);
ActionWait(1.0);
PlaySound(sSound_02);
SetLocalInt(GetModule(), "Door_01_Slam", 1);
}
}
}
Any and all help appreciated!
Ben Sones
06-26-2002, 05:36 AM
Interesting script! Just out of curiosity, where did you get the string names for the GUI sounds? Is there a list somewhere?
I think I may have to play with this one some. I'm not sure why it isn't working, but I've never used the PlaySound function before.
Ben Sones
06-26-2002, 06:00 AM
One is that I want to use the same Area set (a keep) for two different chapters, populated by the same NPCs, but with a unique set of behaviors for each chapter. So mainly I need to do a lot of planning and bookkeeping so I can keep track of everyone.
The quick and dirty way to do this is to make two copies of the same area (call them "Ch1 Keep" and "Ch2 Keep"). Make sure all your NPCs are on your custom Creature palette, make copies of them (so you'd have Joe NPC 1" amd Joe NPC 2"), and then drop the copy in the second area and change behaviors however you want. You can write a script to change the area transitions so that they send players to the second area after some criteria has been reached, and then you have the appearance of an area that has changed dynamically.
It is also possible to do it all through scripting, and it's not too difficult, but it might take longer. Changing conversation trees when a condition has been met is really easy. Changing where NPCs are standing is also easy--a simple OnHeartbeat (or, better yet, OnUserDefined) script that checks for a condition and then triggers an ActionJumpToObject (the object, in this case, would be a waypoint that you paint down in the new location to which you want to send them). Changing things such as patrol routes and such is trickier, but I think it can be done.
The other is the orchestration and execution of a set piece, where a bunch of NPCs conduct a ritual centering on the PC. It's like trying to block movements and dialogue for a play or something! I've been kind of working around it because it seems like a big pain, but I know it can be done.
Hmm... interesting. I think a generous helping of ActionMoveToObject (with corresponding waypoints) and SpeakString functions could handle this. I'd set up some integer variables that break the state of the ritual down into stages. I'd be interested to see what you come up with--post it when you are done (or before, if you want help from the peanut galery... ;)
MONSTER IN THE CLOSET?
The adventure begins with a matronly NPC telling you to go to sleep. Then she says "Don't let the bed bugs bite!" and leaves the room. There's a room, a bed, a chest of drawers, and a chest. (Maybe a crate and a barrel... the crate will have 4 gold in it, just because.)
There's also a door. It's the closet. Dare you open it? Watch out! There might be a monster in there!
You laugh, but that's a great starting point for a tongue-in-cheek module. Have the closet door lead to some bizarre dream landscape. Make it surreal. I'd play it.
Ben Sones
06-26-2002, 10:16 AM
By the way, if anyone wants to use any of the scripting/building tricks I've come up with, feel free. Rather than post them all in long and tedious messages, I've instead integrated them into a little module that I like to call "The Great Crossroads." I use this module as a testbed for ideas and problems that I'm trying to solve.
It's also a fully playable module, with a main adventure and several side-quests (only the main adventure shows up in your journal). Don't expect the greatest story in the world, or thrilling adventure. But there is a bit of unthrilling adventure, and a talking chicken. I don't have a "module end" script in there, however, so when you finish the main quest, you have to log out manually (or not, if you want to explore more).
If you are wondering about the odd appearance of the areas, there is a simple explanation. My planned campaign is set in a post-apocalyptic world in which a once thriving human civilization (comparable to the Roman Empire) was levelled by a magical war hundreds of years ago. The world is currently a wilderness, twisted by magic into a strange eldritch wonderland filled with weird monsters and regions permanently tainted by magic (thus the purple fog and the glowing ruins). Human settlements are sparse--most of them live in the borderlands of the Old Kingdom in loose tribes and trade settlements. The people of Burket apparently didn't get the memo, since they are living on tainted ground.
You can grab the module here:
http://www.odditorium.net/ftp/TheGreatCrossroads.mod
Things to watch for (potential spoilers, but does it really matter?):
If you take a character with a high Charisma (15+) or the Persuade skill, you can get Sparkle to join your party. You probably wan to avoid attacking her, however, since I currently have her set as a plot character (which makes her invulnerable).
The road to the Western Region uses my original system of multiple destinations for a single exit point. It also checks for random encounters (1 in 3 chance) each day, and diverts you to an encounter area if needed. Eventually I want to script the starting exit in the encounter area as a "retreat" exit, allowing you to flee the encounter back to the area you started from. Still working on that.
The sundial in Burket actually works. Another Ben Original. =)
The streetlamps in Burket turn on at sunset and off at sunrise. I can't take credit for that script--I nabbed it off the BioWare forums.
Make sure to check out the well in Burket.
Watch for the music change when you complete the main quest.
Sound objects are fun!
Bub, Andrew
06-26-2002, 10:46 AM
[quote]You laugh, but that's a great starting point for a tongue-in-cheek module. Have the closet door lead to some bizarre dream landscape. Make it surreal. I'd play it.
Yeah, but if I did that I'd have to credit CS Lewis and probably serve Turkish Delight.
Jason Lutes
06-26-2002, 11:24 AM
Mmmm, Turkish Delight.
Ben, thanks for the tips -- They will certainly come in handy. I'm going to try to solve the first problem without using two copies of the area, but I will probably have to do that in the end.
The easiest way I've found to access all of the game's sound files is through the "Sound Wizard" in the Wizard drop-down menu. There's a whole lot of extra stuff in there that doesn't show up on the sound object palette -- like all of the creature, spell, and GUI sounds. My problem may have to do with the fact that I'm trying to tie non-object (i.e., creature/spell) sounds to a trigger, but then I don't know why the GUI noise works and they don't.
Bub, Andrew
06-26-2002, 11:31 AM
Speaking of sound files...
I was in the sewers...er... the aquaducts and a text message popped up saying "Just ahead you hear the sounds of combat". I thought:
"Cool! It's like a DM telling me that!"
Then I thought:
"Wait. This is a computer game. You mean they don't have a combat sound file they could have used instead? I would have gotten the hint."
Jason Lutes
06-26-2002, 03:17 PM
Yeah, that is weird -- they do have a few different combat noise files, but maybe they realized they get really repetitive after awhile or something.
I finally solved my PlaySound problem. it turns out you can't have a trigger itself play a sound; it has to be attached to a different object. So I put down some invisible objects and used AssignCommand to get them to do their thing. Seems to work like a charm, and what a relief!
New problem: How do I get a journal entry to appear via a trigger, as opposed to through conversation? Since the PC in my module is supposed to have some familiarity with his or her initial surroundings, I want journal entries to appear when certain areas are entered, so the player can read them and get some background info (partly to get around all that initial tedious conversation stuff usually found in RPGs, you know: "Where am I?" "Who is the king?" "What year is it?", etc.)
I think I found the right function, but can't seem to get it to work. Can anyone think of a place in the single plyer game where this is done, so I can check it out?
Ben Sones
06-26-2002, 04:39 PM
They do have sound files for many things, but it's nice to have an alternative method for relaying perceptual information to players. After all, they can't have sounds for everything.
Ben Sones
06-26-2002, 04:42 PM
I just put the finishing touches (and finished debugging) my personal cross-country travel system, and I thought I'd share. Here's some background:
The goal was to create area transition exits that can lead to multiple destinations to simulate cross-country travel. For example, in my test module I have a bunch of local areas linked together via standard static area transitions, and then an exit from that cluster of local areas that leads into the open countryside. When you click on that exit, a conversation window pops open with a message that says "The road leads into the Western Region..." and gives you a list of destinations from which to choose. Click on one, and you travel there.
The cool thing is that it's very easy to script variables that add new destinations (new dialog choices) to the list when certain conditions are met. So perhaps the players meet a person who reveals the location of the Lost Ruins in the Western Region. Next time the players click on the Western Region exit, "The Lost Ruins" will appear in their list of possible destinations.
With me so far?
For extra fun, I added in a random encounter script. When you use the exit, it rolls a die to determine whether you have a random encounter on your journey. If you don't get a random encounter, it won't check again until the next game day. If you do, it diverts you from your chosen destination area to a special random encounter area. My random encounter area is basically a chunk of road with an exit at either end. The starting exit transports the players back to wherever they came from (determined dynamically), allowing them to flee. The exit at the other end allows them to continue to their original destination. In between them and that exit is a encounter trigger. The encounter area stays active (i.e. all traffic through the Western Region exit(s) gets diverted to the encounter area) until the players defeat the encounter.
Sound like something you want in your module? Here's how to do it.
1. First, you'll need to make some areas. For the purpose of this tutorial, let's make four (they can be any size and any tileset). We'll call the first one The Shady Woods, the second one The Sleepy Town, the third one The Sunny Fields, and the fourth one Random Encounter. You'll be able to travel to any of the first three areas from any other. Sometimes you'll get diverted to the Random Encounter area along the way, and will have to defeat an encounter in order to continue. Make sure that each of the first three areas has one exit. Make two exits (on opposite ends of the area) in the Random Encounter area. Name each of the exits something that you will remember (it helps to come up with a naming system BEFORE you start work on your module).
2. You will set up each of the exits in the same fashion *except* for the starting Random Encounter area exit (we'll deal with that one later). For now, choose any other exit and do the following: Under the "Advanced" tab, set the exit's faction to "Commoner" (we'll come back later and attach the conversation, after we create it). Under the "Area Transition" tab, select the "Door" destination type (leave everything else alone). Under the "Scripts" tab, add the following script to the OnAreaTransitionClick slot:
//::///////////////////////////////////////////////
//:: Object Conversation
//:: bs_obj_converse
//::
//:: Created By: Felderin
//:: Created On: 6/25/02
//:://////////////////////////////////////////////
//Launches a conversation attached to an object. For placeables, this script must be placed
//in the "OnUsed" slot (make sure the object is flagged as "useable." For doors and area
//exits, this script must be placed in the OnAreaTransitionClick slot.
void main()
{
ActionStartConversation(GetEnteringObject());
}
3. Create a conversation called "spooky_wilderness." Create a node off the Root that says "The roads leads into the Spooky Wilderness..." and then create three player response nodes off that one, like this:
Root
"The road leads into the Spooky Wilderness..."
[Travel to the Shady Woods]
[Travel to the Sleepy Town]
[Travel to the Sunny Fields]
Choose the "[Travel to the Shady Woods]" node and click on the "Actions Taken" tab. Click "Edit" and paste in this script:
//::///////////////////////////////////////////////
//:: Felderin's Cross-Country Travel Script
//:: bs_encounter.nss
//::
//:: Created By: Felderin
//:: Created On: 6/25/02
//:://////////////////////////////////////////////
//Initiates travel from a travel conversation node, and generates a random chance that the
//player will be diverted to a random encounter area.
void main()
{
//Roll the encounter die.
int nEncounter = d3();
//Get the player triggering the script.
object oPC = GetEnteringObject();
//Set the random encounter area.
object oEncounter = GetObjectByTag("EncounterDoorTag");
//Set the target destination.
object oTarget = GetObjectByTag("DestinationAreaDoorTag");
//Encounter state variables are assigned to the party leader.
object oLeader = GetFirstPC();
//Set a variable to remember the triggering player's starting location (see bs_travel_flee.nss).
SetLocalLocation( oPC, "StartingLocation", GetLocation(oPC));
//If an encounter is already active, the exit will automatically transport players to the encounter area until it is resolved.
if (GetLocalInt( oLeader, "nEncounterActive") > 0)
{
AssignCommand( oPC, JumpToObject( oEncounter));
}
//If a negative encounter check was already made today, the script will not make another check until tomorrow.
else if (GetLocalInt( oLeader, "nEncounterInactive") == GetCalendarDay())
{
AssignCommand( oPC, JumpToObject( oTarget));
}
//If neither encounter state variable checks out, the script makes a new encounter check.
else if (nEncounter < 3)
{
AssignCommand( oPC, JumpToObject( oTarget));
SetLocalInt( oLeader, "nEncounterInactive", GetCalendarDay());
}
else
{
AssignCommand( oPC, JumpToObject( oEncounter));
SetLocalInt( oLeader, "nEncounterActive", 1);
}
}
Do the same for each of the other destination nodes in your conversation, making sure to change "ShadyWoodsDoorTag" to the door tag of the target destination in each instance. Save the conversation.
4. Go to each of the exits in your first three areas and attach this conversation to them in the "Advanced" tab of the Properties window. **Be sure to flag the "No Interrupt" checkbox.**
5. The entry door (the door the players will appear at when they have a random encounter) in the random encounter area works a bit differently. Open that door's properties. Under the "Basic" tab, make sure the door's tag matches the "EncounterDoorTag" string in the bs_travel.nss script. Under the "Area Transition" tab, select the Door transition type. Under the "Scripts" tab, place the following script in the OnAreaTransitionClick slot:
//::///////////////////////////////////////////////
//:: Flee from Random Encounter Area
//:: bs_travel_flee.nss
//::
//:: Created By: Felderin
//:: Created On: 6/26/02
//:://////////////////////////////////////////////
//This script allows the players to flee from the Random Encounter area, and is intended for use
//in conjunction with script bs-travel.nss. Place this script in the OnAreaTransitionClick slot of
//the entry door to the random encounter area. Players that use this door will be taken back to
//their starting area (determined dynamically).
void main()
{
object oPC = GetEnteringObject();
AssignCommand( oPC, JumpToLocation(GetLocalLocation(oPC, "StartingLocation")));
}
Set up the second (exit) Random Encounter area door in the same fashion as the doors in all the other areas. Now you need to make the encounter itself; paint down an encounter trigger right next to the entry door in the Random Encounter area. Make sure that the players *must* walk through the trigger in order to traverse the area. The encounter can be anything you like. Open its Properties window and place the following script in the OnExhausted slot under the "Scripts" tab:
//::///////////////////////////////////////////////
//:: Encounter Switch
//:: bs_travel_switch.nss
//::
//:: Created By: Felderin
//:: Created On: 6/26/02
//:://////////////////////////////////////////////
//This script turns off the random encounter area, and is intended to be used in conjunction with
//script bs_travel.nss. Place this script in the OnExhausted slot of the encounter trigger in your
//random encounter area.
void main()
{
SetLocalInt( GetFirstPC(), "nEncounterActive", 0);
SetLocalInt( GetFirstPC(), "nEncounterInactive", GetCalendarDay());
}
You should be set. Save your module, try it out. Enjoy. =)
Bub, Andrew
06-26-2002, 05:00 PM
After all, they can't have sounds for everything.
Granted. But they do have sounds for combat. So I found it weird they'd tell me rather than "show me" that there was combat up ahead.
Jason Lutes
06-26-2002, 06:53 PM
Great stuff, Ben. Have you posted it to Bioware's NWN Scripting form? They'd love it over there.
Ben Sones
06-26-2002, 07:06 PM
Yep, I did. I'm thinking of putting together a new one: "20 uses for conversations (other than having a conversation)." I find them very useful. I'm working on a way to use them (and a few scripts) to integrate secret doors into the game.
Rob O'Boston
06-26-2002, 07:42 PM
Geesh Ben, you rock. I can't wait to get the time to start pounding out some adventures. Thanks for paving the way. I hope I get to play in some of your creations.
Murph
06-26-2002, 08:24 PM
Ditto that -- I downloaded your mod earlier, but I doubt there'll be much time for it between now and the weekend. For certain, though, this weekend, I'll give it a whirl.
Murph
06-27-2002, 08:08 AM
Thanks for making it short enough that I can play it in a quick sitting. :-)
Seriously, that's good stuff. I dig it. The atmosphere is perfect, it shows off some neat stuff (great work on the transitions!), and it made me laugh a couple of times. ("By the gods! A talking well!" "I'm IN the well, you idiot!" Fun stuff!)
I'm impressed. I'm hereby a fan. I'll download anything you create.
Oh, and I think my wizard's in love with Sparkle. I'm not sure I'll ever get him into a module that doesn't involve her.
Scott A.
06-27-2002, 11:42 AM
Nice:
Official script function documentation (http://nwn.lyoness.com/files/scripts/KeithWarner_BioWare_Script_Functions.zip)
Murph
06-29-2002, 02:01 AM
Ben: Recognize this? (http://www.gamersclick.com/tools/screenshot.cfm?image=review_nwn/02.gif)
I couldn't resist.
There's a review attached to that, by the way, for anyone that's interested. Be gentle with your criticism, though. :)
mtkafka
06-29-2002, 04:03 AM
Man, I be like all jealous and stuff at Ben's leet scripting skillz.
Bioware should pay YOU some $$$$. this is one of the better ideas I've seen yet for scripting in NWN!!! I'm actually going to use your scripts for my lazy NWN Diablo mod I've always wanted to make!!! And I'm going to say, "I made these scripts" and thus I will get all the glory and you will be mad. :twisted:
etc
Ben Sones
06-29-2002, 07:07 AM
Heh... feel free. I posted them for people to use. I'm working on some new ones for my module-in-progress; I'll post those, too, when they are working.
Powered by vBulletin® Version 4.2.0 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.