Nwn2fixes


#122

@Aqvilinus
i don’t think Halforc should be included in civorcs … halfelf isn’t in civelves

up for discussion:

    if (sRace == "civdwarves" || sRace == "41")
    {
        int iSubrace = GetSubRace(oPc);
        return (iSubrace == RACIAL_SUBTYPE_GOLD_DWARF           // kL_Fixed: To you know actually be Dwarfs.
             || iSubrace == RACIAL_SUBTYPE_SHIELD_DWARF);
//           || iSubrace == RACIAL_SUBTYPE_GRAY_DWARF
    }

    if (sRace == "civelves" || sRace == "42")
    {
        int iSubrace = GetSubRace(oPc);
        return (iSubrace == RACIAL_SUBTYPE_MOON_ELF             // kL_Fixed: To you know actually be Elfs.
             || iSubrace == RACIAL_SUBTYPE_SUN_ELF              // note: Halfelf/Halfdrow not included.
             || iSubrace == RACIAL_SUBTYPE_WOOD_ELF);
//           || iSubrace == RACIAL_SUBTYPE_WILD_ELF
//           || iSubrace == RACIAL_SUBTYPE_DROW
    }

    if (sRace == "civhalflings" || sRace == "43")
    {
        int iSubrace = GetSubRace(oPc);
        return (iSubrace == RACIAL_SUBTYPE_LIGHTFOOT_HALF       // kL_Fixed: To you know actually be Halflings.
             || iSubrace == RACIAL_SUBTYPE_STRONGHEART_HALF);
//           || iSubrace == RACIAL_SUBTYPE_GHOSTWISE_HALF
    }

    if (sRace == "civorcs" || sRace == "44")
    {
        return (GetSubRace(oPc) == RACIAL_SUBTYPE_GRAYORC);     // note: Halforc not included.
    }

#123

There’re already separate checks for half-orcs/greyorcs. No need in another one. I think they should go together (as was the original intent of OEI programmers).


#124

okay … so leave out GrayDwarf, WildElf, etc also?


#125

civ probably stands for civilized, what is the reason for the exception of those races… well, I don’t know.
I’ll leave the decision to you, KevL.


#126

well, looking back on it I think those extra subraces should be included. I mean, think if a player WildElf talks to an NPC …

NPC: “Do you want to learn the Secrets of the Elf Mistress?”
player: “Yes, I do”
NPC: “Sorry, you’re not an elf”

at that point, as a player I’d check if i could attack the NPC …

 
I wonder if we can get a third opinion here.
a) keep it conservative and go with original OEI design
b) update the script to make sense

/lol


#127

okay since it’s duly noted at the top of the script

// civdwarves   41 -- this is all dwarf subraces, save duergar.
// civelves     42 -- all elf subraces, save drow and wild.
// civhalflings 43 -- all halfling subraces, save ghostwise
// civorcs      44 -- all orc subraces

i’ll keep it conservative. Although i’m still befuddled by the fact that Halforc isn’t actually a subrace of Orc … I mean i understand it (as a special case) but it’s not technically correct


#128

Some bugfixes to the Area 2423 in the 2400_Illefarn_Ruins module. Done via the OnClientEnter script.

// 2423_cliententer
/*
	Fire the ghellu/blix cutscene
*/
// EPF 3/31/06

#include "ginc_misc"

