mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
415 lines
10 KiB
Plaintext
415 lines
10 KiB
Plaintext
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;
|
|
}
|
|
|