Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Neverwinter Nights: Enhanced Edition has been released! Visit to make an order. NWN:EE FAQ is available.
Soundtracks for BG:EE, SoD, BG2:EE, IWD:EE, PST:EE are now available in the Beamdog store.
Attention, new and old users! Please read the new rules of conduct for the forums, and we hope you enjoy your stay!

How do I update/patch my custom modules?

philbophilbo Member Posts: 16
I am having trouble finding out if there is a way you update my custom SP modules with patches/bugfixes/new content without players' current saves/progress becoming obsolete. Is this possible? Will save files only work with one particular version of a module?

Any help is much appreciated!


  • philbophilbo Member Posts: 16
    So I learned how to use HAKs to update scripts and conversation files.

    I'm wondering if there is a way to add new, un-accessed areas that can be reached via updated conversations? I tried this with a HAK, but the conversation wouldn't teleport the character from my saved game. If I reloaded the game with a new character it did teleport. So I'm assuming this method won't work for adding new areas.

    Is there any way to add a new area to a module without making a player's save obsolete?

  • SherincallSherincall Member Posts: 310
    A save file contains the entire copy of the module. You can delete the MOD and still be able to play your SAV.
    As such, any changes to the MOD will not be shown. You can actually rename the .sav to .mod and open it with the toolset to make a bugfix, but that only affects that one user.
    It's possible to make a patcher script that users could use to update their SAVs, if that's something you're interested in pursuing. But so far in the community it has been the case that module updates require starting a new game, people are used to it.

  • ProlericProleric Member Posts: 394
    @philbo As you've clearly figured out, you can't sensibly update an existing area or its contents via a hak, because the hak version will trump the saved version on load, meaning that everything the player achieved there is wiped out.

    If you think about it, even adding a new area in a hak leads to the same problem eventually, once the new area is saved.

    In addition to the area files in a module, there is a master list of areas in the module.ifo file, which you can't safely override. I imagine it's that which blocks jumps to areas added in a hak.

  • CalgacusCalgacus Member Posts: 82
    I added this to today's stream questions as I've been thinking about this lately too. I think there could be something added to EE to help.

  • FreshLemonBunFreshLemonBun Member Posts: 615
    What you could try doing for now is to store all of the relevant information to a module's progress and location of the character to an object in their inventory. Then if you make a change to your module you can suggest that they use the last character export as their character in the new module. When they enter the new module you can read all of the relevant data, set the progress states and position them back where they left.

  • dunahandunahan Member Posts: 66
    edited November 2018
    For adding areas with a update. You could create several dummy areas (2x2) with different tilesets and add created areas by hak later. Also you could do this with every area.
    Those dumnys will be overwritten by those in the haks :wink:

  • philbophilbo Member Posts: 16
    Thanks for the feedback everybody!

    @Proleric @Calgacus It would be very nice if EE had a feature for doing this easily.

    @FreshLemonBun This is the solution I think is most sensible for my goals with my SP module(s). Are there any tutorials to help me understand storing information for cross-module use?

    @dunahan This is a good idea, especially for adding a couple planned future areas.

  • FreshLemonBunFreshLemonBun Member Posts: 615
    You can try various things, campaign variables might work too. Export character strips variables off items in the inventory unless they're in a container.

    If you have a saving object like a book or crystal or whatever in a bag then use GetItemPossessedBy to grab the item and save, lets say GetLocation function of the PC to SetLocalLocation on the inventory item you got. On lets say, the module enter script, use GetItemPossedBy again and GetLocalLocation on the item to grab that location, use AssignCommand to PC with JumpToLocation to the location you saved.

    void main() { object oPC=GetEnteringObject(); object oSave = GetItemPossessedBy(oPC, "save"); if (GetIsObjectValid(oSave) == FALSE) { object oItem = CreateItemOnObject("save_bag", oPC); oSave = CreateItemOnObject("save", oItem); } location lTest = GetLocalLocation(oSave, "loc"); string sTest = GetLocalString(oSave, "test"); SendMessageToPC(oPC, sTest); AssignCommand(oPC, JumpToLocation(lTest)); }

    void main() { object oPC = GetLastPCRested(); location lTest = GetLocation(oPC); object oSave = GetItemPossessedBy(oPC, "save"); SetLocalLocation(oSave, "loc", lTest); SetLocalString(oSave, "test", "test jump"); }

    Lets say you put the first on the OnEnter event of the first area of the module with the starting location object. Then you put the second on I dunno your module's OnRest event. Then you'll save the location and the test message every time you click rest, and when you export your character it will keep that information which your updated module will also read in the same on enter event. You'll need to make a custom container (like a copy of bag of holding with no magic properties) and give it the resref of "save_bag". Your save item will be a custom gem or miscellaneous set to not drop or be sold with I think plot and stolen flags with "save" as the resref and tag.

    That's more or less the basics of how it used to be done.

    Alternatively you can probably try using the campaign database.

  • philbophilbo Member Posts: 16
    @FreshLemonBun This is very helpful! Thank you. I'm thinking I'll use this method to save plot related variables across modules.

    Here's my vision: Self contained quests are released semi-regularly as separate modules. Players can play them in no specific order. Players who choose to carry the same character from one quest/module to another will notice NPCs recall their exploits and/or have different quest options.

    Would an object like you described be the most efficient way to carry over a few plot variables?

  • FreshLemonBunFreshLemonBun Member Posts: 615
    You could probably use a campaign database but the local variable method is tied to the character file. There are different pros and cons to both, the character file can be copied simply from one computer to another, on the other hand the campaign database isn't necessarily tied to one character.

    You can use more or less the same method to read and write different variables like plot flags, just make sure you give them all a unique reference id. To have an NPC remember a character you probably want to look at the "text appears when" input box in the conversation editor and the "action taken" script input box too.

    So you can use "action taken" to call a script that sets the variable on your save object and then "text appears when" to branch or progress the dialogue by the script checking the variable and returning true if it's correct.

    You can also use custom tokens to save certain pieces of text that you want to insert, but you should really google and start reading through nwnlexicon at that point.

    I believe there are various complex script systems to handle conversations but a simple way could be when you edit the properties of your quest npc you can give them two variables, one is a string lets call it "quest_label" and the other is an int lets call it "quest_state" and now you can use this when you're setting your local variable.

    string sLabel = GetLocalString(oNPC, "quest_label"); int nState = GetLocalInt(oNPC, "quest_state"); SetLocalInt(oSave, sLabel, nState);

    So checking it would be the same but instead the third line would be GetLocalInt instead, and you would be checking that the value is the same as nState. Something along the lines of this.

    if (GetLocalInt(oSave, sLabel) == nState) return TRUE;

    For more complicated things you should probably test around a bit first, read the nwnlexicon, and maybe see if the neverwintervault has a scripted system you like.

Sign In or Register to comment.