Kaedrin's Stuff and Companions

Just a shot in the dark here with a couple questions:

  1. I am playing NWN2 with Kaedrin’s content pack and none of his stuff which runs off the heartbeat event handler will run on companions. Everything else works fine on companions if it runs onequip or onlevelup, but not onheartbeat. Any ideas why? Does NWN2 run companion HBs differently than NWN1?

Also, I should note everything requiring event hooks runs fine on the player character.

  1. Did Kaedrin ever release his NSS files? I am going through fixing bugs that I have run into in his stuff and Tome of Battle, but not being able to actually get eyes on it limits what I can do obviously.

2 - Files request (Kaedrin prc pack1.42.1 with nss) - #8 by Raygereio

1 - note that the AI scriptset for PC and/or Companions gets switched (automatically) depending on whether or not the PC/Companion is currently controlled by the player. The engine locks out most of the events (all except OnHeartbeat, OnDeath, OnUserdefined). So that’s probly not it … but thought id mention it

see Nwn2_Scriptsets.2da

 
There might be a condition preceding the call to run Kaedrin’s HB that stops it from running on anything other than the PC … (idk just a guess – there shouldn’t be, but note that the HB-handlers are different scripts for PC/Companion/Associate/etc – see Nwn2_Scriptsets.2da)

Thank you for the NSS files! Once I could actually look at them it only took a couple minutes to find the issue: everything runs through GetFirstPC/GetNextPC. Unless the PC list is composed differently than in NWN1, the companions won’t be evaluated at all. I’ll toss in a loop for henchmen and see if it fixes the issue.

1 Like

I think the PC-list is composed differently than in Nwn1 … Nwn2 has Companions (not just henchmen). So there’s typically a parameter added to the Nwn2 functions

eg

object GetFirstPC(int bOwnedCharacter=TRUE);

An “owned character” in Nwn2 is a PC in the Nwn1 sense.

 
ps. This might help ya get a grip on the confusing mess of player-allied chars that nwn2 has
C-info | The Neverwinter Vault

try GetFirst/NextPC(FALSE) and see what that does …

[edit] actually that cycles through PlayerControlledCharacters (which might not be OwnedCharacters)

usually this sort of loop is used to cycle through PC-faction →

object oPC = ; // define a partymember
object oParty = GetFirstFactionMember(oPC, FALSE);
while (GetIsObjectValid(oParty))
{
    if (GetIsOwnedByPlayer(oParty)) // eg.
    {
        // these are Nwn1-style PCs
        // but if this is what you want just use GetFirst/NextFactionMember(oPC, TRUE)
    }

    if (GetAssociateType(oParty) == ASSOCIATE_TYPE_NONE) // eg.
    {
        // these are PCs and Companions (without Associates, henchmen, familiars, etc)
    }

    // leave the checks off to handle the entire Party
    oParty = GetNextFactionMember(oPC, FALSE);
}
1 Like

Haha well so far looping GetNextPC(FALSE) and looping ASSOCIATE_TYPE_HENCHMAN does not work - I will try the new loop you suggested!

feel free to post a bit of what you’re looking at (and what script its in) :)

remember that Henchmen are NOT Companions … nwn2 has henchmen (which are Associates) and Companions (which are, somewhat ironically, characters for which GetIsPC() returns true, when controlled/possessed by a player)

1 Like

How do you post in script format here? Three single quotes before and after? I am used to Discord.

yep, I usually put

```nwscript
// code
```

because i notice that specifying the language helps the color-syntax a bit more than the default c (or whatever it is)

Rad! Well that last loop fixed all the broken HB feats for companions! Thanks sir.

Ironically, the feat I am interested in (Holy Warrior) did not end up being linked to the heartbeat, but now that I have the NSSs, it won’t take me long to GREP and find it.

Since you apparently know a thing or two about a thing or two, here is another NWN2 scripting question: does GetEffectInteger work with EffectDamageReduction?

that could be a can o’ worms, not sure. DamageReduction is implemented differently in Nwn2. Its kinda not an effect and its kinda not an IP yet it is kinda an effect and it is kinda an IP …

The rules for DR changed from 3e (nwn2) to 3.5e (nwn2) rulesets.

here’s one way of putting DR (on a creature or item)