int StartingConditional()
{
	if (!FiredFromPartyTransition())
		return FALSE;

	object oPC = GetFactionLeader(GetFirstEnteringPC());
	object oArea = OBJECT_SELF;

	if (GetGlobalInt("24_bGhelluIsDead"))
	{
		return FALSE;
	}
		
	//*******************************************************************************
	// Aqvilinus: This fixes a bug which prevented the player from pickpocketing Ghellu's and
	// Blix's rings (they have them equipped, so for technical reasons they are unpickpocketable,
	// despite of the "pickpocketable" flag set on in the Toolset, so this is obviously a bug).
	//*******************************************************************************
	object oGhellu = GetNearestObjectByTag("24_ghellu", oPC);
	object oBlix = GetNearestObjectByTag("24_blix", oPC);

	object oRing = GetItemInSlot(INVENTORY_SLOT_RIGHTRING, oGhellu);
	if (GetIsObjectValid(oRing)) AssignCommand(oGhellu, ActionUnequipItem(oRing));

	oRing = GetItemInSlot(INVENTORY_SLOT_LEFTRING, oBlix);
	if (GetIsObjectValid(oRing)) AssignCommand(oBlix, ActionUnequipItem(oRing));

	//*******************************************************************************
	// Aqvilinus: All goblins in the area have their body armor equipped in the wrong inventory slot (!!!).
	// (INVENTORY_SLOT_CARMOUR instead of INVENTORY_SLOT_CHEST).
	//*******************************************************************************
	if (!IsMarkedAsDone())
	{
		MarkAsDone();

		object oTarget = GetFirstObjectInArea(oArea);
		object oItem;

		while (GetIsObjectValid(oTarget))
		{
			if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && !GetFactionEqual(oTarget, oPC))
			{
				oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTarget);
				if (GetIsObjectValid(oItem) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
				{
					AssignCommand(oTarget, ActionUnequipItem(oItem));
					DelayCommand(0.5f, AssignCommand(oTarget, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)));
				}
			}
			oTarget = GetNextObjectInArea(oArea);
		}

	//	AssignCommand(oGhellu, ActionStartConversation(oPC, "24_cs_ghellu", FALSE, FALSE, TRUE, FALSE));
	}

	return FALSE;
}

Damn, some creatures in the Area 2422 have the same problem with their armor… Besides, one of the goblins (24_goblincaptain) has no armor and no weapon. The other goblin (with the same tag) has his armor simply lying in the inventory… Funny.

UPD: I ended up using the OnClientEnter script for the Area 2410 (2410_area_ce).

	// First time entering
	if (!IsMarkedAsDone())
	{
		MarkAsDone();

		FixFactions();

		object o2421 = GetArea(GetWaypointByTag("2421_wp_fr_2422"));
		object o2422 = GetObjectByTag("2422_riverguar2");
		object o2423 = GetArea(GetWaypointByTag("2423_wp_fr_2421"));

		FixArmor(o2421);
		FixArmor(o2422);
		FixArmor(o2423);

		//....
	}
void FixArmor(object oArea)
{
	object oPC = GetFirstEnteringPC();
	object oTarget = GetFirstObjectInArea(oArea);
	object oItem;

	while (GetIsObjectValid(oTarget))
	{
		if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && !GetFactionEqual(oTarget, oPC))
		{
			oItem = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oTarget);
			if (GetIsObjectValid(oItem) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
			{
				AssignCommand(oTarget, ActionUnequipItem(oItem));
				DelayCommand(0.5f, AssignCommand(oTarget, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST)));
			}
		}
		oTarget = GetNextObjectInArea(oArea);
	}
}

This is another my fix for wrong factions in the Area 2422 (note that blueprints for faction pigs aren’t in the module by default):

void FixFactions()
{
	int i;
	object oOgreFaction = CreateObject(OBJECT_TYPE_CREATURE, "24_faction_ogre", GetLocation(GetWaypointByTag("2410_wp_entrance")));
	object oBBFaction = CreateObject(OBJECT_TYPE_CREATURE, "24_faction_bugbear", GetLocation(GetWaypointByTag("2410_wp_entrance")));
	object oNear = GetWaypointByTag("2422_wp_fr_2421");
	object oTarget;

	i = 1;
	oTarget = GetNearestObjectByTag("24_ogre", oNear, i);
	while (GetIsObjectValid(oTarget))
	{
		ChangeFaction(oTarget, oOgreFaction);
		oTarget = GetNearestObjectByTag("24_ogre", oNear, ++i);
	}

	oTarget = GetNearestObjectByTag("24_ogrechief", oNear);
	ChangeFaction(oTarget, oOgreFaction);

	oTarget = GetNearestObjectByTag("c_ogre", oNear);
	ChangeFaction(oTarget, oOgreFaction);

	i = 1;
	oTarget = GetNearestObjectByTag("24_goblin", oNear, i);
	while (GetIsObjectValid(oTarget))
	{
		ChangeFaction(oTarget, oOgreFaction);
		oTarget = GetNearestObjectByTag("24_goblin", oNear, ++i);
	}

	i = 1;
	oTarget = GetNearestObjectByTag("24_gobcaptain", oNear, i);
	while (GetIsObjectValid(oTarget))
	{
		ChangeFaction(oTarget, oOgreFaction);
		oTarget = GetNearestObjectByTag("24_gobcaptain", oNear, ++i);
	}

	i = 1;
	oTarget = GetNearestObjectByTag("24_bugbear", oNear, i);
	while (GetIsObjectValid(oTarget))
	{
		ChangeFaction(oTarget, oBBFaction);
		oTarget = GetNearestObjectByTag("24_bugbear", oNear, ++i);
	}

	DestroyObject(oOgreFaction, 1.0f, FALSE);
	DestroyObject(oBBFaction, 1.0f, FALSE);
}

