Respawning Treasure/Henchmen lvl up


#1

Hello, does anyone know anything about treasure respawns? I’m trying to get my chests to generate loot again some time after they are opened. I’ve tried a couple different things but nothing really works. Are there any good tried and true treasure systems?
I guess while I’m here I could talk about some other things I’m trying to figure out. Ok, you know how when you get a henchmen, and it has to start out at lvl 1 or it won’t level up with you? So if your like lvl 10 and you pick up a lvl 1 henchmen, you have to hope it doesn’t die. (Because the encounters in my module are scaled to the total level of the party) And if it doesn’t die before you level up, then when you do lvl up, it levels up to you level, which is cool. But it would be nice to find a way to have the henchmen match your level when it joins you. That way your not running around fighting dragons with a lvl 1 rogue in the party lol. I’ve tried several things before. You know how you can make several different copies of a character from lvl 1 to 60 if you wish? And then create a custom encounter containing all those versions, so that when the encounter triggers, it spawns a creature matching the players level? Well, I thought that was cool, and I used that to spawn my henchmen. (Yes, my henchmen spawn in via encounters, so that if they die, you can go get them again, cause they respawn via the trigger.) But the only problem with that was, they wouldn’t level up with me unless they spawned in at lvl 1. So, if I could find a way to have them spawn in matching my lvl, and still level up, that would be awesome. But I really need a treasure respawn script most importantly lol. Any help is appreciated, thanks!


#2

Try taking a look at these for inspiration:

https://neverwintervault.org/project/nwn1/script/razares-treasure-spawn-system-rtss-nwn1-v100
https://neverwintervault.org/project/nwn1/script/simple-treasure-system
https://neverwintervault.org/project/nwn1/script/siliconscouts-treasure-spawn-system-18a

Encouragement: Post your treasure respawn code! If the lot of us take a look at it together, we may be able to spot what’s going wrong, and fix it. :smiley: It’ll pay off on the next scripting project; helps everyone involved learn how to spot and fix problems with code that isn’t working right.

One fairly comfy way to handle random loot generation is to set up hidden unique containers and toss lootable items into them, link the tag of the unique container to the lootable placeable (or creature), and then pick some of the items from that container at random.

You could place a timestamp to check whether enough time has passed that they should be generating loot again, when opening lootable placeables, or apply cutscene invisibility and cutscene ghost effects to them once they’ve been closed.



Are you still using the modified versions of the original campaign henchman hiring scripts? I think the HireHenchman() function from x0_i0_henchman should be levelling them up automatically, but the original campaign scripts use AddHenchman(), so they’re skipping the auto-levelup.

I’d try adding a LevelUpHenchman call to “NW_CH_JOIN”. Return to spawning level 1 henchmen, have them level up to the player’s level on hire.


#3

Hmm well I tried adding a LevelUpHenhmen call to the NW_CH_JOIN script like you suggested. I was surprised to see it compile with no errors, cause i’m still pretty new to scripting. But when I entered the game with my lvl 15 and recruited the henchmen, it was still just lvl 1. So I might play around with that some more and try to get it to work, idk what else to put in the script though lol. Umm well as far as the treasure goes, I’ve kinda toyed around with all 3 of those possibilities, but not to much avail. This is probably one of the trickiest things I’ve had to figure out so far lol. Really, the treasure that the chests generate is fine, it would be cool to modify it maybe, but all I really need is a script to make sure it generates again some time later.


#4

Helllllp lol


#5

Some ideas for things to try:

Thing 1 - Place debug messages.

Put a debug message into nw_ch_join, to make sure that nw_ch_join is even happening at all. Make the henchman SpeakString something - or, you could set up a custom debug message function that lets you turn all debug messages off again at once, like this:

    const int DEBUG_MSGS_ON = TRUE;

void DebugMsg(string sMsg)
{
    if (DEBUG_MSGS_ON)
        SendMessageToPC(GetFirstPC(), GetName(OBJECT_SELF)+" (DEBUG MSG) "+sMsg);
}

By switching constant integer DEBUG_MSGS_ON to FALSE, you’ll turn all debug messages off in one go, so you can comfortably place as many debug messages in your code as you like without having to edit them all back out again, in case you get back to editing it again later.

Thing 2 - Read the Lexicon entry for each new function you use.

Read the Lexicon pages, and check to make sure that you’re passing the right parameters. Functions may not do exactly what you think they do. I fall into this trap all the time. :thinking: Giving it a second glance, it looks like LevelUpHenchman would only ever level them up one level at a time either way, even when working as intended, so we may need a different function anyway. There’s a number of henchman level up functions in x0_i0_henchman that you could try, too.

Once you’ve confirmed that your henchmen are executing nw_ch_join (debug messages!), you could try including x0_i0_henchman into that script, and give LevelUpXP1Henchman() or LevelHenchmanUpTo() a shot.

Thing 3 - When in doubt, post the code.

For serious; if something’s going wrong in a script, don’t hesitate to post the script. It’s much faster than pure trial-and-error learning. There isn’t a single scripter in this entire place who never runs into “augh! my code isn’t working! WHY?!?!?”, no matter how experienced they are. It never, ever, stops. We’re all used to it.

If anybody ever tries to bite your head off over posting imperfect code (which is fairly unlikely), I’m pretty sure some other people will bite right back 'cuz discouraging learners for not knowing things and making people feel anxious for trying to fix problems are pretty much the least constructive things in the history of history.

You can use…

[code]
insert code here
[/code]

… tags to post shiny orderly formatted code.


Some loot respawn delay options, some of which may be more well-suited than others:

Placeable temporarily unusable.

OnClosed of the looted placeable:

    SetUseableFlag(OBJECT_SELF, FALSE);
    ActionWait(30.0);
    ActionDoCommand(SetUseableFlag(OBJECT_SELF, TRUE));
    ActionDoCommand(SetCommandable(TRUE));
    SetCommandable(FALSE);
Day-and-month check.

OnOpen of the looted placeable:

    int nCurrentDay      = GetCalendarDay();
    int nCurrentMonth    = GetCalendarMonth();
    int nLastDayOpened   = GetLocalInt(OBJECT_SELF, "LAST_OPENED_DAY");
    int nLastMonthOpened = GetLocalInt(OBJECT_SELF, "LAST_OPENED_MONTH");

    if (!(nLastDayOpened == nCurrentDay && nLastMonthOpened == nCurrentMonth))
        {
        SetLocalInt(OBJECT_SELF, "LAST_OPENED_DAY",   nCurrentDay);
        SetLocalInt(OBJECT_SELF, "LAST_OPENED_MONTH", nCurrentMonth);

        // Generate loot.
        }
Placeable temporarily invisible.

OnClosed of the looted placeable:

    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_CUTSCENE_INVISIBILITY), OBJECT_SELF, 30.0);
    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_SMOKE), GetLocation(OBJECT_SELF), 30.0);
Link to the timestamp thread.

Timestampery going on in this thread, from some time ago.

The idea of placing timestamps is to calculate current game time in seconds, then store current gametime + seconds until placeable should be generating loot again on the placeable, when opened. Next time it gets opened, compare the stored value against the current gametime. If the stored value is greater than or equal to the current gametime, you know that the set amount of time has passed and a loot respawn is due.

Or you could place a timestamp for the gametime second the event happened, and check whether x amount of time has passed since that timestamp has been set.