Here you can find a number of resources for builders that I am posting as I come across them. To a certain extent, this is my own personal development journal, but I'm posting it with the idea that others may find it useful.
If you have suggestions, requests, questions, etc. please let me know.
Registration is open to all and only requires a verified email address. If you are an authenticated user, you can contribute to the resource book by clicking the "Add child page" link. These contributions will go into the moderation queue for review.
Authenticated users can post comments, but all comments must first be reviewed for approval. Comments may be promoted into the body of the page, then cleaned up for legibility, or incorporated as child pages.
Please remember that the goal is to create a concise and easy-to-use reference that brings together as much of the knowledge-base from the community as possible. And thanks in advance for your contribution!
Here you will find resources and tutorials for getting started.
The official nwn2 documentation can be found in the "Documentation" folder of your Neverwinter Nights 2 folder. So if you installed it in the default location, you would find it at:
C:\Program Files\Atari\Neverwinter Nights 2\Documentation\nwn2toolsethelp.html
NWNmaster over at nwn2toolset.com has a great set of tutorials for getting to know the toolset. His current list of topics include:
Navigate around the Toolset
Toolset Controls
Create an Area
Interiors
All about Terrain
Texturing
Grass
About Water
How to add a Start Location
Create Door Transitions
Add Placeables
Walkmesh
Baking
How to link up areas
Head on over to nwn2toolset.com to check it out:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/gettingstarted.html
Carlo has created a great tool for creating DM-friendly modules. The DMFI Base Mod for Builders comes complete with several commonly used tools that will keep builders from burning time on the systems needed for a good DM-run module. Here's the excerpt from the page on nwvault:
The base mod includes as custom content (hak files with accompanying scripts) the DMFI Tools for NWN2 and Heed’s PC Tools, which are widely considered within the NWN2 community to be essential DM and player client enhancements. A few individual scripted DM tools are also included as well as some small but useful other community scripted content. The mod includes several easily selectable and extensible death, bleeding, respawn, and rest systems. All content is documented and appropriately credited in the included Builder's Guide.
The mod is designed to be a foundation that can be adapted and modified as desired by builders. It is also designed to be accessible for novice builders, being extensively commented and with only one script necessary to edit to select the desired rulesets from the toolset. Furthermore, DMs (and players if you wish) can select among the rulesets in-game by using the included module control book item.
The mod is structured so that builders who wish to take advantage of existing features may do so, while those who wish to make extensive additions and modifications should find it easy to change or remove included elements.
Most builders will want to use the full version with Heed’s PC Tools included, but for flexibility’s sake a lite version without them is also included in the download package.
I'm proud to say that a few of the things I created for A Stop Along the Way made it in there!
Another great resource you should check out is Gilthonym's Don't Panic: The Hitchhiker's Guide to First Opening the NWN2 Toolset.
Here's his intro:
Overwhelmed by the toolset?
Don't Panic: read this guide and get to grips with the basics of the toolset.
The guide assumes no knowledge, and is written for anyone, whether they have experience with the Neverwinter Nights 1 Toolset or not.
The guide currently covers:
The general interface
Creating external and internal areas
Placing trees, buildings and doors
Camera controls
Day/Night lighting
Editing properties
Selecting music for an area
Tinting objects
Rotating objects
Laying down interior tiles
Creating transitions between areas
Installing plugins
The external terrain tools
Baking and walkmeshes
Chests and inventories
Creating custom characters
And more...
There are plenty of screenshots so you can easily follow the tutorial.
I hope this guide helps people to create the adventures they want to share. I encourage you to leave feedback for me so I can keep improving it.
Head over to the vault to grab the Don't Panic guide:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=14
Another great tutorial is Stebby Surehand's Tome of Building.
The NWN2 Tome of Building (ToB) is an on-line help compilation of existing NWN2 documentation. It contains the Obsidian documentation for the Pre-Release Toolset as well as tutorials and tips developed by the Community. I converted their documents into on-line help. Please read the 'Welcome' topic in the Tome for information about how the documents in the Tome differ from the originals. I did not write any of the toolset-related content and I provided full credit to the original authors. Where possible, I also included links to the original document files so you can easily vote for them and leave comments for the authors.
While the Tome of Building is an on-line help file, I did not have time to add hyperlinks to every cross referenece. This first edition of the ToB does contain some hyperlinks within the text, but mostly it is a convenient compilation of existing documentation. It is also easily navigable, thanks to the hyperlinked table of contents and powerful search feature.
The Tome is divided into two main sections, Obsidian Documentation and Community Documentation. There is also a Welcome section that introduces you to the Tome and explains how the Tome differs from the individual documents and how to navigate through the help file.
Recently, several new tutorials have appeared on the Vault. I decided to release this version of the Tome so people would have what it contains now, if they wanted it, and I will update the Tome with the new tutorials for the "Second Edition".
Head over to the Vault and get it:
http://nwvault.ign.com/View.php?view=NWN2Other.Detail&id=10
The number of file formats, and where those files go, can be a bit confusing. Here is some basic information.
A great place to start on what each type of file format is for is the File Formats page at nwn2wiki.
Some additional information about a few types can be found under this page.
My Documents
All user data is meant to go in your My Documents folder. The default place for this is "C:\Documents and Settings\Sean\My Documents\Neverwinter Nights 2". This is where you put all files for modules and custom content that you download from the Vault. This is a big change from NWN1 and it has confused some people. Generally all this content come with instructions for how to install, but here is some additional information:
Program Files
All game data is meant to go in your Program Files folder. The default place for this is "C:\Documents and Settings\Sean\My Documents\Neverwinter Nights 2." All the files for the Official Campaign (OC) are also in your Program Files folder. Generally, you don't have to get into this directory, but the BIG exception is the plugins folder in the NWN2Toolset folder. Here's the rundown:
There is currently a thread going on over at the Citadel about custom content and files.
BMU stands for BioWare Music Unit. This is the file format for background music files. AFAIK, essentially, it's an .mp3 file with some tinkering done on the first few bits of the file and the extension changed.
Here are some tools to convert bmu files:
MP3toBMU 0.35
http://nwvault.ign.com/View.php?view=Other.Detail&id=225
Prince Rouse's Mp3toBMU and WinMP3Converter
http://nwvault.ign.com/View.php?view=Other.Detail&id=821
Using the tools above, you can convert all the music in the Music folder under Program Files to an mp3 and listen to them.
You can find information on the BMU format in this NWN1 tutorial on custom music. (Note that a good deal of this has changed for NWN2).
http://nwn.bioware.com/builders/sounds_bmu.html
At the time of this writing, there are still some complications with bringing your custom music into your module, and I remember seeing a post talking about improvements that will be coming soon. If anyone has any resources along these lines, please let me know.
ERF stands for Encapsulate Resource File. It is used when importing and exporting resources from one module to another.
Most people keep .erf files in a folder in their My Documents folder called erf. Note that you don't get an erf folder by default, so feel free to created one when you need it.
The .pfx file extension is for particle-based effects. As I understand it, these are used as resouces when creating .sef files. You can find some of them in C:\Program Files\Atari\Neverwinter Nights 2\Data\NWN2_VFX.zip.
The .sef files are special effects files for NWN2. Most of the ones that come with the game are located in C:\Program Files\Atari\Neverwinter Nights 2\Data\NWN2_VFX.zip
From the official documentation:
"Visual effects are composed of effect files, which are individual components of an effect (a particle system, a trail, a billboard, etc.), and SEF files, which point to the effect files and organize them into a more complex visual effect."
As I understand it, .sef files are what you create when you save a visual effect from the visual effects editor.
A .wmp file is created by the world map editor plugin.
Before you do anything, save yourself a lot of time and make sure all your modules, areas, object tags, variable names etc. are less than 32 characters. Failure to do so will result in missing data, crashes and other unexpected behavior.
For example:
While I was working on the PRR scripts, some data was not being saved because my global variable names were more than 32 characters. Anything beyond character 32 was getting dropped. I ended up using a hash to store my variables, something that I'm still not quite sure is the right answer. (Hopefully, I'll work this out soon.)
Another example, is that recently Markus "Wayne" Schlegel, the builder behind the Pool of Radiance Remastered series, was having problems loading the next module in the series. After some testing, it came out that his modules were named with 39 characters, and would sometimes (usually when loading the third module) crash to the desktop.
So there you go. Keep the all-powerful 32-character limit in mind. When it doubt, it's better to stay below 32 characters then go over. You'll potentially save yourself hours of troubleshooting.
Lord Niah of the Forgotten Realms Weave has a great base module to help get people started. Not only is it a great way to get a head start on your module, it also serves as a clean example of the proper way to perform a lot of common tasks.
This module includes base scripts and items for the Forgotten Realms Weave (FRW) project, including a player starting area with a trainer and basic merchant.
Other features Include:
-- Wandering Monster and Rest tag system
-- Hardcore bleeding or OC death system
-- Chest-based Random Loot system w/ breakable items
-- Flavor text, ability, and skill check triggers
-- Demonstration companion and "Sunken Flagon" style Inn
-- Demonstration OOC (Out of Character) Start Area
-- Patcha's Sitable chairs
Note: This is currently tested for singleplayer only, but should work for non-persistent multiplayer.
Be sure to read through the documentation file, as well. It has a lot of useful information.
Go grab it here:
http://nwvault.ign.com/View.php?view=NWN2Scripts.Detail&id=55
Here you can find information on creating areas.
You may also want to check out this page concerning naming conventions when you are naming your areas: http://www.wendersnaven.com/node/46
ciViLiZed posted the following links for day and night lighting options for areas:
Day/Night stages lighting is discussed here and here.
See the Day Night Cycle Prefab at the vault for a great collection of lighting settings for areas.
From the NWN2 Teakguides:
Bloom Effects: Bloom effects change the quality of the lighting to create a more saturated, richer and hazier looking game world. The screenshot comparison above demonstrates the difference between enabling or disabling this option in NWN2. If bloom is not to your taste, you can disable it to gain a few FPS, however aside from making the game world seem more vibrant, it also works to reduce the appearance of aliasing (jaggedness) at far less impact than enabling Antialiasing. Note that the more advanced HDR lighting can't be enabled in NWN2; even though there is a UseHDRIfAvailable setting it does not currently work.
Periodiko posted additional comments in this forum thread:
Technically speaking, if you crank bloom up then it will blur everything you see a little, but it will blur bright things far more than dark things. If you crank it really high it will create a dreamy sort of effect, where the bright lights are a little too bright and everything is a little blurry. If you turn it off then the area will seem darker and more sterile.
The main ways it's used in the Neverwinter Nights Toolset that I've seen is with the "hazy" effect. For example, the Githyanki house in the OC has the bloom cranked up really high so the whole area feels magical and dreamy. It is also cranked higher during daytime lighting settings to reproduce the haze of the sun. I think the default morning setting that you see first-thing when you don't adjust the time-settings has it running pretty strong.
ciViLiZed posted the following explanation of some of the settings:
BloomSceneIntensity (BSI) : Sets the overall brightness level of all lights. (With this, individual light intensity values in effect become relative rather than absolute.) As it brightens light, it will not brighten places where light does not reach. A setting of 0, eliminates all light except the highlights (see below). A negative value creates negative brightness which effectively darkens highlights. A BSI of 1, with other bloom settings set to 0, has the same effect as if bloom was disabled.
BloomHighlightThreshold (BHT): Sets the size and quantity of highlight hotspots. Models and tiles have defined zones (“hotspots”) where light causes highlights when it hits them. Different hotspots will be highlighted depending on the angle of the light (e.g. GroundLight vs SkyLight). A higher BHT value will result in bigger and more numerous hotspots. A negative value (regardless of the number) sets hotspots to their maximum. The minimum value at which hotspots appear seems to be about 0.5.
BloomHighlightIntensity (BHI): Sets the intensity of the highlights. Highlights will expand/flare more and more as the value is increased. A very high BHI value (e.g. 1000) with a low BHT (e.g. 0.5) will show clearly where the hotspots are located. Increasing BHI and BHT will eventually burn out the entire scene. A negative BHI value creates darker and darker highlights (eventually creating a negative effect if BSI is positive)
BloomBlurRadius (BBR): Multiplies each individual highlight and spreads these “clones” around the original, like petals of a flower in… bloom. (Original highlight size though seems to be reduced in this operation, making it seem that the highlight might be broken down and its pieces spread, rather than it being cloned.) A higher value increases the distance (i.e. radius) between the center of the original and the center of the clones/pieces. The clones/pieces are spread regularly in a flat grid pattern around the original highlight. Typically, 8 clones/pieces appear to be created. The angle of the flat grid remains perpendicular to the point of view, while the distance between the clones/pieces varies with viewing distance. BBR value is an absolute, so prefixing a negative has no impact. BBR, BHT and BHI combine to create a blur effect. Increasing the BBR up to a point where the additional highlights detach themselves from their model will result in a ghosting effect.
BloomGlowIntensity (BGI): No effect in interior areas. (In fact, the default interior DayNight stages settings have it set to 0.)
Ovocean added these also:
As I understand it, the bloom effect is a filter applied to each frame by the 3D card.
More precisely, it sorts of make a blured copy of the frame and mix it together with the original. (Consequently, dark parts of the frame spread around as much as bright parts (depending on the BHT). There is no direct link between light sources and the bloom effect.)
The toolset gives us some control over the blur filter and how the blured framed is mixed (I would say 'multiplied') with the original frame :
BloomSceneIntensity : Controls how much of the original frame will be in the final mix (= it's luminosity). Set to "0", you'll only see the blured copy of the frame. "1" stands for "luminosity 100%".
BloomBlurRadius : Defines the radius of the blur (how far colors are spread).
Actually, the blured frame is made by mixing a great number (47, if I can trust my sight) of copies of the original frame, arranged in a repeating pattern. The greater the shift of a particular copy, the more transparent it is. The BBR defines the shift between each copy.
If this is not clear to you, try setting the BSI to 0 and play with great values for the BBR.
BloomHighlightIntensity : Well, now, it looks like there is even one more filter put somewhere in the process. This filter controls the luminosity of the blured frame and the BHI is the main parameter of it : it's the global luminosity value (of the blured frame).
BloomHighlightThreshold : This second parameter sets the (color's) intensity threshold beyond wich the colors are affected by the BHI. I don't know what threshold corresponds to what intensity, but when a particular pixel's intensity is under the threshold, it's luminosity is set to 0.
Finally, here are the settings I use when I want a bloom effect wich slightly blends the colors without modifying the overall luminosity of the scene :
BSI = 0.8
BBR = 10
BHI = 0.25
BHT = 2
PS : I've seen no effect for the BloomGlowIntensity.
Check out the full thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=564969&forum=113
Information concerning exteriors.
AmstradHero has posted a great list of tips for proofing your areas over at the Vault. It's a good checklist of things to remember both before and after building your areas. He's got it posted as a very nice looking pdf, but I've duplicated it here as well (Rember to head over and give it a vote if you found it useful):
Here are a few guidelines for working with and improving your areas, whether prefab or not. It's useful to keep in mind as a sort of "final proof" of an area before finishing with it.
Avoid Steep Edges
Blend Textures
Use The Colour Tool
Darken Terrain Underneath Placables
Fix Your Walkmesh
Check Placeable Heights
Use Height/Position Lock
Convert Placeables to Environmental objects
Limit Non-Positional Sounds
Adjust Intervals
Implement Variance
Use Colour
Tweak Your Day/Night Settings
Beware of Shadows
Don't Overdo It
This is just a quick document to provide a few areas to focus on as the final touches for when producing an area – it's not intended to be a full area creation tutorial. I hope you find it useful to glance at before closing an area for the final time.
- AmstradHero aka Shadow Beast
Again, if you found this useful, make sure you head over to his Area Proofing Tips page on the Vault and give it a vote.
One of my favorite builders when it comes to textures is Anduraga. He's given some great tips for the Waterdeep project and other projects over at the Weave. He recently posted a great list of tips for people looking to build good exterior areas. Here's his intro:
I find that many people find area building a very difficult task, and when they do make areas, they are often basic, because of the lack of tutorials, tips, etc. I can relate that to somewhat in a different department. Scripting isn’t really my strong suit, but I can manage to do the basics. But anyway, to the point of this post/thread. I have designed this thread to help new builders, adept builders and even master builders with tips and tricks of the trade. I haven’t checked out many of the tutorials on the vault (Shame on me, I know), so all this stuff I’m throwing out here now might already have been covered.
Check out his list of tips here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=578694&forum=113
BenWH over at DLA has posted a great tutorial on creating exterior areas in the DLA Toolset forums:
Trying out the NWN2 toolset for the first time? Here are the results of my explorations on building an exterior area, combined with the wisdom of several others…
Read the full tutorial here:
http://www.dladventures.net/vB/showthread.php?t=3791
Phoenixus posted a great tutorial on texturing a good grassland area. Check it out here:
You can import terrain data into the toolset to help build exterior areas using YATT. From the YATT website:
Yet Another Terrain Tool (YATT) is a plugin for the Neverwinter Nights 2 Toolset allowing importing of terrain information (including heightmaps, colourmaps, texturemaps, etc) directly into the toolset. It does the importation of height, colour and texture data directly through the TRN stream, meaning it's reasonably nice and fast.
You can download the YATT plug-in form the vault. There's also a good tutorial on the vault for beginners by Laban. The YATT website also has a number of case studies and additional information.
One way that some builders generate terrain data is with L3DT. From the site:
L3DT is a Windows application for generating artificial terrain maps and textures. It is primarily intended for game developers seeking to make large high-quality 3D worlds (eg. for RTSs, MMORPGs, etc), as well as for digital artists who have designs for their landscapes and need a program to build them.
Thanks to nicethugbert for point me in the direction of some of this (I read his sig on the forums). I've known about YATT for a while, but didn't have much luck with other mapping programs. L3DT seems to be more promising. Also check out NTB's Eroded Hills and Valleys, where he has posted some of the areas he generated with these two tools.
The layer with the highest percentage is the one that determines what sounds a creature makes when it walks on that area. Make sure you bake the area in order for the sounds to take effect.
Mike - aka Plane Walker, aka soulraven666 - over at NWN2 Mods has posted a step-by-step tutorial on creating a "roman Colosseum."
I thought I would detail the process I am going through in creating this Arena so this post is going to be an ongoing one that I continue to add to as I progress. Please feel free to reply with comments.
Head over to the NWN2 Mods forum and check it out:
http://www.nwn2mods.com/forums/index.php?showtopic=21
NWNmaster over at nwn2toolset.com has a great set of tutorials for creating areas. His current list of topics include:
Create an area
Interiors
All about Terrain
Texturing
Tips for creating an Area
Grass
About Water
How to add a Start Location
Create a waterfall
Create door transitions
Day and Night Settings
Walkmesh
Baking
Head on over and check it out:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/area.html
NWNmaster over at nwn2toolset.com has a great tutorial for placing a bridge.
After seeing a few people having problems with placing bridges I thought I would give it a go and see what the fuss was about. First thing I did was to create two raised areas like so:
Head on over and check it out:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/placeables/bridge.html
A great tool for making changes to your area is TerraCoppa, by Tani. The most obvious benefit of this tool is being able to rotate areas, so that north matches with north. Here is Tani's description:
TerraCoppa is a toolset plugin allowing you to copy and rotate parts of one (exterior) area to another, including:
- terrain (heightmap)
- tinting (colors)
- textures
- gras
- water
- objects (creatures, placeables, ...)of course you could copy objects via toolset as well, but it lacks the ability to copy or rotate terrain (heightmap).
Go grab the tool here:
http://nwvault.ign.com/View.php?view=NWN2PlugIns.Detail&id=25
Documentation is a bit light, but here is a quick rundown on how I got it to work:
For additional reading, here is a thread on the forum talking about "North Direction" and rotating the area.
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=558621&forum=113
The walkmesh helper is a tool created by Zarathustra217 and apparently quietly slipped into the 1.05 patch.
I came across this post by TheStoryteller01 asking about making creatures hover above terrain. Grinning Fool posted some really amazing looking screenshots that he created using the walkmesh helper.
The walkmesh helper is a tool on the vault by Zarathustra217. Here's the description:
This is a simple package intended to make a builder's life easier. It consists of simple squared invisible placeables with a walkable walkmesh. When scaled, the Walkmesh Helper objects are handy to use along with Walkmesh Cutters (found under trigger) to have more control of the walkmesh. This especially is evident when using a combination of placeables, like several bridges. Place the Walkmesh Helper just above the walkable plane of the placeables, scale it to properly cover the desired area, and cut away with Walkmesh Cutters as fit. You might get the best result by converting the placeables to environment objects, but it shouldn't be required.
It is intended to work as an override, and doesn't require that the end users of your module have this package in place. They will still experience the effect it has on the walkmesh without it installed.
Here's the link:
http://nwvault.ign.com/View.php?view=NWN2HakpaksOriginal.Detail&id=27
Here's an additional tutorial on using this that Feargus Urquhart posted in the developer blog:
http://forums.obsidianent.com/index.php?automodule=blog&blogid=2&showent...
As far as I can tell, the tool on the vault contains a flat plane and a ramp, while patch 1.05 adds two flat planes: a stone version and a wooden version (I'm guessing these are for the footfalls.)
Warning: At the time of this writing, putting the walkmesh helper files in your override seem to cause problems with the official walkmesh objects that came out in 1.05. Hopefully OEI will add the ramp objects soon.
For those of you looking to use it for those annoying house placeables that don't allow you to actually walk up the stairs, try the ramp with a scale of 2, 10, and 7. Getting in place can be a bit tricky, just because it is hard to see exactly where it is sitting. Try baking the area and viewing it with baked and surface mesh enabled and you should see a seamless yellow path onto the roof. I had pretty good results with house 1, but house 3 would only work if I created an additional plan on the roof.
jlf2n posted a great thread about how to reverse engineer methods for shading. In his post, shading refers to using the color brush to add shadows. You'll also see this sometimes refered to as "grayscaling." Here's his intro:
Being new to the NWN2 toolkit I set out in search of a tutorial to show me a terrain shadowing tricks. I couldn’t find any so I set to dissecting one of the areas that came with the main quest to see what I could see. The process I used was very helpful to me so I thought I would run through it here for you guys.
He goes on to walk you through opening an area from the OC, removing all the shading, and trying to recreate it. A great idea for learning how the people at Obsidian put some of the areas together.
Check out the thread on the nwcitade here:
http://nwcitadel.com/forums/showthread.php?t=1158
ScreminMemes and Miserere posted some great advice in the Toolset Q&A thread on the official forums on making seamless exterior areas:
Quote: Posted 10/13/06 02:03 (GMT) by ScreminMemes
The off limits area is there to create the illusion of seamlessness. All you need to to to make your areas seamless is copy one then move it to the side until the last two in-bounds rows from the original area are the first two out of bounds in the next area.
Quote: Posted 10/16/06 17:28 (GMT) by Terror2001
I've been looking for a way to copy sections of a map to create this seamless effect but have yet been unable to. I understand the copying of the map to a new map, but how do you select and move a group of tiles?
Don't try to copy sections of a map. Instead:
(1) Make a copy of the entire area (i.e. copy the area itself, not the terrain and stuff in it). Just select the area in the area list, right-click, and select copy.
(2) Identify the edge you want to carry over (let's say it's the North edge of the original area, so you want to preserve the *North* edge of the new area as well).
(3) Select and delete all objects that do not fall within the 4 tiles along the edge you are preserving (otherwise all those objects will collapse to the new edge when you do the next steps, which will screw up the areas you want to preserve). So in our example we delete all objects that are not within 4 tiles of the *North* edge of the new area.
(4) Use the Resize option (I think it's in the Edit menu, but I don't have the toolset in front of me right now) and reduce the size of the edge *opposite* the one you are preserving until you have only 6 tiles in width, total (4 of which will be off limit areas). The 2 off-limit areas from the other area will now be the walkable areas of the new area. In our example, we would remove most of the tiles on the *South* edge of the new area.
(5) Use the Resize option again to increase the size of the area back to what you want it to be, this time on the other edge. Now you have extended out the walkable area in the other direction and can build it up however you want. So, in our example we would add several tiles to the *North* edge. Et voila.
Think of the process as kind of inch-worming your way from area to area. You move to a new area (by making a copy), contract the area to eliminate the parts you are leaving behind, and then extending again in the direction you are moving. Does that make sense, or do I sound like I'm on crack?
Anyway, hope that helps. I've tried this and it works like a champ. Where this method falls apart is if you try to create four areas arranged in a square pattern, since the fourth area you make will only be able to "inherit" the edge of one of its two adjoining areas, not both. That's where you'd have to do some fudging.
_________________
Miserere
Project Lead (Retired)
Tales of the Pendragon (Defunct)
You can find the conversaion here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=502381&forum=1...
Information on interior tilesets.
BenWH over at DLA has posted a great tutorial on creating an interior area in the Toolset forums as a follow-up to his exterior area tutorial:
Thanks to the Halloween 2008 discussion over at bouncyRock Entertainment, I came across four links for creating load screens:
A tutorial at the nwn2toolset site:
http://www.nwn2toolset.dayjo.org/CustomContent/loadscreen.html
Summary from Amraphael/Nihlar
http://nwn2-zork.blogspot.com/2007/11/load-screens.html
A conversation in the Custom Content boards:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=612275&forum=115
A conversation in the Scripting Boards:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=637175&forum=114
Enjoy!
Most people have had better luck after patch 1.05, but apparently it is still happening. Here is some basic information to help:
Check out the Toolset Corruption thread on the Toolset forum.
One of the most common corruption problems comes when you don't properly set the variable type on a trigger. As a general rule, set the variable type first.
There seem to be additional problems when working with speak triggers. stg_why and mattaus have posted how to recreate these issues:
- open an existing area
- change an attribute of an existing object (or simply add a speaktrigger, although its not 100% of time for everyone causing corruption)
- save , close toolset
- sgt_why
Some people are advocating turning off the auto save function because of this.
There's also an issue where some areas are getting corrupt and are not noticed until further down the development process.
Phil5000 posted some frustrations in the Toolset forum about this:
Hi there. Ever since my mod was corrupted and I lost half of it I've been saving backups regularly. Well it got corrupted again but in a different way. The game wouldn't load the mod but it seemed ok in the toolset. So I opened up every area to check and when I hit one particular one I got a 'program has caused error and must close' message.
So I loaded a backup and checked that same area and I got that same message! I know for a fact the area is ok having played it through several times. So what could have happened?
This time the game would load it though so I went in there to have a look. Everything is black. There's nothing in there at all. I can turn the camera around and access my inventory but the PC isn't there. It's just like a void in space.
The idea that your area could have been corrupt long ago will make any builder nervous.
Chris_Rocks posted a possible back-up strategy about exporting your areas as .erf files. While this may be a bit cumbersome and will require more space, it will definitely give you a good backup that you can easily bring into your module. Remember that there's never such a thing as backing up too much.
jackyo123 posted a comment suggesting that it's always a good idea to shut the area down when you are done building with it:
one thing that is ESSENTIAL to do -
I was in the habit, because of the ridiculous load times of anything to do with the toolset, of simply leaving my large areas open.
I would happily go along, making edits here, edits there, etc. Saving multiple backups, everything looks good.
Then, a night or 2 later, the toolset crashes. Ok, no biggie, i have a hundred backups. I open up the toolset, go to open my big area - NOPE. Gives me a CAST error or something. Ok, go back 1 version. NOPE, same thing. Go back 10 versions. Nope, same thing.
What was happening is that the area i had open the whole time had become corrupted, but i had not known about it, since it was open already in the toolset, and i didnt try to reload it.
So I no longer do this. I close down an area as soon as i am done working on it, then re-open it to verify its ok. THEN i close it again and move on to my next piece of work.
He also offeres some additional backup strategies:
Also, you need to be making backup copies of the DIRECTORY (usually has a temp^&^E%^%^%&&$modname associated witn it) by manually copying this directory to a safe place every once in a while. I copy the directory every 3 or 4 mod saves. I can often pull scripts, blueprints, etc out of there, and merge them with the last known 'good' copy of an area before it got trashed, and everything is ok.
Thanks to these fine people for their thoughts.
It may also be helpful to check out my stragety for versioning your modules when working with a campaign.
Kivinen has some great tools for working the the toolset on his site here:
http://www.kivinen.iki.fi/nwn/
One of the best tools for debuging your module is his check module tool, which can be downloaded here:
http://www.kivinen.iki.fi/nwn/exe/check-module.exe
You can find the documentation here:
http://www.kivinen.iki.fi/nwn/docs/check-module.html
Some have suggested you will actually need to save the module out to a directory.
After you find errors, you can try fixing them with his update-ifo tool:
http://www.kivinen.iki.fi/nwn/exe/update-ifo.exe
Here's the documentation:
http://www.kivinen.iki.fi/nwn/docs/update-ifo.html
He also has perl versions of everything, if you want more up to date options, but I've included the exe files since that's what most people will probably be grabbing.
This section deals with blueprints and objects (creatures, items, placeables, etc)
This section deals with creatures.
Gnorian asked for help making companions in this thread and Dorateen came up with the following reply:
Credit to Celestian the Good:
Making a companion, step by step.
First create your companion NPC. I made a fighter/wizardlevel 1/1 and called him Melf the Elf. His Tagname is "melf" and his resref/template was gh_henchman_melf01.
Load up this new NPCs properties and select import properties->script set and load up "c_CompanionScripts.xml". If you do not have this file you can create it by loading the properties of one of the official campaings companions and selecting export properties->script set and save as "c_CompanionScripts.xml".
Next create a conversation.
Right click the root section, select add and for the text just say "Would you like a new companion"?
right click the line you just created and click add and for the text use "Yes, please join my group.".
Now, find and click the "Actions" tab below and add the following global action scripts:
ga_roster_add_object
ga_roster_selectable
ga_roster_party_add
ga_reset_level
Once you have all the scripts added and in the order above click "refresh" for each script to see the variable options. Once you see those enter in the following values:
ga_roster_add_object sRosterName:melf sTarget:melf
ga_roster_selectable sRosterName:melf bSelectable:1
ga_roster_party_add sRosterName:melf
ga_reset_level sCreature:melf bUseXPMods:1
Replace "melf" with whatever tag you used for your companion.
Save the conversation and then add it to your new companions conversation (under properties).
Place the NPC somewhere in your module and go talk to him. Hit the "yes" response and he should be your new best friend!
Further down, ByblosHex adds this advice:
Note that the NPC's tag must be 10 or less characters for these scripts.
Continue further in the thread for a discussion about how to structure companion conversations. I'll try to pull all of these elements together in a more coherent form at some point.
Check out the full thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=537485&forum=113
NWN2Toolset has released a short and sweet tutorial on creating companions.
Check it out:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/merchants/companion.html
lancerlot_30v recently posted a great new site with a robust character builder tool called the NWN2 Character Builder. Check it out at http://nwn2db.com. It's great for those times when you are in the toolset and can't remember what feats an NPC should have.
See the full forum thread announcement.
Thanks to BeyondthePale for posting this to the nwvault front page.
NWNmaster over at nwn2toolset.com has a great set of tutorials for working with creatures and encounters. His current list of topics include: Create an NPC Adjust Creatures Inventory How to setup Generic Encounters How to setup Custom Encounters Head on over and check it out:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/blueprints/creatures/creatures.html
This is a quick to tutorial I posted to the Vault while exploring creatures and scripting in the toolset. It will show you how to:
Specifically we will create a new zombie that has the properties of a troll. Our zombie will regenerate and can only be killed by fire or acid, but we'll make a few adjustments to the script.
You can view it from the vault here:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=37
Patch 1.04 is apparently responsible for making all the NPCs standing around the module injured. It has something to do with current hit points versus max hit points. Here's a thread talking about it:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=561730&forum=1...
Reports suggest that this only affects previously created module. New modules don't seem to suffer from this bug.
A suggested fix was to manually look at the characters' current and max hit points in the Toolset.
Information on placeables.
Don't forget that containers (chests, dressers, long dead corpses to loot, etc.) should have the following flag set under the behavior section of the properties window:
Has Inventory?: TRUE
Static: FALSE
Useable?: TRUE
If you want dynamic treasure, make sure you define a treasure script for the On Death and On Open events. One option, gp_treasure_op_de, is documented here: http://www.wendersnaven.com/node/65
Leaving the faction to hostile will allow players to bash the object without any real repercussions. In NWN1, setting the faction to a neutral faction would cause any nearby members of that faction to attack the PC if certain events were triggered. If I recall, these were On Death and On Disturbed. I'm unsure what events trigger reactions in NWN2, but they are probably the same.
Converting placeables to environmental objects reduces the size of areas. I think it also increases performance for players. Environmental objects do not cut into the walkmesh, meaning that players will be able to walk right through them. Sometimes this is not an issue, such as when they are out of the walkmesh anyway, but otherwise you will want to use the walkmesh cutter trigger to keep players from walking through your objects.
johnbgardner posted this warning to other builders in the official forums:
I just noticed that when you convert an environmental object back to placeable the Current Hit Points, Hardness, and Hit Points are left at 0. Believe it or not this makes the placeable unuseable regardless of the Useable setting. It was driving me crazy that one placeable could be used while another with identical properties (except for the above which I had ignored) wouldn't. Setting those properties back to the default values made the object useable again. Wierd.
See the thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=535748&forum=113
Here you can find information concerning the effects in the nwn2 Toolset.
BenWH over at DLA has posted another great tutorial for the nwn2 Toolset. This time he takes on the effects editor.
Well, this is actually a plug in, but it comes included with the toolset, so I've placed it here with the tutorials.
We're going to create just one effect to get started, but because I am far from being a dab hand with this editor, you can then use this experience to get comfortable with it:
Read the full tutorial:
http://www.dladventures.net/vB/showthread.php?t=3843
There's a good tutorial on nwn2toolset.com on using the visual effects editor, where he takes you though the process of making a snow effect.
Check it out here:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/plugin/visualeffects.html
Pfx get generated by the effects editor and should be saved in your campaign's individual folder inside the campaign folder.
For example:
C:\Documents and Settings\\My Documents\Neverwinter Nights 2\Campaigns\\effect1.pfx
More from LysanderReturns at http://nwn2forums.bioware.com/forums/viewtopic.html?topic=520330&forum=1...
"The pfx/bbx/sef files associated with your custom vfx can go into a custom campaign folder, ie a new campaign. The /campaigns folder is for holding /campaigns/[individualcampaign] folders.
ie: campaigns/Purgatorio/customvfx.sef would make the customvfx.sef accessible for any modules associated with the Purgatorio campaign (using the campaign editor).
The .sef can also go into a hak. It will also work in override.
Finally, there is Dev post around here somewhere that says you can put them in the temp module folder and they will get saved into the module.
-Monty"
Currently, the suggested way to add a sef file to a module at the time of play is to place it in the override directory. The next patch is supposed to address some issues hak files.
I opened one of the OC areas to see what settings they defined for realistic firelight (torches, candles, fireplaces, etc). Based on that, these are the settings I am using for basic light sources:
Behavior
Shadows
You may also want to nudge the colors just a bit towards red and orange. Not to the point of being overpowering, but just enough that it's not plain white and gives a subtle red/orange undertone.
Nwn2toolset posted this great tutorial on using lights by Geethree. It covers shadows, lerp and some other great items that you might have missed on your first pass through the lighting options.
Check it out here:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/blueprints/lights/light.html
From the official documentation:
"Stores are only accessed through script in a conversation – they are not objects that the player can detect. Stores have blueprints just like other types of objects. After you create your store’s blueprint, place it on the map normally. It is generally best to place your store next to the NPC. Check out the Sample Module for an example of a store."
Stores are usually started from a script attached to a conversation using the "ga_open_store" script. Place a store in the area and use the tag for the store as the first parameter.
The nMarkUp and nMarkDown parameters are for when you want to adjust a store's buy and sell price due to a plot driven situation or some other condition. Generally, you can leave these at 0 and 0.
You can create your own stores based on the pre-generated ones by right clicking and choosing copy blueprint. Note that when you do this, the seling and buying percentages are both 0. If you don't fix this, everything in your store will have a base cost of 1.
Thanks to seryn for doing the leg work to figure out that the OC uses a standard sell price of 100% when players purchase items and a 40% of sell price when the store buys from the player. These options are located in the properties window of the store. This is also the balance that Berliad's FRW character creator uses.
If you're having problems working with items in stores, you may want to consider Lazjen's CPS Inventory Manager. Some features in this plugin include:
GodBeastX, Ash Darkwood and others recently reported a problem with patch 1.05 where you can no longer set the buy and sell list of item types for stores. Apparently this worked fine in 1.05 beta, but now throws an exception and makes it impossible to set up these lists in 1.05 final.
The bug was reported and acknowledged by Rob McGinnis, Obsidian Community Coordinator.
Check out the thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=560804&forum=113&sp=0
You can set variables on blueprints and objects by clicking on the "..." icon in the "Variables" field under the "Scripts" section of the Properties window. Choose the variable type that you will use (string, integer, etc) and place the value in the appropriate field.
This allows you to set flags that scripts can read. This is how switches work.
There have been some reports that setting a value without setting the type will result in a corrupted module. Hopefully this will be fixed soon, but in the meantime, make doubly sure you set the type when assigning variables.
Information about conversations.
There are a lot of good tutorials out there on basic conversation creation. Here are just a few that I've found useful that deal explicitly with tutorials.
Also be sure to check out the conversation sections in the more general tutorials listed in the Getting Started section of this site.
BetterThanLife over at Machinations.org has posted a tutorial on conversations. This tutorial teaches you how to implement conversations, and then goes into some of the more advanced details of creating different types of dialog conversations. The included module, gives three distinctly different examples. An explanation of the use of 'static cameras' is also given and shows how they aren't as 'static' as many think.
Download the zip file with a pdf and example module here: http://www.machinations.org/NeverwinterNights2/ConversationTutorial.zip
(Thanks to Usheen for pointing out the new, working link.)
NWN2 Toolset has a great section on conversations.
You can find it here:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/conversations.html
Cutscenes in NWN2 generally happen through a combination of conversations, conversation switches, and camera control. I'll try to expand this more later, but here is a general procedure:
Kid Gloves asked a great question on the official forums about cutscenes and multiplayer. Nimdolf gave this answer:
Well after playing the OC with my friend online, it works like this. Whoever triggers the cutscene gets to control it, pick what to say, etc. and all of the other players see the cutscene also and what choices you choose. If you join the game midway through a cutscene however you must wait until it is over to do anything.
Check out the thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=521668&forum=114
jackyo123 posted a cutscene tutorial here:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=65
This tutorial document (in rtf format, for those who hate MS-Word) and associated .MOD file walk a basic toolset user through their first cutscene, with animations, movement, etc.
It explains:
- Triggering cutscenes
- Setting up cutscenes that the Player isn't part of (NPC to NPC)
- Camera controls
- Animations
- Basic use of included scripts
- Some snags that you can avoid, that are associated with Cutscene creationThere is *no* scripting in this tutorial, and no scripting knowledge is required. But you should have a basic familiarity with the Toolset.
NWN2 Toolset has this tutorial, which might help those trying to figure out cutscenes: How to make cut scenes by Montgomery Markland of Rogue Dao Studios.
An overview of setting up a cinematic-style cutscene conversation
What you will need:
1) A conversation
2) A blocking script
3) A way to begin your cutscene (either a speak trigger, an on_client_enter script or something else)
4) Plus the area, npcs etc., etc., etc.
Check it out here:
http://www.nwn2toolset.dayjo.org/ToolsetTuts/blueprints/staticcams/cutscenes.html
Some time ago, Papermonk posted some tips about conversations from David Gaider. I recently ran across it and thought it might be good to revisit. Here's a quote from his intro:
I assume most of you know who that is - if not, he's one of the big design boys at Bioware and had his hand in BG2 a LOT, among other things.
Mr. Gaider joined CODI briefly (before being pulled back to insane grinds at BW) but before he left he really helped us figure a few things out.
Rylock's Conversation Tips
1) If you have a large character to write, TEMP dialogue is your friend.
Don't worry about getting caught up in the details right at the beginning. You'll get bogged down with how something is said rather than just getting the structure together... which is important when the NPC has a lot to say. Write a single line that covers each starting condition ("This is what I say when you first meet me!") and then write really quick lines afterwards that cover only the basics of what you're trying to get across. You can go back afterwards and flesh the lines out and add "flavour" routes in the dialogue later.
2) Write comments.
Even if you're doing the scripting yourself, write comments... write comments whenever scripting is needed, either for a starting condition, somebody's supposed to perform an action, a variable should get set here and so forth. You will thank yourself later.
3) Don't repeat yourself unless you have to.
Too many times we get newbie writers here who will have dialogue where the same information comes up numerous times... and they'll write that information up each separate time. A little differently, to be sure, but it's the same info.
Don't do this to yourself. And don't delude yourself into thinking this makes better dialogue. Always recycle whatever you've already written if it's at all possible. One of the most common ways this is done:
"You want to ask me something, you go right ahead."
1 - PC question #1.
2 - PC question #2.
3 - PC question #3.
4 - I don't have any more questions.
After each question is answered, you loop back to the first line (the "You want to ask me..." or even a new line like "You want to know something else?" that has the same response links). Only when the PC is done with his questions and picks #4 will you then go back to the rest of the information the NPC has.
Recycling sub-menus like this will make your structure much, much simpler to understand (especially for you) than trying to have each separate question flow into everything else the NPC might have to say or do. If you do that, I guarantee you will run into situations where the player wanted to ask something else but the question is no longer available to him.
4) Don't use more Starting Conditions than you have to.
Now, this can be taken in one of two ways. While it can be good writing to have multiple starting conditions when the NPC is clicked on (he says something different based on updated circumstances and so forth), a good rule of thumb would be to include everything that the character needs in a single sub-menu as often as possible.
What do I mean? Another example:
"Greetings once again, <FirstName>. Missed something the last time we spoke, didja?"
1 - Do you know your way around this area?
2 - You mentioned that you lived in the building next door...
3 - I was told the building next door is brand new. Are you lying to me?
4 - You come to this bar often?
5 - What do you know about the other patrons here?
6 - So what's there to do for kicks around here?
7 - Want to play some cards, old-timer?
8 - I got that money that Traul owed you.
9 - I should go.
Now... obviously the player's not going to see all of these PC responses at the same time. You can look at that list and see clearly that some of these responses require some foreknowledge that the PC may or may not have. So you add Starting Condition scripts to them all.
1 - No script. It's always available. During the answer the NPC mentioned he lived in the building next door... set a variable on the PC to indicate that info is known.
2 - Only shows if the variable mentioned in #1 has been set.
3 - Only shows if the variable mentioned in #1 has been set AND another variable indicating the PC has spoken to someone else about the new building is also set.
4 - In this one the NPC will mention that yes, he has been coming here a while. Set another variable on the PC. #4 no longer shows once that variable has been set.
5 - Only shows if the variable mentioned in #4 has been set (or if you figure it's a generic enough question, scratch the variable and both 4 and 5 can always show). In the dialogue resulting from this, the NPC could mention that Traul owes him money and he hasn't been able to collect... whether or not the PC agrees to get the money, set a variable on him (he should at least know about it and be able to ask Traul).
6 - In this one the NPC mentions he likes to play cards and challenges the PC to a game. Set another variable on the PC. #6 no longer shows when this is set.
7 - Only shows when the variable in #6 is set. Goes directly to a game of cards.
8 - Only shows if the PC was able to collect money from Traul (after the variable was set in #5).
9 - Always shows.
...and so on. The benefit for doing all this? At the end of every section of dialogue for the NPC (and keep in mind each of these could go into its own sub-menu with separate questions and routes) you do not have to sit around and weigh exactly which PC responses apply in that situation. Link to them ALL and the dialogue will both sort itself out and flow naturally... and save you a lot of time.
5) Make sure the goods are readily available.
What do I mean by that? Simple... don't bury a good piece of writing somewhere where nobody will ever find it. Unless you intend for something to be an Easter Egg, don't give your NPC's specialized dialogue that will only show up once in a blue moon. If you want to add it later, then fine... but finish the damn thing first or you never will.
6) You can always add more later.
Yes, we are all perfectionists. We want the dialogue to include everything possible the very first time through. Well, suck it up, sister, because that isn't going to happen. Don't over-plan the dialogue... get in what you need, first, and add more stuff in later. And keep in mind not every NPC needs to know or tell everything imagineable.
Here are two additional points by Sethai:
7) Limit your text.
I don't know how it will work in nwn2, but in nwn it is best to limit your text to about 2.5 lines, so each section of dialogue never comes past the npc's portrait. Overflow into another node if need be. Huge blocks of text just look unproffessional and discourage the player from reading them. I try to follow the OC conventions, because it makes the game more immersive when you're not distracted by the little things.
8) Most obvious responses first
When, ordering your responses, try and put the most expected, non consequential response first (stuff like "continue" or "could I ask some questions?"); you don't want people to be 1ing through, and accidentally attack the quest giver. Put your "Goodbye" option at the bottom of the list so people know where to find it.
Here's the original post on the FRW forums:
http://nwcitadel.com/forums/showthread.php?t=227
sgt_why asked a great question about writing conversations that are multiplayer friendly. Check it out for yourself here:
http://nwcitadel.forgottenrealmsweave.org/showthread.php?t=1175
A decent amount of this comes down to the options on a conversation. Open a conversation and check the options window and you'll see several items of interest. The mains ones here are Multiplayer Cutscene and NWN1 style.
Here is a response that I wrote up for that thread and decided to repost here:
The multi-player flag got a bad wrap because it was over used in the OC. If you don't have it set to multi-player, you should have it set to use the NWN1 style of conversation. A good rule of thumb seems to be:
Here is a good description by Nimdolf a while back on how multiplayer works in the OC:
"Well after playing the OC with my friend online, it works like this. Whoever triggers the cutscene gets to control it, pick what to say, etc. and all of the other players see the cutscene also and what choices you choose. If you join the game midway through a cutscene however you must wait until it is over to do anything."
Again, that is with the options set to NWN2 style and multi-player. If you don't have multi-player set to TRUE, they are not involved, but I think they are stuck in limbo. If you have the style set to NWN1 and multi-player set to FALSE, players can run around and talk to whomever they want.
Another point is to watch your conversation triggers. All too often you end up with rogues and rangers doing the talking because they are scouting ahead and there is no way to "hand off" the conversation. Usually this is fine. In important conversations where a party might elect a different PC to do the talking, however, let them start it on their terms and you'll take care of a lot of this.
Here are some things to note about the journal:
1. If you are using campaign, you have to use a campaign journal. The module-level journal will not work.
2. You can either update the journal using the script ga_journal, or you can use the "Quest" field on the "Node" tab to browse and find your journal entry.
3. The players will not automatically get the XP defined in the Journal when they hit an endpoint. You have to manually award the XP by attaching the script ga_give_quest_xp to that dialog node.
Tips and tricks for controlling the camera during conversations.
Here is BetterThanLife's section on the camera from his tutorial on machinations.org:
Static cameras are basically cameras that you can place directly into the game
world and position like any other object. If you press the ‘Preview’ tab next to the
properties tab, you will get a rendering of what the camera is seeing, then you
can move it around to carefully position much like a director. You then use static
cameras by attaching them to lines in conversation dialog through the use of the
Node tab as explained in the previous section. You need to give your static
camera a tag name and then link it to the Node. From there you have the ability
to make the camera stationary (default), pan or track. While a static camera
might sound like it doesn’t move, if you use pan or track, it will either always face
the target (pan) or move along with the target (follow). Obviously in order for this
to have any use, the target would need to be moving. This is where the Action
tab comes into play. You might have a script that makes the actors walk as they
are talking, and have static cameras positioned about, following their movement,
so as to create a cut scene. (The camera’s target will be whoever the speaker of
the dialog line is). You can even choose the shot angle of the static cameras,
though I haven’t experimented with it, the names should be obvious as to what
they will do.
You may also want to check out this page concerning the conversation switch script template and how it works with camera control.
UPDATE: Patch 1.07 and MotB changed the way you interact with the camera. Now you just hold down the right mouse button and you can control both turn the camera and control the pitch.
Kephisto posted a great set of instructions in the Toolset forum concerning the camera:
Holding down the control and shift keys then right dragging should roll the camera while holding down alt and shift with right clicking will pitch the static camera up and down.
You can rotate it towards the left and right like other objects as well. To raise and lower it hold down the alt button while moving them. All together you can put it in just about any position and angle you want.
If there are any problems it could be, just guessing, that your keyboard shift and alt and control keys may have a different configuration, but in general play around with those three keys when the static camera is selected and you'll discover a feel for it.
In case you may be wondering, I've already placed many static cameras behind NPCs, across treetops and roofs, angled upwards from the ground, and even upside down viewing a monster.
When you're ready to have even more fun, Inder, right click on the static camera and select properties in new window - which, believe it or not, will bring up another properties window of which you can select view and actually see exactly what the camera does, in real time.
From there it is a matter of selecting a line of a conversation and selecting that static camera. Overall, I hope you enjoy using them.
And further down:
Each line in a conversation, whether spoken by the player or the NPC, has its own properties. For example, please highlight any line in a conversation and look at the bottom left, which should have the four tabs : Conditions, Actions, Node, Animations.
While you have a line in your conversation highlighted (selected) please click on the bottom tab named Node. In the Node panel that comes up in the bottom left should be a wondrous amount of options, divided into three main categories : Behavior, Camera Settings, and Line. Click the left (plus) sign of the Camera Settings category.
Now you should see many options for the Camera Settings, for that one specific line of conversation alone. You are now able to set if you want the camera settings to be random or want the Movement Type to be None, Pan, or Track, or even if you want that line of conversation to use any of your Static Cameras or even if you want the visual shot to be a Close Up, Walk-by, Medium, Over the Shoulder, or even more.
Even without using a static camera, just about all the above options (and more) are still available. So if you want to have a specific part of a conversation have a certain look to it, you can merely select a specific option and leave it at that.
When using Static Cameras all that is needed is to place the desired static camera’s tag in the Static Camera field, which is listed in the Camera Settings of the Node panel. There is probably a better way to say all this but I hope at least this information helps.
And a follow-up by LysanderReturns:
Perfect summation Kephisto. Just to add one last step, you need to set the mode field on the node to "static camera" if you want to use a static cam or "user defined" if you want to choose one of the preset cams (like worms eye or walk by or whatnot).
Check it out: http://nwn2forums.bioware.com/forums/viewtopic.html?topic=514512&forum=113
You can use an invisible cameraman to control where the camera is facing and make the static cameras pan and track to follow the action.
First create your invisible cameraman. Go to blueprints > creatures > special to find the "Attach Spell Node" creature. Place him in the area and give him the following attributes:
Now you can select the cameraman via GetObjectByTag() in a conversation switch. This will allow you to move him around using AssignCommand() calls.
Place a static camera in the area and give it a unique tag. To get the camera to follow him we will use the Node tab on the conversation nodes. To do this open your conversation and go to the node you want perform a moving camera effect on. Follow these steps:
Thanks to Deist who suggested the use of the Attach Spell Node creature. Originally I was trying to use the ScriptHidden flag, but found that the camera does not follow the creature if this is on.
Check out the full thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=535548&forum=113
Here's a threat talking about how to pan the camera up towards the sky:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=535097&forum=1...
A great place to get started learning how to script with NWN2 is http://www.nwn2scripting.com. He's got some great tutorials on getting started, including a "first program" article and some general tips on using the Toolset.
Jassper posted a great list of resourced for those looking to get more familiar with scripting:
Noobs Corner is laid out to help the newbe scripter. Also, here are some links from nwn1 scripting/toolset which can relate to nwn2:
Check out the full thread where he posted these:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=521085&forum=114
Thanks also to Grumpy Badger who recently let me know about this stickied thread on the NWN2 forums:
Helpful Scripts - http://nwn2forums.bioware.com/forums/viewtopic.html?topic=573084&forum=114
KublaKhan1797 asked a question about variable scope on the official boards, and ScarfaceDM gave a nice summary:
A standard variable defined outside (and above) any function or void main will be global within that script, a standard variable defined within a function or void main will not be global within that script, it will be usable within the function or void main that it was defined in.
A local variable is stored on an object and is retrievable from any script as long as it exists, they are not persistent unless stored on items in a PCs inventory and then the PCs character exported.
A global variable is not persistent in any way, it is simply 'global', it is not stored on any object thus making it retrievable via its sVarName and not from an object.
A campaign variable is stored in the database folder in your NWN2 directory and also not on any object, and is persistent and retrievable from any script as long as it exists.
The thread is here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=539873&forum=114
These get get saved to the Bioware Database, which is included in NWN2. They can be accessed via the SetCampaign* and GetCampaign* functions. This is a physical write to the hard drive, and can bog down servers if there are a lot of requests happening at once.
It is worth noting that variable names cannot be longer than 32 characters, or the setting of the variable will fail.
A good system for managing campaign variables is Knat's NBDE.
Globals get saved to a globals.xml file that gets placed in your save game directory when you save the game. You can set and get global variables with the SetGlobal* and GetGlobal* functions.
These variables exist at a level similar to the campaign folder, meaning they exist in the context of a saved game and can cross from one module to another. They are not physically written to the xml file until a save happens, however.
A good way to check that your variables are getting saved correctly is to save the game an open the file.
One important thing to note is that global variable names can have spaces, but they cannot be more than 32 characters long.
Here are the script templates you can add by right clicking in the Scripts window and choosing "Add From Template." I found it nice to have them available outside of the Toolset for ease of reference.
I'll be adding the rest later.
Use this template when you are creating a script that will control actions during a conversation. Pass the variable nAction from the conversation to tell the script which case you want to perform. For instance, pass 100 as the nAction argument to execute the code for case 100.
If you need more information on what a case statement is, see the Wikipedia entry on case statements.
A common way to control the action in conversation switches is with ActionPauseCutscene() and AssignCutsceneActionToObject(). A cut scene action is an action that has a special flag that tells the pause function to resume once the action has been complete. An example from the OC would is:
ActionPauseCutscene(1000, FALSE); AssignCutsceneActionToObject(oRegulator, ActionWait(1.0f));
This example uses a regulator because the example it comes from (a romance script in module 3500) needed to keep both speakers available for other actions. For best results, a regulator is an Ipoint speaker, which can be found under Blueprints > Placeables > Misc Props. I found that removing the heartbeat from the Ipoint and also using it as the speaker is a good way to make sure that you don't run into conflicting action assignments.
Once you have the pauses set and you static cameras place on your converations nodes, you can add custom functions in the case that will control the movement of other characters. For instance, in the following example you can see that there are a number of custom functions that are included in the file that get referenced.
case 6: ActionPauseCutscene(15000, FALSE); AssignCutsceneActionToObject(oRegulator, ActionWait(15.0f)); MoveCameraman1Again(); PlayRomanceStinger(); MovePC(); DelayCommand(11.0f, FadeOut()); break;
and further down:
void MoveCameraman1Again()
{
object oCameraman = GetTarget("3501_cameraman1");
object oWP = GetTarget("3501_wp_camerman2");
AssignCommand(oCameraman, ClearAllActions(TRUE));
DelayCommand(1.0f, AssignCommand(oCameraman, ActionForceMoveToObject(oWP, FALSE)));
}
Note that I usually use GetNearestObjectByTag instead of GetTarget, but that's just because I'm not sure what GetTarget really does.
Obviously you can go pretty crazy with this. Here is the base code from the template for reference:
//
/*
master script for conversation X
*/
//
#include "ginc_actions"
void main(int nAction)
{
object oPC = GetPCSpeaker();
switch ( nAction )
{
case 100: //
break;
case 200: //
break;
case 300: //
break;
case 400: //
break;
case 500: //
break;
}
}
The onClientEnter cut scene script is a great way to start a cut scene conversation. Create either an Ipoint with a new tag or use a creature as the main speaker. Also create a conversation. Then plug these two into number three (below).
The condition to play and the additional cutscene scripting are great places to use variables, either on the module or campaign level, to control whether the cut scene should fire. For instance, if you set a quest tracking variable called "sidequest2" to be 10 when the party got the quest, and you wanted to test for condition sidequest2 == 10, you'd place that in step two below. Then in the additional cut scene scripting you'd update the quest tracking variable to 20 so that the game knew not to play this cutscene again.
// Area OnClientEnter Cutscene.nss
/*
Area OnClientEnter event handler template. Setup cutscene(s) to fire when the party enters a new area.
This script will execute after a group area transition using JumpPartyToArea().
bCutsceneCondition will determine if a cutscene should play, but each cutscene is restricted to play only once.
HOW TO SETUP A CUTSCENE:
0. Copy and paste script block into "CLIENT ENTER CUTSCENES"
1. Specify a title for your cutscene
2. Replace (FALSE) with condition to play cutscene
3. Specify Speaker and Dialog of conversation
4. Add additional cutscene scripting
// Cutscene: 1. Example Title
if (GetIsCutscenePending(stCI) == FALSE)
{
bCutsceneCondition = (FALSE); // 2. Replace (FALSE) with condition to play
sSpeakerTag = ""; // 3. Specify Speaker and Dialog
sDialogName = "";
stCI = SetupCutsceneInfo(stCI, sSpeakerTag, oPC, sDialogName, bCutsceneCondition);
if (GetIsCutscenePending(stCI) == TRUE)
{
// 4. Additional cutscene setup
}
}
*/
// BMA-OEI 2/3/06
// BMA-OEI 2/7/06 added speaker == PC check
// ChazM 2/7/06 modified implementation
// ChazM 2/7/06 moved funcs to ginc_cutscene
// BMA-OEI 2/7/06 support multiple cutscenes
// BMA-OEI 2/7/06 revert original controlled char
// BMA-OEI 2/8/06 added comments, Group Area Transition restriction
#include "ginc_cutscene"
int StartingConditional()
{
// Do not execute if OnClientEnter was not fired from a group area transition
if (FiredFromPartyTransition() == FALSE) return (FALSE);
// Get party leader, force control of owned PC
object oPC = GetFirstEnteringPC();
object oLeader = GetFactionLeader(oPC);
oPC = SetOwnersControlledCompanion(oLeader);
// Initialize temp CutsceneInfo
struct CutsceneInfo stCI;
stCI = ResetCutsceneInfo(stCI);
int bCutsceneCondition;
string sSpeakerTag;
string sDialogName;
// *** START CLIENT ENTER CUTSCENES ***
// Cutscene: 1. Example Title
if (GetIsCutscenePending(stCI) == FALSE)
{
bCutsceneCondition = (FALSE); // 2. Replace (FALSE) with condition to play
sSpeakerTag = ""; // 3. Specify Speaker and Dialog
sDialogName = "";
stCI = SetupCutsceneInfo(stCI, sSpeakerTag, oPC, sDialogName, bCutsceneCondition);
if (GetIsCutscenePending(stCI) == TRUE)
{
// 4. Additional cutscene setup
}
}
// *** END CLIENT ENTER CUTSCENES ***
// Cue cutscene or revert control to original character
if (GetIsCutscenePending(stCI) == TRUE)
{
FireAndForgetConversation(stCI.oSpeaker, oPC, stCI.sDialog);
}
else
{
SetOwnersControlledCompanion(oPC, oLeader);
}
// If cutscene is pending, fade to black
return GetIsCutscenePending(stCI);
}
Here are some common scripting tasks.
A common task that can be more confusing that it should be is adjusting the level, equipment or gold of a character when entering a module. A solid understanding of what scripts are called when the PC enters is a good place to start. Much of this information is taken from this post: http://nwn2forums.bioware.com/forums/viewtopic.html?topic=528278&forum=1...
When a PC logins in, the first events to fire are the OnAcquireItem and OnPlayerEquipItem events. At that point, the PC object exists and can have inventory. But it has no location.
Then OnClientEnter fires. The PC object is complete, but still has no location. (the lack of location is what causes most scripting issues)
Once the PC has been assigned an area, OnPCLoaded is called.
Then OnEnter and OnClientEnter are called for the area the PC ends up in. (OnEnter is called for all creatures entering an area - including NPC right after onModuleLoad, OnClientEnter is just for PCs)
A trigger would be called last.
One more thing I noticed: when you transition to a new module in a campaign (StartNewModule and LoadNewModule), OnPCLoaded is not called. OnClientEnter is called, and so are the area's OnEnter and OnClientEnter. (onClientLeave is also not called)
OnPCLoaded is called when a PC logs out and back in.
Adjusting the new characters
The best way I've found to adjust a new PC is to use an OnClientEnter Script. Go to View > Module Properties to get to the Module Properties window. Under the Scripts heading, look for the On Client Enter Script.
The following script is an example that checks to see if this is the first time the PC has entered the current campaign, removes all inventory, then sets the XP and gold for a level 3 character.
// example_oncliententer
/*
Description:
Onclient enter to call
Also has additional functions to set up first time
entry scripts for the pc.
FRW xp and gold guidelines:
Level XP Gold
2nd 1,000 450
3rd 3,000 1,350
4th 6,000 2,700
5th 10,000 4,500
6th 15,000 6,500
7th 21,000 9,500
8th 28,000 13,500
9th 36,000 18,000
10th 45,000 24,500
11th 55,000 33,000
12th 66,000 44,000
13th 78,000 55,000
14th 91,000 75,000
15th 105,000 100,000
16th 120,000 130,000
17th 136,000 170,000
18th 153,000 220,000
19th 171,000 290,000
20th 190,000 380,000
*/
// Vendalus Nov 15, 2008
// Removes all items from the players inventory
void RemoveAllItems( object oPC )
{
DestroyObject(GetItemInSlot(INVENTORY_SLOT_ARMS, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_BELT, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_BOOTS, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CLOAK, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_HEAD, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_LEFTRING, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_NECK, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC));
DestroyObject(GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oPC));
object oItem = GetFirstItemInInventory();
while( GetIsObjectValid(oItem) ){
DestroyObject(oItem);
oItem = GetNextItemInInventory();
}
}
// Checks to see if this player has already entered the campaign for the first time
int GetHasEnteredThisCampaign( object oPC )
{
return GetGlobalInt("ENTERED_"+GetName(oPC));
}
// Notes that this player entered the module for the first time
void SetHasEnteredThisCampaign( object oPC )
{
SetGlobalInt("ENTERED_"+GetName(oPC), TRUE);
}
// Gives some starting gold
void GiveStartingGold( object oPC, int nAmount )
{
int nGold = GetGold(oPC);
TakeGoldFromCreature(nGold, oPC, TRUE);
GiveGoldToCreature(oPC, nAmount);
}
void main()
{
// get our entering player
object oPC = GetEnteringObject();
// Only run if this is a pc who is entering for the first time
// and who is not a DM.
if( GetIsPC(oPC) && !GetHasEnteredThisCampaign(oPC) && !GetIsDM(oPC)){
// Note that this pc has entered for the first time
SetHasEnteredThisCampaign(oPC);
// Remove all items from the entering player
RemoveAllItems(oPC);
// Give them some starting gold for level 3
GiveStartingGold(oPC, 1350);
// Adjust to level 3
SetXP(oPC, 3000);
}
}
Obviously in a case like this, you'd want to present the character with a store immediately. Note also that there is a chart at the top of the script showing the XP and total gold guidelines per level as outlined by the Forgotten Realms Weave.
Similarly, when the PC logs out OnClientLeave gets called. At that time, the client information is no longer associated with the object, just the physical characteristics. (which is another scripting issue) Then OnExit for the area is called (unless the PC logs out dead, then it is not called). Usually, there is nothing to do here and there have been some reports of this not firing correctly all the time.
A good place to start with general animations is the switches page here:
http://wendersnaven.com/node/43
The short answer is that you can set the following variables on a creature:
Ambient Animations
X2_L_SPAWN_USE_AMBIENT = 1
Immobile Animations
X2_L_SPAWN_USE_AMBIENT_IMMOBILE
With no waypoints, "X2_L_SPAWN_USE_AMBIENT" includes the familiar wandering around near their spawn point and doing some basic interactions with other NPCs. "X2_L_SPAWN_USE_AMBIENT_IMMOBILE" causes them to do the same interactions (waving, force talking, etc.), but they stay in one place. They will turn to face other NPCs, however.
There are a few waypoints that cause additional behaviors. From x0_i0_amins:
Creatures will move randomly between objects in their
area that have the tag "NW_STOP". (I think there is a % chance of them doing this or the standard wander around.)
UPDATE: After some testing, it appears the behavior in the next two paragraphs does not work. Generally speaking, waypoints across areas don't work at all in NWN2. They tended to be inconsistent in NWN1, also. Begin incorrect documentation:
Creatures who are spawned in an area with the "NW_HOME" tag
will mark that area as their home, leave during the day,
and return at night.
Creatures who are spawned in an outdoor area (for instance,
in city streets) will go inside areas that have one of the
interior waypoints (NW_TAVERN, NW_SHOP), if those areas
are connected by an unlocked door. They will come back out
as well.
End incorrect documentation.
There is a good conversation about ambient animations scripts happening here:
http://nwcitadel.forgottenrealmsweave.org/showthread.php?t=1184
qwertyuiop666 asked a question about how one would go about changing the background music in an area when a player walks over a trigger. Here's his question:
I would like to have the music change when the player walks down a path. I am assuming that the best option is to do it from a generic ground trigger to change the music playing when I step on it? I managed to make a trigger that stops the current song. That was easy. I made the ground trigger and then in the "On Enter Script" I just used the "ga_music_stop" script from the drop down.
Shaughn78 and Melirinda were kind enough to give some helpful suggestions. Here is the script that Shaughn78 eventually posted with some minor tweaks for readaiblity:
void main()
{
object oEnter = entering object;
object oArea = GetArea(oEnter);
int nMusic = GetLocalInt (OBJECT_SELF,"music");
int nDefault = GetLocalInt (OBJECT_SELF,"default");
int nCurrent = Get Current Music;
int nOnce = GetLocalInt (OBJECT_SELF,"once");
if(!GetIsPC(oEnter))
{
return;
}
if (nOnce == 0)
{
SetLocalInt (OBJECT_SELF,"once",1);
SetLocalInt (OBJECT_SELF,"default",nCurrent);
}
if(nCurrent != nMusic)
{
MusicBackgroundChangeDay(oArea, nMusic);
}
else
{
MusicBackgroundChangeDay(oArea, nDefault);
}
}
See the full thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=645938&forum=114
UPDATE: Kaldor Silverwand recently posted a good walkthrough on how to use the death and bleeding scripts from SoZ on the official forums. If you've got that installed, it might be a nice reference.
There are a number of options out there for dealing with death, but when dealing with respawn, there is one very important thing to know:
The death and respawn event scripts never on Respawn fire when you use the GUI_DEFAULT_DEATH_SCREEN with DisplayGuiScreen. This is the call for nwn_o0_death, the default script for death events.
Both nwn_o0_death and nwn_o0_respawn contain respawn code, but the gui actually uses a callback script named gui_death_respawn. Opening this file through the File > Open script/conversation menu, you'll see that the default death script is:
// gui_death_respawn.nss
/*
Death GUI 'Respawn' callback: wake up groggy
*/
// BMA-OEI 6/29/06
#include "ginc_death"
void main()
{
// Resurrect PC
object oPC = OBJECT_SELF;
WakeUpCreature( oPC );
RemoveDeathScreens( oPC );
// Apply Groggy penalty
effect eGroggy = EffectDazed();
//eGroggy = EffectLinkEffects( EffectSlow(), eGroggy );
ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eGroggy, oPC, RoundsToSeconds( 2 ) );
}
This results in the character standing up right where the died. Generally, it is better to send them to a safe place, such as a standard waypoint with the tag "NW_DEATH_TEMPLE".
For example, here is how Lordniah did his respawn callback script in the FRW base module.
// gui_death_respawn.nss
/*
Death GUI 'Respawn' callback: wake up groggy
*/
// BMA-OEI 6/29/06
#include "ginc_death"
void main()
{
// Resurrect PC
object oPC = OBJECT_SELF;
WakeUpCreature( oPC );
RemoveDeathScreens( oPC );
// Apply Groggy penalty
effect eGroggy = EffectDazed();
//eGroggy = EffectLinkEffects( EffectSlow(), eGroggy );
ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eGroggy, oPC, RoundsToSeconds( 2 ) );
//Jump respawner to temple waypoint if it exists
object oTemple = GetObjectByTag("NW_DEATH_TEMPLE");
if(GetIsObjectValid(oTemple))
{
ClearAllActions(TRUE);
ActionJumpToLocation(GetLocation(oTemple));
}
}
Thanks to Lordniah for putting that comment in his k_module_respawn script that it never fires. Hopefully this info will help someone else out there.
Thanks to cdaulepp and loudent2 for pointing this one out:
When you are using GetGoldPieceValue() on an item to get the value, if the item is not identified the function will return 1.
See the full post here:
GetGoldPieceValue() Does it work correctly?
Lugoun posted this handy script in the Helpful Scripts thread in the official forums. It allows you to do a find and replace on a string. Just pass in the text you want to perform the find and replace on, the string to find and the string you want to replace it with. His script is below and I've added comments.
// Returns a string based on sStartString where sCurrentWord is replaced by sNewWord
string FindReplaceSubString(string sStartString, string sCurrentWord, string sNewWord)
{
int nLength = GetStringLength(sStartString);
int nCurrSubLoc = FindSubString(sStartString, sCurrentWord);
string sLeftSide = GetStringLeft(sStartString, nCurrSubLoc);
int nCurrentLength = GetStringLength(sCurrentWord);
int nLeftSideLength = nCurrSubLoc + nCurrentLength;
int nRightSideLength = nLength - nLeftSideLength;
string sRightSide = GetStringRight(sStartString, nRightSideLength);
string sNewString = sLeftSide + sNewWord + sRightSide;
return sNewString;
}
So for instance, you can do a call like this:
string sStartString = "the quick brown fox is quick";
string sNewString = FindReplaceSubString(sStartString, "quick", "slow");
Which would assign sNewString a value of "the slow brown fox is slow".
You can make a creature lay down by placing the following two commands on a dialog node:
ga_play_ca_snd with the sAnim set to "laydownB"
ga_play_custom_animation with the sAnim set to "proneB"
Make them stand up by using:
ga_play_custom_animation with sAnim set to "standupB"
Note that this only work for NPCs you can select via a tag.
Thanks to John B. Gardner's Animation Viewer, where I figured out how to do this.
In this thread, puiwaihin was trying to figure out why his invisible creature couldn't cast spells at the PCs. In the end they figured out that anything that is invisible or hidden can't do it.
jackyo123 suggested making the creatures super small instead.
Check it out here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=576056&forum=114
Bemmu over at NWScript.com has created a tutorial that will take you through creating a basic conversation with an attached script to give the PC Speaker some gold.
Tutorial level: very basic
Following along with this tutorial should only take a few minutes. The goal will be to create a new Neverwinter Nights 2 module with one creature in it that you can interact with to receive gold from it.
Click here to view the tutorial:
http://www.nwscript.com/how-to-make-an-npc-give-you-gold.php
Bemmu over at NWScript has created a tutorial for attaching a script to a lever that will open a door.
Tutorial level: very basic
The goal in this tutorial is to create a lever that will cause a door to open when pulled. Following along should be very easy and there will only be about three lines of nwscript (the scripting language in Neverwinter Nights 1 & 2) involved.
Head over to NWScript to check it out:
http://www.nwscript.com/making-a-lever-operated-door.php
Bemmu over at NWScript.com has created a tutorial for creating multiple objects in a line using vectors. The object in question happens to be beer!
Tutorial level: basic
A nice feature of virtual worlds is that things can be created out of thin air without cost. In this tutorial we will play a bit with this by creating a sort of beer vending machine, where pulling a lever will add a new beer bottle to the end of an endlessly expanding row of them.
Head over to NWScript to check it out:
http://www.nwscript.com/infinite-beer.php
A great way to control ambient movement of NPCs is using scripted waypoints. See the sticky thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=512800&forum=114
You can see scripted waypoints at work in the Official Campaign's 1700_Merchant_Quarter.mod and 3000_Neverwinter_A3.mod merchant exterior areas. In module 1700 the road network method is used for ambient commoners (although I could not find the actual script) and in 3000 the dock workers use it.
Here's what Charles Mead (Gameplay Scripter) posted:
Here's some info on a new feature called Scripted Waypoints.
Scripted waypoints builds on the current waypoints system by making the arrival at each waypoint call a script. There are no special requirements for preparing this – it will work with any NPC using the regular default scripts and any new or previously placed set of walkway points.
Quick refresher of the standard waypoint system:
Creatures will automatically walk along a sequence of waypoints that are tagged according to the following convention: “WP_<creature’s tag>_##”. The NPC will begin the journey at waypoint 1 and continue traveling sequentially to waypoint n, and then back again in reverse.
Basic Useage:
In the new “scripted waypoint” system, whenever a creature reaches a waypoint, it calls a script that is named very similarly to the tag used for the waypoints, like this: “wp_<creature’s tag>”. Notice there is just one script for the entire set of waypoints. If the script does not exist, then nothing additional happens and the NPC simply walks back and forth through the set of waypoints.
Below are some examples of “scripted waypoints” scripts:
Example 1.
This script tells the NPC to stop at every waypoint and face in the direction the waypoint is facing and pause 1 second before continuing to the next waypoint.
Notice the inclusion of “ginc_wp” which has a number of helpful functions such as FaceAndPause().
#include "ginc_wp"
void main()
{
int iCurrentWP = GetCurrentWaypoint();
FaceAndPause(iCurrentWP, 1.0f);
}
Note how we call GetCurrentWaypoint() which returns the waypoint we have just reached. This will typically always be the first thing called in a “scripted waypoints” script.
Example 2.
This is a more complex script that completely overrides the normal waypoint behavior and demonstrates how each waypoint can be individually scripted. It accomplishes the following:
When the NPC reaches waypoint 1, he will sit down for a few seconds, and then randomly travel to one of the other waypoints in the set other than the first.
When the NPC reaches waypoint 2, he will play a “get low” animation, and then proceed to waypoint 1.
When the NPC reaches waypoint 3, he will simply head back to waypoint 1.
If there are more than 3 waypoints in the set, then when the NPC reaches one of those he will behave in the default way.
#include "ginc_wp"
#include "ginc_wp"
void main()
{
int iCurrentWP = GetCurrentWaypoint();
int iNextWP;
switch (iCurrentWP)
{
case 1:
iNextWP = Random(GetNumWaypoints()-1) + 2;
SetNextWaypoint(iNextWP);
ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0, 7.0);
break;
case 2:
SetNextWaypoint(1);
ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0, 4.0);
break;
case 3:
SetNextWaypoint(1);
break;
}
}
Note in this example the use of SetNextWaypoint(). The “next” waypoint is the one the NPC is enroute to. SetNextWaypoint() allows us to override this and redirect the NPC to an alternate waypoint.
The script template “wp_tag” is available in the script templates directory in source safe. Simply copy and paste it with the proper script name, replacing the word “tag” with the tag of the creature that will be walking waypoints.
*Advanced Usage*
How to have two or more creatures with different tags walk the same set of waypoints:
To override the initial waypoint set a creature uses, simply set a local string variable “WP_TAG” on the creature with the value of the desired waypoint set to use. So, if you have a bear waypoint set for a creature tagged “bear”, you could get a chicken to also walk these waypoints by setting the chicken's local variable WP_TAG to “bear”.
Note that this variable is only checked when the creature is first spawned, so changing this value via script will have no effect.
How to change the set of waypoints a creature walks dynamically:
You can change the set of waypoints a creature walks at any time via script using this function:
object SetWWPController(string sWalkWayPointsTag, object oCreature=OBJECT_SELF);
So from the previous example, we could have our chicken walk the bear’s waypoints by calling this function in script:
SetWWPController(“bear”);
How to pause/restart a creature walking waypoints.
To stop a creature from walking waypoints, use:
SetWalkCondition(NW_WALK_FLAG_PAUSED, TRUE);
You may also want to clear all actions, otherwise, the creature will still complete his pending actions which will take him to whatever the next waypoint is.
To Restart a creature walking waypoints, use:
SetWalkCondition(NW_WALK_FLAG_PAUSED, TRUE);
The creature should get started on his next heartbeat.
How to create a road network:
The basic outline for a script like this is available in the script template “wp_road_walker” and reads as follows:
#include "ginc_wp"
const int REDIRECTOR_WP = 1;
void main()
{
int iCurrentWP = GetCurrentWaypoint();// where we are
int iNextWP;
switch (iCurrentWP)
{
case 1:
// Node 1 should be placed off somewhere out of the way. This is where the creatures
// will hang out in between reaching the end of the path and starting on a new path.
// Creatures will change their appearance in between travels.
// 1st param is the list of nodes they may reappear at. Must follow the pattern XX,YY,ZZ...
// 2nd param is the length of time to wait before reappearing.
StandardRedirectorNode("02,03", 5.0f);
break;
case 2:
// Nodes 2 on up define the network the road walkers travel. They will never return to the node
// they just came from. When they reach an end node (typically a door or a route out of the area)
// they will be be "redirector node" - typically node 1.
// 1st param is the list of nodes they may travel to. Must follow the pattern XX,YY,ZZ...
// (end nodes are those with only 1 element in the list)
// 2nd param is the redirector WP
StandardRoadNetworkNode("03", REDIRECTOR_WP);
break;
case 3:
StandardRoadNetworkNode("02", REDIRECTOR_WP);
break;
}
}
Where can I learn more about other thing I can do?
Many useful functions are listed in the prototypes of the include file “ginc_wp”.
Patcha posted a script to let PCs sit on objects.
I'm providing you the way to let object be "sittable" and the script that allow PC to sit on them!
The file contains:
- the script (in a .erf to import)
- the English tutorial to bring "sittable" objects
- the Italian tutorial (the same)
- a module with many brench and chairs, to test this mothod
Check it out on the vault:
http://nwvault.ign.com/View.php?view=NWN2Scripts.Detail&id=43
This apparently still uses the old "nw_g0_convplac" from NWN1. Follow these steps:
Test it out and your should get your conversation when you use the placeable.
The default treasure generation script seems to be gp_treasure_op_de. It seems to check variables set on the container it is called from. It includes some of the X2 scripts from HotU. I spent some time walking through how this all works.
Note: After playing with this system a bit more, I've found that:
1. The base chance is 50%. This means that unless you set the base chance on an area, you'll get just a few gold just over 50% of the time.
2. The magic treasure type tends to give one or two +1 weapons for a level 1 PC. This may be a bit over-powered for low-level mods.
3. For better customization, consider lordniah's FRW base module's implementation of the NWN1: SoU treasure scripts (For more see http://www.wendersnaven.com/node/98).
Here is the header comment, which explains the basics:
// gp_treasure_op_de
/*
Spawns in general purpose treasure and gold based on variables:
TreasureClass - one of three values. Default is low
const int X2_DTS_CLASS_LOW = 0; //Treasure Class Low
const int X2_DTS_CLASS_MEDIUM = 1; //Treasure Clas Medium
const int X2_DTS_CLASS_HIGH = 2; //Treasure Class High
TreasureType - add desired types together. For example, gold + disposable = 5
Defualt is 5 (gold + disp)
Note that you cannot add the same type more than once (i.e. no gold+gold).
const int X2_DTS_TYPE_DISP = 1;
const int X2_DTS_TYPE_AMMO = 2;
const int X2_DTS_TYPE_GOLD = 4; // actually gold and gems
(not allowed) const int X2_DTS_TYPE_ITEM = 8; // char specific Item (ignores treasure class)
const int X2_DTS_TYPE_MAGIC = 16; // random magic items
const int X2_DTS_TYPE_MUNDANE = 32; // random mundane items
This script should be placed in the container's OnOpen and OnDeath events.
If bashed, disposeable will be dropped and broken item generated.
If no treasures are generated, 1d20 gold will be created.
*/
This allows module authors to quickly create random treasure of different types by setting both the "TreasureClass" integer variable and the "TreasureType" integer variable on the container. "TreasureClass" uses a simple 0, 1, or 2. "TreasureType" uses a single number that adds up the type values you want for the container. For example, ammo (2) + gold (4) + magic items (16) would be a value of 22.
An important thing to note is that X2_DTS_TYPE_ITEM (8) is not allowed. Here is the reason given in a comment further down in the script: "these don't scale and are to dangerous for balance reasons to have in the standard treasure generation."
Our script then calls DTSGenerateTreasureOnContainer(), which is located in "x2_inc_treasure." This script first calls gets a random number of items to create based on the call to DTSGetMaxItems().
Looking at DTSGetMaxItems(), we see that it first looks for the module-level integer variable "X2_DTS_MAXITEMS." If it can't find it, it uses a default of 2. Note that this variable is not set in the switches file or in the default "On Module Load" file, which means the value will be 2 unless you have specifically set it.
Returning to DTSGenerateTreasureOnContainer(), the next step is to call DTSGenerateTreasureItems() for each item we are going to create. This function checks the chances for each of the types of items we told it to create with the variables set on the container. The chance is defined by DTSGetBaseChance(). The default is defined as 50 in the constants at the top of the file, but these can be overridden at the area and module level with the variable "X2_DTS_BASECHANCE." If a class and chance condition is met based on a randomized number, an item is created by DTSGetRandomItemResRef().
Looking at DTSGetRandomItemResRef(), we see that we first have to get the name of the .2da file we want to reference using DTSGet2DANameByType(). This file looks for a module-level string variable, and uses a default if it can't find one.
The variables it looks for are:
(Note that these match the constants uses for the treasure type.)
The default .2da files that will be used are:
Remember that all these files can be found in Data/2da.zip, in your NWN2 programs files ("C:\Program Files\Atari\Neverwinter Nights 2\Data" by default). Extracting the .zip files to your desktop and opening the .2da files in Microsoft Excel, will reveal how these are laid out. For example, looking at the random magic .2da file (des_treas_magic.2da), will show that the low class items are all +1, the medium class items are +1 and +2, and the high class items are +2, +3 and +4. There is also a very high column, which is probably left over from the epic levels in NWN1: HotU.
Controllore posted a concise answer to using the old HotU "wantering encounter while resting" script.
View the module properties, in the On Module Load event you will see "x2_mod_def_load". Uncomment the line (around 123)
SetModuleSwitch ( MODULE_SWITCH_USE_XP2_RESTSYSTEM, TRUE )
Then where you see
SetWanderingMonster2DAFile( "des_restsystem" )
uncomment it and change "des_restsystem" with any other name you choose.
"des_restsystem" is the name of the 2da file that will be used for the wandering monsters (type, percentage of appearing at daytime/nighttime).
Edit des_restsystem.2da, do your changes and save it with the name you used in x2_mod_def_load.
That should do it.
Edit:
Into your areas, insert a variable named X2_WM_ENCOUNTERTABLE of type string. Its value must be the name used for the TableName in the des_restsystem.2da.
Read the full threat here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=535148&forum=114
Here's some helpful resources for working with companions... (more cominig soon)
The companion influence system used in the OC is not available by default in new modules. To get them, copy all of the kr_influence* scripts from "C:\Program Files\Atari\Neverwinter Nights 2\Campaigns\Neverwinter Nights 2 Campaign." You can then paste them into your own campaign. Note that you will need to edit the constants and companion names across all scripts to match your own companions.
In a conversation between Wayne and Lord Niah over in the FRW forums Lord Niah had some good suggestions for working with companions.
Here are some rules of thumb for dealing with companions and the roster. I don't recall some the exact names for commands and do not have acces to the toolset at the moment.
#1 You should only have one instance of a companion placed within your campaign and you should never spawn that companion using CreateObject.
#2 If you want to destroy a companion, then use the despawn command (not the DestroyObject command)
#3 If you want to spawn your companion back in, use the spawn command instead of CreateObject
#4 If you want to add your companion to the roster, but don't want players to see them in the GUI selection screen, then just mark them as Campaign NPCs. Don't waste time adding/removing the companion from the roster every time they join or leave the party. Once they are in the roster, you just have to add/remove them from the party.
Check out the forum here:
http://nwcitadel.com/forums/showthread.php?t=873
Henchmen are companions who the player cannot directly control or adjust inventory for. Thanks to sgt_why for this explanation on how to set them up.
Here's his post from http://nwn2forums.bioware.com/forums/viewtopic.html?topic=545390&forum=114
for this example;
string sTag = "c_human"// is this a henchmen ? TRUE or FALSE
gc_henchman(sTag)// this adds them to your party as henchmen, not companion
ga_henchman_add(sTag);
/*
note: this has (4) actual parameters ... the last flag can be very useful.
sTag - tag of the creature you want to add
bForce - if set to 1, sTarget will be added even if player already has maximum henchman
sMaster - The Creature you are adding the henchman to (default is PC Speaker)
bOverrideBehavior - if set to 1, sTarget's event handlers (scripts) will be replaced with henchman ones.
*/// removes the henchmen from the party
ga_henchman_remove(sTag);- - - - -
I put all of these into the conversations and seems to work great. In fact, think if the henchman dies .. they are removed from the group as well.And you cant click on them and change thier inventory .. although I did notice there appear to be scripts out there to make the henchman show you his inventory and such, like a companion. But it would need to be during a conversation or such. (I think?)
I wanted to add a couple "friendly"(s) in my areas .. that if the PCs save them, will offer to help out for a short time .. as well as award 50xp for not letting the mobs kill them off.
Following his directions, I was able to create a few henchmen and get them to work with very little setup. Some quick things I noticed:
Kudos to OE on making such an easy to use system, and thanks again to sgt_why
Include ginc_groups to see a number script used for working with group of creatures.
Recently DaveyHavock asked a question about how to use groups to create an onDeath event.
Howdy, wondering if someone has a moment to explain how the custom group ondeath script is used. I guess what i dont understand is how to name the grp, i see it uses getgroupname, but how do i define what the group is?
Kaldor Silverwand provided a good response with an example script:
The first meeting with Neeshka makes use of groups in this way.
The functions you'll need are are in ginc_group.
Here is a bit of script that I have used for having a few halfling NPC's put into a group and then a script is started once they are dead.
Here's the code he posted. Remember to include ginc_groups. Change the group name and tags, then attach this on a dialog action and you're good to go!
string sGroupName = "HalflingBrothers";
object oNHalfling;
int i;
ResetGroup(sGroupName);
for (i = 1; i<=3; i++)
{
object oNHalfling = GetObjectByTag("NHalfling" + IntToString(i));
GroupAddMember(sGroupName, oNHalfling);
ChangeToStandardFaction(oNHalfling, STANDARD_FACTION_HOSTILE);
StandardAttack(oNHalfling, GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC));
}
GroupOnDeathExecuteCustomScript(sGroupName, "0160_a_cs_halfling_postfight");
See the full thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=646321&forum=114
It's important to name your scripts in a consistent manner so that you know what they do and you know where to find them when you need them. Here is some information to help with naming.
Barry The Hatchet posted a good roll up of the script naming conventions the CODI project came up with in NWN1. Here's the link: http://nwcitadel.forgottenrealmsweave.org/showthread.php?t=1131
Here's the actual list:
Include Scripts
Include scripts should be prefixed with INC_
Event Driven Scripts
Following the prefix for EVENT driven scripts, this is the majority; you have 1 letter denoting the object type that has the event this script goes in, they are as follows:
* N - NPC
* M - Monster/Creature
* A - Area
* O - Module
* P - Placable
* T - Trigger
* D - Door
* R - Trap
* C - Conversation
* E - Encounter
* I - Item - This script is not placed on an item per se, but called by module level scripts.
* X - No Object - Use this for a script that is called by other scripts. Executable scripts.
This character is followed by a two character short for the event it goes in, by category:
* N, M
o CO - onConversation
o DI - onDisturbed
o PA - onPhysicalAttacked
o SP - onSpawn
o UD - onUserDefined
o SC - OnSpellCastAt
o BL - onBlocked
o DM - onDamaged
o HB - onHeartbeat
o DE - onDeath
o CR - onCombatRoundEnd
o PE - onPerception
o RE - onRest
* A
o EN - onEnter
o EX - onExit
o HB - onHeartbeat
o UD - onUserDefined
* O
o CE - onClientEnter
o CL - onClientLeave
o PR - onPlayerRest
o RS - onRespawn
o DY - onPlayerDying
o DE - onPlayerDeath
o LE - onPlayerLevelUp
o IA - onItemActivated
o IQ - onItemAquired
o UI - onUnaquireItem
o ML - onModuleLoad
o HB - onHeartBeat
o UD - onUserDefined
o EI - onEquipItem
* P
o US - onUsed
o HB - onHeartBeat
o DE - onDeath
o AT - onAttacked
o SC - onSpellCastAt
o DM - onDamaged
o OP - onOpen
o OC - onClosed
o DI - onDisturbed
o LO - onLocked
o UL - onUnlocked
o UD - onUserDefined
* T
o CL - onClick
o EN - onEnter
o EX - onExit
o HB - onHeartBeat
o UD - onUserDefined
* D
o AT - onAreaTransitionClick
o OC - onClosed
o DM - onDamaged
o DE - onDeath
o FO - onFailedToOpen
o HB - onHeartBeat
o LO - onLocked
o OP - onOpened
o AT - onAttacked
o SC - onSpellCastAt
o UL - onUnlocked
o UD - onUserDefined
* R
o DI - onDisarmed
o TT - onTrapTriggered
* E
o EN - onEnter
o EX - onExit
o OE - onExhausted
o HB - onHeartBeat
o UD - onUserDefined
* C
o AT - Actions Taken
o AP - Appears When (StartingConditional Script)
o AB - onConversation Aborted
o EN - onConversation end
* I
o US - Called when the item is used.
o AQ - Called when the item is Aquired.
o UA - Called when the item is UnAquired.
Prefix examples
Module OnClientEnter script prefix: OCE_
Area OnEnter script prefix: AEN_
Placeable OnUsed prefix: PUS_
__________________
Just bend the pieces 'til they fit.
buried in the official Toolset documentation is a section about naming conventions for scripts. I've replicated it here for easy reference.
All scripts in NWN2 are are prefixed with one of the following:
Use the following for item scripts:
|
i_<Item Tag>_ac |
script to execute when item activated |
|
i_<Item Tag>_aq |
script to execute when item acquired |
|
i_<Item Tag>_ua |
script to execute when item unacquired |
|
i_<Item Tag>_eq |
script to execute when item equipped |
|
i_<Item Tag>_ue |
script to execute when item unequipped |
The module events will be written to automatically execute the proper script.
Conversations have 2 script types.
|
a_<Speaker>… |
actions taken |
|
c_ <Speaker>… |
conditional (Text appears when...) |
Scripts for events on objects should have a prefix to indicate the Object Type. If an object has multiple events, a suffix should be added each script to indicate the Event Type.
|
Object Type |
Abbreviation |
|
Area |
use area num |
|
Creature (Being) |
b |
|
Door |
d |
|
Encounter |
e |
|
Merchant |
m |
|
Placeable |
p |
|
Trigger |
tr |
|
Event |
Abbreviation |
Area** |
Creature |
Door |
Encounter |
Merchant |
Placeable |
Trigger |
|
|
X |
|
|
|
|
|
||
|
click* |
ck |
|
|
X |
|
|
|
X |
|
close* |
cs |
|
|
X |
|
X |
X |
|
|
combat round end* |
ce |
|
X |
|
|
|
|
|
|
conversation |
co |
|
X |
|
|
|
|
|
|
damaged |
da |
|
X |
X |
|
|
X |
|
|
death |
de |
|
X |
X |
|
|
X |
|
|
disturbed |
di |
|
X |
|
|
|
X |
|
|
enter |
en |
X |
|
|
X |
|
|
X |
|
exhausted* |
ed |
|
|
|
X |
|
|
|
|
exit |
ex |
X |
|
|
X |
|
|
X |
|
fail to open |
fa |
|
|
X |
|
|
|
|
|
heartbeat* |
hb |
X |
X |
X |
X |
|
X |
X |
|
lock |
lo |
|
|
X |
|
|
X |
|
|
open |
op |
|
|
X |
|
X |
X |
|
|
perception |
pe |
|
X |
|
|
|
|
|
|
physical attacked |
at |
|
X |
X |
|
|
X |
|
|
rested |
re |
|
X |
|
|
|
|
|
|
spawn |
sp |
|
X |
|
|
|
|
|
|
spell cast at |
ca |
|
X |
X |
|
|
X |
|
|
unlock* |
ul |
|
|
X |
|
|
X |
|
|
used |
us |
|
|
|
|
|
X |
|
|
user defined* |
ud |
X |
X |
X |
X |
|
X |
X |
* These abbreviations don’t use the first 2 letters of the event name.
** Areas don’t need abbreviations.
Boldfaced events are defaults and are assumed if no event is given.
Scripts not covered above should use these prefixes
|
inc_ |
include file |
|
ai_ |
artificial intelligence (combat ai) |
|
n_ |
extra miscellaneous script |
For those of you like me who could not figure out how to open a system script except from the dropdown on creature properties, look under "File > Open Conversation/Script." The keyboard shortcut is "Ctrl + Shift + o."
It seriously took me a month to find that for some reason.
Thanks to DedoITA for pointing me in the direction of Lilac Soul's tutorial on spell hooks. Here's the introduction:
Since version 1.59, it has become exceedingly easy to hook spellcasting. Rather than having to edit each individual spell script, all you now how to do is create a single spell script of your own, and then have that script perform whatever you want the spell to do. In that script, you also get to set whether the original spell script should continue or not.
If you only want to edit a single spell, it may still be easier to just edit its spell script, but I still recommend using the spellhook system. Why? Because, if the spell script is updated in a future patch, your edits will still be valid, but so will the ones BioWare made.
However, the new spell-hook system is very useful for editing a number of spells (even all spells), for instance to make it so that they only work under certain conditions, or that, perhaps, the caster automatically takes a certain amount of damage whenever casting a spell. Thus, you can also use the spellhoook system to make certain creatures react to certain spells in different ways, etc. etc. The sky is the limit really.
Some of the menu options have changed for NWN2, but most of this is still valid.
Check out the full tutorial:
http://www.nwnlexicon.com/compiled/tutorial.lilacsoul-spell-hooking.html
Creating visual effects through scripting works much the same way in NWN2 as it did in NWN1. Use EffectVisualEffect() to create an effect, then ApplyEffectToObject() or ApplyEffectAtLocation() to place that effect in the game.
From the official NWN2 Documentation:
"Visual effects are composed of effect files, which are individual components of an effect (a particle system, a trail, a billboard, etc.), and SEF files, which point to the effect files and organize them into a more complex visual effect."
Effect constants start with "VFX_".
The following samples for creating visual effects through scripting are from the NWN1 Lexicon. (Currently the lexicon is at http://nwn1.nwn2lexicon.com/, but I'm unsure what's in store for that site.)
// Sample code for applying a VFX_IMP_ visual, a AC-bonus
// (Mage armor) visual, to a target.
void main()
{
// This is the Object to apply the effect to.
object oTarget = OBJECT_SELF;
// Create the visual portion of the effect.
effect eVis = EffectVisualEffect(VFX_IMP_AC_BONUS);
// Apply the visual effect to the target.
// - We apply VFX_IMP_ constants instantly, to a target.
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
}
// Sample code for applying a VFX_DUR_ visual, a
// stoneskin visual, to a target.
void main()
{
// This is the Object to apply the effect to.
object oTarget = OBJECT_SELF;
// Create the visual portion of the effect
effect eDur = EffectVisualEffect(VFX_DUR_PROT_STONESKIN);
// Apply the visual effect to the target.
// - We apply VFX_DUR_ constants for a duration, here
// it is permanent (could be temporary), to a target.
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eDur, oTarget);
}
// Sample code for applying a VFX_FNF_ visual, a fireball,
// to a location.
void main()
{
// This is the Target to apply the effect at.
location lTarget = GetLocation(OBJECT_SELF);
// Create the visual portion of the effect
effect eAOE = EffectVisualEffect(VFX_FNF_FIREBALL);
// Apply the visual effect to the target.
// - We apply VFX_FNF_ constants instantly, and only
// at a location.
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eAOE, lTarget);
}
Jassper asked a question in the official forums about certain VFX constants not working. Cracking open the visualeffects.2da, it was discovered that a lot of the effects listed don't have .sef files associated with them.
From loudent2 :
It turns out a lot of the effects have been deprecated. It isn't immedietely apparant which ones (I had a similar problem using the tornado effect). Not sure if this is the problem in your case.
And from Ravine_HU:
I've read somewhere about this... coz the VFXs totally changed in nwn2 - everything is in the sef-files. U can check the visualeffects.2da for the list - find the row, and if there is no xy.sef references in it...unlucky.
I personally miss some nice effect from nwn1, like this raise dead for example. I can't even find that kind of effect which is only visible to the PC whom attached to (for example, no effect for blindness...).
However, the visual effect editor is cool.
Oh yeah, and check the "broken functions list" topic too, there are some issues with applying visualeffects.
More from Jassper
After looking in the 2da file for spells, NWN2 uses visual sp_conjuration_conjure.sef for raise dead. I copied that to the visualeffects.2da under the heading VFX_IMP_RAISE_DEAD and vola! I have an effect - altough it is not the NWN1 style raise dead.
So that indeed seems to be the issue - these effects simply wern't included, or haven't been replaced yet.
BTW, quesion about saveing changes in the 2da's. Will the new 2da be local to that mod only, or is it now a global change for all modules?
And finally, from mykael22000
Saved .2das get written out to your override directory - meaning they'll affect all of your games, but aren't stored inside the module you edited so if you send it to someone else, they won't have a copy...
Get the nwnhak utility from NWN1, create a new hak and move the .2da into it. Then park it in your Hak directory and tell the module to use it. It still won't be sent to anyone with the module, but at least it'll complain and tell them that they are missing it. it also won't stuff up all of your other games.
Here is x2_inc_switches in its entirety. It's a great reference to have when trying to set options on objects via "switch" variables.
The most commonly used is probably the creature section for setting ambient animations, etc.
//------------------------------------------------------------------------------
// x2_inc_switches:: Interface for switching subsystem functionality
//------------------------------------------------------------------------------
/*
This file provides a basic interface for switching different Hordes of
the Underdark subsystems on/off and allows centralized access to certain
"expert" functionality like overriding AI or Spellscripts.
Changing any of these switches from their default position is considered
unsupported and done at your own risk - please do NOT send any bug reports
about problems caused by these switches.
*/
//------------------------------------------------------------------------------
// Copyright (c) 2003 Bioware Corp. * Created By: Georg Zoeller * On: 2003-07-16
//------------------------------------------------------------------------------
// ChazM (OEI) 10/20/05 - added MODULE_SWITCH_ENABLE_SEPERATE_ITEM_SCRIPTS, GetEventPostfix(),
// modified GetUserDefinedItemEventScriptName()
// ChazM (OEI) 4/4/06 - added support for 32 character script names for item scripts.
// BMA-OEI 8/21/06 -- Moved campaign flags from kinc_globals.nss
// ChazM 8/25/06 - Shortened campaign variable names to fit in 32 char limit.
//void main(){}
//------------------------------------------------------------------------------
// C A M P A I G N
//------------------------------------------------------------------------------
// These are stored as globals - note that global names can only be 32 chars long.
// Force kills dominated group members if no valid members remain - checked on HeartBeat ( nw_g0_dominate )
const string CAMPAIGN_SWITCH_FORCE_KILL_DOMINATED_GROUP = "N2_S_KILL_DOM_GROUP";
// Removes effect and prevents transition if object is dominated - checked on transition ( ginc_transition )
const string CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION = "N2_S_REMOVE_DOM_ON_TRAN";
// This global determines whether or not the campaign uses the personal reputation system, which affects
// whether or not neutrals can be damaged by spells
const string CAMPAIGN_SWITCH_USE_PERSONAL_REPUTATION = "N2_S_USE_PERSONAL_REP";
//------------------------------------------------------------------------------
// M O D U L E
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// * Force Use Magic Device Skillchecks, Default = FALSE except for GAME_DIFFICULTY_CORE_RULES+
// * If switched to TRUE, a rogue has to succeed in a UMD check against DC 25+SpellLevel
// * in order to use a scroll. See x2_pc_umdcheck.nss for details
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_UMD_SCROLLS = "X2_SWITCH_ENABLE_UMD_SCROLLS";
//------------------------------------------------------------------------------
// * Toggle on/off the Item Creation Feats, Default = O
// * Disable the Item Creation Feats that come with Hordes of the Underdark for the
// * module.
//------------------------------------------------------------------------------
const string MODULE_SWITCH_DISABLE_ITEM_CREATION_FEATS = "X2_SWITCH_DISABLE_ITEMCREATION_FEATS";
//------------------------------------------------------------------------------
// * Toggle Area of Effect Spell behaviour
// * If set to TRUE, AOE Spells will hurt NPCS that are neutral to the caster if they are
// * caught in the effect
//------------------------------------------------------------------------------
const string MODULE_SWITCH_AOE_HURT_NEUTRAL_NPCS = "X0_G_ALLOWSPELLSTOHURT";
//------------------------------------------------------------------------------
// * For balancing reasons the crafting system will create 50 charges on a new wand
// * instead it will create 10 + casterlevel charges. if you want to be "hard core rules compliant"
// * 50 charges, enable thiis switch
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_CRAFT_WAND_50_CHARGES = "X2_SWITCH_ENABLE_50_WAND_CHARGES";
//------------------------------------------------------------------------------
// * Some epic spells, namely Hellball, do damage to the caster. We found this too confusing
// * in testing, so it was disabled. You can reactivate using this flag
//------------------------------------------------------------------------------
const string MODULE_SWITCH_EPIC_SPELLS_HURT_CASTER = "X2_SWITCH_EPIC_SPELLS_HURT_CASTER";
//------------------------------------------------------------------------------// * Deathless master touch is not supposed to affect creatures of size > large
// * but we do not check this condition by default to balance the fact that the slain
// * creature is not raised under the command of the pale master.
// * by setting this switch to TRUE, the ability will no longer effect creatures of
// * huge+ size.
//------------------------------------------------------------------------------
const string MODULE_SWITCH_SPELL_CORERULES_DMASTERTOUCH = "X2_SWITCH_SPELL_CORERULE_DMTOUCH";
//------------------------------------------------------------------------------
// * By default, all characters can use the various poisons that can be found to poison their weapons if
// * they win a Dex check. Activating this flag will restrict the use of poison to chars with the UsePoison
// * feat only
//------------------------------------------------------------------------------
const string MODULE_SWITCH_RESTRICT_USE_POISON_TO_FEAT = "X2_SWITCH_RESTRICT_USE_POISON_FEAT";
//------------------------------------------------------------------------------
// * Multiple Henchmen: By default, henchmen will never damage each other with AoE spells.
// * By activating this switch, henchmen will be able to damage each other with AoE spells
// * and potentially go on each other's throats.
// * Warning: Activating this switch has the potential of introducing game breaking bugs. Do
// * not use on the official SoU campaign. Use at your own risk. Really, its dangerous!
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_MULTI_HENCH_AOE_DAMAGE = "X2_SWITCH_MULTI_HENCH_AOE_MADNESS";
//------------------------------------------------------------------------------
// * Spell Targeting: Pre Hordes of the underdark, in hardcore mode, creatures would not hurt each other
// * with their AOE spells if they were no PCs. Setting this switch to true, will activate the correct
// * behaviour. Activating this on older modules can break things, unless you know what you are doing!
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_NPC_AOE_HURT_ALLIES = "X2_SWITCH_ENABLE_NPC_AOE_HURT_ALLIES";
//------------------------------------------------------------------------------
// * If set to TRUE, the Bebilith Ruin Armor ability is going to actually destroy
// * the armor it hits. Would be very annoying for players...
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_BEBILITH_RUIN_ARMOR = "X2_SWITCH_BEBILITH_HARDCORE_RUIN_ARMOR";
//------------------------------------------------------------------------------
// * Setting this switch to TRUE will make the Glyph of warding symbol disappear after 6 seconds, but
// * the glyph will stay active....
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_INVISIBLE_GLYPH_OF_WARDING = "X2_SWITCH_GLYPH_OF_WARDING_INVISIBLE";
//------------------------------------------------------------------------------
// * Setting this switch to TRUE will enable the allow NPCs running between waypoints using the WalkWaypoints
// * function to cross areas, like they did in the original NWN. This was changed in 1.30 to use only
// * waypoints in one area.
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_CROSSAREA_WALKWAYPOINTS = "X2_SWITCH_CROSSAREA_WALKWAYPOINTS";
//------------------------------------------------------------------------------
// * Setting this switch to TRUE will disable the glow of a newly found secret door
// * used in some locations in XP2
//------------------------------------------------------------------------------
const string MODULE_SWITCH_DISABLE_SECRET_DOOR_FLASH = "X2_SWITCH_DISABLE_SECRET_DOOR_FLASH";
//------------------------------------------------------------------------------
// * Setting this switch to TRUE will disable execution of tagbased scripts that are enabled
// * by default when using the standard module events (x2_mod_def_*)
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS = "X2_SWITCH_ENABLE_TAGBASED_SCRIPTS";
//------------------------------------------------------------------------------
// * Only applies if MODULE_SWITCH_ENABLE_TAGBASED_SCRIPTS is true.
// This switch determines which type of tagbased scrtipting to use
// (used in module events g_mod_*, x2_s3_hitcastspell, and x2_inc_spellhook)
// FALSE = use X2 version wherein all item events are in 1 script.
// TRUE = use seperated scripts named "i__<2 letter postfix>"
//------------------------------------------------------------------------------
const string MODULE_SWITCH_ENABLE_SEPERATE_ITEM_SCRIPTS = "NWN2_SEPERATE_ITEM_SCRIPTS";
//------------------------------------------------------------------------------
// * Setting thsi switch to TRUE will enable the XP2 Wandering Monster System
// * for this module (if you are using the default rest script and you have set
// * up the correct variables for each area
//------------------------------------------------------------------------------
const string MODULE_SWITCH_USE_XP2_RESTSYSTEM = "X2_SWITCH_ENABLE_XP2_RESTSYSTEM";
//------------------------------------------------------------------------------
// * if this variable is set, the AI will not use Dispel Magic against harmfull AOE
// * spells.
//------------------------------------------------------------------------------
const string MODULE_SWITCH_DISABLE_AI_DISPEL_AOE = "X2_L_AI_NO_AOE_DISPEL";
//------------------------------------------------------------------------------
// * Setting this variable to TRUE on the module will disable the call to the
// * random loot generation in most creatures' OnSpawn script.
//------------------------------------------------------------------------------
const string MODULE_SWITCH_NO_RANDOM_MONSTER_LOOT = "X2_L_NOTREASURE";
//------------------------------------------------------------------------------
// M I S C
//------------------------------------------------------------------------------
const string MODULE_VAR_OVERRIDE_SPELLSCRIPT ="X2_S_UD_SPELLSCRIPT";
const string MODULE_VAR_TAGBASED_SCRIPT_PREFIX ="X2_S_UD_SPELLSCRIPT";
//------------------------------------------------------------------------------
// * Variable that holds the wandering monster 2da filename
//------------------------------------------------------------------------------
const string MODULE_VAR_WANDERING_MONSTER_2DA ="X2_WM_2DA_NAME";
//------------------------------------------------------------------------------
// * This variable allows to specify a % for NOT using dispel magic against AOEs
// instead fleeing
//------------------------------------------------------------------------------
const string MODULE_VAR_AI_NO_DISPEL_AOE_CHANCE = "X2_L_AI_AOE_DISPEL_CHANCE";
//------------------------------------------------------------------------------
// * Setting this variable to TRUE will cause the Combat Expertise/Improved Combat Expertise
// * modes to be disabled whenever a player is casting a spell.
//------------------------------------------------------------------------------
const string MODULE_VAR_AI_STOP_EXPERTISE_ABUSE = "X2_L_STOP_EXPERTISE_ABUSE";
//------------------------------------------------------------------------------
// C R E A T U R E S
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// * see x2_ai_demo for details
//------------------------------------------------------------------------------
const string CREATURE_VAR_CUSTOM_AISCRIPT = "X2_SPECIAL_COMBAT_AI_SCRIPT";
//------------------------------------------------------------------------------
// * Setting this variable on a spellcaster creature will make its spelluse a
// * bit more random, but their spell selection may not always be appropriate
// * to the situation anymore.
//------------------------------------------------------------------------------
const string CREATURE_VAR_RANDOMIZE_SPELLUSE = "X2_SPELL_RANDOM";
//------------------------------------------------------------------------------
// * Set to 1 to make the creature activate stealth mode after spawn
//------------------------------------------------------------------------------
const string CREATURE_VAR_USE_SPAWN_STEALTH = "X2_L_SPAWN_USE_STEALTH";
//------------------------------------------------------------------------------
// * Set to 1 to make the creature activate detectmode after spawn
//------------------------------------------------------------------------------
const string CREATURE_VAR_USE_SPAWN_SEARCH = "X2_L_SPAWN_USE_SEARCH";
//------------------------------------------------------------------------------
// * Set to 1 to make the creature play mobile ambient animations after spawn
//------------------------------------------------------------------------------
const string CREATURE_VAR_USE_SPAWN_AMBIENT = "X2_L_SPAWN_USE_AMBIENT";
//------------------------------------------------------------------------------
// * Set to 1 to make the creature play immobile ambient animations after spawn
//------------------------------------------------------------------------------
const string CREATURE_VAR_USE_SPAWN_AMBIENT_IMMOBILE = "X2_L_SPAWN_USE_AMBIENT_IMMOBILE";
//------------------------------------------------------------------------------
// * Set to 1 to make the creature immune to dispel magic (used for statues)
//------------------------------------------------------------------------------
const string CREATURE_VAR_IMMUNE_TO_DISPEL = "X1_L_IMMUNE_TO_DISPEL";
//------------------------------------------------------------------------------
// * Set this variable to 1 on a creature to make it walk through other creatures
//------------------------------------------------------------------------------
const string CREATURE_VAR_IS_INCORPOREAL = "X2_L_IS_INCORPOREAL";
//------------------------------------------------------------------------------
// * Set this variable to 1 - 6 to override the number of attacks a creature has based on its BAB
//------------------------------------------------------------------------------
const string CREATURE_VAR_NUMBER_OF_ATTACKS = "X2_L_NUMBER_OF_ATTACKS";
//------------------------------------------------------------------------------
// * The value of this variable (int) is added to the chance that a creature
// * will use magic in combat. Set to 100 for always, 0 for never
//------------------------------------------------------------------------------
const string CREATURE_AI_MODIFIED_MAGIC_RATE = "X2_L_BEH_MAGIC";
//------------------------------------------------------------------------------
// * The higher value of this variable, the higher the chance that the creature
// * will use offensive abilities in combat. Set to 0 to make them flee.
//------------------------------------------------------------------------------
const string CREATURE_AI_MODIFIED_OFFENSE_RATE = "X2_L_BEH_OFFENSE";
//------------------------------------------------------------------------------
// * The higher value of this variable, the higher the chance that the creature
// * will aid friendly creatures in combat. Not that helping usually degrades
// * the overall difficulty of an encounter, but makes it more interesting.
//------------------------------------------------------------------------------
const string CREATURE_AI_MODIFIED_COMPASSION_RATE = "X2_L_BEH_COMPASSION";
//------------------------------------------------------------------------------
// * This allows you to script items that enhance a palemaster's summoned creatures. You need
// * to put the name of a script into this variable that will be run on any creature called by
// * the pale master's summon undead ability. You can use this script to add effects to the creature.
// * You can use the OnEquip/OnUnEquip event hooks set this variable.
//------------------------------------------------------------------------------
const string CREATURE_VAR_PALE_MASTER_SPECIAL_ITEM = "X2_S_PM_SPECIAL_ITEM";
//------------------------------------------------------------------------------
// These constants define item messages that are routed to script files with
// the item tag's through the default XP2 module scripts.
//------------------------------------------------------------------------------
const int X2_ITEM_EVENT_ACTIVATE = 0;
const int X2_ITEM_EVENT_EQUIP = 1;
const int X2_ITEM_EVENT_UNEQUIP = 2;
const int X2_ITEM_EVENT_ONHITCAST = 3;
const int X2_ITEM_EVENT_ACQUIRE = 4;
const int X2_ITEM_EVENT_UNACQUIRE = 5;
const int X2_ITEM_EVENT_SPELLCAST_AT = 6;
const int X2_EXECUTE_SCRIPT_CONTINUE =0;
const int X2_EXECUTE_SCRIPT_END =1;
const int SCRIPT_MAX_STRING_LENGTH = 32;
const int SCRIPT_ITEM_EXTENSION_LENGTH = 3;
const string SCRIPT_EXTENSION_ITEM_EVENT_ONHITCAST = "_hc";
const string SCRIPT_EXTENSION_ITEM_EVENT_ACTIVATE = "_ac";
const string SCRIPT_EXTENSION_ITEM_EVENT_EQUIP = "_eq";
const string SCRIPT_EXTENSION_ITEM_EVENT_UNEQUIP = "_ue";
const string SCRIPT_EXTENSION_ITEM_EVENT_ACQUIRE = "_aq";
const string SCRIPT_EXTENSION_ITEM_EVENT_UNACQUIRE = "_ua";
const string SCRIPT_EXTENSION_ITEM_EVENT_SPELLCAST_AT = "_ci";
// Set the active User Defined Item Event
// X2_ITEM_EVENT_ACTIVATE
// X2_ITEM_EVENT_EQUIP
// X2_ITEM_EVENT_UNEQUIP
// X2_ITEM_EVENT_ONHITCAST
// X2_ITEM_EVENT_ACQUIRE
// X2_ITEM_EVENT_UNACQUIRE
// X2_ITEM_EVENT_SPELLCAST_AT
void SetUserDefinedItemEventNumber(int nEvent);
// Get the active User Defined Item Event
// X2_ITEM_EVENT_ACTIVATE
// X2_ITEM_EVENT_EQUIP
// X2_ITEM_EVENT_UNEQUIP
// X2_ITEM_EVENT_ONHITCAST
// X2_ITEM_EVENT_ACQUIRE
// X2_ITEM_EVENT_UNACQUIRE
// X2_ITEM_EVENT_SPELLCAST_AT
int GetUserDefinedItemEventNumber();
//------------------------------------------------------------------------------
// * Used to switch between different rule implementations or to subsystems for the game
// * see x2_inc_switches for more detailed information on these constants
//------------------------------------------------------------------------------
void SetModuleSwitch(string sModuleSwitchConstant,int bValue);
//------------------------------------------------------------------------------
// * Returns the value of a module switch
//------------------------------------------------------------------------------
int GetModuleSwitchValue(string sModuleSwitchConstant);
//------------------------------------------------------------------------------
// D O O R S
//------------------------------------------------------------------------------
const string DOOR_FLAG_RESIST_KNOCK = "X2_FLAG_DOOR_RESIST_KNOCK";
//------------------------------------------------------------------------------
// * Used to toggle custom flags on a door
// * oDoor - Door to set the switch on
// * Valid values for sDoorFlagConstant:
// * X2_FLAG_DOOR_RESIST_KNOCK -
// * Set to 1 to prevent knock from working with feedback.
// * Set to 2 to prevent knock from working without feedback
//------------------------------------------------------------------------------
void SetDoorFlag(object oDoor, string sDoorFlagConstant, int nValue);
int GetDoorFlag(object oDoor, string sDoorFlagConstant);
//------------------------------------------------------------------------------
// W A Y P O I N T S
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// * By setting this variable to 1 on a waypoint, a creature using this
// * waypoint as part of its WalkWaypoints routine will assume the facing
// * of the waypoint upon reaching it.
//------------------------------------------------------------------------------
const string WAYPOINT_VAR_FORCE_SETFACING = "X2_L_WAYPOINT_SETFACING";
//------------------------------------------------------------------------------
// I T E M S
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// NOTE: THIS NO LONGER WORKS. TO PREVENT MODIFICATION USE THE PLOT FLAG
//------------------------------------------------------------------------------
const string ITEM_FLAG_NO_CRAFT_MODIFICATION = "X2_FLAG_ITEM_CRAFT_DO_NOT_MODIFY";
void SetItemFlag(object oItem, string sItemFlagConstant, int nValue);
int GetItemFlag(object oItem, string sItemFlagConstant);
//------------------------------------------------------------------------------
// * Execute sScript on oTarget returning an integer.
// * Do not nest this function
//------------------------------------------------------------------------------
int ExecuteScriptAndReturnInt(string sScript, object oTarget);
//------------------------------------------------------------------------------
// * Sets the return value for scripts called via ExecuteScriptAndReturnInt
// * valid values are
// * X2_EXECUTE_SCRIPT_CONTINUE - continue calling script after executed scriptis done
// * X2_EXECUTE_SCRIPT_END - end calling script after executed script is done
//------------------------------------------------------------------------------
void SetExecutedScriptReturnValue(int nValue = X2_EXECUTE_SCRIPT_END);
//------------------------------------------------------------------------------
// * This is a security feature. If you are running a *local vault* server and you
// * have tag based script execution enabled, people could bring items into your
// * game that execute existing scripts. You can set a script prefix here to
// * prevent that. Note that you have to add this prefix to your item scripts in
// * the module to make them work.
//------------------------------------------------------------------------------
void SetUserDefinedItemEventPrefix(string sPrefix="");
//------------------------------------------------------------------------------
// S P E L L S C R I P T S
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Allows the module creator to specify a script that will be run before any spellscript is run
// You can call SetModuleOverrideSpellscript() at the end of the script specified by
// sScriptName. If you call this function this will prevent the original spellscript
// (and all craft item code) from being executed.
// If you do not add this line, the original spellscript and/or crafting code will
// run in addition to your script
//------------------------------------------------------------------------------
void SetModuleOverrideSpellscript(string sScriptName);
//------------------------------------------------------------------------------
// C R E A T U R E S
//------------------------------------------------------------------------------
void SetCreatureFlag(object oCreature, string sFlag, int nValue);
int GetCreatureFlag(object oCreature, string sFlag);
//------------------------------------------------------------------------------
// * Define a replacement script for DetermineCombatRound
// * See x2_ai_demo for details
//------------------------------------------------------------------------------
void SetCreatureOverrideAIScript(object oCreature, string sScriptName);
//------------------------------------------------------------------------------
// * Call this at end of your custom override AI script set via CREATURE_VAR_CUSTOM_AISCRIPT
// * See x2_ai_demo for details.
//------------------------------------------------------------------------------
void SetCreatureOverrideAIScriptFinished(object oCreature = OBJECT_SELF);
void ClearCreatureOverrideAIScriptTarget(object oCreature = OBJECT_SELF);
object GetCreatureOverrideAIScriptTarget(object oCreature = OBJECT_SELF);
//------------------------------------------------------------------------------
// * Define the name of the 2da file which is used for the wandering monster
// * system
//------------------------------------------------------------------------------
void SetWanderingMonster2DAFile(string s2DAName = "des_restsystem");
//----------------------------------------------------------------------------
// Interface to switch on / off specific subsystems or behaviors
// Check X2_INC_SWITCHES.NSS for details
//----------------------------------------------------------------------------
void SetModuleSwitch(string sModuleSwitchConstant,int bValue)
{
if (bValue == 0)
{
DeleteLocalInt (GetModule(),sModuleSwitchConstant);
return;
} else if ((sModuleSwitchConstant) == MODULE_SWITCH_AOE_HURT_NEUTRAL_NPCS && bValue == TRUE)
{
bValue = 10;
}
SetLocalInt (GetModule(),sModuleSwitchConstant, bValue);
}
//----------------------------------------------------------------------------
// Return the value of a module switch set by SetModuleSwitch
// See X2_INC_SWITCHES for a list of all module switches
//----------------------------------------------------------------------------
int GetModuleSwitchValue(string sModuleSwitchConstant)
{
int nRet = GetLocalInt (GetModule(),sModuleSwitchConstant);
return nRet;
}
void SetDoorFlag(object oDoor, string sDoorFlagConstant, int nValue)
{
if (nValue == 0)
{
DeleteLocalInt (oDoor,sDoorFlagConstant);
return;
}
SetLocalInt (oDoor,sDoorFlagConstant, nValue);
}
int GetDoorFlag(object oDoor, string sDoorFlagConstant)
{
int nRet = GetLocalInt (oDoor,sDoorFlagConstant);
return nRet;
}
void SetItemFlag(object oItem, string sItemFlagConstant, int nValue)
{
if (nValue == 0)
{
DeleteLocalInt (oItem,sItemFlagConstant);
return;
}
SetLocalInt (oItem,sItemFlagConstant, nValue);
}
int GetItemFlag(object oItem, string sItemFlagConstant)
{
int nRet = GetLocalInt (oItem,sItemFlagConstant);
return nRet;
}
void SetModuleOverrideSpellscript(string sScriptName)
{
SetLocalString(GetModule(),MODULE_VAR_OVERRIDE_SPELLSCRIPT,sScriptName);
}
string GetModuleOverrideSpellscript()
{
string sScript = GetLocalString(GetModule(),"X2_S_UD_SPELLSCRIPT");
return sScript;
}
//------------------------------------------------------------------------------
// You can call this in our overridden spellscript. If you call this
// this will prevent the original spellscript (and all craft item code)
// from being executed. If you do not add this line, the original spellscript
// and/or crafting code will run in addition to your script
//------------------------------------------------------------------------------
void SetModuleOverrideSpellScriptFinished()
{
SetLocalInt(OBJECT_SELF,"X2_L_BLOCK_LAST_SPELL",TRUE);
}
int GetModuleOverrideSpellScriptFinished()
{
int nRet = GetLocalInt(OBJECT_SELF,"X2_L_BLOCK_LAST_SPELL");
DeleteLocalInt(OBJECT_SELF,"X2_L_BLOCK_LAST_SPELL");
return nRet;
}
void SetCreatureOverrideAIScript(object oCreature, string sScriptName)
{
SetLocalString(oCreature,CREATURE_VAR_CUSTOM_AISCRIPT,sScriptName);
}
void SetCreatureOverrideAIScriptFinished(object oCreature = OBJECT_SELF)
{
// WriteTimestampedLogEntry("Custom AI Finished");
SetLocalInt(oCreature,"X2_SPECIAL_COMBAT_AI_SCRIPT_OK",TRUE);
}
object GetCreatureOverrideAIScriptTarget(object oCreature = OBJECT_SELF)
{
object oRet= GetLocalObject(oCreature,"X2_NW_I0_GENERIC_INTRUDER");
return oRet;
}
void ClearCreatureOverrideAIScriptTarget(object oCreature = OBJECT_SELF)
{
DeleteLocalObject(oCreature,"X2_NW_I0_GENERIC_INTRUDER");
}
void SetCreatureFlag(object oCreature, string sFlag, int nValue)
{
if (sFlag == CREATURE_VAR_IMMUNE_TO_DISPEL)
{
if (nValue != 0)
{
nValue = 10;
}
}
SetLocalInt(oCreature,sFlag ,nValue);
}
int GetCreatureFlag(object oCreature, string sFlag)
{
int nRet = GetLocalInt(oCreature,sFlag);
return nRet;
}
//----------------------------------------------------------------------------
// Get the current UserDefined Item Event Number
// X2_ITEM_EVENT_ACTIVATE
// X2_ITEM_EVENT_EQUIP
// X2_ITEM_EVENT_UNEQUIP
// X2_ITEM_EVENT_ONHITCAST
// X2_ITEM_EVENT_ACQUIRE
// X2_ITEM_EVENT_UNACQUIRE
// X2_ITEM_EVENT_SPELLCAST_AT
//----------------------------------------------------------------------------
int GetUserDefinedItemEventNumber()
{
return GetLocalInt(OBJECT_SELF, "X2_L_LAST_ITEM_EVENT");
}
//----------------------------------------------------------------------------
// Set the current UserDefined Item Event Number
// X2_ITEM_EVENT_ACTIVATE
// X2_ITEM_EVENT_EQUIP
// X2_ITEM_EVENT_UNEQUIP
// X2_ITEM_EVENT_ONHITCAST
// X2_ITEM_EVENT_ACQUIRE
// X2_ITEM_EVENT_UNACQUIRE
// X2_ITEM_EVENT_SPELLCAST_AT
//----------------------------------------------------------------------------
void SetUserDefinedItemEventNumber(int nEvent)
{
SetLocalInt(OBJECT_SELF,"X2_L_LAST_ITEM_EVENT",nEvent);
}
string GetEventPostfix()
{
string sPostfix = "";
int nEvent = GetUserDefinedItemEventNumber();
switch (nEvent)
{
case X2_ITEM_EVENT_ONHITCAST:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_ONHITCAST;
break;
case X2_ITEM_EVENT_ACTIVATE:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_ACTIVATE;
break;
case X2_ITEM_EVENT_EQUIP:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_EQUIP;
break;
case X2_ITEM_EVENT_UNEQUIP:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_UNEQUIP;
break;
case X2_ITEM_EVENT_ACQUIRE:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_ACQUIRE;
break;
case X2_ITEM_EVENT_UNACQUIRE:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_UNACQUIRE;
break;
case X2_ITEM_EVENT_SPELLCAST_AT:
sPostfix = SCRIPT_EXTENSION_ITEM_EVENT_SPELLCAST_AT;
break;
}
return (sPostfix);
}
//----------------------------------------------------------------------------
// Returns the name for the User Defined Item Event script for oItem,
// including possible prefixes configured by SetUserDefinedItemEventPrefix
//----------------------------------------------------------------------------
string GetUserDefinedItemEventScriptName(object oItem)
{
string sPrefix = GetLocalString(GetModule(), MODULE_VAR_TAGBASED_SCRIPT_PREFIX);
string sTag = sPrefix + GetTag(oItem);
int iMaxPreExtensionLength = SCRIPT_MAX_STRING_LENGTH - SCRIPT_ITEM_EXTENSION_LENGTH;
if (GetLocalInt(GetModule(), MODULE_SWITCH_ENABLE_SEPERATE_ITEM_SCRIPTS))
{
if (GetStringLength(sTag) > iMaxPreExtensionLength)
{
sTag = GetStringLeft(sTag, iMaxPreExtensionLength);
}
sTag = sTag + GetEventPostfix();
}
return sTag;
}
//----------------------------------------------------------------------------
// You can define a prefix for any User Defined Item Event here, to prevent
// people from executing scripts you do not like them to execute on your
// local vault server
//----------------------------------------------------------------------------
void SetUserDefinedItemEventPrefix(string sPrefix="")
{
SetLocalString(GetModule(), MODULE_VAR_TAGBASED_SCRIPT_PREFIX, sPrefix);
}
//----------------------------------------------------------------------------
// Wrapper for Execute Script to execute a script and get an integer
// return value. Do not nest this function!
//----------------------------------------------------------------------------
int ExecuteScriptAndReturnInt(string sScript, object oTarget)
{
DeleteLocalInt(oTarget,"X2_L_LAST_RETVAR");
ExecuteScript(sScript,oTarget);
int nRet = GetLocalInt(oTarget,"X2_L_LAST_RETVAR");
DeleteLocalInt(oTarget,"X2_L_LAST_RETVAR");
return nRet;
}
//----------------------------------------------------------------------------
// Helper function for ExecuteScriptAndReturnInt
//----------------------------------------------------------------------------
void SetExecutedScriptReturnValue(int nValue = X2_EXECUTE_SCRIPT_CONTINUE)
{
SetLocalInt(OBJECT_SELF,"X2_L_LAST_RETVAR",nValue);
}
//----------------------------------------------------------------------------
// Define the name of the 2da file which is used for the wandering monster
// system
//----------------------------------------------------------------------------
void SetWanderingMonster2DAFile(string s2DAName = "des_restsystem")
{
SetLocalString(OBJECT_SELF,MODULE_VAR_WANDERING_MONSTER_2DA,s2DAName);
}
The OC uses a campaign system where there is a central umbrella that connects all the different parts (modules). It would seem that this is a great tool for builders who want to publish a series of modules. So far that has not been a lot of talk about this (I think a lot of people are still getting used to the Toolset), but I think it will become more important as time passes. Here's a thread on the official forum talking about campaigns: http://nwn2forums.bioware.com/forums/viewtopic.html?topic=527622&forum=113
A success story with some suggestions from Quoll.
My campaign is working smoothly. I also had a hitch getting it to load at first, and it was all simply a naming issue. Make sure your campaign start module is named the same as a real module in your campaign... then I think it was either adding the ".mod" or removing it. I'd check for sure but I'm not near my editor, but if what you have doesn't work, try the other way.
On the campaign vs module resources, so far it seems to me to simply be a cool way to manage resources. If you know you only use scripts, characters, etc for a short time, only load them for that period, then never again. Those would be the module resources. If you have a companion or scripts you use all the time, make them campaign based. It's sort of a global vs local concept (but only sort of).
I've set a personal rule of thumb to never make one of my areas bigger than any of the official campaign modules. That seems the smartest route unless you want to do a lot of testing.
Another benefit of campaigns that nobody seems to realize yet is how well it fits into group workflow! Several people can all be working on different "modules" at the same time, then just import the updates to a master campaign. Pretty cool.
Good luck all!
And more from flem1
Actually, here's a cool thing: campaign resources, AFAIK, aren't stored in savegames. So for a SP mod you could upload anything that might be changed in an "expansion" (i.e. adding another mod to the campaign) as a campaign dialog/script/whatnot, and then allow players to pick off right where their final save from the last mod left off, including revisiting old areas for new content as well as remembering what happened...
And from Max Gamer
There's only one way I managed to solve the unpacking module hang when starting a new campaign:
1) Close down your starting module in the toolset. For some odd reason the toolset is fussy about having it open when making it the starting module.
2) Make a new campaign in the campaign editor and type in the starter module name to be exactly the same as the filename without the .mod extension.
3) Hit the save campaign button.
4) Lastly add your starter module to the list of modules the campaign will use. This last step may not be essential to get the starter mod loading but will definitely be needed later on.
NWN2 uses a campaign system where there is a central umbrella that can connect a group of modules. It would seem that this is a great tool for builders who want to publish a series of modules.
This assumed you have a module that you are working on. I'm going to do this with my SKS series, so SKS01 will be my starting module.
Thanks to all who contributed to this thread in the official forums, which is where I learned how to do this. I've pulled some great excerpts in the page above this.
The Official Campaign uses the following conventions in regards to keeping track of modules and areas across the whole campaign. All of this seems to allow a convenient way of tracking where things are in the campaign.
Modules
Each module has a number in the tens of hundreds, followed by an underscore and the name of the module (eg. "1300_Old_Owl_Well.mod").
Areas
Each area in that module has a number within that hundred, followed by a short name of the area (eg. "1302_oldowlwell").
The display name for the area has the area id number in curly brackets preceding it (eg. "{1302}Old Owl Well").
The tag of the area seems to vary between the display name without the number and without spaces, but still capitalized (eg. "OldOwlWell") or the area id with the name (eg. "1304Bonegnasher"). Best practice for module builders would seem to be to always include the area id in the tag.
Scripts
Scripts specifically attached to this area, and this area only, are in the form of the area id and the script type (eg. "1302_enter").
Waypoints
Waypoints seem to use the area id as well. For instance, the initial entrance to the area 1304Bonegnasher is a waypoint with the tag "1304_enter." Note that this is the localized name for the waypoint, as well, which allows for easy reference.
Doors
Doors with transitions can also follow this convention in the form of:
plc_dr_ < id of the current area > _to_ < id of the target area >
For example, if you were setting up a transition between areas 1304 and 1305, they could be tagged as "plc_dr_1304_to_1305" and "plc_dr_1305_to_1304". Unlike waypoints, doors display their localized names to the players. This means that you will want to wrap your localized names in curly brackets.
Note: There's a version control option under the Options menu, but at this time I don't know how one would hook into it. This is a poor man's solution that is easy to use.
I like to save multiple version of my modules just in case something happens. It's also nice to be able to test out something crazy, and roll it back to a previous version if you have to.
A simple way to do this with modules in a campaign is choose the "Save As" option, but I'm always afraid I'm going to continue working on a saved version instead of the one in the campaign. Nothing is worse than testing your module than suddenly realizing you've just wasted 20 minutes in the wrong version. A better way I've found is to simply copy the module and change the name. This allows your named (without version numbers) module to be the latest and greatest that shows up in your campaign.
As an example, I use a system where the first number is the release status, and the second number is the version. The release status is "0" for development and "1" for released. If I need to make large changes, I increment it from there, so if I were to totally redo something I'd change it to a "2." So my first module is the name of the module + "_0_001" and every time I increment it I increase that last number by 1. The first released version is "_1_001." As I fix bugs and update for patches, I continue to increment the last number.
Usually, for me a version is a day's of work or a major change that I don't want to screw up. As I progress with more and more versions, I usually burn them off to a disk... or just delete them. ;)
Use whatever system you want, but some sort of version control is a great idea. So is backing up your files.
A good place to start learning about factions is the faction section of the lexicon:
http://www.nwnlexicon.com/compiled/categoryfunction.reputationfaction.html
Factions are controlled in the Factions window. To view this page in NWN2 go to View > Factions. Here you will see a table showing how factions feel about each other.
Each row shows how the faction listed to the left feels about the faction in each column. To adjust how a faction feels about each faction, change the values in a row.
Note that there is no Player row. This is because the Player faction cannot have feelings one way or another for other factions. Note also that, by default, all factions except for hostile are 100% friendly to Players. This is a change from NWN1 defaults.
Faction is measured on a scale from 0 to 100. Anything 10 or lower means the creatures of a faction are hostile to the creatures in the target faction. Anything 90 or above means the creatures of a faction are friendly to the creatures of the target faction.
Hostile creatures attack on sight. Friendly creatures can share buffs (such as bless and other area of effect spells), and will usually not be affected by area of effect attacks (such as fireballs). Note that area of affect damage will be determined by server and campaign settings.
You can check to see how one faction feels about another using GetReputation():
int GetReputation(
object oSource,
object oTarget
);
You can dynamically adjust how one faction feels about another using the following functions.
| AdjustFactionReputation | Adjusts all factions members reputation in relation to another faction. |
| AdjustReputation | Adjusts positively or negatively how a whole faction views a specific person. |
| AdjustReputationWithFaction | Adjusts reputation of each member in PC's party with NPC's faction |
From the lexicon page on Adjust Reputation:
One method of maximizing the versatility of the AdjustReputation function in conjunction with custom factions is to create an inaccesible area devoted to holding custom faction holders. Let's say your custom faction is titled "CLO" . You would give a creature the tag "CustomFactionHolderCLO", set "CLO" as the faction on the creature and place it in the custom faction holder bed. Keep it isolated from all other custom faction holders. Do not check the "plot" flag on your creature (or this won't work). You are using a creature rather than a placeable because AdjustReputation does not work with placeables. Now, for example, if you want the entire custom faction to turn hostile against your PC, you would script:
AdjustReputation(PC, GetObjectByTag("CustomFactionHolderCLO"), -100)
You can even create a custom faction holder for a standard faction so that you can easily use AdjustReputation with that standard faction.
Also, you may want to read this thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=569037&forum=114
In it, they are talking about the need to set UsesPersonalReactions to TRUE in the campaign settings. This requires you to use a campaign folder if you want to do any serious work with factions.
Create new a new faction by first going to View > Factions and openin the factions page.
One of the things that trip new builders up when dealing with factions is the "global" setting. If a faction is global, any faction adjustments for a creature will affect the entire faction.
So if you make a commoner go hostile, all creatures in the Commoner faction will go hostile across the whole module. Most builders find this annoying and most players are confused when this happens. The first response is that the module is broken.
Thanks to Parat for this post about factions in the Toolset forums, where he pointed out that the four standard factions cannot be changed from being global. This is a change from NWN1.
His solution is to "switch all commoners to a new commoner faction, which is not global, as it seems that you cannot deactivate the global setting for the existing factions?
While this may be a pain, it gives you more options for dealing with factions in general. It is obviously best to consider this at the start of developing your module.
Note that this will only affect you if you've scripted faction changes or if your pvp settings are set to allow players to hurt or otherwise anger Commoners, Defenders and Merchants.
Also, you may want to read this thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=569037&forum=114
In it, they are talking about the need to set UsePersonalReactions to TRUE in the campaign settings. This requires you to use a campaign folder if you want to do any serious work with factions.
There is an issue where SetIsTemporaryEnemy and AdjustReputation don't work unless the campaign-level variable UsesPersonalReputations is set to TRUE. Follow these steps to make these work:
Quote: by TanisGorion
ok i found how it works, i must1-open campaign editor
2-create a new campagin
3-insert the new module created
3-put personal reputation on TRUE
4-click save campaign
5-Click on use this campaign on the module selected.
6-close and reopen the module.
Also note that you probably want to create custom factions, because the four static factions cannot act as non-global factions.
See more about both of these issues here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=569037&forum=114
Here you will find some useful information regarding testing.
Here's a general thread discussing some good ways to make testing and debuging easier in a large module:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=572072&forum=113
The debugger, debug messages, debug creatures with conversations set up to help you test and the console are just a few of the tools you have at your disposal.
So far this section mainly deals with scripting. See the links below:
Getting the debug messages to print to the log or the screen can really help when trying to track down a problem in your module. Following up on some leads from jackyo123 and a few frustrating google searches, here's how I got it to work:
I'm not entirely sure this is needed or how this affects module, but it's also useful for using the ScriptDebuggerServer, so I have it on.
This one took me a while to find, partly because the documentation for DebugPostString() says you need to edit nwn.ini instead of nwnplayer.ini.
Add your PrettyDebug messages where you want them. You'll notice that you'll get a lot of messages from the regular scripts, as well. These are great when you trying to figure out why the script that seems to be saying it should do something, isn't doing what you want.
You can do this in the game or you can do this via the ini file.
In game:
In the nwnplayer.ini:
If you are sending debug information to your logs, they will appear at:
C:\Documents and Settings\Sean\Local Settings\Temp\NWN2\LOGS\nwclientLog1.txt
If you are sending debug information to the screen, they will appear up by the mini-map.
Thanks to jackyo123 for pointing this out. If you type in "logscriptrun" in the console while in debug mode, your log will fill up with all the scripts that are being called. It can be a bit much to wade through, but sometimes it's good to see if something was run.
The debug server is a way to walk through your scipts step by step. It creates a debug window that let's you see the path your script is taking, and is useful for figuring out why something is happening, or how something works. In programming, this is similar to breakpoints. Here's how I got it set up:
When it gets to where you placed the SpawnScriptDebugger(), the game will freeze and wait for you to tell the debugger to continue. Keep clicking "Step Into" until you have finished the script. At this point play will continue as normal.
There are some other options in the debug window that I didn't play with, so experiment.
| Cheat | Effect |
|---|---|
| dm_givegold # | Gives the desired amount of gold |
| dm_god | Invincibility |
| dm_unlockcamera | Allows you to use the camera with better scrolling and the such |
| givefeat # | Add the feat to your currently selected character (use #'s 2 through around 500) |
| giveitem [item tag] # | Gives active player item |
| givespell # | Gives a spell identified by it's id number to the character. |
| givexp # | Gives the desired amount of XP to your character. |
| givexp [-ve number] | Decreases your experience points by the value entered |
| irolltwenties | 20 in every statistic. |
| polymorph # | Turns your controlled character into a different creature. |
| removefeat # | Remove the feat corresponding to that number |
| resetlevels | Delevel you if your experience points is near to 0 |
| rs ga_alignment(-1,0) | to move one point towards evil |
| rs ga_alignment(-1,1) | to move one point towards Chaos |
| rs ga_alignment(1,0) | to move one point towards good |
| rs ga_alignment(1,1) | to move one point towards Law |
| rs ga_influence (x,y) | Raises influence level for that companion. |
| rs ga_party_limit(6) | Raises the amount of party members you may have at once to 6. Default is 3 in Act 1 and 4 in Acts 2 and 3. |
| rs ga_time_advance(Hours,Min,Sec,Milli) | replace Hours, Minutes, Seconds and Milliseconds with how much time you want to advance. |
| rs kr_influence | A simple influence editor, in the form of a dialogue. |
| rs kr_roster_edit | Opens a debug dialogue with an option to open the party roster to switch party members in and out at any time. (Use caution with other features there) |
| Set Appearance # | Makes your character have the appearance of the # in the res ref table of the 2da appearance file...*Note this is just appearance* |
| SetCHA # | Set charisma to given number. |
| SetCON # | Set constitution to given number. |
| SetDEX # | Set dexterity to given number. |
| SetINT # | Set intelligence to given number. |
| SetSTR # | Set strength to given number. |
| SetWIS # | Set wisdom to given number. |
| unpolymorph | Returns your controlled character to normal. |
| rs gr_dm | Spawns a Dungeon Master NPC who will allow you to spawn items, add journal entries, open stores, add/remove party members, and teleport. |
Tweak guides has a full list of debug commands posted on their fantastic NWN2 TweakGuide section.
The command console in Neverwinter Nights 2 allows users to apply various tweaks or changes to the game 'on the fly' while playing. To open and close the console, press the '~' key (or the key above TAB and/or below ESC) on your keyboard. To implement a console command, simply type its name along with any parameters required. Importantly, for many commands to work, you will need to first enable debug mode by entering the following into the console then pressing ENTER:
DebugMode 1
Note that console commands are case sensitive, so entering debugmode 1 for example won't work, it needs to be exactly as shown, i.e. DebugMode 1. The full list of console commands is provided further below in alphabetical order, however I provide full descriptions for the most useful commands first:
showfps - Toggles the frames per second (fps) display on/off.
trees - Toggles the rendering of all trees on/off. Useful for temporarily improving FPS in outdoor areas.
renderwater - Toggles the rendering of water on/off. Useful for temporary FPS boost in areas with water.
rain [0,1] - Toggles rain effects on if set to 1, off if set to 0.
daynight - Toggles the day/night cycle.
wireframe - Toggles wireframe mode on/off, useful for seeing the amount of detail actually being rendered/calculated in any area, even if it's not directly visible on screen.
gfxoptions - Brings up a special Graphics Options dialog box with a multitude of graphics-related settings you can change, including shadow intensity, toggling the day/night cycle, toggling rain on/off and altering the Bloom lighting parameters.
rs kr_roster_edit - Opens the NWN2 Companion Roster Editor, with a proper interface for adding, removing and altering various parameters for companions.
SetSTR, SetDEX, SetCON, SetINT, SetWIS, SetCHA [Value] - Right-click select a target, and use these commands to alter the relevant attribute to the value you wish. For example, right-click select your own character and use SetSTR 18 to give him/her 18 Strength.
givefeat [ID or all] - Select a character then use this command with the appropriate feat ID/name to give them that feat, or use 'all' to give them every feat.
giveitem [ID] [Number of items] - Select a character then use this command to give a particular item to the character, along with how many of that item to give. The list of ID tags for items can be found by launching the NWN2 Toolset, going to the Plugins menu item, selecting 'Universal Blueprint Changer', then selecting Items in the new dialog box and finding the appropriate name under the Tag column.
givespell [iD] - Select a character then use this command to give a particular spell to the character. The spell IDs can be found by launching the NWN2 Toolset, going to the View>2DA File menu option, then selecting the Spells file and using the number under the Name column.
givexp [value] - Select a character then use this command to give them the specified number of experience points.
dm_givegold [value] - Right-click select a character then use this command to give them the specified amount in gold pieces.
dm_god - Enables God mode, meaning you can't be killed.
The following are all the 181 console commands for Neverwinter Nights 2. Aside from DebugMode needing to be enabled for most of them to work, remember that many of them require you to either be the active character, or right-click select a particular character to apply a command successfully.
aabboxes
ambient
anim_blend
animation
animglod
animlod
anims
attachcamera
auditfeats
auditspells
automemorize
axes
base
blurradius
border
bugreport
c2
c3
camera_debug
camera_debug_full
camera_debug_los
capsules
clientstats
creatures
cutscene
cutscene_override
daynight
daynightscale
daytime
debugcam
DebugMode
debugtext
depthbatch
depthbatchindex
diffuse
DirShadowDepthBias
DirShadowSlopeScaleDepthBias
dm_givegold
dm_god
dm_jumptopoint
dropshadows
dumpmemory
dumptextures
emo_blend
EnableCombatDebugging
envshadows
exportchar
ffxbase
flicker_lights
fog
frecam
frusta
full
gfxoptions
givefeat
giveitem
givespell
givexp
glowintens
glows
hiliteintens
hilitethresh
hookpoints
irolltwenties
island
killgui
lights
loadgame
loc
loggameeffects
logrunscript
logserverai
lokkat
memstats
minimapsave
mipfilter
mousepick
mousepos
NetProfile
NetProfileReport
normals
obb_all
obb_cdoor
obb_sdoor
obb_water
obboxes
occlusion
partyadd
partyremove
paths
pbn
perception
physics
playbyname
PointShadowDepthBias
pointshadows
PointShadowSlopeScaleDepthBias
polymorph
portraitsave
possesscompanion
printactions
printcombatdata
printcreatures
printeffects
printfactiontable
printfeats
printglobalvars
printlevelstats
printlistenexpressions
printlocalvars
printperception
printrepository
printreputation
printscripts
profiling
rain
ReigidPointShadowZBias
removefeat
renderpc
renderwater
resetlevels
resetpackage
resetstats
resourcestats
RigidDirShadowZBias
rosteradd
rs
runscript
savedaynightstage
savegame
sceneintens
scriptprofiling
SelfDirShadowDepthBias
SelfDirShadowSlopeScaleDepthBias
SelfPointShadowDepthBias
SelfPointShadowSlopeScaleDepthBias
serverstats
SetCHA
SetCON
SetDEX
SetINT
setstatsdepth
SetSTR
SetWIS
shadowmap
shadows
showattacks
showcomments
showfps
showscriptcalls
showstats
showtriggerevents
skels
SkinDirShadowZBias
SkinPointShadowBias
sky
snow
softshadows
solid
specular
spheres
stats
surface
surfaceonly
takedamage
TerrainDirShadowDepthBias
TerrainDirShadowSlopeScaleDepthBias
TerrainDirShadowZBias
texfilter
textborder
tint
toggleserver
trees
unpolymorph
usebehavior
usescriptset
verifymemory
voiceover
wami
waterreflections
wireframe
Head over to the Tweak Guide for more information: http://www.tweakguides.com/NWN2_1.html
The world map plugin allows you to create an interactive world map that lets players jump from location to location in a campaign.
grinning_fool has posted this on the official message boards in the Toolset thread:
These instructions came from OE:
** The Campaign Editor **
Important thing is that you have opened the campaign editor from the plugins menu in the toolset at least once, created a campaign using “Add Campaign”, named it, saved it to the Campaigns directory, and clicked “set current module to use selected campaign” while working in the module in which you’d like the world map to appear. Then you have to save the module.
** Creating a Map **
1. Open Plugins->World Map Editor in the toolset.
2. Choose File->New in the World Map Editor.
3. In the properties field, set the world map image property to the .tga or .dds of your choice. This is the background map image that will be displayed.
4. For the time being, you need to manually input the height and width of this image. Our OC image is 647x647 pixels. That would be listed as Height = 647, Width = 647.
5. Name the world map in the WorldMapName property
6. Now add a hotspot. Hotspots are the locations that a player clicks on the map when choosing a travel destination. Choose “Add” in the toolbar above the editor window. Click anywhere you would like to add a hotspot. These can also be click-dragged later.
7. Click “select” in the toolbar above the editor. Click on a hotspot.
8. Each hotspot has two associated scripts, an action and a conditional. These will be written by the user. The conditional script returns TRUE if the hotspot should be shown and FALSE if it should be hidden on the map. If you’d always like a given hotspot to display, just use the script gc_true.
9. The Action script gets called if the player chooses that particular hotspot in-game and clicks the “travel” button. Typically this script will contain a jump command, such as JumpPartyToArea(), that will send the party to a waypoint in the destination area the player clicked on the world map. A good simple script to use for this is ga_jump_players.
10. Fill in the icon image fields in the properties pane. These are the images that will be displayed by default, when the mouse hovers over the hotspot icon, and when the player clicks the hotspot icon, respectively. .tga is an acceptable format, and I believe .dds files willl also work. We use .tgas in the OC.
11. Fill in the DisplayName property. This is the name of the hotspot that the user will see in-game along the right side of the world map screen
12. Fill in the height and width of the three image icons. (These are the fields that literally just say “height” and “width.”) Note all three icon images need to be the same size. Our OC uses 32x32 icon images.
13. Fill in the Name property. You’ll see the display name at left in the World Map editor. It also functions as the “Tag” parameter for the ShowWorldMap() command described below.
14. Repeat 6-14 at least once. Probably your world map should have at least 2 functioning hotspots since at a bare minimum you’d probably want to travel back and forth.
15. Save the world map to the campaign directory of the campaign associated with the module in which you’d like to use this world map. So for a campaign called Drizzt, you’d put it in the folder Campaigns\Drizzt. I believe this should work from both the MyDocs\NWN2\Campaigns directory and the NWN2\Game\Campaigns directory.
** Bringing up the World Map in-game **
This can be done at any time, through any script, using the ShowWorldMap() command. We usually call it from the OnClicked event of a transition trigger placed down in game. The first parameter is the world map name, minus the .wmp extension. So Faerun.wmp would be specified as “Faerun.” The second parameter is the player object that is going to have the world map displayed on his screen. The last parameter is the name of the hotspot (set in step 13 above) that the player is currently standing in. I believe it can be the empty string (“”) for “no origin,” but haven’t checked.
There's a lot more information in the original thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=511655&forum=1...
If anyone can point out the Obsidian Entertainment reference that grinning_fool used, it would be appreciated.
Sunjammer posted an excellent guide about world maps on nwvault. From his description on that page:
The NWN2 World Map System provides an exciting new interface for representing long distance travel in your campaign. However as it introduces several new concepts and requires some scripting knowledge the World Map System has proven to be rather difficult to master.
The World Map Guide is designed to help you integrate a fully function World Map into you campaign with the minimum of pain and suffering. When complete the World Map Guide will take you every step along the road from constructing your first World Map to overhauling the World Map GUI.
You can download it here:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=54
You may also want to check out Sunjammer's website.
Wilkin the Wanderer posted some questions and expressed his frustration with the world map system in the official forums, leading to some great pointers by other community members.
Check out the thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=542076&forum=1...
Jaks has posted the following tutorial on creating 3D maps.
For my campaign I really want to give a sense of the size and scope of the region in which the characters will participate. The world map feature of NWN2 will go a long way for providing that depth to our playing field. I've yet to hear details on what formats the world map can be drawn in but I do imagine a graphic format of some kind will be allowed to be imported into the module in some way. So to prepare I have begun to map out my region. Using a combination of the Forgotten Realms Atlas and my campaign book I started a new map for the region in my recently purchased CC3 (Campaign Cartographer 3) application. As usual CC is a bear to use. Trying to be detailed while at the same time trying to be stylish with it is difficult, despite the fact that CC3 has added a slew of new creative features. No matter how hard I try they all come out looking like CC maps, bland and dry. While perusing the recent release of pictures from GenCon I saw the pic for the world map here[link]. I like it, very stylish, almost 3D in a way. That got me thinking, Im a much better application user than I am an artist, could I instead find some 3D tools (like my recently acquired 3DSMax) to create a 3D scene for them to interact with? While looking around for a way to generate terrains (easily) in 3DSMax, I eventually gave up for some other apps that allow the building and rendering of heightfields[link to wikipedia]. This made alot of sense to me, seeing as how the toolset will be using Heightfields as well, it may benefit me to learn more about them, create a detailed and beautiful world map and at the same time find some tools that I may be able to be reused to create my areas as well. Below is the final product of my endeavors so far. As you can see it is a fully realized 3D terrain of the Durpar, Estagund and Var nations of the Shining South, all based around the Golden Waters bay.
The overland map for the Golden Waters area. Covers the nations of Estagund, Durpar and Var the Golden as well as showing the beginnings of the Raurin Desert. Notice how I was able to replicate the golden hue to the bay area as described in the official setting.
Applications Used: Leveller Demo, Terragen, Paint Shop Pro (substitute any graphics app)
So how did I do it? What applications did I use? Read on and I'll walk you through the process I took (without the heavy learning curve) to get to this point.
Check it out:
http://www.nwcitadel.com/blog/index.php?op=ViewArticle&articleId=16&blog...
And don't miss follow-ups:
Realistic World Map Tutorial Part 3 - Landmarks
http://www.nwcitadel.com/blog/index.php?op=ViewArticle&articleId=20&blog...
Realistic World Map Tutorial Part 3 - Mixing Terrains
http://www.nwcitadel.com/blog/index.php?op=ViewArticle&articleId=19&blog...
Realistic World Map Tutorial Part 2 - Terragen
http://www.nwcitadel.com/blog/index.php?op=ViewArticle&articleId=17&blog...
The following examples have been taken from the Official Campaign for reference when building a world map for your campaign. Note that these scripts are "kampaign" scripts and do not exist in modules by default.
The script ka_hotspot_click is the most basic world map script from the Official Campaign. It is meant to go in the "ActionScript" field for a hotspot in the world map plugin interface. At end of the script, notice that this calls SaveRosterLoadModule (located in ginc_companion). This function takes two parameters: the name of the module to load and the name of the waypoint the party will jump to. Here are the parameters for this script: string sModule - The file name of the module string sHotspot - The name of the hotspot clicked for the purposes of checking for a special case int nProbSpecial - Percentage chance for a special encounter int nProbRandom - Percentage chance for a random encounter string sDestinationOverride - The waypoint to go to intead of the default for a module string sCustomScript - Name of a custom script to execute There is a percent chance per transition that the party will have an encounter, but it only happens once. I think that the encounter area sends the party along to where they were going after they have completed the encounter. Note the use of GetIsObjectValid(oDest) to determine if the transition is in the current module and SinglePartyTransition( oPC, oDest ) to jump to the waypoint if it is in the current module.
// ka_hotspot_click
//
// Action script for when a hotspot is clicked on the worldmap. Determines the location to send
// the party to.
// BMA-OEI 4/12/06 - replaced LoadNewModule() with SaveRosterLoadModule()
#include "kinc_worldmap"
#include "ginc_debug"
#include "ginc_companions"
#include "ginc_transition"
void JumpParty(object oPartyMember, object oDestination)
{
object oThisArea = GetArea(oPartyMember);
object oJumper = GetFirstFactionMember(oPartyMember);
while (GetIsObjectValid(oJumper))
{
PrettyDebug("Jumping " + GetName(oJumper) + " to " + GetTag(oDestination));
AssignCommand(oJumper, JumpToObject(oDestination));
oJumper = GetNextFactionMember(oPartyMember);
}
}
void main(string sModule, string sHotspot, int nProbSpecial, int nProbRandom, string sDestinationOverride, string sCustomScript)
{
string sDestination;
object oDestination;
int nRoll;
object oPC = OBJECT_SELF;
if(!GetIsSinglePlayer())
{
if(GetWorldMapLocked())
{
SendMessageToPC(oPC, GetStringByStrRef(STRING_REF_MAP_LOCKED));
return;
}
else
{
SetWorldMapLocked();
}
}
//we only want one map encounter per player attempt to travel --
//prevents the player getting barraged by module cutscenes
//when he just wants to get to point B.
if(!GetGlobalInt("bPlayedEncounterOnThisClick"))
{
sDestination = GetModuleEncounter(sModule, sHotspot);
PrettyMessage(sHotspot + " clicked.");
if (sHotspot == "1302OldOwlWell")
{
if (GetGlobalInt("10_met_grobnar") != 1)
{
object oDest = GetObjectByTag("wp_1003_enter");
SetGlobalInt("10_met_grobnar", 1);
if (GetIsObjectValid(oDest))
{
ForceRestParty( oPC );
// BMA-OEI 6/14/06
SinglePartyTransition( oPC, oDest );
//JumpPartyToArea(oPC, oDest);
}
else
{
ForceRestParty( oPC );
//LoadNewModule("1000_Neverwinter_A1", "wp_1003_enter");
SaveRosterLoadModule("1800_Skymirror", "wp_1003_enter");
}
return;
}
}
if(sCustomScript != "")
{
ExecuteScript(sCustomScript, OBJECT_SELF);
}
if(sDestination == "")
{
nRoll = Random(100);
if(nRoll < nProbSpecial)
{
sDestination = GetSpecialEncounter(sModule, sHotspot);
}
else if(nRoll < nProbSpecial + nProbRandom)
{
sDestination = GetRandomEncounter(sModule, sHotspot);
}
}
}
if(sDestination == "")
{
SetGlobalInt("bPlayedEncounterOnThisClick",FALSE);
if(sDestinationOverride == "")
{
sDestination = GetDefaultDestination(sHotspot);
PrettyMessage("Sending to default destination " + sDestination);
}
else
{
sDestination = sDestinationOverride;
}
}
else //we're doing a special, module, or random encounter
{
SetGlobalInt("bPlayedEncounterOnThisClick",TRUE);
// unless our present encounter overrides the message with a global variable, we play it
// and return.
if(!GetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE))
{
ShowEncounterMessage(sDestination, sModule);
return;
}
SetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE, FALSE);
}
//this variable handles origin-dependent redirection, like changing the point of
//entry in the docks district depending on whether you came from blacklake
//or the merchant quarter. We reset it to its default here. It is set in the
//cliententer scripts of applicable areas.
SetGlobalInt("OriginArea",0);
oDestination = GetObjectByTag(sDestination);
if(GetIsObjectValid(oDestination))
{
ForceRestParty( oPC );
// BMA-OEI 6/14/06
SinglePartyTransition( oPC, oDestination );
//JumpPartyToArea(oPC, oDestination);
}
else
{
ForceRestParty( oPC );
PrettyDebug("Unable to find waypoint in current module. Initiating module transition.");
PrettyDebug("Loading module. Destination = " + sDestination);
//LoadNewModule(sModule, sDestination);
SaveRosterLoadModule(sModule, sDestination);
}
}
This is the heart of the world map functions. Not that all the includes and constants work for the OC only.
// kinc_worldmap
//
// Functions and constants for the NWN2 world map functionality
// EPF 12/8/05
#include "ginc_debug"
// the below files contain all the encounter logic
#include "kinc_module1000"
#include "kinc_module1100"
#include "kinc_module1200"
#include "kinc_module1300"
#include "kinc_module1600"
#include "kinc_module1700"
#include "kinc_module1800"
#include "kinc_module1900"
#include "kinc_module2000"
#include "kinc_module2100"
#include "kinc_module2200"
#include "kinc_module2300"
#include "kinc_module2400"
#include "kinc_module2600"
#include "kinc_module3000"
#include "kinc_module3100"
#include "kinc_module3400"
#include "kinc_module3500"
/////////////////////////
// FUNCTION DECLARATIONS
/////////////////////////
// ** hotspot functions **
//make a hotspot visible on the world map
void ShowHotspot(string sHotspot);
//make a hotspot invisible on the world map
void HideHotspot(string sHotspot);
//returns true if a hotspot is visible on the world map
int GetIsHotspotVisible(string sHotspot);
//make all hotspots with numbers between nLow and nHigh (inclusive) visible
void ShowHotspotRange(int nLow, int nHigh);
//make all hotspots with numbers between nLow and nHigh (inclusive) invisible
void HideHotspotRange(int nLow, int nHigh);
//run at the start of a module to associate a hotspot with its default waypoint
void SetupDefaultDestinations(int nAct = -1);
// ** conversion functions **
//hotspot number is the 4-digit area code for the area that the hotspot points to
string GetHotspotNameFromNumber(int nAreaNumber);
int GetHotspotNumberFromName(string sHotspot);
// ** encounter functions **
// returns the waypoint tag for a plot-based critpath encounter or the empty string if none is available
string GetModuleEncounter(string sModule, string sDestHotspot);
// returns the waypoint tag for a non-critpath encounter that isn't just random monsters or the empty string if none is available
string GetSpecialEncounter(string sModule, string sDestHotspot);
// returns the waypoint tag for a random monster encounter or the empty string if none is available
string GetRandomEncounter(string sModule, string sDestHotspot);
// show a "you have encountered a thing on the world map" message. Callback initiates the transition.
void ShowEncounterMessage(string sDestination, string sModule);
// ** world map locout functions **
// multiple PCs simultaneously clicking travel on the world map causes problems. We use a cooldown time to preven this.
void SetWorldMapLocked();
int GetWorldMapLocked();
/////////////////////////
// CONSTANT DECLARATIONS
/////////////////////////
// GENERAL //
// these are used with the Encounter message box
const int STRREF_ENCOUNTER_MESSAGE = 182995;
const string ENCOUNTER_MESSAGE_OVERRIDE = "00_bOverrideEncounterMessage";
const string LAST_DESTINATION = "00_sLastDestination";
const string LAST_MODULE = "00_sLastModule";
const string PC_CLICKER = "oLastWorldMapClicker"; //this is stored on the module not
// these are for locking the world map so only one user can use it at a time
const string WORLD_MAP_LOCKED = "00_bWorldMapLocked";
const string WORLD_MAP_LOCKER = "oWorldMapLocker";
const int STRING_REF_MAP_LOCKED = 183512;
const string WORLD_MAP_LOCKED_DAY = "00_nWorldMapLockDay";
const string WORLD_MAP_LOCKED_HOUR = "00_nWorldMapLockHour";
const string WORLD_MAP_LOCKED_MINUTE = "00_nWorldMapLockMinute";
const string WORLD_MAP_LOCKED_SECOND = "00_nWorldMapLockSecond";
const int WORLD_MAP_LOCK_COOLDOWN = 18; //seconds until we allow another click
const string WORLD_MAP_LOCK_INITIALIZED = "00_bWorldMapLockInit";
// ACT 1 HOTSPOTS HERE //
// 1000
const int HS_NWC_A1 = 1001;
// 1700 Merchant Quarter
const int HS_MQ = 1013;
// 1800 Skymirror and Grobnar
const int HS_GROBNAR = 1003;
const int HS_SKY = 1040;
// 1900 Back Alley
// 1100
const int HS_WEST_HARBOR = 1100;
const int HS_WH_RUINS = 1120;
// 1200
const int HS_WILLOW = 1202;
const int HS_LIZARD1 = 1206;
const int HS_FORTLOCKE = 1209;
const int HS_GRAVEYARD = 1211;
const int HS_BANDITCAMP = 1214;
const int HS_HIGHCLIFF = 1217;
const int HS_HC_SHANDRA = 1208;
const int HS_HC_RUINS = 1218;
const int HS_LIZARD2 = 1220;
const int HS_GLADE = 1223;
const int HS_WIDOW = 1225;
// 1300
const int HS_OOW_A1 = 1302;
const int HS_BG_APPROACH = 1303;
const int HS_IRONFIST = 1308;
const int HS_EG_APPROACH = 1314;
// 1600
const int HS_EMBER = 1616;
const int HS_GITHAPP = 1620;
const int HS_GITHCAVE = 1621;
const int HS_GC_SHANDRA = 1610;
// ACT 2 HOTSPOTS HERE //
//2000
const int HS_NWC_A2 = 2000;
const int HS_NWC_BLACKLAKE = 2024;
const int HS_NWC_MERCHANT = 2013;
//2100
const int HS_CK_COURT = 2100;
//2200
const int HS_PL_A2 = 2200;
const int HS_PL_EMBER = 2210;
const int HS_PL_DUSKWOOD = 2211;
//2300
const int HS_CKA_FARM = 2300;
const int HS_CKA_TUNNEL = 2340;
//2400
const int HS_IR_OGRUINS = 2410;
//2600
const int HS_AJ_EXTERIOR = 2600;
// ACT 3 HOTSPOTS HERE //
//3000
const int HS_PARTY = 0000;
const int HS_HIGHCLIFF_A3 = 3010;
const int HS_LIZARDMEN = 3014;
const int HS_IRONFIST_A3 = 3030;
const int HS_GALARDRYM = 3031;
const int HS_COT_MERE = 3040;
const int HS_REAVER_A = 3050;
const int HS_REAVER_B = 3051;
const int HS_NWC_MERCH = 3063;
const int HS_SH_FARM_A3 = 3070;
const int HS_PORT_LLAST = 3080;
const int HS_WENDER = 3081;
//3100
const int HS_CK_COURT_A3 = 2100;
const int HS_NOLALOTH = 3090;
/////////////////////////
// FUNCTION DEFINITONS
/////////////////////////
void ShowHotspot(string sHotspot)
{
SetGlobalInt("WM_bShow" + sHotspot, TRUE);
}
void HideHotspot(string sHotspot)
{
SetGlobalInt("WM_bShow" + sHotspot, FALSE);
}
int GetIsHotspotVisible(string sHotspot)
{
return GetGlobalInt("WM_bShow" + sHotspot);
}
void ShowHotspotRange(int nLow, int nHigh)
{
string sHotspot;
while(nLow <= nHigh)
{
sHotspot = GetHotspotNameFromNumber(nLow);
if(sHotspot != "")
{
ShowHotspot(sHotspot);
}
nLow++;
}
}
void HideHotspotRange(int nLow, int nHigh)
{
string sHotspot;
while(nLow <= nHigh)
{
sHotspot = GetHotspotNameFromNumber(nLow);
if(sHotspot != "")
{
HideHotspot(sHotspot);
}
nLow++;
}
}
void SetDefaultDestination(string sHotspot, string sDestWP)
{
SetGlobalString("WM_sDestWP" + sHotspot, sDestWP);
}
string GetDefaultDestination(string sHotspot)
{
return GetGlobalString("WM_sDestWP" + sHotspot);
}
void SetupDefaultDestinationsAct1()
{
// 1000 Neverwinter City Act 1
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_A1), "10_world_to_docks");
// 1700 Merchant Quarter
SetDefaultDestination(GetHotspotNameFromNumber(HS_MQ), "10_wp_docksi_to_merchant");
// 1800 Skymirror and Grobnar
SetDefaultDestination(GetHotspotNameFromNumber(HS_GROBNAR), "wp_1003_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_SKY), "10_wp_OL_to_skymirror");
// 1100 West Harbor
SetDefaultDestination(GetHotspotNameFromNumber(HS_WH_RUINS), "wp_OL_to_1120");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WEST_HARBOR), "tr_1100_from_1120");
// 1200 Highcliff
SetDefaultDestination(GetHotspotNameFromNumber(HS_WILLOW), "wp_OL_to_1202");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARD1), "wp_OL_to_1206");
SetDefaultDestination(GetHotspotNameFromNumber(HS_FORTLOCKE), "wp_OL_to_1209");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GRAVEYARD), "wp_OL_to_1211");
SetDefaultDestination(GetHotspotNameFromNumber(HS_BANDITCAMP), "wp_OL_to_1214");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HIGHCLIFF), "wp_OL_to_1217");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HC_RUINS), "wp_OL_to_1218");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARD2), "wp_OL_to_1220");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HC_SHANDRA), "12_wp_shandra_farm");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GLADE), "wp_1223_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WIDOW), "12_wp_widow");
// 1300 OOW Defaults
SetDefaultDestination(GetHotspotNameFromNumber(HS_OOW_A1), "NG_From_Tavern");
SetDefaultDestination(GetHotspotNameFromNumber(HS_BG_APPROACH), "1303_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IRONFIST), "13_Bonegnash2_To_Bugapproach");
SetDefaultDestination(GetHotspotNameFromNumber(HS_EG_APPROACH), "13_Casavir_To_EGApproach");
// 1600 Githyanki Caves Defaults
SetDefaultDestination(GetHotspotNameFromNumber(HS_GITHAPP), "wp_from_ambush");
SetDefaultDestination(GetHotspotNameFromNumber(HS_EMBER), "wp_from_patrol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GC_SHANDRA), "wp_shandra_farm");
}
void SetupDefaultDestinationsAct2()
{
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_A2),"10_wp_city_to_flagon");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_BLACKLAKE), "wp_from1013_to1024");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_MERCHANT), "10_wp_docksi_to_merchant");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CK_COURT ),"wp_CKA2_start");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_A2 ),"2200_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_EMBER ),"2210_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PL_DUSKWOOD ),"2211_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CKA_FARM ),"23_wp_pc_ritual_start");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CKA_TUNNEL), "23_wp_tunnel_ext");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IR_OGRUINS ),"2410_wp_entrance");
SetDefaultDestination(GetHotspotNameFromNumber(HS_AJ_EXTERIOR ),"2650_wp_pc");
}
void SetupDefaultDestinationsAct3()
{
SetDefaultDestination(GetHotspotNameFromNumber(HS_PARTY),"wp_30_overland_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_HIGHCLIFF_A3),"wp_3010_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_LIZARDMEN),"wp_3014_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_IRONFIST_A3),"wp_3030_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_GALARDRYM),"wp_3031_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_COT_MERE),"wp_3040_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_REAVER_A),"wp_3050_pc");
SetDefaultDestination(GetHotspotNameFromNumber(HS_REAVER_B),"wp_3050_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NWC_MERCH),"wp_3063_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_SH_FARM_A3),"wp_3070_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_PORT_LLAST),"wp_3080_from_ol");
SetDefaultDestination(GetHotspotNameFromNumber(HS_WENDER),"wp_3081_enter");
SetDefaultDestination(GetHotspotNameFromNumber(HS_CK_COURT_A3 ),"wp_21_enter_ck");
SetDefaultDestination(GetHotspotNameFromNumber(HS_NOLALOTH ),"wp_3090_from_ol");
}
void SetupDefaultDestinations(int nAct = -1)
{
switch(nAct)
{
case 1:
SetupDefaultDestinationsAct1();
break;
case 2:
SetupDefaultDestinationsAct2();
break;
case 3:
SetupDefaultDestinationsAct3();
break;
default:
SetupDefaultDestinationsAct1();
SetupDefaultDestinationsAct2();
SetupDefaultDestinationsAct3();
break;
}
}
string GetAct1HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
// 1000
case HS_NWC_A1 :
sName = "1001flagon";
break;
// 1700
case HS_MQ :
sName = "1013merchant";
break;
// 1800
case HS_GROBNAR :
sName = "1003grobnar";
break;
case HS_SKY :
sName = "1040sky";
break;
// 1100
case HS_WH_RUINS :
sName = "1120whruins";
break;
case HS_WEST_HARBOR :
sName = "1100harbor";
break;
// 1200
case HS_WILLOW :
sName = "1202willowinn";
break;
case HS_LIZARD1 :
sName = "1206Lizard1";
break;
case HS_FORTLOCKE :
sName = "1209FortLocke";
break;
case HS_GRAVEYARD :
sName = "1211Graveyard";
break;
case HS_BANDITCAMP :
sName = "1214BanditCamp";
break;
case HS_HIGHCLIFF :
sName = "1217Highcliff";
break;
case HS_HC_SHANDRA :
sName = "1208ShandraFarm";
break;
case HS_HC_RUINS :
sName = "1218HC_Castle";
break;
case HS_LIZARD2 :
sName = "1220Lizard2";
break;
case HS_GLADE :
sName = "1223glade";
break;
case HS_WIDOW :
sName = "1225widow";
break;
// 1300
case HS_OOW_A1 :
sName = "1302OldOwlWell";
break;
case HS_BG_APPROACH :
sName = "1303Bonegnasher";
break;
case HS_IRONFIST :
sName = "1308Ironfist";
break;
case HS_EG_APPROACH :
sName = "1314Eyegouger";
break;
// 1600
case HS_EMBER :
sName = "1616ember";
break;
case HS_GITHAPP :
sName = "1620approach";
break;
case HS_GC_SHANDRA :
sName = "1610shfarm";
break;
default:
sName = "";
break;
}
return sName;
}
string GetAct2HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
case HS_NWC_A2 :
sName = "2000Neverwinter_A2";
break;
case HS_NWC_MERCHANT :
sName = "2013MerchantQuarter";
break;
case HS_NWC_BLACKLAKE :
sName = "2024Blacklake";
break;
case HS_CK_COURT :
sName = "2100CrossroadKeep";
break;
case HS_PL_A2 :
sName = "2200PortLlast";
break;
case HS_PL_EMBER :
sName = "2210Ember";
break;
case HS_PL_DUSKWOOD :
sName = "2211Duskwood";
break;
case HS_CKA_FARM :
sName = "2300CKAdventure";
break;
case HS_CKA_TUNNEL :
sName = "2340TunnelExt";
break;
case HS_IR_OGRUINS :
sName = "2410OvergrownRuins";
break;
case HS_AJ_EXTERIOR :
sName = "2600AJExterior";
break;
default:
sName = "";
break;
}
return sName;
}
string GetAct3HotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
switch(nAreaNumber)
{
case HS_PARTY :
sName = "0000PartyCentral";
break;
case HS_HIGHCLIFF_A3 :
sName = "3010Highcliff";
break;
case HS_LIZARDMEN :
sName = "3014Lizardmen";
break;
case HS_IRONFIST_A3 :
sName = "3030Ironfist";
break;
case HS_GALARDRYM :
sName = "3031MtGalardrym";
break;
case HS_COT_MERE :
sName = "3040Mere";
break;
case HS_REAVER_A :
sName = "3050ReaverA";
break;
case HS_REAVER_B :
sName = "3051ReaverB";
break;
case HS_NWC_MERCH :
sName = "3063MerchantQuarter";
break;
case HS_SH_FARM_A3 :
sName = "3070ShandrasFarm";
break;
case HS_PORT_LLAST :
sName = "3080PortLlast";
break;
case HS_WENDER :
sName = "3081Wendersnaven";
break;
case HS_CK_COURT_A3 :
sName = "2100CrossroadKeep";
break;
case HS_NOLALOTH :
sName = "3090Nolaloth";
break;
default:
sName = "";
break;
}
return sName;
}
string GetHotspotNameFromNumber(int nAreaNumber)
{
string sName = "";
// Divide and conquer by act
if(nAreaNumber < 2000)
{
return GetAct1HotspotNameFromNumber(nAreaNumber);
}
else if (nAreaNumber < 3000)
{
return GetAct2HotspotNameFromNumber(nAreaNumber);
}
else
{
return GetAct3HotspotNameFromNumber(nAreaNumber);
}
}
int GetHotspotNumberFromName(string sAreaName)
{
return StringToInt(GetStringLeft(sAreaName, 4));
}
string GetModuleEncounter(string sModule, string sHotspot)
{
int nModule = StringToInt(GetStringLeft(sModule, 4));
PrettyMessage("nModule = " + IntToString(nModule));
SetGlobalString("KA_HOTSPOT_DEST_MODULE",sModule);
SetGlobalString("KA_HOTSPOT_DEST_HOTSPOT",sHotspot);
string sDestination;
switch(nModule)
{
case 1000:
sDestination = Get1000Encounter(sHotspot);
break;
case 1700:
sDestination = Get1700Encounter(sHotspot);
break;
case 1100:
sDestination = Get1100Encounter(sHotspot);
break;
case 1200:
sDestination = Get1200Encounter(sHotspot);
break;
case 1300:
sDestination = Get1300Encounter(sHotspot);
break;
case 1600:
sDestination = Get1600Encounter(sHotspot);
break;
case 2000:
sDestination = Get2000Encounter(sHotspot);
break;
case 2100:
sDestination = Get2100Encounter(sHotspot);
break;
case 2200:
sDestination = Get2200Encounter(sHotspot);
break;
case 2300:
sDestination = Get2300Encounter(sHotspot);
break;
case 2400:
sDestination = Get2400Encounter(sHotspot);
break;
case 2600:
sDestination = Get2600Encounter(sHotspot);
break;
case 3000:
sDestination = Get3000Encounter(sHotspot);
break;
case 3100:
sDestination = Get3100Encounter(sHotspot);
break;
case 3400:
sDestination = Get3400Encounter(sHotspot);
break;
case 3500:
sDestination = Get3500Encounter(sHotspot);
break;
default:
PrettyMessage("kinc_worldmap: invalid module string given to GetModuleEncounter()");
sDestination = "";
}
return sDestination;
}
string GetSpecialEncounter(string sModule, string sHotspot)
{
int nModule = StringToInt(GetStringLeft(sModule, 4));
string sDestination;
switch(nModule)
{
case 1000:
sDestination = Get1000SpecialEncounter(sHotspot);
break;
case 1700:
sDestination = Get1700SpecialEncounter(sHotspot);
break;
case 1100:
sDestination = Get1100SpecialEncounter(sHotspot);
break;
case 1200:
sDestination = Get1200SpecialEncounter(sHotspot);
break;
case 1300:
sDestination = Get1300SpecialEncounter(sHotspot);
break;
case 1600:
sDestination = Get1600SpecialEncounter(sHotspot);
break;
case 2000:
sDestination = Get2000SpecialEncounter(sHotspot);
break;
case 2100:
sDestination = Get2100SpecialEncounter(sHotspot);
break;
case 2200:
sDestination = Get2200SpecialEncounter(sHotspot);
break;
case 2300:
sDestination = Get2300SpecialEncounter(sHotspot);
break;
case 2400:
sDestination = Get2400SpecialEncounter(sHotspot);
break;
case 2600:
sDestination = Get2600SpecialEncounter(sHotspot);
break;
case 3000:
sDestination = Get3000SpecialEncounter(sHotspot);
break;
case 3100:
sDestination = Get3100SpecialEncounter(sHotspot);
break;
case 3400:
sDestination = Get3400SpecialEncounter(sHotspot);
break;
case 3500:
sDestination = Get3500SpecialEncounter(sHotspot);
break;
default:
PrettyError("kinc_worldmap: invalid module string given to GetModuleEncounter()");
sDestination = "";
}
return sDestination;
}
string GetRandomEncounter(string sModule, string sHotspot)
{
return "";
}
void ShowEncounterMessage(string sDestination, string sModule)
{
// so the callback knows where to jump the player to.
SetGlobalString(LAST_DESTINATION, sDestination);
SetGlobalString(LAST_MODULE, sModule);
SetLocalObject(GetModule(),PC_CLICKER, OBJECT_SELF);
SetCommandable(FALSE); //freeze player until the callback is clicked.
DisplayMessageBox(OBJECT_SELF, STRREF_ENCOUNTER_MESSAGE, "", "gui_map_transition");
}
void SetWorldMapLocked()
{
SetGlobalInt(WORLD_MAP_LOCKED_DAY, GetCalendarDay());
SetGlobalInt(WORLD_MAP_LOCKED_HOUR, GetTimeHour());
SetGlobalInt(WORLD_MAP_LOCKED_MINUTE, GetTimeMinute());
SetGlobalInt(WORLD_MAP_LOCKED_SECOND, GetTimeSecond());
SetGlobalInt(WORLD_MAP_LOCK_INITIALIZED, TRUE); //so we know the timer is initialized
PrettyMessage("World map locked at time " + IntToString(GetTimeHour()) + ":" + IntToString(GetTimeMinute()) + ":" + IntToString(GetTimeSecond()));
}
int TimeToSeconds(int nHour, int nMinute, int nSecond)
{
//for ease, we just convert the time into seconds -- 60 for 60 seconds in a minute, 3600 for number of seconds in an hour.
return nSecond + nMinute * 60 + nHour * 3600;
}
int GetWorldMapLocked()
{
if(GetIsSinglePlayer())
{
return FALSE;
}
if(!GetGlobalInt(WORLD_MAP_LOCK_INITIALIZED))
{
return FALSE;
}
int nLockedHour = GetGlobalInt(WORLD_MAP_LOCKED_HOUR);
int nLockedMinute = GetGlobalInt(WORLD_MAP_LOCKED_MINUTE);
int nLockedSecond = GetGlobalInt(WORLD_MAP_LOCKED_SECOND);
int nCurrentHour = GetTimeHour();
int nCurrentMinute = GetTimeMinute();
int nCurrentSecond = GetTimeSecond();
int nTotalLockedSeconds = TimeToSeconds(nLockedHour,nLockedMinute,nLockedSecond);
int nTargetTime = nTotalLockedSeconds + WORLD_MAP_LOCK_COOLDOWN; //10 sec cooldown
int nCurrentSeconds = TimeToSeconds(nCurrentHour,nCurrentMinute,nCurrentSecond);
// PrettyDebug("Target time for unlock = " + IntToString(nTargetTime));
// PrettyDebug("Current time in seconds = " + IntToString(nCurrentSeconds));
//same day
if(nTargetTime < nCurrentSeconds)
{
// PrettyDebug(IntToString(nCurrentSeconds - nTotalLockedSeconds) + " seconds passed since the last transition.");
return FALSE;
}
//we've rolled to the next calendar day
int nLockedDay = GetGlobalInt(WORLD_MAP_LOCKED_DAY);
int nCurrentDay = GetCalendarDay();
//!= is the check here because the day change could roll the month
//so going from month 1 day 28 to month 2 day 0 should still register as a day having passed.
if(nCurrentDay != nLockedDay && nCurrentSeconds > WORLD_MAP_LOCK_COOLDOWN)
{
return FALSE;
}
return TRUE;
}
If you paint down a new map transition, you'll notice that it has an onClick script of gtr_world_map_cl. You'll also noticed that this script doesn't actually exist in new modules. I think what happened is that this script started as a global, but at some point ended up with some code specific to the OC and was removed. Here the script, pulled from 1000_Neverwinder_A1.mod (The Docks).
// gtr_world_map_cl
//
// Transition to the world map
// EPF
// EPF 2/2/06 -- modifying to have a default map for each act if no other map is specified.
// EPF 3/24/06 -- this is now an OnClicked event
// BMA-OEI 6/24/06 -- Added gather party check
// BMA-OEI 8/11/06 -- Autosave before transition
// ChazM 8/21/06 -- updated constant CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION
// BMA-OEI 8/22/06 -- Replaced auto save w/ AttemptSinglePlayerAutoSave()
#include "ginc_debug"
#include "ginc_autosave"
#include "ginc_transition"
void main()
{
object oPC = GetClickingObject();
if ( GetIsPC( oPC ) == FALSE )
{
return;
}
string sMap = GetLocalString(OBJECT_SELF, "sMap");
string sOrigin = GetLocalString(OBJECT_SELF, "sOrigin");
if(sMap == "")
{
int nAct = GetGlobalInt("00_nAct");
switch(nAct)
{
case 1:
sMap = "Highcliff";
break;
case 2:
sMap = "Act 2";
break;
case 3:
sMap = "Act 3";
break;
default:
sMap = "Highcliff";
break;
}
}
// BMA-OEI 7/04/06 - Check if using remove dominated campaign flag
if ( GetGlobalInt(CAMPAIGN_SWITCH_REMOVE_DOMINATED_ON_TRANSITION) == TRUE )
{
int nRemoved = 0;
object oFM = GetFirstFactionMember( oPC, FALSE );
while ( GetIsObjectValid(oFM) == TRUE )
{
nRemoved = nRemoved + RemoveEffectsByType( oFM, EFFECT_TYPE_DOMINATED );
oFM = GetNextFactionMember( oPC, FALSE );
}
if ( nRemoved > 0 )
{
// Abort transition if dominated effect was found and removed
return;
}
}
// BMA-OEI 6/24/06
if ( GetGlobalInt( VAR_GLOBAL_GATHER_PARTY ) == 1 )
{
if ( IsPartyGathered( oPC ) == FALSE )
{
ReportPartyGather( oPC );
return;
}
}
// BMA-OEI 8/22/06 -- Autosave before transition
AttemptSinglePlayerAutoSave();
ShowWorldMap( sMap, oPC, sOrigin );
}
The script ka_hotspot_click_force gets called when the devs needed to make sure a certain NPC is along for the ride. Otherwise, it seems to work very similar to ka_hotspot_click.
I've removed a number of the plot checks to avoid spoilers.
// ka_hotspot_click_force
//
// Action script for when a hotspot is clicked on the worldmap. Determines the location to send
// the party to. This variant checks a global variable sCompVar, and if it's equal to nCheckValue,
// fires a message box instead of sending the player on. That message box is defined in this file
// as well, in DisplayForceCompanionMessage. The nMessage parameter chooses what message box to use.
// EPF 1/10/06
// TDE 1/31/06 - Added messages for Act 3, and scripting for if any one of a list of companions is required.
// EPF 1/31/06 - Using IsInParty instead of GetIsRosterMemberAvailable().
// TDE 3/23/06 - Fixed a bug in the companion list script
// EPF 3/29/06 -- uses JumpPartyToArea now
// BMA-OEI 4/12/06 - replaced LoadNewModule() with SaveRosterLoadModule()
// TDE 4/25/06 - Added support for excluding companions using "-" instead of ","
#include "kinc_worldmap"
#include "ginc_debug"
#include "ginc_companions"
#include "ginc_transition"
// Each case here needs to do the following, in this order:
// 1. Set a global string "00_sLastForcedCompanion" to be the roster name of the companion you're forcing to join.
// 2. Display a message box. Callback script is always gui_force_comp.
//
// TDE - Eric, if this becomes a permanent solution rather than temp, these strings will need to be
// added to dialog.tlk and called with SpeakStringByStrRef(nNum)
void DisplayForceCompanionMessage(int nMessage)
{
object oPC = OBJECT_SELF;
switch(nMessage)
{
case 1:
//You must have xin your party in order to travel to y. Proceed?
SetGlobalString("00_sLastForcedCompanion", "sand");
DisplayMessageBox(oPC,178912, "", "gui_force_comp","",TRUE,"SCREEN_MESSAGEBOX_DEFAULT",66,"",67);
break
// PLOT CHECKS REMOVED HERE!!!!
}
}
void main(string sModule, string sHotspot, int nProbSpecial, int nProbRandom, string sCompanion, string sCompVar, int nCheckValue, int nMessage)
{
string sDestination;
object oDestination;
int nRoll;
object oPC = OBJECT_SELF;
object oFirstPC = GetFirstPC();
object oFM;
if(!GetIsSinglePlayer())
{
if(GetWorldMapLocked())
{
SendMessageToPC(oPC, GetStringByStrRef(STRING_REF_MAP_LOCKED));
return;
}
else
{
SetWorldMapLocked();
}
}
//companion is supposed to be forced at this point
if ( GetGlobalInt(sCompVar) == nCheckValue )
{
// Added by TDE: to allow passing in a list such as "zhjaeve,ammon_jerro"
int iLen;
int iCommaPos = FindSubString( sCompanion, "," ); //find first comma
int iMinusPos = FindSubString( sCompanion, "-" ); //find first minus
int bDisplayMessage = TRUE; //Display the message if is a required companion is NOT in party or an excluded companion is in the party
if ( iCommaPos == -1 && iMinusPos == -1 )
{
//only checking for one companion
if(IsInParty(sCompanion))
{
bDisplayMessage = FALSE;
}
}
else
{
//Checking for multiple companions
//PrettyMessage("Checking for multiple companions");
string sNewString = sCompanion;
int iPosEnd;
int iPosStart;
int bExclude;
while ( iCommaPos != -1 || iMinusPos != -1 )
{
// PrettyDebug("Trying to find " + sNewString);
// determine length
iLen = GetStringLength(sNewString);
// get next comma or - position (returns -1 if not found)
iCommaPos = FindSubString(sNewString, "," );
iMinusPos = FindSubString(sNewString, "-" );
bExclude = FALSE;
if ( iCommaPos == -1 && iMinusPos == -1 )
{
iPosStart = 0;
iPosEnd = iLen;
}
else
{
if ( iMinusPos != -1 && (iCommaPos == -1 || iCommaPos > iMinusPos) )
{
PrettyDebug("Minus Pos = " + IntToString(iMinusPos));
bExclude = TRUE;
iPosStart = iMinusPos + 1; // Minus is the next in the sequence
if (iCommaPos > iMinusPos)
iPosEnd = iCommaPos - 1;
else iPosEnd = iLen;
}
else
{
// PrettyDebug("Comma Pos = " + IntToString(iCommaPos));
iPosStart = 0;
iPosEnd = iCommaPos; // Comma is the next in the sequence
}
}
// get companion name in string
string sTempString = GetSubString(sNewString, iPosStart, iPosEnd);
PrettyMessage("Getting " + sTempString);
// If this companion is in the party, set flag
if ( IsInParty(sTempString) )
{
//PrettyDebug(sTempString + " is in the party.");
if ( bExclude )
{
// PrettyDebug(sTempString + " should NOT be in the party.");
// Make sure they are selectable, so they can be removed from the party
SetIsRosterMemberSelectable(sTempString,TRUE);
bDisplayMessage = TRUE;
break;
}
else
{
PrettyDebug(sTempString + " should be in the party.");
bDisplayMessage = FALSE;
}
}
else PrettyDebug(sTempString + " is NOT in the party.");
// drop first tag and comma
if ( bExclude )
{
// PrettyDebug("Getting index between zero and" + IntToString(iMinusPos));
sNewString = GetSubString(sNewString, 0, iMinusPos);
}
else
{
// PrettyDebug("Getting index between " + IntToString(iPosEnd + 1) + " and " + IntToString(iLen));
sNewString = GetSubString(sNewString, iPosEnd + 1, iLen);
}
}
}
if( bDisplayMessage )
{
// PrettyDebug("Displaying Force Companion Message.");
DisplayForceCompanionMessage(nMessage);
return;
}
}
//we only want one map encounter per player attempt to travel --
//prevents the player getting barraged by module cutscenes
//when he just wants to get to point B.
if(!GetGlobalInt("bPlayedEncounterOnThisClick"))
{
sDestination = GetModuleEncounter(sModule, sHotspot);
if(sDestination == "")
{
nRoll = Random(100);
if(nRoll < nProbSpecial)
{
sDestination = GetSpecialEncounter(sModule, sHotspot);
}
else if(nRoll < nProbSpecial + nProbRandom)
{
sDestination = GetRandomEncounter(sModule, sHotspot);
}
}
}
if(sDestination == "")
{
SetGlobalInt("bPlayedEncounterOnThisClick",FALSE);
sDestination = GetDefaultDestination(sHotspot);
}
else //we're doing an encounter
{
SetGlobalInt("bPlayedEncounterOnThisClick",TRUE);
// unless our present encounter overrides the message with a global variable, we play it
// and return.
if(!GetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE))
{
ShowEncounterMessage(sDestination, sModule);
return;
}
SetGlobalInt(ENCOUNTER_MESSAGE_OVERRIDE, FALSE);
}
//this variable handles origin-dependent redirection, like changing the point of
//entry in the docks district depending on whether you came from blacklake
//or the merchant quarter. We reset it to its default here. It is set in the
//cliententer scripts of applicable areas.
SetGlobalInt("OriginArea",0);
oDestination = GetObjectByTag(sDestination);
if(GetIsObjectValid(oDestination))
{
ForceRestParty( oPC );
// BMA-OEI 6/14/06
SinglePartyTransition( oPC, oDestination );
//JumpPartyToArea(oPC, oDestination);
}
else
{
ForceRestParty( oPC );
PrettyDebug("Unable to find waypoint in current module. Initiating module transition.");
//LoadNewModule(sModule, sDestination);
SaveRosterLoadModule(sModule, sDestination);
}
}
This simple script can be placed on a conversation node to make a certain hotspot visible at some point in the plot.
// ka_hotspot_show
//
// Set as visible the hotspot with name sHotspot
#include "kinc_worldmap"
void main(string sHotspot)
{
ShowHotspot(sHotspot);
}
The following function checks to see if a hotspot has been found. It is meant to be placed on the ConditionalScript field of a world map.
// kc_hotspot_show
//
// global conditional script for world map hotspots. Returns TRUE if this hotspot should be displayed
// on the world map.
// EPF 12/8/05
#include "kinc_worldmap"
int StartingConditional(string sHotspot)
{
return GetIsHotspotVisible(sHotspot);
}
This script is an example of one of the encounter scripts that kinc_worldmap includes. It's worth noting that none of the OC module includes seem to do anything with the SpecialEncounter() function.
// kinc_module1000
//
// global include file for the module.
// EPF 12/8/05
// DBR 02/22/06 - if I havn't had the Sand intro, don't warp to the Sunken Flagon.
// DBR 08/03/06 - Initiate Olov ambush if player tries to leave Old Owl Well
#include "ginc_debug"
//const string OLOV_CS_FLAG = "13gb_olov_ambush";
//const string OLOV_CS_WP = "13_Cascamp_To_Olov";
string Get1000Encounter(string sDestHotspot)
{
int nOrigin = GetGlobalInt("OriginArea");
if (GetGlobalInt("13gb_olov_ambush") == 1) //Olov ambush should occur, don't leave Old Owl Well without Ambush occurring.
{
SetGlobalInt("13gb_olov_ambush",2);
PrettyMessage("Time for Olov to appear");
return "13_Cascamp_To_Olov";
}
if ((sDestHotspot=="1001flagon")&&(!GetGlobalInt("10_arrival_done")))
return "10_wp_cs_arrival_elstop";
//Sydney/Johcris scene
if (GetGlobalInt("00b_ReadyJocrisNataleCS")==1)
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
return "1025_wp_player";
}
if (sDestHotspot == "1001flagon" || sDestHotspot == "2000Neverwinter_A2")
{
PrettyMessage("Calling redirection script");
switch (nOrigin)
{
case 1013: //Player coming from Merchant Quarter
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
PrettyMessage("Entering from Merchant Quarter");
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_dockso";
}
break;
case 1600: // Player coming from Blacklake
case 2024:
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_dockso";
}
break;
case 1900: // Player coming from Back Alley
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_alley_to_docks1_st_exit";
}
break;
}
}
return "";
}
string Get1000SpecialEncounter(string sDestHotspot)
{
return "";
}
The world map include file for the Merchant Quarter shows how the origin variable is used to redirect to a different waypoint, based on which direction the party is coming from.
// kinc_module1700
//
// global include file for the module.
// JYL 04/17/06
// DBR 08/03/06 - Initiate Olov ambush if player tries to leave Old Owl Well
// DBR 08/16/06 - Changed waypoint override to a tag that is not also in the Docks
//const string OLOV_CS_FLAG = "13gb_olov_ambush";
//const string OLOV_CS_WP = "13_Cascamp_To_Olov";
string Get1700Encounter(string sDestHotspot)
{
int nOrigin = GetGlobalInt("OriginArea");
if (GetGlobalInt("13gb_olov_ambush") == 1) //Olov ambush should occur, don't leave Old Owl Well without Ambush occurring.
{
SetGlobalInt("13gb_olov_ambush",2);
//PrettyMessage("Time for Olov to appear");
return "13_Cascamp_To_Olov";
}
if (sDestHotspot=="1013merchant" || sDestHotspot=="2013MerchantQuarter")
{
switch (nOrigin)
{
case 0: // Player entering from outside city
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_oow_spawn";
}
break;
case 1000: // Player entering from Docks
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "10_wp_docksi_to_merchant";
}
break;
case 1600: // Player entering from Blacklake
case 2024:
{
SetGlobalInt("00_bOverrideEncounterMessage", TRUE);
SetGlobalInt("district_redirect", 1);
return "wp_from1024_to1013";
}
break;
}
}
return "";
}
string Get1700SpecialEncounter(string sDestHotspot)
{
return "";
}
Here are some basic links dealing with custom content.
Heed submitted a great walkthrough of how custom content should be installed and deployed in NWN2.
There are several ways to get custom content into the game, but not all are equal. Some have advantages over others and some can actually break your game install making you unable to patch your game. This document will describe various methods and highlight best practices.
Head over to the Vault and give it a read:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=56%3Cbr%3E
Hak files are the preferred way to distribute and use custom content.
Use the tools listed below to create hak files for NWN2.
tani's ERFinder is a great tool for creating hak files.
ERFinder is a small tool like the old hak-packer of nwn1. it can open/import/export/save any ERF-formatted files for nwn2, especially HAK, MOD, PWC and ERF itself. it uses OEIShared.dll from your nwn2-installation for all file-io (so it should be placed in your nwn2-folder) and needs .net 2.0 (like all nwn2 tools). it complies to the new ERF v1.1 format, thus allowing filenames to be 32 charakters long (hak-packer from nwn1 only supports v1.0, limiting filenames to 16 chars).
Get it from the vault:
http://nwvault.ign.com/View.php?view=NWN2Tools.Detail&id=9
Another tool for creating hak files is Ranmanu's Encapsulated Resource File Editor.
Edits, imports or exports data from Encapsulated Resource File files also known as ERF files (.HAK, .MOD, .ERF and .NWM).
Can be used for NWN1 (ERF version 1.0) as well as NWN2 (ERF version 1.1).
Get it from the vault:
http://nwvault.ign.com/View.php?view=NWN2Tools.Detail&id=30
A lot of people have been asking about this and I found a post here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=526432&forum=115
Maria Caliban has the following advice:
How To...
Add music to your toolset
There are three parts to this:
1. Placing and labeling your music
2. Editing dialog.tlk
3. Editing amdiantsounds.2da
EDITING YOUR MUSIC FILE
1) Find the folder entitled 'Music' in your My Documents/Neverwinter Nights 2 directory
2) Rename it to fit the naming convention, which is mod_mus_[title]. For instance, for my Company of Blasphemous Ravens mod, I'm using Brunete's Amicus Meus, which was originally Brunete-Amicus_Meus.mp3. I change it to mod_mus_amicus.bmu
3) Change the .mp3 file to a .bmu. I use this utility: Click Here
EDITING DIALOG.TLK
1) Open the dialog.tlk directory of Neverwinter Nights in your install directory with a tlk editor, I use this one: Click Here You'll need to update your browser to Java 5 to use it.
3) Scroll to the bottom and find the last number used, in my tlk file that's currently 184757 but yours may be different. Click on EDIT -> RESIZE TABLE.
4) Add one to whatever number appears and hit 'ok.' This should create a blank line at the bottom.
5) In this line, type in the name of song as you want it to appear in your toolset. I put in Amicus Menus
6) Hit save. (Make sure your toolset is closed when you do this) You can exit now but remember the number of the row you typed the title in.
EDITING YOUR AMBIANTMUSIC.2da
1) Open up your toolset, at the very top is a menu item called VIEW. Click on VIEW and then 2DA FILEs...
2) A list of your 2DA files pops. Scroll down to the one called AMBIANTMUSIC and open it.
3) Scroll down to the last, unused row.
4) In the first column, place the number from the dialog.tlk file that you created earlier. In the second, place the name of the music file without the extension. So I would enter and 184758 in the first column and mod_mus_amicus in the second.
5) Hit the 'Save' button for this file. (It's the one near the 'Add Row' button)
I'd like to add a note to the above post. It gives instructions on how to do two things one should rarely do. First, it tells you to alter the dialog.tlk in your install directory. This is typically a bad idea as most patches will overwrite this. For the majority of your modifications, you should copy your dialog.tlk into your My Documents/Neverwinter Nights directory and edit that one. Secondly, it's typically best to add a new row to the bottom of a .2da file instead of overwriting padding, however, I found that caused an error with amdiantmusic.2da.
>>
There's also been talk concerning the issues with importing voice over and music files in 1.02 that are supposed to be addressed as of 1.03.
Anduraga recently posted an excellent guide to creating a custom mountain placeable for use as a background element in a module on his blog. Here's a quick teaser:
We'll be creating a two-dimensional backdrop of a mountain for NWN2. This placeable will be no different than the Tree Cards in the toolset. Throughout this tutorial, I will be saying Photoshop and Max. If you're using a different program, then Once you have those programs (Photoshop and Max installed), we can finally begin making our textures.
Read the full post here:
http://thayviannights.blogspot.com/2008/12/from-image-to-nwn2-mountains....
It's a long post but a great read if you are interested in exploring custom placeables or need a specific placeable like this. Thanks Andurag!
WhoIsEvilTurnip posted this explanation of how to add custom tips to the loading screens:
I figured this out a day or two ago. There didn't seem to be anywhere it was actually written plainly.
First make a custom TLK. It should start with StrRef numbers 0, 1, 2, etc. Make it as long as you like with custom strings in each one.
Next, either make a new nwn2_tips.2da from scratch or copy the default one. If you copy the default one, go ahead and delete all of the lines except the first one.
I don't know why the nwn2_tips.2da has two "Row No." columns, but it works. Change the String for row 0 to reference 16777216, and set row 1 to reference 16777217, and so on, for as many random tips as you want.
Stick your custom TLK in your main NWN2 directory, the same one that the dialog.tlk is in.
You can put the nwn2_tips.2da in a custom hak if you like. I used TlkEdit to make my hak and put it in the My Documents\Neverwinter Nights 2\hak directory. Then go ahead and open your module in the toolset, and in the module properties, add your custom hak, and set your custom tlk as the one this module uses. Save the module, and try it out. When changing areas, your custom tips will appear! For some reason, when you are entering the module for the first time, the default tips show, but every area change after that brings up a custom tip from the custom tlk file.
Hope this helps. I looked for a long time for straightforward instructions for noobs on this subject before using trial and error to get it to work.
See the full thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=596848&forum=115
ladydesire posted a great tutorial on how she made custom prestige classes for Waterdeep.
Check it out here:
http://nwcitadel.com/forums/showthread.php?t=1138
Also, you may get some benefit in Kaedrin's post where he was exploring this issue:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=596753&forum=115
Montgomery Markland over at Rogue Dao Studios has posted some great information concerning custom terrain types:
I've been playing around with terrain textures, learning about how to properly format them with all of the assorted miscellany that's required.
I didn't know a .dds from a dvd until a week ago, so take all of this information as an exploratory process. Also, feel free to add your own comments.
Read the full post here:
http://www.roguedao.com/phpBB2/viewtopic.php?p=1428#1428
There is currently a stickied post the official forums concerning tlk files:
Current word from Obsidian programmer Erik Novales is:
Custom TLK support in the toolset will be in the next patch. In addition, specifying string refs as hex values in 2DAs will also work. This works similarly to how it did in NWN1 -- flipping the high bit on a string ref signifies usage of the module-specific TLK.
The talk tables are indeed UTF-8.
These are prefab files. Place them in your overrides directory.
Information for creating custom user dialogs.
BetterThanLife posted a tutorial concerning custom interface screens. This tutorial guides you through the creation of your own custom user interface screen for Neverwinter Nights 2. The screen is responsible for allowing the user to change their characters name. This is an illustrative example but you could easily extend it for a variety of other purposes. A sample module is included that allows you to ask a gnomish 'name changer' to change your name for you, this just shows one use of such a script and screen.
Download the zip file with the module showing how he did it from his site:
http://nwvault.ign.com/View.php?view=NWN2Tutorials.Detail&id=25
Rob McGinnis has been posting a series of posts in the Obsidian Entertainment NWN2 Developer Blog. There's a ton of information in there, and they seem to be posting one a week. Here is the link to the full category of posts:
http://forums.obsidianent.com/index.php?automodule=blog&blogid=2&&cat=7
And here are some of the topics included at the time of this writing, along with the basic introductions he included:
Here are some useful lists for builders. As the chapters of the Resources for Builders book get better defined, these will be moved into more appropriate locations.
McGavin has posted some complete lists of lootable items in the OC.
Complete List of Armors, Weapons and Miscelaneous Items that are lootables including unique and special edition weapons (NWN2 Campaign Plot Only Weapons are not included).
Head over to the vault to grab it.
http://nwvault.ign.com/View.php?view=NWN2Other.Detail&id=41
See the full list of patches for download at the vault:
http://nwvault.ign.com/View.php?view=NWN2Other.Detail&id=19
Shock Wolf has a good post about how to deal with the risk of updating here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=669984&forum=109
See the official 1.13 thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=643393&forum=1...
Neverwinter Nights 2 Game Update 1.13
Patch Notes - June 2, 2008
Bug Fixes
---------------
General
Multiplayer
DM Client
Toolset
Scripting
Custom Content
New Features
---------------
Multiplayer
Toolset
DM Client
Scripting
o ClearListBox
o AddListBoxRow
o RemoveListBoxRow
o ModifyListBoxRow
This patch came out November 5, 2008 in conjunction with SoZ being released.
I've seen two major issues that affect builders:
Area OnEnter scripts not working
Seems like some builders were having problems with Area OnEnter scripts not firing correctly after they updated the game. Seems the problem tends to be an incorrect use of OnEnter instead of OnClientEnter.
From Rob McGinnis in this thread about OnEnter and 1.21:
The way OnEnter works is that it fires off before the client is fully loaded into the game. This means that when you call the OnEnter function to fire off a conversation or other script, such as giving an item to a character, it may seem like the scripts/conversation is not working, when in fact it is. It is just happening BEFORE the client enters the game fully.
We will not be changing this behavior because there are benefits to this, but we are looking for ways to make it so modders do not need to change their mods.
Moving forward, we suggest you use OnClientEnter as it should handle these things properly.
Speaker triggers not firing correctly
There also seems to be an additional issue where some speaker triggers are not firing correctly. In the same thread Rob suggests making sure the speaker field is set on the dialogs as opposed to leaving this as the default blank for OWNER. I'm unsure if this is a solve for the problem.
See the official thread at:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=656414&forum=109
November 5, 2008
The following list contains the majority of fixes and features added in the 1.21 Game update. All spoilers for Storm of Zehir have been removed from this list.
Bug Fixes
General
* Item costs in the game should match the costs in the toolset.
* Party members that have wands with 0 charges will now attack and use spells normally.
* When dropping an item, characters will now use the appropriate "drop" animation.
* Fixed an issue with opening two bags at once. You will now only be able to open one bag.
*The tool tip for the Player Chat menu item will now say Player Chat.
* Fixed an issue that caused freecam (console command) to not work properly.
* Made several corrections to the Doomgude class description.
* Snake's Swiftness, Mass will now affect the entire party.
* Hellfire Shield should now play an appropriate sound effect when activated.
* Hellfire Blast should now play an appropriate sound when activated.
* The description of Hellfire Shield has been changed to appropriately reflect it is an Area of Effect shield.
* Weapon Focus: Warmace will now be available to all qualified characters.
* The ability score descriptions in character creation have been changed to be more informative and reflect changes to the game.
* Fixed an issue that was causing certain AI behavior feedback to be displayed, even after being deactivated.
* When the game is paused, a much more noticeable message is displayed.
* Aura of protection will no longer provide "No Stacking" feedback.
Toolset
* Item costs in the toolset should match the costs in game.
* Changing checkboxes with multiple objects selected will no longer cause the toolset to crash.
* Changing dropdown lists with multiple objects selected will no longer cause the toolset to crash.
* Fixed an issue where resizing a creature may not have resized the collision spheres.
* Fixed an issue where the creature cache was not working properly.
* Dropdowns generated from 2DAs will no longer start with the wrong row selected.
* Redesigned the fields associated with setting Tints to no longer be collapsed controls.
* Fixed an issue that caused light and sound spheres to not render at their proper size.
* Fixed an issue that caused ceiling tint changes to not show up in the toolset.
New Features
General
* Playable races now have a proper stealth animation.
* Added in the AI functionality from TonyK's AI.
* In a peer-to-peer multiplayer session, the hosting player may now unpause the game unconditionally.
Toolset
* Added properties associated with the overland map, including camera positioning and the flag to mark the area as an overland map.
* Added camera positioning functionality settings in the area properties to support overland maps created by the community.
* Added a flag in the area properties to set an area to be an overland map.
* Added Campaign flags for Unrestricting NPC level ups (Lets them chose any class at level up)
* Added Campaign flags for Conversation Distance limit override.
* Added Campaign flags to turn off party-control character swapping for dialogs on a global level.
* Added Campaign flags to enable Party Creation and setting what the size of the party should be.
* Added Campaign flags to toggle the new death system.
Scripting
* PlaySound() now takes an optional parameter: bPlayAs2D. This parameter will default to FALSE. Setting this parameter to TRUE will force the engine to play the sound you specified as a 2D sound rather than 3D Positional audio, regardless of what the engine would normally do before.
* BeginConversation() now has a parameter that allows you to block the character's 'Greeting' VO from playing.
* Added a script function SetScrollBarValue()
* Added a script function SetPause()
* Added a script function GetPause()
Additional items that will be int he patch, but are not listed int he patch notes are:
* Added in the authentication system to support the Adventure Pack system.
* Fixed issues that would cause the Arcane Scholar of Candlekeep to crash on transition if they had certain items or metamagic spells in the quickbar.
* Use Magic Device will no longer supersede a character's caster class or level, when that caster level is higher than the UMD skill.
* Fixed an issue that caused high level items to be used when a character had a single point in Use Magic Device.
Neverwinter Nights 2 Game Update 1.22 - December 19, 2008
I've attempted to compile links, known issues, patch notes and 2da changes from the forums.
Official forum thread is here: http://nwn2forums.bioware.com/forums/viewtopic.html?topic=669454&forum=1...
Available on the vault here: http://nwvault.ign.com/View.php?view=NWN2Other.Detail&id=212
What has been presented to me is that party damage was supposed to be based on the PvP setting for an area, regardless of the difficulty setting.
So, on hardcore difficulty, in most cases in NWN2 OC, your party will not take damage. However, on a PW, or in a module where areas are set to be full PvP, then the party will take damage.
If there is a bug in all this, it will probably wait to be fixed in 1.23
General
Toolset & Custom Content
Scripting
Multiplayer
Spells
Creature Abilities
Class Abilities
Neverwinter Nights 2 Campaign Fixes
SoZ Crafting
Changed 2da files
(Thanks Senalaya)
\2DA\classes.2da
\2DA\cls_feat_archer.2da
\2DA\cls_feat_arctr.2DA
\2DA\cls_feat_bard.2da
\2DA\cls_feat_cler.2da
\2DA\cls_feat_dradis.2da
\2DA\cls_feat_druid.2da
\2DA\cls_feat_eknight.2da
\2DA\cls_feat_harper.2da
\2DA\cls_feat_pal.2da
\2DA\cls_feat_palema.2da
\2DA\cls_feat_rang.2da
\2DA\cls_feat_sorc.2da
\2DA\cls_feat_wiz.2da
\2DA\cls_feat_wprst.2da
\2DA\des_crft_spells.2da
\2DA\feat.2da
\2DA\packages.2da
\2DA\polymorph.2da
\2DA\spells.2da
\2DA\vfx_persistent.2da
\2DA\visualeffects.2da
\2DA_X1\classes.2da
\2DA_X1\cls_feat_bard.2da
\2DA_X1\cls_feat_cler.2da
\2DA_X1\cls_feat_dradis.2da
\2DA_X1\cls_feat_druid.2da
\2DA_X1\cls_feat_eknight.2da
\2DA_X1\cls_feat_favored_soul.2da
\2DA_X1\cls_feat_harper.2da
\2DA_X1\cls_feat_pal.2da
\2DA_X1\cls_feat_palema.2da
\2DA_X1\cls_feat_rang.2da
\2DA_X1\cls_feat_sacredfist.2da
\2DA_X1\cls_feat_scholar.2da
\2DA_X1\cls_feat_sorc.2da
\2DA_X1\cls_feat_spiritshaman.2da
\2DA_X1\cls_feat_stormlord.2da
\2DA_X1\cls_feat_wprst.2da
\2DA_X1\feat.2da
\2DA_X1\iprp_spells.2da
\2DA_X1\packages.2da
\2DA_X1\polymorph.2da
\2DA_X1\spells.2da
\2DA_X1\vfx_persistent.2da
\2DA_X1\visualeffects.2da
\2DA_X2\classes.2da
\2DA_X2\cls_feat_doomguide.2da
\2DA_X2\des_crft_spells.2da
\2DA_X2\feat.2da
\2DA_X2\iprp_spells.2da
\2DA_X2\packages.2da
\2DA_X2\packftswash1.2da
\2DA_X2\race_feat_yuanti.2da
\2DA_X2\spells.2da
\2DA_X2\vfx_persistent.2da
\2DA_X2\visualeffects.2da
\GUI\chargen_appearance.xml
\GUI\chargen_appearancex1.xml
\GUI\chargen_appearancex2.xml
\GUI\noticewindow.xml
\GUI\playerlogin.xml
\GUI\playerloginx1.xml
\GUI\playerloginx2.xml
As BeyondthePale pointed out on nwvault, the 1.23 patch notes were posted in this forum thread by Rob McGinnis. Apparently the patch is coming very soon. Here are the notes:
Bard
Cleric
Druid
Neverwinter Nine
Paladin
Ranger
Blackguard
Doomguide
Hellfire Warlock
Warlock
Warpriest
ImmortalPob posted a list of crafting recipes in the OC form.
Because I had way too much time on my hands I have copied and pasted the descriptions from all of the crafting books, merged the, removed duplicates, and broken them down by type.
Check it out in the forum, and watch out for the 25+ pages of discussion afterwards:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=511016&forum=110
Sir Chet recently announced a few helpful resources over at thieves-guild.net that will be useful for NWN2: SoZ modules.
I just wanted to let everyone in on what we've done over at The Thieves Guild.
We finally finished our Walk-through for SoZ. I've also listed a few very helpful links to other great resources for OEI's second expansion to NWN2.
- Storm of Zehir Walk-Through
- Storm of Zehir Trading Guide
- Storm of Zehir Item Data Base
- Sorm of Zehir Crafting Guide
- Storm of Zehir Cohort Guide
I hope y'all find these guides useful.
Thanks SirChet!
Here you can find links to other sites concerning nwn2. If you have a link that you would like to be here, let me know using the contact form, or consider becoming a contributor.
Here are some great additional sites meant for builders.
http://www.nwn2toolset.dayjo.org/
Neverwinter Nights 2 Toolset Site
http://www.nwscript.com/
Neverwinter Nights 2 scripting tutorials
http://www.nwn2mods.com/
NWN2 Mods - prefabs and modules
http://www.nwnwiki.org/Neverwinter_Script_directory
Searchable collection of Neverwinter Nights Scripts.
http://www.nwcitadel.com/forums/forumdisplay.php?f=77
The Forgotten Realms Weave: "A project by SP/MP module designers to create a series of interconnectable modules that all support the major canon of the Forgotten Realms and allow cross module compatibility for players of the modules."
http://www.forgottenrealmsweave.org/wiki/tiki-index.php
The Forgotten Realms Weave wiki site
http://forgottenrealms.wikia.com/wiki/Main_Page
The Forgotten Realms wiki
http://en.wikipedia.org/wiki/Forgotten_Realms
Wikipedia entry on the Forgotten Realms
http://www.systemreferencedocuments.org/35/sovelior_sage/home.html
d20 System Reference Document v3.5: Open Source documentation of the 3.5 d20 rules. Contains a quick reference of all rules that end up in the PNP rule books.
Here are a number of links to forums with useful information concerning the Toolset.
http://nwn2forums.bioware.com/forums/viewforum.html?forum=113
The official NWN2 Toolset forum.
http://www.dladventures.net/vB/forumdisplay.php?f=87
The DLA Toolset Forum.
http://www.nwn2.pwp.blueyonder.co.uk/index.html
The Neverwinter Nights 2 Toolset Site forum.
http://www.roguedao.com/phpBB2/index.php
Rogue Dao Studios forum index
http://www.nwn2mods.com/forums/index.php?s=e6766d6b4858155332909a2862d8c...
NWN2 Mods forum
Here are a number of links concerning nwn2:
http://www.nwn2.com
The official site.
http://nwn2forums.bioware.com/forums/index.html
The nwn2 forums.
http://nwvault.ign.com
The vault.
http://nwn2.warcry.com/
NWN2 WarCry
http://nwn.stratics.com/
NWN2 Stratics
http://www.nwn2hq.com/
NWN2 news and updates
http://www.thieves-guild.net/
ThievesGuild.net
Here are some notable sites and blogs of nwn2 module authors.
http://adamandjamie.com/nwn2/
Adam Miller's Dark Water nwn2 site.
http://www.roguedao.com/PlanescapeTrilogy.html
Rogue Dao Studios' Planescape Trilogy
http://www.forgottenrealmsweave.org/wiki/tiki-index.php
The Forgotten Realms Weave wiki: "To allow builders to create coordinated campaigns set in the Forgotten Realms while retaining a high level of autonomy for their individual projects."
http://www.nwcitadel.com/blog/index.php?blogId=5
The Rusty Spike
Jaks design diary of sorts for his upcoming NWN2 DM led campaign.
Information on pulling it all together to create a great experience. Generally, this section is all about what makes a good game and how you can apply that to your NWN2 module.
anobody posted a complaint about the linear aspect of the NWN2 OC on the boards, which spawned an interesting debate about the linear aspects of Computer Role Playing Games.
BW022 made some good points with his post:
In the game all modules and pre-written campaigns have predetermined plot arcs. It simply isn't possible to write a module which covers every conceivable choose.
Imagine a DM writes a module for her group. About twelve hours consisting of a small town, a murder, and an assassin's complex. Maps, stat blocks, NPC descriptions, etc. The module starts out with a gnome coming into the bar and asking to speak with the PCs.
What do you think happens if the PCs say "We kill the gnome."? Well, maybe the DM scrambles a bit and lets the PCs find a note on the gnome talking about a murder. What then happens if the PCs say "We burn the note and leave the village."
Eventually the DM will say, "Fine. Nothing happens." She no longer has anything prepared. Perhaps the DM is good enough to ask what you plan on doing and then writing a specific adventure for you next week. Is the DM supposed to repeatedly spend dozens of hours on stuff you never do?
Kale Kross made an interesting counter point (which really highlights the importance of a DM):
The best DMs (and I've had the privilege of playing with several like this) don't run their sessions by planning out everything that could happen in a module. Rather, they construct their world and retain a clear picture of it and its inhabitents in their minds. They add some more major NPCs who will have their own agendas within the world as well. Naturally and fluidly, the world will continue to operate, even if the PCs decide to sit on their butts in the local tavern and do nothing. The DM creates a sort of "ecology" that is self-sustaining.
Actions the PCs take as well can have ripple effects within the world. The DM does not have to plan entire adventures or even sesssion. Only a continued sense of what is going on in the world and what will happen is necessary (with a few add-ons as the DM sees fit to throw into his/her world).
Using only these guidelines, the best DMs can do it all on the fly, allowing for true freeform roleplaying and stories that go in any direction.
In this sense, planning a whole quest isn't what's really required. Just planning of the world itself and the NPCs. It's the DM's choice to have an overarcing connection between sessions, but sometimes it's just fun to play for the journey of it.
While adventurers can be heros, not all adventurers are. And the reason we play is for the journey of it all anyway, not to "reach the end." After all, that's why DnD can be freeform and neverending in the first place, so long as the DM keeps it going.
Check out the full thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=526710&forum=1...
SCARLETTHORN posted this article about villains over at the Citadel. This first appeared in issue #23 of The Orc.
(Author unknown)
Speculative Fiction is a genre full of villains, from the truly evil ones like The Big Bad Wolf or Tolkein's Dark Lord, through the deranged ones like Misery's Annie Wilkes or Batman's Harley Quinn, to the tragic ones like Darth Vader or Magneto.
In this article I'll attempt to review a few points and tips that should be taken into consideration when creating such an antagonist for an ongoing campaign, an antagonist that would be a little more interesting than a bored dragon lying on his pile of gold, waiting for a group of hardy adventurers to come and turn him into an impressive collection of breast plates.
Like any other issue to be addressed in roleplaying, or at all, for that matter, before asking yourself "how?", you must first ask yourself "what?". Before we start designing our villain, we must first define what exactly we are attempting to create. Is he going to be an ongoing villain, forever lurking in the shadows of our campaign, or just a local antagonist for a single scenario? The villain's powers and motives, his interaction with the characters and the influence he'll have on them and the rest of the campaign will all derive from the answer to this simple question.
Once we've understood the role we want our villain to take, we can move on to creating the villain himself. The first question we should ask ourselves is why he's doing what he's doing, or in other words, what is his motive. Only a handful of villains are truly evil, and they can usually be found only in one of two genres - epic fantasy and horror. Most villains of most campaigns will be driven be much more earthly motives, such as an unquenchable thirst for riches or power (and a complete disregard to the welfare of those who stand in their way), revenge or even an ideological or political agenda which places the characters on the wrong side.
Another issue directly connected to the two previous ones is the relationship between the villain to the characters. Generally speaking, all villains can be roughly divided into two categories - those related to the characters' past, and those who aren't.
The first type of villain is the classic comic-book villain, the villain whose entire existence as a villain, or perhaps even whose entire existence is focused on the characters and on taking his vengeance on them and undoing their efforts. There's nothing wrong with creating such a villain, but in doing so, be careful to avoid the two classical mistakes of over-focusing on one character and of over-using the related villain motif. The first mistake is creating a villain opposing a single character, for a specific reason concerning that character alone, and not the other members of the group. It is possible to create such a villain, but be careful not to draw the campaign's focus to a certain character and not to steal the other characters' spotlight. The second mistake is self explanatory. There's nothing wrong with creating a villain who embarked on his evil career after a past confrontation with the characters, but if every kid who lost a tic-tac-toe game to one of the characters when he was in third grade will later return as a powerful villain - you're doing something wrong.
The other type of villain is the distant and faceless villain, existing only to serve his own cause. He isn't interested in the characters and does not actively seek to defeat or harm them - he simply wants to get them out of his way so they stop interfering in his plans. Or, as General Bison, a mediocre villain in a mediocre movie, once put it: "For you, the day Bison graced your village was the most important day of your life. But for me... it was Tuesday".
Another issue to address is the villain's powers. In order for our villain to be interesting, he must be able to defeat the characters. In other words, for a villain to be interesting, he must have some distinct advantage over the characters. But before you open your Dungeon Muster's Guide or Keeper's Companion and start searching it for interesting spells, formidable magic items and witty catch-phrases, stop and think. Any major villain will physically confront the characters only when all other options are exhausted, usually at the end of a lengthily campaign.
A real villain will lurk in the shadows and attempt to harm the characters in a variety of indirect methods - from various spells and curses that will make the character grow a rat's tail or develop an acute allergy to carrot juice to dirty politics that could cause the characters an insurmountable amount of trouble, from harassment by various law-enforcement agencies, through shop owners refusing to do business with the characters to closing down the characters' favorite tavern. Use your imagination and try to think of different and unique ways to empower your villain. Like any other subject in roleplaying games, there are no "rights" or "wrongs" here - even a close friendship with one of the characters' romantic interest could be considered as an advantage the villain has over that character.
One last issue to think about is the way you use the villain. If every scenario would start with the villain attempting to destroy the characters and would end with the characters defeating the villain, you're well on the way to a glorious yawn-fest. To ensure that your villain remains effective, he must be allowed to hurt the characters in a manner that is noticeable, but not fatal. Destroying valuable equipment, impairing abilities or abducting friends and allies are all great ways to remind the characters that the villain is still there, lurking in the shadows, waiting for an opportunity to strike. And of course, not every scenario needs to revolve around that villain. Even the most vicious villains are allowed to sit out a scenario or two, just to return to the hassle the characters at the least convenient time.
PIPBoy3000 posted something a while ago about how to create a self-extracting installer. He even posted the script he used for Pirate Cards.
Check it out:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=534921&forum=115
Download the NSIS here:
http://nsis.sourceforge.net/Download
Once you have it installed, copy his script to a txt file, change the extension to nsi, and update it to reference your project and files instead. Drag and drop it into the compiler window and it will do everything for you.
For those of you wanted to use Drow and looking to give your NPCs a bit more life, here are some resources:
Descent Into Darkness {Drow Campaign resources set in the Forgotten Realms}.
http://drowcampaign.roleplaynexus.com/
Eilistraee’s Drow Translator
http://www.eilistraee.com/chosen/language.php
The Realm's of Otara: Drow Names
http://www.angelfire.com/rpg2/vortexshadow/drownames.html
Most of these were posted in this language thread over at the Citadel:
http://nwcitadel.forgottenrealmsweave.org/showthread.php?t=634
Frank Perez, aka Elysius, recently posted four articles on how to write a story for NWN. You can see all four posts here:
To decide on our story premise (in other words, the general idea of what the story is about), Dirtywick, Anduraga, and I agreed to hold a brainstorming session. We gave ourselves twenty minutes to generate as many ideas as we could, during which no idea would be criticized. We allowed ourselves to suggest any idea, even those that were deliberately silly, in the hope that these may lead to better ones. Afterward, we voted on three of the ideas that we liked best. We then picked the idea that was chosen by most of us.
> Read more
I once wrote in this blog that regardless of a story’s length, I find it useful to structure its plot as a three-act outline. In fact, I have a specific formula for how the acts are written.
Act 1. The hero (that is, the PC) becomes aware of a problem to be resolved.
Act 2. The hero tries to attain an objective, to which a strong antagonist is opposed. At this point, the hero gets a complication that makes it more difficult to attain the objective.
Act 3. It seems that the hero has no chance to defeat the antagonist. Nevertheless, the hero can still prevail, but only with the help of one or more third parties that tip the balance in the hero's favor.
Entire books have been written on developing fictional characters, but I won’t even begin to touch the surface of this topic. Instead, I’ll provide only a couple of tips on character design. Don’t be misled by this seemingly meager offering, however. When applied properly, these tips will add considerable depth to any character concept.
Here’s my advice to beginning writers on how to create characters:
1. Write a back story for each significant character with a focus on the emotional problems that the character faces, how and why these emotional problems came to be, and what it would take for the character to resolve them.
2. Put your characters in situations that force them to confront their emotional problems in a way that will advance the story.
It helps to read a lot of fiction with an eye toward studying what the authors did that makes their work effective. Even if you aspire to write exclusively in the science fiction or fantasy genre, include a lot of mainstream fiction in your diet of books. My favorite novels include Bel Canto by Ann Patchett, Life of Pi by Yann Martel, Shella by Andrew Vachss, The Name of the Rose by Umberto Eco, The Last Samurai by Helen DeWitt (not to be confused with the movie of the same name), and Wuthering Heights by Emily Brontë (a surprisingly brutal novel from a 19th century country girl). In the fantasy and science fiction genre, my favorite books include Lord of the Rings by J.R.R. Tolkien and American Gods by Neil Gaiman. Doubtless, you’ll have your own list of favorite books. One can learn much by studying the works of the writers you admire.
Reading will not get aspiring writers anywhere unless they set themselves working on their own fiction. Don’t worry if your first stories are amateurish. Even the masters started with baby steps on their path to greatness. They got better with practice, and you can too. So dust off your favorite game toolset and start making the interactive stories that you’ve been wanting to write.
> Read more
Frank Perez is the creator of the NWN2 module "Battle of the Builds" and is currently working on his next module called "Faithless." See more at his blog: Faithless: The Making of an NWN2 Module.
Kulharin posted a good question in the official forums: On average, how long does it take to create an average module.
I was curious. I don't know a heck of a lot about the toolset beyond the basics... But I think I am interesting in creating an average sized module with a few areas. maybe a town or two, a few outdoor areas and a few dungeons ... With a bit of custom 2DA content and monsters .... How long roughly would it take to create a basicly average module.
Rob McGinnis was kind enough to give a quick answer based on their experiences:
For the layout of areas (art only, including props)
Exteriors:
Tiny - 3 days (24 hours)
Small - 5 days (40 hours)
Medium - 8 days (64 hours)
Large - 15 days (120 hours)
Interiors:
Tiny - 1 day (8 hours)
Small - 2 days (16 hours)
Medium - 4 days (32 hours)
Large - 6 days (48 hours)
For Design (writing the story, working out encounters), here are our numbers for Mask of The Betrayer.
Module A (The Barrow)
Avg. Gameplay (minutes) - 75
Implementation Time - 59 man days
# Tiny Areas - 0
# Small Areas - 3
# Medium Areas - 2
# Large Areas - 0
# Designers - 1
Module B (Mulsantir)
Avg. Gameplay (minutes) - 240
Implementation Time - 112 man days
# Tiny Areas - 6
# Small Areas - 4
# Medium Areas - 2
# Large Areas - 2
# Designers - 3
Here are the treasure guidelines as determined in this thread on the FRW forums:
http://nwcitadel.com/forums/showthread.php?t=853
Using this as a guideline will help create a balanced module. This is something I'm always looking for an can never find. Here it is reproduced for your convenience.
I posted the following in another thread since the question came up. These are some very loose guidelines (they could be a lot more detailed) for handing out magic items and wealth in modules. Feel free to discuss, since nothing is set in stone yet.
The two basic guidelines for handing out gold and items are to:
#1 Use the following table of magic weapon (and equivilant) per level
#2 Use a modified version of table 5--1 from the DMG to gauge how much wealth a player of a given level should have. This wealth number is the total value of all items and gold possessed by the player.
Phoenixus magic weapon guidelines
1-3rd = Masterwork weapons
4-6th = no better than +1 weapon/armor or equivilant
6th-9th = no better than +2 weapon/armor or equivilant
10-13th = no better than +3 weapons/armor or equivilant
14-17th = no better than +4 weapons/armor or equivilant
18+ = no better than +5 weapon/armor or equivilant
Note: Also remember that adding special abilities to weapons or armor beyond the enhancement bonus makes them equivilant to more powerful weapon. For a general idea, look at the base gold cost of a weapon with the next powerful enhancement bonus to the one you are handing out and make sure that your weapon or armor is not equal to or greater than that value.
For items like potions, scrolls, and wands, the general idea is only give the player access to items that can cast spells that an equivilant level spell caster could cast, with an occsional item that gives them temporary access to next level higher of spell (but with very limited charges). So, for example, if a first level cleric can only cast cure light wounds, you shouldn't be giving first level character of any class access to potions of cure moderate wounds, except possibly as an extremely rare one-time case.
DMG Table 5--1: Character Wealth By Level (modified to 1/2 vaule)
Level Gold
2nd 450
3rd 1,350
4th 2,700
5th 4,500
6th 6,500
7th 9,500
8th 13,500
9th 18,000
10th 24,500
11th 33,000
12th 44,000
13th 55,000
14th 75,000
15th 100,000
16th 130,000
17th 170,000
18th 220,000
19th 290,000
20th 380,000
Note: One thing to remember is that players will actually spend gold and resources during adventuring, so ou have to make sure they recieve enough gold per encounter to both cover this expenditure and also ensure they have the proper wealth level. One way to easily figure this out is to make the bulk of magic items they acquire expendable items like potions and scrolls, then ensure that they have to use those items to defeat encounters instead of saving them up and selling them.
Further down, Seryn made the following point:
I checked some of the OC merchants just out of curiousity, and the four or so that I looked at all had 100% markups with 40% markdowns, just as an fyi.
Styraxian pointed out this article by Kevin Carter that talks about the placement of NPC/Creatures and their relationship to the environment.
I have a great time playing through all sorts of game worlds—blasting randomly placed enemies, collecting scattered power-ups, earning points, gaining levels, all en route to some nefarious “main boss.” Usually the game world is very transparent though, meaning I can tell I’m in a game from the moment I pick up a controller to the moment I put it down again. As a player, I’m not exploring environments, I’m beating levels. I’m not fighting aliens, I’m defeating scripting.
This isn’t always the case. Sometimes I can forget I’m playing a game. Sometimes I feel I really am crawling through an air vent in the Black Mesa Facility. Sometimes I think I’m actually looking for the orc chieftain who has been leading the attacks on my village. Sometimes I—
Check out the full article Living Worlds: The Ecology of Game Design by clicking the link below:
http://www.gamasutra.com/features/20...arter_01.shtml
Coming up with interesting names that won't have your players rolling their eyes can be difficult. At least it is for me. Here are some good resources to keep you come coming up with another name like "Hard Goodman."
Don't ask my why, but I needed to come up with Kobold names and started looking around. It's an odd subject to do a google search for and the results are even stranger.
My favorite, and probably the most useful, was this:
The Kobold Namer
http://www.dungeonraiders.com/files/kamb/
Just keep hitting refresh for more names.
And speaking of niche needs, try this amusing conversation if you're bored:
http://www.treasuretables.org/2006/07/itty-bitty-niche-products-how-much...
Grey Starr and Dimitria Night-Starr over at Grey's Castle have several quick name generators based on articles in Dragon Magazine. Here's their description from the page:
"All generators here-in are created from the works of Owen KC Stephens from the pages of Dragon Magazine... They follow the exact rules and no changes or modifications were made to the information used."
At the time of this post, they have the following generators:
Random Male Dwarf Names (with Stronghold name)
Random Female Dwarf Names (with Stronghold name)
Random Dwarf Cusses (Swear like a Dwarf)
Visit the site here:
http://grey-starr.ca/index.html
Another good name generator I've found is Samuel Stoddar's Fantasy Name Generator. From his introduction:
One of the perks of creating fantasy stories -- whether by writing a story or game or by role-playing -- is you get to make up the names. Some people relish the task while others are frustrated by it. Some like it but can't seem to create names that are diverse enough. Fantasy Name Generator is a tool that can help you. It can generate an endless number of random names (of people, places, or anything) that would be suitable for use in a fantasy setting. It can generate names on its own, or you can tell it what kind of name you're looking for. Feel free to use this tool and any name that comes out of it (assuming it doesn't accidentally generate a legally protected trademark or something).
Check it out here:
http://www.rinkworks.com/namegen/
There's a fun suite of name generators over at Seventh Sanctum that has a lot of good resources.
Check it out here:
http://www.seventhsanctum.com/index-name.php
Here are some of the more useful generators listed:
Tavern Namer - Where's the next drink, next clue, or next bar fight coming from? Inns and tavers are such an integral part of the average fantasyscape that naming them can be difficult (or boring). Skewed towards fantasy-style names, obviously.
Angel/Demon Namer - A mix of latin and hebrew-sounds, this is a generator for Judeo-Christian style Angels and Demons (just don't expect them to actually translate to anything).
Dark Elf Namer - Not all elves are nice, after all.
Dwarf Namer - Need a name for your latest bearded burrowing buttkicker? Come here! Generates names, full names, and clan names.
Elf Namer - Names for both Tolkeinesque elves, Wild Elves, and general fantasy.
Evil Deity Generator - Dark gods, evil spirits, basphemous amorphous horrors - all in one easy package!
Goblin Namer - Need to name members of your Rampaging Hordes of Vaguely Humanoid Evil? This is the place to do it - from first names to last names.
Kaiju Name Generator - Generates names for your general Rampaging Giant Monster.
Tree-Being Namer - Call them Ents, Treants, Treemen, what you will, this generator gives you something specific to call individuals.
Vampire Namer - From "common" sounding names to outrageous fantasy, it's all you need to name your latest bloodsucker!
Ship Namer - Generates ship names in a variety of style - perfect for anything from a personal craft to a starship, just spend some time generating to get one that fits.
I found this handy table to help create drow names that seems to be parked on The Realm's of Otara Role Playing group's site.
http://www.angelfire.com/rpg2/vortexshadow/drownames.html
I'm not sure what the source is, but it's a quick handy way of throwing some names together.
Good puzzles give the players a chance to overcome obstacles on their own terms. They can be a nice change of pace, but they can also be a dead end that kills the action.
It's always good to review what has been done in the past, so this section contains examples, both good and bad, of puzzles in NWN1, NWN2, and similar games.
Mikar posted a FAQ for all puzzles in NWN1: Hordes of the Underdark. It's a great reference for when you are planning our your own puzzles in NWN2.
I made this FAQ because I'm seeing so many questions about the puzzles in HOTU in this forum. I hope that this FAQ will reduce the numbers of threads where people ask for advice on the puzzles.
Check it out:
http://nwn.bioware.com/forums/viewtopic.html?topic=319245&forum=82
I ran across a post by peterb over at Tea Leaves talking about the state of puzzles in video games.
In a video game context, I'm speaking of puzzles as being parts of games. The typical puzzle implementation is self-contained ("Solve this puzzle to advance past this door,") but that is a matter of habit, not a requirement. A puzzle can have a scope that encompasses all of the non-narrative parts of a game, or can even be intimately intertwined.
Further down her gives four general guidelines for making good puzzles in games:
1. The puzzle has to have a reason for existing.
2. The existence of the puzzle should move the narrative forward somehow, even if only by a little bit.
3. The more integrated into your game world the puzzle is, the better.
4. This one is debatable, but I believe that where possible, the puzzle should be to figure out what the puzzle is. That is, if you have to explain the rules to the player when they start, you've already lost. Ideally, once the player recognizes that they have encountered a puzzle, they should be able to solve it within moments of figuring out how to solve it.
Check it out:
http://www.tleaves.com/weblog/archives/000031.html
I came across a post by by peterb over at Tea Leaves where is examines physical locations in games how what makes for a consistent and engaging experience.
The question then is: if you are describing a space that doesn't signify a real-world space, how do you make the player care? How do you increase the power of the virtual space you've created so that, when she is done playing your game, the player thinks of it, on some level, as a "real" place? In this article, I'm going to discuss three techniques: familiarity and reuse, signifiers such as maps and text, and geometric and logical consistency.
Check it out:
http://www.tleaves.com/weblog/archives/000026.html
Arcane Fury posted a message in the modules forum asking what puts people off a mod. Here's a quick list:
Check out the full thread:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=536202&forum=111
If you are considering placing your module in Abeir-Toril, the fictional planet of The Forgotten Realms on which Faerûn is located, be sure to check out the wiki.
Abeir-Toril main entry:
http://en.wikipedia.org/wiki/Abeir-Toril
The Faerûn entry:
http://en.wikipedia.org/wiki/Faer%C3%BBn
While digging around looking for some ideas, I came across the Writing Your First Adventure article By Wolfgang Baur on the Wizards of the Coast site. It's a fun read and can help stretch your brain:
If you are ready to design your first RPG adventure, or learn how to improve the adventures you've already got, you've come to the right place. The "Adventure Builder" will cover all the bases, from hooks to background to traps and treasures.
This time out, we'll cover the foundation you need to build a great adventure. It's not the background, the stat blocks, or even the main villain. It's monster selection, and figuring out the size and style of the adventure.
Of particular note is the section on balancing encounters. While this it's a bit different from PnP, it's still worth a look.
While this breakdown is good advice, it's not complete. You'll want to be sure that your ... encounters include encounter variety by class as well as by EL. That is, make sure to include each of the following types of encounters, to give every class and every player a chance to shine.
1) Two Skill Encounters: These are creatures or obstacles that can be defeated by stealth or skill, such as guards, castle walls, cliffs, informants, or low-hp creatures that can fall to a single sneak attack.
2) [Eight] Pure Combats: You need some no-negotiation, straight-up combats that play to the fighter classes. Think orcs, wolves, ogres, giants -- or dragons. Consider tactics first here: ambushes, charge, bull-rush, something to make it more than just attack rolls and damage rolls.
3) Two Magical Challenges: Include two magical challenges that require a knock, a fireball, or whatever other strengths your arcane spellcasters have. They might be lore-based challenges, such as knowing the weaknesses of an extraplanar creature, or they might require the use of Concentration or Spellcraft to manipulate a magical object or unravel a mysterious warding.
4) One Divine Challenge: The divine caster in the party is more than just a medic, so give him or her something to do with at least one undead turning, Knowledge (Religion), or nature-knowledge encounter (if your divine caster is a druid).
5) One Puzzle or Trap: This could be as simple as finding the key to a tough lock, deciphering an ancient script, or finding a secret door with Search, but you should include traps and puzzles for your party to solve. If the party doesn't have a rogue in it, use Knowledge skill checks as a substitute.
6) Two Roleplaying Encounters: Social skills play an important part of the game too, and bards don't like to just sit and do their stuff in the background. Provide at least two roleplaying encounters that can be defeated by the right social skills, bribes, exchange of services, or clever conversation. Examples include a scholar with a clue that the party needs to bypass some defenses or wardings, or a devil who will ally with them against a common foe.
7) One Mook Encounter: This should be against foes of at least 2 CR less than the party, and ideally 3 or 4 less. Think kobolds, bandits, skeletons, wild animals, or any other group of many foes that play to Cleave and area-effect spells. It's fun to see heroes cutting a swath through hordes of foes.
8) One Polder: "Polder" is a Dutch word describing land reclaimed from the sea, but here it's a more general term. As described in detail in Dungeon 135, polders are safe havens for adventurers, places where the party can regain strength. Think Rivendell in Lord of the Rings. Your polder could be a xenophobic elven tree city, a magical rope that generates rope trick spells as a charged item, a bound archon who wards a treasure, or a dwarven merchant caravan. If the party wishes, they can heal up to full strength and level up.
9) One Bigger Fish: To keep the blood flowing, you should have one overwhelming encounter that the party can't handle without serious risk of a total party kill. This could turn into a roleplaying bit of Diplomacy, a chase, or a stealth challenge, depending on how the party handles it -- but they should see that not every encounter in every adventure should be fought.
10) Big Finish: A grand finale encounter with all the trimmings: villain, minions, and a room or terrain that provides interesting combat options.
Note that for the sake of increased combat in a CRPG, I've doubled the combats from four to eight. That's a total of 19 encounters, 11 of them involving combat. Whether that's enough for a full level of play is up to you as a builder, but at least Baur's list will get you thinking about balance.
Check out the article here:
http://www.wizards.com/default.asp?x=dnd/ab/20060728a
Check out the full Adventure Builder Archive here:
Sometimes I find that I need to reference some minor factiod about the 3.5 ruleset. Here are some links dealing with this.
If you need to get a rough idea on how much XP a party will get from an average encounter for a certain level, consider the Encounter Calculator v3.5.
http://www.geocities.com/edymnionii/EPLvsEL.html
It's a great way to figure out how many encounters a party might need. Remember to divide by 10 (assuming your experience slider for the module is set to 10%).
Credits: Tiera Starr, John Dells, arcady, Maladaar.
Thanks to dirtywick for pointing this out.
I know I forget this every few months, so here it is thanks to kevinodie and Jassper who posted this on the official forums:
(Current Level * NextLevel)*500 = XP needed for next level.
So level 1 = 0xp,
(level 1 * Level 2)*500 = (1*2)=2*500= 1000 xp for level 2
(level 2 * Level 3)*500 = (2*3)=6*500= 3000 xp for level 3
ect.
This can also be expressed:
N*(N-1)*500 is the minimum XP needed to get to Nth level.
Originally posted here:
http://nwn.bioware.com/forums/viewtopic.html?topic=470745&forum=46
The Dungeon Master Friendly Initiative has been helping build the multiplayer experience since the NWN1.
If you want to explore modules that are Dungeon Master friendly, start at the DMFI modules page:
http://nwvault.ign.com/View.php?view=NWN2ModulesEnglish.DMFM
If you're looking to be a DM for a session, check out the DM 101 module for NWN2:
http://nwvault.ign.com/View.php?view=NWN2ModulesEnglish.Detail&id=296
For more advanced topics on how to bring NPCs to life in a DM'ed module, see Carlo's article "Creating Believable and Memorable NPCs":
http://dmfi.slightlysilly.net/modules.php?name=Content&pa=showpage&pid=9
DM forum
http://nwn2forums.bioware.com/forums/viewforum.html?forum=117
Find others to play with at NWNConnections
http://www.neverwinterconnections.com/
Find others to play with at NWNCampaigns
http://nwncampaigns.com/
Builders who wish to make their modules Dungeon Master friendly can check out the following resources:
DMFI Developer Package
http://nwvault.ign.com/View.php?view=NWN2Scripts.Detail&id=38 Official
The Dungeon Master Friendly Initiative Guild:
http://nwn.bioware.com/guilds_registry/viewguild.html?gid=20
DMFI's Guide: Building a DM-Friendly Module
http://dmfi.slightlysilly.net/modules.php?name=Content&pa=showpage&pid=7
weby posted this list of known issues with the DM client as of patch 1.10.1116. It was posted on Monday, 22 October 2007.
Check the thread here:
http://nwn2forums.bioware.com/forums/viewtopic.html?topic=543448&forum=1...
Here are some basic questions I had when I first started. For now these are just listed in FAQ form, but will be organized into the book later:
How do you delete a blueprint (a creature, an item, etc.) after you have created it in the toolset?
Click on the item in the blueprints window and just press the DEL key on your keyboard. Make sure the properties windows is not open. otherwise nothing will happen. You can minimize the properties window by clicking on the little pin.
How do you stack placeables in the toolset?
Set the Stackable property to True on both of the placeables, then raise the placeable you want to stack on top using ALT-LeftMouse and press Spacebar to have it drop to the bottom placeable. If you don't enable stacking, objects just fall to the ground when hitting spacebar. (thanks Miserere from the forums) The "s" key is a hotkey for turning the stacking flag on. You can also set the height of the placeable and then lock the height. (thanks to knightsubzero from the forums)
What's the difference between scroll direction and scroll angle for water layers
It seems the scroll direction x,y is either off (zero), or on (greater than zero), and this defines what angle of zero is. So if scroll direction is y = -1, and x=0 then angle zero is north. you can then use the scroll angle to control direction, so 90 would be east, 180 would be south, etc. (thanks to evalcarcel from the forums)
How do people create those screenshots where you can see the whole area without that foggy limit?
Look under Vew > Options > Graphics for an entry under FarPlane. Change this to something higher (like 500 or 1000 instead of 100).
How do I create an area that is always night?
MuLmbo has a great answer in the Toolset Q&A thread:
# Fire up the editor.
# Open your module.
# Open the area you want to make eternally night.
# Highlight the area in the areas pane to see its properties.
# Under environment:
* Set the 'Day/Night Cycle' value to false.
* Set the 'Is Always Night?' value to true.
# Under Appearance:
* Expand '7' (Default)
* Customize the colour/lighting however you wish
Why won't my creatures equip or wear items.
Make sure the creature has the appropriate feats to wear the armor or use the weapon you want them to have. If not, they won't be able to equip the item in the game.
How do I use scripting when a PC first enters and leaves my module?
EPOlson has a good answer from this thread in the forums: http://nwn2forums.bioware.com/forums/viewtopic.html?topic=528278&forum=1...
When a PC logins in, the first events to fire are the OnAcquireItem and OnPlayerEquipItem events. At that point, the PC object exists and can have inventory. But it has no location.
Then OnClientEnter fires. The PC object is complete, but still has no location. (the lack of location is what causes most scripting issues)
Once the PC has been assigned an area, OnPCLoaded is called.
Then OnEnter and OnClientEnter are called for the area the PC ends up in. (OnEnter is called for all creatures entering an area - including NPC right after onModuleLoad, OnClientEnter is just for PCs)
A trigger would be called last.
Similarly, when the PC logs out OnClientLeave gets called. At that time, the client information is no longer associated with the object, just the physical characteristics. (which is another scripting issue) Then OnExit for the area is called (unless the PC logs out dead, then it is not called)
One more thing I noticed: when you transition to a new module in a campaign (StartNewModule and LoadNewModule), OnPCLoaded is not called. OnClientEnter is called, and so are the area's OnEnter and OnClientEnter. (onClientLeave is also not called)
OnPCLoaded is called when a PC logs out and back in.
Do heartbeats fire when the PC is not around?
Abby_ suggested in a post on the forums (http://nwn2forums.bioware.com/forums/viewtopic.html?topic=531431&forum=114) that there is an option on the creature properties called "Disable AI while hidden" that might cause heartbeats to fire when a PC is not around.