#129

will have a closer look in a day or two, Aqvi. Have got some stuff on my plate atm,

so do any tweaks …


#130

I’ve put everything in a single archive. Maybe not all from these can be considered as fixes (there’re some improvements also), but anyway have a look…

P.S. Lavallet is me, just another my nickname.


#131

I’m happy to see fixes being made.


#132

@kevL_s I updated some scripts, pls re-download :slight_smile:


#133

keep me updated … since it looks like i’ll be dealing with a terrorship for the next few days

… that’s not what its supposed to look like


#134

Fixes for 2100_Crossroad_Keep_A2 and 3000_Neverwinter_A3 modules I’ve made for myself.


Sorry, there’re not much comments and also there’re some debug messages in Russian… but still I believe you may find it useful. :slightly_smiling_face: And I’m open to discussion.

I believe I managed to fix all the bugs from this page (http://nwn2.wikia.com/wiki/Crossroad_Keep#Bugs), not to mention some improvements made (e.g.: reworked functions for applying injuries/losses, injuries and losses aren’t useless numbers anymore).

UPD: Updated some scripts (fixed small errors / refactored).


#135

Umm, It’s not a Pink Orc beauty salon?

You guys are actually making me look forward to another playthrough.


#136


tada *tshh


#137

@Aqvilinus
There’s a lot of stuff there, quite franky i’d find it overwhelming to chew through …

if we can go through it file by file, directory by directory – fix by fix

eg, start at the top, tell me what the first fix is (and exactly what files are involved), then it can be discussed and i’ll make a commit of it.

 
/over to you


#138

Well, I’ll try :slightly_smiling_face:

Let’s start from something very simple.

The problem:

Area 3031. When you kill the giants by throwing the rock on them, three of the giants from the main encampment are supposed to investigate the matter by moving towards your location. However, this is never triggered due to bugs, fixed. Fixed a problem where the fire giants that go to investigate the incident kill the prisoners in the cage (faction problems). Fixed a problem where these giants get stuck on the way up the mountain due to path-finding bugs.

Files:

  • 3031_text_boulders.dlg
  • 3031a_text_boulders.ncs
  • 3031a_text_boulders.nss

Make sure you downloaded the latest version of my archive since I made changes to the script above half an hour ago.

//3031a_text_boulders

#include "ginc_misc"
#include "ginc_group"

////////////////////////////////////////
//** Function Prototypes
////////////////////////////////////////
void BouldersFall();
void CreateObjects();
void KILL(object oGiant);
void FireGiantsInvestigate();

//** MAIN
void main(int nChoice)
{
	switch (nChoice)
	{
		case 10:
			BouldersFall();
			break;
//		case 20:
//			FireGiantsInvestigate();
//			break;
	}
}

////////////////////////////////////////
//** Function Definitions
////////////////////////////////////////
void BouldersFall()
{
	object oPC = GetFactionLeader(GetFirstPC());
	object oPrisoner;
	object oNeutral = GetObjectByTag("3063_whmover");
	int i;

	for(i = 1; i <=3; i++)
	{
		oPrisoner = GetNearestObjectByTag("3031_prisoner" + IntToString(i), oPC);
		ChangeFaction(oPrisoner, oNeutral);
	}

	object oBoulder = GetTarget("3031_cliffboulder");

	SetPlotFlag(oBoulder, FALSE);
	ActionDoCommand(FadeToBlack(oPC, 1.5f));
	ActionWait(1.0f);
	DelayCommand(2.0f, DestroyObject(oBoulder));
	ActionDoCommand(CreateObjects());
	ActionWait(2.0f); // This delay appears to be sufficient for now.  FOR NOW.  Dun dun dun!!!
	ActionDoCommand(FadeFromBlack(oPC, 1.5f));
}

void CreateObjects()
{
	object oPC = GetFactionLeader(GetFirstPC());
	object oNeutral = GetObjectByTag("3063_whmover");
	object oRegulator = GetTarget("3031_ip_regulator");

	location lNewBoulderWP = GetLocation(GetTarget("3031_wp_fallen_boulders"));
	location lCollisionBox1 = GetLocation(GetTarget("3031_wp_collbox1"));
	location lCollisionBox2 = GetLocation(GetTarget("3031_wp_collbox2"));
	CreateObject(OBJECT_TYPE_PLACEABLE, "3031_boulders", lNewBoulderWP, FALSE);
	CreateObject(OBJECT_TYPE_PLACEABLE, "3031_collbox", lCollisionBox1, FALSE);
	CreateObject(OBJECT_TYPE_PLACEABLE, "3031_collbox", lCollisionBox2, FALSE);

	SetLocalInt(oRegulator, "FGNumCrushed", 0);

	int i = 1;
	object oNearestFG = GetNearestObjectByTag("galad_fgiant", oRegulator, i);
	while (GetIsObjectValid(oNearestFG) && GetLocalInt(oRegulator, "FGNumCrushed") < 3)
	{
		if (GetLocalInt(oNearestFG, "FGNearBoulders") && !GetIsDead(oNearestFG))
		{
			ChangeFaction(oNearestFG, oNeutral);
			AssignCutsceneActionToObject(oPC, KILL(oNearestFG));
			ModifyLocalInt(oRegulator, "FGNumCrushed", 1);
		}
		oNearestFG = GetNearestObjectByTag("galad_fgiant", oRegulator, ++i);
	}

	AssignCutsceneActionToObject(oPC, FireGiantsInvestigate());
}

void KILL(object oGiant)
{
	AssignCommand(oGiant, SetIsDestroyable(FALSE, FALSE, FALSE));

	int nDamage = GetCurrentHitPoints(oGiant) + 11;
	effect eDamage = EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING);
	ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oGiant);
}

