(WIP) Lands of Intrigue development thread

It all began as a family project so we could play together in a D&d setting, but it began to grow and became a little monster.

It has become and Open World type module and I’m a little proud how it’s developing, so I’ll start this thread as a placeholder of data and a resource center for whoever gets interested.

I’ll use this initial post as an update and system overview.

Spawn System
Time Persistency

This video shows the City of Darromar in its early stages.

And a travel from Lesthyn’s Hearth to Darromar.

The village still needs some finishing work.

B.

6 Likes

Those look nice

Spawn System:

  • NESS
    A heavily modified version of NESS is being used in the module to achieve local and ambient spawns.

To those of you who are familiarized with NESS, this version ignores the original tag based systems and relies heavily on a couple of custom flag that makes the system look for variables set on the spawn waypoints.

Some of those variables make up for the original system just telling it the usual spawning option (mainly cause I prefer to see the waypoints listed as “anim_badger_cete_3a5” or “ambient_woods” than “SP_RWR20_SR40_SN2M0_…”).

I realized taht to achieve real ambient spawns I need to use some kind of array system to sort out wich kind of creature spawn when asked by the system.

So if the Spawn Waypoint has a variable CR, the spawned creature CR is “adjusted” acording to the PC triggering the spawn; if the variables says it’s RS, the creature is sorted out from a randomization list (Like the church members spawn in Darromar Cloister of Ilmater, or the inn’s henchmen spawning waypoints); if the variable says CRS, it gets the type of creature from one 2da, and sorts out the creature according to the PC level from a creature list 2da. This is the case of humanoids (ie. bandits) or ambient spawns.

So, this is an example of an ambient farmlands list

amb_farmlands
0 15
1 anim_boar
2 anim_boar
3 anim_boar
4 anim_boar
5 anim_boar
6 anim_badger
7 anim_badger
8 anim_badger
9 anim_badger
10 anim_falcon
11 anim_falcon
12 anim_bear
13 anim_cougar
14 anim_wolf
15 verm_bt_stag

And this would be an example of a type list:

ANIMALS anim_bear
0 **** an_bear02
1 **** an_bear02
2 **** an_bear02
3 **** an_bear03
4 **** an_bear03
5 **** an_bear05
6 **** an_bear06
7 **** an_bear07
8 **** an_bear07
9 **** an_bear_dire09
10 **** an_bear07
11 **** an_bear_dire11
12 **** an_bear07
13 **** an_bear07
14 **** an_bear_dire14
15 **** an_bear07
16 **** an_bear_dire16
17 **** an_bear07
18 **** an_bear07
19 **** an_bear_dire19
20 **** an_bear_dire21

to do:
Upgrade the system to achieve a better CR adjustment. Right now when a PC triggers an ambient encounter, it first resolve the type of creature, and then it uses PC level to get a random option from the creature type list. So a lvl 6 PC triggers an ambient farmland encounter, the system gets a random (15) = 12, so a random (6+1) creature is spawned. You have 28.57% chance to face a lvl2 brown bear, 28.57% chance to face a lvl3 brown bear 14.28% chance to face a lvl4 brown bear, and the same chance for lvl 5 or 6.

You can also face a Bullette or a Hill Giant with a lvl 3 PC.

It’s not a really bad system for ambient spawning, so I’m using a “trigger triggered” vanilla system for specialized areas.

  • Vanilla Spawn System

The vanilla spawn system is being used to spawn specialized areas, like bandit occupied barns. To give it some kind of surprise and randomization effects, I use generic trigger to activate a random encounter at a time.

Barns from the farmlands or Dock warehouses use this type of spawn system.

  • All encounters starts deactivated.
  • All Darromar Dock Warehouses (ie.) are mapped in the same area (which minimaps get blacked out each time a PC enters).
  • Each Darromar Dock Warehouse has its own vanilla encounter trigger.
  • When a PC enters the area, an encounter is sorted out randomly and is set active. It remains active until exhausted.
  • After exhaustion, it waits until area is empty and a restart counter is started.
  • The system restarts and wait until a PC enters the area, and a random encounter is activated again.

This one has a beter CR adjustment but lacks the ambient side of NESS.

B.

Some early pictures from Darromar:




Krimmevol Court

The Royal Palace of Faerntarn

B.

A ride to Masamount in Rivershire

And the village itself

B.

4 Likes

I decided it was time to move to County Varyth and Tor Arcana surroundings to do some finishing…

The farmlands around Tor Arcana:

Count Riiklas tower as background:

Tor Arcana quay (to cross Sulduskoon river):

And as I thought I was a little short of cave variants I decided it was time to add Merricksdad Winspear Hills placeables:

I think they look better in the toolset than ingame… (don’t know if it’s a shadows/lighting thing or what)

B.

2 Likes

I’ve been thinking of adding some kind of time persistency between sessions.

