niBBa

KotOR 2 Improved AI mod and Beancounter's Hardcore mod

Recommended Posts

Both of these edit k_ai_master.ncs but I've seen several people say they can be used together. What do?

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Yes, but IIRC they edit other things as well? The script, you can only choose one, but the other stuff you might be able to include both of, depending on how they achieve raising the difficulty.

I once thought this was as simple as just editing one script. It is not.

Share this post


Link to post
Share on other sites

So could I just install Improved AI and then install Beancounter's mod (which is just the k_ai_master.ncs) over Improved AI's?

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Yes. Not sure what will happen, but I think you should be fine. Easy to fix if it doesn't work.

Share this post


Link to post
Share on other sites

How so?

 

EDIT: I asked the same question on the KotOR Reddit Discord and one guy says that by putting Beancounter's k_ai_master.ncs over Improved AI's, it would nullify most of what Improved AI does. Which makes sense, but like I said, I've seen quite a few posts of people claiming to use both mods at the same time with seemingly no issues...

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Compare the source code. Without it to look at, I couldn't tell you what would be different, and I am on mobile today so no way to see it unless you posted it.

Again, the two mods achieve additive difficulty somewhat differently, so the script may not be doing the heavy lifting.

Share this post


Link to post
Share on other sites

How could I post the source code? Would you need to see the code for both mods?

 

 

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Yes, and you would post it by copying and pasting it into a post, using "code" in brackets before the text, and "/code" in brackets after. It is likely to be a large wall, so put it in a spoiler too.

If both mods provided source code, post both and we can look at it together here and probably learn something.

Edit: the file you are looking for is k_ai_master.nss. You can open it with notepad or any other text editor.

Share this post


Link to post
Share on other sites

EDIT: Nevermind, stand by.

 

Spoiler

//:: k_ai_master
/*
     This is the AI file for the entire
     game.  All the default hen and def
     scripts run through this script.
*/
//:: Created By: Preston Watamaniuk
//:: Copyright (c) 2002 Bioware Corp.

#include "k_inc_debug"
#include "k_inc_generic"
#include "k_inc_switch"
#include "k_inc_utility"
#include "Hardcore_Mod"


