Making Dungeons Persistent

For toolset tutorials as well as question and answers.
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Making Dungeons Persistent

Post by Teric neDhalir »

I have been pondering ways of making dungeon-type areas persistent, in that unlocked doors, triggered traps etc are remembered across server resets... Before I confuse myself by trying to script anything has anyone looked at this and found a solution they'd be willing to share? I'm guessing that the door state might not be too difficult to store, but how would you go about rendering a trap as "sprung"...?
Teric
User avatar
stormsong
Kobold Footpad
Posts: 34
Joined: Sun Jun 21, 2009 2:49 am
Location: Utah

Re: Making Dungeons Persistent

Post by stormsong »

I've got a system I wrote that handles making quests persistant. I'd been working on functions that would make scripts and variables persistant as well. It should be able to handle this without too many issues.

For example:

A door is to remain unlocked for 2 hours. The setting is applied as persistant and when the server crashes at 1:37 and reboots, as a part of the reboot, it pulls all the persistant values and resets them. The door now has :23 left on its wait.

The same type of thing would work for respawning a creature and treasure.

The trap has a state and script attached. when the server reboots, the state is checked in the script and if it shows as open, the script springs the trap.

Like I said, I have half the coding done already.
Stormsong Wyndsinger
  • Bard at large, Adventurer for hire,
    Scripter, Builder and Silly Person
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Re: Making Dungeons Persistent

Post by AcadiusLost »

The ACR has persistent variables available (stored on the central SQL DB). They are generally to be used in moderation, since they do cause tiny lag-spikes while they communicate across the internet, but work well in events like OnModuleLoad, specific OnAreaEnter() scripts, etc. There are various ways of streamlining their use to reinitialize an area after a module reset, which we can discuss next time you're on IRC; Wynna has done about as much of this as anyone for the Silverymoon University, which includes many scripted persistent elements.

In brief though, you want to:
#include "acr_db_persist_i"

and then use:
void ACR_SetPersistentInt(object oReferenceObject, string sVariableName, int nValue);
int ACR_GetPersistentInt(object oReferenceObject, string sVariableName);

Or the same for Strings, Floats, etc.

Note that this data is stored to the pwdata table in whatever SQL database the module is associated with in the xp_mysql.ini in /NWNx4 - locally the lag will be negligible, you will definitely notice it if you call lots of them at the same time while connected to sql.alandfaraway.org.
User avatar
Brokenbone
Chosen of Forumamus, God of Forums
Posts: 5771
Joined: Mon May 16, 2005 1:07 am
Location: London, Ontario, Canada

Re: Making Dungeons Persistent

Post by Brokenbone »

"Re-settable" dungeons as Stormsong mentioned, are well traveled ground.

"Dungeons that stay conquered forever", I've never heard of nor seen systems, possibly because that's not very exciting (unless a party means to take one over as their very own hideout). If it's just a little dungeon of 10 locked doors, 10 traps, 10 monsters, and you address them all in July 09, but you KEEP the dungeon map available from Aug 09 onward except with 0 doors, traps or monsters, again, why bother exploring it? Kind of anticlimactic.

I guess though a very, very tough killer dungeon where GENERATIONS of PCs slowly chip their way through corridor after corridor, suiciding on traps so that their grandchildren can walk down that hall safely, may be a place where this'd work out (so that across resets, these efforts wouldn't be erased).
ALFA NWN2 PCs: Rhaggot of the Bruised-Eye, and Bamshogbo
ALFA NWN1 PC: Jacobim Foxmantle
ALFA NWN1 Dead PC: Jon Shieldjack

DMA Staff
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Re: Making Dungeons Persistent

Post by AcadiusLost »

Ronan's original tech plans for NWN2-Sunset Vale involved "recolonizable" lairs/dungeons which would stay cleared up for a random interval (days to weeks to months) before being re-colonized by a perhaps-different mob, which would then build up it's numbers over time if not dealt with by adventurers. The concept was a nice one, making "clearing out a nest of monsters" a more meaningful and IC operation (as opposed to having to "game around" the fact that the same mob lair is restocked with the same creatures all the time).