note that DR can be scripted as an effect onto a creature okay, but trying to script it as an itemproperty onto an item seems to be broke.

So id say … it might work in some if not all cases (not sure)

here’s my testeffect debug/console script if yer really curious …

// 'testeffect'
/*
	Pass in "-1" to clear all effects on target.
*/

//
void Tell(string sTell) { SendMessageToPC(GetFirstPC(FALSE), sTell); }

//
string GetEffectString(int iType);


// ___________
// ** MAIN ***
void main(int iType)
{
	object oTarget = GetPlayerCurrentTarget(OBJECT_SELF);
	if (!GetIsObjectValid(oTarget)
		|| GetObjectType(oTarget) != OBJECT_TYPE_CREATURE)
	{
		oTarget = OBJECT_SELF;
	}

	Tell("\nRun ( testeffect ) on " + GetName(oTarget));

	if (iType == -1)
	{
		effect eScan = GetFirstEffect(oTarget);
		while (GetIsEffectValid(eScan))
		{
			Tell(". cleared : " + IntToString(GetEffectType(eScan))
					+ " - " + GetEffectString(GetEffectType(eScan)));

			RemoveEffect(oTarget, eScan);
			eScan = GetFirstEffect(oTarget);
		}
	}
	else
	{
		effect eScan = GetFirstEffect(oTarget);
		if (GetIsEffectValid(eScan))
		{
			while (GetIsEffectValid(eScan))
			{
				if (GetEffectType(eScan) == iType)
				{
					Tell(". Creator : "			+ GetName(GetEffectCreator(eScan)) + " ( "
												+ GetTag(GetEffectCreator(eScan)) + " )");
					Tell(". Type : "			+ IntToString(GetEffectType(eScan)) + " - "
												+ GetEffectString(GetEffectType(eScan)));
					Tell(". Sub Type : "		+ IntToString(GetEffectSubType(eScan)));
					Tell(". Duration Type : "	+ IntToString(GetEffectDurationType(eScan)));
					Tell(". Spell ID : "		+ IntToString(GetEffectSpellId(eScan)));
					Tell(". Integer 0 : "		+ IntToString(GetEffectInteger(eScan, 0)));
					Tell(". Integer 1 : "		+ IntToString(GetEffectInteger(eScan, 1)));
					Tell(". Integer 2 : "		+ IntToString(GetEffectInteger(eScan, 2)));
					Tell(". Integer 3 : "		+ IntToString(GetEffectInteger(eScan, 3)));
					Tell(". Integer 4 : "		+ IntToString(GetEffectInteger(eScan, 4)));
					Tell(". Integer 5 : "		+ IntToString(GetEffectInteger(eScan, 5)));
					Tell(". Integer 6 : "		+ IntToString(GetEffectInteger(eScan, 6)));
					Tell(". Integer 7 : "		+ IntToString(GetEffectInteger(eScan, 7)) + "\n");
				}
				else
				{
					Tell(". found Other Effect : " + IntToString(GetEffectType(eScan)) + " "
												   + GetEffectString(GetEffectType(eScan)));
				}
				eScan = GetNextEffect(oTarget);
			}
		}
		else
		{
			Tell(". no Effects found\n");
		}
	}
}


