Author Topic: Check for invisibility on entire party?  (Read 466 times)

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Check for invisibility on entire party?
« on: November 10, 2011, 02:49:34 am »


               I've searched NWN Omnibus for such a script but could not find one.

I'm looking for a script that will see if the player and/or all members of the party - ASSOCIATE_TYPE_ANIMALCOMPANION, ASSOCIATE_TYPE_DOMINATED, ASSOCIATE_TYPE_FAMILIAR, ASSOCIATE_TYPE_HENCHMAN and ASSOCIATE_TYPE_SUMMONED - are invisible.

This is a requirement for sneaking through a particular section and if the player and all associated members of the party are also invisible, they can get past without triggering conversations or particular events.

Now I've fiddled with a few scripts on my own, attempting to put something together, which I'll post below but if there's an easier way to check I'd like to hear it and also get some help in putting it to working order.

#1 is a conditional script for conversations. In this case, when the player clicks on the NPCs that they would need to sneak past, the NPC should detect no one. Currently, I have it working with the NPC only but the problem is, it works even when other party members are NOT invisible - the NPCs conversation line just fires a random "Huh? Is someone there?" type of line when the PC is has either spell applied (#3 below I hope will solve all party members).

int StartingConditional()
{

object oPC = GetFirstPC();

// CHECKING FOR INVISIBILITY SPELLS
object oAC = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
object oD = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
object oF = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
object oH = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC);
object oS = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);

if  (! (GetHasSpellEffect(SPELL_INVISIBILITY, oPC)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oPC)) ) return FALSE;

    return TRUE;
}


#2 is a variation of the above script, used for a trigger that would fire an event if the player and/or party is not invisible.

void main()
{

object oPC = GetFirstPC();

object oAC = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
object oD = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
object oF = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
object oH = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC);
object oS = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);

if (

     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oPC)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oPC)) ) &&
     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oAC)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oAC)) ) &&
     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oD)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oD)) ) &&
     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oF)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oF)) ) &&
     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oH)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oH)) ) &&
     ( (GetHasSpellEffect(SPELL_INVISIBILITY, oS)) || (GetHasSpellEffect(SPELL_INVISIBILITY_SPHERE, oS)) ) )
     {
     AssignCommand(GetObjectByTag("250B10_NPC3"), SpeakString("Keep a sharp eye for anything out of the ordinary!"));
    
     return;
     }
else
{
// OTHER EVENTS - PARTY SPOTTED
}
}


#3 is simply a revision of #1, using the Bioware InvisibleTrue function that comes with the "nw_i0_generic" include.

#include "nw_i0_generic"

int StartingConditional()
{

    object oPC = GetPCSpeaker();

    object oAC = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
    object oD = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
    object oF = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
    object oH = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC);
    object oS = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);

    int nPC = InvisibleTrue(oPC);
    int nAnimalCompanion = InvisibleTrue(oAC);
    int nDominated = InvisibleTrue(oD);
    int nFamiliar = InvisibleTrue(oF);
    int nHenchman = InvisibleTrue(oH);
    int nSummoned = InvisibleTrue(oS);


    if ( (nPC == TRUE) &&
         (nAnimalCompanion == TRUE) &&
         (nDominated == TRUE) &&
         (nFamiliar == TRUE) &&
         (nHenchman == TRUE) &&
         (nSummoned == TRUE)) return TRUE;

    return FALSE;
}


Is there an easier way to do this or a function already that was written by Bioware that such scripts are not required?

I suppose I'd like to go the route of using the InvisibleTrue function as it supports - EFFECT_TYPE_INVISIBILITY/IMPROVED, STEALTH, SANCTUARY and ETHEREAL

FP!
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #1 on: November 10, 2011, 03:08:39 am »


               you can try either this snippet:

            object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT, SPELL_TRUE_SEEING);
            if(!GetIsObjectValid(oSeeMe))
            {
                oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT, SPELL_SEE_INVISIBILITY);
}

or more elaborated way

