NPC Gives Up Script

Hey guys, I’ve looked through Script Gens and the Archive but I can’t seem to find information on how to make an NPC give up when it’s about to be killed. Advice? Thank you!

You can use the built-in SurrenderToEnemies function. Call it in OnDamaged when HP drops below a certain level. Making the creature immortal is also a good idea to prevent it from actually dying.

1 Like

That’s right. Despite the comments in the Lexicon, SurrenderToEnemies seems to be permanent and affects all enemies, including associates. The code I use is

  object oNPC   = OBJECT_SELF;

  SurrenderToEnemies();
  ForceRest(oNPC);                            // Cancels spells in progress (and fully restores NPC)
  AssignCommand(oPC, ClearAllActions(TRUE));  // Ensures PC can talk - conversation should be delayed by (say) 0.5 sec to allow this to take effect
2 Likes

Thank you both!

if((GetIsDead(OBJECT_SELF) == FALSE) && (nCurrHP <= 30) && GetLocalInt(OBJECT_SELF,“Generic_Surrender”) == 0)

Sorry I’m not sure where I’d list the HP marker. Trying to use the OC as an example but as I was told, it’s a bit of a mess. This is, “if not dead and HP at 30 get self and set a surrender variable at 0.” Are they just doing that for the dialogue tree?

The typical protocol (also used by OC) is as follows:

  1. NPC is set as immortal
  2. NPC talks and goes agro
  3. NPC gets beaten up by PC
  4. NPC surrenders (handled by its OnDamaged)
  5. NPC talks to PC, possibly going agro again (when it fights to death)

Variable you’re seeing in that snippet from OC (which has a bug by the way - classy BW) is set at stage 3 to ensure that specific (post-battle) dialogue tree is entered at stage 4.

Assuming you’re trying to achieve this, put this script as NPC’s OnDamaged script.

Click me.
// surrender at this fraction of HP (0 - 1)
const float  SURRENDER_HP_FRACTION = 0.1;
// surrender dialogue variable
const string SURRENDER_VARIABLE    = "i_give_up";

// OnDamaged event script
void main()
{
    float fCurHP = IntToFloat(GetCurrentHitPoints());
    float fMaxHP = IntToFloat(GetMaxHitPoints());
    object oPC;

    if(fCurHP / fMaxHP <= SURRENDER_HP_FRACTION &&
        !GetLocalInt(OBJECT_SELF, SURRENDER_VARIABLE))
    {
        SetLocalInt(OBJECT_SELF, SURRENDER_VARIABLE, TRUE);
        SurrenderToEnemies();
        oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
        ClearAllActions(TRUE);
        AssignCommand(oPC, ClearAllActions(TRUE));
        ActionStartConversation(oPC);
        return;
    }

    ExecuteScript("nw_c2_default6", OBJECT_SELF);
}
2 Likes

Got it working, thanks again!

Just for accuracy what that code snippet actually says in English is -

If the calling object is NOT dead AND it’s current hitpoints are 30 OR less AND
the local variable “Generic_Surrender” set on the calling object is Zero/FALSE,
do the code that follows.

It could be written slightly less complicated like -

    if(!GetIsDead(OBJECT_SELF) && (nCurrHP < 31) && !GetLocalInt(OBJECT_SELF, “Generic_Surrender”))

TR

1 Like

This seems to be correct.

Lexicon also states that the 10 meter distance from function’s description is outdated. It says the value is now 50 m. I made a quick check and it seems to be 45.5 m (Lexicon says 54.5, which I guess is a typo).

The experiment

This is indeed way beyond anyone’s vision range, but may be not enough if there are mobile creatures in the area. Making a NPC neutral towards everyone in such area isn’t a big problem though.

2 Likes