void main()
{
    int nEvent = GetRunScriptVar();

    //GN_MyPrintString("GENERIC DEBUG *************** Firing k_ai_master for event " + GN_ITS(nEvent) + " on " + GN_ReturnDebugName(OBJECT_SELF));

    switch (nEvent)
    {
        case 3001: //This can replace a determine combat round call without an intruder
        {
            GN_DetermineCombatRound();
        }
        break;
        case 3002: //This can replace a determine combat round call with the GetFirstPC as the intruder
        {
            GN_DetermineCombatRound(GetFirstPC());
        }
        break;
        case 3003: //This can replace a determine combat round call with the Member Index 0 as the intruder
        {
            GN_DetermineCombatRound(GetPartyMemberByIndex(0));
        }
        break;
        /*
        //DEFAULT AI EVENTS
        int KOTOR_DEFAULT_EVENT_ON_HEARTBEAT           = 1001;
        int KOTOR_DEFAULT_EVENT_ON_PERCEPTION          = 1002;
        int KOTOR_DEFAULT_EVENT_ON_COMBAT_ROUND_END    = 1003;
        int KOTOR_DEFAULT_EVENT_ON_ATTACKED= 1005;
        int KOTOR_DEFAULT_EVENT_ON_DAMAGE              = 1006;
        int KOTOR_DEFAULT_EVENT_ON_DEATH               = 1007;
        int KOTOR_DEFAULT_EVENT_ON_DISTURBED           = 1008;
        int KOTOR_DEFAULT_EVENT_ON_BLOCKED             = 1009;
        int KOTOR_DEFAULT_EVENT_ON_FORCE_AFFECTED      = 1010;
        int KOTOR_DEFAULT_EVENT_ON_GLOBAL_DIALOGUE_END = 1011;
        int KOTOR_DEFAULT_EVENT_ON_PATH_BLOCKED        = 1012;
        */
        case 1001: //KOTOR_DEFAULT_EVENT_ON_HEARTBEAT
        {

            

            object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF,1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GN_GetSpawnInCondition(SW_FLAG_AMBIENT_ANIMATIONS) || GN_GetSpawnInCondition(SW_FLAG_AMBIENT_ANIMATIONS_MOBILE))
                {
                    string sWay = "WP_" + GetTag(OBJECT_SELF) + "_01";
                    int nSeries = GetLocalNumber(OBJECT_SELF, WALKWAYS_SERIES_NUMBER);
                    if(!GetIsObjectValid(GetObjectByTag(sWay)) && nSeries <= 0)
                    {
                        if(GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT)
                        {
                            if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy))
                            {
                                GN_PlayAmbientAnimation();
                            }
                        }
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1001));
            }
        }
        break;
        case 1002: //KOTOR_DEFAULT_EVENT_ON_PERCEPTION
        {
            //GN_MyPrintString("AI MASTER DEBUG *************** PECEPTION EVENT FIRING for " + GN_ReturnDebugName(OBJECT_SELF));
            //GN_MyPrintString("AI MASTER DEBUG *************** Get Last Perceived = " + GN_ReturnDebugName(GetLastPerceived()));

            object oPerceived = GetLastPerceived();
            if(GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                //Do not bother checking the last target seen if already fighting
                if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()))
                {
                    //Check if the last percieved creature was actually seen
                    if(GetLastPerceptionSeen())
                    {
                        if(GetIsEnemy(oPerceived))
                        {
                            float fDelay = GetDistanceBetween(OBJECT_SELF, oPerceived);
                            fDelay = fDelay/10.0;
                            DelayCommand(fDelay/2.0, SetFacingPoint(GetPosition(oPerceived)));

                            //MODIFIED by Preston Watamaniuk on April 10, 2003
                            //Put in the agitation flag so that re-encountered monsters do not delay.
                            if(GN_GetSpawnInCondition(SW_FLAG_STATE_AGITATED) == TRUE)
                            {
                                fDelay = 0.0;
                            }

                            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                            GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Perception 2");
                            DelayCommand(fDelay, GN_DetermineCombatRound());
                            if(fDelay > 0.0)
                            {
                               GN_SetSpawnInCondition(SW_FLAG_STATE_AGITATED);
                            }
                        }
                    }
                }
                //If the last perception event was hearing based or if someone vanished then go to search mode
                else if ((GetLastPerceptionVanished()) && GetIsEnemy(oPerceived))
                {
                    if(GetAttemptedAttackTarget() == oPerceived ||
                       GetAttemptedSpellTarget() == oPerceived ||
                       GetAttackTarget() == oPerceived)
                    {
                       ClearAllActions();
                       GN_DetermineCombatRound();

                       if(!GetIsObjectValid(GetAttemptedAttackTarget()) &&
                          !GetIsObjectValid(GetAttemptedSpellTarget()) &&
                          !GetIsObjectValid(GetAttackTarget()))
                       {
                           ClearAllActions();
                           ActionMoveToObject(oPerceived, TRUE);
                           ActionAttack(oPerceived);
                       }
                    }
                }
                else if( GetCurrentAction() != ACTION_QUEUEEMPTY )
                {
                    //Check if the last percieved creature was actually seen
                    if(GetLastPerceptionSeen())
                    {
                        if(GetIsEnemy(GetLastPerceived()))
                        {
                            float fDelay = GetDistanceBetween(OBJECT_SELF, oPerceived);
                            fDelay = fDelay/10.0;
                            DelayCommand(fDelay/2.0, SetFacingPoint(GetPosition(oPerceived)));

                            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                            GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Perception 2");
                            DelayCommand(fDelay, GN_DetermineCombatRound());
                        }
                    }
                }
            }


            if (!GetPlayerRestrictMode(OBJECT_SELF) && !GetFeatAcquired(FEAT_IMPLANT_LEVEL_1, OBJECT_SELF))
            {

                Hardcore_Mod();
 
            }


            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION) && GetLastPerceptionSeen())
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1002));
            }
        }
        break;
        case 1003: //KOTOR_DEFAULT_EVENT_ON_COMBAT_ROUND_END
        {
            //This counts the number of combat rounds the creature has seen combat for
            //int nLocal = GetLocalNumber(OBJECT_SELF, SW_NUMBER_LAST_COMBO);
            //nLocal++;
            //SetLocalNumber(OBJECT_SELF, SW_NUMBER_LAST_COMBO, nLocal);
            //GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On End Combat Round");
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetCommandable())
                {
                    SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);
                    GN_DetermineCombatRound();
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_COMBAT_ROUND_END))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1003));
            }
        }
        break;
        case 1004: //KOTOR_DEFAULT_EVENT_ON_DIALOGUE
        {
            int nMatch = GetListenPatternNumber();
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE_INTERRUPT))
            {
                if( nMatch == -1 )
                {
                    ResetDialogState();
                }
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
                return;
            }

            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                object oShouter = GetLastSpeaker();
                object oIntruder;
                //AurPostString( "Got Past AI_OFF", 20, 10, 2.0f );
                object oAttacker = GetLastHostileActor(oShouter);
                if(!GetIsObjectValid(oAttacker) || GetIsDead(oAttacker) || !GetObjectSeen(oAttacker, oShouter)
                   || !GetIsEnemy(oAttacker, oShouter))      //RWT-OEI 04/13/04 - Added GetIsEnemy check. IF the guy is neutral to you, then no reason not to have conversation.
                {
                    //AurPostString( "Got Past ObjectValid()" , 10, 15, 2.0f );
                    if(GetCommandable())
                    {
                        //AurPostString( "Got Past Commandable()", 10, 20, 2.0f );
                        if (nMatch == -1)
                        {
                            ClearAllActions();
                            if(GN_GetSpawnInCondition(SW_FLAG_ON_DIALOGUE_COMPUTER))
                            {
                                //AurPostString( "Starting Conversation.", 10, 25, 2.0f );
                                ActionStartConversation(GetFirstPC(), "", FALSE, CONVERSATION_TYPE_COMPUTER);
                                return;
                            }
                            else
                            {
                                //AurPostString( "Beginning Conversation.", 10, 25, 2.0f );
                                BeginConversation();
                                return;
                            }
                        }
                        else
                        if(nMatch != -1 && GetIsObjectValid(oShouter) && !GetIsPC(oShouter) && GetIsFriend(oShouter))
                        {
                            if (nMatch >= 1)
                            {
                                oIntruder = GetLastHostileActor(oShouter);
                                if(!GetIsObjectValid(oIntruder))
                                {
                                    oIntruder = GetAttemptedAttackTarget();
                                    if(!GetIsObjectValid(oIntruder))
                                    {
                                        oIntruder = GetAttemptedSpellTarget();
                                        if(!GetIsObjectValid(oIntruder))
                                        {
                                            //P.W.(June 3) - More robust perception check on enemies.
                                            oIntruder = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN);
                                            if(!GetIsObjectValid(oIntruder))
                                            {
                                                GN_MyPrintString("GENERIC DEBUG *************** No Intruder Object For Shout");
                                                oIntruder = OBJECT_INVALID;
                                            }
                                        }
                                    }
                                }
                            }
                            //GN_MyPrintString("GENERIC DEBUG *************** Shout Intruder = " + GN_ReturnDebugName(oIntruder));
                            //GN_MyPrintString("GENERIC DEBUG *************** " + GN_ReturnDebugName(OBJECT_SELF) + " shouted at by: " + GN_ReturnDebugName(oShouter) + " for shout: " + IntToString(nMatch));
                            GN_RespondToShout(oShouter, nMatch, oIntruder);
                        }
                    }
                }
            }
            if( nMatch == -1 )
            {
                //AurPostString( "Got to end. Blah.", 10, 20, 2.0f );
                ResetDialogState();
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
            }
        }
        break;
        case 1005: //KOTOR_DEFAULT_EVENT_ON_ATTACKED
        {
            //Shout that I was attacked
            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
            //SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);
            if(GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()))
                {
                    GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Attacked");
                    GN_DetermineCombatRound();
                    //Shout that I was attacked
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                    //SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);
                }
                else if(GetCurrentAction() == ACTION_QUEUEEMPTY)
                {
                    GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Attacked");
                    GN_DetermineCombatRound();
                    //Shout that I was attacked
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_ATTACKED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1005));
            }
        }
        break;
        case 1006: //KOTOR_DEFAULT_EVENT_ON_DAMAGE
        {
            if(GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
                {
                    if(GetIsObjectValid(GetLastDamager()))
                    {
                        //MODIFIED by Preston Watamaniuk on May 9
                        //Put this check in to make sure that people who turn neutral do not get the Determine Combat Round fired
                        if(GetIsEnemy(GetLastDamager()))
                        {
                            if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()))
                            {
                                GN_DetermineCombatRound();
                                if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()))
                                {
                                    object oTarget = GetLastDamager();
                                    if(!GetObjectSeen(oTarget) && GetArea(OBJECT_SELF) == GetArea(oTarget))
                                    {
                                        //P.W. (June 8) - Put this check in to try and reduce the instances of NPCs running right up
                                        //to their enemies with blasters.
                                        effect eLink1 = EffectBlind();
                                        RemoveEffect(OBJECT_SELF, eLink1);
                                        if(GetDistanceBetween(OBJECT_SELF, oTarget) < 20.0 && !GetObjectSeen(oTarget))
                                        {
                                            ActionMoveToObject(oTarget, TRUE, 2.0);
                                        }
                                        else
                                        {
                                            if(GN_GetWeaponType(OBJECT_SELF) == 1)
                                            {
                                                ActionMoveToObject(oTarget, TRUE, 4.0);
                                            }
                                            else
                                            {
                                                ActionMoveToObject(oTarget, TRUE, 15.0);
                                            }
                                        }
                                        //ActionMoveToObject(oTarget, TRUE, fRange);
                                        GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Damaged");
                                        ActionDoCommand(GN_DetermineCombatRound());
                                    }
                                }
                            }
                        }
                    }
                }
                else if (!GetIsObjectValid(GetAttemptedSpellTarget()))
                {
                    object oTarget = GetAttackTarget();
                    if(!GetIsObjectValid(oTarget))
                    {
                        oTarget = GetAttemptedAttackTarget();
                    }
                    object oAttacker = GetLastHostileActor();
                    if (GetIsObjectValid(oAttacker) && oTarget != oAttacker && GetIsEnemy(oAttacker) &&
                       (GetTotalDamageDealt() > (GetMaxHitPoints(OBJECT_SELF) / 4) ||
                        (GetHitDice(oAttacker) - 2) > GetHitDice(oTarget) ) )
                    {
                        GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Attacked 2");
                        GN_DetermineCombatRound(oAttacker);
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DAMAGED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1006));
            }
        }
        break;
        case 1007: //KOTOR_DEFAULT_EVENT_ON_DEATH
        {
            
            
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                SpeakString("GEN_I_AM_DEAD", TALKVOLUME_SILENT_TALK);
                //Shout Attack my target, only works with the On Spawn In setup
                SpeakString("GEN_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DEATH))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1007));
            }
        }
        break;
        case 1008: //KOTOR_DEFAULT_EVENT_ON_DISTURBED
        {
            //NOT USED
        }
        break;
        case 1009: //KOTOR_DEFAULT_EVENT_ON_BLOCKED
        {
            object oDoor = GetBlockingDoor();
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetIsObjectValid(oDoor))
                {
                    if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN))
                    {
                        DoDoorAction(oDoor, DOOR_ACTION_OPEN);
                    }
                    else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH))
                    {
                        DoDoorAction(oDoor, DOOR_ACTION_BASH);
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1009));
            }
        }
        break;
        case 1010: //KOTOR_DEFAULT_EVENT_ON_FORCE_AFFECTED
        {
            object oCaster = GetLastSpellCaster();
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetLastSpellHarmful())
                {
                    if(!GetIsObjectValid(GetAttackTarget()) &&
                     !GetIsObjectValid(GetAttemptedSpellTarget()) &&
                     !GetIsObjectValid(GetAttemptedAttackTarget()) &&
                     GetIsObjectValid(oCaster) &&
                     //GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)) &&
                     GetCommandable() )
                    {
                        GN_MyPrintString("GENERIC DEBUG *************** Determine Combat Round from On Spell Cast At");
                        GN_DetermineCombatRound(oCaster);
                        //Shout Attack my target, only works with the On Spawn In setup
                        //SpeakString("GEN_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
                        //Shout that I was attacked
                        SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_SPELL_CAST_AT))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1010));
            }
        }
        break;
        case 1011: //KOTOR_DEFAULT_EVENT_ON_GLOBAL_DIALOGUE_END
        {
            GN_MyPrintString("GENERIC DEBUG *************** Starting Post Dialogue Event for " + GN_ReturnDebugName(OBJECT_SELF));
            //Added by Aidan March 27,03
            // this allows fleeing creatures to become active after conversation
            if(GetIsEnemy(GetFirstPC()) &&
               GetCommandable() == FALSE)
            {
                SetCommandable(TRUE);
            }

            //MODIFIED by Preston Watamaniuk on April 25, 2003
            //Put LOS check in for enemies to make a Determine Combat Round is appropriate.

            //If they drop through this function the end result is a GN_WalkWayPoints() call.
            if(GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF,1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)))
            {
                if(!IsObjectPartyMember(OBJECT_SELF))
                {
                    DelayCommand(0.2, GN_DetermineCombatRound());
                }
            }
            //P.W.(May 20, 2003) - Put an AI flag check here to make sure people do not move against their will.
            else if(GN_GetSpawnInCondition(SW_FLAG_AI_OFF) == FALSE)
            {
                if(GN_DoPostDCRChecks())
                {
                    GN_MyPrintString("GENERIC DEBUG *************** End Coversation Successful Fall through");
                }
            }

            //JAB-OEI5/21/04
            //Made this change from SW_FLAG_EVENT_DIALOGUE_END
            //The user defined event was not getting called because of this
            //We didn't want to make the change to all the on spawn scripts
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE_END))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1011));
            }
        }
        break;
        case 1012: //KOTOR_DEFAULT_EVENT_ON_PATH_BLOCKED
        {
           object oBlocker = GetBlockingCreature();
           object oEnemy = GetFoundEnemyCreature();

           AurPostString(GN_ReturnDebugName(oBlocker),0,15,2.0);
           AurPostString(GN_ReturnDebugName(oEnemy),0,16,2.0);

           if(GetIsObjectValid(oEnemy) && GetCommandable() && oEnemy != GetAttemptedAttackTarget())
           {
              // we have tried moving around a creature and encountered a creature that is hostile.
              if(!GN_GetSpawnInCondition(SW_FLAG_COMMONER_BEHAVIOR)
                 && !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE)
                 && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
              {
                   GN_MyPrintString("GENERIC DEBUG *************** Combat Blocked " + GN_ReturnDebugName(oEnemy));
                   GN_MyPrintString("GENERIC DEBUG *************** Combat Blocked Clear (PICK an Number preston)");
                   ClearAllActions();
                   GN_DetermineCombatRound(oEnemy);
              }
           }
           if(!GetIsObjectValid(oEnemy) && GetCommandable() )
           {
            // we are blocked and have no way around this creature.
            // what should happen?
           }
        }
        break;
        /*
        //HENCHMEN AI EVENTS
        int KOTOR_HENCH_EVENT_ON_HEARTBEAT           = 2001;
        int KOTOR_HENCH_EVENT_ON_PERCEPTION          = 2002;
        int KOTOR_HENCH_EVENT_ON_COMBAT_ROUND_END    = 2003;
        int KOTOR_HENCH_EVENT_ON_DIALOGUE            = 2004;
        int KOTOR_HENCH_EVENT_ON_ATTACKED            = 2005;
        int KOTOR_HENCH_EVENT_ON_DAMAGE              = 2006;
        int KOTOR_HENCH_EVENT_ON_DEATH               = 2007;
        int KOTOR_HENCH_EVENT_ON_DISTURBED           = 2008;
        int KOTOR_HENCH_EVENT_ON_BLOCKED             = 2009;
        int KOTOR_HENCH_EVENT_ON_FORCE_AFFECTED      = 2010;
        int KOTOR_HENCH_EVENT_ON_GLOBAL_DIALOGUE_END = 2011;
        int KOTOR_HENCH_EVENT_ON_PATH_BLOCKED        = 2012;
        int KOTOR_HENCH_EVENT_ON_ENTER_5m            = 2013;
        int KOTOR_HENCH_EVENT_ON_EXIT_5m             = 2014;
        */
        case 2001: //KOTOR_HENCH_EVENT_ON_HEARTBEAT
        {
            object oEnemy = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF, 1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
            //GN_SetSpawnInCondition(SW_FLAG_SHOUTED_AT, FALSE);

            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode())
            {
                if(GetPartyMemberByIndex(0) != OBJECT_SELF)
                {
                    if(IsObjectPartyMember(OBJECT_SELF) &&  //Note that this check replaces GetIsObjectValid(oMaster)
                       //GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW &&
                       GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT &&
                       //GetCurrentAction(OBJECT_SELF) != ACTION_WAIT &&
                       GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOWLEADER &&
                       !GetIsConversationActive() &&
                       //GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 4.5 &&
                       !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) &&
                       GetCommandable() &&
                       // DJS-OEI 3/12/2004
                       // Those that are meditating will only start following if the
                       // currently controlled PC moves more than 15 meters away.
                       ( !IsMeditating( OBJECT_SELF ) ||
                         ( IsMeditating( OBJECT_SELF ) && ( GetDistanceBetween( OBJECT_SELF, GetPartyMemberByIndex(0) ) > 15.0 ) ) ) )
                    {
                        //Db_PostString(GetTag(OBJECT_SELF) + " HEARTBEAT CHECK 1 PASS", 4, 10, 2.0);
                        if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy))
                        {
                            //Db_PostString(GetTag(OBJECT_SELF) + " HEARTBEAT CHECK 2 PASS", 4, 12, 2.0);
                            //The distance checking is now down in the script fired from AI Action Update - Leave 5m Radius of party leader.
                            ClearAllActions();
                            ActionFollowLeader();
                        }
                    }
                }
            }
            else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER)
            {
                ClearAllActions();
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1001));
            }
        }
        break;
        case 2002: //KOTOR_HENCH_EVENT_ON_PERCEPTION
        {
            GN_PostString("Firing Perception", 10,10,4.0);
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode())
                {
                    //If the last perception event was hearing based or if someone vanished then go to search mode
                    //Db_MyPrintString("GENERIC DEBUG *************** MONKEY CHECKS: " + GN_ReturnDebugName(OBJECT_SELF));
                    //Db_MyPrintString("GENERIC DEBUG *************** Attempted Attack Target " + GN_ReturnDebugName(GetAttemptedAttackTarget()));
                    //Db_MyPrintString("GENERIC DEBUG *************** Attempted Spell Target " + GN_ReturnDebugName(GetAttemptedSpellTarget()));
                    //Db_MyPrintString("GENERIC DEBUG *************** Attack Target " + GN_ReturnDebugName(GetAttackTarget()));

                    if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived()))
                    {
                        object oGone = GetLastPerceived();
                        if((GetAttemptedAttackTarget() == GetLastPerceived() ||
                           GetAttemptedSpellTarget() == GetLastPerceived() ||
                           GetAttackTarget() == GetLastPerceived()) && GetArea(GetLastPerceived()) != GetArea(OBJECT_SELF))
                        {
                           ClearAllActions();
                           GN_DetermineCombatRound();
                        }
                    }
                    //Do not bother checking the last target seen if already fighting

                    else if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()) )
                    {
                        //Check if the last percieved creature was actually seen
                        if(GetLastPerceptionSeen())
                        {
                            if(GetIsEnemy(GetLastPerceived()))
                            {
                                object oLeader = GetPartyMemberByIndex(0);
                                if(GetIsObjectValid(GetAttackTarget(oLeader)))
                                {
                                    GN_PostString("Perception Attack", 10,12,4.0);
                                    //SetFacingPoint(GetPosition(GetLastPerceived()));
                                    //SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);
                                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_SHOUT);
                                    GN_DetermineCombatRound();
                                }
                            }
                        }
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION) && GetLastPerceptionSeen())
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1002));
            }
        }
        break;
        case 2003: //KOTOR_HENCH_EVENT_ON_COMBAT_ROUND_END
        {
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                //MODIFIED by Preston Watamaniuk April 14
                //Took out some legacy code for the Endar Spire
                //Changed the shout from Combat Active to I was attacked.

                //P.W. (May 29) - Took out the if below and replaced it with the one check solo mode instead.
                //if(GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode())
                //{
                    Db_MyPrintString("GENERIC DEBUG *************** End of Combat Round: " + GN_ReturnDebugName(OBJECT_SELF));
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                    GN_DetermineCombatRound();
                //}
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_COMBAT_ROUND_END))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1003));
            }
        }
        break;
        case 2004: //KOTOR_HENCH_EVENT_ON_DIALOGUE
        {
            int nMatch = GetListenPatternNumber();
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetCommandable())
                {
                    object oShouter = GetLastSpeaker();
                    object oIntruder;
                    if (nMatch == -1)
                    {
                        ClearAllActions();
                        BeginConversation();
                        return;
                    }
                    else
                    {
                        GN_RespondToShout(oShouter, nMatch, GetLastHostileActor(oShouter));
                    }
                }
            }
            if( nMatch == -1 )
            {
                ResetDialogState();
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
            }
        }
        break;
        case 2005: //KOTOR_HENCH_EVENT_ON_ATTACKED
        {
            //Shout Attack my target, only works with the On Spawn In setup
            //SpeakString("GEN_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
            //Shout that I was attacked
            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_SHOUT);
            //SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);

            //RWT-OEI 08/28/04 - We need to note if we were last attacked
            //by a Melee weapon so we know that we should switch to melee
            //if we can to defend ourselves.
            object oAttacker = GetLastAttacker();
            object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTWEAPON,oAttacker);

            int nWeaponType = 0;
            if ( GetIsObjectValid(oWeapon))
            {
                nWeaponType = GN_GetWeaponTypeFromBaseItem(GetBaseItemType(oWeapon));
            }
            if ( nWeaponType == 1 || nWeaponType == 0)
            {
                //Indicate that we are being hit by melee. Use the
                //healer AI local number slots since we don't need
                //them for anything else here
                SetLocalNumber( OBJECT_SELF, SW_NUMBER_HEALERAI_THRESHOLD, 2);
            }

            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetPartyMemberByIndex(0) == OBJECT_SELF)
                {
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
                if(GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode())
                {
                    if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()) )
                    {
                        if(GetIsObjectValid(GetLastAttacker()))
                        {
                            if(GetArea(GetLastAttacker()) == GetArea(OBJECT_SELF))
                            {
                                if(!GetIsInCombat())
                                {
                                    GN_DetermineCombatRound();
                                }
                            }
                        }
                    }
                }
                else
                {
                    //Shout that I was attacked
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_ATTACKED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1005));
            }
        }
        break;
        case 2006: //KOTOR_HENCH_EVENT_ON_DAMAGE
        {
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetFirstPC() == OBJECT_SELF &&
                   GetGlobalBoolean("END_BRIDGE_COMBAT") &&
                   GetGlobalBoolean("END_HURT_WARN") == FALSE)
                {
                    SetGlobalBoolean("END_HURT_WARN",TRUE);
                    BarkString(OBJECT_INVALID,10242);
                    PauseGame(TRUE);

                }
                else if(GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode())
                {
                    if(GetCurrentAction() != ACTION_FOLLOWLEADER)
                    {
                        if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
                        {
                            if(GetIsObjectValid(GetLastDamager()))
                            {
                                if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget()) )
                                {
                                    GN_DetermineCombatRound();
                                    if(!GN_GetIsFighting(OBJECT_SELF))
                                    {
                                        object oTarget = GetLastDamager();
                                        if(!GetObjectSeen(oTarget) && GetArea(OBJECT_SELF) == GetArea(oTarget))
                                        {
                                            ActionMoveToLocation(GetLocation(oTarget), TRUE);
                                            ActionDoCommand(GN_DetermineCombatRound());
                                        }
                                    }
                                }
                            }
                        }
                        else if (!GetIsObjectValid(GetAttemptedSpellTarget()))
                        {
                            object oTarget = GetAttackTarget();
                            if(!GetIsObjectValid(oTarget))
                            {
                                oTarget = GetAttemptedAttackTarget();
                            }
                            object oAttacker = GetLastHostileActor();
                            if (GetIsObjectValid(oAttacker) && oTarget != oAttacker && GetIsEnemy(oAttacker) &&
                               (GetTotalDamageDealt() > (GetMaxHitPoints(OBJECT_SELF) / 4) ||
                                (GetHitDice(oAttacker) - 2) > GetHitDice(oTarget) ) )
                            {
                                GN_DetermineCombatRound(oAttacker);
                            }
                        }
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DAMAGED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1006));
            }
        }
        break;
        case 2007: //KOTOR_HENCH_EVENT_ON_DEATH
        {

        }
        break;
        case 2008: //KOTOR_HENCH_EVENT_ON_DISTURBED
        {

        }
        break;
        case 2009: //KOTOR_HENCH_EVENT_ON_BLOCKED
        {
            object oDoor = GetBlockingDoor();
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5)
                {
                    if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7 )
                    {
                        DoDoorAction(oDoor, DOOR_ACTION_OPEN);
                    }
                    else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH))
                    {
                        DoDoorAction(oDoor, DOOR_ACTION_BASH);
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(1009));
            }
        }
        break;
        case 2013: //KOTOR_HENCH_EVENT_ON_ENTER_5m
        {
            /*
            SetCommandable(TRUE);
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(!GetUserActionsPending())
                {
                    if(GetCurrentAction(GetPartyMemberByIndex(0)) == ACTION_ATTACKOBJECT ||
                       GetCurrentAction(GetPartyMemberByIndex(0)) == ACTION_CASTSPELL)
                    {
                        GN_DetermineCombatRound();
                    }
                }
            }
            */
        }
        break;
        case 2014: //KOTOR_HENCH_EVENT_ON_EXIT_5m
        {
            /*
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode())
            {
                if(GetPartyMemberByIndex(0) != OBJECT_SELF)
                {
                    if(IsObjectPartyMember(OBJECT_SELF) &&  //Note that this check replaces GetIsObjectValid(oMaster)
                       //GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOW &&
                       //GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT &&
                       //GetCurrentAction(OBJECT_SELF) != ACTION_WAIT &&
                       GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOWLEADER &&
                       !GetIsConversationActive() &&
                       GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 4.5 &&
                       !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE) &&
                       GetCommandable())
                    {
                        if( //!GetIsInCombat() &&
                            !GetIsObjectValid(GetAttackTarget()) &&
                            !GetIsObjectValid(GetAttemptedAttackTarget()) &&
                            !GetIsObjectValid(GetAttemptedSpellTarget()) )
                        {
                            if(!GetSoloMode())
                            {
                                //The distance checking is now down in the script fired from AI Action Update - Leave 5m Radius of party leader.
                                ClearAllActions();
                                ActionFollowLeader();
                            }
                        }
                    }
                }
            }
            else if(GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER)
            {
                ClearAllActions();
            }
            */
        }
        break;
    }
}

 

 

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Yeah... Well, you could try to DeNCS it. I think it has include files in it so it might be a problem, can't remember.

