Skip to content

[SOLVED] Storing Local Variable On PC

RandomStrangerRandomStranger Member Posts: 10
edited August 2022 in Builders - Scripting
Hello,

I am trying to edit a module to change something to my liking. To do so I need to set some data and I decided to store in on the PC object. However I run into a problem: I use the exactly same method of storing the local variable as the module does - but the problem is that my new variable is only set up until the moment I leave the area where it was set. When I arrive to another area, it's lost (while the existing module variables are still fine).

Why could it be the case? Is there any variables registry where I need to add mine too? Are there any triggers / events that reset variables? (Just in case, I've checked the "Events" of the module and both areas in the toolset and there's nothing suspicious there).

Here's how I set it:
void main ()
{
    object me = GetFirstPC ();
    SetLocalInt (me, "MyAddedVar", 1);
    SendMessageToPC (me, "It was set to 1");
}

and I do so in the conversation tab of "Actions Taken". In the existing (subsequent) branches of the conversation there are some module existing variables set to some values via exactly the same method.

Now if I run the module:
  • I am able to see my added dialogue branch properly
  • If I go through this branch, I see "It was set to 1" in yellow in the log, as intended
  • If I try "dm_getvarint MyAddedVar" on the PC in console before going through the branch, I see "0" as a result
  • If I try "dm_getvarint MyAddedVar" on the PC in console after going through the branch, I see "1" as a result

Which hints that everything works here. The same method of console value retrieval is working of the module existing variables. But when I am moved to another area, "dm_getvarint MyAddedVar" starts to return me "0" and any branches conditional on it being "1" subsequently fail.

Any ideas why it is so? Any help is appreciated.
Post edited by RandomStranger on

