Author Topic: NPC Activities - nGNBDisabled has no effect - bug?  (Read 391 times)

Legacy_belisarius

  • Newbie
  • *
  • Posts: 18
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« on: January 29, 2015, 03:31:05 am »


               

Hey guys,


 


I've been using the NPC Activities scripts, very useful, can't thank Deva Winblood and Qlippoth enough!


 


The 6.1 Documentation tells me I can turn OFF NPC activities for an NPC as follows:


 


 


 


Here is the basic anatomy of a script that disables NPC ACTIVITIES and then enables it when it is done doing its actions: Script is in standard text while my


comments about the script are in Orange.


 


void main()


{


SetLocalInt(OBJECT_SELF,”nGNBDisabled”,TRUE);


This line disables NPC ACTIVITIES so, its anti-stuck behavior will


not interfere with your script. NOTE: It is important that you put


fail safes in place to turn this back to FALSE. If anything goes wrong


in your script or you fail to set this back to FALSE then this NPC


will just stand there and do nothing of interest from this point on.


Put all your own script code here


You will need to handle everything you want done here. Though some


include files to help you will be provided to help you.


SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE);


Like I indicated it is important that this happen. In fact as a fail safe if you


know the maximum amount of time this script should take and say it is no


more than 20 seconds. You should put this line as the first line before


disabling it just as a fail safe. This is in addition to this last line. They


will not interfere with each other and this last line will cause NPC


ACTIVITIES to kick back in as quickly as possible. However, if for some


reason it never makes it to this last line then use this as your first line as a


backup.


DelayCommand(20.0,SetLocalInt(OBJECT_SELF,”nGNBDisabled”,


FALSE));


This can save your script from locking up the NPC completely.


}


 


So, if I were to provide you of say a script called anvilpounder that could be


called using the @script this is what it might look like:



void main()
{
DelayCommand(30.0,SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE));
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,TRUE);
object oAnvil=GetNearestObjectByTag(“Anvil”);
ActionMoveToObject(oAnvil);
ActionAttack(oAnvil,TRUE);
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE);
}

In this example I placed the fail safe as the first line. If within 30 seconds this script has not completed its course it will enable NPC ACTIVITIES again. So, at that point if the NPC is in fact stuck then the anti-stuck code can kick in. An example of why


this might happen is if the NPC does indeed find an Anvil but, they cannot get to it for some reason or it is taking much longer than 30 seconds. You definitely would not want your NPC to perpetually try to get to that anvil and forsake everything else.


I hope this explains it. If you were to save the above script right now as anvilpounder. You could then put @anvilpounder anywhere in your waypoint and it


will work and can be used by any NPC with no further scripting. In fact, at this point


you have made a script that a NON-SCRIPTER can use.


 


 


 


 


 


 


 


But every attempt to turn on nGNBDisabled in my module results in the NPC pausing briefly and then continuing on his merry NPC Activities way. I'm not even sure if the NPC actually pauses.


 


This is very critical to my module, as I DM it, and often need to make an NPC stop for a while to interact with the PCs.


I thought there might be something I was doing wrong, so I created an item called "nGNBDisabled", gave it Cast Spell Unique Power and a script with the same name, as follows:



//::///////////////////////////////////////////////
//:: Example Item Event Script
//:: x2_it_example
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
    This is an example of how to use the
    new default module events for NWN to
    have all code concerning one item in
    a single file.

    Note that this system only works if
    the following scripts are set in your
    module events

    OnEquip      - x2_mod_def_equ
    OnUnEquip    - x2_mod_def_unequ
    OnAcquire    - x2_mod_def_aqu
    OnUnAcqucire - x2_mod_def_unaqu
    OnActivate   - x2_mod_def_act
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: 2003-09-10
//:: Modified By: Grimlar
//:: Modified On: March 2004
//:://////////////////////////////////////////////

#include "x2_inc_switches"