int InvisibleTrue(object oSelf =OBJECT_SELF, int bTestPerception = FALSE)
{
 if(GetHasEffect(EFFECT_TYPE_ETHEREAL, oSelf) || GetActionMode(oSelf, ACTION_MODE_STEALTH))
 {
 return TRUE;
 }
 else if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oSelf) || GetHasEffect(EFFECT_TYPE_IMPROVEDINVISIBILITY, oSelf) || GetHasEffect(EFFECT_TYPE_SANCTUARY, oSelf) ||
 (GetHasSpellEffect(SPELL_DARKNESS, oSelf) && (GetHasSpellEffect(SPELL_DARKVISION, oSelf) || GetHasSpellEffect(SPELL_TRUE_SEEING, oSelf))))
 {
  if(!bTestPerception)
  {
  return TRUE;
  }
 int nTh = 1;
 object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oSelf, nTh, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
  while(oSeeMe != OBJECT_INVALID)
  {
   if(GetObjectSeen(oSelf,oSeeMe))
   {
   return FALSE;
   }
  oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oSelf, ++nTh, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
  }
 return TRUE;
 }
return FALSE;
}

I changed the InvisibleTrue function for AI purposes, should also fit yours
               
               

               


                     Modifié par ShaDoOoW, 12 novembre 2011 - 01:25 .
                     
                  


            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #2 on: November 11, 2011, 02:03:13 am »


               Thanks! Will give a whirl and test these out.

FP!
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #3 on: November 12, 2011, 12:09:10 am »


               Tested this out.

The first script compiles but I can't get it to work.

Here are the variations I've tried to get it working.

Spell cast is Improved Invisibility. Entire party is INVISIBLE when examining them.

Spell cast is Invisibility. Only the player is INVISIBLE.

Lines highlighted for script differences.

Does not work - Invisibility/Improved invisibility or not

// FAILS : NPC does nothing
void main()
{

object oPC = GetEnteringObject();
object oNPC = GetNearestObjectByTag( "250B4_NPC02", oPC);

object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1,
                                  CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT,
                                  SPELL_TRUE_SEEING);

effect eFreeze = EffectCutsceneImmobilize();

if( !GetIsPC( oPC)) return;

if(!GetIsObjectValid(oSeeMe))
{

oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION,
                            REPUTATION_TYPE_ENEMY,
                            OBJECT_SELF,
                            1,
                            CREATURE_TYPE_PERCEPTION,
                            PERCEPTION_SEEN,
                            CREATURE_TYPE_HAS_SPELL_EFFECT,
                            SPELL_SEE_INVISIBILITY);

} return;


AssignCommand( oNPC, SpeakString("DEBUG: I SEE YOU!"));

SetLocalInt(GetFirstPC(), "b250b4", 1);

AssignCommand( oPC, ClearAllActions( TRUE));
AssignCommand( oPC, ActionDoCommand( SetCommandable( TRUE, oPC)));
AssignCommand( oPC, ActionDoCommand(ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFreeze, oPC, 15.0)));
AssignCommand( oNPC, ClearAllActions( TRUE ));
AssignCommand( oNPC, ActionForceMoveToObject( oPC, FALSE));
AssignCommand( oNPC, ActionStartConversation( oPC));
AssignCommand( oPC, SetCommandable( FALSE, oPC));

}


Does not work - Invisibility/Improved or not

// FAILS : NPC does nothing
void main()
{

object oPC = GetEnteringObject();
object oNPC = GetNearestObjectByTag( "250B4_NPC02", oPC);

object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1,
                                  CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_HAS_SPELL_EFFECT,
                                  SPELL_TRUE_SEEING);

effect eFreeze = EffectCutsceneImmobilize();

if( !GetIsPC( oPC)) return;

if(GetIsObjectValid(oSeeMe))
{

oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION,
                            REPUTATION_TYPE_ENEMY,
                            OBJECT_SELF,
                            1,
                            CREATURE_TYPE_PERCEPTION,
                            PERCEPTION_SEEN,
                            CREATURE_TYPE_HAS_SPELL_EFFECT,
                            SPELL_SEE_INVISIBILITY);

} return;

AssignCommand( oNPC, SpeakString("DEBUG: I SEE YOU!"));

SetLocalInt(GetFirstPC(), "b250b4", 1);

AssignCommand( oPC, ClearAllActions( TRUE));
AssignCommand( oPC, ActionDoCommand( SetCommandable( TRUE, oPC)));
AssignCommand( oPC, ActionDoCommand(ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFreeze, oPC, 15.0)));
AssignCommand( oNPC, ClearAllActions( TRUE ));
AssignCommand( oNPC, ActionForceMoveToObject( oPC, FALSE));
AssignCommand( oNPC, ActionStartConversation( oPC));
AssignCommand( oPC, SetCommandable( FALSE, oPC));

}


