Statistics Mod

Is there any nwn2 mod that compiles stats on how your party members are doing? Something similar to this:

I always liked comparing damage and kill stats on my party members in Infinity Engine games so I can tell how my builds are doing. I didn’t see one doing a quick google for nwn2.

If there is none, how difficult would it be to build one? I’m not a modder so I have no idea at all… this could be completely infeasible, but I’m just curious as to the level of work involved.

i’m sure this perks @Clangeddin’s interest, but to me it seems unfeasible.

The combat-engine is too hardcoded to readily access the values you’re looking for. So it’d likely fallback on trying to get as much data as possible from various AI-scripts, but AI-scripts can change from campaign to campaign so that’s extra effort. Some sort of an array (i use the term loosely) would likely have to be thought up. And a UI should be built (else just shoot all the data at the chatbox).

in my opinion it would never be satisfyingly comprehensive, and it’d take a lot of time and effort just to get that far,

If possible, this would probably redefine the concept of “maximum effort, minimum reward”.
I wouldn’t hold my breath on anyone even bothering with this, heck, it would be a more fruitive effort to try to implement turn based combat in NWN2 or making a new Mazinga Zeta class.

The only project even close to this that I’m aware of is this one - https://neverwintervault.org/project/nwnee/other/tool/nwn-loot-alert
Author has just released a version for NWN1 and is looking into NWN2.

Hi,

My module, “The Scroll” has a party statistics panel, with a homebrew GUI.

https://neverwintervault.org/project/nwn2/module/scroll

Note: The final GUI is much better than the one shown here in my opinion. This was its first design, which had more done to it by the time of release.

It keeps track of PC kills, party percentage input and gives PCs a title. Also breaks down types of creatures killed.

Cheers, Lance

3 Likes

it should be pointed out, i think, that The Scroll is a “total conversion” – a highly controlled environment that took Lance many years to master.

it also has turn-based combat, *

(cheers Lance  :)

 
* well, not true turn-based; but “turn-stopped” combat

2 Likes

There is the battlesystem mod that tracks kills during a combat. Maybe that could be adapted.

Sorry link . . . https://neverwintervault.org/project/nwn2/script/battle-system

“A package containing ready to use battle related scripts. Features include setting up and organizing armies, spawning soldiers, reinforcement, barrages and catapults, collecting statistics such as Kill count and other special effects. Play the demo to see all the features.”

2 Likes

@Lance_Botelle party stats and turn based combat? You got me sold! I got to check that out next.

Incidentally, how hard was it to implement the party kills counter? Dumb question – is there a script that gets called everytime something is killed or dies that you can hook into?

As for feedback for a stats page, if you’re still looking for that, I would suggest adding a Scalp List of bosses killed. Over time, the kill % is a decent tracker of party member offense, other than with bosses.

I would view death count as less important because most characters don’t die that often and you usually know who are weak links in your group. A Scalp List of bosses though would be a good nostalgia tool, and help you remember fondly the big moments from your adventures.

@Sawdust37 I thought of parsing the combat logs as well, but I couldn’t figure out an easy way to get combat logs from the game. The nwn2player.ini option to save chat log only captures the chat, and when a creature dies. It doesn’t capture the combat details, not even who killed the creature.

I tried ClientEntireChatWindowLogging=1 in nwn2player.ini, and it didn’t work. Anyone know a way?

Hi Phill,

Stats and (pseudo) TB combat! Yes, The Scroll has them both! :slight_smile:

My players have come from a D&D TB background and so I always intended to have a system of this sort in place for them. They believe it works well and always use it for combat as they like it so much. The good thing about it too, is that you can switch to and fro between TB and real time, so if it’s an easy fight, you can simply switch to real time and let the combat flow more quickly.

The stats GUI was something I always thought would be interesting to have too. I know how much I enjoyed viewing these and so as it was not too much more difficult (for my already quite modified game), I decided to include that too. In fact, The Scroll has many (of what I would call) “improvements” for the game mechanics and GUIs as a whole. i.e. I would love to play other builders modules with the systems I have in place, but as KevL alluded to, it is a very controlled system with many of the systems integral to the game itself. i.e. Each system may have some dependence on another.

As an example of some of the STATS code, below I have included a clip taken from the creature’s OnDeath script to give you a starting point.

By the way, do give me feedback if you can if and when you play my module. (I am considering uploading v2.88 soon.) Thanks.

Cheers, Lance.