Share this post


Link to post
Share on other sites

I found it. I posted right before you did, check the post above yours, that is the k_ai_master.nss for the Hardcore mod. Working on the Improved AI now.

 

EDIT: Improved AI .nss

 

 

Spoiler

// ====================================================================
// K_AI_MASTER - Creature AI Master script
// -------------------------------------------------------------------- 
// Modified variant of K_AI_MASTER with rewritten AI target selection,
// behavior and talent filters and somewhat tweaked reactions to
// different events. Most changes are in the modified k_inc_generic.nss
// and k_inc_gensupport.nss scripts.
//
// 2005-08-18 - Adapted back from st_ai_master to work as Generic 
//              Master AI script again. Beware of oversights.
// -------------------------------------------------------------------- 
// Last changed: 2005-09-10
// ====================================================================

#include "k_inc_generic"
#include "k_inc_switch"
#include "st_inc_ai"

// ST: Uncommenting the line below would include beancounters hardcore mod in the AI.
//     Note that the code at line 158 needs to be uncommented as well,
//     the HCMod source placed in this folder and the scripts recompiled.
// #include "Hardcore_Mod"

void main()
{
    int nEvent = GetRunScriptVar();

    switch (nEvent) {
        case 3001: //This can replace a determine combat round call without an intruder
            GN_DetermineCombatRound(OBJECT_INVALID, 3001);
        	break;
        	
        case 3002: //This can replace a determine combat round call with the GetFirstPC as the intruder
            GN_DetermineCombatRound(GetFirstPC(), 3002);
        	break;
        	
        case 3003: //This can replace a determine combat round call with the Member Index 0 as the intruder
            GN_DetermineCombatRound(GetPartyMemberByIndex(0), 3003);
        	break;
        	
        /*
        //DEFAULT AI EVENTS
        int KOTOR_DEFAULT_EVENT_ON_HEARTBEAT           = 1001;
        int KOTOR_DEFAULT_EVENT_ON_PERCEPTION          = 1002;
        int KOTOR_DEFAULT_EVENT_ON_COMBAT_ROUND_END    = 1003;
        int KOTOR_DEFAULT_EVENT_ON_DIALOGUE			   = 1004;
        int KOTOR_DEFAULT_EVENT_ON_ATTACKED			   = 1005;
        int KOTOR_DEFAULT_EVENT_ON_DAMAGE              = 1006;
        int KOTOR_DEFAULT_EVENT_ON_DEATH               = 1007;
        int KOTOR_DEFAULT_EVENT_ON_DISTURBED           = 1008;
        int KOTOR_DEFAULT_EVENT_ON_BLOCKED             = 1009;
        int KOTOR_DEFAULT_EVENT_ON_FORCE_AFFECTED      = 1010;
        int KOTOR_DEFAULT_EVENT_ON_GLOBAL_DIALOGUE_END = 1011;
        int KOTOR_DEFAULT_EVENT_ON_PATH_BLOCKED        = 1012;
        */
        case 1001: //KOTOR_DEFAULT_EVENT_ON_HEARTBEAT
        {
            object oEnemy = ST_GetNearestEnemy();
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if (GN_GetSpawnInCondition(SW_FLAG_AMBIENT_ANIMATIONS) || GN_GetSpawnInCondition(SW_FLAG_AMBIENT_ANIMATIONS_MOBILE)) {
                    string sWay = "WP_" + GetTag(OBJECT_SELF) + "_01";
                    int nSeries = GetLocalNumber(OBJECT_SELF, WALKWAYS_SERIES_NUMBER);
                    
                    if (!GetIsObjectValid(GetObjectByTag(sWay)) && nSeries <= 0) {
                        if (GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT) {
                            if (!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy))
                                GN_PlayAmbientAnimation();
                        }
                    }
                }            
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))
                SignalEvent(OBJECT_SELF, EventUserDefined(1001));
        }
        break;
        
        case 1002: //KOTOR_DEFAULT_EVENT_ON_PERCEPTION
        {
            object oPerceived = GetLastPerceived();
            if (GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                //Do not bother checking the last target seen if already fighting
                if (   !ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                	&& !ST_GetIsAITargetValid(GetLastHostileTarget())     // ST: Added this...
                	&& !ST_GetIsAITargetValid(ST_GetLastAttackTarget())   // ST: Added...
                	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                	&& !ST_GetIsAITargetValid(GetAttackTarget()))
                {
                    //Check if the last percieved creature was actually seen
                    if(GetLastPerceptionSeen()) {
                        if(GetIsEnemy(oPerceived)) {
                            float fDelay = GetDistanceBetween(OBJECT_SELF, oPerceived);
                            fDelay = fDelay/10.0;
                            DelayCommand(fDelay/2.0, SetFacingPoint(GetPosition(oPerceived)));

                            //MODIFIED by Preston Watamaniuk on April 10, 2003
                            //Put in the agitation flag so that re-encountered monsters do not delay.
                            if(GN_GetSpawnInCondition(SW_FLAG_STATE_AGITATED) == TRUE)
                                fDelay = 0.0;

                            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                            DelayCommand(fDelay, GN_DetermineCombatRound(OBJECT_INVALID, 1002));
                            
                            if(fDelay > 0.0)
                               GN_SetSpawnInCondition(SW_FLAG_STATE_AGITATED);
                        }
                    }
                    // ST: Added(2005-09-08) - If no other valid targets are nearby and I just
                    //     lost sight of a target, move to where I saw them vanish to investigate.
                    else if (GetLastPerceptionVanished()  
                    	&& GetIsEnemy(oPerceived)
                    	&& !GetObjectSeen(oPerceived)
                    	&& !GetIsObjectValid(ST_GetNearestEnemy())) 
                    {
						ActionMoveToLocation(GetLocation(oPerceived), TRUE);	
                    }
                }
                //If the last perception event was hearing based or if someone vanished then go to search mode
				else if ((GetLastPerceptionVanished()) && GetIsEnemy(oPerceived)) {
                	if ((GetAttemptedAttackTarget() == oPerceived)
                      || (GetAttemptedSpellTarget() == oPerceived)
                      || (GetAttackTarget() == oPerceived))
                    {
                    	if ( !ST_GetIsAITargetValid(GetAttemptedAttackTarget())
                          && !ST_GetIsAITargetValid(GetAttemptedSpellTarget())
                          && !ST_GetIsAITargetValid(GetAttackTarget()))
						{
                       		// ST: Don't bypass the combat AI. Let the AI pick a
                       		//     new opponent if necessary instead.
                            // ClearAllActions();
                            // ActionMoveToObject(oPerceived, TRUE);
                            // ActionAttack(oPerceived);
                        	GN_DetermineCombatRound(OBJECT_INVALID, 1002);
						}
                       // ST: Moved these two lines down here to avoid double-calling DCR.
						else {
                       		// ST: REMOVED, let DCR do this itself if necessary...
                       	    // ClearAllActions(); 
							GN_DetermineCombatRound(OBJECT_INVALID, 1002);                       	
						}
					}
                }
                else if(GetCurrentAction() != ACTION_QUEUEEMPTY) {
                    //Check if the last percieved creature was actually seen
                    if(GetLastPerceptionSeen()) {
                        if(GetIsEnemy(GetLastPerceived())) {
                            float fDelay = GetDistanceBetween(OBJECT_SELF, oPerceived);
                            fDelay = fDelay/10.0;
                            DelayCommand(fDelay/2.0, SetFacingPoint(GetPosition(oPerceived)));

                            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                            DelayCommand(fDelay, GN_DetermineCombatRound(OBJECT_INVALID, 1002));
                        }
                    }
                }
            }
            
            // ST: This would add beancounters hardcore mod to the Creature AI, if uncommented and recompiled:
            /*
			if (!GetPlayerRestrictMode() && !GetFeatAcquired(FEAT_IMPLANT_LEVEL_1))
    			Hardcore_Mod(); 
    		*/
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION) && GetLastPerceptionSeen())
                SignalEvent(OBJECT_SELF, EventUserDefined(1002));
        }
        break;
        
        case 1003: //KOTOR_DEFAULT_EVENT_ON_COMBAT_ROUND_END
        {
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if (GetCommandable()) {
                    SpeakString("GEN_COMBAT_ACTIVE", TALKVOLUME_SILENT_TALK);
                    GN_DetermineCombatRound(OBJECT_INVALID, 1003);
                }
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_COMBAT_ROUND_END))
                SignalEvent(OBJECT_SELF, EventUserDefined(1003));
        }
        break;
        
        case 1004: //KOTOR_DEFAULT_EVENT_ON_DIALOGUE
        {
            int nMatch = GetListenPatternNumber();
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE_INTERRUPT)) {
                if (nMatch == -1)
                    ResetDialogState();
                    
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
                return;
            }

            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                object oShouter = GetLastSpeaker();
                object oIntruder;
                object oAttacker = GetLastHostileActor(oShouter);
                
                //RWT-OEI 04/13/04 - Added GetIsEnemy check. IF the guy is neutral to you, 
                // then no reason not to have conversation.
                if (!GetIsObjectValid(oAttacker) 
                	|| GetIsDead(oAttacker) 
                	|| !GetObjectSeen(oAttacker, oShouter)
                   	|| !GetIsEnemy(oAttacker, oShouter))      
                {
                    if (GetCommandable()) {
                        if (nMatch == -1) {
                            ClearAllActions();
                            
                            if (GN_GetSpawnInCondition(SW_FLAG_ON_DIALOGUE_COMPUTER))
                                ActionStartConversation(GetFirstPC(), "", FALSE, CONVERSATION_TYPE_COMPUTER);
                            else
                                BeginConversation();

                            return;
                        }
                        else if ((nMatch != -1) 
                        	&& GetIsObjectValid(oShouter) 
                        	&& !GetIsPC(oShouter) 
                        	&& GetIsFriend(oShouter))
                        {
                            if (nMatch >= 1) {
                                oIntruder = GetLastHostileActor(oShouter);
                                if (!GetIsObjectValid(oIntruder)) {
                                    oIntruder = GetAttemptedAttackTarget();
                                    if (!GetIsObjectValid(oIntruder)) {
                                        oIntruder = GetAttemptedSpellTarget();
                                        if (!GetIsObjectValid(oIntruder)) {	
                                            //P.W.(June 3) - More robust perception check on enemies.
                                            oIntruder = ST_GetNearestEnemy();
                                            if (!GetIsObjectValid(oIntruder))
                                                oIntruder = OBJECT_INVALID;
                                        }
                                    }
                                }
                            }

                            GN_RespondToShout(oShouter, nMatch, oIntruder);
                        }
                    }
                }
            }
            
            if (nMatch == -1)
                ResetDialogState();

            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE))
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
        }
        break;
        
        case 1005: //KOTOR_DEFAULT_EVENT_ON_ATTACKED
        {
            //Shout that I was attacked
            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);

            if(GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if (   !ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                	&& !ST_GetIsAITargetValid(GetLastHostileTarget())     // ST: Added this...
                	&& !ST_GetIsAITargetValid(ST_GetLastAttackTarget())   // ST: Added...
                	&& !ST_GetIsAITargetValid(GetAttackTarget()))
                {
                    GN_DetermineCombatRound(OBJECT_INVALID, 1005);
                    // Shout that I was attacked
                    // ST: You already did a picosecond ago above.... removed.
                    // SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
                // ST: Added Not In Combat check....
                else if ((GetCurrentAction() == ACTION_QUEUEEMPTY) || !GetIsInCombat()) {
                    GN_DetermineCombatRound(OBJECT_INVALID, 1005);
                    // Shout that I was attacked
                    // ST: You already did a picosecond ago above.... removed.
                    // SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_ATTACKED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1005));
        }
        break;
        
        case 1006: //KOTOR_DEFAULT_EVENT_ON_DAMAGE
        {
            if (GetCommandable() && !GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if(    !ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                	&& !ST_GetIsAITargetValid(GetLastHostileTarget())     // ST: Added this...
                	&& !ST_GetIsAITargetValid(ST_GetLastAttackTarget())   // ST: Added...
                	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()))
                {
                    if(GetIsObjectValid(GetLastDamager())) {
                        //MODIFIED by Preston Watamaniuk on May 9
                        //Put this check in to make sure that people who turn neutral do not get the Determine Combat Round fired
                        if(GetIsEnemy(GetLastDamager())) {
                            if(!ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                            	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                            	&& !ST_GetIsAITargetValid(GetAttackTarget()))
                            {
								GN_DetermineCombatRound(OBJECT_INVALID, 1006);
                                
                                if (!ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                                	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                                	&& !ST_GetIsAITargetValid(GetAttackTarget()))
                                {
                                    object oTarget = GetLastDamager();
                                    
                                    if(!GetObjectSeen(oTarget) && GetArea(OBJECT_SELF) == GetArea(oTarget)) {
                                        //P.W. (June 8) - Put this check in to try and reduce the instances of NPCs running right up
                                        //to their enemies with blasters.
                                        // ST: Well, the next two lines do absolutely nothing, but whatever... :)
                                        // effect eLink1 = EffectBlind();
                                        // RemoveEffect(OBJECT_SELF, eLink1);
                                        
                                        if ((GetDistanceBetween(OBJECT_SELF, oTarget) < 20.0) && !GetObjectSeen(oTarget)) {
                                            ActionMoveToObject(oTarget, TRUE, 2.0);
                                        }
                                        else {
                                            if(GN_GetWeaponType(OBJECT_SELF) == 1) {
                                                ActionMoveToObject(oTarget, TRUE, 4.0);
                                            }
                                            else {
                                            	// ST: Try to randomize the movement loc a bit in case they don't get
                                            	//     line of sight at the first spot and the script tries again...
                                                // ActionMoveToObject(oTarget, TRUE, 15.0);
                                                ActionMoveToLocation(Location(GetRandomDestination(OBJECT_SELF, 15), 0.0), TRUE);
                                            }
                                        }
                                        
                                        ActionDoCommand(GN_DetermineCombatRound(OBJECT_INVALID, 1006));
                                    }
                                }
                            }
                        }
                    }
                }
                else if (!ST_GetIsAITargetValid(GetAttemptedSpellTarget())) {
                    object oTarget = GetAttackTarget();
                    if (!GetIsObjectValid(oTarget))
                        oTarget = GetAttemptedAttackTarget();

                    object oAttacker = GetLastHostileActor();
                    // ST: Removed level check, don't switch targets due to level alone.
                    //     Sometimes it can be good to kill off the pesky minions first
                    //     before dealing with their more dangerous allies. Only override 
                    //     targeting AI if someone is inflicting massive damage on me.
                    //     Besides, due to the standard autobalancer almost all opponents are
                    //     much lower in level than the playerparty anyway, so it would only
                    //     matter in NPC vs. NPC fights.
                    if (GetIsObjectValid(oAttacker) 
                    	&& (oTarget != oAttacker) 
                    	&& GetIsEnemy(oAttacker) 
                    	&& (GetTotalDamageDealt() > (GetMaxHitPoints(OBJECT_SELF) / 4)
                    	/* || (GetHitDice(oAttacker) - 2) > GetHitDice(oTarget) */))
                    {            
                        GN_DetermineCombatRound(oAttacker, 1006); 
                    }
                }
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DAMAGED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1006));
        }
        break;
        
        case 1007: //KOTOR_DEFAULT_EVENT_ON_DEATH
        {
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                //Shout Attack my target, only works with the On Spawn In setup
                SpeakString("GEN_I_AM_DEAD", TALKVOLUME_SILENT_TALK);
                SpeakString("GEN_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DEATH))
                SignalEvent(OBJECT_SELF, EventUserDefined(1007));

        }
        break;
        
        case 1008: //KOTOR_DEFAULT_EVENT_ON_DISTURBED
        {
            //NOT USED - Pickpocketing does not exist in KotOR.
        }
        break;
        
        case 1009: //KOTOR_DEFAULT_EVENT_ON_BLOCKED
        {
            object oDoor = GetBlockingDoor();
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if(GetIsObjectValid(oDoor)) {
                    if (GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN)) {
                        DoDoorAction(oDoor, DOOR_ACTION_OPEN);
                    }
                    else if (GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH)) {
                        DoDoorAction(oDoor, DOOR_ACTION_BASH);
                    }
                }
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1009));
        }
        break;
        
        case 1010: //KOTOR_DEFAULT_EVENT_ON_FORCE_AFFECTED
        {
            object oCaster = GetLastSpellCaster();
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if(GetLastSpellHarmful()) {
                	// ST: Added(2005-09-09): DCR if attacked when not in combat.
                	if (!GetIsInCombat()) {
                		SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                		GN_DetermineCombatRound(OBJECT_INVALID, 1010);	
                	}
                    else if (!ST_GetIsAITargetValid(GetAttackTarget()) 
                     && !ST_GetIsAITargetValid(GetAttemptedSpellTarget())
                     && !ST_GetIsAITargetValid(GetAttemptedAttackTarget())
                     && !ST_GetIsAITargetValid(ST_GetLastAttackTarget()) // ST: Added...
                     && GetIsObjectValid(oCaster)
                     && GetCommandable() )
                    {
                        //Shout that I was attacked
                        SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                                            	
						// ST: See if leaving oCaster as Intruder here creates focusing problems!
						if (ST_GetIsAITargetValid(oCaster))
                        	GN_DetermineCombatRound(oCaster, 1010);
                        else
                        	GN_DetermineCombatRound(OBJECT_INVALID, 1010);
                    }
                }
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_SPELL_CAST_AT))
                SignalEvent(OBJECT_SELF, EventUserDefined(1010));
        }
        break;
        
        case 1011: //KOTOR_DEFAULT_EVENT_ON_GLOBAL_DIALOGUE_END
        {
            //Added by Aidan March 27,03
            // this allows fleeing creatures to become active after conversation
            if (GetIsEnemy(GetFirstPC()) && (GetCommandable() == FALSE))
                SetCommandable(TRUE);

            //MODIFIED by Preston Watamaniuk on April 25, 2003
            //Put LOS check in for enemies to make a Determine Combat Round is appropriate.
            //If they drop through this function the end result is a GN_WalkWayPoints() call.
            if (GetIsObjectValid(ST_GetNearestEnemy())) {
                if (!IsObjectPartyMember(OBJECT_SELF)) 
                    DelayCommand(0.2, GN_DetermineCombatRound(OBJECT_INVALID, 1011));
            }
            //P.W.(May 20, 2003) - Put an AI flag check here to make sure people do not move against their will.
            else if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                GN_DoPostDCRChecks();
            }

            //JAB-OEI5/21/04
            //Made this change from SW_FLAG_EVENT_DIALOGUE_END
            //The user defined event was not getting called because of this
            //We didn't want to make the change to all the on spawn scripts
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE_END))
                SignalEvent(OBJECT_SELF, EventUserDefined(1011));
        }
        break;
        
        case 1012: //KOTOR_DEFAULT_EVENT_ON_PATH_BLOCKED
        {
			object oBlocker = GetBlockingCreature();
			object oEnemy = GetFoundEnemyCreature();

			// ST: Added this bit... Check out the blocking creature first and see
			//     if it's an enemy. If so, remove them from the path, forcefully.
			if (GetIsObjectValid(oBlocker)
				&& GetCommandable() 
				&& GetIsEnemy(oBlocker)
				&& (oBlocker != GetAttemptedAttackTarget())) 
			{
				// ST: We have bumped into a hostile creature blocking our path.
				if (!GN_GetSpawnInCondition(SW_FLAG_COMMONER_BEHAVIOR)
					&& !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE)
					&& !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
				{
					// ST: Force change the currently focused target!
					ST_SetLastAttackTarget(oBlocker);
					ClearAllActions(); 
					GN_DetermineCombatRound(oBlocker, 1012);
				}		
			}
			// -----
			else if (GetIsObjectValid(oEnemy) 
				&& GetCommandable() 
				&& (oEnemy != GetAttemptedAttackTarget())) 
			{
				// we have tried moving around a creature and encountered a creature that is hostile.
				if (!GN_GetSpawnInCondition(SW_FLAG_COMMONER_BEHAVIOR)
					&& !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE)
					&& !GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
				{
					// ST: Force change the currently focused target!
					ST_SetLastAttackTarget(oEnemy);
					ClearAllActions(); 
					GN_DetermineCombatRound(oEnemy, 1012);
				}
			}
			else if (!GetIsObjectValid(oEnemy) && GetCommandable()) {
				// we are blocked and have no way around this creature.
				// what should happen?
				// ST: We should stand around doing absolutely nothing while our enemies 
				//     kill us from afar... apparently. Oh well, it happens.
				ST_SetLastAttackTarget(OBJECT_INVALID);
			}
        }
        break;
        
        /*
        //HENCHMEN AI EVENTS
        int KOTOR_HENCH_EVENT_ON_HEARTBEAT           = 2001;
        int KOTOR_HENCH_EVENT_ON_PERCEPTION          = 2002;
        int KOTOR_HENCH_EVENT_ON_COMBAT_ROUND_END    = 2003;
        int KOTOR_HENCH_EVENT_ON_DIALOGUE            = 2004;
        int KOTOR_HENCH_EVENT_ON_ATTACKED            = 2005;
        int KOTOR_HENCH_EVENT_ON_DAMAGE              = 2006;
        int KOTOR_HENCH_EVENT_ON_DEATH               = 2007;
        int KOTOR_HENCH_EVENT_ON_DISTURBED           = 2008;
        int KOTOR_HENCH_EVENT_ON_BLOCKED             = 2009;
        int KOTOR_HENCH_EVENT_ON_FORCE_AFFECTED      = 2010;
        int KOTOR_HENCH_EVENT_ON_GLOBAL_DIALOGUE_END = 2011;
        int KOTOR_HENCH_EVENT_ON_PATH_BLOCKED        = 2012;
        int KOTOR_HENCH_EVENT_ON_ENTER_5m            = 2013;
        int KOTOR_HENCH_EVENT_ON_EXIT_5m             = 2014;
        */
        case 2001: //KOTOR_HENCH_EVENT_ON_HEARTBEAT 
        {
            object oEnemy = ST_GetNearestEnemy();

            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF) && !GetSoloMode()) {
                if(GetPartyMemberByIndex(0) != OBJECT_SELF) {
                    // DJS-OEI 3/12/2004
                    // Those that are meditating will only start following if the
                    // currently controlled PC moves more than 15 meters away.                	
                    if(IsObjectPartyMember(OBJECT_SELF)  
                       && (GetCurrentAction(OBJECT_SELF) != ACTION_MOVETOPOINT)
                       && (GetCurrentAction(OBJECT_SELF) != ACTION_FOLLOWLEADER)
                       && !GetIsConversationActive()
                       && !GN_GetSpawnInCondition(SW_FLAG_SPECTATOR_STATE)
                       && GetCommandable() 
                       && (!IsMeditating(OBJECT_SELF) || (IsMeditating(OBJECT_SELF) && (GetDistanceBetween(OBJECT_SELF, GetPartyMemberByIndex(0)) > 15.0))))
                    {
                        if(!GN_GetIsFighting(OBJECT_SELF) && !GetIsObjectValid(oEnemy)) {
                            //The distance checking is now down in the script fired from AI Action Update - Leave 5m Radius of party leader.
                            ClearAllActions();
                            ActionFollowLeader();
                        }
                    }
                }
            }
            else if (GetSoloMode() && GetCurrentAction(OBJECT_SELF) == ACTION_FOLLOWLEADER) {
                ClearAllActions();
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_HEARTBEAT))
                SignalEvent(OBJECT_SELF, EventUserDefined(1001));
        }
        break;
        
        case 2002: //KOTOR_HENCH_EVENT_ON_PERCEPTION
        {
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if((GetPartyMemberByIndex(0) != OBJECT_SELF) && !GetPlayerRestrictMode()) {
                    //If the last perception event was hearing based or if someone vanished then go to search mode
                    if ((GetLastPerceptionVanished()) && GetIsEnemy(GetLastPerceived())) {
                        object oGone = GetLastPerceived();
                        // ST: Use oGone since it was just declared?
                        if(((GetAttemptedAttackTarget() == oGone) 
                        		|| (GetAttemptedSpellTarget() == oGone) 
                        		|| (GetAttackTarget() == oGone)) 
                        	&& GetArea(oGone) != GetArea(OBJECT_SELF))
                        {
							// ST: REMOVED! Let DCR do this if necessary!
                           	// ClearAllActions(); 
                           	GN_DetermineCombatRound(OBJECT_INVALID, 2002);
                        }
                    }
                    //Do not bother checking the last target seen if already fighting
                    else if (!ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                    	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                    	&& !ST_GetIsAITargetValid(GetAttackTarget()))
                    {
                        //Check if the last percieved creature was actually seen
                        if (GetLastPerceptionSeen()) {
                            if (GetIsEnemy(GetLastPerceived())) {
                                object oLeader = GetPartyMemberByIndex(0);
                                if (GetIsObjectValid(GetAttackTarget(oLeader))) {
                                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_SHOUT);
                                    GN_DetermineCombatRound(OBJECT_INVALID, 2002);
                                }
                            }
                        }
                    }
                }
            }
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_PERCEPTION) && GetLastPerceptionSeen())
                SignalEvent(OBJECT_SELF, EventUserDefined(1002));
        }
        break;
        
        case 2003: //KOTOR_HENCH_EVENT_ON_COMBAT_ROUND_END
        {
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                //MODIFIED by Preston Watamaniuk April 14
                //Took out some legacy code for the Endar Spire
                //Changed the shout from Combat Active to I was attacked.

				SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
				GN_DetermineCombatRound(OBJECT_INVALID, 2003);
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_COMBAT_ROUND_END))
                SignalEvent(OBJECT_SELF, EventUserDefined(1003));
        }
        break;
        
        case 2004: //KOTOR_HENCH_EVENT_ON_DIALOGUE
        {
            int nMatch = GetListenPatternNumber();
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if (GetCommandable()) {
                    object oShouter = GetLastSpeaker();
                    object oIntruder;
                    if (nMatch == -1) {
                        ClearAllActions();
                        BeginConversation();
                        return;
                    }
                    else {
                        GN_RespondToShout(oShouter, nMatch, GetLastHostileActor(oShouter));
                    }
                }
            }
            
            if ( nMatch == -1 )
                ResetDialogState();

            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DIALOGUE))
                SignalEvent(OBJECT_SELF, EventUserDefined(1004));
        }
        break;
        
        case 2005: //KOTOR_HENCH_EVENT_ON_ATTACKED
        {
            //Shout that I was attacked
            SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_SHOUT);

            //RWT-OEI 08/28/04 - We need to note if we were last attacked
            //by a Melee weapon so we know that we should switch to melee
            //if we can to defend ourselves.
            object oAttacker = GetLastAttacker();
            object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTWEAPON,oAttacker);

            int nWeaponType = 0;
            if ( GetIsObjectValid(oWeapon))
                nWeaponType = GN_GetWeaponTypeFromBaseItem(GetBaseItemType(oWeapon));
            
            //Indicate that we are being hit by melee. Use the
            //healer AI local number slots since we don't need
            //them for anything else here
            if ( nWeaponType == 1 || nWeaponType == 0)
                SetLocalNumber( OBJECT_SELF, SW_NUMBER_HEALERAI_THRESHOLD, 2);

            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
            	// ST: Uh? You just did this at the start of the event above,
            	//     which was an area broadcast even... Removed.
                // if(GetPartyMemberByIndex(0) == OBJECT_SELF)
                //    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);

                if(GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode()) {
                    if(    !ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                    	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                    	&& !ST_GetIsAITargetValid(GetAttackTarget())) 
					{
                        if(ST_GetIsAITargetValid(GetLastAttacker())) {
                            if(GetArea(GetLastAttacker()) == GetArea(OBJECT_SELF)) {
                                if(!GetIsInCombat())
                                    GN_DetermineCombatRound(OBJECT_INVALID, 2005);
                            }
                        }
                    }
                }
                // ST: I was attacked was already area broadcasted at the top of
                //     the event. Why do it again here with talk range?
                /*
                else
                {
                    //Shout that I was attacked
                    SpeakString("GEN_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
                */
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_ATTACKED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1005));
        }
        break;
        
        case 2006: //KOTOR_HENCH_EVENT_ON_DAMAGE
        {
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if ((GetFirstPC() == OBJECT_SELF)
                   && GetGlobalBoolean("END_BRIDGE_COMBAT")
                   && !GetGlobalBoolean("END_HURT_WARN"))
				{
                    SetGlobalBoolean("END_HURT_WARN", TRUE);
                    BarkString(OBJECT_INVALID,10242);
                    PauseGame(TRUE);
                }
                else if (GetPartyMemberByIndex(0) != OBJECT_SELF && !GetPlayerRestrictMode()) {
                    if (GetCurrentAction() != ACTION_FOLLOWLEADER) {
                        if (!ST_GetIsAITargetValid(GetAttemptedAttackTarget()) && !ST_GetIsAITargetValid(GetAttemptedSpellTarget())) {
                            if (ST_GetIsAITargetValid(GetLastDamager())) {
                                if (!ST_GetIsAITargetValid(GetAttemptedAttackTarget()) 
                                	&& !ST_GetIsAITargetValid(GetAttemptedSpellTarget()) 
                                	&& !ST_GetIsAITargetValid(GetAttackTarget()) )
								{
                                    GN_DetermineCombatRound(OBJECT_INVALID, 2006);
                                    
                                    if (!GN_GetIsFighting(OBJECT_SELF)) {
                                        object oTarget = GetLastDamager();
                                        if (GetIsObjectValid(oTarget)
                                        	&& !GetObjectSeen(oTarget) 
                                        	&& GetArea(OBJECT_SELF) == GetArea(oTarget)) 
                                        {
                                            // ST: Changed move, DCR may not pick the same target,
                                            //     causing unnessecary running around...
                                            //     Just move a few meters in a random direction to
                                            //     hopefully spot the enemy.
                                            // ActionMoveToLocation(GetLocation(oTarget), TRUE);
                                            ActionForceMoveToLocation(Location(GetRandomDestination(OBJECT_SELF, 4), GetFacing(OBJECT_SELF)), TRUE, 3.0);
                                            ActionDoCommand(GN_DetermineCombatRound(OBJECT_INVALID, 2006));
                                        }
                                    }
                                }
                            }
                        }
                        else if (!ST_GetIsAITargetValid(GetAttemptedSpellTarget())) {
                            object oTarget = GetAttackTarget();
                            if(!GetIsObjectValid(oTarget)) 
                                oTarget = GetAttemptedAttackTarget();
                                
                            // ST: Removed level conditional. Let DCR decide such things.
                            //     Only switch priority here if getting badly hurt by someone.
                            object oAttacker = GetLastHostileActor();
                            if (ST_GetIsAITargetValid(oAttacker) 
                            	&& oTarget != oAttacker 
                            	&& GetIsEnemy(oAttacker) 
                            	&& (GetTotalDamageDealt() > (GetMaxHitPoints(OBJECT_SELF) / 4) 
                            		/* ||(GetHitDice(oAttacker) - 2) > GetHitDice(oTarget)*/) )
                            {
                                GN_DetermineCombatRound(oAttacker, 2006);
                            }
                        }
                    }
                }
            }
            
            if(GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_DAMAGED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1006));
        }
        break;
        
        case 2007: //KOTOR_HENCH_EVENT_ON_DEATH
        {

        }
        break;
        
        case 2008: //KOTOR_HENCH_EVENT_ON_DISTURBED
        {

        }
        break;
        
        case 2009: //KOTOR_HENCH_EVENT_ON_BLOCKED
        {
            object oDoor = GetBlockingDoor();
            if (!GN_GetSpawnInCondition(SW_FLAG_AI_OFF)) {
                if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5) {
                    if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && (GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7) )
                        DoDoorAction(oDoor, DOOR_ACTION_OPEN);
                    else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH))
                        DoDoorAction(oDoor, DOOR_ACTION_BASH);
                }
            }
            
            if (GN_GetSpawnInCondition(SW_FLAG_EVENT_ON_BLOCKED))
                SignalEvent(OBJECT_SELF, EventUserDefined(1009));
        }
        break;
        
        case 2013: //KOTOR_HENCH_EVENT_ON_ENTER_5m
        {
            /*
            SetCommandable(TRUE);
            if(!GN_GetSpawnInCondition(SW_FLAG_AI_OFF))
            {
                if(!GetUserActionsPending())
                {
                    if(GetCurrentAction(GetPartyMemberByIndex(0)) == ACTION_ATTACKOBJECT ||
                       GetCurrentAction(GetPartyMemberByIndex(0)) == ACTION_CASTSPELL)
                    {
                        GN_DetermineCombatRound();
                    }
                }
            }
            */
        }
        break;
        
        case 2014: //KOTOR_HENCH_EVENT_ON_EXIT_5m
        {
		    // ST: Added ----------------------------------------------
		    // A rather ugly hack, but somewhat effective at preventing them
		    // from rushing off when an attack order is issued on a remote target.
		    if ((GetNPCAIStyle(OBJECT_SELF) == NPC_AISTYLE_PARTY_SUPPORT) 
		    	&& !GetSoloMode()
		    	&& IsObjectPartyMember(OBJECT_SELF)) 
		    {	
		    	object oAttack = GetAttemptedAttackTarget();
		    	object oMove = GetAttemptedMovementTarget();
		    	object oSpell = GetAttemptedSpellTarget();
		    	object oLeader = GetPartyLeader();
		    	
		    	int bStop = FALSE;
		    	int nAction = GetCurrentAction();
		    	float fModDist = ST_DEFENSIVE_RADIUS - 0.5;
		    	
		    	if (((nAction == ACTION_CASTSPELL) || (nAction == ACTION_ITEMCASTSPELL))
		    		&& GetIsObjectValid(oSpell) 
		    		&& GetIsEnemy(oSpell)) 
		    	{
		    		fModDist += 10.0;
		    	}
		    	else {
		    		fModDist += ST_GetAttackRange();	
		    	}	
		    	
		    	if (((nAction == ACTION_ATTACKOBJECT) || (nAction == 39))
		    		&& GetIsObjectValid(oAttack) 
		    		&& GetIsEnemy(oAttack)
		    		&& (GetDistanceBetween2D(oLeader, oAttack) > fModDist)) 	    		
		    	{
					bStop = TRUE;
		    	}
		    	else if (((nAction == ACTION_CASTSPELL) || (nAction == ACTION_ITEMCASTSPELL))
		    		&& GetIsObjectValid(oSpell) 
		    		&& GetIsEnemy(oSpell)
		    		&& (GetDistanceBetween2D(oLeader, oSpell) > fModDist)) 	    		
		    	{
					bStop = TRUE;
		    	}
		    	else if ((nAction == ACTION_MOVETOPOINT)
		    		&& GetIsObjectValid(oMove) 
		    		&& GetIsEnemy(oMove)
		    		&& (GetDistanceBetween2D(oLeader, oMove) > fModDist)) 	    		
		    	{
					bStop = TRUE;
		    	}	    		    	
		    	
	    		if (bStop) {
		    		ClearAllActions();
		    		ActionForceMoveToObject(oLeader, TRUE, 2.0, 15.0);
	    		}	    	
		    }
        }
        break;
    }
}

 

 

 

 