//
string GetEffectString(int iType)
{
	switch (iType)
	{
		case 0:
			return "EFFECT_TYPE_INVALIDEFFECT";
		case 1:
			return "EFFECT_TYPE_DAMAGE_RESISTANCE";
//		case 2: EFFECT_TYPE_ABILITY_BONUS
		case 3:
			return "EFFECT_TYPE_REGENERATE";
//		case 4: EFFECT_TYPE_SAVING_THROW_BONUS
//		case 5: EFFECT_TYPE_MODIFY_AC
//		case 6: EFFECT_TYPE_ATTACK_BONUS
		case 7:
			return "EFFECT_TYPE_DAMAGE_REDUCTION";
//		case 8: EFFECT_TYPE_DAMAGE_BONUS
		case 9:
			return "EFFECT_TYPE_TEMPORARY_HITPOINTS";
//		case 10: EFFECT_TYPE_DAMAGE_IMMUNITY
		case 11:
			return "EFFECT_TYPE_ENTANGLE";
		case 12:
			return "EFFECT_TYPE_INVULNERABLE";
		case 13:
			return "EFFECT_TYPE_DEAF";
		case 14:
			return "EFFECT_TYPE_RESURRECTION";
		case 15:
			return "EFFECT_TYPE_IMMUNITY";
//		case 16: EFFECT_TYPE_BLIND
		case 17:
			return "EFFECT_TYPE_ENEMY_ATTACK_BONUS";
		case 18:
			return "EFFECT_TYPE_ARCANE_SPELL_FAILURE";
//		case 19: EFFECT_TYPE_MOVEMENT_SPEED
		case 20:
			return "EFFECT_TYPE_AREA_OF_EFFECT";
		case 21:
			return "EFFECT_TYPE_BEAM";
//		case 22: EFFECT_TYPE_SPELL_RESISTANCE
		case 23:
			return "EFFECT_TYPE_CHARMED";
		case 24:
			return "EFFECT_TYPE_CONFUSED";
		case 25:
			return "EFFECT_TYPE_FRIGHTENED";
		case 26:
			return "EFFECT_TYPE_DOMINATED";
		case 27:
			return "EFFECT_TYPE_PARALYZE";
		case 28:
			return "EFFECT_TYPE_DAZED";
		case 29:
			return "EFFECT_TYPE_STUNNED";
		case 30:
			return "EFFECT_TYPE_SLEEP";
		case 31:
			return "EFFECT_TYPE_POISON";
		case 32:
			return "EFFECT_TYPE_DISEASE";
		case 33:
			return "EFFECT_TYPE_CURSE";
		case 34:
			return "EFFECT_TYPE_SILENCE";
		case 35:
			return "EFFECT_TYPE_TURNED";
		case 36:
			return "EFFECT_TYPE_HASTE";
		case 37:
			return "EFFECT_TYPE_SLOW";
		case 38:
			return "EFFECT_TYPE_ABILITY_INCREASE";
		case 39:
			return "EFFECT_TYPE_ABILITY_DECREASE";
		case 40:
			return "EFFECT_TYPE_ATTACK_INCREASE";
		case 41:
			return "EFFECT_TYPE_ATTACK_DECREASE";
		case 42:
			return "EFFECT_TYPE_DAMAGE_INCREASE";
		case 43:
			return "EFFECT_TYPE_DAMAGE_DECREASE";
		case 44:
			return "EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE";
		case 45:
			return "EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE";
		case 46:
			return "EFFECT_TYPE_AC_INCREASE";
		case 47:
			return "EFFECT_TYPE_AC_DECREASE";
		case 48:
			return "EFFECT_TYPE_MOVEMENT_SPEED_INCREASE";
		case 49:
			return "EFFECT_TYPE_MOVEMENT_SPEED_DECREASE";
		case 50:
			return "EFFECT_TYPE_SAVING_THROW_INCREASE";
		case 51:
			return "EFFECT_TYPE_SAVING_THROW_DECREASE";
		case 52:
			return "EFFECT_TYPE_SPELL_RESISTANCE_INCREASE";
		case 53:
			return "EFFECT_TYPE_SPELL_RESISTANCE_DECREASE";
		case 54:
			return "EFFECT_TYPE_SKILL_INCREASE";
		case 55:
			return "EFFECT_TYPE_SKILL_DECREASE";
		case 56:
			return "EFFECT_TYPE_INVISIBILITY";
		case 57:
			return "EFFECT_TYPE_GREATERINVISIBILITY";
		case 58:
			return "EFFECT_TYPE_DARKNESS";
		case 59:
			return "EFFECT_TYPE_DISPELMAGICALL";
		case 60:
			return "EFFECT_TYPE_ELEMENTALSHIELD";
		case 61:
			return "EFFECT_TYPE_NEGATIVELEVEL";
		case 62:
			return "EFFECT_TYPE_POLYMORPH";
		case 63:
			return "EFFECT_TYPE_SANCTUARY";
		case 64:
			return "EFFECT_TYPE_TRUESEEING";
		case 65:
			return "EFFECT_TYPE_SEEINVISIBLE";
		case 66:
			return "EFFECT_TYPE_TIMESTOP";
		case 67:
			return "EFFECT_TYPE_BLINDNESS";
		case 68:
			return "EFFECT_TYPE_SPELLLEVELABSORPTION";
		case 69:
			return "EFFECT_TYPE_DISPELMAGICBEST";
		case 70:
			return "EFFECT_TYPE_ULTRAVISION";
		case 71:
			return "EFFECT_TYPE_MISS_CHANCE";
		case 72:
			return "EFFECT_TYPE_CONCEALMENT";
		case 73:
			return "EFFECT_TYPE_SPELL_IMMUNITY";
		case 74:
			return "EFFECT_TYPE_VISUALEFFECT";
		case 75:
			return "EFFECT_TYPE_DISAPPEARAPPEAR";
		case 76:
			return "EFFECT_TYPE_SWARM";
		case 77:
			return "EFFECT_TYPE_TURN_RESISTANCE_DECREASE";
		case 78:
			return "EFFECT_TYPE_TURN_RESISTANCE_INCREASE";
		case 79:
			return "EFFECT_TYPE_PETRIFY";
		case 80:
			return "EFFECT_TYPE_CUTSCENE_PARALYZE";
		case 81:
			return "EFFECT_TYPE_ETHEREAL";
		case 82:
			return "EFFECT_TYPE_SPELL_FAILURE";
		case 83:
			return "EFFECT_TYPE_CUTSCENEGHOST";
		case 84:
			return "EFFECT_TYPE_CUTSCENEIMMOBILIZE";
		case 85:
			return "EFFECT_TYPE_BARDSONG_SINGING";
		case 86:
			return "EFFECT_TYPE_HIDEOUS_BLOW";
		case 87:
			return "EFFECT_TYPE_NWN2_DEX_ACMOD_DISABLE";
		case 88:
			return "EFFECT_TYPE_DETECTUNDEAD";
		case 89:
			return "EFFECT_TYPE_SHAREDDAMAGE";
		case 90:
			return "EFFECT_TYPE_ASSAYRESISTANCE";
		case 91:
			return "EFFECT_TYPE_DAMAGEOVERTIME";
		case 92:
			return "EFFECT_TYPE_ABSORBDAMAGE";
		case 93:
			return "EFFECT_TYPE_AMORPENALTYINC";
		case 94:
			return "EFFECT_TYPE_DISINTEGRATE";
		case 95:
			return "EFFECT_TYPE_HEAL_ON_ZERO_HP";
		case 96:
			return "EFFECT_TYPE_BREAK_ENCHANTMENT";
		case 97:
			return "EFFECT_TYPE_MESMERIZE";
		case 98:
			return "EFFECT_TYPE_ON_DISPEL";
		case 99:
			return "EFFECT_TYPE_BONUS_HITPOINTS";
		case 100:
			return "EFFECT_TYPE_JARRING";
		case 101:
			return "EFFECT_TYPE_MAX_DAMAGE";
		case 102:
			return "EFFECT_TYPE_WOUNDING";
		case 103:
			return "EFFECT_TYPE_WILDSHAPE";
		case 104:
			return "EFFECT_TYPE_EFFECT_ICON";
		case 105:
			return "EFFECT_TYPE_RESCUE";
		case 106:
			return "EFFECT_TYPE_DETECT_SPIRITS";
		case 107:
			return "EFFECT_TYPE_DAMAGE_REDUCTION_NEGATED";
		case 108:
			return "EFFECT_TYPE_CONCEALMENT_NEGATED";
		case 109:
			return "EFFECT_TYPE_INSANE";
		case 110:
			return "EFFECT_TYPE_HITPOINT_CHANGE_WHEN_DYING";
	}
	return "ERROR : EffectId not found !";
}