///////////////////////////////////////////////////////////////////////////////////////////////
	// STATISTICS INFO - INCREASE DIRECT ENEMY KILL COUNT (UPDATED IF SCALED)	
	///////////////////////////////////////////////////////////////////////////////////////////////
	
	if(oMainPC != OBJECT_INVALID)
	{	
		// PREPARE KILLS FEEDBACK
		int Kills = GetLocalInt(oKiller, "Kills") + 1; SetLocalInt(oKiller, "Kills", Kills);
		
		// TOTAL NUMBER OF PARTY KILLS
		int PartyKills = GetGlobalInt("PartyKills") + 1; SetGlobalInt("PartyKills", PartyKills);
		
		// PREPARE STATUS FEEDBACK
		float fSTATUS = GetLocalFloat(oKiller, "CurrentCR");	
			
			if(fCR > fSTATUS)
			{
				string sStatus = "Incompetent";								// CR < 2
				if(fCR > 1.00 && fCR < 4.00){sStatus = "Blunderer";}		// CR 2-3
				if(fCR > 3.00 && fCR < 6.00){sStatus = "Huntsman";}			// CR 4-5
				if(fCR > 5.00 && fCR < 8.00){sStatus = "Beast Bane";}		// CR 6-7
				if(fCR > 7.00 && fCR < 11.00){sStatus = "Sell Sword";}		// CR 8-10
				if(fCR > 10.00 && fCR < 14.00){sStatus = "Dungeon Crawler";}// CR 11-13
				if(fCR > 13.00 && fCR < 17.00){sStatus = "Fortune Finder";}	// CR 14-16
				if(fCR > 16.00 && fCR < 20.00){sStatus = "Slayer";}			// CR 17-19
				if(fCR > 19.00){sStatus = "Legendary";}						// CR 20+
				
				SetLocalFloat(oKiller, "CurrentCR", fCR);
				SetLocalString(oKiller, "CurrentStatus", sStatus);
			}
			
		// COLLATE PC & PARTY STATUS (TO ALLOW INDIVIDUAL PC CONTRIBUTION)
		float fPARTYSTATUS = GetGlobalFloat("PARTYSTATUS") + fCR; SetGlobalFloat("PARTYSTATUS", fPARTYSTATUS);
		float fPCCONTRIB = GetLocalFloat(oKiller, "PCCONTRIB") + fCR; SetLocalFloat(oKiller, "PCCONTRIB", fPCCONTRIB);	
		
		// COLLATE RACIAL TYPES KILLS FEEDBACK
		int iRType = GetRacialType(OBJECT_SELF);	
		
		// ALTHEA RECOGNISED CATEGORIES FOR STATS FEEDBACK
		int HUMANOID = GetGlobalInt("RACE_HUMANOID"); 				// 6 (USE TO COVER ALL HUMANOID RACES)
		int ABERRATIONS = GetGlobalInt("RACE_ABERRATIONS");			// 7 
		int ANIMALS = GetGlobalInt("RACE_ANIMALS");					// 8
		int BEASTS = GetGlobalInt("RACE_BEASTS"); 					// 9
		int CONSTRUCTS = GetGlobalInt("RACE_CONSTRUCTS");			// 10
		int DRAGONS = GetGlobalInt("RACE_DRAGONS"); 				// 11
		int ELEMENTALS = GetGlobalInt("RACE_ELEMENTALS");			// 16
		int FEY = GetGlobalInt("RACE_FEY"); 						// 17
		int GIANTS = GetGlobalInt("RACE_GIANTS");					// 18				
		int MAGICBEASTS = GetGlobalInt("RACE_MAGICALBEASTS");		// 19		
		int OUTSIDERS = GetGlobalInt("RACE_OUTSIDERS");				// 20
		int PLANTS = GetGlobalInt("RACE_PLANT"); 	  				// 22
		int SHAPECHANGERS = GetGlobalInt("RACE_SHAPECHANGERS"); 	// 23
		int UNDEAD = GetGlobalInt("RACE_UNDEAD"); 					// 24
		int VERMIN = GetGlobalInt("RACE_VERMIN");					// 25
		int OOZES = GetGlobalInt("RACE_OOZES"); 					// 29
		
		// CONVERT MOST TO HUMANOID IF NOT OF TYPE ABOVE
		if(iRType < 6 || (iRType > 11 && iRType < 16) || iRType == 21 || (iRType > 25 && iRType != 29)){iRType = 6;}
		
		// NOW UPDATE THE MONSTER TYPE KILL STAT
		if(iRType == 6){SetGlobalInt("RACE_HUMANOID", HUMANOID + 1);}	
		else if(iRType == 7){SetGlobalInt("RACE_ABERRATIONS", ABERRATIONS + 1);}	
		else if(iRType == 8){SetGlobalInt("RACE_ANIMALS", ANIMALS + 1);}	
		else if(iRType == 9){SetGlobalInt("RACE_BEASTS", BEASTS + 1);}	
		else if(iRType == 10){SetGlobalInt("RACE_CONSTRUCTS", CONSTRUCTS + 1);}	
		else if(iRType == 11){SetGlobalInt("RACE_DRAGONS", DRAGONS + 1);}	
		else if(iRType == 16){SetGlobalInt("RACE_ELEMENTALS", ELEMENTALS + 1);}	
		else if(iRType == 17){SetGlobalInt("RACE_FEY", FEY + 1);}	
		else if(iRType == 18){SetGlobalInt("RACE_GIANTS", GIANTS + 1);}	
		else if(iRType == 19){SetGlobalInt("RACE_MAGICALBEASTS", MAGICBEASTS + 1);}	
		else if(iRType == 20){SetGlobalInt("RACE_OUTSIDERS", OUTSIDERS + 1);}	
		else if(iRType == 22){SetGlobalInt("RACE_PLANT", PLANTS + 1);}	
		else if(iRType == 23){SetGlobalInt("RACE_SHAPECHANGERS", SHAPECHANGERS + 1);}	
		else if(iRType == 24){SetGlobalInt("RACE_UNDEAD", UNDEAD + 1);}	
		else if(iRType == 25){SetGlobalInt("RACE_VERMIN", VERMIN + 1);}	
		else if(iRType == 29){SetGlobalInt("RACE_OOZES", OOZES + 1);}	
						
		// REFRESH STATS GUI FOR ALL PLAYERS
		RefreshStatsGUI();
	}
3 Likes