The initial efforts towards this end remain on the ACR code SVN, but he didn't get very far into it. If it could be managed, it'd be a nice middle ground between the "nothing PCs do matters" and "nothing to do anymore cause it's all cleared out forever" extremes.
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Re: Making Dungeons Persistent

Post by Teric neDhalir »

@ Stormsong and AL; I'm at home with the ACR persistency variables and can probably figure out how to set something basic like LOCKED = Yes/No, I was just fishing to see if anyone had implemented anything I could steal.

@ Brokenbone. I understand what you're saying about clearing out an area so it then becomes boring, but I have a swathe of canon areas on my patch and it seems a bit daft to have one party overcome the dreaded McGuffin of Doom only to have it reappear the next day. What I'm trying to achieve is have small sub-levels that require certain levels of skill to get into (and one-shot guardians/rewards/traps etc) hanging off larger areas that have the normal "wandering monsters". I'm also trying to design stuff that would require long-term planning to get into, e.g. a rockfall that needs clearing out in an area prone to hostile passers-by (or, indeed, if you did a static-like task to dig out a bit at a time then you have the dilemma of trying to do it all or risking another group "breaking through" when you're not there.).
User avatar
Brokenbone
Chosen of Forumamus, God of Forums
Posts: 5771
Joined: Mon May 16, 2005 1:07 am
Location: London, Ontario, Canada

Re: Making Dungeons Persistent

Post by Brokenbone »

Not saying I don't like the idea, the rockpile example is exactly the kind of "chipping away" (literal and figurative) that it sounds like fits into your thinking. That is, progress in a presumably DMless dungeon, is not arbitrarily reset to zero by a server reset.