That is awesome! I will use that and find out. The Tome of Battle scripted combat system is very similar to what we have in the PRC for NWN1. Problem is, overcoming DR is not even considered by the ToB system. Right now I have it ignoring DR, but that isn’t a good solution.

In our PRC scripted combat system we loop all the IPs (almost all DR are item props on the hide in NWN1) and check for relevant spell effects, and if the weapon should be able to overcome the DR, we pump up physical EffectDamage by an amount adequate to cancel out the DR and let the rest through.

When I look in the NWN2 toolset though, DR appears to be some independent thing (as you indicate, not an IP and not an effect) that exists on the creature. Not to mention it has the extra integer for type now for 3.5 rules. And passing a damage power through EffectDamage still appears to be bugged as it was in NWN1 and it won’t overcome DR.

1 Like

hides are bugged in nwn2 /lol

they shouldn’t be equipped on PCs/Companions … because if the weapon/shield is swapped in/out multiple times the ACP (iirc) goes totally wonky. But they’re fine on NPCs/mobs who don’t do much if any weapon switching

(ill try to find the thread about it)

re. DR
the 2nd value changed from what the DR protects against to what pierces the DR … (unless im totally wonk on that)

probably ;) u really have to test things in nwn2, my advice is to take next to nothing for granted

I’ve never played around with the damagepower parameter. But a trick to get physical damage (not sure if you know this) is to sum the physical type bits →