Comments

  • TarotRedhandTarotRedhand Member Posts: 1,481
    As you want it to be available anywhere in the module, have you considered setting it on the module object?
    object oThisModule = GetModule();
    

    TR
  • RandomStrangerRandomStranger Member Posts: 10
    edited August 2022
    As you want it to be available anywhere in the module, have you considered setting it on the module object?
    object oThisModule = GetModule();
    

    TR


    Thanks. Well - I'm completely new to NWN scripts (not new to the whole scripting though). So I don't understand why the existing variables set by the module work and mine doesn't.

    Apart from that, the module has several chapters (part 1,2 etc) which are separate modules. If I understand it correctly, it stores variables in the PC object precisely because it wants to transfer them through those separate chapters. If I set a variable on the module - won't it be lost if I move between chapters (because they're technically different module files)?
  • ForSeriousForSerious Member Posts: 466
    I've never learned why, but storing variables on the player object has never worked as expected. Many servers resorted to storing variables on items that could not be removed from the player's inventory for this very reason.
  • RandomStrangerRandomStranger Member Posts: 10
    edited August 2022
    ForSerious wrote: »
    I've never learned why, but storing variables on the player object has never worked as expected. Many servers resorted to storing variables on items that could not be removed from the player's inventory for this very reason.

    Well, the module variables set on PC somehow work though. Adding an item seems to be an okay idea, but I struggle to make it lore-friendly (the item would need to be responsible for some decisions PC makes or events that unfold - but it's not the "journal" type)
  • KamirynKamiryn Member Posts: 74
    I would use GetPCSpeaker() instead of GetFirstPC() to get the PC doing the dialog but that shouldn't be the reason for your problems.
    Hello,

    But when I am moved to another area, "dm_getvarint MyAddedVar" starts to return me "0" and any branches conditional on it being "1" subsequently fail.

    Any ideas why it is so? Any help is appreciated.
    Seems that somewhere in your module MyAddedVar is reset to 0.

    Btw if you don't have many locals you can use dm_dumplocals instead of dm_getvarint MyAddedVar (quicker to type). You can even put that on the quickbar.


  • RandomStrangerRandomStranger Member Posts: 10
    edited August 2022
    Kamiryn wrote: »
    I would use GetPCSpeaker() instead of GetFirstPC() to get the PC doing the dialog but that shouldn't be the reason for your problems.
    Hello,

    But when I am moved to another area, "dm_getvarint MyAddedVar" starts to return me "0" and any branches conditional on it being "1" subsequently fail.

    Any ideas why it is so? Any help is appreciated.
    Seems that somewhere in your module MyAddedVar is reset to 0.

    Btw if you don't have many locals you can use dm_dumplocals instead of dm_getvarint MyAddedVar (quicker to type). You can even put that on the quickbar.


    Wow, that's incredibly useful! And helped me a lot! It turns out that if I check all variables after every step of the dialogue where I set it, I see that:
    • Right before the moment I set it, it does not exist (expected)
    • At the moment I set it (i.e. when the dialogue that triggers the script is displayed), it is set to 1 and I see it in the list of variables
    • But when I move just one step further into the dialogue and dump locals again .. it disappears.

    So.. it has nothing to do with changing areas (and that alone is a huge progress!), but rather - it only exists when I am on that specific dialogue entry and immediately disappears right after. Any ideas, why is that?

    Also, good idea that maybe I accidentally used a name that's also used somewhere else in the module but it's unlikely. I made it very obscure and added some random jibberish at the end of its name just to be sure it can't be the case.
  • KamirynKamiryn Member Posts: 74
    Then there has to be a script that sets the variable to 0. Setting a variable to 0 is the same as deleting it. To find that script search you scripts for MyAddedVar.
  • ProlericProleric Member Posts: 1,316
    Agreed.

    Setting local variables on PCs works exactly as expected - in a single player module, the variable persists until some script deletes it.

    Passing variables between modules or server sessions is more complicated, but that doesn't seem to be the issue here.
  • RandomStrangerRandomStranger Member Posts: 10
    edited August 2022
    Heh.. I feel embarrassed for bothering you folks with this. It's indeed the case. I was only checking the "Actions Taken" part where all was correct indeed. But somehow (I bet it was Ctrl+C / Ctrl+V) setting the variable to 0 got into the "Text Appears When" slot on one of the entries after. And - well, it worked as intended.

    So it works now, all the stuff is set and the branches I added later react on the variable as I'd expect.

    Now, there's another question - likely for another topic, but still:

    How to test dialogues / scripts etc on a large module? I mean it can be several hours of gameplay till I get to the point I want to test. Or worse - I need to take certain plot route to even get there. The thing is - as far as I observed, if I make a change to the module, I always need to start a new game with it in order to see changes. This severely complicates any testing of my changes.

    So - how does everybody does it? I doubt that when dozens of hours of playtime are involved, it really requires that for any change in the logic (which maybe faulty as my experience above shows - I was just lucky that my change is possible to test after 5-10 minutes of gameplay)
  • 4BOLTMAIN4BOLTMAIN Member Posts: 90
    Sounds like you are editing a single player or an original campaign module.

    If that is the case then just save game right before you enter the area with the custom changes and load that save for testing.
  • RandomStrangerRandomStranger Member Posts: 10
    edited August 2022
    4BOLTMAIN wrote: »
    Sounds like you are editing a single player or an original campaign module.

    If that is the case then just save game right before you enter the area with the custom changes and load that save for testing.

    It's not OC, but rather a big module (not my making, but I just want to do some local edits to add some stuff and alter some plot routes). I tried exactly what you said: save in the area before the one I'm going into - where the dialogue I've been working on is triggered. And it didn't work. Not only the scripts weren't triggered, even the new branches I added in the editor never showed up. It was all as if I'm playing the cached version of it.

    Also, the size of the save file is larger than the size of the module itself (the module is ~80Mb and the save is ~150Mb - holy cow! I found what's eating my disk space) - that hints me that the game just writes the whole module into it therefore confirming my guess about caching. If that's the case then I have no idea how to test anything, really.
  • ForSeriousForSerious Member Posts: 466
    For my testing, I add a temporary on enter script that sets up my player with the variables or items I need to test what I've been working on. I also set the start location to right by what I want to test.
    Once it's working to my satisfaction, I delete all that extra stuff and put the start location back to where it should be.
  • KamirynKamiryn Member Posts: 74
    edited August 2022
    ... I just want to do some local edits to add some stuff and alter some plot routes). I tried exactly what you said: save in the area before the one I'm going into - where the dialogue I've been working on is triggered. And it didn't work. Not only the scripts weren't triggered, even the new branches I added in the editor never showed up. It was all as if I'm playing the cached version of it.
    That's what the development folder is for: put your changed files there and then load your save. The files in the development folder will overwrite the files stored in your savegame.

    Here's an article about how NWN loads content:

    https://nwn.wiki/display/NWN1/Content+Load+Order
  • ProlericProleric Member Posts: 1,316
    edited August 2022
    It's helpful to distinguish between "unit testing" - checking that a change has worked in isolation - and "end to end testing" - playing through the entire module.

    For unit testing, in the toolset, use Paint Start Location (top right icon) to start at the desired point. Build > Test Module to launch at that point, by-passing character generation.

    Run a script in game to set up anything that would normally have happened earlier, for example
    • Level up
    • Add weapons / armour / keys / plot items
    • Add companions
    • Update journals

    You'll find that for a given test, you generally need to set very few things. For example, to test an advanced stage of a conversation, you may only need to set one journal to a higher state.

    However, since tests often need to be repeated, I find it convenient to have everything in one script, with the unwanted sections dummied out. For example,
    /* Set up Morbida finale 
      AddJournalQuestEntry("jt_empusa", 8, oPC);
      bhOpenDoor("dt_SandeniToMistgrave");
      SetLocked(GetObjectByTag("dt_MistgraveKitchen"), FALSE);
      ExecuteScript("bh_exit", GetObjectByTag("Morbida"));
    //*/
    

    is dummied out, but if you simply add // to the start of the comment, the whole section will be executed (the final //*/ enables that trick).

    When the entire module seems to be ready for release, remember to Paint Start Location at the original position, and do plenty of end-to-end testing, ideally for each race and class.
  • RandomStrangerRandomStranger Member Posts: 10
    Kamiryn wrote: »
    ... I just want to do some local edits to add some stuff and alter some plot routes). I tried exactly what you said: save in the area before the one I'm going into - where the dialogue I've been working on is triggered. And it didn't work. Not only the scripts weren't triggered, even the new branches I added in the editor never showed up. It was all as if I'm playing the cached version of it.
    That's what the development folder is for: put your changed files there and then load your save. The files in the development folder will overwrite the files stored in your savegame.

    Here's an article about how NWN loads content:

    https://nwn.wiki/display/NWN1/Content+Load+Order


    But the article says "all files except .mod" ? I.e. if I modify the module that I need to test, even if I place it into the development folder, it will be ignored? And the next in the load order is already a .sav file. If I didn't miss anything, placing .mod into the development folder will not help here?
    Proleric wrote: »

    For unit testing, in the toolset, use Paint Start Location (top right icon) to start at the desired point. Build > Test Module to launch at that point, by-passing character generation.

    ...

    that's not exactly what unit-tests are, but thanks, I got the idea on how to test certain things in the module. Will give it a go.
  • KamirynKamiryn Member Posts: 74
    But the article says "all files except .mod" ? I.e. if I modify the module that I need to test, even if I place it into the development folder, it will be ignored?
    You don't put the mod file there but only files you have changed. For example if you have made some changes to a script or a dialog you can copy these files from modules\temp0 to the development folder.
  • RandomStrangerRandomStranger Member Posts: 10
    Kamiryn wrote: »
    But the article says "all files except .mod" ? I.e. if I modify the module that I need to test, even if I place it into the development folder, it will be ignored?
    You don't put the mod file there but only files you have changed. For example if you have made some changes to a script or a dialog you can copy these files from modules\temp0 to the development folder.

    I didn't know I can do that, I mean - that it's possible to extract anything from the module. Where is that "temp0" folder? I don't have it in my "modules" location.
  • ForSeriousForSerious Member Posts: 466
    It gets created when you open a module in the toolset. I didn't know about the development folder until just now either. I probably still wont use it, but it could have been helpful in the past.
  • RandomStrangerRandomStranger Member Posts: 10
    ForSerious wrote: »
    It gets created when you open a module in the toolset. I didn't know about the development folder until just now either. I probably still wont use it, but it could have been helpful in the past.

    Ah, that's good to know - it exists there indeed when I open it. I will try!

    Thanks, everyone, this was most helpful!
  • MelkiorMelkior Member Posts: 204
    I commonly give all players in a multi-player module a "Bag of Holding" or equivalent which is undroppable. Any persistent variables can go on there. It's not difficult to find an excuse to give a player an undroppable item and they're not likely to complain if it's useful to them in some way.
Sign In or Register to comment.