I guess reducing the problem to small chunks might make it manageable? For example, a boulder placeable, would there be any way to have some kind of persistent variable on it, where after people had interacted with it 500 times with I dunno, a chisel and hammer, it'd destroy itself? Starts at 500, after a few explorers give it a try, it's down to 450, next server reset it's still at 450, few more parties get it down to 300, etc.? I'm used to the idea of statics giving out variables of all sorts, which usually remain tied to PCs (so Joe PC can't do the same static twice, but it's still open to Fred PC even if he's travelling with Joe), or also used to the idea of at least persistent chests being linked to a database, just trying to get my head around something which is hopefully simple like a placeable.

Doors, traps and monsters all seem a little more complex than that, but maybe they aren't!
ALFA NWN2 PCs: Rhaggot of the Bruised-Eye, and Bamshogbo
ALFA NWN1 PC: Jacobim Foxmantle
ALFA NWN1 Dead PC: Jon Shieldjack

DMA Staff
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Re: Making Dungeons Persistent

Post by Teric neDhalir »

BB,
I hadn't thought of having individual rocks, more like one big placeable that stores a persistent variable that decrements each time some work is done on it until it hits zero at which point it disappears. As you can spawn placeables in you could add a script to the spawn point saying "don't spawn in if variable == 0". There's probably a big logical flaw in that somewhere that someone will point out :)

Same thing is possible with creatures, I think. Spawn in your bandit camp until the chief is killed and sets a switch turning the spawn off. I think it's a possible way of scattering little temporary un-DMed adventures about with the bonus that they are finite, not "farming" and someone gets "boasting points" for having rid the neighbourhood of this week's menace.
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Re: Making Dungeons Persistent

Post by AcadiusLost »

Two ways to dictate the behavior of ALFA spawn points (for placeables, creatures, etc):
acr_spawn_i wrote:// The script run before this waypoint spawns. OBJECT_SELF points to the
// waypoint when this script is executed. If the script calls the function
// ACR_DisallowSpawn(), the waypoint will not be spawned. If it calls
// ACR_ForceSpawn(), the waypoint will always be spawned, regardless of other
// settings. If it doesn't call anything, the spawn point's behavior will be the
// default.
const string _WP_IS_ACTIVE_SCRIPT = "ACR_SPAWN_IS_ACTIVE_SCRIPT";
I'm not sure if this has been tested, but by setting a local string "011_dungeon01_check" on each of the waypoints called "ACR_SPAWN_IS_ACTIVE_SCRIPT", you should be able to dictate the activity of all those spawn points collectively on the basis of a single "011_dungeon01_check.nss" script, which could check various persistent variables. If you go this route, I would strongly recommend caching the persistent variables on the area once they're retrieved, such that each spawn point isn't independently querying the remote SQL database every time.

Alternatively, a more laborious method (but one which has been tested) is just to manipulate the flag on a spawn point that enables/disables it individually.
acr_spawn_i wrote:// Indicates whether or not the spawn is disabled.
// Boolean value of 0 (no) or 1 (yes).
const string _WP_SPAWN_DISABLED = "ACR_SPAWN_IS_DISABLED";
So getting the spawn waypoint as an object, SetLocalInt(oWP, "ACR_SPAWN_IS_DISABLED", TRUE); will disable the spawn point until next mod reset, or until the variable is changed back to FALSE.
User avatar
Mulu
Mental Welfare Queen
Posts: 2065
Joined: Mon Dec 13, 2004 8:25 am

Re: Making Dungeons Persistent

Post by Mulu »

Spawn in your bandit camp until the chief is killed and sets a switch turning the spawn off. I think it's a possible way of scattering little temporary un-DMed adventures about with the bonus that they are finite, not "farming" and someone gets "boasting points" for having rid the neighbourhood of this week's menace.
It sounds to me like you're actually looking for randomness, not persistence, similar to the random dungeon generators on the vault, endless adventure type mods on the vault.

Talk to quest giver Militia Captain who says, "go to location X and rid of menace Y" which then triggers a spawned encounter Y in location X complete with a boss and treasure drop, preferably based on the level of the PC/party taking the quest, could even code to require a party of 3+ PC's presumably. Can only do once/RL week or whatever.

Endless balanced static content results. Set up a dozen locations with interesting features that only have encounters if set up with this spawn system, some above ground some below.
Neverwinter Connections Dungeon Master since 2002! :D
Click for the best roleplaying!

On NWVault by me:
X-INV, X-COM, War of the Worlds, Lantan University.
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Re: Making Dungeons Persistent

Post by Teric neDhalir »

AcadiusLost wrote:So getting the spawn waypoint as an object, SetLocalInt(oWP, "ACR_SPAWN_IS_DISABLED", TRUE); will disable the spawn point until next mod reset, or until the variable is changed back to FALSE.
AL,
The original thrust of this post was that if a door is unlocked, trap is sprung, mob is killed it's then off forever. As far as encounters go I do most of my spawning using an as_group_xx script so I would just propose to have an if statement at the head of the group script that spawns the objects, creatures or whatever if a persistent variable has not been set that prevents it. Sound reasonable?
Mulu wrote:It sounds to me like you're actually looking for randomness, not persistence, similar to the random dungeon generators on the vault, endless adventure type mods on the vault.
Um, no, I mean an encounter that stops happening once certain criteria have been met. I hadn't thought it through much further than that...
User avatar
AcadiusLost
Chosen of Forumamus, God of Forums
Posts: 5061
Joined: Tue Oct 19, 2004 8:38 am
Location: Montara, CA [GMT -8]
Contact:

Re: Making Dungeons Persistent

Post by AcadiusLost »

A conditional clause for the main body of the as_group script would lead to the same end result (as the spawnpoint wouldn't spawn any of it's creature "children"), but again, I would strongly recommend you cache the result of the first check locally, or else you're going to have a high-lag situation.

To clarify:

Code: Select all

void main (); {

object oArea = GetArea(OBJECT_SELF);
int nIsStatusCached = GetLocalInt(oArea, "IsCached");
object oMod = GetModule();

if (!nIsStatusCached) {
    int nPstate = ACR_GetPersistentInt(oMod, "Dungeon01_enabled");
    SetLocalInt(oArea, "SpawnPointShouldBeEnabled", nPstate);
    SetLocalInt(oArea, "IsCached", TRUE);
}

if (GetLocalInt(oArea, "SpawnPointShouldBeEnabled")) {

// spawn stuff in here

}
}
That way the persistent database only ever needs to be called once per area per module reset, rather than once per spawnpoint per activation of the area, which can get crazy if you have a lot of spawn points referencing the same as_group script. The Local reads and writes are instantaneous, being just operations in memory. If your spawn points are across multiple areas, you may want to cache the LocalInts on the module object rather than the area, the idea is just to have a common point of reference for all subsequent linked calls of "should we be firing?"

Clarifies things, I hope?
User avatar
stormsong
Kobold Footpad
Posts: 34
Joined: Sun Jun 21, 2009 2:49 am
Location: Utah

Re: Making Dungeons Persistent

Post by stormsong »

Hail Teric,

An interesting approach. I see some great things here! I hope I can make this clear.

When I thought of persistence, I thought of keeping a state over a restart, but in a repetitive way. Door locks, door is unlocked. But I think I understand what you are looking for. Say in an area there is a camp of Orcs. Someone drops by and wipes them. You want to have things hold off adding a new encounter for 2 days and then it should add a batch of bandits. Am I getting there?

I would be happy to help you as this is an area I had started coding on and expect to use extensively. I was thinking of it in the first way of persistence but thinking of the second way I see some great possibilities.

The approach I was using was designed to replace coding each individual persistent instance by moving to a set of functions that when fed the needed information, stored the persistent information, reset the state (and timer) on server reboot and fired the timer that would change the state at the appropriate time.

When a persistent impacting action is completed, the following things need to be done:
  • The state and delay need to be saved to the database
    If necessary a script can be called to affect the current state
    A script needs to fire the timer that will call a script that will change the state after a delay
When the server is restarted then the following occur:
  • A master script is called when the server resets which then checks for records in the DB indicating outstanding persistent actions, pulls them and processes them.
    In this case it checks for the balance of time remaining and fires klg_Persistent_Function that changes the state on the updated timing. When the time is reached the state is changed.
This system would use the ALFA persistent database functions (or calls to a local database) and without getting into the details, the result would be up to two calls to a function as follows:

Code: Select all

int klg_Persistent_Function(object oObject, string sAction, string sFutureAction, float fInterval, string sInterval);

object oObject 		- ResRef of object to be targeted
string sAction			- Name of action to be performed eg
				Lock
				Unlock
				klg_wipe_orcs
string sFutureAction	- Name of action to be performed in future eg
				Lock
				Unlock
				klg_spawn_bandits
Float fInterval		- number of intervals to pass before sFutureAction is executed
string sInterval		- type of interval
This would be

Code: Select all

iSuccess = klg_Persistent_Function(oObject, ‘klg_wipe_orcs’, ‘klg_spawn_bandits’, 4.00, ‘D’);
The first call is when the state changes initially, the second call will be when the server is rebooted.

With the initial call:
  • klg_wipe_orcs is called with oObject as its target
and
  • klg_spawn_bandits is called to be executed in 4.00 days with oObject as its target
In a server reboot:
  • klg_spawn_bandits is called to be executed in 4.00 Days of server up time from the initial call (tracking elapsed time) with oObject as its target
Stormsong Wyndsinger
  • Bard at large, Adventurer for hire,
    Scripter, Builder and Silly Person
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Re: Making Dungeons Persistent

Post by Teric neDhalir »

AcadiusLost wrote:Clarifies things, I hope?
It's taken 48 hours to percolate through my subconscious, but yes, I think I get that.
User avatar
Teric neDhalir
Githyanki
Posts: 1495
Joined: Mon Jan 05, 2004 10:04 pm
Location: Manchester UK

Re: Making Dungeons Persistent

Post by Teric neDhalir »

// The script run before this waypoint spawns. OBJECT_SELF points to the
// waypoint when this script is executed. If the script calls the function
// ACR_DisallowSpawn(), the waypoint will not be spawned. If it calls
// ACR_ForceSpawn(), the waypoint will always be spawned, regardless of other
// settings. If it doesn't call anything, the spawn point's behavior will be the
// default.
const string _WP_IS_ACTIVE_SCRIPT = "ACR_SPAWN_IS_ACTIVE_SCRIPT";
Two months of patching later and I'm back on the case with this. AL, do you remember that we decided this particular bit of the spawn system was not actually functioning? I've done the work on making a generic persistent spawn point work, but it's pointless without this particular function. Can I beg, plead and shower praises upon you enough to have a look at getting it working?
Grovelling,
Teric
Locked