void main()
{
    int nEvent = GetUserDefinedItemEventNumber();    //Which event triggered this
    object oPC;                                                           //The player character using the item
    object oItem;                                                        //The item being used
    object oSpellOrigin;                                               //The origin of the spell
    object oSpellTarget;                                              //The target of the spell
    int iSpell;                                                             //The Spell ID number

    //Set the return value for the item event script
    // * X2_EXECUTE_SCRIPT_CONTINUE - continue calling script after executed script is done
    // * X2_EXECUTE_SCRIPT_END - end calling script after executed script is done
    int nResult = X2_EXECUTE_SCRIPT_END;

    switch (nEvent)
    {
        case X2_ITEM_EVENT_ONHITCAST:
            // * This code runs when the item has the 'OnHitCastSpell: Unique power' property
            // * and it hits a target(if it is a weapon) or is being hit (if it is a piece of armor)
            // * Note that this event fires for non PC creatures as well.

            oItem  =  GetSpellCastItem();               // The item triggering this spellscript
            oPC = OBJECT_SELF;                            // The player triggering it
            oSpellOrigin = OBJECT_SELF ;               // Where the spell came from
            oSpellTarget = GetSpellTargetObject();  // What the spell is aimed at

            //Your code goes here
            break;

        case X2_ITEM_EVENT_ACTIVATE:
// * This code runs when the Unique Power property of the item is used or the item
// * is activated. Note that this event fires for PCs only
        {

            oPC   = GetItemActivator();                 // The player who activated the item
            oItem = GetItemActivated();               // The item that was activated
            object oTarget = GetItemActivatedTarget();

            int nGNBDisabled = GetLocalInt(oTarget,"nGNBDisabled");
            FloatingTextStringOnCreature("nGNBDisabled is " +IntToString(GetLocalInt(oTarget,"nGNBDisabled")),oTarget, TRUE);
            SendMessageToAllDMs("nGNBDisabled is " +IntToString(GetLocalInt(oTarget,"nGNBDisabled")));

            if (nGNBDisabled == TRUE) SetLocalInt(oTarget,"nGNBDisabled",FALSE);
            else if (nGNBDisabled == FALSE) SetLocalInt(oTarget,"nGNBDisabled",TRUE) ;

            FloatingTextStringOnCreature("nGNBDisabled is " +IntToString(GetLocalInt(oTarget,"nGNBDisabled")),oTarget, TRUE);
            SendMessageToAllDMs("nGNBDisabled is " +IntToString(GetLocalInt(oTarget,"nGNBDisabled")));


            break;

        }
        case X2_ITEM_EVENT_EQUIP:
            // * This code runs when the item is equipped
            // * Note that this event fires for PCs only

            oPC = GetPCItemLastEquippedBy();        // The player who equipped the item
            oItem = GetPCItemLastEquipped();         // The item that was equipped

            //Your code goes here
            break;

        case X2_ITEM_EVENT_UNEQUIP:
            // * This code runs when the item is unequipped
            // * Note that this event fires for PCs only

            oPC    = GetPCItemLastUnequippedBy();   // The player who unequipped the item
            oItem  = GetPCItemLastUnequipped();      // The item that was unequipped

            //Your code goes here
            break;

        case X2_ITEM_EVENT_ACQUIRE:
            // * This code runs when the item is acquired
            // * Note that this event fires for PCs only

            oPC = GetModuleItemAcquiredBy();        // The player who acquired the item
            oItem  = GetModuleItemAcquired();        // The item that was acquired

            //Your code goes here
            break;

        case X2_ITEM_EVENT_UNACQUIRE:

            // * This code runs when the item is unacquired
            // * Note that this event fires for PCs only

            oPC = GetModuleItemLostBy();            // The player who dropped the item
            oItem  = GetModuleItemLost();            // The item that was dropped

            //Your code goes here
            break;

       case X2_ITEM_EVENT_SPELLCAST_AT:
            //* This code runs when a PC or DM casts a spell from one of the
            //* standard spellbooks on the item

            oPC = OBJECT_SELF;                          // The player who cast the spell
            oItem  = GetSpellTargetObject();        // The item targeted by the spell
            iSpell = GetSpellId();                         // The id of the spell that was cast
                                                                    // See the list of SPELL_* constants

            //Your code goes here

            //Change the following line from X2_EXECUTE_SCRIPT_CONTINUE to
            //X2_EXECUTE_SCRIPT_END if you want to prevent the spell that was
            //cast on the item from taking effect
            nResult = X2_EXECUTE_SCRIPT_CONTINUE;
            break;
    }

    //Pass the return value back to the calling script
    SetExecutedScriptReturnValue(nResult);
}


As you can see, all my script does is flip the nGNBDisabled integer, and inform the DM of the change.


It works. But has no effect on my NPCs, who ignore nGNBDisabled, and keep doing their own thing.


 


 


 


Okay, maybe something wrong with my module, I thought.


 


 


So I opened Deva Winblood's version 6.0 demo module, and added my item and my script. Tested that. Nope, the NPCs ignore the nGNBDisabled integer, and keep doing their own thing.


 


Maybe the bug was fixed in a later version, I thought.


 


Imported the v6.1 scripts into the 6.0 demo module. Tested that. Nope, the NPCs ignore the nGNBDisabled integer, and keep doing their own thing.


 


Opened Quippoth's v6.2 Pathways Demo. Added my script and my item. Nope, the NPCs ignore the nGNBDisabled integer, and keep doing their own thing. ARRRRRGGGGGHHHHH...!


I've looked through the code, but haven't found a solution. The NPC Activities code does check for the nGNBDisabled integer, but some "anti-stuck" code, somewhere, is overruling it, I believe.


 


Has anyone else come up against this problem? How do you turn off NPC Activities for an NPC - and have it stay off?


 


