////:://////////////////////////////////////////////// //:: Generic Scripting Include v1.0 //:: NW_I0_GENERIC //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* ******************************************** 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 "jw_talents_inc" #include "jw_walkways_inc" //GENERIC STRUCTURES struct sSpellSelect { int RANGED; int MELEE; object GROUP_TARGET; object MOB_TARGET; object MELEE_TOUGHEST; object TOUGHEST_TARGET; int ENEMY_HD; int ALLIED_HD; }; //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 constants int NW_GENERIC_SHOUT_I_WAS_ATTACKED = 1; // NOT USED int NW_GENERIC_SHOUT_I_AM_DEAD = 12; //IN OnDeath Script int NW_GENERIC_SHOUT_BACK_UP_NEEDED = 13; //IN TalentMeleeAttacked int NW_GENERIC_SHOUT_BLOCKER = 2; //Master Constants int NW_FLAG_SPECIAL_CONVERSATION = 0x00000001; int NW_FLAG_SHOUT_ATTACK_MY_TARGET = 0x00000002; int NW_FLAG_STEALTH = 0x00000004; int NW_FLAG_SEARCH = 0x00000008; int NW_FLAG_SET_WARNINGS = 0x00000010; int NW_FLAG_ESCAPE_RETURN = 0x00000020; //Failed int NW_FLAG_ESCAPE_LEAVE = 0x00000040; int NW_FLAG_TELEPORT_RETURN = 0x00000080; //Failed int NW_FLAG_TELEPORT_LEAVE = 0x00000100; int NW_FLAG_PERCIEVE_EVENT = 0x00000200; int NW_FLAG_ATTACK_EVENT = 0x00000400; int NW_FLAG_DAMAGED_EVENT = 0x00000800; int NW_FLAG_SPELL_CAST_AT_EVENT = 0x00001000; int NW_FLAG_DISTURBED_EVENT = 0x00002000; int NW_FLAG_END_COMBAT_ROUND_EVENT = 0x00004000; int NW_FLAG_ON_DIALOGUE_EVENT = 0x00008000; int NW_FLAG_RESTED_EVENT = 0x00010000; int NW_FLAG_DEATH_EVENT = 0x00020000; int NW_FLAG_SPECIAL_COMBAT_CONVERSATION = 0x00040000; int NW_FLAG_AMBIENT_ANIMATIONS = 0x00080000; int NW_FLAG_HEARTBEAT_EVENT = 0x00100000; int NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 0x00200000; int NW_FLAG_DAY_NIGHT_POSTING = 0x00400000; int NW_FLAG_AMBIENT_ANIMATIONS_AVIAN = 0x00800000; int NW_FLAG_APPEAR_SPAWN_IN_ANIMATION = 0x01000000; int NW_FLAG_SLEEPING_AT_NIGHT = 0x02000000; int NW_FLAG_FAST_BUFF_ENEMY = 0x04000000; //Behavior Constants int NW_FLAG_BEHAVIOR_SPECIAL = 0x00000001; int NW_FLAG_BEHAVIOR_CARNIVORE = 0x00000002; //Will always attack regardless of faction int NW_FLAG_BEHAVIOR_OMNIVORE = 0x00000004; //Will only attack if approached int NW_FLAG_BEHAVIOR_HERBIVORE = 0x00000008; //Will never attack. Will alway flee. //CORE AI FUNCTIONS void DetermineCombatRound(object oIntruder = OBJECT_INVALID, int nAI_Difficulty = 10); void SetListeningPatterns(); void RespondToShout(object oShouter, int nShoutIndex, object oIntruder = OBJECT_INVALID); //PLOT FUNCTIONS void SetNPCWarningStatus(int nStatus = TRUE); int GetNPCWarningStatus(); void SetSummonHelpIfAttacked(); void CreateSignPostNPC(string sTag, location lLocal); void ActivateFleeToExit(); int GetFleeToExit(); //AMBIENT ANIMATION COMMANDS void PlayMobileAmbientAnimations(); void PlayImmobileAmbientAnimations(); //BEHAVIOR LOCAL FUNCTIONS void SetBehaviorState(int nCondition, int bValid = TRUE); int GetBehaviorState(int nCondition); void DetermineSpecialBehavior(object oIntruder = OBJECT_INVALID); //:://///////////////////////////////////////////// //:: Master Local Get and Set //:: FileName //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* All On Spawn in conditions in the game are now being stored within one local. The get and set changed or checks the condition of this one Hex local. The NW_FLAG_XXX variables above allow for the user of these functions throughout the generic scripts. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Nov 14, 2001 //::////////////////////////////////////////////// //:://///////////////////////////////////////////// //:: 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) + " ****************************************"); if(GetAssociateState(NW_ASC_IS_BUSY)) { return; } // very first thing we do is run away if we are a commoner or coward object oAttacker=GetTarget(); int nCoward=FALSE; if ((GetLevelByClass(CLASS_TYPE_COMMONER)>=1)||(GetLocalInt(OBJECT_SELF,"coward")==TRUE)) { nCoward=TRUE; } if ((GetObjectSeen(oAttacker))&&(nCoward==TRUE)) { TalentFlee(oAttacker); return; } /* // Added this to try to fix bug of mobs not attacking object oHostile=GetLastHostileActor(); if (!GetIsEnemy(oHostile)) { SetIsTemporaryEnemy(oHostile); SetIsTemporaryEnemy(OBJECT_SELF,oHostile); } */ if (GetHasEffect(EFFECT_TYPE_FRIGHTENED)||GetHasEffect(EFFECT_TYPE_TURNED)) { ClearAllActions(); TalentFlee(oAttacker); return; } if (GetHasEffect(EFFECT_TYPE_PARALYZE)||GetHasEffect(EFFECT_TYPE_STUNNED)||GetHasEffect(EFFECT_TYPE_CUTSCENE_PARALYZE)) { return; } if (!GetIsObjectValid(oIntruder)) { oIntruder=ChooseTarget(); } if (!GetObjectSeen(oIntruder)||!GetIsObjectValid(oIntruder)||GetIsDeadOrBleeding(oIntruder)) { oIntruder=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN_AND_HEARD); } if (!GetIsObjectValid(oIntruder)) { oIntruder=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN_AND_NOT_HEARD); } if (!GetIsObjectValid(oIntruder)) { oIntruder=GetNearestCreature(CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,OBJECT_SELF,1,CREATURE_TYPE_PERCEPTION,PERCEPTION_HEARD_AND_NOT_SEEN); } int nClass = DetermineClassToUse(); ///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; } } } } } if(GetIsObjectValid(GetMaster())) { if(GetDistanceToObject(GetMaster()) > 15.0) { if(GetCurrentAction(GetMaster()) != ACTION_FOLLOW) { ClearAllActions(); //ActionAttack(OBJECT_INVALID); ActionForceFollowObject(GetMaster(), GetFollowDistance()); //ActionForceMoveToObject(GetMaster(), TRUE, GetFollowDistance(), 5.0); return; } } } int nOffense = d100(); MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "Offense Roll " + IntToString(nOffense)); if(GetIsObjectValid(oIntruder) || GetIsObjectValid(GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN)) || (GetIsObjectValid(oIntruder) && GetIsObjectValid(GetMaster()))) { ///// Palmer's list of things the mob will do. //Use healing potions to not die if(TalentHealingSelf()) { return;} //Check if allies or self are injured if(TalentHeal()) { return;} // Heal undead // Heal undead is not currently working //if(TalentHealUndead()) { return;} if(TalentPersistentAbilities()) { return;} // use aura if(TalentDismissal(oIntruder)) { return;} // dismiss summoned mob if possible if(TalentSummonAllies()) {return;} //Summon allies if posible // if(TalentBlackguardAura(oIntruder)) { return;} // do blackgaurd aura if possible if(TalentBardSong()) { return;} // do bard song if possible if(TalentCurseSong(oIntruder)) { return;} // do curse song if possible if(TalentBuffSelf()) { return;} // use potions on self if(TalentUseEnhancementOnSelf()) { return;} //Use Enhancements on self if(TalentEnhanceOthers()) { return;} //use enhancement on others if(TalentUseProtectionOnSelf()) { return;} // use basic protection on self if(TalentUseProtectionOthers()) {return;} //Check if the character can enhance themselves if(TalentCureCondition()) { return;} //cure allies if(TalentMimicCombat(oIntruder)) { return;} // MimicCombat if(TalentThrowTree(oIntruder)) { return;} // Throw a tree if(TalentBlindSpit(oIntruder)) { return;} // spitting spider attack if(TalentGarotte (oIntruder)) { return;} // Use a garotte if(TalentDispelEffects(oIntruder)) { return;} // Dispel effects if possible if(TalentDragonCombat(oIntruder)) { return;} // use dragon breath if(TalentSneakAttack()) { return;} // sneak if rogue if(TalentAdvancedProtectSelf()) {return;} //******************************************// //Use advanced protections on Self if(TalentFlyToEnemy(oIntruder)) { return;} // fly to enemy if (TalentWingBlast(oIntruder)) {return;} if (TalentUseTurning()) { return;} // turn undead if(TalentRangedAttackers(oIntruder)) { return;} //cast ranged spells if(TalentRangedEnemies(oIntruder)) { return;} // cast ranged spells if(TalentMeleeAttacked(oIntruder)) { return;} // cast melee spells if(TalentSpellAttack(oIntruder)) {return;} //Spell Attack if(TalentMeleeAttack(oIntruder)) { return;} // just hit them if(TalentFlee(oIntruder)) { return;} // run away SendMessageToAllDMs("My AI is failing, I am "+GetName(OBJECT_SELF)+" in "+GetName(GetArea(OBJECT_SELF))); return; } //This check is to make sure that people do not drop out of combat before they are supposed to. object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN); if(GetIsObjectValid(oTarget)) { SpeakString("Danger Will Robinson Danger"); DetermineCombatRound(oTarget); return; } //This is a call to the function which determines which way point to go back to. ClearAllActions(); SetLocalObject(OBJECT_SELF, "NW_GENERIC_LAST_ATTACK_TARGET", OBJECT_INVALID); WalkWayPoints(); } //:://///////////////////////////////////////////// //:: SetListeningPatterns //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* Sets the correct listen checks on the NPC by determining what talents they possess or what class they use. This is also a good place to set up all of the sleep and appear disappear animations for various models. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Oct 24, 2001 //::////////////////////////////////////////////// void SetListeningPatterns() { //There is a 70% chance to make someone sleep if it is night. //If they have no way points to walk. if(GetIsNight() && !CheckWayPoints()) { if(GetSpawnInCondition(NW_FLAG_SLEEPING_AT_NIGHT)) { if(d10() <= 7) { int nRand = Random(361); SetFacing(IntToFloat(nRand)); //effect eSleep = EffectSleep(); //ApplyEffectToObject(DURATION_TYPE_PERMANENT, eSleep, OBJECT_SELF); } } } if(GetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION)) { MyPrintString("GENERIC SCRIPT DEBUG STRING ********** " + "USING SPAWN IN CONDITION NOW BASTARDO"); effect eAppear = EffectAppear(); ApplyEffectToObject(DURATION_TYPE_INSTANT, eAppear, OBJECT_SELF); } SetListening(OBJECT_SELF, TRUE); SetListenPattern(OBJECT_SELF, "NW_I_WAS_ATTACKED", 1); //This sets the commoners listen pattern to mob under //certain conditions if(GetLevelByClass(CLASS_TYPE_COMMONER) > 0) { SetListenPattern(OBJECT_SELF, "NW_MOB_ATTACK", 2); } SetListenPattern(OBJECT_SELF, "NW_I_AM_DEAD", 3); //Set a custom listening pattern for the creature so that placables with //"NW_BLOCKER" + Blocker NPC Tag will correctly call to their blockers. string sBlocker = "NW_BLOCKER_BLK_" + GetTag(OBJECT_SELF); SetListenPattern(OBJECT_SELF, sBlocker, 4); SetListenPattern(OBJECT_SELF, "NW_CALL_TO_ARMS", 6); } //:://///////////////////////////////////////////// //:: 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) { 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) { ActionAttack(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)) { ActionAttack(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) { ActionAttack(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) { ActionAttack(oIntruder); } else { DetermineCombatRound(); } } break; case 5: //ATTACK MY TARGET { if(GetIsFriend(oShouter)) { SetIsTemporaryEnemy(oIntruder,OBJECT_SELF,TRUE,180.0); ClearAllActions(); DetermineCombatRound(oIntruder); } } break; case 6: //CALL_TO_ARMS { //This was once commented out. DetermineCombatRound(); } break; //ASSOCIATE SHOUT RESPONSES ****************************************************************************** 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, PlayVoiceChat(VOICE_CHAT_CANDO)); 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, PlayVoiceChat(VOICE_CHAT_CANDO)); //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, PlayVoiceChat(VOICE_CHAT_CANDO)); return;} if(TalentHeal(TRUE)) {DelayCommand(2.0, PlayVoiceChat(VOICE_CHAT_CANDO)); return;} DelayCommand(2.5, PlayVoiceChat(VOICE_CHAT_CANTDO)); } 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)) { ClearAllActions(); PlayVoiceChat(VOICE_CHAT_CANDO); ActionCastSpellAtObject(SPELL_KNOCK, oLastObject); ActionWait(1.0); bValid = FALSE; } else if (GetIsDoorActionPossible(oLastObject, DOOR_ACTION_UNLOCK)|| GetIsPlaceableObjectActionPossible(oLastObject, PLACEABLE_ACTION_UNLOCK)) { ClearAllActions(); PlayVoiceChat(VOICE_CHAT_PICKLOCK); 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)) { ClearAllActions(); PlayVoiceChat(VOICE_CHAT_CANDO); ActionEquipMostDamagingMelee(oLastObject); ActionAttack(oLastObject); SetLocalObject(OBJECT_SELF, "NW_GENERIC_DOOR_TO_BASH", oLastObject); bValid = FALSE; } } if(bValid == TRUE) { //ClearAllActions(); PlayVoiceChat(VOICE_CHAT_CANTDO); } else { ActionDoCommand(PlayVoiceChat(VOICE_CHAT_TASKCOMPLETE)); } } } } } 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)) { //PlayVoiceChat(VOICE_CHAT_ENEMIES); DetermineCombatRound(GetLastHostileActor(GetMaster())); } else { //PlayVoiceChat(VOICE_CHAT_ENEMIES); 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()))) { //PlayVoiceChat(VOICE_CHAT_ENEMIES); 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, PlayVoiceChat(VOICE_CHAT_CANDO)); ActionAttack(OBJECT_INVALID); ClearAllActions(); } 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) { PlayVoiceChat(VOICE_CHAT_STOP); if(GetHasSkill(SKILL_DISABLE_TRAP, OBJECT_SELF)) { ClearAllActions(); ActionUseSkill(SKILL_DISABLE_TRAP, oTrap); ActionDoCommand(SetCommandable(TRUE)); ActionDoCommand(PlayVoiceChat(VOICE_CHAT_TASKCOMPLETE)); SetCommandable(FALSE); nCheck = 2; } } else if(nCheck = 0 && GetSkillRank(SKILL_DISABLE_TRAP) > 0 && GetCurrentAction(OBJECT_SELF) != ACTION_DISABLETRAP) { PlayVoiceChat(VOICE_CHAT_CANTDO); } } } } } break; case ASSOCIATE_COMMAND_MASTERATTACKEDOTHER: { if(!GetAssociateState(NW_ASC_MODE_STAND_GROUND)) { if(!GetAssociateState(NW_ASC_MODE_DEFEND_MASTER)) { if(!GetIsFighting(OBJECT_SELF)) { //PlayVoiceChat(VOICE_CHAT_ENEMIES); object oAttack = GetAttackTarget(GetMaster()); if(GetIsObjectValid(oAttack) && GetObjectSeen(oAttack)) { ClearAllActions(); 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)) { ClearAllActions(); //PlayVoiceChat(VOICE_CHAT_ENEMIES); DetermineCombatRound(oAttacker); } } } } break; case ASSOCIATE_COMMAND_LEAVEPARTY: { object oMaster = GetMaster(); if(GetIsObjectValid(oMaster)) { ClearAllActions(); 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 poarty was a PC and was friendly. The Get will return the status of the local. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Oct 29, 2001 //::////////////////////////////////////////////// void SetNPCWarningStatus(int nStatus = TRUE) { SetLocalInt(OBJECT_SELF, "NW_GENERIC_WARNING_STATUS", nStatus); } 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) { ClearAllActions(); ActionMoveAwayFromObject(oAOEObject, TRUE, 5.0); AssignCommand(OBJECT_SELF, DetermineCombatRound()); } //:://///////////////////////////////////////////// //:: Play Mobile Ambient Animations //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* Used for spawned creatures to not look like zombies */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Nov 23, 2001 //::////////////////////////////////////////////// void PlayMobileAmbientAnimations() { location lLocal; vector vFrnd; int nRoll = Random(5)+1; object oFriend = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, nRoll, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN); int nHDMe = GetHitDice(OBJECT_SELF); int nHDOther = GetHitDice(oFriend); //If a bird if(!GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) { /* Use this animation for all player races and humanoids who are civilized. Monstrous races will wonder about and try to look busy in as non-social manner. */ if(GetRacialType(OBJECT_SELF) == RACIAL_TYPE_ELF || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_GNOME || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HALFELF || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HALFLING || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HALFORC || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HUMAN || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HUMANOID_GOBLINOID || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HUMANOID_REPTILIAN || GetRacialType(OBJECT_SELF) == RACIAL_TYPE_HUMANOID_ORC) { if(nRoll == 4 || nRoll == 5) { ClearAllActions(); ActionRandomWalk(); } else { if(!GetIsObjectValid(oFriend) || GetIsPC(oFriend) || IsInConversation(oFriend)) { ClearAllActions(); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } else { if(GetDistanceToObject(oFriend) >= 3.0 && GetDistanceToObject(oFriend) <= 5.0 ) { ClearAllActions(); ActionMoveToObject(oFriend, FALSE, 2.0); } else if(GetDistanceToObject(oFriend) >= 5.0) { ClearAllActions(); ActionPlayAnimation(ANIMATION_FIREFORGET_GREETING, 0.75); ActionMoveToObject(oFriend, FALSE, 2.0); } vFrnd = GetPosition(oFriend); SetFacingPoint(vFrnd); nRoll = d4(); } if(GetIsObjectValid(oFriend)) { ClearAllActions(); if(nHDMe == nHDOther) { if(nRoll == 1) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 6.0); } else if(nRoll == 2) { ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD, 1.0, 6.0); } else if(nRoll == 3) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 6.0); } else { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } } else if(nHDMe > nHDOther) { if(nRoll == 1) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 6.0); } else if(nRoll == 2) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 6.0); } else if(nRoll == 3) { ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD, 1.0, 6.0); } else { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } } else if (nHDMe < nHDOther) { if(nRoll == 1) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 6.0); } else if(nRoll == 2) { ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD, 1.0, 6.0); } else if(nRoll == 3) { ActionPlayAnimation(ANIMATION_FIREFORGET_SALUTE, 0.75); } else { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } } } } } else { ClearAllActions(); int nRand = d6(); if(nRand == 1) { if(GetDistanceToObject(oFriend) >= 3.0 && GetDistanceToObject(oFriend) <= 10.0 ) { ActionMoveToObject(oFriend, FALSE, 2.0); vFrnd = GetPosition(oFriend); SetFacingPoint(vFrnd); } } else if(nRand == 2 || nRand == 3 || nRand == 4) { ActionRandomWalk(); } else if(nRand == 5) { ActionPlayAnimation(ANIMATION_LOOPING_GET_MID); } else if(nRand == 6) { } } } else //Birds Ambient Behavior { int nBird = d4(); location lFriend; effect eBird; if(GetIsObjectValid(oFriend)) { lFriend = GetLocation(oFriend); } else { lFriend = GetLocation(OBJECT_SELF); } if(nBird == 0) { ClearAllActions(); ActionMoveToObject(oFriend, TRUE, 4.0); // BK: Commenting this out because the effect wasn't meant to be played here // ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBird, OBJECT_SELF, 5.0); } else if (nBird == 1 || nBird == 2 || nBird == 3) { ClearAllActions(); ActionMoveAwayFromObject(oFriend, TRUE, 100.0); } else { ClearAllActions(); eBird = EffectDisappearAppear(lFriend); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBird, OBJECT_SELF, 4.0); ActionMoveAwayFromObject(oFriend, TRUE, 100.0); } } } //:://///////////////////////////////////////////// //:: Play Immobile Ambient Animations //:: Copyright (c) 2001 Bioware Corp. //::////////////////////////////////////////////// /* Used for spawned creatures to not look like zombies */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Nov 23, 2001 //::////////////////////////////////////////////// void PlayImmobileAmbientAnimations() { location lLocal; vector vFrnd; int nRoll = d2(); object oFriend = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, nRoll, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN); int nHDMe = GetHitDice(OBJECT_SELF); int nHDOther = GetHitDice(oFriend); if(!GetIsObjectValid(oFriend) || GetIsPC(oFriend) || IsInConversation(oFriend)) { if (d4()==1) { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } } else { if(GetIsObjectValid(oFriend) && GetDistanceToObject(oFriend) <= 3.0) { vFrnd = GetPosition(oFriend); SetFacingPoint(vFrnd); nRoll = d10(); ClearAllActions(); if(nRoll == 1) { ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_BORED, 1.0, 6.0); } else if(nRoll == 2) { ActionPlayAnimation(ANIMATION_FIREFORGET_PAUSE_SCRATCH_HEAD, 1.0, 6.0); } else if(nRoll == 3) { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } else if(nRoll == 4) { ActionPlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 0.75,2.0); } else { return; } } else if (d4()==1) { ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_LEFT, 0.75); ActionPlayAnimation(ANIMATION_FIREFORGET_HEAD_TURN_RIGHT, 0.75); } } } //::////////////////////////////////////////////////////////////////////////////////////////////// //:: Special Behavior Functions //:: Copyright (c) 2001 Bioware Corp. //::///////////////////////////////////////////////////////////////////////////////////////////// /* These commands handle the setting and getting of the Behavioral Master If these special behaviors are used they will override the normal behavior expected the animals normal Neutral Faction. */ //::///////////////////////////////////////////////////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Dec 10, 2001 //::///////////////////////////////////////////////////////////////////////////////////////////// void SetBehaviorState(int nCondition, int bValid = TRUE) { int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER"); if(bValid == TRUE) { nPlot = nPlot | nCondition; SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot); } else if (bValid == FALSE) { nPlot = nPlot & ~nCondition; SetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER", nPlot); } } int GetBehaviorState(int nCondition) { int nPlot = GetLocalInt(OBJECT_SELF, "NW_BEHAVIOR_MASTER"); if(nPlot & nCondition) { return TRUE; } return FALSE; } //:://///////////////////////////////////////////// //:: 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. */ //::////////////////////////////////////////////// //:: Created By: Preston Watamaniuk //:: Created On: Dec 14, 2001 //::////////////////////////////////////////////// void DetermineSpecialBehavior(object oIntruder = OBJECT_INVALID) { object oTarget = GetNearestCreature(CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, OBJECT_SELF ,1, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY); if(GetBehaviorState(NW_FLAG_BEHAVIOR_OMNIVORE)) { if(!GetIsObjectValid(oIntruder)) { if(!GetIsObjectValid(GetAttemptedAttackTarget()) && !GetIsObjectValid(GetAttemptedSpellTarget()) && !GetIsObjectValid(GetAttackTarget())) { if(GetIsObjectValid(oTarget) && GetDistanceToObject(oTarget) <= 5.0) { if(!GetIsFriend(oTarget)) { if(GetLevelByClass(CLASS_TYPE_DRUID, oTarget) == 0 && GetLevelByClass(CLASS_TYPE_RANGER, oTarget) == 0) { SetIsTemporaryEnemy(oTarget, OBJECT_SELF, FALSE, 20.0); DetermineCombatRound(oTarget); } } } } } else if(!IsInConversation(OBJECT_SELF)) { DetermineCombatRound(oIntruder); } else { ClearAllActions(); 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)) { ClearAllActions(); ActionRandomWalk(); return; } } }