Share this post


Link to post
Share on other sites

HardcoreTSL's k_ai_master.nss looks to be just the original code Preston wrote for KotOR 1, but I don't know. I found it in the Source Scripts folder of HardcoreModTSL.

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn
// ST: Uncommenting the line below would include beancounters hardcore mod in the AI.//     Note that the code at line 158 needs to be uncommented as well,//     the HCMod source placed in this folder and the scripts recompiled.// #include "Hardcore_Mod"

 

There ya go

 

Edit: bless stoffe, the commenting is so helpful

Share this post


Link to post
Share on other sites

I'm glad that there's a potential resolution to this (and very grateful for all your help so far) but could I get a walkthrough with that? Especially with

the HCMod source placed in this folder and the scripts recompiled.// #include "Hardcore_Mod"

Share this post


Link to post
Share on other sites
Guest Qui-Gon Glenn

Yes. You need to take the first k_ai_master.nss that you quoted first, which I assume is from the beancounter mod (aka "HCMod source"), and put it into the stoffe's Improved AI folder. Uncomment the #include"Hardcore_Mod" (remove the //), and then k_ai_master needs to be recompiled drawing from beancounter's version.

Basically, somehow beancounter's mod gets turned into an include file, which may mean a renaming of the file k_ai_master from beancounter's mod to Hardcore_Mod, but honestly my memory is pretty fuzzy on include files at the moment.