NPC Activities: http://neverwinterva...ies-62-pathways



               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« Reply #1 on: January 29, 2015, 04:52:08 am »


               


void main()
{
DelayCommand(30.0,SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE));
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,TRUE);
object oAnvil=GetNearestObjectByTag(“Anvil”);
ActionMoveToObject(oAnvil);
ActionAttack(oAnvil,TRUE);
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE);
}


 

Where is Axe when you need him!!!   He is much better at explaining this then I am.   

 

The script above shows a basic misunderstanding of the difference between Actions and Commands.  

 

Commands get executed right away,  unless they are placed into a Que.

 

Actions always  get placed into a Que and have there execution delayed untill it is there turn. ( well the ActionJump is an exception, because it is added to the top of the Que instead of the bottom.)

 

You can add a command to a creatures action Que by using the ActionDoCommand function.   

 

 

Your script is basically

 



 //Setting the local into to TRUE 
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,TRUE);

//Placing to actions into the ActionQue of OBJECT_SELF
ActionMoveToObject(oAnvil);
ActionAttack(oAnvil,TRUE);    

//And then setting  the local to FALSE before the actions have a chance to happen.
SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE);

 

 

What you want to do is add that last SetLocalInt CommandTo the Que so that it waits it turn to execute. You can do that using the ActionDoCommand function.


ie.

ActionDoCommand( SetLocalInt(OBJECT_SELF,”nGNBDisabled”,FALSE));



               
               

               
            

Legacy_belisarius

  • Newbie
  • *
  • Posts: 18
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« Reply #2 on: January 29, 2015, 06:30:33 am »


               

You're absolutely right about action queues, Lightfoot8. That's the demo code by Deva Winblood, the original author of NPC Activities. I believe he is using the DelayCommand command outside the Action queue as a failsafe - if ClearAllActions is called at some point, at least the DelayCommand will still trigger in time and reset the integer.



My script, further down the OP, sets nGNBDisabled to TRUE (or FALSE) immediately, and doesn't reset it. NPCs targetted by the script are having their nGNBDisabled integer set correctly - and the script reads the value back to all DMs. But NPCs then continue to walk to new waypoints, add new actions to their action queues, proceed to the next waypoint etc. etc. ad infinitum.


That shouldn't be happening! nGNBDisabled is being overruled somewhere by some very DM-unfriendly and undocumented code :-(


Will be great if Qlippoth or someone equally familiar with NPC Activities reads this - I hope there is a simple fix, a switch to override the undocumented override or something...



               
               

               
            

Legacy_Pstemarie

  • Hero Member
  • *****
  • Posts: 4368
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« Reply #3 on: January 29, 2015, 11:04:58 am »


               

Have you tried to search all the NPC Activities script for that variable name. IF its value is being overridden somewhere, then you'll find a call to set the value somewhere else. It may even be a case where the variable is using both its const name to set the value and its actual name. To explain better...


 


I have seen scripts where authors began with just a straight up variable call. For example - SetLocalInt(oObject, "SOME_VARIABLE"); At some point they decided to start using constants and so created a constant for each of their variable names. For example - "SOME_VARIABLE" became const int SOME_VARIABLE. However, they missed a few calls within the scripts and now had two names for the same variable. Later on a guy comes in to debug the script, sees the const int SOME_VARIABLE name and searches all scripts for that, missing the old name and thus failing to debug the script.



               
               

               
            

Legacy_belisarius

  • Newbie
  • *
  • Posts: 18
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« Reply #4 on: January 29, 2015, 12:25:42 pm »


               Thanks, Ptsemarie.


I have searched for the variable name, there are dozens of occurances - but I've checked each and all seem to be correct :-/


I'm afraid its probably something similar to what you're saying about use of constants. nGNBDisabled is for a check, that prevents the normal behaviour under atypical circumstances. It's being ignored. Somewhere amid those scripts an occurrence of nGNBDisabled ISNT there and should be.


I have no idea where to look first, was hoping someone more familiar with the NPCACT codebase might know...
               
               

               
            

Legacy_belisarius

  • Newbie
  • *
  • Posts: 18
  • Karma: +0/-0
NPC Activities - nGNBDisabled has no effect - bug?
« Reply #5 on: January 30, 2015, 11:19:52 am »


               

Well, I had an email back from Qlippoth, the NPC Activities maintainer.

 


He will investigate, but in the meantime I built a "Wand of NPC Activities Control" - but seems to work on my NPCs, and Pathways demo Orcs. But demo Dwarves behave oddly - they stop, then walk all the way to their posts and stay there. The wand is kludgy - I had to set nGNBProfessions and a few other flags to make NPC Activities leave the target in peace! But it now works.

 

Deva included a "DM Wand" in version 6.1 with the same feature, but it didn't work. Think it was last updated in v5.0.


Thanks for your help, peoples! And if anyone needs a copy of my wand for their own module / PW, no problem, pm me and I'll email it '<img'>