PWE_PRC8/_module/_removed/nw_i0_generic.nss
Jaysyn904 ee1dc35889 Initial Commit
Initial Commit
2025-04-03 10:29:41 -04:00

1691 lines
58 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Generic Scripting Include v1.0
//:: NW_I0_GENERIC
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
December 7 2002, Naomi Novik
Many functions removed to separate libraries:
x0_i0_anims
PlayMobileAmbientAnimations_NonAvian
PlayMobileAmbientAnimations_Avian
(with PlayMobileAmbientAnimations changed to
just a call to one of these two)
PlayImmobileAmbientAnimations
x0_i0_assoc
associate constants (NW_ASC_...)
GetPercentageHPLoss (only used in GetAssociateHealMaster)
SetAssociateState
GetAssociateState
ResetHenchmenState
AssociateCheck
GetAssociateHealMaster
GetFollowDistance
SetAssociateStartLocation
GetAssociateStartLocation
x0_i0_behavior
behavior constants
SetBehaviorState
GetBehaviorState
x0_i0_spawncond
OnSpawn condition constants
SetSpawnInCondition
GetSpawnInCondition
SetSpawnInLocals
SetListeningPatterns
x0_i0_walkway
WalkWayPoints
RunNextCircuit
RunCircuit
CheckWayPoints
GetIsPostOrWalking
x0_i0_talent
ALL the talent functions
x0_i0_equip
Equipping functions
x0_i0_match
Matching functions
x0_i0_debug
MyPrintString
DebugPrintTalentId
newdebug
x0_inc_generic
Pretty much everything else
***********************************************'
CHANGE SUMMARY
February 6 2003: Commented out the Henchman RespondToShout because now using
the newer bkRespondToShout function in x0_i0_henchman
September 18 2002: DetermineCombatRound broken into smaller functions
19 : Removed randomness from Talent system. You can't
have smart AI and random behavior. Only healing
has the possiblity of being random.
I may want to add the possibility of getting a
random talent only in the Talent filter if
something fails (*)
********************************************
WARNING THIS SCRIPT IS CHANGED AT YOUR PERIL
********************************************
This is the master generic script and currently
handles all combat and some plot behavior
within NWN. If this script is tampered
with there is a chance of introducing game
breaking bugs. But other than that enjoy.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Sept 20, 2001
//:://////////////////////////////////////////////
//#include "x0_i0_assoc" - included in x0_inc_generic
//#include "x0_inc_generic" - included in x0_i0_talent
//#include "x0_i0_talent" - included in x0_i0_combat
//#include "x0_i0_combat" - include in x0_i0_anims
//#include "x0_i0_walkway" - include in x0_i0_anims
#include "x0_i0_behavior"
#include "x0_i0_anims"
/**********************************************************************
* CONSTANTS
**********************************************************************/
/**********************************************************************
* Flee and move constants
**********************************************************************/
int NW_GENERIC_FLEE_EXIT_FLEE = 0;
int NW_GENERIC_FLEE_EXIT_RETURN = 1;
int NW_GENERIC_FLEE_TELEPORT_FLEE = 2;
int NW_GENERIC_FLEE_TELEPORT_RETURN = 3;
/**********************************************************************
* Shout constats
**********************************************************************/
// NOT USED
int NW_GENERIC_SHOUT_I_WAS_ATTACKED = 1;
//IN OnDeath Script
int NW_GENERIC_SHOUT_I_AM_DEAD = 12;
//IN TalentMeleeAttacked
int NW_GENERIC_SHOUT_BACK_UP_NEEDED = 13;
int NW_GENERIC_SHOUT_BLOCKER = 2;
/**********************************************************************
* FUNCTION PROTOTYPES
**********************************************************************/
// * New Functions September - 2002
// * The class-specific tactics have been broken out from DetermineCombatRound
// * for readability. This function determines the actual tactics each class
// * will use.
int chooseTactics(object oIntruder);
// Adds all three of the class levels together. Used before
// GetHitDice became available
int GetCharacterLevel(object oTarget);
//If using ambient sleep this will remove the effect
void RemoveAmbientSleep();
//Searches for the nearest locked object to the master
object GetLockedObject(object oMaster);
/**********************************************************************
* DetermineCombatRound subfunctions
**********************************************************************/
// Used in DetermineCombatRound to keep a
// henchmen bashing doors.
int BashDoorCheck(object oIntruder = OBJECT_INVALID);
// Determines which of a NPCs three classes to
// use in DetermineCombatRound
int DetermineClassToUse();
/**********************************************************************
* Core AI Functions
**********************************************************************/
//::///////////////////////////////////////////////
//:: DetermineCombatRound
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This function is the master function for the
generic include and is called from the main
script. This function is used in lieu of
any actual scripting.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 16, 2001
//:://////////////////////////////////////////////
void DetermineCombatRound(object oIntruder = OBJECT_INVALID, int nAI_Difficulty = 10);
//::///////////////////////////////////////////////
//:: Respond To Shouts
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
// Allows the listener to react in a manner
// consistant with the given shout but only to one
// combat shout per round
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
//NOTE ABOUT COMMONERS
// Commoners are universal cowards. If you attack anyone
// they will flee for 4 seconds away from the attacker.
// However to make the commoners into a mob, make a single
// commoner at least 10th level of the same faction.
// If that higher level commoner is attacked or killed then
// the commoners will attack the attacker. They will disperse again
// after some of them are killed. Should NOT make multi-class
// creatures using commoners.
//
//NOTE ABOUT BLOCKERS
// It should be noted that the Generic Script for On Dialogue
// attempts to get a local set on the shouter by itself.
// This object represents the LastOpenedBy object. It is this
// object that becomes the oIntruder within this function.
//
//NOTE ABOUT INTRUDERS
// The intruder object is for cases where a placable needs to
// pass a LastOpenedBy Object or a AttackMyAttacker
// needs to make his attacker the enemy of everyone.
void RespondToShout(object oShouter, int nShoutIndex, object oIntruder = OBJECT_INVALID);
//******** PLOT FUNCTIONS
// NPCs who have warning status set to TRUE will allow
// one 'free' attack by PCs from a non-hostile faction.
void SetNPCWarningStatus(int nStatus = TRUE);
// NPCs who have warning status set to TRUE will allow
// one 'free' attack by PCs from a non-hostile faction.
int GetNPCWarningStatus();
// * Presently Does not work with the current implementation
// * of encounter triggers!
//
// This function works in tandem with an encounter
// to spawn in guards to fight for the attacked
// NPC. MAKE SURE THE ENCOUNTER TAG IS SET TO:
//
// "ENC_" + NPC TAG
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 29, 2001
void SetSummonHelpIfAttacked();
// The target object flees to the specified
// way point and then destroys itself, to be
// respawned at a later point. For unkillable
// sign post characters who are not meant to fight
// back.
// This function is used only because ActionDoCommand can
// only accept void functions.
void CreateSignPostNPC(string sTag, location lLocal);
// The target object flees to the specified
// way point and then destroys itself, to be
// respawned at a later point. For unkillable
// sign post characters who are not meant to fight
// back.
void ActivateFleeToExit();
// The target object flees to the specified
// way point and then destroys itself, to be
// respawned at a later point. For unkillable
// sign post characters who are not meant to fight
// back.
int GetFleeToExit();
// Checks that an item was unlocked.
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 19, 2001
void CheckIsUnlocked(object oLastObject);
// This function is now just a wrapper around the functions
// PlayMobileAmbientAnimations_Nonavian() and
// PlayMobileAmbientAnimations_Avian(), in x0_i0_anims
void PlayMobileAmbientAnimations();
// Determines the special behavior used by the NPC.
// Generally all NPCs who you want to behave differently
// than the defualt behavior.
// For these behaviors, passing in a valid object will
// cause the creature to become hostile the the attacker.
void DetermineSpecialBehavior(object oIntruder = OBJECT_INVALID);
/**********************************************************************
* FUNCTION DEFINITIONS
**********************************************************************/
//::///////////////////////////////////////////////
//:: chooseTactics
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Separated this function out from DetermineCombatRound
for readibility
*/
//:://////////////////////////////////////////////
//:: Created By: Brent
//:: Created On: September 2002
//:://////////////////////////////////////////////
int chooseTactics(object oIntruder)
{
// SpawnScriptDebugger();
// SELF PRESERVATION: Always attempt to heal self first
if(TalentHealingSelf() == TRUE) return 99; //Use spells and potions
// Next, try the special tactics routines
// specific to XP1
if (SpecialTactics(oIntruder)) return 99;
// * These constants in ChooseTactics routine
// * remember previous rounds choices
int MEMORY_OFFENSE_MELEE = 0;
int MEMORY_DEFENSE_OTHERS = 1;
int MEMORY_DEFENSE_SELF = 2;
int MEMORY_OFFENSE_SPELL = 3;
// * If defensive last round, try to be offensive this round
// * this is to prevent wasting time on multiple protections
int nPreviousMemory = GetLocalInt(OBJECT_SELF, "NW_L_MEMORY");
int nClass = DetermineClassToUse();
int nOffense, nCompassion, nCoward, nMagic, nCrazy = 0;
// * Defaulted high so unspecified classes will not be cowards
nOffense = 50;
nCompassion = 25;
// * Defaulted this high because non standard creatures
// * with spells should try and use them.
nMagic = 55;
int nDiff;
string sDiff;
// * setup base BEHAVIOR
switch (nClass)
{
case CLASS_TYPE_COMMONER:
// Commoners should run away from fights
nOffense = 0; nCompassion = 0; nMagic = 0; nCoward = 10; break;
case CLASS_TYPE_WIZARD:
case CLASS_TYPE_SORCERER:
nOffense = 40; nCompassion = 40; nMagic = 100; break;
case CLASS_TYPE_BARD:
nOffense = 40; nCompassion = 42; nMagic = 43; break;
case CLASS_TYPE_CLERIC:
case CLASS_TYPE_DRUID:
{
nOffense = 40;
nCompassion = 45;
nMagic = 44;
// * Clerics shouldn't constantly cast spells
if (nPreviousMemory != MEMORY_OFFENSE_MELEE)
nMagic = Random(50) + 1;
break;
}
case CLASS_TYPE_PALADIN :
case CLASS_TYPE_RANGER :
nOffense = 40; nCompassion = 25; nMagic = Random(50) + 1; break;
case CLASS_TYPE_BARBARIAN:
// SpawnScriptDebugger();
// * GetHasFeat(...) does not work correctly with no-leveled up
// * characters. So for now, only Xanos gets to do this.
nDiff = GetCombatDifficulty(oIntruder);
sDiff = IntToString(nDiff);
//SendMessageToPC(GetFirstPC(), "Difficulty is " +sDiff);
if (GetCombatDifficulty(oIntruder) >= 15) //Changed 69MEH69
{
if (GetHasFeatEffect(FEAT_BARBARIAN_RAGE) == FALSE)
{
if (GetHasFeat(FEAT_BARBARIAN_RAGE) == TRUE)
{
ActionUseFeat(FEAT_BARBARIAN_RAGE, OBJECT_SELF);
return 99;
}
}
}
nOffense = 50; nCompassion = 25; nMagic = 20; break;
// * set high magic to use rage
// * suggestion don't give barbarians lots of magic or else they will fight oddly
case CLASS_TYPE_FIGHTER:
case CLASS_TYPE_ROGUE :
case CLASS_TYPE_MONK :
nOffense = 40; nCompassion = 0; nMagic = 0; break;
case CLASS_TYPE_UNDEAD:
nOffense = 40; nCompassion = 40; nMagic = 40; break;
case CLASS_TYPE_OUTSIDER:
{
nOffense = 40; nCompassion = 0; nMagic = 40;
if (GetAlignmentGoodEvil(OBJECT_SELF) == ALIGNMENT_GOOD)
{
nCompassion = 40;
}
break;
}
case CLASS_TYPE_CONSTRUCT:
case CLASS_TYPE_ELEMENTAL:
nOffense = 40; nCompassion = 0; nMagic = 40; break;
case CLASS_TYPE_DRAGON:
nOffense = 40; nCompassion = 20; nMagic = 40; break;
}
// MyPrintString("Made it past the class-specific settings");
// ************************************
// * MODIFY BEHAVIOR FOR SPECIAL CASES
// ************************************
if (GetRacialType(OBJECT_SELF) == RACIAL_TYPE_UNDEAD)
nCompassion = nCompassion - 20;
// Randomize things a bit
nOffense = Random(10 + nCrazy) + nOffense - nCoward;
nMagic = Random(10 + nCrazy) + nMagic;
nCompassion = Random(10 + nCrazy) + nCompassion;
// * if your opponent is close to you, then increase offense
// * as casting defensive abilities when enemies are close
// * is generally not a good idea.
// * Dec 18 2002: If you have Combat Casting, you'll still be more
// * liable to use defensive abilities
if (GetIsObjectValid(oIntruder) && !GetHasFeat(FEAT_COMBAT_CASTING)) {
if (GetDistanceToObject(oIntruder) <= 5.0) {
nOffense = nOffense + 20;
nMagic = nMagic - 20;
}
}
// * If enemies are further away, more chance of doing magic
if (GetDistanceToObject(oIntruder) > 3.0)
nMagic = nMagic + 15;
// * Dec 18 2002: Add your level to your magic rating
nMagic = nMagic + GetHitDice(OBJECT_SELF);
// **************************************
// * CHOOSE TALENT TO USE
// **************************************
//SpawnScriptDebugger();
// * If defensive last round, try to be offensive this round
// * this is to prevent wasting time on multiple protections
if ((nPreviousMemory == MEMORY_DEFENSE_OTHERS)
|| (nPreviousMemory == MEMORY_DEFENSE_SELF))
{
nOffense = nOffense + 40;
}
// April 2003
// If in rage should be almost no chance of doing magic
if (GetHasFeatEffect(FEAT_BARBARIAN_RAGE) == TRUE)
{
nMagic = 0;
}
// SpeakString("BUG!! Magic " + IntToString(nMagic) + " Compassion " + IntToString(nCompassion) + " Offense " + IntToString(nOffense));
// MyPrintString("Offense " + IntToString(nOffense)
// + " Magic " + IntToString(nMagic)
// + " Compassion " + IntToString(nCompassion));
//(Offense <= 5), (MAGIC > 50) MAGICAL, NO OFFENSE
//new InvisibleFlee
// PHYSICAL, NO OFFENSE
if (nOffense <= 5)
if (TalentFlee(oIntruder) == TRUE) return 99;
// protect others: MAGICAL, DEFENSE, COMPASSION
if ((nOffense<= 50) && (nMagic > 50) && (nCompassion > 50))
{
SetLocalInt(OBJECT_SELF, "NW_L_MEMORY", MEMORY_DEFENSE_OTHERS);
if (TalentHeal() == TRUE) return 99;
if (TalentCureCondition() == TRUE) return 99;
if (TalentUseProtectionOthers() == TRUE) return 99;
if (TalentEnhanceOthers() == TRUE) return 99;
// * Temporarily be non-compassionate to buff self
// * if we got to this point.
nCompassion = 0;
}
// protectself: MAGICAL, DEFENSE, NO COMPASSION
if ((nOffense<= 50) && (nMagic > 50) && (nCompassion <=50))
{
SetLocalInt(OBJECT_SELF, "NW_L_MEMORY", MEMORY_DEFENSE_SELF);
/* Dec 19 2002:
Against spell-casters, cast protection spells more often
*/
int nClass = GetClassByPosition(1,oIntruder);
if (nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_SORCERER
|| nClass == CLASS_TYPE_CLERIC || nClass == CLASS_TYPE_DRUID)
{
if (TalentSelfProtectionMantleOrGlobe())
return 99;
}
if(TalentBardSong() == TRUE) return 99;
if(TalentUseProtectionOnSelf() == TRUE) return 99;
if(TalentUseEnhancementOnSelf() == TRUE) return 99;
if(TalentPersistentAbilities() == TRUE) return 99;
// int TalentAdvancedBuff(float fDistance);
//Used for Potions of Enhancement and Protection
if(TalentBuffSelf() == TRUE) return 99;
if(TalentAdvancedProtectSelf() == TRUE) return 99;
if(TalentSummonAllies() == TRUE) return 99;
if(TalentSeeInvisible() == TRUE) return 99;
if(TalentMeleeAttacked(oIntruder) == TRUE) return 99;
if(TalentRangedAttackers(oIntruder) == TRUE) return 99;
if(TalentRangedEnemies(oIntruder) == TRUE) return 99;
}
// MAGICAL, OFFENSE
if (nMagic > 50)
{
// MyPrintString("in offensive spell");
// SpawnScriptDebugger();
SetLocalInt(OBJECT_SELF, "NW_L_MEMORY", MEMORY_OFFENSE_SPELL);
if (TalentUseTurning() == TRUE) return 99;
if (TalentSpellAttack(oIntruder) == TRUE) return 99;
}
// If we got here, we're going to melee offense
SetLocalInt(OBJECT_SELF, "NW_L_MEMORY", MEMORY_OFFENSE_MELEE);
// PHYSICAL, OFFENSE (if nothing else applies)
if (TalentSneakAttack() == TRUE) return 99;
if (TalentDragonCombat(oIntruder)) {return 99;}
if (TalentMeleeAttack(oIntruder) == TRUE) return 99;
object oHostile = GetNearestSeenEnemy();
// * Feb 17 2003: This error could happen in the situation that someone
// * went into combat mode and their 'hostility' ended while going through ChooseTactics
if (GetIsObjectValid(oHostile) == TRUE)
{
// * BK if it returns this it means the AI found nothing
// * Appropriate to do
//SpeakString("BUG!!!!!!!!!!!!!!!!!!!!!!!! (Let Brent Knowles know about this. Supply savegame) Nothing valid to do !!!!!!!!!!!!!!!!!!!!!");
//SpeakString("BUG!! Magic " + IntToString(nMagic) + " Compassion " + IntToString(nCompassion) + " Offense " + IntToString(nOffense));
}
return 1;
} // * END of choosetactics
//::///////////////////////////////////////////////
//:: DetermineCombatRound
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This function is the master function for the
generic include and is called from the main
script. This function is used in lieu of
any actual scripting.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 16, 2001
//:://////////////////////////////////////////////
void DetermineCombatRound(object oIntruder = OBJECT_INVALID, int nAI_Difficulty = 10)
{
MyPrintString("************** DETERMINE COMBAT ROUND START *************");
MyPrintString("************** " + GetTag(OBJECT_SELF) + " ************");
// May 2003
// Abort out of here, if petrified
if (GetHasEffect(EFFECT_TYPE_PETRIFY, OBJECT_SELF) == TRUE)
{
return;
}
/* Dec 19 2002:
If I have already decided on a course of action
for this round, then stick to it.
***WARNING*** This change has the potential to
cause ai-stoppages, however it is necessary
to prevent multiple determinecombatrounds to
run in the same round.
*/
/* Except this doesn't just prevent multiple calls
* in the same round, it prevents calls in subsequent
* rounds, causing us to just use a standard attack
* over and over and over! -- NN
*/
/* Keep commented out as a reminder not to do this...
if(GetIsObjectValid(GetAttemptedAttackTarget())
||
*/
// * Trying to prevent spellcasting only from being interuppted
if (GetIsObjectValid(GetAttemptedSpellTarget()) && GetCurrentAction(OBJECT_SELF) == ACTION_CASTSPELL)
{
object oDebugSpellTarget = GetAttemptedSpellTarget();
int nDebugAction = GetCurrentAction(OBJECT_SELF);
// SpawnScriptDebugger();
// SpeakString("Casting spell on self");
return;
}
else
{
// SpeakString("Yep, I'm interrupting my combat round");
}
// ********************************
// * DetermineCombatRound: EVALUATIONS
// ********************************
if(GetAssociateState(NW_ASC_IS_BUSY))
{
return;
}
if(BashDoorCheck(oIntruder)) {return;}
// * MODIFIED FEBRUARY 13 2003: This code already in the Henchmen determine combat round
//This check is to see if the master is being attacked and in need of help
/*if(GetAssociateState(NW_ASC_HAVE_MASTER))
{
if(GetAssociateState(NW_ASC_MODE_DEFEND_MASTER))
{
oIntruder = GetLastHostileActor(GetMaster());
if(!GetIsObjectValid(oIntruder))
{
oIntruder = GetGoingToBeAttackedBy(GetMaster());
if(!GetIsObjectValid(oIntruder))
{
oIntruder = GetLastHostileActor();
if(!GetIsObjectValid(oIntruder))
{
return;
}
else if(!GetIsEnemy(oIntruder))
{
oIntruder = OBJECT_INVALID;
}
}
}
}
}
*/
// * BK: stop fighting if something bizarre that shouldn't happen, happens
if (bkEvaluationSanityCheck(oIntruder, GetFollowDistance()) == TRUE)
return;
// ** Store HOw Difficult the combat is for this round
int nDiff = GetCombatDifficulty();
SetLocalInt(OBJECT_SELF, "NW_L_COMBATDIFF", nDiff);
MyPrintString("COMBAT: " + IntToString(nDiff));
//***************TARGETTING****************************************
// * If no special target has been passed into the function
// * then choose an appropriate target
if (GetIsObjectValid(oIntruder) == FALSE)
oIntruder = bkAcquireTarget();
if (GetIsDead(oIntruder) == TRUE)
{
// * if for some reason my target is dead, then leave
// * the poor guy alone. Jeez. What kind of monster am I?
return;
}
// ********************************
// * DetermineCombatRound: ACTIONS
// ********************************
if(GetIsObjectValid(oIntruder))
{
// * Will put up things like Auras quickly
if(TalentPersistentAbilities()) {
return;
}
// *BK September 2002
// * If a succesful tactic has been chosen then
// * exit this function directly
if (chooseTactics(oIntruder) == 99) {
return;
}
//This check is to make sure that people do not drop out of
// combat before they are supposed to.
//SpeakString("BUG Determine Combat Round stopped prematurely");
object oNearEnemy = GetNearestSeenEnemy();
DetermineCombatRound(oNearEnemy);
return;
}
//This is a call to the function which determines which
// way point to go back to.
ClearActions(CLEAR_NW_I0_GENERIC_658);
SetLocalObject(OBJECT_SELF,
"NW_GENERIC_LAST_ATTACK_TARGET",
OBJECT_INVALID);
WalkWayPoints();
}
//::///////////////////////////////////////////////
//:: Respond To Shouts
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Allows the listener to react in a manner
consistant with the given shout but only to one
combat shout per round
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 25, 2001
//:://////////////////////////////////////////////
//NOTE ABOUT COMMONERS
/*
Commoners are universal cowards. If you attack anyone they will flee for 4 seconds away from the attacker.
However to make the commoners into a mob, make a single commoner at least 10th level of the same faction.
If that higher level commoner is attacked or killed then the commoners will attack the attacker. They will disperse again
after some of them are killed. Should NOT make multi-class creatures using commoners.
*/
//NOTE ABOUT BLOCKERS
/*
It should be noted that the Generic Script for On Dialogue attempts to get a local set on the shouter by itself.
This object represents the LastOpenedBy object. It is this object that becomes the oIntruder within this function.
*/
//NOTE ABOUT INTRUDERS
/*
The intruder object is for cases where a placable needs to pass a LastOpenedBy Object or a AttackMyAttacker
needs to make his attacker the enemy of everyone.
*/
void RespondToShout(object oShouter, int nShoutIndex, object oIntruder = OBJECT_INVALID)
{
// Pausanias: Do not respond to shouts if you've surrendered.
int iSurrendered = GetLocalInt(OBJECT_SELF,"Generic_Surrender");
if (iSurrendered) return;
switch (nShoutIndex)
{
case 1://NW_GENERIC_SHOUT_I_WAS_ATTACKED:
{
object oTarget = oIntruder;
if(!GetIsObjectValid(oTarget))
{
oTarget = GetLastHostileActor(oShouter);
}
if(!GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
{
if(!GetLevelByClass(CLASS_TYPE_COMMONER))
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
{
if(GetIsObjectValid(oTarget))
{
if(!GetIsFriend(oTarget) && GetIsFriend(oShouter))
{
RemoveAmbientSleep();
//DetermineCombatRound(oTarget);
DetermineCombatRound(GetLastHostileActor(oShouter));
}
}
}
}
else if (GetLevelByClass(CLASS_TYPE_COMMONER, oShouter) >= 10)
{
WrapperActionAttack(GetLastHostileActor(oShouter));
}
else
{
DetermineCombatRound(oIntruder);
}
}
else
{
DetermineSpecialBehavior();
}
}
break;
case 2://NW_GENERIC_SHOUT_MOB_ATTACK:
{
if(!GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
{
//Is friendly check to make sure that only like minded commoners attack.
if(GetIsFriend(oShouter))
{
WrapperActionAttack(GetLastHostileActor(oShouter));
}
//if(TalentMeleeAttack()) {return;}
}
else
{
DetermineSpecialBehavior();
}
}
break;
case 3://NW_GENERIC_SHOUT_I_AM_DEAD:
{
if(!GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
{
//Use I was attacked script above
if(!GetLevelByClass(CLASS_TYPE_COMMONER))
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
{
if(GetIsObjectValid(GetLastHostileActor(oShouter)))
{
if(!GetIsFriend(GetLastHostileActor(oShouter)) && GetIsFriend(oShouter))
{
DetermineCombatRound(GetLastHostileActor(oShouter));
}
}
}
}
else if (GetLevelByClass(CLASS_TYPE_COMMONER, oShouter) >= 10)
{
WrapperActionAttack(GetLastHostileActor(oShouter));
}
else
{
DetermineCombatRound();
}
}
else
{
DetermineSpecialBehavior();
}
}
break;
//For this shout to work the object must shout the following
//string sHelp = "NW_BLOCKER_BLK_" + GetTag(OBJECT_SELF);
case 4: //BLOCKER OBJECT HAS BEEN DISTURBED
{
if(!GetLevelByClass(CLASS_TYPE_COMMONER))
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()))
{
if(GetIsObjectValid(oIntruder))
{
SetIsTemporaryEnemy(oIntruder);
DetermineCombatRound(oIntruder);
}
}
}
else if (GetLevelByClass(CLASS_TYPE_COMMONER, oShouter) >= 10)
{
WrapperActionAttack(oIntruder);
}
else
{
DetermineCombatRound();
}
}
break;
case 5: //ATTACK MY TARGET
{
AdjustReputation(oIntruder, OBJECT_SELF, -100);
if(GetIsFriend(oShouter))
{
SetIsTemporaryEnemy(oIntruder);
ClearActions(CLEAR_NW_I0_GENERIC_834);
DetermineCombatRound(oIntruder);
}
}
break;
case 6: //CALL_TO_ARMS
{
//This was once commented out.
DetermineCombatRound();
}
break;
//ASSOCIATE SHOUT RESPONSES ******************************************************************************
/* This was moved into X0_I0_HENCHMAN as bkRespondToHenchmenShout
case ASSOCIATE_COMMAND_ATTACKNEAREST: //Used to de-activate AGGRESSIVE DEFEND MODE
{
ResetHenchmenState();
SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE);
SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE);
DetermineCombatRound();
}
break;
case ASSOCIATE_COMMAND_FOLLOWMASTER: //Only used to retreat, or break free from Stand Ground Mode
{
ResetHenchmenState();
SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE);
DelayCommand(2.5, VoiceCanDo());
if(GetAssociateState(NW_ASC_AGGRESSIVE_STEALTH))
{
//ActionUseSkill(SKILL_HIDE, OBJECT_SELF);
}
if(GetAssociateState(NW_ASC_AGGRESSIVE_SEARCH))
{
ActionUseSkill(SKILL_SEARCH, OBJECT_SELF);
}
ActionForceFollowObject(GetMaster(), GetFollowDistance());
SetAssociateState(NW_ASC_IS_BUSY);
DelayCommand(5.0, SetAssociateState(NW_ASC_IS_BUSY, FALSE));
}
break;
case ASSOCIATE_COMMAND_GUARDMASTER: //Used to activate AGGRESSIVE DEFEND MODE
{
ResetHenchmenState();
DelayCommand(2.5, VoiceCanDo());
//Companions will only attack the Masters Last Attacker
SetAssociateState(NW_ASC_MODE_DEFEND_MASTER);
SetAssociateState(NW_ASC_MODE_STAND_GROUND, FALSE);
if(GetIsObjectValid(GetLastHostileActor(GetMaster())))
{
DetermineCombatRound(GetLastHostileActor(GetMaster()));
}
}
break;
case ASSOCIATE_COMMAND_HEALMASTER: //Ignore current healing settings and heal me now
{
ResetHenchmenState();
//SetCommandable(TRUE);
if(TalentCureCondition()) {DelayCommand(2.0, VoiceCanDo()); return;}
if(TalentHeal(TRUE)) {DelayCommand(2.0, VoiceCanDo()); return;}
DelayCommand(2.5, VoiceCannotDo());
}
break;
case ASSOCIATE_COMMAND_MASTERFAILEDLOCKPICK: //Check local for Re-try locked doors and
{
if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND))
{
if(GetAssociateState(NW_ASC_RETRY_OPEN_LOCKS))
{
int bValid = TRUE;
object oLastObject = GetLockedObject(GetMaster());
int nSkill = GetSkillRank(SKILL_OPEN_LOCK) - GetAbilityModifier(ABILITY_DEXTERITY);
if(GetIsObjectValid(oLastObject) && GetPlotFlag(oLastObject) == FALSE)
{
if(GetIsDoorActionPossible(oLastObject, DOOR_ACTION_KNOCK) || GetIsPlaceableObjectActionPossible(oLastObject, PLACEABLE_ACTION_KNOCK))
{
ClarAllActions();
VoiceCanDo();
ActionCastSpellAtObject(SPELL_KNOCK, oLastObject);
ActionWait(1.0);
bValid = FALSE;
}
else if (GetIsDoorActionPossible(oLastObject, DOOR_ACTION_UNLOCK)|| GetIsPlaceableObjectActionPossible(oLastObject, PLACEABLE_ACTION_UNLOCK))
{
ClarAllActions();
VoicePicklock();
ActionWait(1.0);
ActionUseSkill(SKILL_OPEN_LOCK,oLastObject);
bValid = FALSE;
}
else if(nSkill < 5 && GetAbilityScore(OBJECT_SELF, ABILITY_STRENGTH) >= 16 && GetSkillRank(SKILL_OPEN_LOCK) <= 0)
{
if(GetIsDoorActionPossible(oLastObject, DOOR_ACTION_BASH) || GetIsPlaceableObjectActionPossible(oLastObject, PLACEABLE_ACTION_BASH))
{
ClarAllActions();
VoiceCanDo();
ActionEquipMostDamagingMelee(oLastObject);
WrapperActionAttack(oLastObject);
SetLocalObject(OBJECT_SELF, "NW_GENERIC_DOOR_TO_BASH", oLastObject);
bValid = FALSE;
}
}
if(bValid == TRUE)
{
//ClarAllActions();
VoiceCannotDo();
}
else
{
ActionDoCommand(VoiceTaskComplete());
}
}
}
}
}
break;
case ASSOCIATE_COMMAND_MASTERUNDERATTACK: //Check whether the master has you in AGGRESSIVE DEFEND MODE
{
if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND))
{
//Check the henchmens current target
object oTarget = GetAttemptedAttackTarget();
if(!GetIsObjectValid(oTarget))
{
oTarget = GetAttemptedSpellTarget();
if(!GetIsObjectValid(oTarget))
{
if(GetAssociateState(NW_ASC_MODE_DEFEND_MASTER))
{
DetermineCombatRound(GetLastHostileActor(GetMaster()));
}
else
{
DetermineCombatRound();
}
}
}
//Switch targets only if the target is not attacking the master and is greater than 6.0 from
//the master.
if(GetAttackTarget(oTarget) != GetMaster() && GetDistanceBetween(oTarget, GetMaster()) > 6.0)
{
if(GetAssociateState(NW_ASC_MODE_DEFEND_MASTER) && GetIsObjectValid(GetLastHostileActor(GetMaster())))
{
DetermineCombatRound(GetLastHostileActor(GetMaster()));
}
}
}
}
break;
case ASSOCIATE_COMMAND_STANDGROUND: //No longer follow the master or guard him
{
SetAssociateState(NW_ASC_MODE_STAND_GROUND);
SetAssociateState(NW_ASC_MODE_DEFEND_MASTER, FALSE);
DelayCommand(2.0, VoiceCanDo());
WrapperActionAttack(OBJECT_INVALID);
ClarAllActions();
}
break;
case ASSOCIATE_COMMAND_MASTERSAWTRAP:
{
int nCheck = 0;
if(!GetIsInCombat())
{
if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND))
{
object oTrap = GetLastTrapDetected();
if(GetIsObjectValid(oTrap))
{
int nTrapDC = GetTrapDisarmDC(oTrap);
int nSkill = GetSkillRank(SKILL_DISABLE_TRAP);
int nMod = GetAbilityModifier(ABILITY_DEXTERITY);
if((nSkill - nMod) > 0)
{
nSkill = nSkill + 20 - nTrapDC;
}
else
{
nSkill = 0;
nCheck = 1;
}
if(GetCurrentAction(OBJECT_SELF) != ACTION_DISABLETRAP && nSkill > 0)
{
VoiceStop();
if(GetHasSkill(SKILL_DISABLE_TRAP, OBJECT_SELF))
{
ClarAllActions();
ActionUseSkill(SKILL_DISABLE_TRAP, oTrap);
ActionDoCommand(SetCommandable(TRUE));
ActionDoCommand(VoiceTaskComplete());
SetCommandable(FALSE);
nCheck = 2;
}
}
else if(nCheck = 0 &&
GetSkillRank(SKILL_DISABLE_TRAP) > 0 &&
GetCurrentAction(OBJECT_SELF) != ACTION_DISABLETRAP)
{
VoiceCannotDo();
}
}
}
}
}
break;
case ASSOCIATE_COMMAND_MASTERATTACKEDOTHER:
{
if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND))
{
if(!GetAssociateState(NW_ASC_MODE_DEFEND_MASTER))
{
if(!GetIsFighting(OBJECT_SELF))
{
object oAttack = GetAttackTarget(GetMaster());
if(GetIsObjectValid(oAttack) && GetObjectSeen(oAttack))
{
ClarAllActions();
DetermineCombatRound(oAttack);
}
}
}
}
}
break;
case ASSOCIATE_COMMAND_MASTERGOINGTOBEATTACKED:
{
if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND))
{
if(!GetIsFighting(OBJECT_SELF))
{
object oAttacker = GetGoingToBeAttackedBy(GetMaster());
if(GetIsObjectValid(oAttacker) && GetObjectSeen(oAttacker))
{
ClarAllActions();
DetermineCombatRound(oAttacker);
}
}
}
}
break;
case ASSOCIATE_COMMAND_LEAVEPARTY:
{
object oMaster = GetMaster();
if(GetIsObjectValid(oMaster))
{
ClarAllActions();
if(GetAssociate(ASSOCIATE_TYPE_HENCHMAN, GetMaster()) == OBJECT_SELF)
{
AddJournalQuestEntry("Henchman",50,GetMaster(),FALSE,FALSE,TRUE);
}
SetLocalObject(OBJECT_SELF,"NW_L_FORMERMASTER", oMaster);
RemoveHenchman(oMaster, OBJECT_SELF);
}
}
break; */
}
}
//::///////////////////////////////////////////////
//:: Set and Get NPC Warning Status
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This function sets a local int on OBJECT_SELF
which will be checked in the On Attack, On
Damaged and On Disturbed scripts to check if
the offending party was a PC and was friendly.
The Get will return the status of the local.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 29, 2001
//:://////////////////////////////////////////////
// NPCs who have warning status set to TRUE will allow
// one 'free' attack by PCs from a non-hostile faction.
void SetNPCWarningStatus(int nStatus = TRUE)
{
SetLocalInt(OBJECT_SELF, "NW_GENERIC_WARNING_STATUS", nStatus);
}
// NPCs who have warning status set to TRUE will allow
// one 'free' attack by PCs from a non-hostile faction.
int GetNPCWarningStatus()
{
return GetLocalInt(OBJECT_SELF, "NW_GENERIC_WARNING_STATUS");
}
//::///////////////////////////////////////////////
//:: Set SummonHelpIfAttacked
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This function works in tandem with an encounter
to spawn in guards to fight for the attacked
NPC. MAKE SURE THE ENCOUNTER TAG IS SET TO:
"ENC_" + NPC TAG
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 29, 2001
//:://////////////////////////////////////////////
//Presently Does not work with the current implementation of encounter trigger
void SetSummonHelpIfAttacked()
{
string sEncounter = "ENC_" + GetTag(OBJECT_SELF);
object oTrigger = GetObjectByTag(sEncounter);
if(GetIsObjectValid(oTrigger))
{
SetEncounterActive(TRUE, oTrigger);
}
}
//************************************************************************************************************************************
//************************************************************************************************************************************
//
// ESCAPE FUNCTIONS
//
//************************************************************************************************************************************
//************************************************************************************************************************************
//::///////////////////////////////////////////////
//:: Set, Get Activate,Flee to Exit
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
The target object flees to the specified
way point and then destroys itself, to be
respawned at a later point. For unkillable
sign post characters who are not meant to fight
back.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 29, 2001
//:://////////////////////////////////////////////
//This function is used only because ActionDoCommand can only accept void functions
void CreateSignPostNPC(string sTag, location lLocal)
{
CreateObject(OBJECT_TYPE_CREATURE, sTag, lLocal);
}
void ActivateFleeToExit()
{
object oExitWay = GetWaypointByTag("EXIT_" + GetTag(OBJECT_SELF));
int nPlot = GetLocalInt(OBJECT_SELF, "NW_GENERIC_MASTER");
location lLocal = GetLocalLocation(OBJECT_SELF, "NW_GENERIC_START_POINT");
float fDelay = 6.0;
string sTag = GetTag(OBJECT_SELF);
if(nPlot & NW_FLAG_TELEPORT_RETURN || nPlot & NW_FLAG_TELEPORT_LEAVE)
{
effect eVis = EffectVisualEffect(VFX_IMP_UNSUMMON);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF);
if(nPlot & NW_FLAG_TELEPORT_RETURN)
{
DelayCommand(fDelay, ActionDoCommand(CreateSignPostNPC(sTag, lLocal)));
}
ActionDoCommand(DestroyObject(OBJECT_SELF, 0.75));
}
else
{
if(nPlot & NW_FLAG_ESCAPE_LEAVE)
{
ActionMoveToObject(oExitWay, TRUE);
ActionDoCommand(DestroyObject(OBJECT_SELF, 1.0));
}
else if(nPlot & NW_FLAG_ESCAPE_RETURN)
{
ActionMoveToObject(oExitWay, TRUE);
DelayCommand(fDelay, ActionDoCommand(CreateSignPostNPC(sTag, lLocal)));
ActionDoCommand(DestroyObject(OBJECT_SELF, 1.0));
}
}
}
int GetFleeToExit()
{
int nPlot = GetLocalInt(OBJECT_SELF, "NW_GENERIC_MASTER");
if(nPlot & NW_FLAG_ESCAPE_RETURN)
{
return TRUE;
}
else if(nPlot & NW_FLAG_ESCAPE_LEAVE)
{
return TRUE;
}
else if(nPlot & NW_FLAG_TELEPORT_RETURN)
{
return TRUE;
}
else if(nPlot & NW_FLAG_TELEPORT_LEAVE)
{
return TRUE;
}
return FALSE;
}
//**********************************
//**********************************
//**********************************
// PRIVATE FUNCTIONS
//**********************************
//**********************************
//**********************************
//This is experimental and has not been looked at closely.
void ExitAOESpellArea(object oAOEObject)
{
ClearActions(CLEAR_NW_I0_GENERIC_ExitAOESpellArea);
ActionMoveAwayFromObject(oAOEObject, TRUE, 5.0);
AssignCommand(OBJECT_SELF, DetermineCombatRound());
}
//::///////////////////////////////////////////////
//:: Get Character Levels
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Returns the combined class levels of the
target.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Oct 22, 2001
//:://////////////////////////////////////////////
int GetCharacterLevel(object oTarget)
{
return GetHitDice(oTarget);
}
//::///////////////////////////////////////////////
//:: Remove Ambient Sleep
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Checks if the NPC has sleep on them because
of ambient animations. Sleeping creatures
must make a DC 15 listen check.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Feb 27, 2002
//:://////////////////////////////////////////////
void RemoveAmbientSleep()
{
if(GetHasEffect(EFFECT_TYPE_SLEEP))
{
effect eSleep = GetFirstEffect(OBJECT_SELF);
while(GetIsEffectValid(eSleep))
{
if(GetEffectCreator(eSleep) == OBJECT_SELF)
{
int nRoll = d20();
nRoll += GetSkillRank(SKILL_LISTEN);
nRoll += GetAbilityModifier(ABILITY_WISDOM);
if(nRoll > 15)
{
RemoveEffect(OBJECT_SELF, eSleep);
}
}
eSleep = GetNextEffect(OBJECT_SELF);
}
}
}
//::///////////////////////////////////////////////
//:: Get Locked Object
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Finds the closest locked object to the object
passed in up to a maximum of 10 objects.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: March 15, 2002
//:://////////////////////////////////////////////
object GetLockedObject(object oMaster)
{
int nCnt = 1;
int bValid = TRUE;
object oLastObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, GetLocation(oMaster), nCnt);
while (GetIsObjectValid(oLastObject) && bValid == TRUE)
{
//COMMENT THIS BACK IN WHEN DOOR ACTION WORKS ON PLACABLE.
//object oItem = GetFirstItemInInventory(oLastObject);
if(GetLocked(oLastObject))
{
return oLastObject;
}
nCnt++;
if(nCnt == 10)
{
bValid = FALSE;
}
oLastObject = GetNearestObjectToLocation(OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE, GetLocation(oMaster), nCnt);
}
return OBJECT_INVALID;
}
//::///////////////////////////////////////////////
//:: Check if an item is locked
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Checks that an item was unlocked.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Nov 19, 2001
//:://////////////////////////////////////////////
void CheckIsUnlocked(object oLastObject)
{
if(GetLocked(oLastObject))
{
ActionDoCommand(VoiceCuss());
}
else
{
ActionDoCommand(VoiceCanDo());
}
}
//::///////////////////////////////////////////////
//:: Play Mobile Ambient Animations
//:: This function is now just a wrapper around
//:: code from x0_i0_anims.
//:://////////////////////////////////////////////
void PlayMobileAmbientAnimations()
{
if(!GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) {
// not a bird
PlayMobileAmbientAnimations_NonAvian();
} else {
// a bird
PlayMobileAmbientAnimations_Avian();
}
}
//::///////////////////////////////////////////////
//:: Determine Special Behavior
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Determines the special behavior used by the NPC.
Generally all NPCs who you want to behave differently
than the defualt behavior.
For these behaviors, passing in a valid object will
cause the creature to become hostile the the attacker.
MODIFIED February 7 2003:
- Rearranged logic order a little so that the creatures
will actually randomwalk when not fighting
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Dec 14, 2001
//:://////////////////////////////////////////////
void DetermineSpecialBehavior(object oIntruder = OBJECT_INVALID)
{
object oTarget = GetNearestSeenEnemy();
if(GetBehaviorState(NW_FLAG_BEHAVIOR_OMNIVORE))
{
int bAttack = FALSE;
if(!GetIsObjectValid(oIntruder))
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) &&
!GetIsObjectValid(GetAttemptedSpellTarget()) &&
!GetIsObjectValid(GetAttackTarget()))
{
if(GetIsObjectValid(oTarget) && GetDistanceToObject(oTarget) <= 8.0)
{
if(!GetIsFriend(oTarget))
{
if(GetLevelByClass(CLASS_TYPE_DRUID, oTarget) == 0 && GetLevelByClass(CLASS_TYPE_RANGER, oTarget) == 0)
{
SetIsTemporaryEnemy(oTarget, OBJECT_SELF, FALSE, 20.0);
bAttack = TRUE;
DetermineCombatRound(oTarget);
}
}
}
}
}
else if(!IsInConversation(OBJECT_SELF))
{
bAttack = TRUE;
DetermineCombatRound(oIntruder);
}
// * if not attacking, the wander
if (bAttack == FALSE)
{
ClearActions(CLEAR_NW_I0_GENERIC_DetermineSpecialBehavior1);
ActionRandomWalk();
return;
}
}
else if(GetBehaviorState(NW_FLAG_BEHAVIOR_HERBIVORE))
{
if(!GetIsObjectValid(GetAttemptedAttackTarget()) &&
!GetIsObjectValid(GetAttemptedSpellTarget()) &&
!GetIsObjectValid(GetAttackTarget()))
{
if(GetIsObjectValid(oTarget) && GetDistanceToObject(oTarget) <= 6.0)
{
if(!GetIsFriend(oTarget))
{
if(GetLevelByClass(CLASS_TYPE_DRUID, oTarget) == 0 && GetLevelByClass(CLASS_TYPE_RANGER, oTarget) == 0)
{
TalentFlee(oTarget);
}
}
}
}
else if(!IsInConversation(OBJECT_SELF))
{
ClearActions(CLEAR_NW_I0_GENERIC_DetermineSpecialBehavior2);
ActionRandomWalk();
return;
}
}
}
//::///////////////////////////////////////////////
//:: Bash Doors
//:: Copyright (c) 2002 Bioware Corp.
//:://////////////////////////////////////////////
/*
Used in DetermineCombatRound to keep a
henchmen bashing doors.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: April 4, 2002
//:://////////////////////////////////////////////
int BashDoorCheck(object oIntruder = OBJECT_INVALID)
{
int bDoor = FALSE;
//This code is here to make sure that henchmen keep bashing doors and placables.
object oDoor = GetLocalObject(OBJECT_SELF, "NW_GENERIC_DOOR_TO_BASH");
// * MODIFICATION February 7 2003 BK
// * don't bash trapped doors.
if (GetIsTrapped(oDoor) ) return FALSE;
if(GetIsObjectValid(oDoor))
{
int nDoorMax = GetMaxHitPoints(oDoor);
int nDoorNow = GetCurrentHitPoints(oDoor);
int nCnt = GetLocalInt(OBJECT_SELF,"NW_GENERIC_DOOR_TO_BASH_HP");
if(!GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN))
|| (!GetIsObjectValid(oIntruder) && !GetIsObjectValid(GetMaster())))
{
if(GetLocked(oDoor))
{
if(nDoorMax == nDoorNow)
{
nCnt++;
SetLocalInt(OBJECT_SELF,"NW_GENERIC_DOOR_TO_BASH_HP", nCnt);
}
if(nCnt <= 0)
{
bDoor = TRUE;
if(GetHasFeat(FEAT_IMPROVED_POWER_ATTACK))
{
ActionUseFeat(FEAT_IMPROVED_POWER_ATTACK, oDoor);
}
else if(GetHasFeat(FEAT_POWER_ATTACK))
{
ActionUseFeat(FEAT_POWER_ATTACK, oDoor);
}
else
{
WrapperActionAttack(oDoor);
}
}
}
}
if(bDoor == FALSE)
{
VoiceCuss();
DeleteLocalObject(OBJECT_SELF, "NW_GENERIC_DOOR_TO_BASH");
DeleteLocalInt(OBJECT_SELF, "NW_GENERIC_DOOR_TO_BASH_HP");
}
}
return bDoor;
}
//::///////////////////////////////////////////////
//:: Determine Class to Use
//:: Copyright (c) 2002 Bioware Corp.
//:://////////////////////////////////////////////
/*
Determines which of a NPCs three classes to
use in DetermineCombatRound
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: April 4, 2002
//:://////////////////////////////////////////////
int DetermineClassToUse()
{
int nClass;
int nTotal = GetHitDice(OBJECT_SELF);
float fTotal = IntToFloat(nTotal);
int nState1 = FloatToInt((IntToFloat(GetLevelByClass(GetClassByPosition(1))) / fTotal) * 100);
MyPrintString(GetTag(OBJECT_SELF) + "Class: " + IntToString(GetClassByPosition(1)) + " %" + IntToString(nState1));
int nState2 = FloatToInt((IntToFloat(GetLevelByClass(GetClassByPosition(2))) / fTotal) * 100) + nState1;
MyPrintString(GetTag(OBJECT_SELF) + "Class: " + IntToString(GetClassByPosition(2)) + " %" + IntToString(nState2));
int nState3 = FloatToInt((IntToFloat(GetLevelByClass(GetClassByPosition(3))) / fTotal) * 100) + nState2;
MyPrintString(GetTag(OBJECT_SELF) + "Class: " + IntToString(GetClassByPosition(3)) + " %" + IntToString(nState3));
int nUseClass = d100();
MyPrintString("D100 Roll " + IntToString(nUseClass));
if(nUseClass <= nState1)
{
nClass = GetClassByPosition(1);
}
else if(nUseClass > nState1 && nUseClass <= nState2)
{
nClass = GetClassByPosition(2);
}
else
{
nClass = GetClassByPosition(3);
}
MyPrintString(GetName(OBJECT_SELF) + " Return Class = " + IntToString(nClass));
return nClass;
}
/* DO NOT CLOSE THIS TOP COMMENT!
This main() function is here only for compilation testing.
void main() {}
/* */