@fairstrides, how many things am I forgetting :p

Share this post


Link to post
Share on other sites

Hey there fellas I've been reading over this board and since I'm an idiot and don't know how to script or anything I was wondering if anyone could make a video of how to combine both of these mods together so I don't mess anything up? I have both of the mods in folders already with the improved ai mod already installed. Also for line 158 It's only the "/*" I was under the impression of the definition I got from google that in order to uncomment something it had to be listed as "//" or am I looking at it wrong? I would appreciate the gesture if anyone can spare the time or has a link to it already being done. Thanks 😃 

 

P.S. I know this thread is a little old so hopefully someone replies.

Edited by Triad24

Share this post


Link to post
Share on other sites

So what code exactly am I putting there after the /* and before the */ after I remove them??? Am I copying all of the text inside beancounter's k_ai_master file and inserting it into that one place of Improved A.I. k_ai_master file or??? Because this is what is in between those two.

 // ST: This would add beancounters hardcore mod to the Creature AI, if uncommented and recompiled:
            /*
			if (!GetPlayerRestrictMode() && !GetFeatAcquired(FEAT_IMPLANT_LEVEL_1))
    			Hardcore_Mod(); 
    		*/

 

I'm confused because up on the thread  Qui-Gon Glenn states that 

On 8/23/2018 at 3:53 PM, Qui-Gon Glenn said:

