include library.ai_lib; include library.factions; include ai.ai_combat; const string ALERT_VOLUME_NAME = "alertTriggerVolume"; const string ACTION_ALERT = "alert"; const string ACTION_THREATEN = "threaten"; const float CORPSE_CLEANUP_DELAY = 30.0f; trigger OnAttach() { // To ensure that you don't do anything with the NPC until he has been // instantiated and setup, use a callback: //CHANGE THE NAME OF THIS HANDLER TO ONE SPECIFIC TO THIS AI SCRIPT! messageTo( self, "handleSetupNPC", null, 5, isObjectPersisted( self ) ); //mever do anything here. return SCRIPT_CONTINUE; } trigger OnInitialize() { //mever do anything here. return SCRIPT_CONTINUE; } //CHANGE THE NAME OF THIS HANDLER TO ONE SPECIFIC TO THIS AI SCRIPT! messageHandler handleSetupNPC() { //if setup isn't complete yet, then wait 5 seconds and try again: if ( !hasObjVar( self, "ai.setupComplete" )) { //CHANGE THE NAME OF THIS HANDLER TO ONE SPECIFIC TO THIS AI SCRIPT! messageTo( self, "handleSetupNPC", null, 5, isObjectPersisted( self ) ); return SCRIPT_CONTINUE; } /* -----------------9/11/2002 11:30AM---------------- * Your setup code goes here. * --------------------------------------------------*/ return SCRIPT_CONTINUE; } messageHandler resumeDefaultCalmBehavior() { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat if ( hasObjVar( self, "ai.conversing") ) { //the npc is conversing. Want to do something special? // return SCRIPT_OVERRIDE; // otherwise return SCRIPT_CONTINUE; } //if you don't want a calm NPC to resume his default calm behavior, // then // // YOUR CODE GOES HERE // // return SCRIPT_OVERRIDE; // else return SCRIPT_CONTINUE; } trigger OnMovePathComplete() { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat return SCRIPT_CONTINUE; } trigger OnMovePathNotFound() { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat // return SCRIPT_OVERRIDE; if you do NOT want the NPC to // resume patrolling (if he was patrolling) or to // resume his default behavior (if he's calm) // otherwise: return SCRIPT_CONTINUE; } trigger OnTriggerVolumeEntered( string volumeName, obj_id breacher ) { //ignore gm's if ( hasObjVar( breacher, "gm") ) return SCRIPT_CONTINUE; //ignore yourself and dead things if ( breacher == self || ai_lib.isAiDead( breacher ) ) return SCRIPT_CONTINUE; if ( volumeName == ALERT_VOLUME_NAME ) { //the alert trigger has been breached! Wand to prevent default // reactions from taking place? // return SCRIPT_OVERRIDE; // otherwise: } return SCRIPT_CONTINUE; } trigger OnTriggerVolumeExited( string volumeName, obj_id breacher ) { if ( volumeName == ALERT_VOLUME_NAME ) { //want to prevent herding behaviors and the like? // if you return SCRIPT_OVERRIDE here, make sure // to call this function first! //ignoreCreatureMovement(self, breacher); // return SCRIPT_OVERRIDE; } return SCRIPT_CONTINUE; } trigger OnLoiterWaiting(modifiable_float time) { int herding = dataTableGetInt("datatables/ai/species.iff", ai_lib.aiGetSpecies( self ), "Herd"); if ( herding != 1 ) { //you can do anything you want to here, and // return SCRIPT_OVERRIDE; } //you can do anything you want to here, // but if you return SCRIPT_OVERRIDE then // herding animals won't herd! // Unless you also call: // ai_lib.maintainHerding( self ); // return SCRIPT_OVERRIDE; return SCRIPT_CONTINUE; } trigger OnBehaviorChange( int newBehavior, int oldBehavior, int[] changeFlags ) { if ( ai_lib.isAiDead( self) ) return SCRIPT_CONTINUE; if ( ai_lib.isInCombat( self ) ) return SCRIPT_CONTINUE;//you probably don't want to do anything if you are in combat //don't put code in this trigger. Put it in doCalmerBehavior or doAgitated behavior // this is hard enough to read already: if ( newBehavior <= oldBehavior ) { if ( doCalmerBehavior( self, newBehavior, oldBehavior ) == SCRIPT_CONTINUE) return SCRIPT_CONTINUE; else return SCRIPT_OVERRIDE; } else { if ( doAgitatedBehavior( self, newBehavior, oldBehavior) == SCRIPT_CONTINUE ) return SCRIPT_CONTINUE; else return SCRIPT_OVERRIDE; } } int doCalmerBehavior( obj_id npc, int newBehavior, int oldBehavior ) { //You are now calming down. // return SCRIPT_OVERRIDE to stomp on default behaviors: switch ( newBehavior ) { case BEHAVIOR_CALM: //going from More Agitated to Calm // Your code goes here. break; case BEHAVIOR_ALERT: //going from More Agitated to Alert // Your code goes here. break; case BEHAVIOR_THREATEN: //going from More Agitated to Threaten // Your code goes here. break; case BEHAVIOR_FLEE: //going from More Agitated to Flee // Your code goes here. break; case BEHAVIOR_PANIC: //going from More Agitated to Panic // Your code goes here. break; case BEHAVIOR_ATTACK: //Going from More Agitated to Attack // Your code goes here. break; case BEHAVIOR_FRENZY: //This is impossible. break; default : // This is an error break; } return SCRIPT_CONTINUE; } int doAgitatedBehavior( obj_id npc, int newBehavior, int oldBehavior ) { //You are becoming more Fearful or more Angry // return SCRIPT_OVERRIDE to stomp on default behaviors: switch ( newBehavior ) { case BEHAVIOR_CALM: //this is impossible break; case BEHAVIOR_ALERT: //going from Calmer to Alert // Your code goes here. break; case BEHAVIOR_THREATEN: //going from Calmer to Threaten // Your code goes here. break; case BEHAVIOR_FLEE: //going from Calmer to Flee // Your code goes here. break; case BEHAVIOR_PANIC: //Going from Calmer to Panic // Your code goes here. break; case BEHAVIOR_ATTACK: //Going from Calmer to Attack // Your code goes here. break; case BEHAVIOR_FRENZY: //going from Calmer to Frenzy break; default : // This is an error break; } return SCRIPT_CONTINUE; } /* -----------------8/1/2002 9:42PM------------------ * COMBAT: * --------------------------------------------------*/ trigger OnEnteredCombat() { //you probably dont want to do anything here return SCRIPT_CONTINUE; } trigger OnDefenderCombatAction( obj_id attacker, obj_id weapon, int combatResult ) { //bet you shouldn't do anything here, either. return SCRIPT_CONTINUE; } messageHandler lairThreatened() { if ( ai_lib.isAiDead( self) ) return SCRIPT_CONTINUE; if ( ai_lib.isInCombat( self) ) return SCRIPT_CONTINUE; if ( !hasObjVar( self, "poi.baseObject" )) return SCRIPT_CONTINUE; obj_id myLair = getObjIdObjVar( self, "poi.baseObject" ); obj_id lair = params.getObjId( "lairId" ); if ( lair == null || lair == obj_id.NULL_ID ) return SCRIPT_CONTINUE; if ( lair == myLair ) { //your code goes here. // return SCRIPT_OVERRIDE; // to stomp default behavior. } return SCRIPT_CONTINUE; } //--------------- DEATH -----------------------// trigger OnIncapacitated( obj_id attacker ) { //you probably don't ever want to use // return SCRIPT_OVERRIDE here // if you do, it'll prevent the body from // decaying (Ever!), etc. return SCRIPT_CONTINUE; } messageHandler corpseCleanup() { //want to do something special when the corpse // is deleted? Better hurry! // If you // return SCRIPT_OVERRIDE // then you'd better //destroyObject( self ); // or the corpse will never go away. return SCRIPT_CONTINUE; } //---------------DEATH -----------------------// trigger OnStartNpcConversation (obj_id speaker) { if ( ai_lib.isInCombat( self ) ) return SCRIPT_CONTINUE; if ( ai_lib.isInCombat( speaker ) ) return SCRIPT_CONTINUE; //if you return SCRIPT_OVERRIDE in this trigger, // then do all this stuff FIRST! /* ai_lib.setMood( self, ai_lib.MOOD_CALM ); stop( self ); faceTo( self, speaker ); setObjVar( self, "ai.conversing", false ); messageTo( self, "handleAbortConversation", null, 30, true ); */ return SCRIPT_CONTINUE; } trigger OnNpcConversationResponse(string convo, obj_id player, string_id response) { //if you return SCRIPT_OVERRIDE from this trigger, then do // this stuff FIRST! /* if ( hasObjVar( self, "ai.conversing" ) ) setObjVar( self, "ai.conversing", true); */ return SCRIPT_CONTINUE; } trigger OnEndNpcConversation(obj_id speaker ) { //if you return SCRIPT_OVERRIDE from this trigger, then do // this stuff FIRST! /* removeObjVar( self, "ai.conversing"); if ( getBehavior(self) == BEHAVIOR_CALM ) messageTo( self, "resumeDefaultCalmBehavior", null, 5, false ); */ return SCRIPT_CONTINUE; } trigger OnFleeTargetLost(obj_id oldTarget) { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat //if you don't want the NPC to resume default calm behavior (if calm) //return SCRIPT_OVERRIDE; //else: return SCRIPT_CONTINUE; } trigger OnFleePathNotFound(obj_id oldTarget) { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat //if you don't want the NPC to resume default calm behavior (if calm) //return SCRIPT_OVERRIDE; //else: return SCRIPT_CONTINUE; } trigger OnFollowTargetLost(obj_id oldTarget) { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat //note: if the npc is not in combat, and you fail // to return SCRIPT_CONTINUE -and- you don't call // ai_lib.stopFollowing(), then this NPC will // think he's following someone, but won't be moving! // That's BAD. return SCRIPT_CONTINUE; } trigger OnFollowPathNotFound(obj_id target) { if ( ai_lib.isInCombat( self )) return SCRIPT_CONTINUE;//you probably don't want to do anything if the creature is in combat //note: if the npc is not in combat, and you fail // to return SCRIPT_CONTINUE -and- you don't call // ai_lib.stopFollowing(), then this NPC will // think he's following someone, but won't be moving! // That's BAD. return SCRIPT_CONTINUE; }