void FireGiantsInvestigate()
{
	object oRegulator = GetTarget("3031_ip_regulator");
	string sGiantsGroup = "InvesGiants";

	ResetGroup(sGiantsGroup);
	SetLocalInt(oRegulator, "FGNumLeaving", 0);

	int i = 1;
	object oNearestFG = GetNearestObjectByTag("galad_fgiant", oRegulator, i);
	while (GetIsObjectValid(oNearestFG) && GetLocalInt(oRegulator, "FGNumLeaving") < 3)
	{
		if (GetLocalInt(oNearestFG, "CanInvestigate") && !GetIsDead(oNearestFG))
		{
			GroupAddMember(sGiantsGroup, oNearestFG, TRUE);
			SetBumpState(oNearestFG, BUMPSTATE_BUMPABLE);
			ModifyLocalInt(oRegulator, "FGNumLeaving", 1);
		}
		oNearestFG = GetNearestObjectByTag("galad_fgiant", oRegulator, ++i);
	}

	if (GetIsGroupValid(sGiantsGroup, TRUE))
	{
		AssignCutsceneActionToObject(GetFirstInGroup(sGiantsGroup), GroupJumpToWP(sGiantsGroup, "3031_wp_fg_investigate"));
		AssignCutsceneActionToObject(GetFirstInGroup(sGiantsGroup), GroupMoveToWP(sGiantsGroup, "wp_3031_from_3032", MOVE_RUN));
		GroupSetSemicircleFormation(sGiantsGroup, FORMATION_HUDDLE_FACE_OUT , 5.0f);
	}
}

#139

What does it say about me that my first guess as to what the terrorship was supposed to be ended up being the control room of Lolth’s spider ship…


#140

hehe, if i knew more about modelling and tilesets i’d plop one of those puppies down somewhere

/jk


#141

Small improvement for 3031_tholap_cliff.dlg.

Before

After

So all party member that potentially can say something in that cutscene, will do that now.

Also the player’s response “Sign or not, it is rather peculiar.” obviously shouldn’t appear if Zhjaeve isn’t in the party (gc_is_in_party("zhjaeve") <- but I didn’t add this check in my pack, so do it yourself).

Another small problem here: what if you don’t take Khelgar with you to the Mount Galadrym? This dialog would be still fired (through the IPS speaker) and end abruptly. But I don’t think it’s critical and requires some care.