k_ai_master needs to be recompiled drawing from beancounter's version

Which I have no idea what that means. but then what he states after confuses me more. 

 

On 8/23/2018 at 3:53 PM, Qui-Gon Glenn said:

Basically, somehow beancounter's mod gets turned into an include file, which may mean a renaming of the file k_ai_master from beancounter's mod to Hardcore_Mod, but honestly my memory is pretty fuzzy on include files at the moment.

I apologize if all of this is simple to you guys but I'm more of a visual learner.

Edited by Triad24

Share this post


Link to post
Share on other sites
19 hours ago, Triad24 said:

So what code exactly am I putting there after the /* and before the */ after I remove them???

Nothing. The code is already there. Removing the comment characters transforms the in between block of text from a comment back into actual code.

Share this post


Link to post
Share on other sites

I'm just going to link this if you don't mind taking a look at it. It's a list of steps I took. And didn't get any results. I'd appreciate it if you took a look at it and let me know what I could've done wrong. Thanks you :)

Share this post


Link to post
Share on other sites

I've been trying to combine the two mods together too. What I did to merge them is:

1. Download both the Hardcore mod and the Improved AI mod.

2. Look in the "Source Scripts" folder of the Hardcore mod. You will notice a few source script (nss) files. Open "Hardcore_mod.nss" in a text editor and you will see

