Creature damage immunity

Alright here I am again!

So as I am working on this quest I wonder the following if something like this could be achieved and if anyone might already have a script for this?

So basically there is this creature that spawns when the player enters a room the creature will be invulnerable for every kind of damage unless the players got an item in their inventory.

thank you in advance <3

This compiles in NWN2 at least. If you put this on OnHeartbeat of the NPC:

void PrepForDestruction(object oNPC)
{
	SetPlotFlag(oNPC,FALSE);
    SetImmortal(oNPC,FALSE);
    AssignCommand(oNPC,SetIsDestroyable(TRUE,FALSE,FALSE));
}

void MakeImmortal(object oNPC)
{
	SetPlotFlag(oNPC,TRUE);
    SetImmortal(oNPC,TRUE);
    AssignCommand(oNPC,SetIsDestroyable(FALSE,FALSE,FALSE));
}


void main()
{

object oPC = GetFirstPC();
object oNPC = OBJECT_SELF;

object oItem = GetObjectByTag("item");

int PcHasTheItem = FALSE;

	if (GetIsObjectValid(GetItemPossessedBy(oPC,"item")))
	{
		PcHasTheItem = TRUE;
	}	

	if (!PcHasTheItem)
	{
		MakeImmortal(oNPC);
		return;
	}

	if(PcHasTheItem)
	{
	
	PrepForDestruction(oNPC);
	
	}
		
}

Make sure the NPC is immortal at the start when it spawns, I guess.

Edit: I tested my script and it worked in NWN2 at least.

Will the item remove ALL immunities? Or will it only make the creature vulnerable to a certain type/certain types/a random type/random types of damage? Is it enough to have that item in the inventory or will the PC(s) have to use it?

I don’t have much time right now, but you can set Plot flags (indestructible, creature might not attack, though), Immortal flags (creature can’t die and stays at 1 HP) or item properties (like of the creature skin or an undroppable item the creature has, not sure you can be immune to Ki damage, though) via script.

You also can check the OC chapter 3. While they weren’t exactly invulnerable, there were those guardian golems which became vulnerable to one type of damage when you talked to the slaves building them. Maybe there is something close enough to what you need.

Hopefully someone will be able to help you. If not, I’ll open the toolset and check a few things later when I have more time.

1 Like

@Dragonqueeny Maybe you could put my script on the creature’s OnSpawn as well as on its OnHeartbeat. That way the script should check when it is spawned if the PC has the item to make it mortal, and then the script checks every 6 seconds if the PC has the item or not.

1 Like

While setting creature as plot is one way to do it, I recommend against it. Immortal flag is indeed better here (in communication at least).

Rationale: players may be confused why they cannot damage the target and may assume there is something wrong with the module (i.e. builder forgot to clear the plot status when combat started). They will also see incorrect messages, such as the target being immune to critical hits when it isn’t, etc.

I suggest making the creature immortal in toolset or OnSpawn, then check in its OnDamage whether the attacker has the specific item:

  • no item - full heal
  • item - turn immortality off

This has the benefit of being applied when the hit lands and allows the creature to play VFX and taunt the attacker.

Give PC an emerald to “dispel” the “invulnerability” permanently:

// OnDamage
void main()
{
    object oDamager = GetLastDamager();

    // I am immortal (set this flag to on elsewhere, i.e. on spawn)
    if(GetImmortal())
    {
        // but attacker got the item (item is not consumed)
        if(GetIsObjectValid(GetItemPossessedBy(
            oDamager, "NW_IT_GEM012"))) // emerald
        {
            SpeakString("I am now vulnerable!");
            SetImmortal(OBJECT_SELF, FALSE);
        }
        else
        {
            // or maybe not
            SpeakString("You cannot hurt me!");
            ApplyEffectToObject(DURATION_TYPE_INSTANT,
                EffectHeal(GetMaxHitPoints()),
                OBJECT_SELF);
            ApplyEffectToObject(DURATION_TYPE_INSTANT,
                EffectVisualEffect(VFX_IMP_MAGIC_PROTECTION),
                OBJECT_SELF);
        }
    }

    // execute default script now
    ExecuteScript("nw_c2_default6", OBJECT_SELF);
}

You may need to duplicate this code for OnSpellCastAt.

If you need however the creature to become invulnerable again, try this instead:

// OnDamage
void main()
{
    object oDamager = GetLastDamager();
    int iDamage = GetTotalDamageDealt();

    // attacker got the item (item is not consumed)
    if(GetIsObjectValid(GetItemPossessedBy(oDamager, "NW_IT_GEM012")))
    {
        SpeakString("I am vulnerable!");
        SetImmortal(OBJECT_SELF, FALSE);
        DelayCommand(0.0, SetImmortal(OBJECT_SELF, TRUE));
    }
    else
    {
        // attacker has no item
        SpeakString("You cannot hurt me!");
        ApplyEffectToObject(DURATION_TYPE_INSTANT,
            EffectHeal(iDamage),
            OBJECT_SELF);
        ApplyEffectToObject(DURATION_TYPE_INSTANT,
            EffectVisualEffect(VFX_IMP_MAGIC_PROTECTION),
            OBJECT_SELF);
    }

    // execute default script now
    ExecuteScript("nw_c2_default6", OBJECT_SELF);
}

The trick here is to re-enable immortality right after damage is dealt, so only those who carry the emerald can actually hurt the creature. Or if you prefer - it will absorb their damage and convert it into HP.

3 Likes

Even though I actually think that my solution works too, @NWShacker’s solution is more neat, so I would suggest you use his.

1 Like

Thanks everyone for all this insight and help! <3

1 Like