Need a Script - Faction Behavior

So in the mod I’m playing the player can add various guards, etc. to the game to protect assets from wandering monsters. Trouble begins when commoner, merchants or neutrals use AOE spells or supernatural abilities and accidentally damage a defender. All of the defenders then start attacking a faction they should be protecting. Game = Borked!

I need a way to either reset all factions to their original values or set the behavior for two specific factions to a desired value.

I already ran search on the vault and I don’t see this issue addressed before.

1 Like

experimental →

// 'fix_faction'
/*
	Console script.

	Adjusts how 'sSource' feels about 'sTarget' to 'desiredrep'.

	Pass a blank string for 'sTarget' to denote player-party.

	- desiredrep should be confined between 0 and 100
	- sSource and sTarget represent tags of creatures that currently exist
	- alternately specify bCreateSource/bCreateTarget to create creature(s) by resref

	kL_note: The faction-functions in this script also have "reversed" arguments
	but their calls are commented out. You can switch the faction-function calls
	if you believe that the faction-table in NwN2 is reversed like I do.

	Example usage:
	- 2 creatures exist in the module and change how faction a feels about faction b
	fix_faction("tag_of_creature_faction_a", 0, "tag_of_creature_faction_b", 0, 50)

	- create a creature by resref and change how it feels about the PC
	fix_faction("resref_of_creature_faction", 1, "", 0, 50)
*/

//
void main(string sSource, int bCreateSource, string sTarget, int bCreateTarget, int desiredrep)
{
	object oSource;
	if (bCreateSource)
	{
		oSource = CreateObject(OBJECT_TYPE_CREATURE, sSource, GetLocation(OBJECT_SELF));
	}
	else
		oSource = GetObjectByTag(sSource);

	if (!GetIsObjectValid(oSource))
	{
		SendMessageToPC(GetFirstPC(FALSE), "Source is not valid.");
		return;
	}

	object oTarget;
	if (sTarget == "")
	{
		oTarget = GetFirstPC();
	}
	else if (bCreateTarget)
	{
		oTarget = CreateObject(OBJECT_TYPE_CREATURE, sTarget, GetLocation(OBJECT_SELF));
	}
	else
		oTarget = GetObjectByTag(sTarget);

	if (!GetIsObjectValid(oTarget))
	{
		SendMessageToPC(GetFirstPC(FALSE), "Target is not valid.");
		return;
	}


	// set Pause in case creatures aggro ...
	if (!GetPause())
	{
		SetPause(TRUE);
		SendMessageToPC(GetFirstPC(FALSE), "Game PAUSED ...");
	}


	int rep = GetReputation(oSource, oTarget); // not reversed
//	int rep = GetReputation(oTarget, oSource); // reversed
	SendMessageToPC(GetFirstPC(FALSE), "Source feels " + IntToString(rep) + " toward Target");

	int change = desiredrep - rep;

	SendMessageToPC(GetFirstPC(FALSE), ". change= " + IntToString(change));
	AdjustReputation(oTarget, oSource, change); // not reversed
//	AdjustReputation(oSource, oTarget, change); // reversed

	rep = GetReputation(oSource, oTarget); // not reversed
//	rep = GetReputation(oTarget, oSource); // reversed
	SendMessageToPC(GetFirstPC(FALSE), ". result= " + IntToString(rep));


	if (bCreateSource)
	{
		SetPlotFlag(oSource, FALSE);
		SetImmortal(oSource, FALSE);
		AssignCommand(oSource, SetIsDestroyable(TRUE));
		DestroyObject(oSource, 0.3f);
	}

	if (bCreateTarget && sTarget != "")
	{
		SetPlotFlag(oTarget, FALSE);
		SetImmortal(oTarget, FALSE);
		AssignCommand(oTarget, SetIsDestroyable(TRUE));
		DestroyObject(oTarget, 0.3f);
	}
}

// Clear all personal feelings that oSource has about oTarget.
//void ClearPersonalReputation(object oTarget, object oSource=OBJECT_SELF);

// Set how nStandardFaction feels about oCreature.
// - nStandardFaction: STANDARD_FACTION_*
// - nNewReputation: 0-100 (inclusive)
// - oCreature
//void SetStandardFactionReputation(int nStandardFaction, int nNewReputation, object oCreature=OBJECT_SELF);

// Find out how nStandardFaction feels about oCreature.
// - nStandardFaction: STANDARD_FACTION_*
// - oCreature
//int GetStandardFactionReputation(int nStandardFaction, object oCreature=OBJECT_SELF);
3 Likes

THX!!!

I’ll give it a try tonight and let you know what happens.
Edit: Maybe tomorrow. Real life is such a hassle.

2 Likes

np. Take care of your garden…

1 Like

Back from my trip and it worked.
It took me longer to figure out which faction each creature belonged to than to compile and run the script.

I’ve figured out how the factions interact and posted it on the module’s project page along with your temporary fix.

Tanks a lot …

2 Likes

nice. tanks …

1 Like

Is it possible that the Faction Table is “correct” but some of the functions that call it are reading the wrong cells leading to inconsistent game behavior?

1 Like

The inversion seems to be happening very near the faction table itself.

Eg. even using the function GetNearestCreature() with the CREATURE_TYPE_REPUTATION argument has to be reversed (for me to get proper output).

 
note that it doesn’t affect reputation against the pc-party, and since most factions have the same value against each other it’s barely noticeable.

To test it I had to set up a table in which every value is different. Then run a script that prints how a member of a faction feels about a member of all other factions, then how a member of the next faction feels about all other factions, etc

most people aren’t interested but i did get confirmation from one other person i trust.

 
It would really only be an issue if, say you wanted to enact a passivist (npc) monk faction against an aggressive (npc) warlord faction …

2 Likes

This isn’t the first time I’ve seen a faction go rouge but in most games, it would not matter as the commoners are only there for background color and the merchants have no behaviors outside of their shop dialogs. The game would play out exactly the same if all the generic population were killed off.

In this case, I’m playing Sean Maxhell’s Town Simulator. Sort of a Sim City meets D&D. You need the population to grow in order to unlock new features so you can’t have your Defender’s killing off all the peasants. Bad form and all that.

1 Like

just remembered, things like adjust reputation (with reversed faction values) are a bit complicated …

// this function corrects the fault in AdjustReputation()
void kL_AdjustReputation(object oTarget, object oSource, int iAdjustment)
{
	int iRep_source = GetReputation(oTarget, oSource);
	int iRep_target = GetReputation(oSource, oTarget);

	int iDiff = iRep_source - iRep_target;
		iDiff += iAdjustment;

	AdjustReputation(oTarget, oSource, iDiff);
}

(eg)

anyway as long as things work and the game continues :)

 

its not arbitrary. A misplaced fireball is gonna wreak havoc either way …

2 Likes

My other idea was to turn this into a bribery/payoff/kickback function.
“How much is the PC willing to pay to get faction A to stop killing faction B?”
I imagine that could get a bit complicated in the case of custom factions. It would have to be integrated with the mod to avoid breaking the plot in some cases.

yes anyone who did that would want to become intimately familiar with the module and the faction-functions

but that’s the kind of thing that intrigues me from a mechanic’s perspective …

1 Like