#include "HC_Control"

The HC_Control.nss file is used for custom difficulty, but you can change the file included in the script to another file in the directory for a predefined difficulty (e.g. "HC_Control-Hard"). If you wish to use a custom difficulty, edit "HC_Control.nss" to your liking, otherwise just make sure you've included the correct file of the difficulty of your choice.

3. Now copy both "Hardcore_mod.nss" and your included file into the "tlspatchdata" folder of your Improved AI mod download. 

4. As has been previously mentioned in this post, open up "k_ai_master.nss" in a text editor and uncomment line 21 (by removing the '//'). After uncommented it should appear thus:

#include "Hardcore_Mod"

Then remove the /* and */, such that:

 // ST: This would add beancounters hardcore mod to the Creature AI, if uncommented and recompiled:
            /*
			if (!GetPlayerRestrictMode() && !GetFeatAcquired(FEAT_IMPLANT_LEVEL_1))
    			Hardcore_Mod(); 
    		*/

becomes:

 // ST: This would add beancounters hardcore mod to the Creature AI, if uncommented and recompiled:
            
			if (!GetPlayerRestrictMode() && !GetFeatAcquired(FEAT_IMPLANT_LEVEL_1))
    			Hardcore_Mod(); 
    		

5. This next step assumes you don't want the High Level Force Powers mod. My steps here were to edit the "st_inc_powers.nss" file such that:

