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.
// '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);
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?
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 …
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.
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 …
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.