The general idea I’ve been working on is to store the time variables in campaign db (globally) each time a PC starts resting and on module load retrieve and set those time variables.

Has anybody tried this aproach? Is it the right way of doing it?

Time persistency

Finally I decided with this aproach to ensure time persistency between sessions.

OnPlayerRest:

after

case:         REST_EVENTTYPE_REST_FINISHED:
            // TDLI - Time persistency
            int iYear = GetCalendarYear();
            int iMonth = GetCalendarMonth();
            int iDay = GetCalendarDay();
            int iHour = GetTimeHour();
            int iMinute = GetTimeMinute();
            int iSecond = GetTimeSecond();
            SetCampaignInt ("DB_name","iYear",  iYear);
            SetCampaignInt ("DB_name","iMonth", iMonth);
            SetCampaignInt ("DB_name","iDay",   iDay);
            SetCampaignInt ("DB_name","iHour",  iHour);
            SetCampaignInt ("DB_name","iMinute",iMinute);
            SetCampaignInt ("DB_name","iSecond",iSecond);

and onModuleLoad (so it has nothing to do with players login in a cooperative scenario)

    //TDLI - Time persistency
    if (GetCampaignInt ("DB_name","iMonth") != 0) { //I needed to check against a value that could not be 0 if it was not null
        SetTime (
            GetCampaignInt ("DB_name","iHour"),
            GetCampaignInt ("DB_name","iMinute"),
            GetCampaignInt ("DB_name","iSecond"),
            0 //Don't give a **** about milliseconds
        );
        SetCalendar (
            GetCampaignInt ("DB_name","iYear"),
            GetCampaignInt ("DB_name","iMonth"),
            GetCampaignInt ("DB_name","iDay")
        );
    }

A small tour on County Varyth farmlands, rolling plains and hills…

…and a small teaser on followers.

1 Like

I found out that the plain ugly textures I was seeing were an error caused by NWNhak (at least my version) that did not recognize the .mtr extension when I repacked them. I used the merge option and it got solved.

There are only a couple of reasons why NwHak won’t recognise the .mtr extension. Either you used the NwHak that came with 1.69/Diamond or you haven’t updated your version of NwN EE in a very long time.

TR

1 Like

I think you’re right TR, I didn’t notice I was using a NWHak version sitting on my docs, last updated on 2014 :man_facepalming:t2:

After finishing up County Varyth hills…

… I’m turning back to County Rivershire and the Seminary of St. Ostus and its surrounding village.

Meanwhile I’m doing some planning around rumor & information, and generic task & quest systems.

B.

2 Likes

About the task system…

I’m thinking a “witcheresque” aproach with notice boards outside inns, tavers or some other key locations like the entrance to the Seminary of St. Ostus (image below).

The board will sort a random quest out of a prefixed table for the local area and send the PC to look after some NPC who will ask the PC to fullfill a task.

  • Some NPC might not have a task when PC reaches them (PC arrived “too late”).
  • Some NPC might reward the PC even if they have no task to offer
  • Some errands might be near, some might encourage travelling.

By now I’m testing tasks that involve carrying/gathering.

  • Once a task has been setup in a notice board, it will remain until accepted. Then it can re-roll.
  • The more boards in a location (more inns/taverns = more boards), more options to choose from.
  • Once taken from the board tasks can be rejected when the task giver NPC is reached.

The system uses a 2da table with the task data that is setup using custom tokens into NPC dialogs and PC journal.

It also stores and retrieves all the task data using the built-in database function.

Once I’m satisfied with the outcome I’ll start new variations.

More to come…

B.

(?) Simulated walkmesh helper

As I have been playing with some placeables that a proper walkmesh I decided to see if I could simulate a movement blocker that could be adjusted to any form.

So I draw a trigger around the placeable and added this onEnter script…

#include "x0_i0_position"

void no_walk_jump(object oPC, object NWA)
{
    if (GetIsInSubArea (oPC, NWA)) {
//      location locPCnew = GetBehindLocation (oPC);
        AssignCommand (oPC, ClearAllActions (TRUE));
//      AssignCommand (oPC, JumpToLocation (locPCnew));
        AssignCommand (oPC, ActionMoveAwayFromLocation (GetLocation (oPC), FALSE, 1.0));
        AssignCommand (oPC, ActionDoCommand (SetCommandable (TRUE, oPC)));
        AssignCommand (oPC, ActionDoCommand (no_walk_jump (oPC, NWA)));
        AssignCommand (oPC, SetCommandable (FALSE, oPC));

    }
}

void main()
{
    object oPC = GetEnteringObject ();
    if (GetIsInSubArea (oPC, OBJECT_SELF)) {
        no_walk_jump (oPC, OBJECT_SELF);
    }
}

I think it works wather well…

B.

1 Like

Here’s how the triggers are placed…

…and this is how it’s working.

AI won’t be able to find its path wisely (well…like 50% of the time), but I don’t dislike how it works.

B.