const int ST_GLOBAL_ENABLE_POWERS 	= FALSE; // Set to TRUE to enable, FALSE to disable.
const int ST_GLOBAL_ENABLE_BOSS_POWERS	= FALSE; // Set to TRUE to enable, FALSE to disable.

I then changed the following code to all equal zero (as my spells.2da file is unedited*). 

6. Use the "nwnnsscomp.exe" file provided with the Improved AI mod to compile your edited scripts. To do this, use the command:

nwnnsscomp -c k_ai_master.nss

This will generate an ncs file called "k_ai_master.ncs".

7. Copy this newly generated file into the "static" folder within "tslpatchdata" (you can replace the file if you want, or you can make a backup first. Up to you). 

8. Now simply copy all of the ncs files in the static folder into your KoTOR2 Override folder.

 

Hope these steps help :) Assuming you haven't already got it working lol! But hopefully this will be useful for anyone trying to get it working too.

I tested it very briefly by loading up a save

Spoiler

before fighting three enemies whose ritual you most rudely interrupted lol.

I got absolutely destroyed so the hardcore mod was definitely active!

 

*The HLFP mod adds entries for the extra force powers into the spells.2da file. I think the idea is to find the line numbers of the added entries and edit those into "st_inc_powers.nss".

  • Like 1

Share this post


Link to post
Share on other sites

i'm trying to figure this out based on the previous post and it makes 0 sense.. which k_ai am i editing to add the line to?  and what is this "included file" from? the hardcore mod? the improved AI mod?

edit: mostly figured it out but now i can't get it to compile when running nwnnsscomp.exe it just opens a command prompt and closes near instantly and there's no way to add the -c k_ai_master.nss command with properties

Edited by Divinehero

Share this post


Link to post
Share on other sites
On 7/11/2020 at 9:20 AM, Divinehero said:

i can't get it to compile when running nwnnsscomp.exe it just opens a command prompt and closes near instantly and there's no way to add the -c k_ai_master.nss command with properties

Same, anyone know how to compile that?

On 1/17/2020 at 11:23 AM, Davik Kang said:

This next step assumes you don't want the High Level Force Powers mod. My steps here were to edit the "st_inc_powers.nss" file such that:


const int ST_GLOBAL_ENABLE_POWERS 	= FALSE; // Set to TRUE to enable, FALSE to disable.
const int ST_GLOBAL_ENABLE_BOSS_POWERS	= FALSE; // Set to TRUE to enable, FALSE to disable.

I then changed the following code to all equal zero (as my spells.2da file is unedited*). 

And what should I change to zero? All things below?

Share this post


Link to post
Share on other sites

You can't run nwnnsscomp by double clicking it. It's a commandline program. You need to run it from a DOS prompt.

  • Open a command window Start -> Run -> cmd and navigate to the location of nwnnsscomp (you'll have to Google how to do that)
  • Alternatively, on Windows 10 go here and download one of the REG files to enable a context menu "Open command window here" in any folder
  • Run your command.
  • Alternatively to all that, create a batch file that will compile all NSS files in the current directory:
@echo off

rem CHANGE THIS TO YOUR LOCAL NWNNSSCOMP FOLDER:
set nwnsscompdir=F:\Star Wars Knights of the Old Republic\-=TOOLS=-\NWNSSCOMP\K1

rem NOTE THAT YOU NEED SEPARATE VERSIONS FOR K1 AND TSL, EACH WITH
rem THEIR OWN GAME-SPECIFIC VERSION OF NWSCRIPT.NSS

for %%F in (*.nss) do (
  if not "%%~nF"=="nwscript" (
    "%nwnsscompdir%\nwnnsscomp.exe" -c "%~dp0%%~nF.nss" -o "%~dp0%%~nF.ncs"
  ) else (
    echo Skipping: %%F
  )
)

pause

Just copy and paste it into a text file and save as xxx.bat (note that you will need specific K1 and TSL versions, as described).

As far as the other question, TRUE is 1 and FALSE is 0. So whatever statements you set to 0 will be set to FALSE.

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.