When I remove the following:

if(!GetIsObjectValid(oSeeMe))
{

 oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION,
                             REPUTATION_TYPE_ENEMY,
                             OBJECT_SELF,
                             1,
                             CREATURE_TYPE_PERCEPTION,
                             PERCEPTION_SEEN,
                             CREATURE_TYPE_HAS_SPELL_EFFECT,
                             SPELL_SEE_INVISIBILITY);

} return;


The NPC fires the DEBUG line.

The second script does not compile.
- ERROR: FUNCTION IMPLEMENTATION AND DEFINTITION DIFFER

FP!
               
               

               


                     Modifié par Fester Pot, 12 novembre 2011 - 12:23 .
                     
                  


            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #4 on: November 12, 2011, 12:52:26 am »


               I see, I havent posted exactly what you needed. The first snippet code I sent you is meant to be used on a creature that "ask, can anyone see me?". So since its used somewhere else you have to rewrite it. Also the snippet checks for creature's enemy. But if the creature in question is not hostile, this wont work again. So the snipped code I sent was more or less useless. Sorry about that '<img'>.

This should work

void main()
{
object oPC = GetEnteringObject();
 if(!GetIsPC( oPC)) return;
object oNPC = GetNearestObjectByTag( "250B4_NPC02", oPC);

object oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oNPC, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
 if(!GetIsObjectValid(oSeeMe))
 {
 //once again if they are not hostile                                  //now looking for neutrals
 oSeeMe = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_NEUTRAL, oNPC, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
  if(!GetIsObjectValid(oSeeMe))
  {
  return;
  }
 }
effect eFreeze = EffectCutsceneImmobilize();
AssignCommand( oNPC, SpeakString("DEBUG: I SEE YOU!"));

SetLocalInt(GetFirstPC(), "b250b4", 1);

AssignCommand( oPC, ClearAllActions( TRUE));
AssignCommand( oPC, ActionDoCommand( SetCommandable( TRUE, oPC)));
AssignCommand( oPC, ActionDoCommand(ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFreeze, oPC, 15.0)));
AssignCommand( oNPC, ClearAllActions( TRUE ));
AssignCommand( oNPC, ActionForceMoveToObject( oPC, FALSE));
AssignCommand( oNPC, ActionStartConversation( oPC));
AssignCommand( oPC, SetCommandable( FALSE, oPC));
}


for #2 this should work

#include "nw_i0_generic"

void main()
{
object oTrigger = OBJECT_SELF;
object oPC = GetEnteringObject();//its in the trigger right?
object oMember = GetFirstFactionMember(oPC,FALSE);
 while(oMember != OBJECT_INVALID)
 {
  if(!InvisibleTrue(oMember))
  {
  //someone is not invisible
  //do something
  return;
  }
 oMember = GetNextFactionMember(oPC,FALSE);
 }
}


Your second script cannot be compiled because if you put function I sent you you also had the old implementation from include. Remove the include and it will work but for your purpose you dont need my new InvisibleTrue function. I rewritten it to fix one issue in AI where creature already invisible ignored fact that their target could seen them. So the function now has two possible uses depending on second value. If TRUE it also checks whether there is anyone who can see me and in that case function returns FALSE (its like the childs idea that when you close eyes nobody can't see you haha). But in certain cases when you want just to know if you have an invisibility effect on you, using the functuin with parametr FALSE wont check this.
               
               

               
            

Legacy_Fester Pot

  • Hero Member
  • *****
  • Posts: 1698
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #5 on: November 12, 2011, 01:13:36 am »


               Thanks for your help and patience ShaDoOoW. Your second solution scripts worked like a charm.

FP!
               
               

               
            

Legacy_Axe_Murderer

  • Full Member
  • ***
  • Posts: 199
  • Karma: +0/-0
Check for invisibility on entire party?
« Reply #6 on: November 14, 2011, 04:39:14 pm »


               Alternative approach is to spawn in or pre-place an invisible non-hostile critter(s) and use its (their) perception script to determine if anybody in the party gets visually spotted. Probably significantly less CPU intensive than all those loops and effect checks on the party.