int iDamageType = DAMAGE_TYPE_BLUDGEONING | DAMAGE_TYPE_PIERCING | DAMAGE_TYPE_SLASHING;

that is, don’t use

int DAMAGE_TYPE_ALL = 0; // AFW-OEI 06/07/2007: Deprecated. May function correctly for EffectDamage(); results are undefined for EffectDamageImmunity() and EffectDamageResistance().

May function correctly … wtf

1 Like

The 4th integer is now what type of DR it is. So material, damage type, magical, epic, etc. The 2nd integer is still what pierces it, this is the same at NWN1, but it will look at a different set of values depending on what the 4th integer is. So if 4th param says material, 2nd param could be the value for a specific material, if 4th is magical, 2nd will work just like NWN1/3.0 rules.

At least that is what the entry in nwscript for NWN2 indicates. My own testing hasn’t been able to confirm that. Or even if you can grab DRs as effects and use GetEffectInteger on them.

For combining the damage types, can you actually pass that to EffectDamage as you wrote it with all those pipes in there?

yes it’s a legal bitwise operation

int iDamageType = DAMAGE_TYPE_BLUDGEONING | DAMAGE_TYPE_PIERCING | DAMAGE_TYPE_SLASHING;
iDamageType = 1 + 2 + 4;
iDamageType = 7;

So u could just use 7 but the constants make it explicit

It fixed an issue i was having with EffectDamageIncrease() and have seen it mentioned in notes of the stock scripts, so that’s what i go with …

// since DAMAGE_TYPE_ALL does not work in EffectDamageIncrease()
// try this ->
const int DAMAGE_TYPE_PHYSICAL = DAMAGE_TYPE_BLUDGEONING
							   | DAMAGE_TYPE_PIERCING
							   | DAMAGE_TYPE_SLASHING;
2 Likes

Wow that is handy. I add all three physical types, grab the type of the weapon, then do EffectDamage in that type. That is much more efficient.

1 Like

Maybe …

Or …

Bottom line: Skins/Hides for PCs do not work.

2 Likes

yes. and I believe there may be one more thread where i reproduced the bug :)

1 Like

@Lance_Botelle,

I read your comments related to skill increases effects leaving icons you didn’t want shown:

Thankfully, many of the ideas I had that involved using a skin can now be coded using new functions allowing us to directly alter attributes. One aspect that did still need consideration, however, was if a new feat altered a PC’s skills in some way. The problem is that while it is possible to alter PCs skills directly, the same process leaves small icons showing the changes as spell effects, which is not wanted.

I was able to remove the icons with the following code, you just need to find the icon number for skill increase:

        eSpellResistance = EffectSpellResistanceIncrease(maxItemSpellResistance);
        eSpellResistance = SupernaturalEffect(eSpellResistance);
        eSpellResistance = SetEffectSpellId(eSpellResistance, HENCH_SPELL_RESISTANCE_SPELL_ID);
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSpellResistance, oTarget);
        // get rid of icon
		effect eIcon = EffectEffectIcon(41);	// spell resistance increase
		ApplyEffectToObject(DURATION_TYPE_INSTANT, eIcon, oTarget);
		RemoveEffect(oTarget, eIcon);

1 Like

@TonyK

what if the character has a SpellResistanceIncrease effect (eg) already, for which the icon should show to the player? Wouldn’t that code (potentially) remove a legit icon ?

1 Like