Over the past several days I’ve been looking for ways to modify the way in which custom AI is implemented. Currently the standard convention is to create a custom OnSpawn script with a custom OnUserDefined script or to directly modify the other AI scripts (OnPerception, OnDamaged, etc.) to tweak the BioWare AI, leading to MANY scripts.
While this approach is effective, it ignores the fact that the X2 AI, with the introduction of Pre and Post-Spawn events, allows a Builder to place ALL this code into ONE OnUserDefined event - by moving all the AI switches from nw_c2_default9 to the EVENT_POST_SPAWN conditional in your custom OnUserDefined event.
/*
Pstemarie: 12-23-2019
Generic Creature OnUserDefined Event Script
To use:
1. Set the creature to use the X2 Monster AI (scripts with the prefix
x2_def_****).
2. Set this script as the creature's OnUserDefined event handler.
3. Set an INT variable named "X2_USERDEFINED_ONSPAWN_EVENTS" with a
value of "2" on the creature.
4. Uncomment any desired special behavior under the PRE and POST-SPAWN
conditionals
Leeched from nw_c2_default9, nw_c2_herbivore, and x2_def_userdef - all (c) 2002-2004 Bioware
*/
const int EVENT_USER_DEFINED_PRESPAWN = 1510;
const int EVENT_USER_DEFINED_POSTSPAWN = 1511;
#include "x0_i0_anims"
void main()
{
int nEvent = GetUserDefinedEventNumber();
if (nEvent == EVENT_USER_DEFINED_PRESPAWN)
{
}
else if (nEvent == EVENT_USER_DEFINED_POSTSPAWN)
{
//----------------------------------------------------------------------
// OPTIONAL BEHAVIORS (Comment In or Out to Activate )
//SetSpawnInCondition(NW_FLAG_SPECIAL_CONVERSATION);
//SetSpawnInCondition(NW_FLAG_SPECIAL_COMBAT_CONVERSATION);
//* This causes the creature to say a special greeting in their conversation file
//* upon Perceiving the player. Attach the [NW_D2_GenCheck.nss] script to the desired
//* greeting in order to designate it. As the creature is actually saying this to
//* himself, don't attach any player responses to the greeting.
//SetSpawnInCondition(NW_FLAG_SHOUT_ATTACK_MY_TARGET);
//* This will set the listening pattern on the NPC to attack when allies call
//SetSpawnInCondition(NW_FLAG_STEALTH);
//* If the NPC has stealth and they are a rogue go into stealth mode
//SetSpawnInCondition(NW_FLAG_SEARCH);
//* If the NPC has Search go into Search Mode
//SetSpawnInCondition(NW_FLAG_SET_WARNINGS);
//* This will set the NPC to give a warning to non-enemies before attacking
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
//* If this is set, the NPC will appear using the "EffectAppear" animation instead of fading in.
//SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
//* This will play Ambient Animations until the NPC sees an enemy or is cleared.
//* NOTE: These animations will play automatically for Encounter Creatures.
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
//* This will play Ambient Animations until the NPC sees an enemy or is cleared.
//* NOTE: NPCs using this form of ambient animations will not move to other NPCs.
//----------------------------------------------------------------------
// ANIMATION SETTINGS
/*
These are extra conditions you can put on creatures using ambient animations - either
NW_FLAG_AMBIENT_ANIMATIONS or NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS.
*/
//SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
//* Civilized creatures interact with placeables in their area that have the tag "NW_INTERACTIVE"
//* and "talk" to each other.
//*
//* Humanoid races are civilized by default, so only set this flag for monster races that you want to
//* behave the same way.
//SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
//* If this flag is set, this creature will constantly be acting. Otherwise, creatures will only start
//* performing their ambient animations when they first perceive a player, and they will stop when the
//* player moves away.
//SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
//* Civilized creatures with this flag set will randomly use a few voicechats. It's a good idea to avoid
//* putting this on multiple creatures using the same voiceset.
//SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
//* Creatures with _immobile_ ambient animations can have this flag set to make them mobile in close
//* range. They will never leave their immediate area, but will move around in it, frequently returning
//* to their starting point.
//*
//* NOTE: Creatures spawned inside interior areas that contain a waypoint with one of the tags "NW_HOME",
//* "NW_TAVERN", and "NW_SHOP" will automatically have this condition set.
//----------------------------------------------------------------------
// SPECIAL BEHAVIOR SECTION
/*
The following section outlines the various special behaviors that can be placed on a creature.
To activate one of the special behaviors:
1. Comment in SetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL);
2. Comment in ONE other special behavior setting (ONLY ONE).
*/
//SetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL);
//* OPTIONAL SPECIAL BEHAVIORS - ONLY ONE OF THESE SHOULD BE SET AT A TIME
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN);
//* Flee to a waypoint and return a short time later.
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE);
//* Flee to a waypoint and do not return.
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE);
//* Teleport to a waypoint and do not return.
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN);
//* Teleport to a waypoint and return a short time later.
//SetBehaviorState(NW_FLAG_BEHAVIOR_OMNIVORE);
//* Will only attack those that close within 5m and are not friends, Rangers or Druids.
//SetBehaviorState(NW_FLAG_BEHAVIOR_HERBIVORE);
//* Will flee those that close within 7m if they are not friends, Rangers or Druids.
//SetCombatCondition(X0_COMBAT_FLAG_RANGED);
//* Ranged Attacker: Will attempt to stay at ranged distance from their target.
//SetCombatCondition(X0_COMBAT_FLAG_DEFENSIVE);
//* Defensive Attacker: Will use defensive combat feats and parry
//SetCombatCondition(X0_COMBAT_FLAG_AMBUSHER);
//* Ambusher: Will go stealthy/invisible and attack, then run away and try to go stealthy
//* again before attacking anew.
//SetCombatCondition(X0_COMBAT_FLAG_COWARDLY);
// * Cowardly: Will attempt to flee attackers.
//----------------------------------------------------------------------
// CUSTOM USER DEFINED EVENTS
/*
The following settings will allow the user to fire one of the blank user defined events in
the NW_D2_DefaultD. Like the On Spawn In script this script is meant to be customized by
the end user to allow for unique behaviors. The user defined events are 1001 - 1007, and
1510 and 1511.
*/
//SetSpawnInCondition(NW_FLAG_HEARTBEAT_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
//SetSpawnInCondition(NW_FLAG_PERCIEVE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1002
//SetSpawnInCondition(NW_FLAG_ATTACK_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
//SetSpawnInCondition(NW_FLAG_DAMAGED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
//SetSpawnInCondition(NW_FLAG_DISTURBED_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
//SetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1003
//SetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
//SetSpawnInCondition(NW_FLAG_DEATH_EVENT); //OPTIONAL BEHAVIOR - Fire User Defined Event 1007
}
else if(nEvent == EVENT_HEARTBEAT ) //HEARTBEAT
{
}
else if(nEvent == EVENT_PERCEIVE) // PERCEIVE
{
}
else if(nEvent == EVENT_END_COMBAT_ROUND) // END OF COMBAT
{
}
else if(nEvent == EVENT_DIALOGUE) // ON DIALOGUE
{
}
else if(nEvent == EVENT_ATTACKED) // ATTACKED
{
}
else if(nEvent == EVENT_DAMAGED) // DAMAGED
{
}
else if(nEvent == 1007) // DEATH - do not use for critical code, does not fire reliably all the time
{
}
else if(nEvent == EVENT_DISTURBED) // DISTURBED
{
}
}
While I haven’t playtested every single switch, I have determined that the following switches DO work when set in the EVENT_POST_SPAWN:
All Special Behaviors
Ambient Animations (and Animation Settings)
All Custom User Defined Events (Death, Heartbeat, etc.)
Just thought I’d share a little Christmas gift for the Community.