Removed JAI
Removed JAI, added CODI AI. Fixed encounters & NPCs in Forest of Hope Central. Fixed Outcast store not opening. Added Druid Grove & associated NPCS.
This commit is contained in:
242
_module/nss/drusilla_ondeath.nss
Normal file
242
_module/nss/drusilla_ondeath.nss
Normal file
@@ -0,0 +1,242 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Name drusilla_ondeath
|
||||
//:: Copyright (c) 2022 Project RATDOG
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Drusilla the Druid's OnDeath script
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Jaysyn
|
||||
//:: Created On: 20221129
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "sql_db_partywide"
|
||||
#include "pqj_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oNPC = OBJECT_SELF;
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
// Makes sure armor's droppable flag is set to 0
|
||||
/* SetDroppableFlag(GetItemInSlot(INVENTORY_SLOT_CHEST, OBJECT_SELF), 0);
|
||||
|
||||
if ((GetResRef(oNPC) == "ra_bandit001") ||
|
||||
(GetResRef(oNPC) == "ra_brigand001") ||
|
||||
(GetResRef(oNPC) == "ra_brigand002"))
|
||||
{
|
||||
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oNPC);
|
||||
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oNPC);
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oNPC);
|
||||
|
||||
// Give a 3% chance to drop armor &/or equipped weapon
|
||||
int bDroppableA = d100() > 97;
|
||||
int bDroppableW = d100() > 97;
|
||||
int bDroppableS = d100() > 97;
|
||||
|
||||
SetDroppableFlag(oArmor, bDroppableA);
|
||||
SetDroppableFlag(oWeapon, bDroppableW);
|
||||
SetDroppableFlag(oWeapon, bDroppableS);
|
||||
|
||||
}*/
|
||||
|
||||
int nVFX = GetLocalInt(OBJECT_SELF,"SpawnVFX");
|
||||
if(nVFX)
|
||||
{
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT,SupernaturalEffect(EffectVisualEffect(nVFX)),OBJECT_SELF);
|
||||
}
|
||||
int nFirey = GetLocalInt(OBJECT_SELF,"FIREY");
|
||||
if (nFirey)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_INFERNO_NO_SOUND);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nShadowy = GetLocalInt(OBJECT_SELF,"SHADOWY");
|
||||
if (nShadowy)
|
||||
{
|
||||
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_PROT_SHADOW_ARMOR);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nStony = GetLocalInt(OBJECT_SELF,"STONY");
|
||||
if (nStony)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_PROT_STONESKIN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nWoody = GetLocalInt(OBJECT_SELF,"WOODY");
|
||||
if (nWoody)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_PROT_BARKSKIN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nIcy = GetLocalInt(OBJECT_SELF,"ICY");
|
||||
if (nIcy)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_ICESKIN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
int nConcealed20 = GetLocalInt(OBJECT_SELF,"CONCEALED20");
|
||||
if (nConcealed20)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_BLUR );
|
||||
effect eConceal = EffectConcealment(20, 0);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nConcealed50 = GetLocalInt(OBJECT_SELF,"CONCEALED50");
|
||||
if (nConcealed50)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_BLUR );
|
||||
effect eConceal = EffectConcealment(50, 0);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
int nGlow = GetLocalInt (OBJECT_SELF,"GLOW_COLOR");
|
||||
if (nGlow == 1)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_BLUE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 2)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_BROWN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 3)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_GREEN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 4)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_GREY);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 5)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_BLUE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 6)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_BROWN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 7)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_GREEN);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 8)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_ORANGE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 9)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_PURPLE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 10)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_RED);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 11)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_LIGHT_YELLOW);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 12)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_ORANGE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 13)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_PURPLE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 14)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_RED);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
else if (nGlow == 15)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_WHITE);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
else if (nGlow == 16)
|
||||
{
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_GLOW_YELLOW);
|
||||
eVis = SupernaturalEffect(eVis);
|
||||
eVis = ExtraordinaryEffect(eVis);
|
||||
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT,eVis,OBJECT_SELF));
|
||||
}
|
||||
|
||||
//:: Track which PC's have seen Drusilla dead
|
||||
SQL_SetLocalIntOnAll(oPC, "bKilledDrusilla", 1);
|
||||
|
||||
//:: Set quest stage & update DB.
|
||||
AddPersistentJournalQuestEntry("VengefulDruid", 99, oPC);
|
||||
|
||||
//:: Execute CODI AI NPC OnDeath script
|
||||
ExecuteScript("no_ai_dth", OBJECT_SELF);
|
||||
|
||||
//:: Execute Default NPC OnDeath script
|
||||
//ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
|
||||
//:: Execute PRC NPC OnDeath script
|
||||
ExecuteScript("prc_npc_death", OBJECT_SELF);
|
||||
}
|
45
_module/nss/drusilla_onperce.nss
Normal file
45
_module/nss/drusilla_onperce.nss
Normal file
@@ -0,0 +1,45 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: drusilla_onpercep
|
||||
//:: Copyright (c) 2022 Project RATDOG
|
||||
//::///////////////////////////////////////////////
|
||||
/*
|
||||
Makes the NPC speak to the PC upon seeing them
|
||||
the first time.
|
||||
*/
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Created By: Jaysyn
|
||||
//:: Created On: 20221202
|
||||
//::///////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
//:: Declare major variables
|
||||
object oPC = GetLastPerceived();
|
||||
object oNPC = OBJECT_SELF;
|
||||
string sUUID = GetObjectUUID(oPC);
|
||||
string sTag = GetTag(oNPC);
|
||||
|
||||
//:: Only looks out for players
|
||||
if (!GetIsPC(oPC)) return;
|
||||
|
||||
//:: Must be seen & not just heard
|
||||
if (!GetLastPerceptionSeen()) return;
|
||||
|
||||
//:: If NPC has seen PC before stop
|
||||
int DoOnce = GetLocalInt(oPC,"SeenBy"+sTag);
|
||||
|
||||
if (DoOnce==TRUE) return;
|
||||
|
||||
//:: Execute the PRC NPC OnPerception script
|
||||
ExecuteScript("prc_npc_percep", OBJECT_SELF);
|
||||
|
||||
//:: Mark that NPC has seen the PC before
|
||||
SetLocalInt(oPC,"SeenBy"+sTag,GetLocalInt(oPC,"SeenBy"+sTag) + 1);
|
||||
//SetLocalInt(OBJECT_SELF, GetTag(OBJECT_SELF), TRUE);
|
||||
|
||||
//:: Execute the CODI AI NPC OnPerception script
|
||||
ExecuteScript("no_ai_per", OBJECT_SELF);
|
||||
|
||||
//:: Start conversation
|
||||
ActionStartConversation(oPC, "");
|
||||
}
|
@@ -1,99 +0,0 @@
|
||||
/*/////////////////////// [Destroy Ourself] ////////////////////////////////////
|
||||
Filename: J_AI_DestroySelf
|
||||
///////////////////////// [Destroy Ourself] ////////////////////////////////////
|
||||
This is executed OnDeath to clean up the corpse. It helps - clears all
|
||||
non-droppable stuff.
|
||||
|
||||
It is not fired if there are corpses or whatever :-)
|
||||
|
||||
Sorts destroyed things.
|
||||
|
||||
Oh, if this is executed any other time when they are dead, they are
|
||||
destroyed instantly.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added to replace a include function for death.
|
||||
- No locals are destroyed. The game should do that anyway. Items are, though.
|
||||
1.4 -
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
this, if ever fired, will destroy the creature. It is not deleayed - there
|
||||
is a special function in the death script to check the whole "Did I get
|
||||
raised?" stuff.
|
||||
|
||||
I suppose you can edit this to put a corpse in :-D
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A - none needed.
|
||||
///////////////////////// [Destroy Ourself] //////////////////////////////////*/
|
||||
|
||||
|
||||
// Exectued from death, to speed things up.
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// This will delete all un-droppable items, before they fade out.
|
||||
void DeleteAllThings();
|
||||
// Used in DeleteAllThings.
|
||||
void ClearSlot(int iSlotID);
|
||||
|
||||
void main()
|
||||
{
|
||||
// To not crash limbo. Destroying in limbo crashes a server (1.2 bugfix)
|
||||
if(GetIsObjectValid(GetArea(OBJECT_SELF)))
|
||||
{
|
||||
// Must be dead.
|
||||
if(GetIsDead(OBJECT_SELF))
|
||||
{
|
||||
// Totally dead - no death file, no raising.
|
||||
SetAIInteger(I_AM_TOTALLY_DEAD, TRUE);
|
||||
// Ok, we are going to set we are lootable (maybe)
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_USE_BIOWARE_LOOTING, AI_OTHER_MASTER))
|
||||
{
|
||||
// As it is now destroyable, it should destroy itself if it has
|
||||
// no inventory. SetLootable is set up on spawn.
|
||||
// 75: "[Dead] Setting to selectable/destroyable (so we go) for Bioware corpses."
|
||||
DebugActionSpeakByInt(75);
|
||||
SetIsDestroyable(TRUE, FALSE, TRUE);
|
||||
}
|
||||
else // Destroy self normally
|
||||
{
|
||||
// Debug
|
||||
// 76: "[Dead] Destroying self finally."
|
||||
DebugActionSpeakByInt(76);
|
||||
DeleteAllThings();
|
||||
// Just in case, we set destroyable, but not raiseable.
|
||||
SetIsDestroyable(TRUE, FALSE, FALSE);
|
||||
// Remove plot/immoral/lootable flags JUST in case.
|
||||
SetPlotFlag(OBJECT_SELF, FALSE);
|
||||
SetImmortal(OBJECT_SELF, FALSE);
|
||||
SetLootable(OBJECT_SELF, FALSE);
|
||||
// Destroy ourselves
|
||||
DestroyObject(OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: we never do more then one death removal check. DM's can re-raise and kill a NPC if they wish.
|
||||
}
|
||||
|
||||
// Used in DeleteAllThings.
|
||||
void ClearSlot(int iSlotID)
|
||||
{
|
||||
object oItem = GetItemInSlot(iSlotID);
|
||||
if(GetIsObjectValid(oItem) && !GetDroppableFlag(oItem))
|
||||
DestroyObject(oItem);
|
||||
}
|
||||
// This will delete all un-droppable items, before they fade out.
|
||||
void DeleteAllThings()
|
||||
{
|
||||
// Destroy all equipped slots - 0 to 18 (18 = NUM_INVENTORY_SLOTS)
|
||||
int iSlotID;
|
||||
for(iSlotID = 0; iSlotID <= NUM_INVENTORY_SLOTS; iSlotID++)
|
||||
{
|
||||
ClearSlot(iSlotID);
|
||||
}
|
||||
// Destroy all inventory items
|
||||
object oItem = GetFirstItemInInventory();
|
||||
while(GetIsObjectValid(oItem))
|
||||
{
|
||||
if(!GetDroppableFlag(oItem))
|
||||
DestroyObject(oItem);
|
||||
oItem = GetNextItemInInventory();
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
/*/////////////////////// [Execute Combat Action] //////////////////////////////
|
||||
Filename: J_AI_DeterCombat
|
||||
///////////////////////// [Execute Combat Action] //////////////////////////////
|
||||
Fired from other scripts, this runs an actual actions.
|
||||
|
||||
It also contains the Pre-combat and Post-combat action events. In essense
|
||||
they therefore fire if they percieve a target, or a new round, or maybe
|
||||
a spell cast at - any combat action.
|
||||
|
||||
Therefore, they only fire if the default AI is being used :-)
|
||||
|
||||
Do NOT mess with this file, please. :-D
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - AI Include only fired from here. This script is executed from others,
|
||||
as the default in place of custom AI scripts.
|
||||
1.4 - Mainly See the generic AI include file for changes. This is just
|
||||
what calls DetermineCombatRound() and associated things.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is simple:
|
||||
|
||||
- We execute it if there is no other AI files.
|
||||
- We use a stored target for things like "On Percieve, attack seen", so
|
||||
we react as normal.
|
||||
|
||||
If there is a custom AI file specified, this won't fire.
|
||||
|
||||
It cleans things up, and is the only script in the whole set that has
|
||||
j_inc_generic_ai in, reducing file size, and compile times. AI is more
|
||||
manageable too!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: See J_INC_GENERIC_AI
|
||||
///////////////////////// [Execute Combat Action] ////////////////////////////*/
|
||||
|
||||
#include "J_INC_GENERIC_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-combat-event
|
||||
if(FireUserEvent(AI_FLAG_UDE_COMBAT_ACTION_PRE_EVENT, EVENT_COMBAT_ACTION_PRE_EVENT))
|
||||
// We may exit if it fires
|
||||
if(ExitFromUDE(EVENT_COMBAT_ACTION_PRE_EVENT)) return;
|
||||
|
||||
// Check: Are we imputting a target? We imputt it even if invalid
|
||||
object oTarget = GetLocalObject(OBJECT_SELF, AI_TEMP_SET_TARGET);
|
||||
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Speak combat round speakstring
|
||||
SpeakArrayString(AI_TALK_ON_COMBAT_ROUND, TRUE);
|
||||
}
|
||||
|
||||
// Call combat round using include
|
||||
AI_DetermineCombatRound(oTarget);
|
||||
|
||||
// Delete it whatever happens
|
||||
DeleteAIObject(AI_TEMP_SET_TARGET);
|
||||
|
||||
// Fire end of combat action event.
|
||||
FireUserEvent(AI_FLAG_UDE_COMBAT_ACTION_EVENT, EVENT_COMBAT_ACTION_EVENT);
|
||||
}
|
@@ -1,39 +0,0 @@
|
||||
/*/////////////////////// [On Heartbeat - Animations] //////////////////////////
|
||||
Filename: J_AI_Heart_aimat
|
||||
///////////////////////// [On Heartbeat - Animations] //////////////////////////
|
||||
To keep the heartbeat small, I've divided all the bits that MIGHT fire
|
||||
into other scripts. This makes it smaller, and faster.
|
||||
|
||||
I've also shortened the perception script too - and along with the heartbeat
|
||||
is the largest, Out-Of-Combat script. It isn't divided up by execute scripts,
|
||||
but should be leaner.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added to speed up heartbeat and keep filesize down on un-used parts.
|
||||
1.4 - Changed to nw_i0_generic, as to include all animations, whatever NwN version.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is executed as file HEARTBEAT_ANIMATIONS_FILE, from the heartbeat
|
||||
script (Default1, or onheartbeat). It can run by itself, using the SoU
|
||||
animations - better then me changing and making my own, as they are vastly
|
||||
improved from NwN!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [On Heartbeat - Animations] ////////////////////////*/
|
||||
|
||||
// Generic Include File. This contains animations whatever NwN version it is.
|
||||
#include "NW_I0_GENERIC"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS))
|
||||
{
|
||||
PlayMobileAmbientAnimations_NonAvian();
|
||||
}
|
||||
else if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN))
|
||||
{
|
||||
PlayMobileAmbientAnimations_Avian();
|
||||
}
|
||||
else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS))
|
||||
{
|
||||
PlayImmobileAmbientAnimations();
|
||||
}
|
||||
}
|
@@ -1,188 +0,0 @@
|
||||
/*/////////////////////// [On Heartbeat - Buff] ////////////////////////////////
|
||||
Filename: j_ai_heart_buff
|
||||
///////////////////////// [On Heartbeat - Buff] ////////////////////////////////
|
||||
This is ExecuteScript'ed from the heartbeat file, if they want to buff
|
||||
themselves with spells to be prepared for any battle coming up.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
1.4 - Will Add all the appropriate Hordes spells, notably the missing epic ones.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This contains Advance Buffing - IE quick protection spells.
|
||||
I've done what ones I think are useful - IE most protection ones & summons!
|
||||
|
||||
This doesn't include any which are (potentionally) very short duration (IE:
|
||||
1 round/level, or a set value):
|
||||
|
||||
Elemntal shield/Wounding whispers (though you can add all of these!)
|
||||
Aid, bless, aura of vitality, aura of glory, blood frenzy, prayer,
|
||||
divine* Range (Power, Might, Shield, Favor), Expeditious retreat,
|
||||
holy/unholy aura (or protection from /magic circle against),
|
||||
natures balance, one with the land, shield of faith, virtue, war cry, dirge,
|
||||
death armor, mestals acid sheath.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [On Heartbeat - Buff] //////////////////////////////*/
|
||||
|
||||
// Constants for some unconstantanated spells
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Wrapper, to stop repeating the same lines! :-)
|
||||
int BuffCastSpell(int nSpell);
|
||||
|
||||
void main()
|
||||
{
|
||||
// For summons counter.
|
||||
int nCnt, bBreak;
|
||||
// FAST BUFF SELF
|
||||
// Stop what we are doing first, to perform the actions.
|
||||
ClearAllActions();
|
||||
|
||||
// Always cast "Epic Warding" and "Epic Mage Armor".
|
||||
BuffCastSpell(FEAT_EPIC_SPELL_EPIC_WARDING);
|
||||
BuffCastSpell(FEAT_EPIC_SPELL_MAGE_ARMOUR);
|
||||
|
||||
// Combat Protections
|
||||
if(!BuffCastSpell(SPELL_PREMONITION))
|
||||
if(!BuffCastSpell(SPELL_GREATER_STONESKIN))
|
||||
BuffCastSpell(SPELL_STONESKIN);
|
||||
|
||||
// Visage Protections
|
||||
if(!BuffCastSpell(SPELL_SHADOW_SHIELD))
|
||||
if(!BuffCastSpell(SPELL_ETHEREAL_VISAGE))
|
||||
BuffCastSpell(SPELL_GHOSTLY_VISAGE);
|
||||
|
||||
// Mantle Protections
|
||||
if(!BuffCastSpell(SPELL_GREATER_SPELL_MANTLE))
|
||||
if(!BuffCastSpell(SPELL_SPELL_MANTLE))
|
||||
BuffCastSpell(SPELL_LESSER_SPELL_MANTLE);
|
||||
|
||||
// True seeing, see invisibility. We take true seeing to be better then the latter.
|
||||
if(BuffCastSpell(SPELL_TRUE_SEEING))
|
||||
BuffCastSpell(SPELL_SEE_INVISIBILITY);
|
||||
|
||||
// Elemental Protections. 4 lots. From 40/- to 10/-
|
||||
if(!BuffCastSpell(SPELL_ENERGY_BUFFER))
|
||||
if(!BuffCastSpell(SPELL_PROTECTION_FROM_ELEMENTS))
|
||||
if(!BuffCastSpell(SPELL_RESIST_ELEMENTS))
|
||||
BuffCastSpell(SPELL_ENDURE_ELEMENTS);
|
||||
|
||||
// Mental Protections
|
||||
if(!BuffCastSpell(SPELL_MIND_BLANK))
|
||||
if(!BuffCastSpell(SPELL_LESSER_MIND_BLANK))
|
||||
BuffCastSpell(SPELL_CLARITY);
|
||||
|
||||
// Globes
|
||||
if(!BuffCastSpell(SPELL_GLOBE_OF_INVULNERABILITY))
|
||||
BuffCastSpell(SPELL_MINOR_GLOBE_OF_INVULNERABILITY);
|
||||
|
||||
// Invisibility
|
||||
// Note: Improved has 50% consealment, etherealness has just invisiblity.
|
||||
if(!BuffCastSpell(SPELL_IMPROVED_INVISIBILITY))
|
||||
BuffCastSpell(SPELL_DISPLACEMENT);//50% consealment
|
||||
if(!BuffCastSpell(SPELL_ETHEREALNESS))
|
||||
if(!BuffCastSpell(SPELL_INVISIBILITY_SPHERE))
|
||||
if(!BuffCastSpell(SPELL_INVISIBILITY))
|
||||
BuffCastSpell(SPELL_SANCTUARY);
|
||||
|
||||
// The stat-increasing ones.
|
||||
if(!BuffCastSpell(SPELL_GREATER_BULLS_STRENGTH))
|
||||
BuffCastSpell(SPELL_BULLS_STRENGTH);
|
||||
if(!BuffCastSpell(SPELL_GREATER_CATS_GRACE))
|
||||
BuffCastSpell(SPELL_CATS_GRACE);
|
||||
if(!BuffCastSpell(SPELL_GREATER_EAGLE_SPLENDOR))
|
||||
BuffCastSpell(SPELL_EAGLE_SPLEDOR);
|
||||
if(!BuffCastSpell(SPELL_GREATER_FOXS_CUNNING))
|
||||
BuffCastSpell(SPELL_FOXS_CUNNING);
|
||||
if(!BuffCastSpell(SPELL_GREATER_ENDURANCE))
|
||||
BuffCastSpell(SPELL_ENDURANCE);
|
||||
if(!BuffCastSpell(AI_SPELL_OWLS_INSIGHT))
|
||||
if(!BuffCastSpell(SPELL_GREATER_OWLS_WISDOM))
|
||||
BuffCastSpell(SPELL_OWLS_WISDOM);
|
||||
|
||||
// Mage armor or shield. Don't stack them.
|
||||
if(!BuffCastSpell(SPELL_SHIELD))
|
||||
BuffCastSpell(SPELL_MAGE_ARMOR);
|
||||
// Entropic Shield (20% consealment, 1 turn/level)
|
||||
BuffCastSpell(SPELL_ENTROPIC_SHIELD);
|
||||
|
||||
// Protection from negative energy
|
||||
if(!BuffCastSpell(SPELL_UNDEATHS_ETERNAL_FOE))
|
||||
BuffCastSpell(SPELL_DEATH_WARD);
|
||||
//Misc Protections which have no more powerful.
|
||||
BuffCastSpell(SPELL_BARKSKIN);
|
||||
BuffCastSpell(SPELL_ENTROPIC_SHIELD);
|
||||
BuffCastSpell(SPELL_PROTECTION_FROM_SPELLS);
|
||||
BuffCastSpell(SPELL_REGENERATE);
|
||||
BuffCastSpell(SPELL_DARKVISION);
|
||||
BuffCastSpell(SPELL_REGENERATE);
|
||||
BuffCastSpell(SPELL_SPELL_RESISTANCE);
|
||||
BuffCastSpell(SPELL_FREEDOM_OF_MOVEMENT);
|
||||
BuffCastSpell(SPELL_FREEDOM_OF_MOVEMENT);
|
||||
|
||||
// Low durations (Rounds per caster level)
|
||||
// if(!BuffCastSpell(SPELL_ELEMENTAL_SHIELD))
|
||||
// BuffCastSpell(SPELL_WOUNDING_WHISPERS);
|
||||
// BuffCastSpell(SPELL_DEATH_ARMOR);
|
||||
|
||||
|
||||
//Summon Ally.
|
||||
// Spell ID's: These are quite odd. Spells.2da:
|
||||
/*
|
||||
174 Summon_Creature_I 1
|
||||
175 Summon_Creature_II 2
|
||||
176 Summon_Creature_III 3
|
||||
177 Summon_Creature_IV 4
|
||||
178 Summon_Creature_IX 9
|
||||
179 Summon_Creature_V 5
|
||||
180 Summon_Creature_VI 6
|
||||
181 Summon_Creature_VII 7
|
||||
182 Summon_Creature_VIII 8
|
||||
*/
|
||||
// We can loop through. 9 first, then 8-5, then undead ones, then 4-1
|
||||
if(!BuffCastSpell(SPELL_SUMMON_CREATURE_IX))// 9
|
||||
{
|
||||
// 8, 7, 6, 5.
|
||||
for(nCnt = SPELL_SUMMON_CREATURE_VIII;
|
||||
(nCnt >= SPELL_SUMMON_CREATURE_V && bBreak != TRUE);
|
||||
nCnt--)
|
||||
{
|
||||
if(BuffCastSpell(nCnt)) bBreak = TRUE;
|
||||
}
|
||||
// Then undead
|
||||
if(bBreak != TRUE)
|
||||
{
|
||||
if(!BuffCastSpell(SPELL_CREATE_GREATER_UNDEAD))
|
||||
{
|
||||
if(!BuffCastSpell(SPELL_CREATE_UNDEAD))
|
||||
{
|
||||
if(!BuffCastSpell(SPELL_ANIMATE_DEAD))
|
||||
{
|
||||
// Lastly, the 4-1 ones.
|
||||
for(nCnt = SPELL_SUMMON_CREATURE_IV;
|
||||
nCnt >= SPELL_SUMMON_CREATURE_I;
|
||||
nCnt--)
|
||||
{
|
||||
if(BuffCastSpell(nCnt)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finally, equip the best melee weapon to look more prepared.
|
||||
// Don't use a ranged, we can equip it manually if need be :=P
|
||||
// but sneak attackers would have a field day if we didn't have
|
||||
// a melee weapon out...
|
||||
ActionEquipMostDamagingMelee();
|
||||
}
|
||||
|
||||
// Wrapper, to stop repeating the same lines! :-)
|
||||
int BuffCastSpell(int nSpell)
|
||||
{
|
||||
if(GetHasSpell(nSpell))
|
||||
{
|
||||
ActionCastSpellAtObject(nSpell, OBJECT_SELF, METAMAGIC_ANY, FALSE, FALSE, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
/*/////////////////////// [On Heartbeat - Move Nearer PC] //////////////////////
|
||||
Filename: J_AI_Heart_Serch
|
||||
///////////////////////// [On Heartbeat - Move Nearer PC] //////////////////////
|
||||
This is fired to perform moving nearer the PC, or searching towards them.
|
||||
|
||||
Yes, like the Henchmen and Battle AI code. I am sure they won't mind - if
|
||||
they do, I will remove it :-)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
1.4 - Reformatted as with the rest of the AI
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This makes the NPC move nearer to a PC. Fires if the spawn condition
|
||||
is on and the timer is not, and only 1/4 heartbeats to lessen the effect.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [On Heartbeat - Move Nearer PC] ////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
|
||||
if(GetIsObjectValid(oPC) && GetIsEnemy(oPC) &&
|
||||
GetDistanceToObject(oPC) <
|
||||
IntToFloat(GetBoundriedAIInteger(AI_SEARCH_IF_ENEMIES_NEAR_RANGE, 25, 50, 5)))
|
||||
{
|
||||
vector vPC = GetPosition(oPC);
|
||||
// Whats the distance we use to move a bit nearer?
|
||||
int nRandom = 10 + Random(10);
|
||||
// Randomise a point nearby.
|
||||
vPC.x += IntToFloat(nRandom - (Random(2 * nRandom + 1)));
|
||||
vPC.y += IntToFloat(nRandom - (Random(2 * nRandom + 1)));
|
||||
vPC.z += IntToFloat(nRandom - (Random(2 * nRandom + 1)));
|
||||
// Define the location
|
||||
location lNew = Location(GetArea(oPC), vPC, IntToFloat(Random(359)));
|
||||
SetLocalTimer(AI_TIMER_SEARCHING, GetDistanceToObject(oPC));
|
||||
ClearAllActions();
|
||||
ActionMoveToLocation(lNew);
|
||||
}
|
||||
}
|
@@ -1,332 +0,0 @@
|
||||
/*/////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Filename: J_AI_OnBlocked or nw_c2_defaulte
|
||||
///////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Added in user defined constant - won't open any doors.
|
||||
0 = Default (even if not set) opens as appropriate
|
||||
1 = Always bashes the door.
|
||||
2 = Never open any doors
|
||||
3 = Never opens plot doors
|
||||
|
||||
They will: (int is intellgience needed)
|
||||
1. Open if not trapped (7 int)
|
||||
2. Unlock if possible, and rank is high enough, and it needs no key and is not trapped (7 int)
|
||||
3. Untrap the door, if possible, if trapped (7 int)
|
||||
4. Else, if has high enough stats, try Knock. (10 int)
|
||||
6. Else Equip appropriate weapons and bash (5 int)
|
||||
|
||||
Note: This also fires for blocking via. creatures. It is optimised, and
|
||||
works by re-targeting and doing a few small things to do with blocking.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.0 - Opens with Knock. Unlocks door. Ignores trapped doors.
|
||||
1.3 - Debug messages.
|
||||
- New events, even if the change of using them is small!
|
||||
- No ClearAllactions so any previous movings will carry on once the door is gone.
|
||||
- Removed debug messages
|
||||
- Added Creature reaction code
|
||||
1.4 - Need to add a "hands" check (done on spawn, to set a setting to not
|
||||
open doors at all, IE: We do NOT have hands, do not open doors), so
|
||||
its a little more realistic "out of the box"
|
||||
- Fixed an instance of GetObjectSeen being repeated.
|
||||
- Fixed the variable AI_DOOR_INTELLIGENCE not being got via GetAIInteger().
|
||||
- Removed unneeded else statement.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Uses simple code to deal with a door in the best way possible.
|
||||
|
||||
Uses DoDoorAction, which is added to the top of an action queue and doesn't,
|
||||
therefore, delete any ActionAttack's and so on below it. (Or I hope it
|
||||
is like this)
|
||||
|
||||
Creatures are reacted by with ClearAllActions usually.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetBlockingDoor, GetIsDoorActionPossible, GetLocked, GetLockKeyRequired
|
||||
GetLockKeyTag, GetLockUnlockDC, GetPlotFlag, DoDoorAction
|
||||
///////////////////////// [On Blocked] ///////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
// Fires the end-blocked event.
|
||||
void FireBlockedEvent();
|
||||
// Range attack oTarget.
|
||||
int RangedAttack(object oTarget = OBJECT_INVALID);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-on blocked-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, EVENT_ON_BLOCKED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// This CAN return a blocking creature.
|
||||
object oBlocker = GetBlockingDoor();
|
||||
int nBlockerType = GetObjectType(oBlocker);
|
||||
|
||||
if(!GetIsObjectValid(oBlocker)) return;
|
||||
|
||||
// Anyone blocked by an enemy will re-target them (and attack them), blocked
|
||||
// by someone they cannot get they will cast seeing spells and react, and if
|
||||
// blocked by a friend, they may run back and use a ranged weapon if they
|
||||
// have one.
|
||||
if(nBlockerType == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// Are we doing something that should not be overriden? (even fleeing,
|
||||
// if stuck, we can't do anything else then move again on heartbeat!)
|
||||
if(GetIsPerformingSpecialAction()) return;
|
||||
|
||||
// Blocked timer, we normally do an action. A small timer stops a lot
|
||||
// of lag.
|
||||
if(GetLocalTimer(AI_TIMER_BLOCKED)) return;
|
||||
|
||||
// Set the timer for 1 second
|
||||
SetLocalTimer(AI_TIMER_BLOCKED, 1.0);
|
||||
|
||||
// Is it an enemy?
|
||||
if(GetIsEnemy(oBlocker))
|
||||
{
|
||||
// Check if seen or heard
|
||||
if(GetObjectSeen(oBlocker) || GetObjectHeard(oBlocker))
|
||||
{
|
||||
// Enemy :-) We can re-target (as know of thier presence), using
|
||||
// them as a target.
|
||||
// - This overrides even casting a spell - basically, as we should
|
||||
// be moving, this will re-cast it at someone or something in range
|
||||
SetAIObject(AI_ATTACK_SPECIFIC_OBJECT, oBlocker);
|
||||
|
||||
// Check if we can do combat - if we cannot, we can re-do combat
|
||||
// next time
|
||||
if(!GetIsBusyWithAction())
|
||||
{
|
||||
// Attacks if we are not attacking
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oBlocker);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invisible? Not there? Some odd error? We set that we know of
|
||||
// someone invisible, and will attack if not in combat.
|
||||
if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oBlocker) ||
|
||||
GetStealthMode(oBlocker) == STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
SetAIObject(AI_LAST_TO_GO_INVISIBLE, oBlocker);
|
||||
}
|
||||
// Shout to allies
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// Check if we can do combat
|
||||
if(!GetIsBusyWithAction())
|
||||
{
|
||||
// Attacks if we are not attacking
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else is non-enemy, a friend or neutral
|
||||
else
|
||||
{
|
||||
// As we are blocked by them, we re-do combat - we have a choice of
|
||||
// either using a Bow to attack our target (if that was what
|
||||
// we were doing) and move back a little, or re-initiate combat
|
||||
|
||||
// Were we attacking in combat?
|
||||
object oPrevious = GetAttackTarget();
|
||||
|
||||
// Check action
|
||||
if(GetCurrentAction() == ACTION_ATTACKOBJECT)
|
||||
{
|
||||
// This gets set to FALSE if we can cutthrough attack,
|
||||
// or whatever.
|
||||
|
||||
int bPreviousAttackFailed = FALSE;
|
||||
// Check if we can see our previous target
|
||||
if(GetObjectSeen(oPrevious) ||
|
||||
(GetObjectHeard(oPrevious) && LineOfSightObject(OBJECT_SELF, oPrevious)))
|
||||
{
|
||||
// We can! see if we can re-attack with ranged weapon, else
|
||||
// doesn't matter we can see them
|
||||
bPreviousAttackFailed = RangedAttack(oPrevious);
|
||||
}
|
||||
|
||||
// If we havn't added an action yet...
|
||||
if(bPreviousAttackFailed == FALSE)
|
||||
{
|
||||
// We have not stopped the script - so determine combat
|
||||
// round against nearest seen or heard enemy!
|
||||
if(!RangedAttack())
|
||||
{
|
||||
// Else normal round to try and get a new target
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else // if(nAction == ACTION_CASTSPELL and others)
|
||||
{
|
||||
// Reinitate combat, but don't attack oPrevious
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Placeable - Currently not returned, however, added just in case!
|
||||
else if(nBlockerType == OBJECT_TYPE_PLACEABLE)
|
||||
{
|
||||
// Check for plot, and therefore attack it to bring it down.
|
||||
// - Remember, ActionAttack will re-initiate when combat round fires
|
||||
// again in 3 or 6 seconds (or less, if we just were moving)
|
||||
if(!GetPlotFlag(oBlocker) &&
|
||||
GetIsPlaceableObjectActionPossible(oBlocker, PLACEABLE_ACTION_BASH))
|
||||
{
|
||||
// Do placeable action
|
||||
DoPlaceableObjectAction(oBlocker, PLACEABLE_ACTION_BASH);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Door behaviour
|
||||
else if(nBlockerType == OBJECT_TYPE_DOOR)
|
||||
{
|
||||
int nDoorIntelligence = GetAIInteger(AI_DOOR_INTELLIGENCE);
|
||||
int nInt = GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE);
|
||||
if(nDoorIntelligence == 1)// 1 = Always bashes the doors, plot, locked or anything.
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
// We re-initiate combat.
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(nDoorIntelligence == 2)// 2 = Never open anything, bashing or not.
|
||||
{
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(nDoorIntelligence == 3)// 3 = Never tries anything against plot doors.
|
||||
{
|
||||
if(GetPlotFlag(oBlocker))
|
||||
{
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(nInt >= 5)
|
||||
{
|
||||
// Need some intelligence :-)
|
||||
if(nInt >= 7)
|
||||
{
|
||||
// Right, first, we may...shock...open it!!!
|
||||
// Checks Key, lock, trap and if the action is possible.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_OPEN) &&
|
||||
!GetLocked(oBlocker) &&
|
||||
!GetIsTrapped(oBlocker) &&
|
||||
(!GetLockKeyRequired(oBlocker) ||
|
||||
(GetLockKeyRequired(oBlocker) && GetItemPossessor(GetObjectByTag(GetLockKeyTag(oBlocker))) == OBJECT_SELF)))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_OPEN);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
// Unlock it with the skill, if it is not trapped and we can :-P
|
||||
// We take 20 off the door DC, thats our minimum roll, after all.
|
||||
if(GetLocked(oBlocker) &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER) &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSkill(SKILL_OPEN_LOCK) &&
|
||||
GetIsDoorActionPossible(oBlocker, DOOR_ACTION_UNLOCK) && !GetIsTrapped(oBlocker) &&
|
||||
(GetSkillRank(SKILL_OPEN_LOCK) >= (GetLockLockDC(oBlocker) - 20)))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_UNLOCK);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
// Specilist thing - knock
|
||||
if(nInt >= 10)
|
||||
{
|
||||
if((GetIsDoorActionPossible(oBlocker, DOOR_ACTION_KNOCK)) &&
|
||||
GetLockUnlockDC(oBlocker) <= 25 &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSpell(SPELL_KNOCK))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_KNOCK);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If Our Int is over 5, we will bash after everything else.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_BASH) && !GetPlotFlag(oBlocker))
|
||||
{
|
||||
if(GetAttackTarget() != oBlocker)
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
}
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire Blocked event
|
||||
FireBlockedEvent();
|
||||
}
|
||||
// Fires the end-blocked event.
|
||||
void FireBlockedEvent()
|
||||
{
|
||||
// Fire End-blocked-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_ON_BLOCKED_EVENT, EVENT_ON_BLOCKED_EVENT);
|
||||
}
|
||||
// Range attack oTarget.
|
||||
int RangedAttack(object oTarget)
|
||||
{
|
||||
// If we are primarily melee, don't use this
|
||||
if(!GetSpawnInCondition(AI_FLAG_COMBAT_BETTER_AT_HAND_TO_HAND, AI_COMBAT_MASTER)) return FALSE;
|
||||
|
||||
object oRangedTarget = oTarget;
|
||||
if(!GetIsObjectValid(oRangedTarget))
|
||||
{
|
||||
oRangedTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
{
|
||||
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
// heard must be in LOS to attack, as we are probably stuck
|
||||
if(!GetIsObjectValid(oTarget) && LineOfSightObject(OBJECT_SELF, oRangedTarget))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ranged weapon attack against oTarget
|
||||
// doesn't matter we can see them
|
||||
object oRanged = GetAIObject(AI_WEAPON_RANGED);
|
||||
int nAmmo = GetAIInteger(AI_WEAPON_RANGED_AMMOSLOT);
|
||||
|
||||
// Check ammo and validness
|
||||
if(GetIsObjectValid(oRanged) && (nAmmo == INVENTORY_SLOT_RIGHTHAND ||
|
||||
GetIsObjectValid(GetItemInSlot(nAmmo))))
|
||||
{
|
||||
// Attack with it
|
||||
ClearAllActions();
|
||||
ActionEquipItem(oRanged, INVENTORY_SLOT_RIGHTHAND);
|
||||
ActionAttack(oRangedTarget);
|
||||
// Stop
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
/*/////////////////////// [On Combat Round End] ////////////////////////////////
|
||||
Filename: nw_c2_default3 or J_AI_OnCombatrou
|
||||
///////////////////////// [On Combat Round End] ////////////////////////////////
|
||||
This is run every 3 or 6 seconds, if the creature is in combat. It is
|
||||
executed only in combat automatically.
|
||||
|
||||
It runs what the AI should do, bascially.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Executes same script as the other parts of the AI to cuase a new action
|
||||
1.4 -
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Calls the combat AI file using the J_INC_OTHER_AI include function,
|
||||
DetermineCombatRound.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetAttackTarget, GetLastHostileActor, GetAttemptedAttackTarget,
|
||||
GetAttemptedSpellTarget (Or these are useful at least!)
|
||||
///////////////////////// [On Combat Round End] //////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-combat-round-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_END_COMBAT_ROUND_PRE_EVENT, EVENT_END_COMBAT_ROUND_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// It is our normal call (every 3 or 6 seconds, when we can change actions)
|
||||
// so no need to delete, and we fire the UDE's.
|
||||
|
||||
// Determine combat round against an invalid target (as default)
|
||||
DetermineCombatRound();
|
||||
|
||||
// Fire End of end combat round event
|
||||
FireUserEvent(AI_FLAG_UDE_END_COMBAT_ROUND_EVENT, EVENT_END_COMBAT_ROUND_EVENT);
|
||||
}
|
@@ -1,160 +0,0 @@
|
||||
/*/////////////////////// [On Conversation] ////////////////////////////////////
|
||||
Filename: J_AI_OnConversat or nw_c2_default4
|
||||
///////////////////////// [On Conversation] ////////////////////////////////////
|
||||
OnConversation/ Listen to shouts.
|
||||
Documented, and checked. -Working-
|
||||
|
||||
Added spawn in condition - Never clear actions when talking.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in conversation thing - IE we can set speakstrings, no need for conversation file.
|
||||
- Sorted more shouts out.
|
||||
- Should work right, and not cause too many actions (as we ignore
|
||||
shouts for normally 12 or so seconds before letting them affect us again).
|
||||
1.4 - Deafness incorpreated.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Uses RespondToShout to react to allies' shouts, and just attacks any enemy
|
||||
who speaks, or at least moves to them. (OK, dumb if they are invisible, but
|
||||
oh well, they shouldn't talk so loud!)
|
||||
|
||||
Remember, whispers are never heard if too far away, speakstrings don't go
|
||||
through walls, and shouts are always heard (so we don't go off to anyone
|
||||
not in our area, remember)
|
||||
|
||||
Deafness causes us to never hear battle, so unless we see the target speaking
|
||||
we do not react. Doesn't apply to normal conversations - although if we cannot
|
||||
talk (also restricted by deafness) then so be it.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetListenPatternNumber, GetLastSpeaker, TestStringAgainstPattern,
|
||||
GetMatchedSubstring
|
||||
///////////////////////// [On Conversation] //////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-conversation-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ON_DIALOGUE_PRE_EVENT, EVENT_ON_DIALOGUE_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Declarations
|
||||
int nMatch = GetListenPatternNumber();
|
||||
object oShouter = GetLastSpeaker();
|
||||
string sSpoken = GetMatchedSubstring(0);
|
||||
|
||||
// We can ignore everything under special cases - EG no valid shouter,
|
||||
// we are fleeing, its us, or we are not in the same area.
|
||||
// - We break out of the script if this happens.
|
||||
if(!GetIsObjectValid(oShouter) || /* Must be a valid speaker! */
|
||||
oShouter == OBJECT_SELF || /* Not us! */
|
||||
GetIsPerformingSpecialAction() || /* Not fleeing */
|
||||
GetIgnore(oShouter) || /* Not ignoring the shouter */
|
||||
GetArea(oShouter) != GetArea(OBJECT_SELF))/* Same area (Stops loud yellow shouts getting NPCs) */
|
||||
{
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Conversation if not a shout.
|
||||
if(nMatch == -1)
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Make sure it is a PC and we are not fighting.
|
||||
if(!GetIsFighting() && (GetIsPC(oShouter) || GetIsDMPossessed(oShouter)))
|
||||
{
|
||||
// If we have something random (or not) to say instead of
|
||||
// the conversation, we will say that.
|
||||
if(GetLocalInt(OBJECT_SELF, ARRAY_SIZE + AI_TALK_ON_CONVERSATION))
|
||||
{
|
||||
ClearAllActions();// Stop
|
||||
SetFacingPoint(GetPosition(oShouter));// Face
|
||||
SpeakArrayString(AI_TALK_ON_CONVERSATION);// Speak string
|
||||
PlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 3.0);// "Talk", then resume potitions.
|
||||
ActionDoCommand(ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are set to NOT clear all actions, we won't.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_NO_CLEAR_ACTIONS_BEFORE_CONVERSATION, AI_OTHER_MASTER))
|
||||
{
|
||||
ClearAllActions();
|
||||
}
|
||||
BeginConversation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it is a valid shout...and a valid shouter.
|
||||
// - Not a DM. Not ignoring shouting. Not a Debug String.
|
||||
else if(!GetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID) &&// Not listening (IE heard already)
|
||||
!GetIsDM(oShouter) && FindSubString(sSpoken, "[Debug]") == -1 &&
|
||||
// 1.4 - Deafness (or they are seen) check, for fun.
|
||||
(!GetHasEffect(EFFECT_TYPE_DEAF) || GetObjectSeen(oShouter)))
|
||||
{
|
||||
if(GetIsFriend(oShouter) || GetFactionEqual(oShouter))
|
||||
{
|
||||
// If they are a friend, not a PC, and a valid number, react.
|
||||
// In the actual RespondToShout call, we do check to see if we bother.
|
||||
// - Is PC - or is...master?
|
||||
// - Shouts which are not negative, and not AI_ANYTHING_SAID_CONSTANT.
|
||||
if(nMatch >= 0 && nMatch != AI_SHOUT_ANYTHING_SAID_CONSTANT &&
|
||||
!GetIsPC(oShouter) && !GetIsPC(GetMaster(oShouter)))
|
||||
{
|
||||
// Respond to the shout
|
||||
RespondToShout(oShouter, nMatch);
|
||||
}
|
||||
// Else either is PC or is shout 0 (everything!)
|
||||
// - not if we are in combat, or they are not.
|
||||
else if(!CannotPerformCombatRound() &&
|
||||
GetIsInCombat(oShouter) &&
|
||||
GetObjectType(oShouter) == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// 57: "[Shout] Friend (may be PC) in combat. Attacking! [Friend] " + GetName(oShouter)
|
||||
DebugActionSpeakByInt(57, oShouter);
|
||||
|
||||
// Respond to oShouter
|
||||
IWasAttackedResponse(oShouter);
|
||||
}
|
||||
}
|
||||
else if(GetIsEnemy(oShouter) && GetObjectType(oShouter) == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// If we hear anything said by an enemy, and are not fighting, attack them!
|
||||
if(!CannotPerformCombatRound())
|
||||
// the negatives are associate shouts, Normally (!)
|
||||
// 0+ are my shouts. 0 is anything
|
||||
{
|
||||
// We make sure it isn't an emote (set by default)
|
||||
if(nMatch == AI_SHOUT_ANYTHING_SAID_CONSTANT &&
|
||||
GetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER))
|
||||
{
|
||||
// Jump out if its an emote - "*Nods*"
|
||||
if(GetStringLeft(sSpoken, 1) == EMOTE_STAR &&
|
||||
GetStringRight(sSpoken, 1) == EMOTE_STAR)
|
||||
{
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 58: "[Shout] Responding to shout [Enemy] " + GetName(oShouter) + " Who has spoken!"
|
||||
DebugActionSpeakByInt(58, oShouter);
|
||||
|
||||
// Short non-respond
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
|
||||
// Attack the enemy!
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oShouter);
|
||||
|
||||
// Shout to allies to attack the shouter
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
}
|
@@ -1,241 +0,0 @@
|
||||
/*/////////////////////// [On Damaged] /////////////////////////////////////////
|
||||
Filename: nw_c2_default6 or J_AI_OnDamaged
|
||||
///////////////////////// [On Damaged] /////////////////////////////////////////
|
||||
We attack any damager if same area (and not already fighting
|
||||
then search for enemies (defaults to searching if there are no enemies left).
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - If we have a damager, not equal faction, and not a DM...
|
||||
- We set Max Elemental damage.
|
||||
- Sets the highest damager and amount (if the new damager is seen/heard)
|
||||
- Polymorph improved a little
|
||||
- Hide check
|
||||
- Morale penalty (if set)
|
||||
1.4 - Elemental damage fixed with bugfixed introduced in later patches.
|
||||
- Moved things around, more documentation, a little more ordered.
|
||||
- Added the missing silent shout strings to get allies to attack.
|
||||
- Damaged taunting will not happen if we are dead.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Now with fixes, we can correctly set physical damage done (and elemental
|
||||
damage).
|
||||
|
||||
Otherwise, this acts like a hositile spell, or a normal attack or pickpocket
|
||||
attempt would - and attack the damn person who dares damage us!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetTotalDamageDealt, GetLastDamager, GetCurrentHitPoints (and max),
|
||||
GetDamageDealtByType (must be done seperatly for each, doesn't count melee damage)
|
||||
///////////////////////// [On Damaged] ///////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-damaged-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DAMAGED_PRE_EVENT, EVENT_DAMAGED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Define Objects/Integers.
|
||||
int nDamage = GetTotalDamageDealt();
|
||||
object oDamager = GetLastDamager();
|
||||
// Check to see if we will polymorph.
|
||||
int nPolymorph = GetAIConstant(AI_POLYMORPH_INTO);
|
||||
|
||||
// Total up the physical damage
|
||||
|
||||
// Polymorph check.
|
||||
if(nPolymorph >= 0)
|
||||
{
|
||||
// We won't polymorph if already so
|
||||
if(!GetHasEffect(EFFECT_TYPE_POLYMORPH))
|
||||
{
|
||||
// Polymorph into the requested shape. Cannot be dispelled.
|
||||
effect eShape = SupernaturalEffect(EffectPolymorph(nPolymorph));
|
||||
effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD);
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eShape, OBJECT_SELF));
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF));
|
||||
}
|
||||
DeleteAIConstant(AI_POLYMORPH_INTO);// We set it to invalid (sets to 0).
|
||||
}
|
||||
// First, we check AOE spells...
|
||||
if(GetObjectType(oDamager) == OBJECT_TYPE_AREA_OF_EFFECT)
|
||||
{
|
||||
// Set the damage done by it (the last damage)
|
||||
// Set to the tag of the AOE, prefixed AI style to be sure.
|
||||
// - Note, doesn't matter about things like
|
||||
if(nDamage > 0)
|
||||
{
|
||||
// Set it to object to string, which we will delete later anywho.
|
||||
SetAIInteger(ObjectToString(oDamager), nDamage);
|
||||
}
|
||||
}
|
||||
// Hostile attacker...but it doesn't matter (at the moment) if they even
|
||||
// did damage.
|
||||
// * GetIgnoreNoFriend() wrappers DM, Validity, Faction Equal and Dead checks in one
|
||||
else if(!GetIgnoreNoFriend(oDamager))
|
||||
{
|
||||
// Adjust automatically if set. (and not an AOE)
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oDamager) && !GetFactionEqual(oDamager))
|
||||
{
|
||||
AdjustReputation(oDamager, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oDamager);
|
||||
|
||||
// Did they do damage to use? (IE: No DR) Some things are inapproprate
|
||||
// to check if no damage was actually done.
|
||||
if(nDamage > 0)
|
||||
{
|
||||
// Speak the damaged string, if applicable.
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
SpeakArrayString(AI_TALK_ON_DAMAGED);
|
||||
}
|
||||
// 1.4 note: These two variables are currently *unused* apart from
|
||||
// healing. When healing a being (even another NPC) they are checked
|
||||
// for massive damage. Can not bother to set the highest damager for now.
|
||||
// NEW:
|
||||
int nHighestDamage = GetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
if(nDamage >= nHighestDamage)
|
||||
{
|
||||
SetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT, nDamage);
|
||||
}
|
||||
|
||||
/* OLD:
|
||||
|
||||
// Get the previous highest damager, and highest damage amount
|
||||
object oHighestDamager = GetAIObject(AI_HIGHEST_DAMAGER);
|
||||
int nHighestDamage = GetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
// Set the highest damager, if they are seen or heard, and have done loads.
|
||||
if((GetObjectSeen(oDamager) || GetObjectHeard(oDamager)) &&
|
||||
nDamage >= nHighestDamage || !GetIsObjectValid(oHighestDamager))
|
||||
{
|
||||
SetAIObject(AI_HIGHEST_DAMAGER, oDamager);
|
||||
SetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT, nDamage);
|
||||
}
|
||||
// Else, if the original was not valid...or not seen/heard, we
|
||||
// delete it so we don't bother to use it later.
|
||||
else if(!GetIsObjectValid(oHighestDamager) ||
|
||||
(!GetObjectSeen(oHighestDamager) && !GetObjectHeard(oHighestDamager)))
|
||||
{
|
||||
DeleteAIObject(AI_HIGHEST_DAMAGER);
|
||||
DeleteAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
}
|
||||
*/
|
||||
|
||||
// Get all the physical damage. Elemental damage is then nDamage minus
|
||||
// the physical damage.
|
||||
int nPhysical = GetDamageDealtByType(DAMAGE_TYPE_BASE_WEAPON |
|
||||
DAMAGE_TYPE_BLUDGEONING |
|
||||
DAMAGE_TYPE_PIERCING |
|
||||
DAMAGE_TYPE_SLASHING);
|
||||
// If they are all -1, then we make nPhysical 0.
|
||||
if(nPhysical <= -1) nPhysical = 0;
|
||||
|
||||
// Physical damage - only sets if the last damager is the last attacker.
|
||||
if(GetAIObject(AI_STORED_LAST_ATTACKER) == oDamager)
|
||||
{
|
||||
// Get the previous highest damage and test it
|
||||
if(nPhysical > GetAIInteger(AI_HIGHEST_PHISICAL_DAMAGE_AMOUNT))
|
||||
{
|
||||
// If higher, and was a melee/ranged attacker, set it.
|
||||
// This does include other additional physical damage - EG:
|
||||
// weapon property: Bonus Damage.
|
||||
SetAIInteger(AI_HIGHEST_PHISICAL_DAMAGE_AMOUNT, nPhysical);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the max elemental damage done, for better use of elemental
|
||||
// protections. This is set for the most damage...so it could be
|
||||
// 1 (for a +1 fire weapon, any number of hits) or over 50 (good
|
||||
// fireball/flame storm etc.)
|
||||
int nElemental = nDamage - nPhysical;
|
||||
if(nElemental > GetAIInteger(MAX_ELEMENTAL_DAMAGE))
|
||||
{
|
||||
SetAIInteger(MAX_ELEMENTAL_DAMAGE, nElemental);
|
||||
}
|
||||
// Set the last damage done, may set to 0 of course :-P
|
||||
// * This is only set if they did damage us at all, however.
|
||||
SetAIInteger(LAST_ELEMENTAL_DAMAGE, nElemental);
|
||||
|
||||
// Morale: We may get a penalty if it does more than a cirtain amount of HP damage.
|
||||
// Other: We set highest damager and amount.
|
||||
if(!GetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER))
|
||||
{
|
||||
// Get penalty and how much damage at once needs to be done
|
||||
int nPenalty = GetBoundriedAIInteger(AI_DAMAGE_AT_ONCE_PENALTY, 6, 50, 1);
|
||||
int nToDamage = GetBoundriedAIInteger(AI_DAMAGE_AT_ONCE_FOR_MORALE_PENALTY, GetMaxHitPoints()/6, GetMaxHitPoints(), 1);
|
||||
if(nDamage > nToDamage)
|
||||
{
|
||||
// 61: "[Damaged] Morale Penalty for 600 seconds [Penalty]" + IntToString(iPenalty)
|
||||
DebugActionSpeakByInt(61, OBJECT_INVALID, nPenalty);
|
||||
// Apply penalty
|
||||
SetMoralePenalty(nPenalty, 300.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we are not attacking anything, and not in combat, react!
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// 62: "[Damaged] Not in combat: DCR [Damager]" + GetName(oDamager)
|
||||
DebugActionSpeakByInt(62, oDamager);
|
||||
|
||||
// Check if they are in the same area. Can be a left AOE spell.
|
||||
// Don't attack purposly across area's.
|
||||
if(GetArea(oDamager) == GetArea(OBJECT_SELF))
|
||||
{
|
||||
// Shout to allies to attack the enemy who attacked me
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
DetermineCombatRound(oDamager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// Else it is friendly, or invalid damager
|
||||
else
|
||||
{
|
||||
// Still will react - eg: A left AOE spell (which might mean a battle
|
||||
// just happened)
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Shout to allies to attack generally. No target to specifically attack,
|
||||
// as it is an ally.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// 63: [Damaged] Not in combat: DCR. Ally hit us. [Damager(Ally?)]" + GetName(oDamager)
|
||||
DebugActionSpeakByInt(63, oDamager);
|
||||
DetermineCombatRound();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// User defined event - for normally immoral creatures.
|
||||
if(GetCurrentHitPoints() == 1)
|
||||
{
|
||||
// Fire the immortal damaged at 1 HP event.
|
||||
FireUserEvent(AI_FLAG_UDE_DAMAGED_AT_1_HP, EVENT_DAMAGED_AT_1_HP);
|
||||
}
|
||||
// Fire End of Damaged event
|
||||
FireUserEvent(AI_FLAG_UDE_DAMAGED_EVENT, EVENT_DAMAGED_EVENT);
|
||||
}
|
@@ -1,164 +0,0 @@
|
||||
/*/////////////////////// [On Death] ///////////////////////////////////////////
|
||||
Filename: J_AI_OnDeath or nw_c2_default7
|
||||
///////////////////////// [On Death] ///////////////////////////////////////////
|
||||
Speeded up no end, when compiling, with seperate Include.
|
||||
Cleans up all un-droppable items, all ints and all local things when destroyed.
|
||||
|
||||
Check down near the bottom for a good place to add XP or corpse lines ;-)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in Turn of corpses toggle
|
||||
- Added in appropriate space for XP awards, marked with ideas (effect death)
|
||||
1.4 - Removed the redudnant notes on the "You have gained 0 experience" message
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
You can edit this for experience, there is a seperate section for it.
|
||||
|
||||
It will use DeathCheck to execute a cleanup-and-destroy script, that removes
|
||||
any coprse, named "j_ai_destroyself".
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastKiller.
|
||||
///////////////////////// [On Death] /////////////////////////////////////////*/
|
||||
|
||||
// We only require the constants/debug file. We have 1 function, not worth another include.
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// We need a wrapper. If the amount of deaths, got in this, is not equal to iDeaths,
|
||||
// we don't execute the script, else we do. :-P
|
||||
void DeathCheck(int nDeaths);
|
||||
|
||||
void main()
|
||||
{
|
||||
// If we are set to, don't fire this script at all
|
||||
if(GetAIInteger(I_AM_TOTALLY_DEAD)) return;
|
||||
|
||||
// Pre-death-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DEATH_PRE_EVENT, EVENT_DEATH_PRE_EVENT)) return;
|
||||
|
||||
// Note: No AI on/off check here.
|
||||
|
||||
// Who killed us? (alignment changing, debug, XP).
|
||||
object oKiller = GetLastKiller();
|
||||
|
||||
// Stops if we just applied EffectDeath to ourselves.
|
||||
if(GetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH)) return;
|
||||
|
||||
// Special: To stop giving out multiple amounts of XP, we use EffectDeath
|
||||
// to change the killer, so the XP systems will NOT award MORE XP.
|
||||
// - Even the default one suffers from this!
|
||||
if(GetAIInteger(WE_HAVE_DIED_ONCE))
|
||||
{
|
||||
if(!GetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH))
|
||||
{
|
||||
// Don't apply effect death to self more then once per 2 seconds.
|
||||
SetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH, 2.0);
|
||||
// This should make the last killer us.
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), OBJECT_SELF);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(GetMaxHitPoints()), OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
else if(oKiller != OBJECT_SELF)
|
||||
{
|
||||
// Set have died once, stops giving out mulitple amounts of XP.
|
||||
SetAIInteger(WE_HAVE_DIED_ONCE, TRUE);
|
||||
|
||||
/*/////////////////////// [Experience] /////////////////////////////////////////
|
||||
THIS is the place for it, below this comment.
|
||||
|
||||
It is useful to use GetFirstFactionMember (and Next), GiveXPToCreature,
|
||||
GetXP, SetXP, GetChallengeRating (of self) all are really useful.
|
||||
|
||||
Bug note: GetFirstFactionMember/Next with the PC parameter means either ONLY PC,
|
||||
and so NPC henchmen, unless FALSE is used, will not be even recognised.
|
||||
///////////////////////// [Experience] ///////////////////////////////////////*/
|
||||
// Do XP things (Use object "oKiller" for who killed us).
|
||||
|
||||
|
||||
|
||||
/*/////////////////////// [Experience] ///////////////////////////////////////*/
|
||||
}
|
||||
|
||||
// Note: Here we do a simple way of checking how many times we have died.
|
||||
// Nothing special. Debugging most useful aspect.
|
||||
int nDeathCounterNew = GetAIInteger(AMOUNT_OF_DEATHS);
|
||||
nDeathCounterNew++;
|
||||
SetAIInteger(AMOUNT_OF_DEATHS, nDeathCounterNew);
|
||||
|
||||
// Here is the last time (in game seconds) we died. It is used in the executed script
|
||||
// to make sure we don't prematurly remove areselves.
|
||||
|
||||
// We may want some sort of visual effect - like implosion or something, to fire.
|
||||
int nDeathEffect = GetAIConstant(AI_DEATH_VISUAL_EFFECT);
|
||||
|
||||
// Valid constants from 0 and up. Apply to our location (not to us, who will go!)
|
||||
if(nDeathEffect >= 0)
|
||||
{
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nDeathEffect), GetLocation(OBJECT_SELF));
|
||||
}
|
||||
// Default Commoner alignment changing. (If the commoner is not evil!)
|
||||
if(GetLevelByClass(CLASS_TYPE_COMMONER) > 0 &&
|
||||
GetAlignmentGoodEvil(OBJECT_SELF) != ALIGNMENT_EVIL &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_NO_COMMONER_ALIGNMENT_CHANGE, AI_OTHER_MASTER))
|
||||
{
|
||||
if(GetIsPC(oKiller))
|
||||
{
|
||||
AdjustAlignment(oKiller, ALIGNMENT_EVIL, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it is a summon, henchmen or familar of a PC, we adust the PC itself
|
||||
// Clever, eh?
|
||||
object oMaster = GetMaster(oKiller);
|
||||
if(GetIsObjectValid(oMaster) && GetIsPC(oMaster))
|
||||
{
|
||||
AdjustAlignment(oMaster, ALIGNMENT_EVIL, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Always shout when we are killed. Reactions - Morale penalty, and
|
||||
// attack the killer.
|
||||
AISpeakString(AI_SHOUT_I_WAS_KILLED);
|
||||
|
||||
// Speaks the set death speak, like "AGGGGGGGGGGGGGGGGGGG!! NOOOO!" for instance :-)
|
||||
// Note for 1.4: No need for "CanSpeak()" for this, of course.
|
||||
SpeakArrayString(AI_TALK_ON_DEATH);
|
||||
|
||||
// First check - do we use "destroyable corpses" or not? (default, yes)
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_TURN_OFF_CORPSES, AI_OTHER_MASTER))
|
||||
{
|
||||
// We will actually dissapear after 30.0 seconds if not raised.
|
||||
int nTime = GetAIInteger(AI_CORPSE_DESTROY_TIME);
|
||||
if(nTime == 0) // Error checking
|
||||
{
|
||||
nTime = 30;
|
||||
}
|
||||
// 64: "[Death] Checking corpse status in " + IntToString(nTime) + " [Killer] " + GetName(oKiller) + " [Times Died Now] " + IntToString(nDeathCounterNew)
|
||||
DebugActionSpeakByInt(64, oKiller, nTime, IntToString(nDeathCounterNew));
|
||||
// Delay check
|
||||
DelayCommand(IntToFloat(nTime), DeathCheck(nDeathCounterNew));
|
||||
}
|
||||
else
|
||||
{
|
||||
/************************ [Alternative Corpses] ********************************
|
||||
This is where you can add some alternative corpse code - EG looting
|
||||
and so on, without disrupting the rest of the AI (as the corpses
|
||||
are turned off).
|
||||
************************* [Alternative Corpses] *******************************/
|
||||
// Add alternative corpse code here
|
||||
|
||||
|
||||
/************************ [Alternative Corpses] *******************************/
|
||||
}
|
||||
// Signal the death event.
|
||||
FireUserEvent(AI_FLAG_UDE_DEATH_EVENT, EVENT_DEATH_EVENT);
|
||||
}
|
||||
|
||||
// We need a wrapper. If the amount of deaths, got in this, is not equal to iDeaths,
|
||||
// we don't execute the script, else we do. :-P
|
||||
void DeathCheck(int nDeaths)
|
||||
{
|
||||
// Do the deaths imputted equal the amount we have suffered?
|
||||
if(GetAIInteger(AMOUNT_OF_DEATHS) == nDeaths)
|
||||
{
|
||||
// - This now includes a check for Bioware's lootable functions and using them.
|
||||
ExecuteScript(FILE_DEATH_CLEANUP, OBJECT_SELF);
|
||||
}
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
/*/////////////////////// [On Disturbed] ///////////////////////////////////////
|
||||
Filename: J_AI_OnDisturbed or nw_c2_default8
|
||||
///////////////////////// [On Disturbed] ///////////////////////////////////////
|
||||
This will attack pickpockets, and inventory disturbers. Note: Stupidly, Bioware
|
||||
made this only affect the creature by stealing. Still, oh well :-(
|
||||
|
||||
This means that the only event which fires it is pickpocketing.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Changed why we determine combat round
|
||||
- Any change in inventory will trigger appropriate SetWeapons again.
|
||||
- Added turn of hide things.
|
||||
1.4 - Cleaned up a bit. Removed unused declared variable.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Only fired by stealing, great. Oh well, it will attack any disturber anyway.
|
||||
|
||||
It *might* not be fired if the natural spot check to notice a theft doesn't
|
||||
work. No idea personally.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetInventoryDisturbItem, GetLastDisturbed,
|
||||
GetInventoryDisturbType (I think it is always be stolen :-( ).
|
||||
///////////////////////// [On Disturbed] /////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-disturbed-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DISTURBED_PRE_EVENT, EVENT_DISTURBED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Declare major variables
|
||||
object oDisturber = GetLastDisturbed();
|
||||
object oItem = GetInventoryDisturbItem();
|
||||
int nType = GetInventoryDisturbType();
|
||||
int nBase = GetBaseItemType(oItem);
|
||||
|
||||
// We will reset weapons if it is a weapon.
|
||||
// Reset weapons, or specifically healers kits.
|
||||
if(GetIsObjectValid(oItem))
|
||||
{
|
||||
// Kits
|
||||
if(nBase == BASE_ITEM_HEALERSKIT)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_WEAPONSETTING_SETWEAPONS, 2);
|
||||
ExecuteScript(FILE_RE_SET_WEAPONS, OBJECT_SELF);
|
||||
}
|
||||
else // Think it is a weapon. Saves time :-)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_WEAPONSETTING_SETWEAPONS, 1);
|
||||
ExecuteScript(FILE_RE_SET_WEAPONS, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
// Fight! Or search!
|
||||
if(!GetIgnoreNoFriend(oDisturber) &&
|
||||
(nType == INVENTORY_DISTURB_TYPE_STOLEN || GetIsEnemy(oDisturber)))
|
||||
{
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oDisturber);
|
||||
|
||||
// Can we attack?
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Someone specific to attack
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// One debug speak. We always do one.
|
||||
// 65: "[Disturbed] (pickpocket) Attacking Enemy Distrube [Disturber] " + GetName(oTarget) + " [Type] " + IntToString(iType)
|
||||
DebugActionSpeakByInt(65, oDisturber, nType);
|
||||
|
||||
// Attack the disturber
|
||||
DetermineCombatRound(oDisturber);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get allies interested.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_DISTURBED_EVENT, EVENT_DISTURBED_EVENT);
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
/*/////////////////////// [On Heartbeat] ///////////////////////////////////////
|
||||
Filename: nw_c2_default1 or J_AI_OnHeartbeat
|
||||
///////////////////////// [On Heartbeat] ///////////////////////////////////////
|
||||
Removed stupid stuff, special behaviour, sleep.
|
||||
|
||||
Also, note please, I removed waypoints and day/night posting from this.
|
||||
It can be re-added if you like, but it does reduce heartbeats.
|
||||
|
||||
Added in better checks to see if we should fire this script. Stops early if
|
||||
some conditions (like we can't move, low AI settings) are set.
|
||||
|
||||
Hint: If nothing is used within this script, either remove it from creatures
|
||||
or create one witch is blank, with just a "void main(){}" at the top.
|
||||
|
||||
Hint 2: You could add this very small file to your catche of scripts in the
|
||||
module properties, as it runs on every creature every 6 seconds (ow!)
|
||||
|
||||
This also uses a system of Execute Script :-D This means the heartbeat, when
|
||||
compiled, should be very tiny.
|
||||
|
||||
Note: NO Debug strings!
|
||||
Note 2: Remember, I use default SoU Animations/normal animations. As it is
|
||||
executed, we can check the prerequisists here, and then do it VIA
|
||||
execute script.
|
||||
|
||||
-Working- Best possible, fast compile.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added more "buffs" to fast buff.
|
||||
- Fixed animations (they both WORK and looping ones do loop right!)
|
||||
- Loot behaviour!
|
||||
- Randomly moving nearer a PC in 25M if set.
|
||||
- Removed silly day/night optional setting. Anything we can remove, is a good idea.
|
||||
1.4 - Removed AI level setting. Not good to use, I mistakenly added it.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This fires off every 6 seconds (with PCs in the area, or AI_LEVEL_HIGH without)
|
||||
and therefore is intensive.
|
||||
|
||||
It fires of ExecutesScript things for the different parts - saves CPU stuff
|
||||
if the bits are not used.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: Basically, none. Nothing activates this script. Fires every 6 seconds.
|
||||
///////////////////////// [On Heartbeat] /////////////////////////////////////*/
|
||||
|
||||
// - This includes J_Inc_Constants
|
||||
#include "J_INC_HEARTBEAT"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Special - Runner from the leader shouts, each heartbeat, to others to get thier
|
||||
// attention that they are being attacked.
|
||||
// - Includes fleeing making sure (so it resets the ActionMoveTo each 6 seconds -
|
||||
// this is not too bad)
|
||||
// - Includes door bashing stop heartbeat
|
||||
if(PerformSpecialAction()) return;
|
||||
|
||||
// Pre-heartbeat-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, EVENT_HEARTBEAT_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff() || GetSpawnInCondition(AI_FLAG_OTHER_LAG_IGNORE_HEARTBEAT, AI_OTHER_MASTER)) return;
|
||||
|
||||
// Define the enemy and player to use.
|
||||
object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
|
||||
object oPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
|
||||
|
||||
// We can skip to the end if we are in combat, or something...
|
||||
if(!JumpOutOfHeartBeat() && // We don't stop due to effects.
|
||||
!GetIsInCombat() && // We are not in combat.
|
||||
!GetIsObjectValid(GetAttackTarget()) && // Second combat check.
|
||||
!GetObjectSeen(oEnemy)) // Nearest enemy is not seen.
|
||||
{
|
||||
// Fast buffing...if we have the spawn in condition...
|
||||
if(GetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER) &&
|
||||
GetIsObjectValid(oEnemy) && GetDistanceToObject(oEnemy) <= 40.0)
|
||||
{
|
||||
// ...we may do an advanced buff. If we cannot see/hear oEnemy, but oEnemy
|
||||
// is within 40M, we cast many defensive spells instantly...
|
||||
ExecuteScript(FILE_HEARTBEAT_TALENT_BUFF, OBJECT_SELF);
|
||||
//...if TRUE (IE it does something) we turn of future calls.
|
||||
DeleteSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
// This MUST STOP the heartbeat event - else, the actions may be interrupted.
|
||||
return;
|
||||
}
|
||||
// Execute waypoints file if we have waypoints set up.
|
||||
if(GetWalkCondition(NW_WALK_FLAG_CONSTANT))
|
||||
{
|
||||
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
||||
}
|
||||
// We can't have any waypoints for the other things
|
||||
else
|
||||
{
|
||||
// We must have animations set, and not be "paused", so doing a
|
||||
// longer looping one
|
||||
// - Need a valid player.
|
||||
if(GetIsObjectValid(oPlayer) && !IsInConversation(OBJECT_SELF))
|
||||
{
|
||||
// We may search for PC enemies, 25% chance to move closer to PC's
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_SEARCH_IF_ENEMIES_NEAR, AI_OTHER_MASTER) &&
|
||||
!GetLocalTimer(AI_TIMER_SEARCHING) && d4() == 1)
|
||||
{
|
||||
ExecuteScript(FILE_HEARTBEAT_WALK_TO_PC, OBJECT_SELF);
|
||||
}
|
||||
// Else, Do we have any animations to speak of?
|
||||
// If we have a nearby PC, we do animations.
|
||||
else if(GetHasValidAnimations())
|
||||
{
|
||||
ExecuteScript(FILE_HEARTBEAT_ANIMATIONS, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_HEARTBEAT_EVENT, EVENT_HEARTBEAT_EVENT);
|
||||
}
|
@@ -1,220 +0,0 @@
|
||||
/*/////////////////////// [On Percieve] ////////////////////////////////////////
|
||||
Filename: J_AI_OnPercieve or nw_c2_default2
|
||||
///////////////////////// [On Percieve] ////////////////////////////////////////
|
||||
If the target is an enemy, attack
|
||||
Will determine combat round on that person, is an enemy, basically.
|
||||
Includes shouting for a big radius - if the spawn in condition is set to this.
|
||||
|
||||
NOTE: Debug strings in this file will be uncommented for speed by default.
|
||||
- It is one of the most intensive scripts as it runs so often.
|
||||
- Attempted to optimise as much as possible.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - We include j_inc_other_ai to initiate combat (or go into combat again)
|
||||
- j_inc_other_ai holds all other needed functions/integers ETC.
|
||||
- Turn off hide things.
|
||||
- Added "Only attack if attacked"
|
||||
- Removed special conversation things. Almost no one uses them, and the taunt system is easier.
|
||||
- Should now search around if they move to a dead body, and only once they get there.
|
||||
1.4 - TO DO:
|
||||
|
||||
1. Perception needs checking - attacking outside perception ranges!
|
||||
2. Vanishing targets, etc. test, improve.
|
||||
3. Problems with dispelling invisibility. Maybe either do change the line to create placable, or, of course, cast at location (dispells cannot be metamagiked or whatever) Source
|
||||
4. No Effect Type Ethereal. Source
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
It fires:
|
||||
|
||||
- When a creature enters it perception range (Set in creature properties) and
|
||||
is seen or heard.
|
||||
* Tests show (and in general) it fires HEARD first, then immediantly SEEN if,
|
||||
of course, they are visible. Odd really, but true.
|
||||
- When a creature uses invisiblity/leaves the area in the creatures perception
|
||||
range
|
||||
- When a creature appears suddenly, already in the perception range (not
|
||||
the other way round, normally)
|
||||
- When a creature moves out of the creatures perception range, and therefore
|
||||
becomes unseen.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastPerceived, GetLastPerceptionSeen, GetLastPerceptionHeard,
|
||||
GetLastPerceptionVanished, GetLastPerceptionInaudible.
|
||||
///////////////////////// [On Percieve] //////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-percieve-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_PERCIEVE_PRE_EVENT, EVENT_PERCIEVE_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Declare main things.
|
||||
// - We declare OUTSIDE if's JUST IN CASE!
|
||||
object oPerceived = GetLastPerceived();
|
||||
object oAttackTarget = GetAttackTarget();
|
||||
// 1.4: Very rarely is our attack target valid, so we will set it to
|
||||
// what we would have melee attacked when DCR was called.
|
||||
if(GetIgnoreNoFriend(oAttackTarget) || oAttackTarget == OBJECT_SELF)
|
||||
{
|
||||
oAttackTarget = GetAIObject(AI_LAST_MELEE_TARGET);
|
||||
}
|
||||
int bSeen = GetLastPerceptionSeen();
|
||||
int bHeard = GetLastPerceptionHeard();
|
||||
int bVanished = GetLastPerceptionVanished();
|
||||
int bInaudiable = GetLastPerceptionInaudible();
|
||||
|
||||
// Debug
|
||||
DebugActionSpeak("*** PER ***: " + GetName(oPerceived) + "| SEEN: " + IntToString(bSeen) +
|
||||
"| HEARD: " + IntToString(bHeard) + "| VANISHED: " + IntToString(bVanished) +
|
||||
"| INAUDIABLE: " + IntToString(bInaudiable));
|
||||
|
||||
// Need to be valid and not ignorable.
|
||||
if(GetIsObjectValid(oPerceived) &&
|
||||
!GetIsDM(oPerceived) &&
|
||||
!GetIgnore(oPerceived))
|
||||
{
|
||||
// First, easy enemy checks.
|
||||
if(GetIsEnemy(oPerceived) && !GetFactionEqual(oPerceived))
|
||||
{
|
||||
DebugActionSpeak("*** PER *** ENEMY");
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oPerceived);
|
||||
|
||||
// Well, are we both inaudible and vanished?
|
||||
// * the GetLastPerception should only say what specific event has fired!
|
||||
if(bVanished || bInaudiable)
|
||||
{
|
||||
DebugActionSpeak("*** PER *** VANISHED OR INAUDIBLE");
|
||||
// If they just became invisible because of the spell
|
||||
// invisiblity, or improved invisiblity...we set a local object.
|
||||
// - Beta: Added in ethereal as well.
|
||||
if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oPerceived) ||
|
||||
GetHasEffect(EFFECT_TYPE_SANCTUARY, oPerceived) ||
|
||||
GetStealthMode(oPerceived) == STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
// Set object, AND the location they went invisible!
|
||||
SetAIObject(AI_LAST_TO_GO_INVISIBLE, oPerceived);
|
||||
// We also set thier location for AOE dispelling - same name
|
||||
SetAILocation(AI_LAST_TO_GO_INVISIBLE, GetLocation(oPerceived));
|
||||
}
|
||||
|
||||
// If they were our target, follow! >:-D
|
||||
// - Optional, on spawn option, for following through areas.
|
||||
if(oAttackTarget == oPerceived)
|
||||
{
|
||||
DebugActionSpeak("*** PER *** VANISHED OR INAUDIBLE AND IS CURRENT TARGET");
|
||||
// This means they have exited the area! follow!
|
||||
if(GetArea(oPerceived) != GetArea(OBJECT_SELF))
|
||||
{
|
||||
ClearAllActions();
|
||||
// 51: "[Perception] Our Enemy Target changed areas. Stopping, moving too...and attack... [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(51, oPerceived);
|
||||
// Call to stop silly moving to enemies if we are fleeing
|
||||
ActionMoveToEnemy(oPerceived);
|
||||
}
|
||||
// - Added check for not casting a spell. If we are, we finnish
|
||||
// (EG: AOE spell) and automatically carry on.
|
||||
// 1.4: If we are using a targetted spell, we do cancle our
|
||||
// spellcasting if it is them.
|
||||
else if(GetCurrentAction() != ACTION_CASTSPELL ||
|
||||
GetAttackTarget() == oPerceived)
|
||||
{
|
||||
ClearAllActions();
|
||||
// 52: "[Perception] Enemy Vanished (Same area) Retargeting/Searching [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(52, oPerceived);
|
||||
DetermineCombatRound(oPerceived);
|
||||
}
|
||||
}
|
||||
}// End if just gone out of perception
|
||||
// ELSE they have been SEEN or HEARD. We don't check specifics.
|
||||
else //if(bSeen || bHeard)
|
||||
{
|
||||
// If they have been made seen, and they are our attack target,
|
||||
// we must re-do combat round - unless we are casting a spell.
|
||||
if(bSeen && GetCurrentAction() != ACTION_CASTSPELL &&
|
||||
(oAttackTarget == oPerceived || !GetObjectSeen(oAttackTarget)))
|
||||
{
|
||||
// 53: "[Perception] Enemy seen, and was old enemy/cannot see current. Re-evaluating (no spell) [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(53, oPerceived);
|
||||
DetermineCombatRound(oPerceived);
|
||||
|
||||
// Shout to allies to attack oPerceived
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
// Else We check if we are already attacking.
|
||||
else if(!CannotPerformCombatRound() &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_ONLY_ATTACK_IF_ATTACKED, AI_OTHER_MASTER))
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Special shout, d1000 though!
|
||||
SpeakArrayString(AI_TALK_ON_PERCIEVE_ENEMY, TRUE);
|
||||
}
|
||||
|
||||
// Stop stuff because of facing point - New enemy
|
||||
HideOrClear();
|
||||
|
||||
// Get all allies in 60M to come to thier aid. Talkvolume silent
|
||||
// shout does not seem to work well.
|
||||
// - void function. Checks for the spawn int. in it.
|
||||
// - Turns it off in it too (5 minutes - 1.4)
|
||||
// - Variable range On Spawn
|
||||
ShoutBossShout(oPerceived);
|
||||
|
||||
// 54: "[Perception] Enemy Seen. Not in combat, attacking. [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(54, oPerceived);
|
||||
|
||||
// 1.4 change: SetFacingPoint(GetPosition(oPerceived));
|
||||
// Is now part of DetermineCombatRound().
|
||||
// * This means other events will work similarily.
|
||||
DetermineCombatRound(oPerceived);
|
||||
|
||||
// Warn others
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else, they are an equal faction, or not an enemy (or both)
|
||||
else
|
||||
{
|
||||
// If they are dead, or fighting, eg: we saw something on
|
||||
// waypoints, we charge in to investigate.
|
||||
// * Higher intelligence will buff somewhat as well!
|
||||
if((GetIsDead(oPerceived) || GetIsInCombat(oPerceived)) &&
|
||||
(bSeen || bHeard))
|
||||
{
|
||||
if(GetIsDead(oPerceived))
|
||||
{
|
||||
// 55: "[Perception] Percieved Dead Friend! Moving into investigate [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(55, oPerceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 56: "[Perception] Percieved Alive Fighting Friend! Moving to and attacking. [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(56, oPerceived);
|
||||
}
|
||||
// Check if we can attack
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Hide or clear actions
|
||||
HideOrClear();
|
||||
|
||||
// If we were called to arms, react
|
||||
CallToArmsResponse(oPerceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Warn others even if we don't, or cannot, attack
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End of Percieve event
|
||||
FireUserEvent(AI_FLAG_UDE_PERCIEVE_EVENT, EVENT_PERCIEVE_EVENT);
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
/*/////////////////////// [On Phisical Attacked] ///////////////////////////////
|
||||
Filename: J_AI_OnPhiAttack or nw_c2_default5
|
||||
///////////////////////// [On Phisical Attacked] ///////////////////////////////
|
||||
On Attacked
|
||||
No checking for fleeing or warnings.
|
||||
Very boring really!
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added hiding things
|
||||
1.4 - Missing Silent Shouts have been added.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Got some simple Knockdown timer, so that we use heal sooner if we keep getting
|
||||
a creature who is attempting to knock us down.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastAttacker, GetLastWeaponUsed, GetLastAttackMode, GetLastAttackType
|
||||
///////////////////////// [On Phisical Attacked] /////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-attacked-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ATTACK_PRE_EVENT, EVENT_ATTACK_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Set up objects.
|
||||
object oAttacker = GetLastAttacker();
|
||||
object oWeapon = GetLastWeaponUsed(oAttacker);
|
||||
//int nMode = GetLastAttackMode(oAttacker); // Currently unused
|
||||
int nAttackType = GetLastAttackType(oAttacker);
|
||||
|
||||
// Check if they are valid, a DM, we are ignoring them, they are dead now, or invalid
|
||||
if(!GetIgnoreNoFriend(oAttacker))
|
||||
{
|
||||
// Adjust automatically if set.
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oAttacker))
|
||||
{
|
||||
AdjustReputation(oAttacker, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
// If we were attacked by knockdown, for a timer of X seconds, we make
|
||||
// sure we attempt healing at a higher level.
|
||||
if(!GetLocalTimer(AI_TIMER_KNOCKDOWN) &&
|
||||
(nAttackType == SPECIAL_ATTACK_IMPROVED_KNOCKDOWN ||
|
||||
nAttackType == SPECIAL_ATTACK_KNOCKDOWN) &&
|
||||
!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_KNOCKDOWN) &&
|
||||
GetBaseAttackBonus(oAttacker) + 20 >= GetAC(OBJECT_SELF))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_KNOCKDOWN, 30.0);
|
||||
}
|
||||
|
||||
// Set last hostile, valid attacker (Used in the On Damaged event)
|
||||
SetAIObject(AI_STORED_LAST_ATTACKER, oAttacker);
|
||||
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Speak the phisically attacked string, if applicable.
|
||||
// Speak the damaged string, if applicable.
|
||||
SpeakArrayString(AI_TALK_ON_PHISICALLY_ATTACKED);
|
||||
}
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oAttacker);
|
||||
|
||||
// We set if we are attacked in HTH onto a low-delay timer.
|
||||
// - Not currently used
|
||||
/*if(!GetLocalTimer(AI_TIMER_ATTACKED_IN_HTH))
|
||||
{
|
||||
// If the weapon is not ranged, or is not valid, set the timer.
|
||||
if(!GetIsObjectValid(oWeapon) ||
|
||||
!GetWeaponRanged(oWeapon))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_ATTACKED_IN_HTH, f18);
|
||||
}
|
||||
}*/
|
||||
|
||||
// If we are not fighting, and they are in the area, attack. Else, determine anyway.
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Must be in our area to go after now.
|
||||
if(GetArea(oAttacker) == GetArea(OBJECT_SELF))
|
||||
{
|
||||
// 59: "[Phisically Attacked] Attacking back. [Attacker(enemy)] " + GetName(oAttacker)
|
||||
DebugActionSpeakByInt(59, oAttacker);
|
||||
|
||||
// Attack the attacker
|
||||
DetermineCombatRound(oAttacker);
|
||||
|
||||
// Shout to allies to attack the enemy who attacked me
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// 60: "[Phisically Attacked] Not same area. [Attacker(enemy)] " + GetName(oAttacker)
|
||||
DebugActionSpeakByInt(60, oAttacker);
|
||||
|
||||
// May find another hostile to attack...
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// Else, invalid, DM, ally, etc...must be prepared at least (could be
|
||||
// they are charmed or something!)
|
||||
else
|
||||
{
|
||||
// If we are not fighting, prepare for battle. Something bad must have
|
||||
// happened.
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Respond to oAttacker as if they shouted for help.
|
||||
IWasAttackedResponse(oAttacker);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End of Attacked event
|
||||
FireUserEvent(AI_FLAG_UDE_ATTACK_EVENT, EVENT_ATTACK_EVENT);
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
/*/////////////////////// [On Rested] //////////////////////////////////////////
|
||||
Filename: J_AI_OnRest or nw_c2_defaulta
|
||||
///////////////////////// [On Rested] //////////////////////////////////////////
|
||||
This will play the sitting animation for 6 seconds, just something for resting.
|
||||
Also, walks waypoints (as resting would stop this) :-) and signals event (if so be)
|
||||
Feel free to edit.
|
||||
|
||||
It does have the spell trigger information resetting, however. This can
|
||||
only be removed if they have no spell triggers, although it is hardly worth it.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added sitting.
|
||||
1.4 - Will be editing this down. No need to reset anything on rest, for a
|
||||
better working AI.
|
||||
IDEA: Change so that we will work through all spells/feats in order.
|
||||
If, at cirtain levels, we do not have any spells to cast from that
|
||||
level (set in a global stored integer in the general AI) we ignore all
|
||||
spells in that level. Same for each talent category (no need to use
|
||||
talents for them in the spawn script).
|
||||
|
||||
If not in combat (EG: In heartbeat) we reset the integers saying "don't
|
||||
bother checking those spells" to false.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This fires once, at the END of resting.
|
||||
|
||||
If ClearAllActions is added, the resting is actually stopped, or so it seems.
|
||||
|
||||
It doesn't fire more then once.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: None, it seems.
|
||||
///////////////////////// [On Rested] ////////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Resets all spell triggers used for sString
|
||||
void LoopResetTriggers(string sString, object oTrigger);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-rest-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_RESTED_PRE_EVENT, EVENT_RESTED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Simple debug.
|
||||
// 66: "[Rested] Resting. Type: " + IntToString(GetLastRestEventType())
|
||||
DebugActionSpeakByInt(66, OBJECT_INVALID, GetLastRestEventType());
|
||||
|
||||
// Reset all spell triggers.
|
||||
// Set all triggers
|
||||
object oTrigger = GetAIObject(AI_SPELL_TRIGGER_CREATURE);
|
||||
if(GetIsObjectValid(oTrigger))
|
||||
{
|
||||
LoopResetTriggers(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_DAMAGED_AT_PERCENT, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_IMMOBILE, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_START_OF_COMBAT, oTrigger);
|
||||
}
|
||||
// Some sitting for a few seconds.
|
||||
ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0, 6.0);
|
||||
DelayCommand(9.0, ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF));
|
||||
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_RESTED_EVENT, EVENT_RESTED_EVENT);
|
||||
}
|
||||
|
||||
// Resets all spell triggers used for sString
|
||||
void LoopResetTriggers(string sString, object oTrigger)
|
||||
{
|
||||
int nCnt, bBreak, bUsed;
|
||||
for(nCnt = 1; bBreak != TRUE; nCnt++)
|
||||
{
|
||||
// Check max for this setting
|
||||
bUsed = GetLocalInt(oTrigger, sString + USED);
|
||||
if(bUsed)
|
||||
{
|
||||
DeleteLocalInt(oTrigger, sString + USED);
|
||||
}
|
||||
else
|
||||
{
|
||||
bBreak = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,644 +0,0 @@
|
||||
/*/////////////////////// [On Spawn] ///////////////////////////////////////////
|
||||
Filename: J_AI_OnSpawn or nw_c2_default9
|
||||
///////////////////////// [On Spawn] ///////////////////////////////////////////
|
||||
This file contains options that will determine some AI behaviour, and a lot
|
||||
of toggles for turning things on/off. A big read, but might be worthwhile.
|
||||
|
||||
The documentation is actually fully in the readme files, under the name
|
||||
"On Spawn.html", under "AI File Explanations".
|
||||
|
||||
The order of the options:
|
||||
|
||||
- Important Spawn Settings N/A
|
||||
- Targeting & Fleeing (AI_TARGETING_FLEE_MASTER)
|
||||
- Fighting & Spells (AI_COMBAT_MASTER)
|
||||
- Other Combat - Healing, Skills & Bosses (AI_OTHER_COMBAT_MASTER)
|
||||
- Other - Death corpses, minor things (AI_OTHER_MASTER)
|
||||
- User Defined (AI_UDE_MASTER)
|
||||
- Shouts N/A
|
||||
- Default Bioware settings (WP's, Anims) (NW_GENERIC_MASTER)
|
||||
|
||||
The OnSpawn file is a settings file. These things are set onto a creature, to
|
||||
define cirtain actions. If more than one creature has this script, they all
|
||||
use the settings, unless If/Else statements are used somehow. There is also
|
||||
the process of setting any spells/feats availible, and hiding and walk waypoints
|
||||
are started.
|
||||
|
||||
Other stuff:
|
||||
- Targeting is imporant :-D
|
||||
- If you delete this script, there is a template for the On Spawn file
|
||||
in the zip it came in, for use in the "scripttemplate" directory.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
Note: I have removed:
|
||||
- Default "Teleporting" and exit/return (this seemed bugged anyway, or useless)
|
||||
- Spawn in animation. This can be, of course, re-added.
|
||||
- Day/night posting. This is uneeded, with a changed walk waypoints that does it automatically.
|
||||
|
||||
1.0-1.2 - Used short amount of spawn options.
|
||||
1.3 - All constants names are changed, I am afraid.
|
||||
- Added Set/Delete/GetAIInteger/Constant/Object. This makes sure that the AI
|
||||
doesn't ever interfere with other things - it pre-fixes all stored things
|
||||
with AI_INTEGER_ (and so on)
|
||||
1.4 - TO DO: Clear up some old non-working ones
|
||||
- Added in User Defined part of the script, an auto-turn-off-spells for
|
||||
Ranger and Paladin classes. Need to test - perhaps 1.64 fixed it?
|
||||
|
||||
|
||||
Spawn options changed:
|
||||
- Removed AI level settings (can still be done manually)
|
||||
- Added optional (and off by default) fear-visual for fleeing
|
||||
|
||||
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Note: You can do without all the comments (it may be that you don't want
|
||||
the extra KB it adds or something, although it does not at all slow down a module)
|
||||
so as long as you have these at the end:
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0, SpawnWalkWayPoints());
|
||||
|
||||
Oh, and the include file (Below, "j_inc_spawnin") must be at the top like
|
||||
here. Also recommended is the AI_INTELLIGENCE and AI_MORALE being set (if
|
||||
not using custom AI).
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetIsEncounterCreature
|
||||
///////////////////////// [On Spawn] /////////////////////////////////////////*/
|
||||
|
||||
// Treasure Includes - See end of spawn for uncomment options.
|
||||
|
||||
//#include "nw_o2_coninclude"
|
||||
// Uncomment this if you want default NwN Treasure - Uses line "GenerateNPCTreasure()" at the end of spawn.
|
||||
// - This generates random things from the default pallet based on the creatures level + race
|
||||
|
||||
//#include "x0_i0_treasure"
|
||||
// Uncomment this if you want the SoU Treasure - Uses line "CTG_GenerateNPCTreasure()" at the end of spawn.
|
||||
// - This will spawn treasure based on chests placed in the module. See "x0_i0_treasure" for more information.
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "J_INC_SPAWNIN"
|
||||
|
||||
void main()
|
||||
{
|
||||
/************************ [Important Spawn Settings] **************************/
|
||||
SetAIInteger(AI_INTELLIGENCE, 10);
|
||||
// Intelligence value of the creauture. Can be 1-10, read readme's for help.
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
// Will save (See readme). Remember: -1 or below means they always flee.
|
||||
//SetCustomAIFileName("CUSTOM_AI_FILE");
|
||||
// Sets our custom AI file. Really, only animation settings will apply when this is set.
|
||||
// - Can sort actions against a imputted target (EG: On Percieved enemy) by
|
||||
// "GetLocalObject(OBJECT_SELF, "AI_TEMP_SET_TARGET");"
|
||||
/************************ [Important Spawn Settings] **************************/
|
||||
|
||||
/************************ [Targeting] ******************************************
|
||||
All targeting settings.
|
||||
************************* [Targeting] *****************************************/
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_HP, AI_TARGETING_FLEE_MASTER);
|
||||
// We only attack the lowest current HP.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_AC, AI_TARGETING_FLEE_MASTER);
|
||||
// We only attack the lowest AC (as in 1.2).
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_HD, AI_TARGETING_FLEE_MASTER);
|
||||
// Target the lowest hit dice
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_MAGE_CLASSES, AI_TARGETING_FLEE_MASTER);
|
||||
// We go straight for mages/sorcerors. Nearest one.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_ARCHERS, AI_TARGETING_FLEE_MASTER);
|
||||
// We go for the nearest enemy with a ranged weapon equipped.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_PCS, AI_TARGETING_FLEE_MASTER);
|
||||
// We go for the nearest seen PC enemy.
|
||||
|
||||
//SetAIConstant(AI_FAVOURED_ENEMY_RACE, RACIAL_TYPE_HUMAN);
|
||||
// The AI attacks the nearest enemy, seen, of this race. Use the RACIAL_* constants.
|
||||
//SetAIConstant(AI_FAVOURED_ENEMY_CLASS, CLASS_TYPE_BARD);
|
||||
// The AI attacks the nearest enemy, seen, of this class. Use the CLASS_* constants.
|
||||
|
||||
// Target changing - see readme for info.
|
||||
//SetAIInteger(AI_MAX_TURNS_TO_ATTACK_ONE_TARGET, 6);
|
||||
// Maximum rounds to attack the current target, before re-checking.
|
||||
// % Chance to re-set each target type each round (Could result in current target still)
|
||||
//SetAIInteger(AI_MELEE_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
//SetAIInteger(AI_RANGED_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
//SetAIInteger(AI_SPELL_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
|
||||
// We only target PC's if there are any in range if this is set
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_FILTER_FOR_PC_TARGETS, AI_TARGETING_FLEE_MASTER);
|
||||
|
||||
// Main explanation of AI_SetAITargetingValues, see the AI readme (spawn file)
|
||||
// - Remember, uncommenting one will just ignore it (so will never check target's
|
||||
// AC without TARGETING_AC on)
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_MANTALS, TARGET_LOWER, 1, 12);
|
||||
// Spell mantals are checked only for the spell target. Either Absense of or got any.
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
// Range - very imporant! Basis for all ranged/spell attacks.
|
||||
AI_SetAITargetingValues(TARGETING_AC, TARGET_LOWER, 2, 6);
|
||||
// AC is used for all phisical attacks. Lower targets lower (By default).
|
||||
AI_SetAITargetingValues(TARGETING_SAVES, TARGET_LOWER, 2, 4);
|
||||
// Used for spell attacks. Saves are sorta a AC versus spells.
|
||||
|
||||
// Phisical protections. Used by spells, ranged and melee.
|
||||
// Jasperre - simple check if we are a fighter (hit lower phisicals) or a
|
||||
// mage (attack higher!)
|
||||
if(GetBaseAttackBonus(OBJECT_SELF) > ((GetHitDice(OBJECT_SELF)/2) + 1))
|
||||
{
|
||||
// Fighter/Clerics (It is over a mages BAB + 1 (IE 0.5 BAB/Level) target lower
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_LOWER, 2, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mages target higher (so dispel/elemental attack those who fighters
|
||||
// cannot hit as much). (the lowest BAB, under half our hit dice in BAB)
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_HIGHER, 1, 5);
|
||||
}
|
||||
// Base attack bonus. Used for spells and phisical attacks. Checked with GetBaseAttackBonus.
|
||||
AI_SetAITargetingValues(TARGETING_BAB, TARGET_LOWER, 1, 4);
|
||||
// Hit dice - how powerful in levels the enemy is. Used for all checks.
|
||||
AI_SetAITargetingValues(TARGETING_HITDICE, TARGET_LOWER, 1, 3);
|
||||
|
||||
//AI_SetAITargetingValues(TARGETING_HP_PERCENT, TARGET_LOWER, 1, 3);
|
||||
//AI_SetAITargetingValues(TARGETING_HP_CURRENT, TARGET_LOWER, 1, 3);
|
||||
//AI_SetAITargetingValues(TARGETING_HP_MAXIMUM, TARGET_LOWER, 1, 3);
|
||||
// The HP's are the last thing to choose a target with.
|
||||
/************************ [Targeting] *****************************************/
|
||||
|
||||
/************************ [Fleeing] ********************************************
|
||||
Fleeing - these are toggled on/off by FEARLESS flag.
|
||||
|
||||
3 or under intelligence will just run away. 4 or more will know where allies
|
||||
are, and if there are none, will not run.
|
||||
************************* [Fleeing] *******************************************/
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
// Forces them to not flee. This may be set with AI_SetMaybeFearless at the end.
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_NEVER_FIGHT_IMPOSSIBLE_ODDS, AI_TARGETING_FLEE_MASTER);
|
||||
// This will make the creature never fight against impossible odds (8HD+ different)
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_TURN_OFF_GROUP_MORALE, AI_TARGETING_FLEE_MASTER);
|
||||
// This turns OFF any sort of group morale bonuses.
|
||||
|
||||
//SetAIInteger(AMOUNT_OF_HD_DIFFERENCE_TO_CHECK, -2);
|
||||
// If enemy is within this amount of HD, we do not check morale.
|
||||
//SetAIInteger(BASE_MORALE_SAVE, 20);
|
||||
// Base DC of the will save. It is set to 20 + HD difference - Morale - Group morale mod.
|
||||
//SetAIInteger(HP_PERCENT_TO_CHECK_AT, 80);
|
||||
// %HP needed to be at to check morale. This doesn't affect "Never fight impossible odds"
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_NO_OVERRIDING_HP_AMOUNT, AI_TARGETING_FLEE_MASTER);
|
||||
// This will turn off overriding HP checks. AI may decide to run even
|
||||
// not at the %HP above, this turns the checks off.
|
||||
|
||||
//SetAIInteger(AI_DAMAGE_AT_ONCE_FOR_MORALE_PENALTY, GetMaxHitPoints()/6);
|
||||
// Damage needed to be done at once to get a massive morale penalty (Below)
|
||||
//SetAIInteger(AI_DAMAGE_AT_ONCE_PENALTY, 6);
|
||||
// Penalty for the above, set for some time to negativly affect morale. Added to save DC for fleeing.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_FLEE_TO_NEAREST_NONE_SEEN, AI_TARGETING_FLEE_MASTER);
|
||||
// If set, just runs to nearest non-seen ally, and removes the loop for a good group of allies to run to.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_FLEE_TO_OBJECT, AI_TARGETING_FLEE_MASTER);
|
||||
// They will flee to the nearest object of the tag below, if set.
|
||||
//SetLocalString(OBJECT_SELF, AI_FLEE_OBJECT, "BOSS_TAG_OR_WHATEVER");
|
||||
// This needs setting if the above is to work.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_USE_VISUAL_EFFECT, AI_TARGETING_FLEE_MASTER);
|
||||
// If this is on, we play a visual effect while we flee.
|
||||
/************************ [Fleeing] *******************************************/
|
||||
|
||||
/************************ [Combat - Fighters] **********************************
|
||||
Fighter (Phiscal attacks, really) specific stuff - disarmed weapons, better
|
||||
at hand to hand, and archer behaviour.
|
||||
************************* [Combat - Fighters] *********************************/
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_PICK_UP_DISARMED_WEAPONS, AI_COMBAT_MASTER);
|
||||
// This sets to pick up weapons which are disarmed.
|
||||
|
||||
//SetAIInteger(AI_RANGED_WEAPON_RANGE, 3);
|
||||
// This is the range at which they go into melee (from using a ranged weapon). Default is 3 or 5.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_BETTER_AT_HAND_TO_HAND, AI_COMBAT_MASTER);
|
||||
// Set if you want them to move forwards into HTH sooner. Will always
|
||||
// if the enemy is a mage/archer, else % based on range.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ATTACKING, AI_COMBAT_MASTER);
|
||||
// For archers. If they have ally support, they'd rather move back & shoot then go into HTH.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_MOVE_BACK, AI_COMBAT_MASTER);
|
||||
// This forces the move back from attackers, and shoot bows. Very small chance to go melee.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_USE_BOW, AI_COMBAT_MASTER);
|
||||
// This will make the creature ALWAYs use any bows it has. ALWAYS.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NO_GO_FOR_THE_KILL, AI_COMBAT_MASTER);
|
||||
// Turns off any attempts to kill dying PCs, or attack low hit point people.
|
||||
// This is only ever attempted at 9 or 10 intelligence anyway.
|
||||
/************************ [Combat - Fighters] *********************************/
|
||||
|
||||
/************************ [Combat - Spell Casters] *****************************
|
||||
Spellcaster AI has been improved significantly. As well as adding all new spells,
|
||||
now spellcasters more randomly choose spells from the same level (EG: they
|
||||
may choose not to cast magic missile, and cast negative energy ray instead).
|
||||
|
||||
There are also options here for counterspelling, fast buffing, Cheat cast spells,
|
||||
dispelling, spell triggers, long ranged spells first, immunity toggles, and AOE settings.
|
||||
************************* [Combat - Spell Casters] ****************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_LONGER_RANGED_SPELLS_FIRST, AI_COMBAT_MASTER);
|
||||
// Casts spells only if the caster would not move into range to cast them.
|
||||
// IE long range spells, then medium, then short (unless the enemy comes to us!)
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
// When an enemy comes in 40M, we fast-cast many defensive spells, as if prepared.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_SUMMON_FAMILIAR, AI_COMBAT_MASTER);
|
||||
// The caster summons thier familiar/animal companion. Either a nameless Bat or Badger respectivly.
|
||||
|
||||
// Counterspelling/Dispelling...
|
||||
// It checks for these classes within the 20M counterspell range.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_ARCANE, AI_COMBAT_MASTER);
|
||||
// If got dispels, it counterspells Arcane (Mage/Sorceror) spellcasters.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_DIVINE, AI_COMBAT_MASTER);
|
||||
// If got dispels, it counterspells Divine (Cleric/Druid) spellcasters.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_ONLY_IN_GROUP, AI_COMBAT_MASTER);
|
||||
// Recommended. Only counterspells with 5+ allies in group.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_MAGES_MORE, AI_COMBAT_MASTER);
|
||||
// Targets seen mages to dispel, else uses normal spell target.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_IN_ORDER, AI_COMBAT_MASTER);
|
||||
// This will make the mage not dispel just anything all the time, but important (spell-stopping)
|
||||
// things first, others later, after some spells. If off, anything is dispelled.
|
||||
|
||||
// AOE's
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NEVER_HIT_ALLIES, AI_COMBAT_MASTER);
|
||||
// Override toggle. Forces to never cast AOE's if it will hit an ally + harm them.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_AOE_DONT_MIND_IF_THEY_SURVIVE, AI_COMBAT_MASTER);
|
||||
// Allies who will survive the blast are ignored for calculating best target.
|
||||
//SetAIInteger(AI_AOE_ALLIES_LOWEST_IN_AOE, 3);
|
||||
// Defualt: 3. If amount of allies in blast radius are equal or more then
|
||||
// this, then that location is ignored.
|
||||
//SetAIInteger(AI_AOE_HD_DIFFERENCE, -8);
|
||||
// Very weak allies (who are not comparable to us) are ignored if we would hit them.
|
||||
|
||||
// For these 2, if neither are set, the AI will choose AOE more if there are
|
||||
// lots of enemies, or singles if there are not many.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_SINGLE_TARGETING, AI_COMBAT_MASTER);
|
||||
// For Same-level spells, single target spells are used first.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_MANY_TARGETING, AI_COMBAT_MASTER);
|
||||
// For Same-level spells, AOE spells are used first.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_INSTANT_DEATH_SPELLS, AI_COMBAT_MASTER);
|
||||
// A few Death spells may be cast top-prioritory if the enemy will always fail saves.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SUMMON_TARGETING, AI_COMBAT_MASTER);
|
||||
// Will use a better target to summon a creature at (EG: Ranged attacker)
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_IMMUNITY_CHECKING, AI_COMBAT_MASTER);
|
||||
// Turns On "GetIsImmune" checks. Auto on for 7+ Intel.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SPECIFIC_SPELL_IMMUNITY, AI_COMBAT_MASTER);
|
||||
// Turns On checks for Globes & levels of spells. Auto on for 9+ Intel.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_MORE_ALLY_BUFFING_SPELLS, AI_COMBAT_MASTER);
|
||||
// This will make the caster buff more allies - or, in fact, use spells
|
||||
// to buff allies which they might have not used before.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_USE_ALL_POTIONS, AI_COMBAT_MASTER);
|
||||
// Uses all buffing spells before melee.
|
||||
|
||||
//SetAICheatCastSpells(SPELL_MAGIC_MISSILE, SPELL_ICE_DAGGER, SPELL_HORIZIKAULS_BOOM, SPELL_MELFS_ACID_ARROW, SPELL_NEGATIVE_ENERGY_RAY, SPELL_FLAME_ARROW);
|
||||
// Special: Mages cast for ever with this set.
|
||||
|
||||
// Spell triggers
|
||||
//SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 1, SPELL_PREMONITION);
|
||||
// This is just an example. See readme for more info.
|
||||
|
||||
/************************ [Combat - Spell Casters] ****************************/
|
||||
|
||||
/************************ [Combat - Dragons] ***********************************
|
||||
I have a fondness for dragons - in NWN they are deprived of many abilities. Here
|
||||
are some new ones for your enjoyment! Switches and flying for ANYTHING! :-)
|
||||
************************* [Combat - Dragons] **********************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NO_WING_BUFFET, AI_COMBAT_MASTER);
|
||||
//This sets so there is no Dragon wing buffet. Readme has details of it.
|
||||
//SetAIInteger(AI_DRAGON_FREQUENCY_OF_BUFFET, 3);
|
||||
// Min. Amount of Rounds between each buffet. See readme for counter defaults. Def: 3
|
||||
//SetAIInteger(AI_DRAGON_FREQUENCY_OF_BREATH, 3);
|
||||
// Min. Amount of Rounds between each breath use. See readme for counter defaults. Def: 3
|
||||
|
||||
// Default checks for dragon flying automatic turning on of flying.
|
||||
if(GetLevelByClass(CLASS_TYPE_DRAGON) || MyPRCGetRacialType(OBJECT_SELF) == RACIAL_TYPE_DRAGON)
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_FLYING, AI_COMBAT_MASTER);
|
||||
// This turns ON combat flying. I think anything winged looks A-OK. See readme for info.
|
||||
}
|
||||
/************************ [Combat - Dragons] **********************************/
|
||||
|
||||
/************************ [Combat Other - Healers/Healing] *********************
|
||||
Healing behaviour - not specifically clerics. See readme.
|
||||
************************* [Combat Other - Healers/Healing] ********************/
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_HEAL_AT_PERCENT_NOT_AMOUNT, AI_OTHER_COMBAT_MASTER);
|
||||
// if this is set, we ignore the amount we need to be damaged, as long
|
||||
// as we are under AI_HEALING_US_PERCENT.
|
||||
//SetAIInteger(AI_HEALING_US_PERCENT, 50);
|
||||
// % of HP we need to be at until we heal us at all. Default: 50
|
||||
//SetAIInteger(AI_HEALING_ALLIES_PERCENT, 60);
|
||||
// % of HP allies would need to be at to heal them Readme = info. Default: 60
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_WILL_RAISE_ALLIES_IN_BATTLE, AI_OTHER_COMBAT_MASTER);
|
||||
// Turns on rasing dead with Resurrection/Raise dead.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_CURING, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off all healing.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_ONLY_CURE_SELF, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off ally healing.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_ONLY_RESTORE_SELF, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off ally restoring (Remove/Restoration).
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_USE_BAD_HEALING_SPELLS, AI_OTHER_COMBAT_MASTER);
|
||||
// This forces all cure spells to be used, check readme.
|
||||
//SetAIInteger(SECONDS_BETWEEN_STATUS_CHECKS, 30);
|
||||
// Seconds between when we loop everyone for bad effects like Fear/stun ETC. If not set, done each round.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GIVE_POTIONS_TO_HELP, AI_OTHER_COMBAT_MASTER);
|
||||
// ActionGiveItem standard healing potion's to allies who need them, if they possess them.
|
||||
|
||||
/************************ [Combat Other - Healers/Healing] ********************/
|
||||
|
||||
/************************ [Combat Other - Skills] ******************************
|
||||
Skills are a part of fighting - EG Taunt. These are mainly on/off switches.
|
||||
A creature will *may* use it if they are not set to "NO_" for the skill.
|
||||
************************* [Combat Other - Skills] *****************************/
|
||||
|
||||
// "NO" - This is for forcing the skill NEVER to be used by the combat AI.
|
||||
// "FORCE" - This forces it on (and to be used), except if they have no got the skill.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_USING_HEALING_KITS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_SEARCH, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_SEARCH, AI_OTHER_COMBAT_MASTER);
|
||||
// - Concentration - special notes in the readme
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_CONCENTRATION, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_CONCENTRATION, AI_OTHER_COMBAT_MASTER);
|
||||
|
||||
/************************ [Combat Other - Skills] *****************************/
|
||||
|
||||
/************************ [Combat Other - Leaders] *****************************
|
||||
Leaders/Bosses can be set to issue some orders and inspire more morale - and bring
|
||||
a lot of allies to a battle at once!
|
||||
************************* [Combat Other - Leaders] ****************************/
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER);
|
||||
// Special leader. Can issuse some orders. See readme for details.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_BOSS_MONSTER_SHOUT, AI_OTHER_COMBAT_MASTER);
|
||||
// Boss shout. 1 time use - calls all creatures in X meters (below) for battle!
|
||||
//SetAIInteger(AI_BOSS_MONSTER_SHOUT_RANGE, 60);
|
||||
// Defaults to a 60 M range. This can change it. Note: 1 toolset square = 10M.
|
||||
|
||||
/************************ [Combat Other - Leaders] ****************************/
|
||||
|
||||
/************************ [Other - Behaviour/Generic] **************************
|
||||
This is generic behaviours - alright, really it is all things that cannot
|
||||
really be categorised.
|
||||
************************* [Other - Behaviour/Generic] *************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_CLEAR_ACTIONS_BEFORE_CONVERSATION, AI_OTHER_MASTER);
|
||||
// No ClearAllActions() before BeginConversation. May keep a creature sitting.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_POLYMORPHING, AI_OTHER_MASTER);
|
||||
// This will stop all polymorphing spells feats from being used.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_CHEAT_MORE_POTIONS, AI_OTHER_MASTER);
|
||||
// If at low HP, and no potion, create one and use it.
|
||||
//SetAIConstant(AI_POLYMORPH_INTO, POLYMORPH_TYPE_WEREWOLF);
|
||||
// Polymorph to this creature when damaged (once, natural effect).
|
||||
|
||||
//AI_CreateRandomStats(-3, 3, 6);
|
||||
// Create (Effect-applied) random statistics.
|
||||
//AI_CreateRandomOther(-2, 2, -2, 2, -2, 2, -2, 2);
|
||||
// Create (Effect-applied) random HP, saves, AC.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION, AI_OTHER_MASTER);
|
||||
// This will store our spawn location, and then move back there after combat.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_DONT_SHOUT, AI_OTHER_MASTER);
|
||||
// Turns off all silent talking NPC's do to other NPC's.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_SEARCH_IF_ENEMIES_NEAR, AI_OTHER_MASTER);
|
||||
// Move randomly closer to enemies in range set below.
|
||||
//SetAIInteger(AI_SEARCH_IF_ENEMIES_NEAR_RANGE, 25);
|
||||
// This is the range creatures use, in metres.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_ONLY_ATTACK_IF_ATTACKED, AI_OTHER_MASTER);
|
||||
// One shot. We won't instantly attack a creature we see. See readme.
|
||||
|
||||
//SetAIInteger(AI_DOOR_INTELLIGENCE, 1);
|
||||
// 3 Special "What to do with Doors" settings. See readme. Good for animals.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_REST_AFTER_COMBAT, AI_OTHER_MASTER);
|
||||
// When combat is over, creature rests. Useful for replenising health.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_PLAYING_VOICE_CHAT, AI_OTHER_MASTER);
|
||||
// Stops any use of "PlayVoiceChat". Use with Custom speakstrings.
|
||||
|
||||
/*** Death settings - still under AI_OTHER_MASTER ***/
|
||||
|
||||
//AI_SetDeathResRef("Resref Here");
|
||||
// Creates a creature from the string set. Instantly destroys this creatures body on death.
|
||||
|
||||
//SetAIConstant(AI_DEATH_VISUAL_EFFECT, VFX_FNF_IMPLOSION);
|
||||
// Fires this visual effect number instantly on death. Use FNF and IMP ones.
|
||||
|
||||
//SetAIInteger(AI_CORPSE_DESTROY_TIME, 30);
|
||||
// Seconds before body finally gets destroyed. Used for Clerical Raise Dead on NPC's.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_TURN_OFF_CORPSES, AI_OTHER_MASTER);
|
||||
// This turns off the SetDestroyable() usually performed, and the above timer.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_USE_BIOWARE_LOOTING, AI_OTHER_MASTER);
|
||||
// Makes the death file use Bioware's cool SetLootable() feature when corpses would disappear.
|
||||
|
||||
/*** Lag and a few performance settings - still under AI_OTHER_MASTER ***/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_ITEMS, AI_OTHER_MASTER);
|
||||
// The creature doesn't check for, or use any items that cast spells.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
//The creature doesn't ever cast spells (and never checks them)
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_LISTENING, AI_OTHER_MASTER);
|
||||
// The creature doesn't have SetListening() set. Turns of the basic listening for shouts.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_EQUIP_MOST_DAMAGING, AI_OTHER_MASTER);
|
||||
// Uses EquipMostDamaging(), like Bioware code. No shield/second weapon equipped.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_CURING_ALLIES, AI_OTHER_MASTER);
|
||||
// This will stop checks for and curing of allies ailments.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_IGNORE_HEARTBEAT, AI_OTHER_MASTER);
|
||||
// Stops the heartbeat running (Except Pre-Heartbeat-event).
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_TARGET_NEAREST_ENEMY, AI_OTHER_MASTER);
|
||||
// Ignores targeting settings. VERY good for lag/bad AI. Attacks nearest seen enemy.
|
||||
|
||||
/************************ [Other - Behaviour/Generic] *************************/
|
||||
|
||||
/************************ [User Defined and Shouts] ****************************
|
||||
The user defined events, set up to fire here.
|
||||
- New "Start combat attack" and "End Combat Attack" events
|
||||
- New "Pre" events. Use these to optionally stop a script from firing
|
||||
under cirtain circumstances as well! (Read nw_c2_defaultd or j_ai_onuserdef)
|
||||
(User Defined Event = UDE)
|
||||
************************* [User Defined and Shouts] ***************************/
|
||||
|
||||
// This is REQUIRED if we use any Pre-events. If not there, it will default
|
||||
// to the default User Defined Event script for the default AI.
|
||||
SetCustomUDEFileName("k_ai_onuserdef");
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_EVENT, AI_UDE_MASTER); // UDE 1001
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, AI_UDE_MASTER); // UDE 1021
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_PERCIEVE_EVENT, AI_UDE_MASTER); // UDE 1002
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_PERCIEVE_PRE_EVENT, AI_UDE_MASTER); // UDE 1022
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_END_COMBAT_ROUND_EVENT, AI_UDE_MASTER); // UDE 1003
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_END_COMBAT_ROUND_PRE_EVENT, AI_UDE_MASTER); // UDE 1023
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_DIALOGUE_EVENT, AI_UDE_MASTER); // UDE 1004
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_DIALOGUE_PRE_EVENT, AI_UDE_MASTER); // UDE 1024
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ATTACK_EVENT, AI_UDE_MASTER); // UDE 1005
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ATTACK_PRE_EVENT, AI_UDE_MASTER); // UDE 1025
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_EVENT, AI_UDE_MASTER); // UDE 1006
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_PRE_EVENT, AI_UDE_MASTER); // UDE 1026
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DEATH_EVENT, AI_UDE_MASTER); // UDE 1007
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DEATH_PRE_EVENT, AI_UDE_MASTER); // UDE 1027
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DISTURBED_EVENT, AI_UDE_MASTER); // UDE 1008
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DISTURBED_PRE_EVENT, AI_UDE_MASTER); // UDE 1028
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_RESTED_EVENT, AI_UDE_MASTER); // UDE 1009
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_RESTED_PRE_EVENT, AI_UDE_MASTER); // UDE 1029
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_SPELL_CAST_AT_EVENT, AI_UDE_MASTER); // UDE 1011
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_SPELL_CAST_AT_PRE_EVENT, AI_UDE_MASTER); // UDE 1031
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_BLOCKED_EVENT, AI_UDE_MASTER); // UDE 1015
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, AI_UDE_MASTER); // UDE 1035
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_COMBAT_ACTION_EVENT, AI_UDE_MASTER); // UDE 1012
|
||||
// Fires when we have finnished all combat actions.
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_COMBAT_ACTION_PRE_EVENT, AI_UDE_MASTER); // UDE 1032
|
||||
// This fires at the start of DetermineCombatRound() *IF they can do an action*.
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_AT_1_HP, AI_UDE_MASTER); // UDE 1014
|
||||
// Fires when we are damaged, and are at 1 HP. Use for immortal-flagged creatures.
|
||||
|
||||
/*** Speakstrings - as it were, said under cirtain conditions % chance each time ***/
|
||||
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_CONVERSATION, 100, 4, "Hello there", "I hope you enjoy your stay", "Do you work here too?", "*Hic*");
|
||||
// On Conversation - see readme. Replaces BeginConversation().
|
||||
|
||||
// Morale
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_MORALE_BREAK, 100, 3, "No more!", "I'm outta here!", "Catch me if you can!");
|
||||
// Spoken at running point, if they run to a group of allies.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_CANNOT_RUN, 100, 3, "Never give up! Never surrender!", "I've no where to run, so make my day!", "RRRAAAAA!!!");
|
||||
// Spoken at running point, if they can find no ally to run to, and 4+ Intelligence. See readme
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_STUPID_RUN, "Ahhhhgggg! NO MORE! Run!!");
|
||||
// As above, when morale breaks + no ally, but they panic and run from enemy at 3 or less intelligence.
|
||||
|
||||
// Combat
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_EQUAL, 5, 4, "Come on!", "You won't win!", "We are not equals! I am better!", "Nothing will stop me!");
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_THEM_OVER_US, 5, 4, "I'll try! try! and try again!", "Tough man, are we?", "Trying out your 'skills'? Pathetic excuse!", "Nothing good will come from killing me!");
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_US_OVER_THEM, 5, 4, "My strength is mighty then yours!", "You will definatly die!", "NO chance for you!", "No mercy! Not for YOU!");
|
||||
// Spoken each DetermineCombatRound. % is /1000. See readme for Equal/Over/Under values.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_TAUNT, 100, 3, "You're going down!", "No need to think, let my blade do it for you!", "Time to meet your death!");
|
||||
// If the creature uses thier skill, taunt, on an enemy this will be said.
|
||||
|
||||
// Event-driven.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_PERCIEVE_ENEMY, 70, 6, "Stand and fight, lawbreaker!", "Don't run from the law!", "I have my orders!", "I am ready for violence!", "CHARGE!", "Time you died!");
|
||||
// This is said when they see/hear a new enemy, and start attacking them.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_DAMAGED, 20, 2, "Ouch, damn you!", "Haha! Nothing will stop me!");
|
||||
// A random value is set to speak when damaged, and may fire same time as below ones.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_PHISICALLY_ATTACKED, 20, 2, "Hah! Mear weapons won't defeat me!", "Pah! You cannot defeat me with such rubbish!");
|
||||
// This is said when an enemy attacks the creature with a melee/ranged weapon.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_HOSTILE_SPELL_CAST_AT, 20, 2, "No one spell will stop me!", "Is that all you have!?!");
|
||||
// This is said when an enemy attacks the creature with a hostile spell.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_DEATH, "Agggggg!");
|
||||
// This will ALWAYS be said, whenever the creature dies.
|
||||
|
||||
// Specific potion ones.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_WE_PASS_POTION, "Here! Catch!");
|
||||
// This will be spoken when the creature passes a potion to an ally. See readme.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_WE_GOT_POTION, "Got it!");
|
||||
// This will be spoken by the creature we pass the potion too, using AssignCommand().
|
||||
|
||||
// Leader ones
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_SEND_RUNNER, "Quickly! We need help!");
|
||||
// This will be said when the leader, if this creature, sends a runner.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_ATTACK_TARGET, "Help attack this target!");
|
||||
// When the leader thinks target X should be attacked, it will say this.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_BOSS_SHOUT, "Come my minions! To battle!");
|
||||
// This will be said when the leader, if this creature, sees an enemy and uses his "Boss Monster Shout", if turned on.
|
||||
|
||||
|
||||
/************************ [User Defined and Shouts] ***************************/
|
||||
|
||||
/************************ [Bioware: Animations/Waypoints/Treasure] *************
|
||||
All Bioware Stuff. I'd check out "x0_c2_spwn_def" for the SoU/Hordes revisions.
|
||||
************************* [Bioware: Animations/Waypoints/Treasure] ************/
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_STEALTH, NW_GENERIC_MASTER);
|
||||
// SetSpawnInCondition(NW_FLAG_SEARCH, NW_GENERIC_MASTER);
|
||||
// Uses said skill while WalkWaypoints()
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING, NW_GENERIC_MASTER);
|
||||
// Separate the NPC's waypoints into day & night. See comment in "nw_i0_generic" for use.
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
// This will cause an NPC to use common animations it possesses,
|
||||
// and use social ones to any other nearby friendly NPCs.
|
||||
// SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
// Same as above, except NPC will wander randomly around the area.
|
||||
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
// Interacts with placeables + More civilized actions. See Readme.
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// Will use random voicechats during animations, if Civilized
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
// Will move around the area a bit more, if using Immobile Animations. See readme.
|
||||
|
||||
// Treasure generating.
|
||||
//CTG_GenerateNPCTreasure();
|
||||
// SoU. Requires "x0_i0_treasure" to be uncommented. See readme.
|
||||
//GenerateNPCTreasure();
|
||||
// Default NwN. Requires "nw_o2_coninclude" to be uncommented. See readme.
|
||||
|
||||
/************************ [Bioware: Animations/Waypoints/Treasure] ************/
|
||||
|
||||
// AI Behaviour. DO NOT CHANGE! DO NOT CHANGE!!!
|
||||
AI_SetUpEndOfSpawn();
|
||||
// This MUST be called. It fires these events:
|
||||
// SetUpSpells, SetUpSkillToUse, SetListeningPatterns, SetWeapons, AdvancedAuras.
|
||||
// These MUST be called! the AI might fail to work correctly if they don't fire!
|
||||
|
||||
/************************ [User] ***********************************************
|
||||
This is the ONLY place you should add user things, on spawn, such as
|
||||
visual effects or anything, as it is after SetUpEndOfSpawn. By default, this
|
||||
does have encounter animations on. This is here, so is easily changed :-D
|
||||
|
||||
Be careful otherwise.
|
||||
|
||||
Notes:
|
||||
- SetListening is already set to TRUE, unless AI_FLAG_OTHER_LAG_NO_LISTENING is on.
|
||||
- SetListenPattern's are set from 0 to 7.
|
||||
- You can use the wrappers AI_SpawnInInstantVisual and AI_SpawnInPermamentVisual
|
||||
for visual effects (Instant/Permament as appropriate).
|
||||
************************* [User] **********************************************/
|
||||
// Example (and default) of user addition:
|
||||
// - If we are from an encounter, set mobile (move around) animations.
|
||||
if(GetIsEncounterCreature())
|
||||
{
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
}
|
||||
// Leave this in if you use the variable for creature attacks, as for golems. Bioware's code.
|
||||
int nNumber = GetLocalInt(OBJECT_SELF, "CREATURE_VAR_NUMBER_OF_ATTACKS");
|
||||
if(nNumber > 0)
|
||||
{
|
||||
SetBaseAttackBonus(nNumber);
|
||||
}
|
||||
|
||||
// If we are a ranger or paladin class, do not cast spells. This can be
|
||||
// manually removed if wished. To get the spells they have working correctly,
|
||||
// remove this, and use Monster Abilties instead of thier normal class spells.
|
||||
// if(GetLevelByClass(CLASS_TYPE_RANGER) >= 1 || GetLevelByClass(CLASS_TYPE_PALADIN) >= 1)
|
||||
// {
|
||||
// SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
// }
|
||||
|
||||
/************************ [User] **********************************************/
|
||||
|
||||
// Note: You shouldn't really remove this, even if they have no waypoints.
|
||||
DelayCommand(2.0, SpawnWalkWayPoints());
|
||||
// Delayed walk waypoints, as to not upset instant combat spawning.
|
||||
// This will also check if to change to day/night posts during the walking, no heartbeats.
|
||||
}
|
@@ -1,493 +0,0 @@
|
||||
/*/////////////////////// [On Spell Cast At] ///////////////////////////////////
|
||||
Filename: j_ai_onspellcast or nw_c2_defaultb
|
||||
///////////////////////// [On Spell Cast At] ///////////////////////////////////
|
||||
What does this do? Well...
|
||||
- Any AOE spell effects are set in a timer, so we can react to them right
|
||||
- Reacts to hostile casters, or allies in combat
|
||||
|
||||
And the normal attack :-)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added special AOE checks.
|
||||
- Hide checks.
|
||||
1.4 - Added more silent shouts. Edited the formatting. Moved a few things around.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is fired when EventSpellCastAt(object oCaster, int nSpell, int bHarmful=TRUE)
|
||||
is signaled on the creature.
|
||||
|
||||
GetLastSpellCaster() = oCaster (Door, Placeable, Creature who cast it)
|
||||
GetLastSpell() = nSpell (The spell cast at us)
|
||||
GetLastSpellHarmful()= bHarmful (If it is harmful!)
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastSpellCaster, GetLastSpellHarmful GetLastSpell()
|
||||
///////////////////////// [On Spell Cast At] /////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
// Sets a local timer if the spell is an AOE one
|
||||
void SetAOESpell(int nSpellCast, object oCaster);
|
||||
// Gets the nearest AOE cast by oCaster, of sTag.
|
||||
object GetNearestAOECastBy(string sTag, object oCaster);
|
||||
// Gets the amount of protections we have - IE globes
|
||||
int GetOurSpellLevelImmunity();
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-spell cast at-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_SPELL_CAST_AT_PRE_EVENT, EVENT_SPELL_CAST_AT_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
object oCaster = GetLastSpellCaster();
|
||||
int bHarmful = GetLastSpellHarmful();
|
||||
int nSpellCast = GetLastSpell();
|
||||
object oAttackerOfCaster;
|
||||
|
||||
// If harmful, we set the spell to a timer, if an AOE one.
|
||||
if(bHarmful && GetIsObjectValid(oCaster))
|
||||
{
|
||||
// Might set AOE spell to cast.
|
||||
SetAOESpell(nSpellCast, oCaster);
|
||||
}
|
||||
// If not a creature, probably an AOE or trap.
|
||||
if(GetObjectType(oCaster) != OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// 67: "[Spell] Caster isn't a creature! May look for target [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(67, oCaster);
|
||||
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// Attack anyone else around
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Determine Combat Round
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
// If a friend, or dead, or a DM, or invalid, or self, we ignore them.
|
||||
else if(!GetIgnoreNoFriend(oCaster) && oCaster != OBJECT_SELF)
|
||||
{
|
||||
// 1.3 changes here:
|
||||
// - We do NOT need to know if it is hostile or not, except if it is hostile
|
||||
// and they are not our faction! We do, however, use bHarmful for speakstrings.
|
||||
|
||||
// If harmful, we attack anyone! (and if is enemy)
|
||||
// 1.4: Faction equal check in GetIgnoreNoFriend()
|
||||
if(bHarmful || GetIsEnemy(oCaster))
|
||||
{
|
||||
// Spawn in condition hostile thingy
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oCaster))
|
||||
{
|
||||
AdjustReputation(oCaster, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
if(bHarmful)
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Hostile spell speaksting, if set.
|
||||
SpeakArrayString(AI_TALK_ON_HOSTILE_SPELL_CAST_AT);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn of hiding check
|
||||
TurnOffHiding(oCaster);
|
||||
|
||||
// We attack
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// 68: "[Spell:Enemy/Hostile] Not in combat. Attacking: [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(68, oCaster);
|
||||
DetermineCombatRound(oCaster);
|
||||
}
|
||||
|
||||
// Shout to allies to attack the enemy who attacked me, got via. Last Hostile Actor.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
// Else, was neutral perhaps. Don't attack them anyway.
|
||||
else
|
||||
{
|
||||
// 69: "[Spell] (ally). Not in combat. May Attack/Move [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(69, oCaster);
|
||||
|
||||
// Set special action to investigate - as if this event was triggered
|
||||
// by I_WAS_ATTACKED.
|
||||
|
||||
// If we are already attacking, we do not move
|
||||
if(CannotPerformCombatRound())
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We react as if the caster, a neutral, called for help ala
|
||||
// I_WAS_ATTACKED (they might not have, might just be
|
||||
// preperation for something), but normally, this is a neutral
|
||||
// casting a spell. Do not respond to PC's.
|
||||
if(!GetIsPC(oCaster))
|
||||
{
|
||||
IWasAttackedResponse(oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If they are not a faction equal, and valid, we help them.
|
||||
else if(GetIsObjectValid(oCaster) && GetFactionEqual(oCaster))
|
||||
{
|
||||
IWasAttackedResponse(oCaster);
|
||||
}
|
||||
// Fire End-spell cast at-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_SPELL_CAST_AT_EVENT, EVENT_SPELL_CAST_AT_EVENT);
|
||||
}
|
||||
|
||||
// Sets a local timer if the spell is an AOE one
|
||||
void SetAOESpell(int nSpellCast, object oCaster)
|
||||
{
|
||||
// Check it is one we can check
|
||||
int bStop = TRUE;
|
||||
switch(nSpellCast)
|
||||
{
|
||||
case SPELL_ACID_FOG:
|
||||
case SPELL_MIND_FOG:
|
||||
case SPELL_STORM_OF_VENGEANCE:
|
||||
case SPELL_GREASE:
|
||||
case SPELL_CREEPING_DOOM:
|
||||
case SPELL_SILENCE:
|
||||
case SPELL_BLADE_BARRIER:
|
||||
case SPELL_CLOUDKILL:
|
||||
case SPELL_STINKING_CLOUD:
|
||||
case SPELL_WALL_OF_FIRE:
|
||||
case SPELL_INCENDIARY_CLOUD:
|
||||
case SPELL_ENTANGLE:
|
||||
case SPELL_EVARDS_BLACK_TENTACLES:
|
||||
case SPELL_CLOUD_OF_BEWILDERMENT:
|
||||
case SPELL_STONEHOLD:
|
||||
case SPELL_VINE_MINE:
|
||||
case SPELL_SPIKE_GROWTH:
|
||||
case SPELL_VINE_MINE_HAMPER_MOVEMENT:
|
||||
case SPELL_VINE_MINE_ENTANGLE:
|
||||
{
|
||||
bStop = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Check immune level
|
||||
int nImmuneLevel = GetOurSpellLevelImmunity();
|
||||
if(nImmuneLevel >= 9)
|
||||
{
|
||||
bStop = TRUE;
|
||||
}
|
||||
// Check
|
||||
if(bStop == TRUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// We do use intelligence here...
|
||||
int nAIInt = GetBoundriedAIInteger(AI_INTELLIGENCE);
|
||||
int bIgnoreSaves;
|
||||
int bIgnoreImmunities;
|
||||
object oAOE;
|
||||
|
||||
// If it is low, we ignore all things that we could ignore with it...
|
||||
if(nAIInt <= 3)
|
||||
{
|
||||
bIgnoreSaves = TRUE;
|
||||
bIgnoreImmunities = TRUE;
|
||||
}
|
||||
// Average ignores saves
|
||||
else if(nAIInt <= 7)
|
||||
{
|
||||
bIgnoreSaves = TRUE;
|
||||
bIgnoreImmunities = FALSE;
|
||||
}
|
||||
// Else, we do both.
|
||||
else
|
||||
{
|
||||
bIgnoreSaves = FALSE;
|
||||
bIgnoreImmunities = FALSE;
|
||||
}
|
||||
|
||||
int bSetAOE = FALSE;// TRUE means set to timer
|
||||
int nSaveDC = 11;
|
||||
|
||||
// Get the caster DC, the most out of WIS, INT or CHA...
|
||||
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE, oCaster);
|
||||
int nWis = GetAbilityModifier(ABILITY_WISDOM, oCaster);
|
||||
int nCha = GetAbilityModifier(ABILITY_CHARISMA, oCaster);
|
||||
|
||||
if(nInt > nWis && nInt > nCha)
|
||||
{
|
||||
nSaveDC += nInt;
|
||||
}
|
||||
else if(nWis > nCha)
|
||||
{
|
||||
nSaveDC += nWis;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSaveDC += nCha;
|
||||
}
|
||||
// Note:
|
||||
// - No reaction type/friendly checks. Signal Event is only fired if the
|
||||
// spell WILL pierce any PvP/Friendly/Area settings
|
||||
|
||||
// We check immunities here, please note...
|
||||
switch(nSpellCast)
|
||||
{
|
||||
// First: IS GetIsReactionTypeHostile ones.
|
||||
case SPELL_EVARDS_BLACK_TENTACLES:
|
||||
// Fortitude save, but if we are immune to the hits, its impossible to hurt us
|
||||
{
|
||||
// If save immune OR AC immune, we ignore this.
|
||||
if(25 >= GetAC(OBJECT_SELF) && nImmuneLevel < 4 &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 2) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Nearest string of tag
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_EVARDS_BLACK_TENTACLES, oCaster);
|
||||
}
|
||||
}
|
||||
case SPELL_SPIKE_GROWTH:
|
||||
case SPELL_VINE_MINE_HAMPER_MOVEMENT:
|
||||
// d4 damage. LOTS of speed loss.
|
||||
// Reflex save, or immunity, would stop the speed
|
||||
{
|
||||
if(nImmuneLevel < 3 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_MOVEMENT_SPEED_DECREASE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 5) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Both use ENTANGLE AOE's
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_ENTANGLE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_ENTANGLE:
|
||||
case SPELL_VINE_MINE_ENTANGLE:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_ENTANGLE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 4) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Both use ENTANGLE AOE's
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_ENTANGLE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_WEB:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_ENTANGLE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 4) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Web AOE
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WEB, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Fort save
|
||||
case SPELL_STINKING_CLOUD:
|
||||
{
|
||||
if(nImmuneLevel < 3 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_POISON) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_DAZED) || bIgnoreImmunities) &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 6) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Stinking cloud persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGSTINK, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Fort save
|
||||
case SPELL_CLOUD_OF_BEWILDERMENT:
|
||||
{
|
||||
if(nImmuneLevel < 2 &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 7) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Bewilderment cloud persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGBEWILDERMENT, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: Mind save is the effect.
|
||||
case SPELL_STONEHOLD:
|
||||
{
|
||||
if(nImmuneLevel < 6 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_MIND_SPELLS) || bIgnoreImmunities) &&
|
||||
((GetWillSavingThrow(OBJECT_SELF) < nSaveDC + 7) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Stonehold persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_STONEHOLD, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: EFFECT_TYPE_SAVING_THROW_DECREASE is the effect.
|
||||
case SPELL_MIND_FOG:
|
||||
{
|
||||
if(nImmuneLevel < 5 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_SAVING_THROW_DECREASE) || bIgnoreImmunities) &&
|
||||
((GetWillSavingThrow(OBJECT_SELF) < nSaveDC + 6) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Mind fog
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGMIND, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: Feats, knockdown
|
||||
case SPELL_GREASE:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_KNOCKDOWN) || bIgnoreImmunities) &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE, OBJECT_SELF) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 2) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Grease
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_GREASE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// All other ReactionType ones. Some have different saves though!
|
||||
case SPELL_BLADE_BARRIER: // Reflex
|
||||
case SPELL_INCENDIARY_CLOUD:// reflex
|
||||
case SPELL_WALL_OF_FIRE:// Reflex
|
||||
{
|
||||
if(nImmuneLevel < 6 &&
|
||||
(((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 6) &&
|
||||
!GetHasFeat(FEAT_IMPROVED_EVASION) &&
|
||||
!GetHasFeat(FEAT_EVASION)) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
if(nSpellCast == SPELL_BLADE_BARRIER)
|
||||
{
|
||||
// BB
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WALLBLADE, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_INCENDIARY_CLOUD)
|
||||
{
|
||||
// Fog of fire
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGFIRE, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_WALL_OF_FIRE)
|
||||
{
|
||||
// Wall of fire
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WALLFIRE, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_ACID_FOG: // Fort: Half. No check, always damages.
|
||||
case SPELL_CLOUDKILL:// No save!
|
||||
case SPELL_CREEPING_DOOM: // No save!
|
||||
{
|
||||
if(nImmuneLevel < 6)
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
if(nSpellCast == SPELL_ACID_FOG)
|
||||
{
|
||||
// Acid fog
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGACID, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_CLOUDKILL)
|
||||
{
|
||||
// Cloud Kill
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGKILL, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_CREEPING_DOOM)
|
||||
{
|
||||
// Creeping doom
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_CREEPING_DOOM, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Storm - because the AI likes it, we stay in it if it is ours :-)
|
||||
case SPELL_STORM_OF_VENGEANCE: // Reflex partial. No check, always damages.
|
||||
{
|
||||
if(oCaster != OBJECT_SELF && nImmuneLevel < 9)
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Storm of vengance
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_STORM, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bSetAOE)
|
||||
{
|
||||
if(!GetLocalTimer(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast)))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast), 18.0);
|
||||
// Set nearest AOE
|
||||
if(GetIsObjectValid(oAOE))
|
||||
{
|
||||
// Set nearest AOE of this spell to the local
|
||||
object oNearest = GetAIObject(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast));
|
||||
if(GetDistanceToObject(oAOE) < GetDistanceToObject(oNearest) ||
|
||||
!GetIsObjectValid(oNearest))
|
||||
{
|
||||
SetAIObject(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast), oAOE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Gets the nearest AOE cast by oCaster, of sTag.
|
||||
object GetNearestAOECastBy(string sTag, object oCaster)
|
||||
{
|
||||
int nCnt = 1;
|
||||
object oAOE = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||||
object oReturn = OBJECT_INVALID;
|
||||
// Loop
|
||||
while(GetIsObjectValid(oAOE) && !GetIsObjectValid(oReturn))
|
||||
{
|
||||
// Check creator
|
||||
if(GetAreaOfEffectCreator(oAOE) == oCaster)
|
||||
{
|
||||
oReturn = oAOE;
|
||||
}
|
||||
nCnt++;
|
||||
oAOE = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||||
}
|
||||
return oReturn;
|
||||
}
|
||||
|
||||
// Gets the amount of protections we have - IE globes
|
||||
int GetOurSpellLevelImmunity()
|
||||
{
|
||||
int nNatural = GetLocalInt(OBJECT_SELF, AI_SPELL_IMMUNE_LEVEL);
|
||||
// Stop here, if natural is over 4
|
||||
if(nNatural > 4) return nNatural;
|
||||
|
||||
// Big globe affects 4 or lower spells
|
||||
if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY, OBJECT_SELF) || nNatural >= 4)
|
||||
return 4;
|
||||
// Minor globe is 3 or under
|
||||
if(GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY, OBJECT_SELF) ||
|
||||
// Shadow con version
|
||||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE, OBJECT_SELF) ||
|
||||
nNatural >= 3)
|
||||
return 3;
|
||||
// 2 and under is ethereal visage.
|
||||
if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE, OBJECT_SELF) || nNatural >= 2)
|
||||
return 2;
|
||||
// Ghostly Visarge affects 1 or 0 level spells, and any spell immunity.
|
||||
if(GetHasSpellEffect(SPELL_GHOSTLY_VISAGE, OBJECT_SELF) || nNatural >= 1 ||
|
||||
// Or shadow con version.
|
||||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE, OBJECT_SELF))
|
||||
return 1;
|
||||
// Return nNatural, which is 0-9
|
||||
return FALSE;
|
||||
}
|
@@ -1,326 +0,0 @@
|
||||
/*/////////////////////// [On User Defined] ////////////////////////////////////
|
||||
Filename: J_AI_OnUserDef or nw_c2_defaultd
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
1.4 Adds proper Pre-event functionality. Use this to make sure you keep the
|
||||
AI working, but making small additions using this event.
|
||||
|
||||
Can be deleted to save space if you want :-)
|
||||
|
||||
How to use user defined events (brief):
|
||||
|
||||
There are a set of optional Spawn In values you can set within the spawn file.
|
||||
If you set one of the Events to fire, it will activate this script. Then,
|
||||
under the correct choice (EG I choose the Pre-Heartbeat event, then I
|
||||
uncomment the line "SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, AI_UDE_MASTER);"
|
||||
and find, in this file, the section with EVENT_HEARTBEAT_PRE_EVENT above it).
|
||||
add in whatever to do.
|
||||
|
||||
With my Pre-heartbeat example, if I wanted it to check for a PC, then
|
||||
check for a combat dummy, and attack it, I'd add this between the brackets:
|
||||
|
||||
// Code:
|
||||
|
||||
// Not in combat, of course!
|
||||
if(!GetIsInCombat())
|
||||
{
|
||||
// Function in j_inc_npc_attack to get nearest PC
|
||||
object oPC = GetNearestPCCreature();
|
||||
// Why check for a PC? Well, it saves memory
|
||||
if(GetIsObjectValid(oPC) && GetDistanceToObject(oPC) <= 40.0)
|
||||
{
|
||||
object oDummy = GetNearestObjectByTag("DUMMY");
|
||||
if(GetIsObjectValid(oDummy))
|
||||
{
|
||||
ClearAllActions();
|
||||
ActionAttack(oDummy);
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_HEARTBEAT_PRE_EVENT);
|
||||
// Stop rest of script
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End code
|
||||
|
||||
Simple, no?
|
||||
|
||||
You can delete sections you don't need, and is recommended as long as you know
|
||||
how to use User Defined events.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in with some documentation
|
||||
1.4 - Changed Pre-events. Now, it uses Execute Script. Will need to set
|
||||
a special string on the creature to now what script to fire.
|
||||
- It means they work correctly, however!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: Dependant on event. See seperate event scripts.
|
||||
///////////////////////// [On User Defined] //////////////////////////////////*/
|
||||
|
||||
// This contains a lot of useful things.
|
||||
// - Combat starting
|
||||
// - Constant values
|
||||
// - Get/Set spawn in values.
|
||||
#include "J_INC_OTHER_AI"
|
||||
// This contains some useful things to get NPC's to attack and so on.
|
||||
#include "J_INC_NPC_ATTACK"
|
||||
|
||||
/************************ [UDE Values] *****************************************
|
||||
These are uneeded, but here for reference. Use the constants in the file
|
||||
"j_inc_constants" like "EVENT_HEARTBEAT_PRE_EVENT" which is classed as 1021.
|
||||
* The normal death event might not fire before the creature has vanished.
|
||||
Use the Pre-event (but with no stopping the death event) if you want a special
|
||||
death event to happen.
|
||||
|
||||
Name Normal-End event - Pre-Event
|
||||
Heartbeat Event 1001 1021
|
||||
Percieve Event 1002 1022
|
||||
Combat Round Event 1003 1023
|
||||
Dialog Event 1004 1024
|
||||
Attack Event 1005 1025
|
||||
Damaged Event 1006 1026
|
||||
Death Event 1007 1027
|
||||
Disturbed Event 1008 1028
|
||||
Rested Event 1009 1029
|
||||
Spell Cast At Event 1011 1031
|
||||
Combat Action Event 1012 1032
|
||||
Damaged 1HP Event 1014 -
|
||||
Blocked Event 1015 1035
|
||||
************************* [UDE Values] ****************************************/
|
||||
|
||||
void main()
|
||||
{
|
||||
// Get the user defined number.
|
||||
// * NOTE: YOU MUST USE AI_GetUDENumber(), not GetUserDefinedEventNumber()!
|
||||
int nEvent = AI_GetUDENumber();
|
||||
|
||||
// Events.
|
||||
switch(nEvent)
|
||||
{
|
||||
// Event Heartbeat
|
||||
// Arguments: Basically, none. Nothing activates this script. Fires every 6 seconds.
|
||||
case EVENT_HEARTBEAT_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Heartbeat file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_HEARTBEAT_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_HEARTBEAT_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Heartbeat file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Percieve
|
||||
// Arguments: GetLastPerceived, GetLastPerceptionSeen, GetLastPerceptionHeard,
|
||||
// GetLastPerceptionVanished, GetLastPerceptionInaudible.
|
||||
case EVENT_PERCIEVE_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Percieve file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_PERCIEVE_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_PERCIEVE_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Percieve file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Combat Round End
|
||||
// Arguments: GetAttackTarget, GetLastHostileActor, GetAttemptedAttackTarget,
|
||||
// GetAttemptedSpellTarget (Or these are useful at least!)
|
||||
case EVENT_END_COMBAT_ROUND_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Combat Round End file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_END_COMBAT_ROUND_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_END_COMBAT_ROUND_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Combat Round End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Dialogue
|
||||
// Arguments: GetListenPatternNumber, GetLastSpeaker, TestStringAgainstPattern,
|
||||
// GetMatchedSubstring (I think),
|
||||
case EVENT_ON_DIALOGUE_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the dialog file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ON_DIALOGUE_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ON_DIALOGUE_EVENT:
|
||||
{
|
||||
// This fires after the rest of the dialog file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Attacked
|
||||
// Arguments: GetLastAttacker, GetLastWeaponUsed, GetLastAttackMode,
|
||||
// GetLastAttackType
|
||||
case EVENT_ATTACK_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Attacked file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ATTACK_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ATTACK_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Attacked file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Damaged
|
||||
// Arguments: GetTotalDamageDealt, GetLastDamager, GetCurrentHitPoints
|
||||
// (and max), GetDamageDealtByType
|
||||
case EVENT_DAMAGED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the damaged file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DAMAGED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DAMAGED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the damaged file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Death
|
||||
// Arguments: GetLastKiller
|
||||
case EVENT_DEATH_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the death file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DEATH_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DEATH_EVENT:
|
||||
{
|
||||
// This fires after the rest of the death file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Distrubed
|
||||
// Arguments: GetInventoryDisturbItem, GetLastDisturbed,
|
||||
// GetInventoryDisturbType (should always be stolen :-( ).
|
||||
case EVENT_DISTURBED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the disturbed file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DISTURBED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DISTURBED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the disturbed file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Rested
|
||||
// Arguments: None
|
||||
// Note: Not sure if this fires at the end of rest event, but the actual
|
||||
// duration of the rest is 0, so you never "see" it.
|
||||
case EVENT_RESTED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the rested file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_RESTED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_RESTED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the rested file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Spell cast at
|
||||
// Arguments: GetLastSpellCaster, GetLastSpellHarmful GetLastSpell()
|
||||
case EVENT_SPELL_CAST_AT_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Spell Cast At file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_SPELL_CAST_AT_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_SPELL_CAST_AT_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Spell Cast At End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Blocked
|
||||
// Arguements: GetBlockingDoor, GetIsDoorActionPossible, GetLocked,
|
||||
// GetLockKeyRequired, GetLockKeyTag, GetLockUnlockDC, GetPlotFlag.
|
||||
case EVENT_ON_BLOCKED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the on blocked file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ON_BLOCKED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ON_BLOCKED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the on blocked file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Combat Action
|
||||
// Arguments: GetAttackTarget(), and lots of others.
|
||||
// Note: Fires when DetermineCombatRound runs to perform an action.
|
||||
case EVENT_COMBAT_ACTION_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Determine Combat Round call does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_COMBAT_ACTION_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_COMBAT_ACTION_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Determine Combat Round call does
|
||||
// Calling ClearAllActions should stop any actions added in the call.
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Damaged at 1 HP.
|
||||
// Arguments: None really.
|
||||
// Note: Fires OnDamaged, when we have exactly 1HP. Use for Immortal Creatures.
|
||||
case EVENT_DAMAGED_AT_1_HP:
|
||||
{
|
||||
// This fires after the rest of the On Combat Round End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// End all in-built events. Add more in here, if you wish.
|
||||
}
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
/*/////////////////////// [Set Weapons] ////////////////////////////////////////
|
||||
Filename: J_AI_SetWeapons
|
||||
///////////////////////// [Set Weapons] ////////////////////////////////////////
|
||||
Executed to re-set any weapons, or set them at spawn, using ExecuteScript.
|
||||
|
||||
It isn't included in the generic AI or onspawn to try and speed it up a little
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added to a new file, removed from spawn include.
|
||||
1.4 - Nothing changed here. Include file might have changed however.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
It can be easily re-added to the spawn include, however, the generic AI calls
|
||||
it so little, that it may well be useful to keep a seperate file anyway.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: RESET_HEALING_KITS
|
||||
///////////////////////// [Set Weapons] //////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_SETWEAPONS"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(GetAIInteger(RESET_HEALING_KITS))
|
||||
{
|
||||
ResetHealingKits(OBJECT_SELF);
|
||||
DeleteAIInteger(RESET_HEALING_KITS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set weapons if not
|
||||
SetWeapons(OBJECT_SELF);
|
||||
}
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
/*/////////////////////// [Resume Waypoint Walking] ////////////////////////////
|
||||
Filename: j_ai_walkwaypoin
|
||||
///////////////////////// [Resume Waypoint Walking] ////////////////////////////
|
||||
Executed On Spawn, and from the end of combat, to resume walking
|
||||
|
||||
Notes:
|
||||
Needed my own file as to execute and be sure it exsisted. This means
|
||||
the Non-override version will not use 2 different waypoint files most of the
|
||||
time.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.0 - Added
|
||||
1.3 - Changed to SoU waypoints. fired from End of Spawn and heartbeat.
|
||||
It also returns to start location if set.
|
||||
1.4 -
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Might change to SoU waypoints, this, at the moment, will just
|
||||
walk normal waypoints.
|
||||
|
||||
GEORG:
|
||||
|
||||
Short rundown on WalkWaypoints
|
||||
|
||||
You can create a set of waypoints with their tag constructed like this:
|
||||
|
||||
WP_[TAG]_XX where [TAG] is the exact, case sensitive tag of the creature
|
||||
you want to walk these waypoints and XX the number of the waypoint.
|
||||
|
||||
Numbers must be ascending without a gap and must always contain 2 digits.
|
||||
|
||||
If your creature's tag is MY_Monster, the tags would be
|
||||
WP_MY_Monster_01, WP_MY_Monster_02, ...
|
||||
|
||||
You can auto-create a first waypoint in the toolset by rightclicking on a
|
||||
creature and selecting the "Create Waypoint" option. You can create
|
||||
subsequent waypoints by rightclicking on the ground while the creature is
|
||||
still selected and choosing "Create Waypoint".
|
||||
|
||||
If you want to make your creature have a different patrol route at night,
|
||||
you can create a different set of WayPoints prefixed with WN_ (i.e.
|
||||
WN_MY_Monster_01, WN_MY_Monster_02, ...).
|
||||
|
||||
You can also define so called POST waypoints for creatures that do not have
|
||||
a route of waypoints but you want to return to their position after a combat
|
||||
(i.e. Guards at a gate). This can be done by creating a single Waypoint with
|
||||
the tag POST_[TAG] for day and NIGHT_[TAG] for night posts. Creatures will
|
||||
automaticall switch between those posts when day changes to night and vice
|
||||
versa.
|
||||
|
||||
Waypoints can be between areas and creatures will move there, if you set a
|
||||
global integer variable called X2_SWITCH_CROSSAREA_WALKWAYPOINTS on your
|
||||
module to 1.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: WAYPOINT_RUN, WAYPOINT_PAUSE are set On Spawn to remember
|
||||
the pause/run actions.
|
||||
///////////////////////// [Resume Waypoint Walking] //////////////////////////*/
|
||||
|
||||
#include "NW_I0_GENERIC"
|
||||
#include "J_INC_DEBUG"
|
||||
|
||||
const string WAYPOINT_RUN = "WAYPOINT_RUN";
|
||||
const string WAYPOINT_PAUSE = "WAYPOINT_PAUSE";
|
||||
const int AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION = 0x00020000;
|
||||
const string AI_OTHER_MASTER = "AI_OTHER_MASTER";
|
||||
const string AI_LOCATION = "AI_LOCATION";
|
||||
const string AI_RETURN_TO_POINT = "AI_RETURN_TO_POINT";
|
||||
|
||||
|
||||
// For return to.
|
||||
int AI_GetSpawnInCondition(int nCondition, string sName, object oTarget = OBJECT_SELF);
|
||||
|
||||
void main()
|
||||
{
|
||||
// FIRST, if we are meant to move back to the start location, do it.
|
||||
if(AI_GetSpawnInCondition(AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION, AI_OTHER_MASTER))
|
||||
{
|
||||
location lReturnPoint = GetLocalLocation(OBJECT_SELF, AI_LOCATION + AI_RETURN_TO_POINT);
|
||||
object oReturnArea = GetAreaFromLocation(lReturnPoint);
|
||||
if(GetIsObjectValid(oReturnArea))
|
||||
{
|
||||
if((GetArea(OBJECT_SELF) == oReturnArea &&
|
||||
GetDistanceBetweenLocations(GetLocation(OBJECT_SELF), lReturnPoint) > 3.0) ||
|
||||
GetArea(OBJECT_SELF) != oReturnArea)
|
||||
{
|
||||
// 77: "[Waypoints] Returning to spawn location. [Area] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(77, GetAreaFromLocation(lReturnPoint));
|
||||
ActionForceMoveToLocation(lReturnPoint);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Use on-spawn run/pauses.
|
||||
WalkWayPoints(GetLocalInt(OBJECT_SELF, WAYPOINT_RUN), GetLocalFloat(OBJECT_SELF, WAYPOINT_PAUSE));
|
||||
}
|
||||
|
||||
int AI_GetSpawnInCondition(int nCondition, string sName, object oTarget)
|
||||
{
|
||||
return (GetLocalInt(oTarget, sName) & nCondition);
|
||||
}
|
@@ -1,109 +0,0 @@
|
||||
/*/////////////////////// [Ability - Dragon Wing Buffet] ///////////////////////
|
||||
Filename: J_AI_WingBuffet
|
||||
///////////////////////// [Ability - Dragon Wing Buffet] ///////////////////////
|
||||
"The dragon will launch into the air, knockdown
|
||||
all opponents who fail a Reflex Save and then
|
||||
land on one of those opponents doing damage
|
||||
up to a maximum of the Dragons HD + 10."
|
||||
|
||||
This is modified by Jasperre for use by Dragons in the AI. Instead of
|
||||
crashing, using effect appear, disspear, it just uses effect appear.
|
||||
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Made the "action attack" work better, getting the nearest
|
||||
seen and heard instead of the nearest (which may not be seen or heard).
|
||||
- Added in random damage for each target!
|
||||
- Faction Equal as well as GetIsFriend check.
|
||||
1.4 - Cleaned it up a bit, to be more readable.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Executed via. ExecuteScript from the AI file, it is seperate because it is
|
||||
almost a new AI ability.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Ability - Dragon Wing Buffet] /////////////////////*/
|
||||
|
||||
void main()
|
||||
{
|
||||
// Stop the creature's actions.
|
||||
ClearAllActions();// To rid errors.
|
||||
|
||||
// Declare major variables
|
||||
int nDamage;
|
||||
int nDC = GetHitDice(OBJECT_SELF);
|
||||
location lSelf = GetLocation(OBJECT_SELF);
|
||||
string sMessage = GetName(OBJECT_SELF) + " is using its wing buffet against you!";
|
||||
location lTarget;
|
||||
float fRandomKnockdown;
|
||||
// Use a delay based on range,
|
||||
float fDelay;
|
||||
|
||||
// Declare effects
|
||||
effect eDam;
|
||||
effect eKnockDown = EffectKnockdown();
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_PULSE_WIND);
|
||||
|
||||
// Pulse of wind applied...
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lSelf);
|
||||
|
||||
// Get first target in spell area
|
||||
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lSelf);
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
// Get thier location (for visual) and the delay.
|
||||
lTarget = GetLocation(oTarget);
|
||||
fDelay = GetDistanceToObject(oTarget)/20.0;
|
||||
|
||||
// Wind pulse to all
|
||||
DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTarget));
|
||||
|
||||
// Do not effect allies.
|
||||
if(!GetIsFriend(oTarget) && !GetFactionEqual(oTarget))
|
||||
{
|
||||
// Send a message about the wing buffet (allies do not see this)
|
||||
SendMessageToPC(oTarget, sMessage);
|
||||
|
||||
// Huge creatures (IE: Dragon size) are not affected.
|
||||
if(GetCreatureSize(oTarget) != CREATURE_SIZE_HUGE)
|
||||
{
|
||||
// A standard (not spell) reflex save negates the damage and knockdown
|
||||
if(!ReflexSave(oTarget, nDC))
|
||||
{
|
||||
// Randomise damage. (nDC = Hit dice)
|
||||
nDamage = Random(nDC) + 11;
|
||||
|
||||
// Define the damage
|
||||
eDam = EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING);
|
||||
|
||||
// Randomise knockdown duration, to minimum of 6.0 (1.0/2 = 0.5. + 5.5 = 6.0)
|
||||
fRandomKnockdown = 5.5 + ((IntToFloat(Random(30)) + 1.0)/10.0);
|
||||
|
||||
// We'll have a windy effect..depending on range
|
||||
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
||||
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKnockDown, oTarget, fRandomKnockdown));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get next target in spell area
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lSelf);
|
||||
}
|
||||
|
||||
// Do a great flapping wings on land effect.
|
||||
effect eAppear = EffectAppear();
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eAppear, OBJECT_SELF);
|
||||
|
||||
// Attack the nearest seen (so not to stand there for 6 seconds, but get
|
||||
// back in the action!).
|
||||
object oNearest = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(GetIsObjectValid(oNearest))
|
||||
{
|
||||
DelayCommand(1.0, ActionAttack(oNearest));
|
||||
}
|
||||
else
|
||||
{
|
||||
oNearest = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(GetIsObjectValid(oNearest))
|
||||
{
|
||||
DelayCommand(1.0, ActionAttack(oNearest));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,133 +0,0 @@
|
||||
/*/////////////////////// [Ability - Dragon Flying] ////////////////////////////
|
||||
Filename: J_AI_WingFlying
|
||||
///////////////////////// [Ability - Dragon Flying] ////////////////////////////
|
||||
Hey, a dragon can fly (if we are set to, mind you!) this is executed from
|
||||
the default AI, using local objects to "fly" to, a duration based on the
|
||||
distance between the 2 places.
|
||||
|
||||
When we fly down, we apply knockdown to the targets in the area's affected
|
||||
if not huge size, like wing buffet.
|
||||
|
||||
NOTE:
|
||||
|
||||
- Can be used with NPC's who are not dragons, but if they are not huge,
|
||||
the damage is not done (only the pulses at thier location and the target
|
||||
location)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
1.4 - Added an actual spell event fire for the damage. It might not have
|
||||
registered with some hostile monsters otherwise! (EG: DR)
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Executed via. ExecuteScript from the AI file, it is seperate because it is
|
||||
almost a new AI ability.
|
||||
|
||||
It is a 6 second or more fly - note it adds 1/10 second more for each
|
||||
1M between targets. Not too much, but enough.
|
||||
|
||||
Does damage to landing and taking off sites too :-)
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Ability - Dragon Flying] //////////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Damages area with blast of flying
|
||||
void DoDamageToArea(location lLocation);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Get the target location
|
||||
object oJumpTo = GetAIObject(AI_FLYING_TARGET);
|
||||
location lJumpTo = GetLocation(oJumpTo);
|
||||
|
||||
DeleteAIObject(AI_FLYING_TARGET);
|
||||
|
||||
// Errors
|
||||
if(!GetIsObjectValid(oJumpTo)) return;
|
||||
|
||||
ClearAllActions();// To rid errors.
|
||||
SetFacingPoint(GetPosition(oJumpTo));
|
||||
|
||||
// Get location of ourselves, to damage those as we fly away.
|
||||
location lSelf = GetLocation(OBJECT_SELF);
|
||||
// Jump to the next location, using a delay of 3.0 seconds + Distance/10
|
||||
float fDuration = 3.0 + (GetDistanceBetweenLocations(lSelf, lJumpTo)/10.0);
|
||||
|
||||
if(GetCreatureSize(OBJECT_SELF) == CREATURE_SIZE_HUGE)
|
||||
{
|
||||
// Damage instantly
|
||||
DelayCommand(1.0, DoDamageToArea(lSelf));
|
||||
// Delay the jump down damage - a little extra delay mind you.
|
||||
DelayCommand(fDuration + 1.2, DoDamageToArea(lJumpTo));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Visual effects only
|
||||
effect eImpact = EffectVisualEffect(VFX_IMP_PULSE_WIND);
|
||||
// Pulse of wind applied...
|
||||
DelayCommand(1.0, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, lSelf));
|
||||
// Delay the new wind
|
||||
DelayCommand(fDuration + 1.2, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, lJumpTo));
|
||||
}
|
||||
// New determine combat round - via. Action attacking.
|
||||
DelayCommand(fDuration + 1.5, ActionAttack(oJumpTo));
|
||||
|
||||
effect eFly = EffectDisappearAppear(lJumpTo);
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFly, OBJECT_SELF, fDuration - 1.0));
|
||||
}
|
||||
|
||||
// Damages area with blast of flying
|
||||
void DoDamageToArea(location lLocation)
|
||||
{
|
||||
// Declare effects
|
||||
effect eKnockDown = EffectKnockdown();
|
||||
int nDamage;
|
||||
int nDC = GetHitDice(OBJECT_SELF);
|
||||
effect eDam;
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_PULSE_WIND);
|
||||
// Use a delay based on range,
|
||||
float fDelay;
|
||||
|
||||
string sMessage = GetName(OBJECT_SELF) + " is flying!";
|
||||
location lTarget;
|
||||
float fRandomKnockdown;
|
||||
// Pulse of wind applied...
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lLocation);
|
||||
//Apply the VFX impact and effects
|
||||
//Get first target in spell area
|
||||
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lLocation);
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
lTarget = GetLocation(oTarget);
|
||||
fDelay = GetDistanceBetweenLocations(lTarget, lLocation)/20.0;
|
||||
// Visual wind pulse
|
||||
DelayCommand(fDelay, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTarget));
|
||||
//Get next target in spell area
|
||||
// Do not effect allies.
|
||||
if(!GetIsFriend(oTarget) && !GetFactionEqual(oTarget))
|
||||
{
|
||||
SendMessageToPC(oTarget, sMessage);
|
||||
// Can't knock over huge things!
|
||||
if(GetCreatureSize(oTarget) != CREATURE_SIZE_HUGE)
|
||||
{
|
||||
// Signal spell cast at event
|
||||
// * Using: SPELLABILITY_DRAGON_WING_BUFFET - just so something is used
|
||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_DRAGON_WING_BUFFET));
|
||||
|
||||
// Reflex save for damage
|
||||
if(!ReflexSave(oTarget, nDC))
|
||||
{
|
||||
// Randomise damage. (nDC = Hit dice)
|
||||
nDamage = Random(nDC) + 11;
|
||||
eDam = EffectDamage(nDamage, DAMAGE_TYPE_BLUDGEONING);
|
||||
// Randomise knockdown, to minimum of 6.0 (1.0/2 = 0.5. + 5.5 = 6.0)
|
||||
fRandomKnockdown = 5.5 + ((IntToFloat(Random(30)) + 1.0)/10.0);
|
||||
// We'll have a windy effect..depending on range
|
||||
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
|
||||
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eKnockDown, oTarget, fRandomKnockdown));
|
||||
}
|
||||
}
|
||||
}
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_GARGANTUAN, lLocation);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,187 +0,0 @@
|
||||
/*/////////////////////// [Include - Debugging] ////////////////////////////////
|
||||
Filename: J_Inc_Debug
|
||||
///////////////////////// [Include - Debugging] ////////////////////////////////
|
||||
This contains DebugActionSpeak, the debug function.
|
||||
|
||||
Makes it easier to uncomment debug lines.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
- In beta, changed it so this file controls all debug strings. Just
|
||||
uncomment them and recompile to turn it on/off.
|
||||
1.4 - TO DO: Added some more debug strings I use
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
DebugActionSpeak normally writes a timestamped log entry, and speak a silent
|
||||
string Server Admins can hear.
|
||||
|
||||
1.3 added:
|
||||
- DebugActionSpeakByInt(int iInteger);
|
||||
- Removes many strings into this file
|
||||
- Can easily comment out all string so they are not added to compiled
|
||||
scripts if debugging unused (This saves space on compiled files :-D )
|
||||
- Always uncomment the right bits if not using any debugging.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Include - Debugging] //////////////////////////////*/
|
||||
|
||||
// This will speak a cirtain integer number string (similar to a dialog reference).
|
||||
// - I (Jass) have just moved all strings I used all the time into here, so
|
||||
// if the strings are uncommented, they will not be compiled
|
||||
// - The numbers have no reference to much really.
|
||||
// - Calls DebugActionSpeak!
|
||||
// - See J_INC_DEBUG to uncomment/recomment in
|
||||
void DebugActionSpeakByInt(int iInteger, object oInput = OBJECT_INVALID, int nInput = FALSE, string sInput = "");
|
||||
|
||||
// Speaks and stamps a debug string.
|
||||
// - See J_INC_DEBUG to uncomment/recomment the debug strings.
|
||||
// - Only used in special circumstances.
|
||||
void DebugActionSpeak(string sString);
|
||||
|
||||
// This will speak a cirtain integer number string (similar to a dialog reference).
|
||||
// - I (Jass) have just moved all strings I used all the time into here, so
|
||||
// if the strings are uncommented, they will not be compiled
|
||||
// - The numbers have no reference to much really.
|
||||
// - Calls DebugActionSpeak!
|
||||
// - See J_INC_DEBUG to uncomment/recomment in
|
||||
void DebugActionSpeakByInt(int iInteger, object oInput = OBJECT_INVALID, int nInput = FALSE, string sInput = "")
|
||||
{
|
||||
// TO UNCOMMENT/COMMENT:
|
||||
// - Add/Remove in "//" before the next lines "/*"
|
||||
// - Recompile all files
|
||||
|
||||
///*
|
||||
|
||||
string sDebug;
|
||||
switch(iInteger)
|
||||
{
|
||||
// - Generic AI stuff
|
||||
case 1: sDebug = "[DCR:Melee] Most Damaging Weapon. Target: " + GetName(oInput); break;
|
||||
case 2: sDebug = "[DCR:Melee] Most Damaging as Not Effective"; break;
|
||||
case 3: sDebug = "[DCR:Melee] Melee Code. No valid melee target/Dead. Exiting"; break;
|
||||
case 4: sDebug = "[DCR:Melee] Melee attack. [Target] " + GetName(oInput) + " [Feat/Attack] " + IntToString(nInput); break;
|
||||
case 5: sDebug = "[DCR:Caster] Defensive Casting Mode ON [Enemy] " + GetName(oInput); break;
|
||||
case 6: sDebug = "[DCR:Caster] Moving away from AOO's. [Enemy] " + GetName(oInput); break;
|
||||
case 7: sDebug = "[DCR:Casting] Talent(item) [TalentID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 8: sDebug = "[DCR:Casting] Workaround for Spontaeous [SpellID] " + IntToString(nInput) + " [Target] " + GetName(oInput); break;
|
||||
case 9: sDebug = "[DCR:Casting] NormalSpell [ID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 10: sDebug = "[DCR:Casting] TalentSpell. [ID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 11: sDebug = "[DCR:Casting] SubSpecialSpell. [ID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 12: sDebug = "[DCR:Casting] NormalRandomSpell. [ID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 13: sDebug = "[DCR:Casting] Backup spell caught: " + IntToString(nInput); break;
|
||||
case 14: sDebug = "[DCR:Feat] [ID] " + IntToString(nInput) + " [Enemy] " + GetName(oInput); break;
|
||||
case 15: sDebug = "[DCR:Casting] Grenade [ID] " + IntToString(nInput) + " [Target] " + GetName(oInput) + " [Location] " + sInput; break;
|
||||
case 16: sDebug = "[AOE Call] Moving out of/Dispeling an AOE. [Tag] " + GetTag(oInput); break;
|
||||
case 17: sDebug = "[DCR:Special] Darkness + Caster. No seen enemy. Dispel/Move."; break;
|
||||
case 18: sDebug = "[DRC:Talent] Using Talent (Healing). [TalentID] " + IntToString(nInput) + " [Target] " + GetName(oInput); break;
|
||||
case 19: sDebug = "[DCR:Healing] (Should) Healing [Target]" + GetName(oInput) + " [CurrentHP|Max|ID|Rank|Power] " + IntToString(nInput); break;
|
||||
case 20: sDebug = "[DCR Healing] Boss Action, create Critical Wounds potion"; break;
|
||||
case 21: sDebug = "[DCR:Casting] Healing self with healing kit, [Kit] " + GetName(oInput); break;
|
||||
case 22: sDebug = "[DCR:Feat] Summoning my familiar"; break;
|
||||
case 23: sDebug = "[DCR:Feat] Summoning my animal companion"; break;
|
||||
case 24: sDebug = "[DCR:Fleeing] Stupid/Panic/Flee moving from enemies/position - We are a commoner/no morale/failed < 3 int"; break;
|
||||
case 25: sDebug = "[DCR:Fleeing] Fleeing to allies. [ID Array] " + sInput + " [Ally] " + GetName(oInput); break;
|
||||
case 26: sDebug = "[DCR:GFTK] Attacking a PC who is dying/asleep! [Enemy]" + GetName(oInput); break;
|
||||
case 27: sDebug = "[DCR:Moving] Archer Retreating back from the enemy [Enemy]" + GetName(oInput); break;
|
||||
case 28: sDebug = "[DCR:Turning] Using Turn Undead"; break;
|
||||
case 29: sDebug = "[DCR:Bard Song] Using"; break;
|
||||
case 30: sDebug = "[DCR:Bard Curse Song] Using"; break;
|
||||
case 31: sDebug = "[DCR:All Spells] Error! No casting (No spells, items, target Etc)."; break;
|
||||
case 32: sDebug = "[DCR:All Spells] [Modifier|BaseDC|SRA] " + IntToString(nInput); break;
|
||||
case 33: sDebug = "[DCR:Casting] Cheat Spell. End of Spells. [Spell] " + IntToString(nInput) + "[Target]" + GetName(oInput); break;
|
||||
case 34: sDebug = "[DCR:All Spells] Ranged Spells. Should use closer spells/move nearer"; break;
|
||||
case 35: sDebug = "[DCR:Dragon] Breath weapon & attacking [Breath ID] " + IntToString(nInput) + " [Target] " + GetName(oInput); break;
|
||||
case 36: sDebug = "[DCR:Dragon] Wing Buffet [Target] " + GetName(oInput); break;
|
||||
case 37: sDebug = "[DCR:Beholder] Teleport"; break;
|
||||
case 38: sDebug = "[DCR:Beholder] Rays"; break;
|
||||
case 39: sDebug = "[DCR:Targeting] No valid enemies in sight, moving to allies target's. [Target] " + GetName(oInput); break;
|
||||
case 40: sDebug = "[DCR:Targeting] Override Target Seen. [Name]" + GetName(oInput); break;
|
||||
case 41: sDebug = "[DCR:Targeting] No seen in LOS, Attempting to MOVE to something [Target]" + GetName(oInput); break;
|
||||
case 42: sDebug = "[DCR:Skill] Using agressive skill (+Attack). [Skill] " + IntToString(nInput) + " [Enemy]" + GetName(oInput); break;
|
||||
case 43: sDebug = "[DCR:Pre-Melee Spells] All Potions Using. [Spell ID] " + IntToString(nInput); break;
|
||||
case 44: sDebug = "[DCR:Pre-Melee Spells] True Strike Emptive attack [Target] " + GetName(oInput); break;
|
||||
case 45: sDebug = "[DCR:CounterSpell] Counterspelling. [Target] " + GetName(oInput); break;
|
||||
case 46: sDebug = "[DRC] START [Intruder]" + GetName(oInput); break;
|
||||
case 47: sDebug = "[DCR] [PREMITURE EXIT] Cannot Do Anything."; break;
|
||||
case 48: sDebug = "[DCR] [PREMITURE EXIT] Dazed move away."; break;
|
||||
case 49: sDebug = "[DCR] [PREMITURE EXIT] Fleeing or otherwise"; break;
|
||||
case 50: sDebug = "[DRC] END - DELETE PAST TARGETS"; break;
|
||||
// Perception
|
||||
case 51: sDebug = "[Perception] Our Enemy Target changed areas. Stopping, moving too...and attack... [Percieved] " + GetName(oInput); break;
|
||||
case 52: sDebug = "[Perception] Enemy Vanished (Same area) Retargeting/Searching [Percieved] " + GetName(oInput); break;
|
||||
case 53: sDebug = "[Perception] Enemy seen, and was old enemy/cannot see current. Re-evaluating (no spell) [Percieved] " + GetName(oInput); break;
|
||||
case 54: sDebug = "[Perception] Enemy Seen. Not in combat, attacking. [Percieved] " + GetName(oInput); break;
|
||||
case 55: sDebug = "[Perception] Percieved Dead Friend! Moving and Searching [Percieved] " + GetName(oInput); break;
|
||||
case 56: sDebug = "[Perception] Percieved Alive Fighting Friend! Moving to and attacking. [Percieved] " + GetName(oInput); break;
|
||||
// Conversation
|
||||
case 57: sDebug = "[Shout] Friend (may be PC) in combat. Attacking! [Friend] " + GetName(oInput); break;
|
||||
case 58: sDebug = "[Shout] Responding to shout [Enemy] " + GetName(oInput) + " Who has spoken!"; break;
|
||||
// Phisical Attacked
|
||||
case 59: sDebug = "[Phisically Attacked] Attacking back. [Attacker(enemy)] " + GetName(oInput); break;
|
||||
case 60: sDebug = "[Phisically Attacked] Not same area. [Attacker(enemy)] " + GetName(oInput); break;
|
||||
// Damaged
|
||||
case 61: sDebug = "[Damaged] Morale Penalty for 600 seconds [Penalty]" + IntToString(nInput); break;
|
||||
case 62: sDebug = "[Damaged] Not in combat: DCR [Damager]" + GetName(oInput); break;
|
||||
case 63: sDebug = "[Damaged] Not in combat: DCR. Ally hit us. [Damager(Ally?)]" + GetName(oInput); break;
|
||||
// Death
|
||||
case 64: sDebug = "[Death] Checking corpse status in " + IntToString(nInput) + " [Killer] " + GetName(oInput) + " [Times Died Now] " + sInput; break;
|
||||
// Disturbed
|
||||
case 65: sDebug = "[Disturbed] (pickpocket) Attacking Enemy [Disturber] " + GetName(oInput) + " [Type] " + IntToString(nInput); break;
|
||||
// Rest
|
||||
case 66: sDebug = "[Rested] Resting. [Type(should be invalid)] " + IntToString(nInput); break;
|
||||
// Spell Cast at
|
||||
case 67: sDebug = "[Spell] Caster isn't a creature! May look for target [Caster] " + GetName(oInput); break;
|
||||
case 68: sDebug = "[Spell:Enemy/Hostile] Not in combat. Attacking: [Caster] " + GetName(oInput); break;
|
||||
case 69: sDebug = "[Spell] (ally). Not in combat. May Attack/Move [Caster] " + GetName(oInput); break;
|
||||
// Spell Other AI
|
||||
// - Shouts
|
||||
case 70: sDebug = "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(nInput) + " [Shouter] " + GetName(oInput); break;
|
||||
// Constants
|
||||
// - Search
|
||||
case 71: sDebug = "[Search] Resting"; break;
|
||||
case 72: sDebug = "[Search] Searching, No one to attack. [Rounds Remaining] " + IntToString(nInput) + ". [Possible target] " + GetName(oInput); break;
|
||||
// - DCR
|
||||
case 73: sDebug = "[Call for DCR] Default AI [Pre-Set Target]" + GetName(oInput); break;
|
||||
case 74: sDebug = "[Call for DCR] Custom AI [" + sInput + "] [Pre-Set Target]" + GetName(oInput); break;
|
||||
// Destroy self
|
||||
case 75: sDebug = "[Dead] Setting to selectable/destroyable (so we go) for Bioware corpses."; break;
|
||||
case 76: sDebug = "[Dead] Destroying self finally."; break;
|
||||
// Waypoints
|
||||
case 77: sDebug = "[Waypoints] Returning to spawn location. [Area] " + GetName(oInput); break;
|
||||
|
||||
default: return; break;
|
||||
}
|
||||
if(sDebug != "")
|
||||
{
|
||||
DebugActionSpeak(sDebug);
|
||||
}
|
||||
// */
|
||||
}
|
||||
|
||||
void DebugActionSpeak(string sString)
|
||||
{
|
||||
// You MUST uncomment this line, IF you use either of the below things
|
||||
string sNew = "[Debug]" + GetName(OBJECT_SELF) + "[ObjectID]" + ObjectToString(OBJECT_SELF) + " [Debug] " + sString;
|
||||
|
||||
// Note, uncomment this, so that DM's can hear the debug speaks, normally it is
|
||||
// only server admins who can hear the debug. If you are not testing, it might
|
||||
// be best to keep this uncommented.
|
||||
// Futher: - Must have debug mode set to 1
|
||||
// - Only the server admin can seem to see this.
|
||||
// SpeakString(sNew, TALKVOLUME_TALK);
|
||||
|
||||
// Note, uncomment this line to send a message to the first PC in the module.
|
||||
// - Useful for singleplayer testing
|
||||
//SendMessageToPC(GetFirstPC(), sNew);
|
||||
|
||||
// This writes the entry to the log, very important, if debugging
|
||||
// Futher: - If left up for a long time, logs can get very big with the AI
|
||||
// - Use to find problems in the AI and report to me :-D (Jasperre)
|
||||
WriteTimestampedLogEntry(sNew);
|
||||
}
|
||||
|
||||
// Debug: To compile this script full, uncomment all of the below.
|
||||
/* - Add two "/"'s at the start of this line
|
||||
void main()
|
||||
{
|
||||
return;
|
||||
}
|
||||
//*/
|
File diff suppressed because it is too large
Load Diff
@@ -1,605 +0,0 @@
|
||||
/*/////////////////////// [Include - Heartbeat] ////////////////////////////////
|
||||
Filename: J_INC_Heartbeat
|
||||
///////////////////////// [Include - Heartbeat] ////////////////////////////////
|
||||
This contains any heartbeat function calls.
|
||||
|
||||
Note that the heartbeat uses ExecuteScript for larget behaviours that are
|
||||
better split up so the heartbeat is as tiny as possible.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - After Beta - Added
|
||||
1.4 - TO DO
|
||||
- Add in some function (see rest script) that resets if we are not in
|
||||
combat
|
||||
- Some more of the things we should do even if interrupted not the
|
||||
heartbeat.
|
||||
|
||||
- Have moved "after combat searching" into here. It isn't long - but
|
||||
it is more reliable. The special action is cancled if there is combat
|
||||
going on, of course.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is included in nw_c2_default1 and J_AI_OnHeartbeat.
|
||||
|
||||
Contains things like in J_INC_OTHER_AI, but only for the heartbeat event.
|
||||
Keeps it cleaner to read.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Include - Heartbeat] //////////////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Bioware walk waypoints condition name
|
||||
const string sWalkwayVarname = "NW_WALK_CONDITION";
|
||||
// Walk waypoint constant set in the SoU waypoint include
|
||||
const int NW_WALK_FLAG_CONSTANT = 0x00000002;
|
||||
|
||||
// Checks:
|
||||
// * No valid location
|
||||
// * Petrified, paralised, ETC.
|
||||
// Note: If sleep is found, it may apply Zzzz randomly, as well as stopping.
|
||||
int JumpOutOfHeartBeat();
|
||||
|
||||
// This checks fleeing, door bashing and so on, to stop the heartbeat
|
||||
// and perform the override special action, rather then run normal behaviour.
|
||||
int PerformSpecialAction();
|
||||
|
||||
// Get whether the condition is set
|
||||
// * Bioware SoU Waypoint call.
|
||||
int GetWalkCondition(int nCondition, object oCreature=OBJECT_SELF);
|
||||
|
||||
// Cast fleeing spells.
|
||||
// - Invisiblity (best)
|
||||
// - Haste/Expeditious Retreat
|
||||
void ActionCastFleeingSpells();
|
||||
// Cast fleeing spells.
|
||||
// - Invisiblity (best)
|
||||
// - Haste/Expeditious Retreat
|
||||
void ActionCastMoveToCombatSpells();
|
||||
|
||||
// Attempt to cast nSpell. TRUE if true.
|
||||
// Searching and fleeing spells use this.
|
||||
int HeartbeatSpellCast(int nSpell);
|
||||
|
||||
// Used in Search(). This apply Trueseeing, See invisibility, or Invisiblity purge
|
||||
// if we have neither of the 3 on us.
|
||||
void SearchSpells();
|
||||
|
||||
// Returns TRUE if any of the animation settings are on.
|
||||
int GetHasValidAnimations();
|
||||
|
||||
// Checks:
|
||||
// * No valid location
|
||||
// * Petrified, paralised, ETC.
|
||||
// Note: If sleep is found, it may apply Zzzz randomly, as well as stopping.
|
||||
int JumpOutOfHeartBeat()
|
||||
{
|
||||
// What to return
|
||||
int bReturn = FALSE;
|
||||
// Checks:
|
||||
// * No valid location
|
||||
// * Petrified, paralised, ETC.
|
||||
// Note: If sleep is found, it may apply Zzzz randomly, as well as stopping.
|
||||
|
||||
// Effect checking
|
||||
effect eCheck = GetFirstEffect(OBJECT_SELF);
|
||||
int nEffectType;
|
||||
while(GetIsEffectValid(eCheck) && bReturn == FALSE)
|
||||
{
|
||||
nEffectType = GetEffectType(eCheck);
|
||||
// Sleep is special
|
||||
if(nEffectType == EFFECT_TYPE_SLEEP)
|
||||
{
|
||||
bReturn = 2;// This immediantly breaks.
|
||||
}
|
||||
// ALL these stop heartbeat.
|
||||
else if(nEffectType == EFFECT_TYPE_PARALYZE || nEffectType == EFFECT_TYPE_STUNNED ||
|
||||
nEffectType == EFFECT_TYPE_FRIGHTENED || /* Removed sleep above */
|
||||
nEffectType == EFFECT_TYPE_TURNED || nEffectType == EFFECT_TYPE_PETRIFY ||
|
||||
nEffectType == EFFECT_TYPE_DAZED || nEffectType == EFFECT_TYPE_TIMESTOP ||
|
||||
nEffectType == EFFECT_TYPE_DISAPPEARAPPEAR || nEffectType == EFFECT_TYPE_CHARMED ||
|
||||
nEffectType == EFFECT_TYPE_DOMINATED || nEffectType == EFFECT_TYPE_CONFUSED)
|
||||
{
|
||||
bReturn = 1;// 1 = No Zzz. We continue to check for Zzz as well.
|
||||
}
|
||||
eCheck = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
// Do we fire the heartbeat event?
|
||||
if(bReturn != FALSE)
|
||||
{
|
||||
// If it is sleep... Zzzzz sometimes.
|
||||
if(bReturn == 2 && d6() == 1)
|
||||
{
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT,
|
||||
EffectVisualEffect(VFX_IMP_SLEEP),
|
||||
OBJECT_SELF);
|
||||
}
|
||||
// Fire event 1001
|
||||
FireUserEvent(AI_FLAG_UDE_HEARTBEAT_EVENT, EVENT_HEARTBEAT_EVENT);
|
||||
}
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
// This checks fleeing, door bashing and so on, to stop the heartbeat
|
||||
// and perform the override special action, rather then run normal behaviour.
|
||||
int PerformSpecialAction()
|
||||
{
|
||||
int nAction = GetCurrentSetAction();
|
||||
object oTarget = GetAttackTarget();
|
||||
object oRunTarget;
|
||||
switch(nAction)
|
||||
{
|
||||
// - Leader has made me a runner. I must run to a nearby group calling
|
||||
// for help to get more men
|
||||
case AI_SPECIAL_ACTIONS_ME_RUNNER:
|
||||
{
|
||||
oRunTarget = GetAIObject(AI_RUNNER_TARGET);
|
||||
if(GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
if(GetObjectSeen(oRunTarget))
|
||||
{
|
||||
// Stop thinking we are a runner if we can see the run target
|
||||
ResetCurrentAction();
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else run to them
|
||||
if(GetObjectHeard(oRunTarget))
|
||||
{
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
}
|
||||
ClearAllActions();
|
||||
ActionMoveToObject(oRunTarget, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
// - I am fleeing.
|
||||
case AI_SPECIAL_ACTIONS_FLEE:
|
||||
{
|
||||
oRunTarget = GetAIObject(AI_FLEE_TO);
|
||||
if(GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
// If they are a leader, and seen, and they are running, we
|
||||
// obviously follow only.
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER, oRunTarget) ||
|
||||
GetLocalInt(oRunTarget, AI_CURRENT_ACTION) == AI_SPECIAL_ACTIONS_FLEE)
|
||||
{
|
||||
ClearAllActions();
|
||||
// New - cast fleeing spells. Important (and only used
|
||||
// at higher intelligence) things like Expeditious retreat.
|
||||
// - Only used once - one invisibility or haste. Deleted above.
|
||||
ActionCastFleeingSpells();
|
||||
ActionForceFollowObject(oRunTarget, 3.0);
|
||||
}
|
||||
else if(GetObjectSeen(oRunTarget))
|
||||
{
|
||||
// If we see the flee target, reset targets
|
||||
ResetCurrentAction();
|
||||
|
||||
// We will delete the local int (set to TRUE) which we
|
||||
// stopped fleeing spells from being used
|
||||
DeleteAIInteger(AI_HEARTBEAT_FLEE_SPELLS);
|
||||
// Speak to allies to come :-)
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
|
||||
// Also reset visual effect
|
||||
RemoveFleeingVisual();
|
||||
|
||||
// And attack/heal self
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
// Return TRUE, we attacked
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else flee!
|
||||
if(GetObjectHeard(oRunTarget))
|
||||
{
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
}
|
||||
ClearAllActions();
|
||||
// New - cast fleeing spells. Important (and only used
|
||||
// at higher intelligence) things like Expeditious retreat.
|
||||
// - Only used once - one invisibility or haste. Deleted above.
|
||||
ActionCastFleeingSpells();
|
||||
ActionMoveToObject(oRunTarget, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if we have bad intellgence, if we have, we will run away
|
||||
// from the nearest enemy we can see or hear.
|
||||
if(GetAIInteger(AI_INTELLIGENCE) <= 3)
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetLastHostileActor();
|
||||
if(!GetIsObjectValid(oRunTarget) || GetIsDead(oRunTarget))
|
||||
{
|
||||
// If we do not have anyone to run from, stop
|
||||
ResetCurrentAction();
|
||||
// Speak to allies to come :-)
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
// Also reset visual effect
|
||||
RemoveFleeingVisual();
|
||||
// And attack/heal self
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
// Return TRUE, we attacked
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run from enemy (1.4: Was oTarget, now oRunTarget)
|
||||
ClearAllActions();
|
||||
ActionMoveAwayFromObject(oRunTarget, TRUE, 50.0);
|
||||
return TRUE;
|
||||
}
|
||||
// If we see the flee target, reset targets
|
||||
ResetCurrentAction();
|
||||
// Speak to allies to come :-)
|
||||
AISpeakString(AI_SHOUT_HELP_MY_FRIEND);
|
||||
// Also reset visual effect
|
||||
RemoveFleeingVisual();
|
||||
// And attack/heal self
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
// Return TRUE, we attacked/healed
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// If this is set, we are usually in combat - and must move out of an AOE.
|
||||
case AI_SPECIAL_ACTIONS_MOVE_OUT_OF_AOE:
|
||||
{
|
||||
// We must be X distance away from a cirtain AOE, if we are not, we
|
||||
// move.
|
||||
oRunTarget = GetAIObject(AI_AOE_FLEE_FROM);
|
||||
|
||||
// If not valid, or already far enough away, delete special action
|
||||
// and return false.
|
||||
if(!GetIsObjectValid(oRunTarget) ||
|
||||
GetLocalFloat(OBJECT_SELF, AI_AOE_FLEE_FROM_RANGE) < GetDistanceToObject(oRunTarget))
|
||||
{
|
||||
ResetCurrentAction();
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Valid and still in range
|
||||
// - Run away
|
||||
ClearAllActions();
|
||||
ActionMoveAwayFromLocation(GetLocation(oRunTarget), TRUE, GetLocalFloat(OBJECT_SELF, AI_AOE_FLEE_FROM_RANGE));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
// If this is the one, we will search around for enemies - usually done
|
||||
// at the end of a combat round, it is more reliable here.
|
||||
case AI_SPECIAL_ACTIONS_SEARCH_AROUND:
|
||||
{
|
||||
// If we are in combat, delete this special thing, and return FALSE
|
||||
if(GetIsObjectValid(GetAttemptedSpellTarget()) ||
|
||||
GetIsObjectValid(GetAttemptedAttackTarget()) ||
|
||||
GetIsObjectValid(GetAttackTarget()))
|
||||
{
|
||||
// Reset, and return FALSE.
|
||||
ResetCurrentAction();
|
||||
return FALSE;
|
||||
}
|
||||
// Added this so special actions do not get ignored (EG: healkitting)
|
||||
// It will not do anything, but no heartbeat will be performed. These
|
||||
// kind of actions happen at the end of combat (healing self of damage ETC)
|
||||
// So, basically, will keep in mind it's still searching, but will leave
|
||||
// it until no busy actions are being done.
|
||||
else if(GetIsBusyWithAction())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// We search for a cirtain number of rounds, set in the generic AI
|
||||
// file, when we first start searching, or restart even. The generic
|
||||
// AI will not actually do search actions, and if it finds no enemy,
|
||||
// will probably just increase the integer to do more search rounds.
|
||||
// * Will be intelligence + 2 to start.
|
||||
int nRoundsRemaining = GetAIInteger(AI_SEARCH_ROUNDS_REMAINING);
|
||||
// Decrease rounds remaining
|
||||
nRoundsRemaining--;
|
||||
// Set new one onto us to use next time
|
||||
SetAIInteger(AI_SEARCH_ROUNDS_REMAINING, nRoundsRemaining);
|
||||
// * Note: If nRoundsRemaining is 0 at the end of this function, we
|
||||
// will remove this action as the current special one.
|
||||
|
||||
// Get the target to move to/around
|
||||
// * Can be invalid, but usually the creature we just killed or noticed
|
||||
// lying on the ground.
|
||||
object oTarget = GetAIObject(AI_SEARCH_TARGET);
|
||||
|
||||
// Stop now (Small amounts of movement each time seem more cautious)
|
||||
ClearAllActions();
|
||||
|
||||
// Check some spells. Cast one if we have no true seeing ETC.
|
||||
SearchSpells();
|
||||
|
||||
// Stealth/search.
|
||||
int bStealth = GetStealthMode(OBJECT_SELF);
|
||||
int bSearch = GetDetectMode(OBJECT_SELF);
|
||||
|
||||
// We perfere to hide again if we search if set to...sneaky!
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(bStealth != STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are hiding, stop to search (we shouldn't be - who knows?)
|
||||
if(bStealth == STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, FALSE);
|
||||
}
|
||||
// And search!
|
||||
if(bSearch != DETECT_MODE_ACTIVE && !GetHasFeat(FEAT_KEEN_SENSE))
|
||||
{
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_DETECT, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// We check around the target, if there is one.
|
||||
if(GetIsObjectValid(oTarget))
|
||||
{
|
||||
// Move to the location of oTarget
|
||||
ActionMoveToLocation(GetLocation(oTarget));
|
||||
|
||||
// If it is a chest ETC. We close it.
|
||||
if(GetIsOpen(oTarget))
|
||||
{
|
||||
if(GetObjectType(oTarget) == OBJECT_TYPE_DOOR)
|
||||
{
|
||||
ActionCloseDoor(oTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Close it
|
||||
ActionDoCommand(DoPlaceableObjectAction(oTarget, PLACEABLE_ACTION_USE));
|
||||
}
|
||||
}
|
||||
}
|
||||
// We will get nearest enemy at the very least
|
||||
else
|
||||
{
|
||||
// Use nearest heard
|
||||
object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY,
|
||||
OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD);
|
||||
if(GetIsObjectValid(oEnemy))
|
||||
{
|
||||
// Move to location
|
||||
ActionMoveToLocation(GetLocation(oEnemy));
|
||||
}
|
||||
}
|
||||
// Note: Here, we will return to spawn location after moving to the
|
||||
// object, if it is a valid setting, else we do the normal randomwalk
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION, AI_OTHER_MASTER))
|
||||
{
|
||||
ActionMoveToLocation(GetAILocation(AI_RETURN_TO_POINT));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 72: "[Search] Searching, No one to attack. [Rounds Remaining] " + IntToString(nRoundsRemaining) + ". [Possible target] " + GetName(oTarget)
|
||||
DebugActionSpeakByInt(72, oTarget, nRoundsRemaining);
|
||||
// Randomly walk.
|
||||
ActionRandomWalk();
|
||||
}
|
||||
// If we have 0 rounds left of searching time, we turn of this special
|
||||
// action, walk waypoints, and probably rest.
|
||||
if(nRoundsRemaining == 0)
|
||||
{
|
||||
// Rest after combat?
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_REST_AFTER_COMBAT, AI_OTHER_MASTER))
|
||||
{
|
||||
// 71: "[Search] Resting"
|
||||
DebugActionSpeakByInt(71);
|
||||
// Yes - we use ActionRest(). It can possibly still fail if
|
||||
// enemies are still around!
|
||||
ActionRest();
|
||||
ActionWait(1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else, just execute Walk Waypoints
|
||||
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
||||
}
|
||||
// Delete this special action
|
||||
ResetCurrentAction();
|
||||
}
|
||||
// If we havn't bailed out early and returned FALSE (do normal hb) we
|
||||
// will return TRUE, we have something to do at least.
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
// Move to combat - we buff (and only buff again after 1 minute of running)
|
||||
// and either follow the person who wants us to help them, or we will run to the
|
||||
// location set.
|
||||
// * Set only by "AI_HELP_MY_FRIEND_CONSTANT" at the moment.
|
||||
case AI_SPECIAL_ACTIONS_MOVE_TO_COMBAT:
|
||||
{
|
||||
// We get a location to move to first
|
||||
location lTarget = GetAILocation(AI_MOVE_TO_COMBAT_LOCATION);
|
||||
object oObject = GetAreaFromLocation(lTarget);
|
||||
|
||||
// Check if the location is valid
|
||||
if(GetIsObjectValid(oObject) && GetArea(OBJECT_SELF) == oObject)
|
||||
{
|
||||
// Just move, rapidly, to lTarget.
|
||||
ClearAllActions();
|
||||
|
||||
// Buff up an action
|
||||
ActionCastMoveToCombatSpells();
|
||||
|
||||
// Move (fast) to that location
|
||||
ActionMoveToLocation(lTarget, TRUE);
|
||||
// If we see/hear combat, we'll attack
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get who we should "follow" or move to.
|
||||
oObject = GetAIObject(AI_MOVE_TO_COMBAT_OBJECT);
|
||||
|
||||
if(GetIsObjectValid(oObject))
|
||||
{
|
||||
// Just move, rapidly, to oTarget. It isn't "real" following,
|
||||
// but paced. Means it looks OK. Need to test - but should be OK.
|
||||
ClearAllActions();
|
||||
|
||||
// Buff up an action
|
||||
ActionCastMoveToCombatSpells();
|
||||
|
||||
// Move (fast) to that location
|
||||
ActionMoveToObject(oTarget, TRUE);
|
||||
// If we see/hear combat, we'll attack
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the special action and return FALSE
|
||||
ResetCurrentAction();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Return false to carry on a normal heartbeat
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get whether the condition is set
|
||||
// * Bioware SoU Waypoint call.
|
||||
int GetWalkCondition(int nCondition, object oCreature=OBJECT_SELF)
|
||||
{
|
||||
return (GetLocalInt(oCreature, sWalkwayVarname) & nCondition);
|
||||
}
|
||||
|
||||
// Cast fleeing spells.
|
||||
// - Invisiblity (best)
|
||||
// - Haste/Expeditious Retreat
|
||||
void ActionCastFleeingSpells()
|
||||
{
|
||||
// Not got local
|
||||
if(GetAIInteger(AI_HEARTBEAT_FLEE_SPELLS)) return;
|
||||
// Set local
|
||||
SetAIInteger(AI_HEARTBEAT_FLEE_SPELLS, TRUE);
|
||||
|
||||
// Invisibilities
|
||||
if(HeartbeatSpellCast(SPELL_IMPROVED_INVISIBILITY)) return;
|
||||
if(HeartbeatSpellCast(SPELL_INVISIBILITY)) return;
|
||||
|
||||
// Haste
|
||||
if(HeartbeatSpellCast(SPELL_MASS_HASTE)) return;
|
||||
if(HeartbeatSpellCast(SPELL_HASTE)) return;
|
||||
if(HeartbeatSpellCast(SPELL_EXPEDITIOUS_RETREAT)) return;
|
||||
}
|
||||
// Cast fleeing spells.
|
||||
// - Invisiblity (best)
|
||||
// - Haste/Expeditious Retreat
|
||||
void ActionCastMoveToCombatSpells()
|
||||
{
|
||||
// Timer to stop too many spells at once
|
||||
if(GetLocalTimer(AI_TIMER_MOVE_TO_COMBAT_BUFF)) return;
|
||||
|
||||
// We first will cast a preperation spell before jumping in!
|
||||
// This is used once per minute.
|
||||
SetLocalTimer(AI_TIMER_MOVE_TO_COMBAT_BUFF, 60.0);
|
||||
|
||||
// We possibly cast a few spell first - stoneskin range, see
|
||||
// invisible range, and invisibility range.
|
||||
// Protection things
|
||||
// * Cast 1 spell!
|
||||
if(HeartbeatSpellCast(SPELL_PREMONITION)) return;
|
||||
if(HeartbeatSpellCast(SPELL_GREATER_STONESKIN)) return;
|
||||
if(HeartbeatSpellCast(SPELL_STONESKIN)) return;
|
||||
// Invisibility range
|
||||
if(HeartbeatSpellCast(SPELL_ETHEREALNESS)) return;
|
||||
if(HeartbeatSpellCast(SPELL_IMPROVED_INVISIBILITY)) return;
|
||||
if(HeartbeatSpellCast(SPELL_INVISIBILITY_SPHERE)) return;
|
||||
if(HeartbeatSpellCast(SPELL_INVISIBILITY)) return;
|
||||
// See invisible things
|
||||
if(HeartbeatSpellCast(SPELL_TRUE_SEEING)) return;
|
||||
if(HeartbeatSpellCast(SPELL_SEE_INVISIBILITY)) return;
|
||||
|
||||
// Stealth! Only if we are good at it, of course.
|
||||
|
||||
// Spawn in conditions for it
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
// Need skill or force on
|
||||
if((GetSkillRank(SKILL_HIDE) - 4 >= GetHitDice(OBJECT_SELF)) ||
|
||||
GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
// Use hide
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Used in Search(). This apply Trueseeing, See invisibility, or Invisiblity purge
|
||||
// if we have neither of the 3 on us.
|
||||
void SearchSpells()
|
||||
{
|
||||
effect eCheck = GetFirstEffect(OBJECT_SELF);
|
||||
int nEffectType, bBreak;
|
||||
while(GetIsEffectValid(eCheck) && bBreak == FALSE)
|
||||
{
|
||||
nEffectType = GetEffectType(eCheck);
|
||||
if(nEffectType == EFFECT_TYPE_TRUESEEING ||
|
||||
nEffectType == EFFECT_TYPE_SEEINVISIBLE)
|
||||
{
|
||||
bBreak = TRUE;
|
||||
}
|
||||
eCheck = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
// We have effects, stop.
|
||||
if(bBreak == TRUE || GetHasSpellEffect(SPELL_INVISIBILITY_PURGE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Else we apply the best spell we have.
|
||||
if(HeartbeatSpellCast(SPELL_TRUE_SEEING)) return;
|
||||
if(HeartbeatSpellCast(SPELL_SEE_INVISIBILITY)) return;
|
||||
if(HeartbeatSpellCast(SPELL_INVISIBILITY_PURGE)) return;
|
||||
}
|
||||
// Attempt to cast nSpell. TRUE if true.
|
||||
int HeartbeatSpellCast(int nSpell)
|
||||
{
|
||||
// 1.4: added check to see if has effect already
|
||||
if(GetHasSpell(nSpell) && !GetHasSpellEffect(nSpell, OBJECT_SELF))
|
||||
{
|
||||
ActionCastSpellAtObject(nSpell, OBJECT_SELF);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns TRUE if any of the animation settings are on.
|
||||
int GetHasValidAnimations()
|
||||
{
|
||||
int nCheck = GetLocalInt(OBJECT_SELF, NW_GENERIC_MASTER);
|
||||
if((nCheck & NW_FLAG_AMBIENT_ANIMATIONS) ||
|
||||
(nCheck & NW_FLAG_AMBIENT_ANIMATIONS_AVIAN) ||
|
||||
(nCheck & NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -1,447 +0,0 @@
|
||||
/*/////////////////////// [Include - NPC (Combat) Attack] //////////////////////
|
||||
Filename: J_INC_NPC_Attack
|
||||
///////////////////////// [Include - NPC (Combat) Attack] //////////////////////
|
||||
What does this do?
|
||||
|
||||
It is a wrapper/include for getting a creature to attack target X, or do
|
||||
Y. I use this for conversations, triggers, the lot, as a simple wrapper
|
||||
that will execute my AI.
|
||||
|
||||
There are several functions here to do things, that may be useful wrappers.
|
||||
|
||||
And it also keeps Combat files SMALL! I uses Execute Script to fire the
|
||||
combat file, not include it here.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
1.4 - TO DO:
|
||||
- Bugfix a few things (copy/paste errors)
|
||||
- Add example script to use (User defined events)
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Include this in any conversation file or whatever, and mearly read the
|
||||
descriptions of the different functions, and it will do what it says :-)
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Include - NPC (Combat) Attack] ////////////////////*/
|
||||
|
||||
// Include the constants for the combat, spawn integers ETC.
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Hostile amount
|
||||
const int HOSTILE = -100;// Reputation to change to
|
||||
const int TYPE_ALL_PCS = 1;// is all PC's in the world.
|
||||
const int TYPE_ALL_AREA = 2;// is all PC's in the specific area.
|
||||
const int TYPE_IN_RANGE = 3;// is all PC's within fRange.
|
||||
|
||||
// A slightly modified way to determine a combat round.
|
||||
// * oTarget - The target to attack
|
||||
// * sShout - The string to silently speak to get allies to come and help
|
||||
void DetermineSpeakCombatRound(object oTarget = OBJECT_INVALID, string sShout = "");
|
||||
|
||||
// A slightly modified way to determine a combat round.
|
||||
// * oTarget - The target to attack
|
||||
// * oAttacker - The NPC who you want to determine a combat round, on oTarget
|
||||
void DetermineSpeakCombatRoundNotMe(object oTarget, object oAttacker);
|
||||
|
||||
// This is the main wrapper to get an NPC to attack in conversation.
|
||||
// * fDelay - The delay AFTER adjusting reputation, that we attack and shout
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// Example, how to keep flags already set:
|
||||
// HostileAttackPCSpeaker(0.0, GetPlotFlag(), GetImmortal());
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackPCSpeaker(float fDelay = 0.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE);
|
||||
|
||||
// This will make our faction hostile to the target, and attack them.
|
||||
// * oTarget - The target object to attack
|
||||
// * fDelay - The delay AFTER adjusting reputation, that we attack and shout
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// Example, how to keep flags already set:
|
||||
// HostileAttackObject(oPC, 0.0, GetPlotFlag(), GetImmortal());
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackObject(object oTarget, float fDelay = 0.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE);
|
||||
|
||||
// This will make our faction hostile to the target, and shout.
|
||||
// * oTarget - The target object to shout about.
|
||||
// Use: Placeables, disturbers and so on.
|
||||
// Note: Placeables are normally defaulted hostile faction! Must change it to work
|
||||
void ShoutAbout(object oTarget);
|
||||
|
||||
// This will make our faction hostile to ALL(!) PC's...in the area or game or range
|
||||
// * nType - TYPE_ALL_PCS (1) is all PC's in the world.
|
||||
// - TYPE_ALL_AREA (2) is all PC's in the specific area.
|
||||
// - TYPE_IN_RANGE (3) is all PC's within fRange.
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackAllPCs(int nType = 1, float fRange = 40.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE);
|
||||
|
||||
// This will thier most damaging weapon, and wait to disarm it.
|
||||
// * fDuration - Delay until the weapon is withdrawn.
|
||||
// * bRanged - if TRUE, it will equip a ranged weapon as a prioritory (EquipRanged call)
|
||||
void EquipWeaponsDuration(float fDuration, int bRanged = FALSE);
|
||||
// Disarms the persons right-hand-weapon
|
||||
void RemoveWeapons();
|
||||
|
||||
// Plays talks like "ATTACK!" and "Group Near Me" etc.
|
||||
// * nLowest, nHighest - the High/Lowest value to use.
|
||||
// 0 = ATTACK, 1 = TAUNT, 2-4 = BATTLE(1-3), 5 = ENEMIES, 6 = GROUP, 7 = HELP.
|
||||
void PlaySomeTaunt(int nLowest = 0, int nHighest = 7);
|
||||
|
||||
// Gets all allies of ourselves to attack oTarget
|
||||
// * oTarget - The target to attack.
|
||||
void AlliesAttack(object oTarget);
|
||||
|
||||
// Returns the nearest PC object
|
||||
object GetNearestPCCreature();
|
||||
// Returns the nearest enemy (but doesn't determine if it can see/hear it)
|
||||
object GetNearestEnemyCreature();
|
||||
// Returns the nearest friend
|
||||
object GetNearestFriendCreature();
|
||||
|
||||
|
||||
// A slightly modified way to determine a combat round.
|
||||
// * oTarget - The target to attack
|
||||
// * sShout - The string to silently speak to get allies to come and help
|
||||
void DetermineSpeakCombatRound(object oTarget, string sShout)
|
||||
{
|
||||
// Shout
|
||||
if(sShout != "") AISpeakString(sShout);
|
||||
|
||||
// Check for custom AI script, else fire default.
|
||||
string sAI = GetCustomAIFileName();
|
||||
// Fire default AI script
|
||||
if(sAI == "")
|
||||
{
|
||||
// Sanity check - to not fire this off multiple times, we make sure temp
|
||||
// object is not the same as oTarget (and valid)
|
||||
if(!GetIsObjectValid(oTarget) || (GetIsObjectValid(oTarget) &&
|
||||
!GetLocalTimer(AI_DEFAULT_AI_COOLDOWN)))
|
||||
{
|
||||
SetLocalObject(OBJECT_SELF, AI_TEMP_SET_TARGET, oTarget);
|
||||
ExecuteScript(COMBAT_FILE, OBJECT_SELF);
|
||||
SetLocalTimer(AI_DEFAULT_AI_COOLDOWN, 0.1);
|
||||
}
|
||||
}
|
||||
// Fire custom AI script
|
||||
else
|
||||
{
|
||||
SetLocalObject(OBJECT_SELF, AI_TEMP_SET_TARGET, oTarget);
|
||||
ExecuteScript(sAI, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
|
||||
// A slightly modified way to determine a combat round.
|
||||
// * oTarget - The target to attack
|
||||
// * oAttacker - The NPC who you want to determine a combat round, on oTarget
|
||||
void DetermineSpeakCombatRoundNotMe(object oTarget, object oAttacker)
|
||||
{
|
||||
// Check for custom AI script, else fire default.
|
||||
string sAI = GetLocalString(oAttacker, AI_CUSTOM_AI_SCRIPT);
|
||||
// Fire default AI script
|
||||
if(sAI == "")
|
||||
{
|
||||
// Sanity check - to not fire this off multiple times, we make sure temp
|
||||
// object is not the same as oTarget (and valid)
|
||||
if(!GetIsObjectValid(oTarget) || (GetIsObjectValid(oTarget) &&
|
||||
!GetLocalTimer(AI_DEFAULT_AI_COOLDOWN)))
|
||||
{
|
||||
SetLocalObject(oAttacker, AI_TEMP_SET_TARGET, oTarget);
|
||||
ExecuteScript(COMBAT_FILE, oAttacker);
|
||||
SetLocalTimer(AI_DEFAULT_AI_COOLDOWN, 0.1);
|
||||
}
|
||||
}
|
||||
// Fire custom AI script
|
||||
else
|
||||
{
|
||||
SetLocalObject(oAttacker, AI_TEMP_SET_TARGET, oTarget);
|
||||
ExecuteScript(sAI, oAttacker);
|
||||
}
|
||||
}
|
||||
// This is the main wrapper to get an NPC to attack in conversation.
|
||||
// * fDelay - The delay AFTER adjusting reputation, that we attack and shout
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// Example, how to keep flags already set:
|
||||
// HostileAttackPCSpeaker(0.0, GetPlotFlag(), GetImmortal());
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackPCSpeaker(float fDelay = 0.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE)
|
||||
{
|
||||
// Get the PC
|
||||
object oPC = GetPCSpeaker();
|
||||
|
||||
// Error checking
|
||||
if(!GetIsObjectValid(oPC) || GetIsDM(oPC)) return;
|
||||
|
||||
// Change our flags for plot and immortal (usually turns them off)
|
||||
SetPlotFlag(OBJECT_SELF, bPlot);
|
||||
SetImmortal(OBJECT_SELF, bImmortal);
|
||||
|
||||
// We make them hostile to our faction
|
||||
AdjustReputation(oPC, OBJECT_SELF, HOSTILE);
|
||||
|
||||
// Attack them
|
||||
SetLocalObject(OBJECT_SELF, AI_TO_ATTACK, oPC);
|
||||
if(fDelay > 0.0)
|
||||
{
|
||||
// Round start...
|
||||
DelayCommand(fDelay, DetermineSpeakCombatRound(oPC, AI_SHOUT_I_WAS_ATTACKED));
|
||||
if(bAllAllies) DelayCommand(fDelay, AlliesAttack(oPC));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Round start...
|
||||
DetermineSpeakCombatRound(oPC, AI_SHOUT_I_WAS_ATTACKED);
|
||||
if(bAllAllies) AlliesAttack(oPC);
|
||||
}
|
||||
}
|
||||
|
||||
// This will make our faction hostile to the target, and attack them.
|
||||
// * oTarget - The target object to attack
|
||||
// * fDelay - The delay AFTER adjusting reputation, that we attack and shout
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// Example, how to keep flags already set:
|
||||
// HostileAttackObject(oPC, 0.0, GetPlotFlag(), GetImmortal());
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackObject(object oTarget, float fDelay = 0.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE)
|
||||
{
|
||||
// Error checking
|
||||
if(!GetIsObjectValid(oTarget) || GetIsDM(oTarget)) return;
|
||||
|
||||
// Change our flags for plot and immortal (usually turns them off)
|
||||
SetPlotFlag(OBJECT_SELF, bPlot);
|
||||
SetImmortal(OBJECT_SELF, bImmortal);
|
||||
|
||||
// We make them hostile to our faction
|
||||
AdjustReputation(oTarget, OBJECT_SELF, HOSTILE);
|
||||
|
||||
// Attack them
|
||||
SetLocalObject(OBJECT_SELF, AI_TO_ATTACK, oTarget);
|
||||
|
||||
if(fDelay > 0.0)
|
||||
{
|
||||
// Round start...
|
||||
DelayCommand(fDelay, DetermineSpeakCombatRound(oTarget, AI_SHOUT_I_WAS_ATTACKED));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Round start...
|
||||
DetermineSpeakCombatRound(oTarget, AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
}
|
||||
|
||||
// This will make our faction hostile to the target, and shout.
|
||||
// * oTarget - The target object to shout about.
|
||||
// Use: Placeables, disturbers and so on.
|
||||
void ShoutAbout(object oTarget)
|
||||
{
|
||||
// We make them hostile to our faction
|
||||
AdjustReputation(oTarget, OBJECT_SELF, HOSTILE);
|
||||
// And shout for others to attack
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
|
||||
// This will make our faction hostile to ALL(!) PC's...in the area or game or range
|
||||
// * nType - TYPE_ALL_PCS (1) is all PC's in the world.
|
||||
// - TYPE_ALL_AREA (2) is all PC's in the specific area.
|
||||
// - TYPE_IN_RANGE (3) is all PC's within fRange.
|
||||
// * bPlot - The plot flag to set US to (Usually FALSE).
|
||||
// * bImmortal - The immortal flag US to set to (Usually FALSE).
|
||||
// * bAllAllies - This will determine combat rounds against the target, that are in 50.0M. False = Don't
|
||||
void HostileAttackAllPCs(int nType = 1, float fRange = 40.0, int bPlot = FALSE, int bImmortal = FALSE, int bAllAllies = TRUE)
|
||||
{
|
||||
object oPC, oToAttack;
|
||||
int bShout, nCnt;
|
||||
float fNearestEnemy = 10000.0;
|
||||
object oArea = GetArea(OBJECT_SELF);
|
||||
switch(nType)
|
||||
{
|
||||
case TYPE_ALL_PCS:// s all PC's in the world.
|
||||
{
|
||||
oPC = GetFirstPC();
|
||||
while(GetIsObjectValid(oPC))
|
||||
{
|
||||
if(!GetIsDM(oPC) &&
|
||||
GetIsObjectValid(GetArea(oPC)))
|
||||
{
|
||||
AdjustReputation(oPC, OBJECT_SELF, HOSTILE);
|
||||
if(GetArea(oPC) == oArea)
|
||||
{
|
||||
if(GetDistanceToObject(oPC) <= fNearestEnemy)
|
||||
{
|
||||
oToAttack = oPC;
|
||||
}
|
||||
}
|
||||
bShout = TRUE;
|
||||
}
|
||||
oPC = GetNextPC();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_ALL_AREA:// is all PC's in the specific area.
|
||||
{
|
||||
nCnt = 1;
|
||||
oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, nCnt);
|
||||
while(GetIsObjectValid(oPC))
|
||||
{
|
||||
// Attack it! (if not a DM!)
|
||||
if(!GetIsDM(oPC))
|
||||
{
|
||||
AdjustReputation(oPC, OBJECT_SELF, HOSTILE);
|
||||
if(GetArea(oPC) == oArea)
|
||||
{
|
||||
if(GetDistanceToObject(oPC) <= fNearestEnemy)
|
||||
{
|
||||
oToAttack = oPC;
|
||||
}
|
||||
}
|
||||
bShout = TRUE;
|
||||
}
|
||||
// Next one
|
||||
nCnt++;
|
||||
oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, nCnt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_IN_RANGE:// is all PC's within fRange.
|
||||
{
|
||||
nCnt = 1;
|
||||
oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, nCnt);
|
||||
while(GetIsObjectValid(oPC) && GetDistanceToObject(oPC) <= fRange)
|
||||
{
|
||||
// Attack it! (if not a DM!)
|
||||
if(!GetIsDM(oPC))
|
||||
{
|
||||
AdjustReputation(oPC, OBJECT_SELF, HOSTILE);
|
||||
if(GetArea(oPC) == oArea)
|
||||
{
|
||||
if(GetDistanceToObject(oPC) <= fNearestEnemy)
|
||||
{
|
||||
oToAttack = oPC;
|
||||
}
|
||||
}
|
||||
bShout = TRUE;
|
||||
}
|
||||
// Next one
|
||||
nCnt++;
|
||||
oPC = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC, OBJECT_SELF, nCnt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Attack nearest one (if valid)
|
||||
if(GetIsObjectValid(oToAttack))
|
||||
{
|
||||
// Change our flags for plot and immortal (usually turns them off)
|
||||
SetPlotFlag(OBJECT_SELF, bPlot);
|
||||
SetImmortal(OBJECT_SELF, bImmortal);
|
||||
|
||||
DetermineSpeakCombatRound(oToAttack);
|
||||
if(bAllAllies) AlliesAttack(oToAttack);
|
||||
}
|
||||
// Check if we shout
|
||||
if(bShout) AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
// This will thier most damaging weapon, and wait to disarm it.
|
||||
// * fDuration - Delay until the weapon is withdrawn.
|
||||
// * bRanged - if TRUE, it will equip a ranged weapon as a prioritory (EquipRanged call)
|
||||
void EquipWeaponsDuration(float fDuration, int bRanged = FALSE)
|
||||
{
|
||||
if(bRanged)
|
||||
{
|
||||
// Equip any most damaging (don't use oVersus, incase it doesn't arm anything)
|
||||
ActionEquipMostDamagingRanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Equip any most damaging (don't use oVersus, incase it doesn't arm anything)
|
||||
ActionEquipMostDamagingMelee();
|
||||
}
|
||||
// Delay the un-equip
|
||||
DelayCommand(fDuration, RemoveWeapons());
|
||||
}
|
||||
// Disarms the persons right-hand-weapon
|
||||
void RemoveWeapons()
|
||||
{
|
||||
// cannot be in combat, duh!
|
||||
if(GetIsInCombat() || GetIsObjectValid(GetAttackTarget()))
|
||||
return;
|
||||
// Get the weapon, make sure it is valid, and...
|
||||
object oUnequip = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND);
|
||||
if(GetIsObjectValid(oUnequip))
|
||||
{
|
||||
// ...unequip it.
|
||||
ClearAllActions();
|
||||
ActionUnequipItem(oUnequip);
|
||||
}
|
||||
}
|
||||
/*::///////////////////////////////////////////////
|
||||
//:: PlaySomeTaunt
|
||||
//::///////////////////////////////////////////////
|
||||
Plays talks like "ATTACK!" and "Group Near Me" etc.
|
||||
* iLowest, iHighest - the High/Lowest value to use.
|
||||
0 = ATTACK, 1 = TAUNT, 2-4 = BATTLE(1-3), 5 = ENEMIES, 6 = GROUP, 7 = HELP.
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Created by : Jasperre
|
||||
//:://///////////////////////////////////////////*/
|
||||
void PlaySomeTaunt(int nLowest, int nHighest)
|
||||
{
|
||||
int nRandom = Random(nHighest) + nLowest;
|
||||
int nVoice = VOICE_CHAT_ATTACK;
|
||||
switch (nRandom)
|
||||
{
|
||||
case 0: nVoice = VOICE_CHAT_ATTACK; break;
|
||||
case 1: nVoice = VOICE_CHAT_TAUNT; break;
|
||||
case 2: nVoice = VOICE_CHAT_BATTLECRY1; break;
|
||||
case 3: nVoice = VOICE_CHAT_BATTLECRY2; break;
|
||||
case 4: nVoice = VOICE_CHAT_BATTLECRY3; break;
|
||||
case 5: nVoice = VOICE_CHAT_ENEMIES; break;
|
||||
case 6: nVoice = VOICE_CHAT_GROUP; break;
|
||||
case 7: nVoice = VOICE_CHAT_HELP; break;
|
||||
default: nVoice = VOICE_CHAT_ATTACK; break;
|
||||
}
|
||||
PlayVoiceChat(nVoice);
|
||||
}
|
||||
|
||||
// Gets all allies of ourselves to attack oTarget
|
||||
// * oTarget - The target to attack.
|
||||
void AlliesAttack(object oTarget)
|
||||
{
|
||||
if(!GetIsObjectValid(oTarget)) return;
|
||||
int nCnt = 1;
|
||||
object oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, nCnt, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
while(GetIsObjectValid(oAlly) && GetDistanceToObject(oAlly) <= 50.0)
|
||||
{
|
||||
// A slightly modified way to determine a combat round.
|
||||
// * oTarget - The target to attack
|
||||
// * oAttacker - The NPC who you want to determine a combat round, on oTarget
|
||||
DetermineSpeakCombatRoundNotMe(oTarget, oAlly);
|
||||
nCnt++;
|
||||
oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, nCnt, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the nearest PC object
|
||||
object GetNearestPCCreature()
|
||||
{
|
||||
return GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
|
||||
}
|
||||
// Returns the nearest enemy (but doesn't determine if it can see/hear it)
|
||||
object GetNearestEnemyCreature()
|
||||
{
|
||||
return GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
|
||||
}
|
||||
// Returns the nearest friend
|
||||
object GetNearestFriendCreature()
|
||||
{
|
||||
return GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND);
|
||||
}
|
||||
|
||||
// Debug: To compile this script full, uncomment all of the below.
|
||||
/* - Add two "/"'s at the start of this line
|
||||
void main()
|
||||
{
|
||||
return;
|
||||
}
|
||||
//*/
|
@@ -1,723 +0,0 @@
|
||||
/*/////////////////////// [Include - Other AI Functions] ///////////////////////
|
||||
Filename: J_INC_Other_AI
|
||||
///////////////////////// [Include - Other AI Functions] ///////////////////////
|
||||
This contains fuctions and calls for these scripts:
|
||||
nw_c2_default2 - Percieve
|
||||
nw_c2_default3 - On Combat round End (For DetermineCombatRound() only)
|
||||
nw_c2_default4 - Conversation (shout)
|
||||
nw_c2_default5 - Phisical attacked
|
||||
nw_c2_default6 - Damaged
|
||||
nw_c2_default8 - Disturbed
|
||||
nw_c2_defaultb - Spell cast at
|
||||
|
||||
Ones that don't use this use different or no includes.
|
||||
|
||||
HOPEFULLY it will make them faster, if they don't run combat.
|
||||
|
||||
They use Execute Script to initiate combat. (With the override ones
|
||||
initiating the override version, the normal initiateing the normal).
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added to speed up compilings and gather non-combat, or other workings
|
||||
in one place.
|
||||
1.4 - TO DO:
|
||||
-
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is included in other AI files.
|
||||
|
||||
They then use these functions in them scripts.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Include - Other AI Functions] /////////////////////*/
|
||||
|
||||
// All constants.
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Responds to it (like makinging the callers attacker thier target)
|
||||
// Called in OnConversation, and thats it. Use "ShouterFriend" To stop repeated GetIsFriend calls.
|
||||
void RespondToShout(object oShouter, int nShoutIndex);
|
||||
// Gets any possible target which is attacking oShouter (and isn't an ally)
|
||||
// or who oShouter is attacking. oShouter should be a ally.
|
||||
object GetIntruderFromShout(object oShouter);
|
||||
|
||||
// Shouts, or really brings all people in 60.0M(by default) to the "shouter"
|
||||
void ShoutBossShout(object oEnemy);
|
||||
// This sets a morale penalty, to the exsisting one, if there is one.
|
||||
// It will reduce itself after fDuration (or if we die, ETC, it is deleted).
|
||||
// It is deleted at the end of combat as well.
|
||||
void SetMoralePenalty(int nPenalty, float fDuration = 0.0);
|
||||
// Removes nPenalty amount if it can.
|
||||
void RemoveMoralePenalty(int nPenalty);
|
||||
// At 5+ intelligence, we fire off any dispells at oPlaceables location
|
||||
void SearchDispells(object oPlaceable);
|
||||
|
||||
// This MAY make us set a local timer to turn off hiding.
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
void TurnOffHiding(object oIntruder);
|
||||
// Used when we percieve a new enemy and are not in combat. Hides the creature
|
||||
// appropriatly with spawn settings and ability.
|
||||
// - At least it will clear all actions if it doesn't set hiding on
|
||||
void HideOrClear();
|
||||
|
||||
// This MIGHT move to oEnemy
|
||||
// - Checks special actions, such as fleeing, and may run instead!
|
||||
void ActionMoveToEnemy(object oEnemy);
|
||||
|
||||
// Returns TRUE if we have under 0 morale, set to flee.
|
||||
// - They then run! (Badly)
|
||||
int PerceptionFleeFrom(object oEnemy);
|
||||
|
||||
// This wrappers commonly used code for a "Call to arms" type response.
|
||||
// * We know of no enemy, so we will move to oAlly, who either called to
|
||||
// us, or, well, we know of.
|
||||
// * Calls out AI_SHOUT_CALL_TO_ARMS too.
|
||||
void CallToArmsResponse(object oAlly);
|
||||
// This wrappers commonly used code for a "I was attacked" type response.
|
||||
// * We know there will be an enemy - or should be - and if we find one to attack
|
||||
// (using GetIntruderFromShout()) - we attack it (and call another I was attacked)
|
||||
// else, this will run CallToArmsResponse(oAlly);
|
||||
// * Calls out AI_SHOUT_I_WAS_ATTACKED, or AI_SHOUT_CALL_TO_ARMS too.
|
||||
void IWasAttackedResponse(object oAlly);
|
||||
|
||||
/*::///////////////////////////////////////////////
|
||||
//:: Name: ShoutBossShout
|
||||
//::///////////////////////////////////////////////
|
||||
This is used in the OnPercieve, and if we are set to,
|
||||
we will "shout" and bring lots of allies a running
|
||||
//:://///////////////////////////////////////////*/
|
||||
void ShoutBossShout(object oEnemy)
|
||||
{
|
||||
// 1.4 - Added a 5 minute cooldown timer for this. Thusly, if the boss lingers,
|
||||
// so will the big shout they do.
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_BOSS_MONSTER_SHOUT, AI_OTHER_COMBAT_MASTER) &&
|
||||
!GetLocalTimer(AI_TIMER_BOSS_SHOUT_COOLDOWN))
|
||||
{
|
||||
// Get the range (and default to 60.0 M)
|
||||
float fRange = IntToFloat(GetBoundriedAIInteger(AI_BOSS_MONSTER_SHOUT_RANGE, 60, 370));
|
||||
// We loop through nearest not-seen, not-heard allies and get them
|
||||
// to attack the person.
|
||||
int nCnt = 1;
|
||||
// Not seen, not heard...
|
||||
object oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND,
|
||||
OBJECT_SELF, nCnt, CREATURE_TYPE_IS_ALIVE, TRUE,
|
||||
CREATURE_TYPE_PERCEPTION, PERCEPTION_NOT_SEEN_AND_NOT_HEARD);
|
||||
// Get who thier target is.
|
||||
object oThierTarget;
|
||||
while(GetIsObjectValid(oAlly) && GetDistanceToObject(oAlly) <= fRange)
|
||||
{
|
||||
oThierTarget = GetLocalObject(oAlly, AI_TO_ATTACK);
|
||||
// If they are not attacking the enemy, we assing them to attack.
|
||||
if(oThierTarget != oEnemy)
|
||||
{
|
||||
// Can't be in combat.
|
||||
if(!GetIsInCombat(oAlly))
|
||||
{
|
||||
// Set them to move to this
|
||||
SetLocalObject(oAlly, AI_TO_ATTACK, oEnemy);
|
||||
// Make them attack the person
|
||||
SetLocalObject(oAlly, AI_TEMP_SET_TARGET, oEnemy);
|
||||
ExecuteScript(COMBAT_FILE, oAlly);
|
||||
}
|
||||
}
|
||||
nCnt++;
|
||||
oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND,
|
||||
OBJECT_SELF, nCnt, CREATURE_TYPE_IS_ALIVE, TRUE,
|
||||
CREATURE_TYPE_PERCEPTION, PERCEPTION_NOT_SEEN_AND_NOT_HEARD);
|
||||
}
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Speak a string associated with this action being carried out
|
||||
SpeakArrayString(AI_TALK_ON_LEADER_BOSS_SHOUT);
|
||||
}
|
||||
// Remove it for 5 minutes.
|
||||
SetLocalTimer(AI_TIMER_BOSS_SHOUT_COOLDOWN, 300.0);
|
||||
}
|
||||
}
|
||||
// This MAY make us set a local timer to turn off hiding.
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
void TurnOffHiding(object oIntruder)
|
||||
{
|
||||
if(!GetLocalTimer(AI_TIMER_TURN_OFF_HIDE) &&
|
||||
// Are we actually seen/heard or is it just an AOE?
|
||||
(GetObjectSeen(OBJECT_SELF, oIntruder) ||
|
||||
GetObjectHeard(OBJECT_SELF, oIntruder)))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_TURN_OFF_HIDE, 18.0);
|
||||
}
|
||||
}
|
||||
|
||||
// Used when we percieve a new enemy and are not in combat. Hides the creature
|
||||
// appropriatly with spawn settings and ability.
|
||||
// - At least it will clear all actions if it doesn't set hiding on
|
||||
void HideOrClear()
|
||||
{
|
||||
// Spawn in conditions for it
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER) &&
|
||||
GetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH) == FALSE)
|
||||
{
|
||||
// Need skill or force on
|
||||
int nRank = GetSkillRank(SKILL_HIDE);
|
||||
if((nRank - 4 >= GetHitDice(OBJECT_SELF) && nRank >= 7) ||
|
||||
GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
// Use hide
|
||||
ClearAllActions(TRUE);
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_STEALTH, TRUE);
|
||||
// Stop
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Else clear all actions normally.
|
||||
ClearAllActions();
|
||||
}
|
||||
|
||||
/*::///////////////////////////////////////////////
|
||||
//:: Respond To Shouts
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//::///////////////////////////////////////////////
|
||||
Useage:
|
||||
|
||||
//NOTE ABOUT BLOCKERS
|
||||
|
||||
int NW_GENERIC_SHOUT_BLOCKER = 2;
|
||||
|
||||
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
|
||||
|
||||
These are the enemy that attacked the shouter.
|
||||
|
||||
//NOTE ABOUT EVERYTHING ELSE
|
||||
|
||||
I_WAS_ATTACKED = 1;
|
||||
|
||||
If not in combat, attack the attackee of the shouter. Basically the best
|
||||
way to get people to come and help us, if we know of an attacker!
|
||||
* Call this after we call DetermineCombatRound() to make sure that any
|
||||
responses know of the attackers. It doesn't matter in actual fact, but
|
||||
useful anyway.
|
||||
|
||||
CALL_TO_ARMS = 3;
|
||||
|
||||
If not in combat, determine combat round. By default, it should check any
|
||||
allies it can see/hear for thier targets and help them too.
|
||||
* Better if we do not know of a target (and thusly our allies wouldn't know
|
||||
of them as well) so the allies will move to us.
|
||||
|
||||
HELP_MY_FRIEND = 4;
|
||||
|
||||
This is a runner thing. Said when the runner sees the target to run to.
|
||||
Gets a local location, and sets off people to run to it.
|
||||
If no valid area for the location, no moving :-P
|
||||
|
||||
We also shout this if we are fleeing. It will set the person to buff too.
|
||||
|
||||
LEADER_FLEE_NOW = 5
|
||||
|
||||
We flee to a pre-set object or follow the leader (who should be fleeing).
|
||||
|
||||
LEADER_ATTACK_TARGET = 6
|
||||
|
||||
We attack the intruder next round, by setting it as a local object to
|
||||
override other choices.
|
||||
|
||||
I_WAS_KILLED = 7
|
||||
|
||||
If lots are killed in one go - ouch! morale penalty each time someone dies.
|
||||
|
||||
I_WAS_OPENED = 8
|
||||
|
||||
Chests/Doors which say this get the AI onto the tails of those who opened it, OR
|
||||
they get searched! :-)
|
||||
//::///////////////////////////////////////////////
|
||||
// Modified almost completely: Jasperre
|
||||
//:://///////////////////////////////////////////*/
|
||||
// Gets any possible target which is attacking oShouter (and isn't an ally)
|
||||
// or who oShouter is attacking. oShouter should be a ally.
|
||||
object GetIntruderFromShout(object oShouter)
|
||||
{
|
||||
// First, get who they specifically want to attack (IE: Input target the shout
|
||||
// is usually for)
|
||||
object oIntruder = GetLocalObject(oShouter, AI_OBJECT + AI_ATTACK_SPECIFIC_OBJECT);
|
||||
if(GetIgnoreNoFriend(oIntruder) || (!GetObjectSeen(oShouter) && !GetObjectHeard(oShouter)))
|
||||
{
|
||||
// Or, we look for the last melee target (which, at least, will be set)
|
||||
oIntruder = GetLocalObject(oShouter, AI_OBJECT + AI_LAST_MELEE_TARGET);
|
||||
if(GetIgnoreNoFriend(oIntruder) || (!GetObjectSeen(oShouter) && !GetObjectHeard(oShouter)))
|
||||
{
|
||||
// Current actual attack target of the shouter
|
||||
oIntruder = GetAttackTarget(oShouter);
|
||||
if(GetIgnoreNoFriend(oIntruder) || (!GetObjectSeen(oShouter) && !GetObjectHeard(oShouter)))
|
||||
{
|
||||
// Last hostile actor of the shouter
|
||||
oIntruder = GetLastHostileActor(oShouter);
|
||||
if(GetIgnoreNoFriend(oIntruder) || (!GetObjectSeen(oShouter) && !GetObjectHeard(oShouter)))
|
||||
{
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return oIntruder;
|
||||
}
|
||||
// Responds to it (like makinging the callers attacker thier target)
|
||||
// Called in OnConversation, and thats it. Use "ShouterFriend" To stop repeated GetIsFriend calls.
|
||||
void RespondToShout(object oShouter, int nShoutIndex)
|
||||
{
|
||||
// We use oIntruder to set who to attack.
|
||||
object oIntruder;
|
||||
// Check nShoutIndex against known constants
|
||||
switch(nShoutIndex)
|
||||
{
|
||||
// Note: Not checked in sequential order (especially as they are constants).
|
||||
// Instead, it is "Ones which if we are in combat, we still check" first.
|
||||
|
||||
// Attack a specific object which the leader shouted about.
|
||||
case AI_SHOUT_LEADER_ATTACK_TARGET_CONSTANT:
|
||||
{
|
||||
// If a leader, we set it as a local object, nothing more
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER, oShouter))
|
||||
{
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
oIntruder = GetLocalObject(oShouter, AI_ATTACK_SPECIFIC_OBJECT);
|
||||
if(GetObjectSeen(oIntruder))
|
||||
{
|
||||
// Set local object to use in next DetermineCombatRound.
|
||||
// We do not interrupt current acition (EG: Life saving stoneskins!) to re-direct.
|
||||
SetAIObject(AI_ATTACK_SPECIFIC_OBJECT, oIntruder);
|
||||
// 6 second delay.
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
// Leader flee now - mass retreat to those who hear it.
|
||||
case AI_SHOUT_LEADER_FLEE_NOW_CONSTANT:
|
||||
{
|
||||
// If a leader, we set it as a local object, nothing more
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER, oShouter))
|
||||
{
|
||||
// Get who we are going to run too
|
||||
oIntruder = GetLocalObject(oShouter, AI_FLEE_TO);
|
||||
|
||||
// RUN! If intruder set is over 5.0M or no valid intruder
|
||||
ClearAllActions();
|
||||
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
// Set to run
|
||||
SetCurrentAction(AI_SPECIAL_ACTIONS_FLEE);
|
||||
// Turn on fleeing visual effect
|
||||
ApplyFleeingVisual();
|
||||
|
||||
// Ignore talk for 12 seconds
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 12.0);
|
||||
|
||||
// If valid, we run to the intruder
|
||||
if(GetIsObjectValid(oIntruder))
|
||||
{
|
||||
SetAIObject(AI_FLEE_TO, oIntruder);
|
||||
ActionMoveToObject(oIntruder);
|
||||
}
|
||||
else // Else, we will just follow our leader!
|
||||
{
|
||||
SetAIObject(AI_FLEE_TO, oShouter);
|
||||
ActionForceFollowObject(oShouter, 3.0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
// All others (IE: We need to not be in combat for these)
|
||||
// Anything that requires "DetermineCombatRound()" is here.
|
||||
|
||||
// If the shout is number 8, it is "I was opened" and so can only be a
|
||||
// placeable or door.
|
||||
case AI_SHOUT_I_WAS_OPENED_CONSTANT:
|
||||
{
|
||||
// If we are already attacking, we ignore this shout.
|
||||
if(CannotPerformCombatRound()) return;
|
||||
|
||||
// We need somewhat complexe here - to get thier opener.
|
||||
int nType = GetObjectType(oShouter);
|
||||
// Check object type. If not a placeable nor door - stop script.
|
||||
if(nType == OBJECT_TYPE_PLACEABLE ||
|
||||
nType == OBJECT_TYPE_DOOR)
|
||||
{
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
// Now, we assign the placeable/door to set thier opener.
|
||||
// We do this by just executing a script that does it.
|
||||
ExecuteScript(FILE_SET_OPENER, oShouter);
|
||||
// We can immediantly get this would-be attacker!
|
||||
oIntruder = GetLocalObject(oShouter, AI_PLACEABLE_LAST_OPENED_BY);
|
||||
if(GetIsObjectValid(oIntruder))
|
||||
{
|
||||
// Attack
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oShouter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move to the object who shouted in detect mode
|
||||
SetActionMode(OBJECT_SELF, ACTION_MODE_DETECT, TRUE);
|
||||
ActionMoveToObject(oShouter, TRUE);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
// Call to arms requires nothing special. It is only called if
|
||||
// There is no target the shouter has to attack specifically, rather then
|
||||
// "I_WAS_ATTACKED" which would have.
|
||||
case AI_SHOUT_CALL_TO_ARMS_CONSTANT:
|
||||
{
|
||||
// If we are already attacking, we ignore this shout.
|
||||
if(CannotPerformCombatRound()) return;
|
||||
|
||||
// Ignore for 6 seconds
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
// do standard Call to Arms response - IE: Move to oShouter
|
||||
CallToArmsResponse(oShouter);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
// "Help my friend" is when a runner is running off (sorta fleeing) to
|
||||
// get help. This will move to the location set on them to reinforce.
|
||||
case AI_SHOUT_HELP_MY_FRIEND_CONSTANT:
|
||||
{
|
||||
// If we are already attacking, we ignore this shout.
|
||||
if(CannotPerformCombatRound()) return;
|
||||
|
||||
// Ignore things for 6 seconds
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
|
||||
// We move to where the runner/shouter wants us.
|
||||
location lMoveTo = GetLocalLocation(oShouter, AI_LOCATION + AI_HELP_MY_FRIEND_LOCATION);
|
||||
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
// If the location is valid
|
||||
if(GetIsObjectValid(GetAreaFromLocation(lMoveTo)))
|
||||
{
|
||||
// New special action, but one that is overrided by combat
|
||||
SetCurrentAction(AI_SPECIAL_ACTIONS_MOVE_TO_COMBAT);
|
||||
SetAIObject(AI_MOVE_TO_COMBAT_OBJECT, oShouter);
|
||||
SetAILocation(AI_MOVE_TO_COMBAT_LOCATION, lMoveTo);
|
||||
|
||||
// Move to the location of the fight, attack.
|
||||
ClearAllActions();
|
||||
// Move to the fights location
|
||||
ActionMoveToLocation(lMoveTo, TRUE);
|
||||
// When we see someone fighting, we'll DCR
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else, if we do not know of the friends attackers, or the location
|
||||
// they are at, we will follow them without casting any preperation
|
||||
// spells.
|
||||
ClearAllActions();
|
||||
ActionForceFollowObject(oShouter, 3.0);
|
||||
// When we see an enemy, we'll attack!
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
// "I was attacked" is called when a creature is hurt or sees an enemy,
|
||||
// and starts to attack them. This means they know who the enemy is -
|
||||
// and thusly we can get it from them (Ususally GetLastHostileActor()
|
||||
// "I was killed" is the same, but applies a morale penalty too
|
||||
case AI_SHOUT_I_WAS_ATTACKED_CONSTANT:
|
||||
case AI_SHOUT_I_WAS_KILLED_CONSTANT:
|
||||
{
|
||||
// If it was "I was killed", we apply a short morale penatly
|
||||
// Penalty is "Hit dice / 4 + 1" (so always 1 minimum) for 18 seconds.
|
||||
if(nShoutIndex == AI_SHOUT_I_WAS_KILLED_CONSTANT)
|
||||
{
|
||||
SetMoralePenalty(GetHitDice(oShouter)/4 + 1, 18.0);
|
||||
}
|
||||
|
||||
// If we are already attacking, we ignore this shout.
|
||||
if(CannotPerformCombatRound()) return;
|
||||
|
||||
// 70. "[Shout] Reacting To Shout. [ShoutNo.] " + IntToString(iInput) + " [Shouter] " + GetName(oInput)
|
||||
DebugActionSpeakByInt(70, oShouter, nShoutIndex);
|
||||
|
||||
// Ignore for 6 seconds
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
|
||||
// Respond to oShouter's request for help - find thier target, and
|
||||
// attack!
|
||||
IWasAttackedResponse(oShouter);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// At 5+ intelligence, we fire off any dispells at oPlaceables location
|
||||
void SearchDispells(object oPlaceable)
|
||||
{
|
||||
// No dispelling at low intelligence.
|
||||
if(GetBoundriedAIInteger(AI_INTELLIGENCE) < 5) return;
|
||||
location lPlace = GetLocation(oPlaceable);
|
||||
// Move closer if not seen.
|
||||
if(!GetObjectSeen(oPlaceable))
|
||||
{
|
||||
// Move nearer - 6 M is out of the dispell range
|
||||
ActionMoveToObject(oPlaceable, TRUE, 6.0);
|
||||
}
|
||||
// Dispell if we have any - at the location of oPlaceable.
|
||||
if(GetHasSpell(SPELL_LESSER_DISPEL))
|
||||
{
|
||||
ActionCastSpellAtLocation(SPELL_LESSER_DISPEL, lPlace);
|
||||
}
|
||||
else if(GetHasSpell(SPELL_DISPEL_MAGIC))
|
||||
{
|
||||
ActionCastSpellAtLocation(SPELL_DISPEL_MAGIC, lPlace);
|
||||
}
|
||||
else if(GetHasSpell(SPELL_GREATER_DISPELLING))
|
||||
{
|
||||
ActionCastSpellAtLocation(SPELL_GREATER_DISPELLING, lPlace);
|
||||
}
|
||||
else if(GetHasSpell(SPELL_MORDENKAINENS_DISJUNCTION))
|
||||
{
|
||||
ActionCastSpellAtLocation(SPELL_MORDENKAINENS_DISJUNCTION, lPlace);
|
||||
}
|
||||
}
|
||||
|
||||
// This sets a morale penalty, to the exsisting one, if there is one.
|
||||
// It will reduce itself (by the penalty) after fDuration (or if we die, ETC, it is deleted).
|
||||
// It is deleted at the end of combat as well.
|
||||
void SetMoralePenalty(int nPenalty, float fDuration = 0.0)
|
||||
{
|
||||
int nNewPenalty = GetAIInteger(AI_MORALE_PENALTY) + nPenalty;
|
||||
SetAIInteger(AI_MORALE_PENALTY, nNewPenalty);
|
||||
DelayCommand(fDuration, RemoveMoralePenalty(nPenalty));
|
||||
}
|
||||
// Removes nPenalty amount if it can.
|
||||
void RemoveMoralePenalty(int nPenalty)
|
||||
{
|
||||
int nNewPenalty = GetAIInteger(AI_MORALE_PENALTY) - nPenalty;
|
||||
if(nNewPenalty > 0 && !GetIsDead(OBJECT_SELF))
|
||||
{
|
||||
SetAIInteger(AI_MORALE_PENALTY, nNewPenalty);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteAIInteger(AI_MORALE_PENALTY);
|
||||
}
|
||||
}
|
||||
|
||||
// This MIGHT move to oEnemy
|
||||
// - Checks special actions, such as fleeing, and may run instead!
|
||||
void ActionMoveToEnemy(object oEnemy)
|
||||
{
|
||||
// Make sure that we are not fleeing badly (-1 morale from all enemies)
|
||||
if(GetIsEnemy(oEnemy))
|
||||
{
|
||||
// -1 morale, flee
|
||||
if(PerceptionFleeFrom(oEnemy)) return;
|
||||
}
|
||||
if(GetIsPerformingSpecialAction())
|
||||
{
|
||||
// Stop if we have an action we don't want to override
|
||||
return;
|
||||
}
|
||||
// End default is move to the enemy
|
||||
ClearAllActions();
|
||||
ActionMoveToObject(oEnemy, TRUE);
|
||||
// combat round to heal/search/whatever
|
||||
if(!GetFactionEqual(oEnemy))
|
||||
{
|
||||
ActionDoCommand(DetermineCombatRound(oEnemy));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns TRUE if we have under 0 morale, set to flee.
|
||||
// - They then run! (Badly)
|
||||
int PerceptionFleeFrom(object oEnemy)
|
||||
{
|
||||
object oRunTarget = oEnemy;
|
||||
if(GetAIInteger(AI_INTELLIGENCE) < FALSE)
|
||||
{
|
||||
// Valid run from target
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetLastHostileActor();
|
||||
if(!GetIsObjectValid(oRunTarget) || GetIsDead(oRunTarget))
|
||||
{
|
||||
// Stop - nothing to flee from!
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run from enemy
|
||||
ClearAllActions();
|
||||
ActionMoveAwayFromObject(oRunTarget, TRUE, 50.0);
|
||||
return TRUE;
|
||||
}
|
||||
// 0 or more morale.
|
||||
return FALSE;
|
||||
}
|
||||
// This wrappers commonly used code for a "Call to arms" type response.
|
||||
// * We know of no enemy, so we will move to oAlly, who either called to
|
||||
// us, or, well, we know of.
|
||||
// * Calls out AI_SHOUT_CALL_TO_ARMS too.
|
||||
void CallToArmsResponse(object oAlly)
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// If we are over 2 meters away from oShouter, we move to them using
|
||||
// the special action
|
||||
if(GetDistanceToObject(oAlly) > 2.0 || !GetObjectSeen(oAlly))
|
||||
{
|
||||
// New special action, but one that is overrided by combat
|
||||
location lAlly = GetLocation(oAlly);
|
||||
SetCurrentAction(AI_SPECIAL_ACTIONS_MOVE_TO_COMBAT);
|
||||
SetAIObject(AI_MOVE_TO_COMBAT_OBJECT, oAlly);
|
||||
SetAILocation(AI_MOVE_TO_COMBAT_LOCATION, lAlly);
|
||||
|
||||
// Move to the location of the fight, attack.
|
||||
ClearAllActions();
|
||||
// Move to the fights location
|
||||
ActionMoveToLocation(lAlly, TRUE);
|
||||
// When we see someone fighting, we'll DCR
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine it anyway - we will search around oShouter
|
||||
// if nothing is found...but we are near to the shouter
|
||||
DetermineCombatRound(oAlly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// This wrappers commonly used code for a "I was attacked" type response.
|
||||
// * We know there will be an enemy - or should be - and if we find one to attack
|
||||
// (using GetIntruderFromShout()) - we attack it (and call another I was attacked)
|
||||
// else, this will run CallToArmsResponse(oAlly);
|
||||
// * Calls out AI_SHOUT_I_WAS_ATTACKED, or AI_SHOUT_CALL_TO_ARMS too.
|
||||
void IWasAttackedResponse(object oAlly)
|
||||
{
|
||||
// Get the indruder. This is either who oShouter is currently attacking,
|
||||
// or the last attacker of them.
|
||||
object oIntruder = GetIntruderFromShout(oAlly);
|
||||
|
||||
// If valid, of course attack!
|
||||
if(GetIsObjectValid(oIntruder))
|
||||
{
|
||||
// 1.4 Note:
|
||||
// * It used to check "Are they seen". Basically, this is redudant
|
||||
// with the checks used in DetermineCombatRound(). It will do the
|
||||
// searching using oIntruder whatever.
|
||||
|
||||
// Stop, and attack
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oIntruder);
|
||||
|
||||
// Shout I was attacked - we've set our intruder now
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
return;
|
||||
}
|
||||
// If invalid, we act as if it was "Call to arms" type thing.
|
||||
// Call to arms is better to use normally, of course.
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// We see if they are attacking anything:
|
||||
oIntruder = GetAttackTarget(oAlly);
|
||||
if(!GetIsObjectValid(oIntruder))
|
||||
{
|
||||
oIntruder = GetLocalObject(oAlly, AI_OBJECT + AI_LAST_MELEE_TARGET);
|
||||
}
|
||||
|
||||
// If valid, we will move to a point bisecting the intruder and oAlly, or
|
||||
// move to oAlly. Should get interrupted once we see the attack target.
|
||||
// * NEED TO TEST
|
||||
if(GetIsObjectValid(oIntruder))
|
||||
{
|
||||
// New special action, but one that is overrided by combat
|
||||
vector vTarget = GetPosition(oIntruder);
|
||||
vector vSource = GetPosition(OBJECT_SELF);
|
||||
vector vDirection = vTarget - vSource;
|
||||
float fDistance = VectorMagnitude(vDirection) / 2.0;
|
||||
vector vPoint = VectorNormalize(vDirection) * fDistance + vSource;
|
||||
location lTarget = Location(GetArea(OBJECT_SELF), vPoint, DIRECTION_NORTH);
|
||||
|
||||
SetCurrentAction(AI_SPECIAL_ACTIONS_MOVE_TO_COMBAT);
|
||||
SetAIObject(AI_MOVE_TO_COMBAT_OBJECT, oAlly);
|
||||
SetAILocation(AI_MOVE_TO_COMBAT_LOCATION, lTarget);
|
||||
|
||||
// Move to the location of the fight, attack.
|
||||
ClearAllActions();
|
||||
// Move to the fights location
|
||||
ActionMoveToLocation(lTarget, TRUE);
|
||||
// When we see someone fighting, we'll DCR
|
||||
return;
|
||||
}
|
||||
// If we are over 2 meters away from oShouter, we move to them using
|
||||
// the special action
|
||||
else if(GetDistanceToObject(oAlly) > 2.0 || !GetObjectSeen(oAlly))
|
||||
{
|
||||
// New special action, but one that is overrided by combat
|
||||
location lAlly = GetLocation(oAlly);
|
||||
SetCurrentAction(AI_SPECIAL_ACTIONS_MOVE_TO_COMBAT);
|
||||
SetAIObject(AI_MOVE_TO_COMBAT_OBJECT, oAlly);
|
||||
SetAILocation(AI_MOVE_TO_COMBAT_LOCATION, lAlly);
|
||||
|
||||
// Move to the location of the fight, attack.
|
||||
ClearAllActions();
|
||||
// Move to the fights location
|
||||
ActionMoveToLocation(lAlly, TRUE);
|
||||
// When we see someone fighting, we'll DCR
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine it anyway - we will search around oShouter
|
||||
// if nothing is found...but we are near to the shouter
|
||||
DetermineCombatRound(oAlly);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Debug: To compile this script full, uncomment all of the below.
|
||||
/* - Add two "/"'s at the start of this line
|
||||
void main()
|
||||
{
|
||||
return;
|
||||
}
|
||||
//*/
|
@@ -1,479 +0,0 @@
|
||||
/*/////////////////////// [Include - Set Effects] //////////////////////////////
|
||||
Filename: J_INC_SetEffects
|
||||
///////////////////////// [Include - Set Effects] //////////////////////////////
|
||||
This can be executed on a PC or NPC, and sets what thier current effects
|
||||
are - the hostile ones.
|
||||
|
||||
It is executed on a PC every 6 seconds in combat, delayed by a timer,
|
||||
by other NPCs who want to target them.
|
||||
|
||||
It is meant to be more efficient then doing countless checks against other
|
||||
NPCs and PCs for what effects they already have on them.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added
|
||||
1.4 - Changed so fear and stun was seperate.
|
||||
Uncommandable still is now for any uncommandable effects.
|
||||
|
||||
- TO DO
|
||||
- Make the ability decrease into "light" "major" and so on, about 4
|
||||
ratings, each set as more decreases are present.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
ExecuteScript - might not work faster. If so, it is easy to add into the
|
||||
generic AI and have oTarget to set to.
|
||||
|
||||
It searches the code and sets 3 custom integers, but only once (so not
|
||||
during the loop)
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A
|
||||
///////////////////////// [Include - Set Effects] ////////////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
#include "prc_inc_racial"
|
||||
|
||||
//void main (){}
|
||||
|
||||
// List (use Global to not conflict with the nwscript.nss!)
|
||||
const int GlobalEffectUncommandable = 0x00000001;// Stun. Sleep. Fear. Turning. Paralsis. Petrify.
|
||||
const int GlobalEffectSilenced = 0x00000002;// Eeek!
|
||||
const int GlobalEffectSlowed = 0x00000004;// Stop with haste.
|
||||
const int GlobalEffectUltravision = 0x00000008;
|
||||
const int GlobalEffectSeeInvisible = 0x00000010; // NOT Inc. Trueseeing
|
||||
const int GlobalEffectTrueSeeing = 0x00000020;
|
||||
const int GlobalEffectTimestop = 0x00000040;
|
||||
const int GlobalEffectInvisible = 0x00000080;
|
||||
const int GlobalEffectDeaf = 0x00000100;// Ack!
|
||||
const int GlobalEffectHaste = 0x00000200;
|
||||
const int GlobalEffectPolymorph = 0x00000400;// Only attack
|
||||
const int GlobalEffectBlindness = 0x00000800;// Oh no! Cannot see others to cast spells.
|
||||
const int GlobalEffectDisease = 0x00001000;
|
||||
const int GlobalEffectPoison = 0x00002000;
|
||||
const int GlobalEffectCurse = 0x00004000;
|
||||
const int GlobalEffectNegativeLevel = 0x00008000;
|
||||
const int GlobalEffectEntangle = 0x00010000;
|
||||
const int GlobalEffectMovementSpeedDecrease = 0x00020000;
|
||||
const int GlobalEffectDarkness = 0x00040000;// Noo! Need ultravision!
|
||||
const int GlobalEffectDazed = 0x00080000;// Special: 1.30 patch, we can move!
|
||||
const int GlobalEffectEthereal = 0x00100000;
|
||||
const int GlobalEffectPetrify = 0x00200000;
|
||||
const int GlobalEffectParalyze = 0x00400000;// Divided from Uncommandable for healing of
|
||||
const int GlobalEffectSpellFailure = 0x00800000;// Makes sure spells are not cast under high failure.
|
||||
const int GlobalEffectDamageShield = 0x01000000;// All damage shields
|
||||
const int GlobalEffectFear = 0x02000000;// 1.4. Remove fear + G.Rest. Removes.
|
||||
const int GlobalEffectStun = 0x04000000;// 1.4. G.Rest. Removes.
|
||||
//int GlobalEffectAbilityDecrease = 0; // In combat include
|
||||
|
||||
// These are Globals for spell effects, to not csat them on us again, and to
|
||||
// speed things up...
|
||||
// These are *good* spells. This effect is only set up on us.
|
||||
const int GlobalHasStoneSkinProtections = 0x00000001;
|
||||
const int GlobalHasElementalProtections = 0x00000002;
|
||||
const int GlobalHasVisageProtections = 0x00000004;
|
||||
const int GlobalHasMantalProtections = 0x00000008;
|
||||
const int GlobalHasGlobeProtections = 0x00000010;
|
||||
const int GlobalHasMindResistanceProtections = 0x00000020;
|
||||
const int GlobalHasAidingSpell = 0x00000040;
|
||||
const int GlobalHasRangedConsealment = 0x00000080;
|
||||
const int GlobalHasRageSpells = 0x00000100;
|
||||
const int GlobalHasBullsStrengthSpell = 0x00000200;
|
||||
const int GlobalHasCatsGraceSpell = 0x00000400;
|
||||
const int GlobalHasClairaudienceSpell = 0x00000800;
|
||||
const int GlobalHasDeathWardSpell = 0x00001000;
|
||||
const int GlobalHasDivinePowerSpell = 0x00002000;
|
||||
const int GlobalHasEaglesSpledorSpell = 0x00004000;
|
||||
const int GlobalHasEnduranceSpell = 0x00008000;
|
||||
const int GlobalHasFoxesCunningSpell = 0x00010000;
|
||||
const int GlobalHasProtectionEvilSpell = 0x00020000;
|
||||
const int GlobalHasProtectionGoodSpell = 0x00040000;
|
||||
const int GlobalHasLightSpell = 0x00080000;
|
||||
const int GlobalHasConsealmentSpells = 0x00100000;// Displacement
|
||||
const int GlobalHasProtectionSpellsSpell = 0x00200000;
|
||||
const int GlobalHasRegenerateSpell = 0x00400000;
|
||||
const int GlobalHasOwlsWisdomSpell = 0x00800000;
|
||||
const int GlobalHasSpellResistanceSpell = 0x01000000;
|
||||
const int GlobalHasSpellWarCrySpell = 0x02000000;
|
||||
//const int GlobalHasElementalShieldSpell = 0x04000000;// Is general effect
|
||||
const int GlobalHasDomainSpells = 0x08000000;
|
||||
const int GlobalHasDeflectionACSpell = 0x10000000;
|
||||
const int GlobalHasNaturalACSpell = 0x20000000;
|
||||
const int GlobalHasOtherACSpell = 0x40000000;
|
||||
const int GlobalHasWeaponHelpSpell = 0x80000000;
|
||||
|
||||
// Other, AOE ones
|
||||
//const int GlobalHasAreaEffectDamaging = 0x04000000;
|
||||
//const int GlobalHasAreaEffectImpeding = 0x08000000;
|
||||
|
||||
int TempEffectHex, TempSpellHex;
|
||||
|
||||
// Sets up an effects thing to that
|
||||
void AI_SetTargetHasEffect(int nEffectHex);
|
||||
// Sets we have spell iSpellHex's effects.
|
||||
void AI_SetWeHaveSpellsEffect(int nSpellHex);
|
||||
// Sets up effects on oTarget
|
||||
void AI_SetEffectsOnTarget(object oTarget = OBJECT_SELF);
|
||||
|
||||
|
||||
// Simple return TRUE if it matches hex.
|
||||
// - Effects tested on oTarget
|
||||
int AI_GetAIHaveEffect(int nEffectHex, object oTarget = OBJECT_SELF);
|
||||
// Simple return TRUE if it matches hex.
|
||||
// * Can only be used on ourself.
|
||||
int AI_GetAIHaveSpellsEffect(int nSpellHex);
|
||||
|
||||
// Sets up an effects thing to that
|
||||
void AI_SetTargetHasEffect(int nEffectHex)
|
||||
{
|
||||
TempEffectHex = TempEffectHex | nEffectHex;
|
||||
}
|
||||
// Sets we have spell iSpellHex's effects.
|
||||
void AI_SetWeHaveSpellsEffect(int nSpellHex)
|
||||
{
|
||||
TempSpellHex = TempSpellHex | nSpellHex;
|
||||
}
|
||||
|
||||
// Simple return TRUE if it matches hex.
|
||||
// - Effects tested on oTarget
|
||||
int AI_GetAIHaveEffect(int nEffectHex, object oTarget = OBJECT_SELF)
|
||||
{
|
||||
return (GetLocalInt(oTarget, AI_EFFECT_HEX) & nEffectHex);
|
||||
|
||||
}
|
||||
// Simple return TRUE if it matches hex.
|
||||
// * Can only be used on ourself.
|
||||
int AI_GetAIHaveSpellsEffect(int nSpellHex)
|
||||
{
|
||||
return (GetLocalInt(OBJECT_SELF, AI_SPELL_HEX) & nSpellHex);
|
||||
}
|
||||
|
||||
// Sets up effects on oTarget
|
||||
void AI_SetEffectsOnTarget(object oTarget = OBJECT_SELF)
|
||||
{
|
||||
TempEffectHex = FALSE;
|
||||
TempSpellHex = FALSE;
|
||||
// Checks our effects once.
|
||||
effect eCheck = GetFirstEffect(oTarget);
|
||||
int nEffect, nEffectAbilityDecrease, nSpellID;
|
||||
// EFFECTS:
|
||||
// For ALL targets (that we will use), we set up effects on a system of Hexes.
|
||||
// like spawn in things. Replaces GetHasSpellEffect, except genralising -
|
||||
// IE we will NOT cast more than one of the stoneskin type things at once.
|
||||
while(GetIsEffectValid(eCheck))
|
||||
{
|
||||
nEffect = GetEffectType(eCheck);
|
||||
switch(nEffect)
|
||||
{
|
||||
case EFFECT_TYPE_INVALIDEFFECT:
|
||||
case EFFECT_TYPE_VISUALEFFECT:
|
||||
// Don't check these for spell values.
|
||||
break;
|
||||
case EFFECT_TYPE_PARALYZE: // Also makes you uncommandable
|
||||
{
|
||||
AI_SetTargetHasEffect(GlobalEffectParalyze);
|
||||
AI_SetTargetHasEffect(GlobalEffectUncommandable);
|
||||
}
|
||||
break;
|
||||
case EFFECT_TYPE_STUNNED: // Also makes you uncommandable
|
||||
{
|
||||
AI_SetTargetHasEffect(GlobalEffectStun);
|
||||
AI_SetTargetHasEffect(GlobalEffectUncommandable);
|
||||
}
|
||||
break;
|
||||
case EFFECT_TYPE_FRIGHTENED: // Also makes you uncommandable
|
||||
{
|
||||
AI_SetTargetHasEffect(GlobalEffectFear);
|
||||
AI_SetTargetHasEffect(GlobalEffectUncommandable);
|
||||
}
|
||||
break;
|
||||
// * Cannot remove these, but make you unable to move.
|
||||
case EFFECT_TYPE_SLEEP:
|
||||
case EFFECT_TYPE_TURNED:
|
||||
case EFFECT_TYPE_DISAPPEARAPPEAR:// Added for dragon flying
|
||||
case EFFECT_TYPE_CONFUSED:// 1.4 added. wasn't in before
|
||||
AI_SetTargetHasEffect(GlobalEffectUncommandable);
|
||||
break;
|
||||
case EFFECT_TYPE_DAZED:
|
||||
AI_SetTargetHasEffect(GlobalEffectDazed);
|
||||
break;
|
||||
case EFFECT_TYPE_SILENCE:
|
||||
AI_SetTargetHasEffect(GlobalEffectSilenced);
|
||||
break;
|
||||
case EFFECT_TYPE_SLOW:
|
||||
AI_SetTargetHasEffect(GlobalEffectSlowed);
|
||||
break;
|
||||
case EFFECT_TYPE_ULTRAVISION:
|
||||
AI_SetTargetHasEffect(GlobalEffectUltravision);
|
||||
break;
|
||||
case EFFECT_TYPE_SEEINVISIBLE:
|
||||
AI_SetTargetHasEffect(GlobalEffectSeeInvisible);
|
||||
break;
|
||||
// Caused by Beholder things mainly, but this stops any spell being
|
||||
// cast, not just, for example, arcane spells cast in armor.
|
||||
case EFFECT_TYPE_SPELL_FAILURE:
|
||||
AI_SetTargetHasEffect(GlobalEffectSpellFailure);
|
||||
break;
|
||||
// Penetrates darkness.
|
||||
case EFFECT_TYPE_TRUESEEING:
|
||||
AI_SetTargetHasEffect(GlobalEffectTrueSeeing);
|
||||
break;
|
||||
// Timestop - IE don't cast same spell twice.
|
||||
case EFFECT_TYPE_TIMESTOP:
|
||||
AI_SetTargetHasEffect(GlobalEffectTimestop);
|
||||
break;
|
||||
// Invisibility/Improved (although improved only uses normal in the spell)
|
||||
// Sneak attack/whatever :-)
|
||||
// - include the spell EFFECT_TYPE_ETHEREAL.
|
||||
case EFFECT_TYPE_INVISIBILITY:
|
||||
case EFFECT_TYPE_IMPROVEDINVISIBILITY:
|
||||
AI_SetTargetHasEffect(GlobalEffectInvisible);
|
||||
break;
|
||||
// Deaf - spell failing of 20%, but still cast.
|
||||
case EFFECT_TYPE_DEAF:
|
||||
AI_SetTargetHasEffect(GlobalEffectDeaf);
|
||||
break;
|
||||
// Special invis.
|
||||
case EFFECT_TYPE_ETHEREAL:
|
||||
AI_SetTargetHasEffect(GlobalEffectEthereal);
|
||||
break;
|
||||
// Haste - so don't cast haste again and whatever.
|
||||
case EFFECT_TYPE_HASTE:
|
||||
AI_SetTargetHasEffect(GlobalEffectHaste);
|
||||
break;
|
||||
// Haste - so don't cast haste again and whatever.
|
||||
case EFFECT_TYPE_POLYMORPH:
|
||||
AI_SetTargetHasEffect(GlobalEffectPolymorph);
|
||||
break;
|
||||
// Blindness - oh no, can't see, only hear!
|
||||
case EFFECT_TYPE_BLINDNESS:
|
||||
AI_SetTargetHasEffect(GlobalEffectBlindness);
|
||||
break;
|
||||
// Damage shield = Elemental shield, wounding whispers, Death armor, mestals
|
||||
// sheth and so on.
|
||||
case EFFECT_TYPE_ELEMENTALSHIELD:
|
||||
AI_SetTargetHasEffect(GlobalEffectDamageShield);
|
||||
break;
|
||||
// Things we may want to remove VIA cirtain spells, we set here - may as well.
|
||||
// Same setting as any other.
|
||||
// IF we can remove it (not confusion ETC of course) then we set it.
|
||||
case EFFECT_TYPE_DISEASE:
|
||||
AI_SetTargetHasEffect(GlobalEffectDisease);
|
||||
break;
|
||||
case EFFECT_TYPE_POISON:
|
||||
AI_SetTargetHasEffect(GlobalEffectPoison);
|
||||
break;
|
||||
// SoU Petrify
|
||||
// Note: Also makes them uncommandable
|
||||
case EFFECT_TYPE_PETRIFY:
|
||||
{
|
||||
AI_SetTargetHasEffect(GlobalEffectPetrify);
|
||||
AI_SetTargetHasEffect(GlobalEffectUncommandable);
|
||||
}
|
||||
break;
|
||||
case EFFECT_TYPE_CURSE:
|
||||
AI_SetTargetHasEffect(GlobalEffectCurse);
|
||||
break;
|
||||
case EFFECT_TYPE_NEGATIVELEVEL:
|
||||
AI_SetTargetHasEffect(GlobalEffectNegativeLevel);
|
||||
break;
|
||||
case EFFECT_TYPE_ABILITY_DECREASE:
|
||||
case EFFECT_TYPE_AC_DECREASE:
|
||||
case EFFECT_TYPE_ATTACK_DECREASE:
|
||||
case EFFECT_TYPE_DAMAGE_DECREASE:
|
||||
case EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE:
|
||||
case EFFECT_TYPE_SAVING_THROW_DECREASE:
|
||||
case EFFECT_TYPE_SPELL_RESISTANCE_DECREASE:
|
||||
case EFFECT_TYPE_SKILL_DECREASE:
|
||||
// Special - we add one to this, to determine when to use restoration
|
||||
nEffectAbilityDecrease++;
|
||||
break;
|
||||
case EFFECT_TYPE_ENTANGLE:
|
||||
AI_SetTargetHasEffect(GlobalEffectEntangle);
|
||||
break;
|
||||
case EFFECT_TYPE_MOVEMENT_SPEED_DECREASE:
|
||||
AI_SetTargetHasEffect(GlobalEffectMovementSpeedDecrease);
|
||||
break;
|
||||
case EFFECT_TYPE_DARKNESS:
|
||||
AI_SetTargetHasEffect(GlobalEffectDarkness);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Check spells *we* (1.4 change: now checks OBJECT_SELF)
|
||||
// have on...so we don't cast over them!
|
||||
nSpellID = GetEffectSpellId(eCheck);
|
||||
if(nSpellID != -1 && oTarget == OBJECT_SELF)
|
||||
{
|
||||
switch(nSpellID)
|
||||
{
|
||||
// All weapon things are on one variable. We cast the best.
|
||||
case SPELL_MAGIC_WEAPON:
|
||||
case SPELL_BLESS_WEAPON:
|
||||
case SPELL_FLAME_WEAPON:
|
||||
case SPELL_GREATER_MAGIC_WEAPON:
|
||||
case SPELL_BLACKSTAFF:
|
||||
case SPELL_BLADE_THIRST:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasWeaponHelpSpell);
|
||||
break;
|
||||
case SPELL_ENDURE_ELEMENTS:
|
||||
case SPELL_ENERGY_BUFFER:
|
||||
case SPELL_RESIST_ELEMENTS:
|
||||
case SPELL_PROTECTION_FROM_ELEMENTS:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasElementalProtections);
|
||||
break;
|
||||
case SPELL_BARKSKIN:
|
||||
case SPELL_STONE_BONES: // +3 to undead
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasNaturalACSpell);
|
||||
break;
|
||||
case SPELL_SHIELD:
|
||||
case SPELL_DIVINE_SHIELD:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasDeflectionACSpell);
|
||||
break;
|
||||
case SPELL_EPIC_MAGE_ARMOR:// Epic spell +20 to AC.
|
||||
case SPELL_MAGE_ARMOR:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasOtherACSpell);
|
||||
break;
|
||||
case SPELL_ENTROPIC_SHIELD:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasRangedConsealment);
|
||||
break;
|
||||
case AI_SPELL_EPIC_WARDING:
|
||||
case SPELL_STONESKIN:
|
||||
case SPELL_GREATER_STONESKIN:
|
||||
case SPELL_PREMONITION:
|
||||
case SPELL_SHADES_STONESKIN: // Stoneskin one: 342
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasStoneSkinProtections);
|
||||
break;
|
||||
case SPELL_GHOSTLY_VISAGE:
|
||||
case SPELL_SHADOW_SHIELD:
|
||||
case SPELL_ETHEREAL_VISAGE:
|
||||
case SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE: // one: 351 is gostly visage. Speeds up not using number
|
||||
case SPELL_SHADOW_EVADE: // Shadow dancer
|
||||
case SPELLABILITY_AS_GHOSTLY_VISAGE: // Assassin
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasVisageProtections);
|
||||
break;
|
||||
case SPELL_GREATER_SPELL_MANTLE:
|
||||
case SPELL_SPELL_MANTLE:
|
||||
case SPELL_LESSER_SPELL_MANTLE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasMantalProtections);
|
||||
break;
|
||||
case SPELL_MINOR_GLOBE_OF_INVULNERABILITY:
|
||||
case SPELL_GLOBE_OF_INVULNERABILITY:
|
||||
case SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasGlobeProtections);
|
||||
break;
|
||||
case SPELL_AID:
|
||||
case SPELL_PRAYER:
|
||||
case SPELL_BLESS:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasAidingSpell);
|
||||
break;
|
||||
case SPELL_BULLS_STRENGTH:
|
||||
case SPELL_GREATER_BULLS_STRENGTH:
|
||||
case SPELLABILITY_BG_BULLS_STRENGTH: // Blackguard
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasBullsStrengthSpell);
|
||||
break;
|
||||
case SPELL_CATS_GRACE:
|
||||
case SPELL_GREATER_CATS_GRACE:
|
||||
case AI_SPELLABILITY_HARPER_CATS_GRACE: // Harper
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasCatsGraceSpell);
|
||||
break;
|
||||
case SPELL_CLAIRAUDIENCE_AND_CLAIRVOYANCE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasClairaudienceSpell);
|
||||
break;
|
||||
case SPELL_CLARITY:
|
||||
case SPELL_LESSER_MIND_BLANK:
|
||||
case SPELL_MIND_BLANK:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasMindResistanceProtections);
|
||||
break;
|
||||
case SPELL_DEATH_WARD:
|
||||
case SPELL_UNDEATHS_ETERNAL_FOE:// Similar to death ward. Got more things.
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasDeathWardSpell);
|
||||
break;
|
||||
case SPELL_DISPLACEMENT:// 50% consealment
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasConsealmentSpells);
|
||||
break;
|
||||
case SPELL_DIVINE_POWER:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasDivinePowerSpell);
|
||||
break;
|
||||
case SPELL_EAGLE_SPLEDOR:
|
||||
case SPELL_GREATER_EAGLE_SPLENDOR:
|
||||
case AI_SPELLABILITY_HARPER_EAGLE_SPLEDOR: // Harper
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasEaglesSpledorSpell);
|
||||
break;
|
||||
case SPELL_ENDURANCE:
|
||||
case SPELL_GREATER_ENDURANCE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasEnduranceSpell);
|
||||
break;
|
||||
case SPELL_FOXS_CUNNING:
|
||||
case SPELL_GREATER_FOXS_CUNNING:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasFoxesCunningSpell);
|
||||
break;
|
||||
case SPELL_HOLY_AURA:
|
||||
case SPELL_MAGIC_CIRCLE_AGAINST_EVIL:
|
||||
case SPELL_PROTECTION_FROM_EVIL:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasProtectionEvilSpell);
|
||||
break;
|
||||
case SPELL_UNHOLY_AURA:
|
||||
case SPELL_MAGIC_CIRCLE_AGAINST_GOOD:
|
||||
case SPELL_PROTECTION_FROM_GOOD:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasProtectionGoodSpell);
|
||||
break;
|
||||
case SPELL_LIGHT:
|
||||
case SPELL_CONTINUAL_FLAME:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasLightSpell);
|
||||
break;
|
||||
case SPELL_OWLS_WISDOM:
|
||||
case SPELL_GREATER_OWLS_WISDOM:
|
||||
case AI_SPELL_OWLS_INSIGHT:// Missed spell
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasOwlsWisdomSpell);
|
||||
break;
|
||||
case SPELL_PROTECTION_FROM_SPELLS:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasProtectionSpellsSpell);
|
||||
break;
|
||||
case SPELL_REGENERATE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasRegenerateSpell);
|
||||
break;
|
||||
case SPELL_SPELL_RESISTANCE:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasSpellResistanceSpell);
|
||||
break;
|
||||
case SPELL_WAR_CRY:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasSpellWarCrySpell);
|
||||
break;
|
||||
case SPELLABILITY_DIVINE_PROTECTION:
|
||||
case SPELLABILITY_DIVINE_STRENGTH:
|
||||
case SPELLABILITY_DIVINE_TRICKERY:
|
||||
case SPELLABILITY_BATTLE_MASTERY:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasDomainSpells);
|
||||
break;
|
||||
case SPELLABILITY_RAGE_3:
|
||||
case SPELLABILITY_RAGE_4:
|
||||
case SPELLABILITY_RAGE_5:
|
||||
case SPELLABILITY_BARBARIAN_RAGE:
|
||||
case SPELLABILITY_INTENSITY_1:
|
||||
case SPELLABILITY_INTENSITY_2:
|
||||
case SPELLABILITY_INTENSITY_3:
|
||||
case SPELLABILITY_FEROCITY_1:
|
||||
case SPELLABILITY_FEROCITY_2:
|
||||
case SPELLABILITY_FEROCITY_3:
|
||||
case SPELL_BLOOD_FRENZY:
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasRageSpells);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
eCheck = GetNextEffect(oTarget);
|
||||
}
|
||||
// If undead, set some immunities by default
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
AI_SetWeHaveSpellsEffect(GlobalHasDeathWardSpell);
|
||||
}
|
||||
DeleteLocalInt(oTarget, AI_ABILITY_DECREASE);
|
||||
DeleteLocalInt(oTarget, AI_EFFECT_HEX);
|
||||
// Special - only we set spell hexs on ourselves.
|
||||
if(oTarget == OBJECT_SELF)
|
||||
{
|
||||
DeleteLocalInt(oTarget, AI_SPELL_HEX);
|
||||
SetLocalInt(oTarget, AI_SPELL_HEX, TempSpellHex);
|
||||
}
|
||||
// Set final ones from temp integers
|
||||
SetLocalInt(oTarget, AI_ABILITY_DECREASE, nEffectAbilityDecrease);
|
||||
SetLocalInt(oTarget, AI_EFFECT_HEX, TempEffectHex);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -1,917 +0,0 @@
|
||||
/*/////////////////////// [Include - Spawn In] /////////////////////////////////
|
||||
Filename: J_Inc_SpawnIn
|
||||
///////////////////////// [Include - Spawn In] /////////////////////////////////
|
||||
This contains all the functions used in the spawning process, in one easy
|
||||
and very long file.
|
||||
|
||||
It also importantly sets up spells we have, or at least talents, so we
|
||||
know if we have any spells from category X.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Changed, added a lot of new things (such as constants file)
|
||||
1.4 - No more setting talent categories On Spawn. This is too much hassel.
|
||||
See the On rest script for ideas (remove this when complete!).
|
||||
|
||||
Perhaps set "Items" the first time we enter combat, and reset each time
|
||||
combat stops. Can be more efficeint maybe.
|
||||
- Skills set to "use" should have, say, 3 or more skill points to be
|
||||
used automatically, especially true for hiding.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This doesn't call anything to run the rest, except AI_SetUpEndOfSpawn has
|
||||
a lot of things that the generic AI requires (SetListeningPatterns and skills
|
||||
and waypoints ETC)
|
||||
|
||||
See the spawn in script for all the actual uses.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: N/A see spawn in script
|
||||
///////////////////////// [Include - Spawn In] ///////////////////////////////*/
|
||||
|
||||
// All constants.
|
||||
#include "J_INC_SETWEAPONS"
|
||||
#include "prc_inc_racial"
|
||||
// Set weapons
|
||||
// - Constants file is in this
|
||||
|
||||
// Special: Bioware SoU Waypoints/Animations constants
|
||||
// - Here so I know where they are :-P
|
||||
const string sAnimCondVarname = "NW_ANIM_CONDITION";
|
||||
// If set, the NPC is civilized
|
||||
const int NW_ANIM_FLAG_IS_CIVILIZED = 0x00000400;
|
||||
// If set, the NPC will use voicechats
|
||||
const int NW_ANIM_FLAG_CHATTER = 0x00000004;
|
||||
// If set, the NPC is mobile in a close-range
|
||||
const int NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE = 0x00000200;
|
||||
|
||||
/******************************************************************************/
|
||||
// Functions:
|
||||
/******************************************************************************/
|
||||
// This will activate one aura, very quickly.
|
||||
// If we have more than one...oh well.
|
||||
void AI_AdvancedAuras();
|
||||
// Activate the aura number (IE: Spell number), if it is possible.
|
||||
void AI_ActivateAura(int nAuraNumber);
|
||||
|
||||
// Base for moving round thier waypoints
|
||||
// - Uses ExectuteScript to run the waypoint walking.
|
||||
// * If bRun is TRUE, we run all the waypoint.
|
||||
// * fPause is the time delay between walking to the next waypoint (default 1.0)
|
||||
void SpawnWalkWayPoints(int bRun = FALSE, float fPause = 1.0);
|
||||
|
||||
// Sets up what we will listen to (everything!)
|
||||
void AI_SetListeningPatterns();
|
||||
// This will set what creature to create OnDeath.
|
||||
void AI_SetDeathResRef(string sResRef);
|
||||
// This will set the string, sNameOfValue, to sValue. Array size of 1.
|
||||
// - Use nPercentToSay to determine what % out of 100 it is said.
|
||||
void AI_SetSpawnInSpeakValue(string sNameOfValue, string sValue, int nPercentToSay = 100);
|
||||
// This will choose a random string, using iAmountOfValues, which is
|
||||
// the amount of non-empty strings given. The size of the array is therefore 1.
|
||||
// - Use nPercentToSay to determine what % out of 100 it is said.
|
||||
void AI_SetSpawnInSpeakRandomValue(string sNameOfValue, int nPercentToSay, int nAmountOfValues, string sValue1, string sValue2, string sValue3 = "", string sValue4 = "", string sValue5 = "", string sValue6 = "", string sValue7 = "", string sValue8 = "", string sValue9 = "", string sValue10 = "", string sValue11 = "", string sValue12 = "");
|
||||
// This will set an array of values, to sNameOfValue, for one to be chosen to
|
||||
// be said at the right time :-)
|
||||
// - sNameOfValue must be a valid name.
|
||||
// - Use iPercentToSay to determine what % out of 100 it is said.
|
||||
// NOTE: If the sNameOfValue is any combat one, we make that 1/100 to 1/1000.
|
||||
void AI_SetSpawnInSpeakArray(string sNameOfValue, int nPercentToSay, int nSize, string sValue1, string sValue2, string sValue3 = "", string sValue4 = "", string sValue5 = "", string sValue6 = "", string sValue7 = "", string sValue8 = "", string sValue9 = "", string sValue10 = "", string sValue11 = "", string sValue12 = "");
|
||||
|
||||
// This applies an increase, decrease or no change to the intended stat.
|
||||
// * Applies the effects INSTANTLY. These CANNOT be removed easily!
|
||||
void AI_ApplyStatChange(int nStat, int nAmount);
|
||||
// This will alter (magically) an ammount of random stats - nAmount
|
||||
// by a value within iLowest and nHighest.
|
||||
// * Applies the effects INSTANTLY. These CANNOT be removed easily!
|
||||
void AI_CreateRandomStats(int nLowest, int nHighest, int nAmount);
|
||||
// This will randomise other stats. Put both numbers to 0 to ignore some.
|
||||
// nHPMin, nHPMax = HP changes.
|
||||
// nReflexSaveMin, nReflexSaveMax = Reflex Save changes
|
||||
// nWillSaveMin, nWillSaveMax = Will Save changes
|
||||
// nFortSaveMin, nFortSaveMax = Fortitude Save changes
|
||||
// nACMin, nACMax = AC change.
|
||||
// Use nACType to define the AC type - default AC_DODGE_BONUS
|
||||
// * Applies the effects INSTANTLY. These CANNOT be removed easily!
|
||||
void AI_CreateRandomOther(int nHPMin, int nHPMax, int nReflexSaveMin = 0, int nReflexSaveMax = 0, int nWillSaveMin = 0, int nWillSaveMax = 0, int nFortSaveMin = 0, int nFortSaveMax = 0, int nACMin = 0, int nACMax = 0, int nACType = AC_DODGE_BONUS);
|
||||
|
||||
// Sets up thier selection of skills, to integers, if they would ever use them.
|
||||
// NOTE: it also triggers "hide" if they have enough skill and not stopped.
|
||||
// * 1.4 Changes: Some skills are turned off automatically when they have very
|
||||
// low points in that skill (IE: No possibility of doing it sucessfully). Also
|
||||
// edited other parts of the AI to take this into account.
|
||||
void AI_SetUpSkillToUse();
|
||||
// Sets the turning level if we have FEAT_TURN_UNDEAD.
|
||||
// - Called from AI_SetUpEndOfSpawn.
|
||||
void AI_SetTurningLevel();
|
||||
// This MUST be called. It fires these events:
|
||||
// SetUpSpells, SetUpSkillToUse, SetListeningPatterns, SetWeapons, AdvancedAuras.
|
||||
// These MUST be called! the AI might fail to work correctly if they don't fire!
|
||||
void AI_SetUpEndOfSpawn();
|
||||
// This will make the visual effect passed play INSTANTLY at the creatures location.
|
||||
// * nVFX - The visual effect constant number
|
||||
void AI_SpawnInInstantVisual(int nVFX);
|
||||
// This will make the visual effect passed play PERMAMENTLY.
|
||||
// * nVFX - The visual effect constant number
|
||||
// NOTE: They will be made to be SUPERNATUAL, so are not dispelled!
|
||||
void AI_SpawnInPermamentVisual(int nVFX);
|
||||
// This should not be used!
|
||||
// * called from SetUpEndOfSpawn.
|
||||
void AI_SetMaybeFearless();
|
||||
// This will set the MAXIMUM and MINIMUM targets to pass this stage (under sName)
|
||||
// of the targeting system. IE:
|
||||
// - If we set it to min of 5, max of 10, for AC, if we cancled 5 targets on having
|
||||
// AC higher then wanted, we will take the highest 5 minimum.
|
||||
// If there are over 10, we take a max of 10 to choose from.
|
||||
// * nType - must be TARGET_HIGHER or TARGET_LOWER. Defaults to the lowest, so it
|
||||
// targets the lowest value for sName.
|
||||
void AI_SetAITargetingValues(string sName, int nType, int nMinimum, int nMaximum);
|
||||
|
||||
|
||||
// Levels up us.
|
||||
// * nLevel - Levels to this number (doesn't do anything if already GetHitDice >= nLevel).
|
||||
// * nClass, nClass2, nClass3 - the 3 classes to level up in. Only needs 1 minimum
|
||||
// Spreads equally if there is more then 1 nClass.
|
||||
// Sets up spells to use automatically, but DOES NOT CHANGE CHALLENGE RATING!
|
||||
void AI_LevelUpCreature(int nLevel, int nClass, int nClass2 = CLASS_TYPE_INVALID, int nClass3 = CLASS_TYPE_INVALID);
|
||||
|
||||
// Used in AI_LevelUpCreature.
|
||||
// - Levels up OBJECT_SELF, in nClass for nLevels
|
||||
void AI_LevelLoop(int nClass, int nLevels);
|
||||
|
||||
// Sets up what random spells to cheat-cast at the end of all known spells.
|
||||
// it does NOT check for immunities, barriers, or anything else.
|
||||
// - You can set spells to more then one of the imputs to have a higher % to cast that one.
|
||||
void SetAICheatCastSpells(int nSpell1, int nSpell2, int nSpell3, int nSpell4, int nSpell5, int nSpell6);
|
||||
|
||||
// Mark that the given creature has the given condition set for anitmations
|
||||
// * Bioware SoU animations thing.
|
||||
void SetAnimationCondition(int nCondition, int bValid = TRUE, object oCreature = OBJECT_SELF);
|
||||
|
||||
// Sets we are a Beholder and use Ray attacks, and Animagic Ray.
|
||||
void SetBeholderAI();
|
||||
// Set we are a mindflayer, and uses some special AI for them.
|
||||
void SetMindflayerAI();
|
||||
|
||||
// This will set a spell trigger up. Under cirtain conditions, spells are released
|
||||
// and cast on the caster.
|
||||
// Once fired, a spell trigger is only reset by resting. Only 1 of each max is fired at once!
|
||||
// * sType - is specifically:
|
||||
// SPELLTRIGGER_DAMAGED_AT_PERCENT - When damaged, the trigger fires. Use iValue for the %. One at a time is fired.
|
||||
// SPELLTRIGGER_IMMOBILE - Fired when held/paralyzed/sleeping ETC. One at a time is fired.
|
||||
// SPELLTRIGGER_NOT_GOT_FIRST_SPELL - Makes sure !GetHasSpellEffect(iSpell1) already,
|
||||
// then fires. Checks all in this category each round (first one fires!)
|
||||
// SPELLTRIGGER_START_OF_COMBAT - Triggered always, at the start of DetermineCombatRound.
|
||||
// * nNumber - can be 1-9, in sequential order of when you want them to fire.
|
||||
// * nValue - is only required with DAMAGED_AT_PERCENT.
|
||||
// * nSpellX - Cannot be 0. It should only really be defensive spells.
|
||||
void SetSpellTrigger(string sType, int nValue, int nNumber, int nSpell1, int nSpell2 = 0, int nSpell3 = 0, int nSpell4 = 0, int nSpell5 = 0, int nSpell6 = 0, int nSpell7 = 0, int nSpell8 = 0, int nSpell9 = 0);
|
||||
|
||||
// Mark that the given creature has the given condition set
|
||||
void SetAnimationCondition(int nCondition, int bValid = TRUE, object oCreature = OBJECT_SELF)
|
||||
{
|
||||
int nCurrentCond = GetLocalInt(oCreature, sAnimCondVarname);
|
||||
if (bValid) {
|
||||
SetLocalInt(oCreature, sAnimCondVarname, nCurrentCond | nCondition);
|
||||
} else {
|
||||
SetLocalInt(oCreature, sAnimCondVarname, nCurrentCond & ~nCondition);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets up what random spells to cheat-cast at the end of all known spells.
|
||||
// it does NOT check for immunities, barriers, or anything else.
|
||||
// - You can set spells to more then one of the imputs to have a higher % to cast that one.
|
||||
void SetAICheatCastSpells(int nSpell1, int nSpell2, int nSpell3, int nSpell4, int nSpell5, int nSpell6)
|
||||
{
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(1), nSpell1);
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(2), nSpell2);
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(3), nSpell3);
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(4), nSpell4);
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(5), nSpell5);
|
||||
SetAIConstant(AI_CHEAT_CAST_SPELL + IntToString(6), nSpell6);
|
||||
}
|
||||
|
||||
|
||||
// Levels up us.
|
||||
// * nLevel - Levels to this number (doesn't do anything if already GetHitDice >= nLevel).
|
||||
// * nClass, nClass2, nClass3 - the 3 classes to level up in. Only needs 1 minimum
|
||||
// - Spreads equally if there is more then 1 nClass.
|
||||
// - Sets up spells to use automatically, but DOES NOT CHANGE CHALLENGE RATING!
|
||||
// - Does NOT check for validness, or report any information.
|
||||
void AI_LevelUpCreature(int nLevel, int nClass, int nClass2 = CLASS_TYPE_INVALID, int nClass3 = CLASS_TYPE_INVALID)
|
||||
{
|
||||
// Divide by 1, 2 or 3 (100%, 50%, 33%)
|
||||
int nDivideBy = (nClass >= 0) + (nClass2 >= 0) + (nClass3 >= 0);
|
||||
|
||||
int nTotalPerClass = nLevel / nDivideBy;
|
||||
|
||||
// Limit and loop - Class 1.
|
||||
AI_LevelLoop(nClass, nTotalPerClass);
|
||||
// 2
|
||||
AI_LevelLoop(nClass2, nTotalPerClass);
|
||||
// 3
|
||||
AI_LevelLoop(nClass3, nTotalPerClass);
|
||||
}
|
||||
|
||||
// Used in AI_LevelUpCreature.
|
||||
// - Levels up OBJECT_SELF, in iClass for nLevels
|
||||
void AI_LevelLoop(int nClass, int nLevels)
|
||||
{
|
||||
// Limit and loop
|
||||
while(nLevels > FALSE)
|
||||
{
|
||||
LevelUpHenchman(OBJECT_SELF, nClass, TRUE);
|
||||
nLevels--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This will set what creature to create OnDeath.
|
||||
void AI_SetDeathResRef(string sResRef)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, AI_WE_WILL_CREATE_ON_DEATH, sResRef);
|
||||
}
|
||||
// This will set the string, sNameOfValue, to sValue. Array size of 1.
|
||||
// - Use iPercentToSay to determine what % out of 100 it is said.
|
||||
void AI_SetSpawnInSpeakValue(string sNameOfValue, string sValue, int iPercentToSay)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "1", sValue);
|
||||
// The array is 1 big!
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_SIZE + sNameOfValue, 1);
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_PERCENT + sNameOfValue, iPercentToSay);
|
||||
}
|
||||
// This will choose a random string, using iAmountOfValues, which is
|
||||
// the amount of non-empty strings given. The size of the array is therefore 1.
|
||||
// - Use iPercentToSay to determine what % out of 100 it is said.
|
||||
void AI_SetSpawnInSpeakRandomValue(string sNameOfValue, int nPercentToSay, int nAmountOfValues, string sValue1, string sValue2, string sValue3, string sValue4, string sValue5, string sValue6, string sValue7, string sValue8, string sValue9, string sValue10, string sValue11, string sValue12)
|
||||
{
|
||||
// Need a value amount of values!
|
||||
if(nAmountOfValues)
|
||||
{
|
||||
int nRandomNum = Random(nAmountOfValues) - 1; // take one, as it is 0 - X, not 1 - X
|
||||
string sValueToUse;
|
||||
switch(nRandomNum)
|
||||
{
|
||||
case 0:{sValueToUse = sValue1;}break;
|
||||
case 1:{sValueToUse = sValue2;}break;
|
||||
case 2:{sValueToUse = sValue3;}break;
|
||||
case 3:{sValueToUse = sValue4;}break;
|
||||
case 4:{sValueToUse = sValue5;}break;
|
||||
case 5:{sValueToUse = sValue6;}break;
|
||||
case 6:{sValueToUse = sValue7;}break;
|
||||
case 7:{sValueToUse = sValue8;}break;
|
||||
case 8:{sValueToUse = sValue9;}break;
|
||||
case 9:{sValueToUse = sValue10;}break;
|
||||
case 10:{sValueToUse = sValue11;}break;
|
||||
case 11:{sValueToUse = sValue12;}break;
|
||||
}
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "1", sValueToUse);
|
||||
// The array is 1 big!
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_SIZE + sNameOfValue, 1);
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_PERCENT + sNameOfValue, nPercentToSay);
|
||||
}
|
||||
}
|
||||
void AI_SetSpawnInSpeakArray(string sNameOfValue, int nPercentToSay, int nSize, string sValue1, string sValue2, string sValue3 = "", string sValue4 = "", string sValue5 = "", string sValue6 = "", string sValue7 = "", string sValue8 = "", string sValue9 = "", string sValue10 = "", string sValue11 = "", string sValue12 = "")
|
||||
{
|
||||
if(nSize >= 1)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "1", sValue1);
|
||||
if(nSize >= 2)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "2", sValue2);
|
||||
if(nSize >= 3)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "3", sValue3);
|
||||
if(nSize >= 4)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "4", sValue4);
|
||||
if(nSize >= 5)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "5", sValue5);
|
||||
if(nSize >= 6)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "6", sValue6);
|
||||
if(nSize >= 7)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "7", sValue7);
|
||||
if(nSize >= 8)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "8", sValue8);
|
||||
if(nSize >= 9)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "9", sValue9);
|
||||
if(nSize >= 10)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "10", sValue10);
|
||||
if(nSize >= 11)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "11", sValue11);
|
||||
if(nSize >= 12)
|
||||
{
|
||||
SetLocalString(OBJECT_SELF, sNameOfValue + "12", sValue12);
|
||||
// Hehe, this looks not stright if you stare at it! :-P
|
||||
} } } } } } } } } } } }
|
||||
// The array is so big...
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_SIZE + sNameOfValue, nSize);
|
||||
SetLocalInt(OBJECT_SELF, ARRAY_PERCENT + sNameOfValue, nPercentToSay);
|
||||
}
|
||||
// This applies an increase, decrease or no change to the intended stat.
|
||||
// * Applies the effects INSTANTLY. These CANNOT be removed easily!
|
||||
void AI_ApplyStatChange(int nStat, int nAmount)
|
||||
{
|
||||
if(nAmount != 0)
|
||||
{
|
||||
effect eChange;
|
||||
if(nAmount < 0)
|
||||
{
|
||||
nAmount = abs(nAmount);
|
||||
eChange = SupernaturalEffect(EffectAbilityDecrease(nStat, nAmount));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
else
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectAbilityIncrease(nStat, nAmount));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
// This will, eventually, choose X number of stats, and change them within the
|
||||
// range given.
|
||||
void AI_CreateRandomStats(int nLowest, int nHighest, int nAmount)
|
||||
{
|
||||
if(nAmount > 0 && nHighest != 0 && nLowest != 0 && nHighest >= nLowest)
|
||||
{
|
||||
int nRange = nHighest - nLowest;
|
||||
int nNumSlots = nAmount;
|
||||
if(nNumSlots > 6) nNumSlots = 6;
|
||||
int nNumLeft = 6;
|
||||
// Walk through each stat and figure out what it's chance of being
|
||||
// modified is. As an example, suppose we wanted to have 4 randomized
|
||||
// abilities. We'd look at the first ability and it would have a 4 in 6
|
||||
// chance of being picked. Let's suppose it was, the next ability would
|
||||
// have a 3 in 5 chance of being picked. If this next ability wasn't
|
||||
// picked to be changed, the 3rd ability woud have a 3 in 4 chance of
|
||||
// being picked and so on.
|
||||
int nCnt;
|
||||
int nChange;
|
||||
for(nCnt = 0; (nNumSlots > 0 && nCnt < 6); nCnt++)
|
||||
{
|
||||
if((nNumSlots == nNumLeft) || (Random(nNumLeft) < nNumSlots))
|
||||
{
|
||||
nChange = Random(nRange) + nLowest;
|
||||
AI_ApplyStatChange(nCnt, nChange);
|
||||
nNumSlots--;
|
||||
}
|
||||
nNumLeft--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will randomise other stats. Put both numbers to 0 to ignore some.
|
||||
// nHPMin, nHPMax = HP changes.
|
||||
// nReflexSaveMin, nReflexSaveMax = Reflex Save changes
|
||||
// nWillSaveMin, nWillSaveMax = Will Save changes
|
||||
// nFortSaveMin, nFortSaveMax = Fortitude Save changes
|
||||
// nACMin, nACMax = AC change.
|
||||
// Use nACType to define the AC type - default AC_DODGE_BONUS
|
||||
// * Applies the effects INSTANTLY. These CANNOT be removed easily!
|
||||
void AI_CreateRandomOther(int nHPMin, int nHPMax, int nReflexSaveMin = 0, int nReflexSaveMax = 0, int nWillSaveMin = 0, int nWillSaveMax = 0, int nFortSaveMin = 0, int nFortSaveMax = 0, int nACMin = 0, int nACMax = 0, int nACType = AC_DODGE_BONUS)
|
||||
{
|
||||
int nRange, nChange, nNewChange;
|
||||
effect eChange;
|
||||
if(!(nHPMin == 0 && nHPMax == 0) && nHPMax >= nHPMin)
|
||||
{
|
||||
nRange = nHPMax - nHPMin;
|
||||
nChange = Random(nRange) + nHPMin;
|
||||
if(nChange > 0)
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectTemporaryHitpoints(nChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
// * Must have 1HP remaining at least.
|
||||
else if(nChange < 0 && GetMaxHitPoints() > nChange)
|
||||
{
|
||||
eChange = EffectDamage(nChange, DAMAGE_TYPE_DIVINE, DAMAGE_POWER_PLUS_TWENTY);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
if(!(nReflexSaveMin == 0 && nReflexSaveMax == 0) && nReflexSaveMax >= nReflexSaveMin)
|
||||
{
|
||||
nRange = nReflexSaveMax - nReflexSaveMin;
|
||||
nChange = Random(nRange) + nReflexSaveMin;
|
||||
if(nChange > 0)
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectSavingThrowIncrease(SAVING_THROW_REFLEX, nChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
// Cannot apply 0 change, but can make our saves negative
|
||||
else if(nChange < 0)
|
||||
{
|
||||
nNewChange = abs(nChange);
|
||||
eChange = SupernaturalEffect(EffectSavingThrowDecrease(SAVING_THROW_REFLEX, nNewChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
if(!(nWillSaveMin == 0 && nWillSaveMax == 0) && nWillSaveMax >= nWillSaveMin)
|
||||
{
|
||||
nRange = nWillSaveMax - nWillSaveMin;
|
||||
nChange = Random(nRange) + nWillSaveMin;
|
||||
if(nChange > 0)
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectSavingThrowIncrease(SAVING_THROW_WILL, nChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
// Cannot apply 0 change, but can make our saves negative
|
||||
else if(nChange < 0)
|
||||
{
|
||||
nNewChange = abs(nChange);
|
||||
eChange = SupernaturalEffect(EffectSavingThrowDecrease(SAVING_THROW_WILL, nNewChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
if(!(nFortSaveMin == 0 && nFortSaveMax == 0) && nFortSaveMax >= nFortSaveMin)
|
||||
{
|
||||
nRange = nFortSaveMax - nFortSaveMin;
|
||||
nChange = Random(nRange) + nFortSaveMin;
|
||||
if(nChange > 0)
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectSavingThrowIncrease(SAVING_THROW_FORT, nChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
// Cannot apply 0 change, but can make our saves negative
|
||||
else if(nChange < 0)
|
||||
{
|
||||
nNewChange = abs(nChange);
|
||||
eChange = SupernaturalEffect(EffectSavingThrowDecrease(SAVING_THROW_FORT, nNewChange));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
if(!(nACMin == 0 && nACMax == 0) && nACMax >= nACMin)
|
||||
{
|
||||
nRange = nACMax - nACMin;
|
||||
nChange = Random(nRange) + nACMin;
|
||||
if(nChange > 0)
|
||||
{
|
||||
eChange = SupernaturalEffect(EffectACIncrease(nChange, nACType));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
else if(nChange < 0)
|
||||
{
|
||||
nNewChange = abs(nChange);
|
||||
eChange = SupernaturalEffect(EffectACDecrease(nNewChange, nACType));
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eChange, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*::///////////////////////////////////////////////
|
||||
//:: SetListeningPatterns
|
||||
//:://////////////////////////////////////////////
|
||||
Changed a lot. added in "**" (all) listening, for hearing enemies.
|
||||
//::////////////////////////////////////////////*/
|
||||
|
||||
void AI_SetListeningPatterns()
|
||||
{
|
||||
// Lag check
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_LISTENING, AI_OTHER_MASTER)) return;
|
||||
SetListening(OBJECT_SELF, TRUE);
|
||||
|
||||
// Anyone that can hear it, and is not fighting, comes and helps
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_I_WAS_ATTACKED, AI_SHOUT_I_WAS_ATTACKED_CONSTANT);
|
||||
|
||||
//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, AI_SHOUT_BLOCKER_CONSTANT);
|
||||
|
||||
// Determines combat round, if not fighting
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_CALL_TO_ARMS, AI_SHOUT_CALL_TO_ARMS_CONSTANT);
|
||||
|
||||
// These call to allies, to move them to a battle.
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_HELP_MY_FRIEND, AI_SHOUT_HELP_MY_FRIEND_CONSTANT);
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_LEADER_FLEE_NOW, AI_SHOUT_LEADER_FLEE_NOW_CONSTANT);
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_LEADER_ATTACK_TARGET, AI_SHOUT_LEADER_ATTACK_TARGET_CONSTANT);
|
||||
|
||||
// 1.3 - Need a killed one.
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_I_WAS_KILLED, AI_SHOUT_I_WAS_KILLED_CONSTANT);
|
||||
|
||||
// 1.3 - PLaceables/doors which shout this get responded to!
|
||||
SetListenPattern(OBJECT_SELF, AI_SHOUT_I_WAS_OPENED, AI_SHOUT_I_WAS_OPENED_CONSTANT);
|
||||
|
||||
// This will make the listener hear anything, used to react to enemy talking.
|
||||
SetListenPattern(OBJECT_SELF, "**", AI_SHOUT_ANYTHING_SAID_CONSTANT);
|
||||
}
|
||||
|
||||
// Base for moving round thier waypoints
|
||||
// - Uses ExectuteScript to run the waypoint walking.
|
||||
// * If bRun is TRUE, we run all the waypoint.
|
||||
// * fPause is the time delay between walking to the next waypoint (default 1.0)
|
||||
void SpawnWalkWayPoints(int bRun = FALSE, float fPause = 1.0)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, WAYPOINT_RUN, bRun);
|
||||
SetLocalFloat(OBJECT_SELF, WAYPOINT_PAUSE, fPause);
|
||||
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
||||
}
|
||||
|
||||
// This MUST be called. It fires these events:
|
||||
// SetUpSpells, SetUpSkillToUse, SetListeningPatterns, SetWeapons, AdvancedAuras.
|
||||
// These MUST be called! the AI might fail to work correctly if they don't fire!
|
||||
void AI_SetUpEndOfSpawn()
|
||||
{
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION, AI_OTHER_MASTER))
|
||||
{
|
||||
// This will store thier starting location, and then move back there after combat
|
||||
// Will turn off if there are waypoints. It is set in SetUpEndOfSpawn.
|
||||
SetAILocation(AI_RETURN_TO_POINT, GetLocation(OBJECT_SELF));
|
||||
}
|
||||
|
||||
// Set up if we are immune to cirtain levels of spells naturally for better
|
||||
// AI spellcasters.
|
||||
object oHide = GetItemInSlot(INVENTORY_SLOT_CARMOUR, OBJECT_SELF);
|
||||
// Get if immune is on
|
||||
if(GetItemHasItemProperty(oHide, ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL))
|
||||
{
|
||||
itemproperty eCheck = GetFirstItemProperty(oHide);
|
||||
int nAmount;
|
||||
// Check for item properties until we find the level.
|
||||
while(GetIsItemPropertyValid(eCheck) && nAmount == FALSE)
|
||||
{
|
||||
// Check subtype.
|
||||
if(GetItemPropertyType(eCheck) == ITEM_PROPERTY_IMMUNITY_SPELLS_BY_LEVEL)
|
||||
{
|
||||
// Get the amount
|
||||
nAmount = GetItemPropertyCostTableValue(eCheck);
|
||||
}
|
||||
eCheck = GetNextItemProperty(oHide);
|
||||
}
|
||||
// Set it
|
||||
if(nAmount)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_SPELL_IMMUNE_LEVEL, nAmount);
|
||||
}
|
||||
}
|
||||
|
||||
// All things only used by my personal AI.
|
||||
// * If we are not using a custom AI file, we do these things.
|
||||
if(GetCustomAIFileName() == "")
|
||||
{
|
||||
// If we are a commoner of any sort, and under 10 hit dice, we are
|
||||
// panicy - IE: We set to -1 morale, which triggers the "commoner" fleeing
|
||||
if(GetLevelByClass(CLASS_TYPE_COMMONER) && GetHitDice(OBJECT_SELF) < 10)
|
||||
{
|
||||
SetAIInteger(AI_MORALE, -1);
|
||||
}
|
||||
// If we are not set already to fearless, we might be set to fearless
|
||||
if(!GetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER))
|
||||
{
|
||||
AI_SetMaybeFearless();
|
||||
}
|
||||
// Set if we are a beholder or mindflayer
|
||||
switch(GetAppearanceType(OBJECT_SELF))
|
||||
{
|
||||
// Sets we are a Beholder and use Ray attacks, and Animagic Ray.
|
||||
case APPEARANCE_TYPE_BEHOLDER: // beholder, 401
|
||||
case APPEARANCE_TYPE_BEHOLDER_EYEBALL: // beholder, 402
|
||||
case APPEARANCE_TYPE_BEHOLDER_MAGE: // beholder, 403
|
||||
case APPEARANCE_TYPE_BEHOLDER_MOTHER: // Hive mother, 472
|
||||
{
|
||||
// 1 = beholder
|
||||
SetAIInteger(AI_SPECIAL_AI, AI_SPECIAL_AI_BEHOLDER);
|
||||
}
|
||||
break;
|
||||
|
||||
// Set we are a mindflayer, and uses some special AI for them, IE:
|
||||
// brain sucking.
|
||||
case APPEARANCE_TYPE_MINDFLAYER: // Mindflayer, 413
|
||||
case APPEARANCE_TYPE_MINDFLAYER_2: // Mindflayer2, 414
|
||||
case APPEARANCE_TYPE_MINDFLAYER_ALHOON: // Mindflayer_Alhoon, 415
|
||||
{
|
||||
// 2 = mindflayer
|
||||
SetAIInteger(AI_SPECIAL_AI, AI_SPECIAL_AI_MINDFLAYER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// This will turn OFF skills we cannot use, so will never attempt them
|
||||
// at low skill levels anywhere in the AI.
|
||||
AI_SetUpSkillToUse();
|
||||
|
||||
// Sets the turning level if we have FEAT_TURN_UNDEAD.
|
||||
AI_SetTurningLevel();
|
||||
|
||||
// This sets what weapons the creature will use. They will use the best, according to a "value"
|
||||
// Giving a creature the feat Two-weapon-fighting makes them deul wield if appropriate weapons.
|
||||
SetWeapons();
|
||||
}
|
||||
|
||||
// We don't set up corpses if set not to...else set to resurrect
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_TURN_OFF_CORPSES, AI_OTHER_MASTER))
|
||||
{
|
||||
// Note: Here, if we can, we set Bioware's lootable on.
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_USE_BIOWARE_LOOTING, AI_OTHER_MASTER))
|
||||
{
|
||||
// Set to lootable
|
||||
SetLootable(OBJECT_SELF, TRUE);
|
||||
}
|
||||
// Just handling corpse raising/resurrection/removal
|
||||
// - Undestroyable, Raiseable and Selectable
|
||||
SetIsDestroyable(FALSE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
// Goes through and sets up which shouts the NPC will listen to.
|
||||
// - Custom AI uses this also, or should take advantage of it
|
||||
AI_SetListeningPatterns();
|
||||
|
||||
// This activates the creatures aura's.
|
||||
if(GetCommandable()) AI_AdvancedAuras();
|
||||
}
|
||||
|
||||
// Sets the turning level if we have FEAT_TURN_UNDEAD.
|
||||
void AI_SetTurningLevel()
|
||||
{
|
||||
// Most taken directly from NW_S2_TURNDEAD which is used with FEAT_TURN_UNDEAD
|
||||
if(GetHasFeat(FEAT_TURN_UNDEAD))
|
||||
{
|
||||
// By default, it is clerical levels which provide turn undead power.
|
||||
// We can turn HD up to nTurnLevel (HD = GetHitDice + GetTurnREsistsnceHD of undead)
|
||||
int nTurnLevel = GetLevelByClass(CLASS_TYPE_CLERIC);
|
||||
// Paladins turn at -2 the level of clerics
|
||||
if(GetLevelByClass(CLASS_TYPE_PALADIN) - 2 > nTurnLevel)
|
||||
{
|
||||
nTurnLevel = GetLevelByClass(CLASS_TYPE_PALADIN) - 2;
|
||||
}
|
||||
// Blackguard gets to turn at HITDICE -2 level, not character level,
|
||||
// as it says in NW_S2_TURNDEAD.
|
||||
if(GetLevelByClass(CLASS_TYPE_BLACKGUARD) > 0 &&
|
||||
(GetHitDice(OBJECT_SELF) - 2 > nTurnLevel))
|
||||
{
|
||||
nTurnLevel = GetHitDice(OBJECT_SELF) - 2;
|
||||
}
|
||||
// BTW, the number of undead turned is at least nTurnLevel, so we
|
||||
// can always turn one :-D
|
||||
SetAIInteger(AI_TURNING_LEVEL, nTurnLevel);
|
||||
// Note: Turn undead could be used for FEAT_DIVINE_MIGHT and
|
||||
// FEAT_DIVINE_SHIELD
|
||||
}
|
||||
}
|
||||
// This should not be used!
|
||||
// * called from SetUpEndOfSpawn.
|
||||
void AI_SetMaybeFearless()
|
||||
{
|
||||
// Cirtain races are immune to fear
|
||||
switch(MyPRCGetRacialType(OBJECT_SELF))
|
||||
{
|
||||
case RACIAL_TYPE_CONSTRUCT:
|
||||
case RACIAL_TYPE_DRAGON:
|
||||
case RACIAL_TYPE_UNDEAD:
|
||||
case RACIAL_TYPE_OUTSIDER:
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// If we are immune to fear anyway, we don't care
|
||||
if(GetHasFeat(FEAT_AURA_OF_COURAGE) ||
|
||||
GetHasFeat(FEAT_RESIST_NATURES_LURE) ||
|
||||
GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_FEAR))
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
}
|
||||
}
|
||||
|
||||
// Activate all auras.
|
||||
void AI_ActivateAura(int nAuraNumber)
|
||||
{
|
||||
// Just ActionCast - cheat cast, as then we can use it unlmimted times, as books say.
|
||||
if(GetHasSpell(nAuraNumber))
|
||||
{
|
||||
ActionCastSpellAtObject(nAuraNumber, OBJECT_SELF, METAMAGIC_NONE, TRUE, 20, PROJECTILE_PATH_TYPE_DEFAULT, TRUE);
|
||||
}
|
||||
}
|
||||
// This will activate one aura, very quickly.
|
||||
// If we have more than one...oh well.
|
||||
void AI_AdvancedAuras()
|
||||
{
|
||||
// Do aura's
|
||||
|
||||
// NOTE:
|
||||
// - All cheat cast. As DMG, they should be always on OR free action to reapply.
|
||||
ClearAllActions();
|
||||
AI_ActivateAura(SPELLABILITY_DRAGON_FEAR);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_UNEARTHLY_VISAGE);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_BLINDING);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_OF_COURAGE);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_PROTECTION);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_STUN);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_FIRE);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_COLD);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_ELECTRICITY);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_UNNATURAL);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_FEAR);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_UNNATURAL);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_MENACE);
|
||||
AI_ActivateAura(SPELLABILITY_TYRANT_FOG_MIST);
|
||||
AI_ActivateAura(AI_SPELLABILITY_AURA_OF_HELLFIRE);
|
||||
AI_ActivateAura(SPELLABILITY_AURA_HORRIFICAPPEARANCE);
|
||||
}
|
||||
|
||||
// Sets up thier selection of skills, to integers, if they would ever use them.
|
||||
// NOTE: it also triggers "hide" if they have enough skill and not stopped.
|
||||
void AI_SetUpSkillToUse()
|
||||
{
|
||||
// Get our hitdice
|
||||
int nHitDice = GetHitDice(OBJECT_SELF);
|
||||
int nRank;
|
||||
// Hiding. We turn off if we have no skill or under 1 skill in it
|
||||
// * Note: For the AI to decide "oh, we should hide", it requires a minimum
|
||||
// of 7 points in hide, and Rank - 4 must be >= our HD too. Can be forced.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(!GetHasSkill(SKILL_HIDE) ||
|
||||
GetSkillRank(SKILL_HIDE) < 1)
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Pickpocketing...we only turn it OFF here if low skill
|
||||
// (or none) Needs 1/2 HD or 10 minimum - 10 is probably needed for the DC35
|
||||
// check for this skill at all.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PICKPOCKETING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
nRank = GetSkillRank(SKILL_PICK_POCKET);
|
||||
if(!GetHasSkill(SKILL_PICK_POCKET) ||
|
||||
nRank < nHitDice/2 || nRank < 10)
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Taunting. Again, only off if low skill. Needs half of HD, or 3 minimum
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_TAUNTING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
nRank = GetSkillRank(SKILL_TAUNT);
|
||||
if(!GetHasSkill(SKILL_TAUNT) ||
|
||||
nRank < nHitDice/2 || nRank < 3)
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Empathy. Again, only off if low skill. Needs any, checked futher in game.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_EMPATHY, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(!GetHasSkill(SKILL_ANIMAL_EMPATHY))
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Unlocking doors. Again, only off if low skill. Needs any, checked futher in game.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(!GetHasSkill(SKILL_OPEN_LOCK))
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Healing kits.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_USING_HEALING_KITS, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(!GetHasSkill(SKILL_HEAL))
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_USING_HEALING_KITS, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_USING_HEALING_KITS, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
// Parrying
|
||||
// Only on if we have some skill in it :-)
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PARRYING, AI_OTHER_COMBAT_MASTER))
|
||||
{
|
||||
if(!GetHasSkill(SKILL_PARRY))
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
DeleteSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This will make the visual effect passed play INSTANTLY at the creatures location.
|
||||
// * nVFX - The visual effect constant number
|
||||
void AI_SpawnInInstantVisual(int nVFX)
|
||||
{
|
||||
// Beta 3 change: Made to at location.
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT,
|
||||
EffectVisualEffect(nVFX),
|
||||
GetLocation(OBJECT_SELF));
|
||||
}
|
||||
// This will make the visual effect passed play PERMAMENTLY.
|
||||
// * nVFX - The visual effect constant number
|
||||
// NOTE: They will be made to be SUPERNATUAL, so are not dispelled!
|
||||
void AI_SpawnInPermamentVisual(int nVFX)
|
||||
{
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT,
|
||||
SupernaturalEffect(EffectVisualEffect(nVFX)),
|
||||
OBJECT_SELF);
|
||||
}
|
||||
// This will set the MAXIMUM and MINIMUM targets to pass this stage (under sName)
|
||||
// of the targeting system. IE:
|
||||
// - If we set it to min of 5, max of 10, for AC, if we cancled 5 targets on having
|
||||
// AC higher then wanted, we will take the highest 5 minimum.
|
||||
// If there are over 10, we take a max of 10 to choose from.
|
||||
// * nType - must be TARGET_HIGHER or TARGET_LOWER. Defaults to the lowest, so it
|
||||
// targets the lowest value for sName.
|
||||
void AI_SetAITargetingValues(string sName, int nType, int nMinimum, int nMaximum)
|
||||
{
|
||||
// Error checking
|
||||
if((nType == TARGET_HIGHER || nType == TARGET_LOWER) &&
|
||||
nMinimum >= 1 && nMaximum >= 1 && nMaximum >= nMinimum)
|
||||
{
|
||||
// Set the type to sName.
|
||||
// - It is TARGET_HIGHER (1) or TARGET_LOWER (0).
|
||||
SetAIInteger(sName, nType);
|
||||
|
||||
// Minimum amount of targets for this?
|
||||
SetAIInteger(sName + MINIMUM, nMinimum);
|
||||
|
||||
// Maximum targets for this?
|
||||
SetAIInteger(sName + MAXIMUM, nMaximum);
|
||||
}
|
||||
}
|
||||
|
||||
// This will set a spell trigger up. Under cirtain conditions, spells are released
|
||||
// and cast on the caster.
|
||||
// Once fired, a spell trigger is only reset by resting. Only 1 of each max is fired at once!
|
||||
// * sType - is specifically:
|
||||
// SPELLTRIGGER_DAMAGED_AT_PERCENT - When damaged, the trigger fires. Use iValue for the %. One at a time is fired.
|
||||
// SPELLTRIGGER_IMMOBILE - Fired when held/paralyzed/sleeping ETC. One at a time is fired.
|
||||
// SPELLTRIGGER_NOT_GOT_FIRST_SPELL - Makes sure !GetHasSpellEffect(iSpell1) already,
|
||||
// then fires. Checks all in this category each round (first one fires!)
|
||||
// SPELLTRIGGER_START_OF_COMBAT - Triggered always, at the start of DetermineCombatRound.
|
||||
// * nNumber - can be 1-9, in sequential order of when you want them to fire.
|
||||
// * nValue - is only required with DAMAGED_AT_PERCENT.
|
||||
// * nSpellX - Cannot be 0. It should only really be defensive spells.
|
||||
void SetSpellTrigger(string sType, int nValue, int nNumber, int nSpell1, int nSpell2 = 0, int nSpell3 = 0, int nSpell4 = 0, int nSpell5 = 0, int nSpell6 = 0, int nSpell7 = 0, int nSpell8 = 0, int nSpell9 = 0)
|
||||
{
|
||||
// Either get our spell trigger (creature) or create one
|
||||
object oTrigger = GetAIObject(AI_SPELL_TRIGGER_CREATURE);
|
||||
// Is it valid?
|
||||
if(!GetIsObjectValid(oTrigger))
|
||||
{
|
||||
// Create it
|
||||
oTrigger = CreateObject(OBJECT_TYPE_CREATURE, "jass_spelltrig", GetLocation(OBJECT_SELF));
|
||||
// Set local on them for the target
|
||||
AddHenchman(OBJECT_SELF, oTrigger);
|
||||
// Local for us to get our spell trigger (should be our henchmen)
|
||||
SetAIObject(AI_SPELL_TRIGGER_CREATURE, oTrigger);
|
||||
}
|
||||
int nSize = 1;
|
||||
string sTotalID = sType + IntToString(nNumber);
|
||||
|
||||
SetLocalInt(oTrigger, sTotalID + "1", nSpell1);
|
||||
if(nSpell2 != FALSE)
|
||||
{ nSize = 2;
|
||||
SetLocalInt(oTrigger, sTotalID + "2", nSpell2); }
|
||||
if(nSpell3 != FALSE)
|
||||
{ nSize = 3;
|
||||
SetLocalInt(oTrigger, sTotalID + "3", nSpell3); }
|
||||
if(nSpell4 != FALSE)
|
||||
{ nSize = 4;
|
||||
SetLocalInt(oTrigger, sTotalID + "4", nSpell4); }
|
||||
if(nSpell5 != FALSE)
|
||||
{ nSize = 5;
|
||||
SetLocalInt(oTrigger, sTotalID + "5", nSpell5); }
|
||||
if(nSpell6 != FALSE)
|
||||
{ nSize = 6;
|
||||
SetLocalInt(oTrigger, sTotalID + "6", nSpell6); }
|
||||
if(nSpell7 != FALSE)
|
||||
{ nSize = 7;
|
||||
SetLocalInt(oTrigger, sTotalID + "7", nSpell7); }
|
||||
if(nSpell8 != FALSE)
|
||||
{ nSize = 8;
|
||||
SetLocalInt(oTrigger, sTotalID + "8", nSpell8); }
|
||||
if(nSpell9 != FALSE)
|
||||
{ nSize = 9;
|
||||
SetLocalInt(oTrigger, sTotalID + "9", nSpell9); }
|
||||
|
||||
// Set final sizes ETC.
|
||||
SetLocalInt(oTrigger, MAXINT_ + sTotalID, nSize);
|
||||
SetLocalInt(oTrigger, sTotalID + USED, FALSE);
|
||||
|
||||
// Check value
|
||||
if(nValue > GetLocalInt(oTrigger, VALUE + sType))
|
||||
{
|
||||
SetLocalInt(oTrigger, VALUE + sType, nValue);
|
||||
}
|
||||
|
||||
// Set how many spell triggers we have too
|
||||
if(nNumber > GetLocalInt(oTrigger, MAXIMUM + sType))
|
||||
{
|
||||
SetLocalInt(oTrigger, MAXIMUM + sType, nNumber);
|
||||
}
|
||||
}
|
||||
// Debug: To compile this script, uncomment all of the below.
|
||||
/* - Add two "/"'s at the start of this line
|
||||
void main()
|
||||
{
|
||||
return;
|
||||
}
|
||||
//*/
|
@@ -1,333 +0,0 @@
|
||||
// Walk waypoints include.
|
||||
|
||||
int NW_FLAG_STEALTH = 0x00000004;
|
||||
int NW_FLAG_SEARCH = 0x00000008;
|
||||
int NW_FLAG_DAY_NIGHT_POSTING = 0x00100000;
|
||||
|
||||
// Animations:
|
||||
// Randomwalk normally, or move to nearest ally.
|
||||
int AMBIENT_ANIMATIONS = 1;
|
||||
// These will face nearest ally, and talk or laugh. If no ally then look right/left.
|
||||
int IMMOBILE_AMBIENT_ANIMATIONS = 2;
|
||||
// This is the bird animations.
|
||||
int AMBIENT_ANIMATIONS_AVIAN = 3;
|
||||
// This will make the creatures "group" and sit, and normally talk.
|
||||
int AMBIENT_GROUP_ANIMATIONS = 4;
|
||||
// This will make the creature talk with nearby allies, as to not look dead.
|
||||
// Also, if alone, it will take drinks, and things like that.
|
||||
int IMMOBILE_ANIMATIONS_AND_SOLO = 5;
|
||||
// This is a consitution for just random walking, nothing else.
|
||||
int AMBIENT_ANIMAL_WALKING = 6;
|
||||
|
||||
// Run the circuit.
|
||||
void RunCircuit(int nTens, int nNum, int nRun = FALSE, float fPause = 1.0);
|
||||
// Base for moving round thier waypoints
|
||||
void WalkWayPoints(int nRun = FALSE, float fPause = 1.0);
|
||||
// Used in walk waypoints
|
||||
void RunNextCircuit(int nRun = FALSE, float fPause = 1.0);
|
||||
// Checks which waypoint they are on, if any valid. TRUE if got any waypoints in range.
|
||||
int CheckWayPoints(object oWalker = OBJECT_SELF);
|
||||
//Returns true if the object is walking any waypoints.
|
||||
int GetIsPostOrWalking(object oWalker = OBJECT_SELF);
|
||||
// Returns the string to use - depending on day or night.
|
||||
string GetStringPrefix(string sPrefix, object oWalker = OBJECT_SELF);
|
||||
// This sets a spawn in condition.
|
||||
void SetSpawnInCondition(int nCondition, int bValid = TRUE, string sName = "NW_GENERIC_MASTER");
|
||||
//Gets the spawn in condition.Can set things to different ints if you like.
|
||||
int GetSpawnInCondition(int nCondition, string sName = "NW_GENERIC_MASTER");
|
||||
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Master Local 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
|
||||
//:://////////////////////////////////////////////
|
||||
void SetSpawnInCondition(int nCondition, int bValid, string sName)
|
||||
{
|
||||
int nPlot = GetLocalInt(OBJECT_SELF, sName);
|
||||
if(bValid == TRUE)
|
||||
{
|
||||
nPlot = nPlot | nCondition;
|
||||
SetLocalInt(OBJECT_SELF, sName, nPlot);
|
||||
}
|
||||
else if (bValid == FALSE)
|
||||
{
|
||||
nPlot = nPlot & ~nCondition;
|
||||
SetLocalInt(OBJECT_SELF, sName, nPlot);
|
||||
}
|
||||
}
|
||||
|
||||
int GetSpawnInCondition(int nCondition, string sName)
|
||||
{
|
||||
int nPlot = GetLocalInt(OBJECT_SELF, sName);
|
||||
if(nPlot & nCondition)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//***************************
|
||||
//***************************
|
||||
//
|
||||
//WAY POINT WALK FUNCTIONS
|
||||
//
|
||||
//***************************
|
||||
//***************************
|
||||
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Walk Way Point Path
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Allows specified person walk a waypoint path
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Aidan Scanlan
|
||||
//:: Created On: July 10, 2001
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
void WalkWayPoints(int nRun = FALSE, float fPause = 1.0) //Run first circuit
|
||||
{
|
||||
if(CheckWayPoints())
|
||||
{
|
||||
ClearAllActions();
|
||||
}
|
||||
|
||||
string NightWayString;
|
||||
string NightPostString;
|
||||
string sWay;
|
||||
string sPost;
|
||||
|
||||
//The block of code below deals with night and day cycle for postings and walkway points.
|
||||
if(GetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING))
|
||||
{
|
||||
NightWayString = "WN_";
|
||||
NightPostString = "NIGHT_";
|
||||
}
|
||||
else
|
||||
{
|
||||
NightWayString = "WP_";
|
||||
NightPostString = "POST_";
|
||||
}
|
||||
|
||||
// We will set what strings to use.
|
||||
SetLocalString(OBJECT_SELF, "NW_GENERIC_WALKWAYS_DAY", "WP_");
|
||||
SetLocalString(OBJECT_SELF, "NW_GENERIC_WALKWAYS_NIGHT", NightWayString);
|
||||
SetLocalString(OBJECT_SELF, "NW_GENERIC_POSTING_DAY", "POST_");
|
||||
SetLocalString(OBJECT_SELF, "NW_GENERIC_POSTING_NIGHT", NightPostString);
|
||||
|
||||
// Which shall we use? Day or night?
|
||||
sWay = GetStringPrefix("NW_GENERIC_WALKWAYS");
|
||||
sPost = GetStringPrefix("NW_GENERIC_POSTING");
|
||||
|
||||
//I have now determined what the prefixs for the current walkways and postings are and will use them instead
|
||||
// of POST_ and WP_
|
||||
|
||||
if(GetSpawnInCondition(NW_FLAG_STEALTH))
|
||||
{
|
||||
// Will hide all the time, when they walk
|
||||
ActionUseSkill(SKILL_HIDE, OBJECT_SELF);
|
||||
}
|
||||
else if(GetSpawnInCondition(NW_FLAG_SEARCH) || GetLocalInt(OBJECT_SELF, "ANIMATIONS") == IMMOBILE_AMBIENT_ANIMATIONS)
|
||||
{
|
||||
// Will search all the time, when they walk, or if we are not going to move.
|
||||
ActionUseSkill(SKILL_SEARCH, OBJECT_SELF);
|
||||
}
|
||||
|
||||
//Test if OBJECT_SELF has waypoints to walk
|
||||
string sWayTag = GetTag(OBJECT_SELF);
|
||||
sWayTag = sWay + sWayTag + "_01";
|
||||
object oWay1 = GetNearestObjectByTag(sWayTag);
|
||||
// Get the object, if nearest (IE in area one) is not valid.
|
||||
if(!GetIsObjectValid(oWay1))
|
||||
{
|
||||
oWay1 = GetObjectByTag(sWayTag);
|
||||
}
|
||||
|
||||
if(GetIsObjectValid(oWay1))
|
||||
{
|
||||
int nNth = 1;
|
||||
int nTens;
|
||||
int nNum;
|
||||
object oNearest = GetNearestObject(OBJECT_TYPE_WAYPOINT, OBJECT_SELF, nNth);
|
||||
while (GetIsObjectValid(oNearest))
|
||||
{
|
||||
string sNearestTag = GetTag(oNearest);
|
||||
//removes the first 3 and last three characters from the waypoint's tag
|
||||
//and checks it against his own tag. Waypoint tag format is WP_MyTag_XX.
|
||||
if(GetSubString(sNearestTag, 3, GetStringLength(sNearestTag) - 6) == GetTag(OBJECT_SELF))
|
||||
{
|
||||
string sTens = GetStringRight(GetTag(oNearest), 2);
|
||||
nTens = StringToInt(sTens)/10;
|
||||
nNum= StringToInt(GetStringRight(GetTag(oNearest), 1));
|
||||
oNearest = OBJECT_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
nNth++;
|
||||
oNearest = GetNearestObject(OBJECT_TYPE_WAYPOINT,OBJECT_SELF,nNth);
|
||||
}
|
||||
}
|
||||
RunCircuit(nTens, nNum, nRun, fPause); //***************************************
|
||||
ActionWait(fPause);
|
||||
ActionDoCommand(RunNextCircuit(nRun, fPause));
|
||||
}
|
||||
else // Else go to the post we have set.
|
||||
{
|
||||
sWayTag = GetTag(OBJECT_SELF);
|
||||
sWayTag = sPost + sWayTag;
|
||||
oWay1 = GetNearestObjectByTag(sWayTag);
|
||||
if(!GetIsObjectValid(oWay1))
|
||||
{
|
||||
oWay1 = GetObjectByTag(sWayTag);
|
||||
}
|
||||
if(GetIsObjectValid(oWay1))
|
||||
{
|
||||
ActionForceMoveToObject(oWay1, nRun, 1.0, 60.0);
|
||||
float fFacing = GetFacing(oWay1);
|
||||
ActionDoCommand(SetFacing(fFacing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunNextCircuit(int nRun = FALSE, float fPause = 1.0)
|
||||
{
|
||||
RunCircuit(0, 1, nRun, fPause);
|
||||
ActionWait(fPause);
|
||||
ActionDoCommand(RunNextCircuit(nRun, fPause));
|
||||
}
|
||||
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Run Circuit
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Calculates the proper path to follow along a
|
||||
predetermined set of way points
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Aidan Scanlan
|
||||
//:: Created On: July 10, 2001
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
void RunCircuit(int nTens, int nNum, int nRun = FALSE, float fPause = 1.0)
|
||||
{
|
||||
// starting at a given way point, move sequentialy through incrementally
|
||||
// increasing points until there are no more valid ones.
|
||||
// We will check for day/night in these instead of heartbeats.
|
||||
string sWay = GetStringPrefix("NW_GENERIC_WALKWAYS");
|
||||
string sNewString;
|
||||
object oTargetPoint = GetWaypointByTag(sWay + GetTag(OBJECT_SELF) + "_" + IntToString(nTens) + IntToString(nNum));
|
||||
|
||||
while(GetIsObjectValid(oTargetPoint))
|
||||
{
|
||||
ActionWait(fPause);
|
||||
ActionMoveToObject(oTargetPoint, nRun);
|
||||
nNum++;
|
||||
if (nNum > 9)
|
||||
{
|
||||
nTens++;
|
||||
nNum = 0;
|
||||
}
|
||||
// Maybe change string prefix to use.
|
||||
sNewString = GetStringPrefix("NW_GENERIC_WALKWAYS");
|
||||
if(sNewString != sWay)
|
||||
{
|
||||
WalkWayPoints(nRun, fPause);
|
||||
return;
|
||||
}
|
||||
oTargetPoint = GetWaypointByTag(sWay + GetTag(OBJECT_SELF) + "_" + IntToString(nTens) + IntToString(nNum));
|
||||
}
|
||||
// once there are no more waypoints available, decriment back to the last
|
||||
// valid point.
|
||||
nNum--;
|
||||
if (nNum < 0)
|
||||
{
|
||||
nTens--;
|
||||
nNum = 9;
|
||||
}
|
||||
|
||||
// start the cycle again going back to point 01
|
||||
oTargetPoint = GetWaypointByTag(sWay + GetTag(OBJECT_SELF) + "_" + IntToString(nTens) + IntToString(nNum));
|
||||
while(GetIsObjectValid(oTargetPoint))
|
||||
{
|
||||
ActionWait(fPause);
|
||||
ActionMoveToObject(oTargetPoint, nRun);
|
||||
nNum--;
|
||||
if (nNum < 0)
|
||||
{
|
||||
nTens--;
|
||||
nNum = 9;
|
||||
}
|
||||
// Maybe change string prefix to use.
|
||||
sNewString = GetStringPrefix("NW_GENERIC_WALKWAYS");
|
||||
if(sNewString != sWay)
|
||||
{
|
||||
WalkWayPoints(nRun, fPause);
|
||||
return;
|
||||
}
|
||||
oTargetPoint = GetWaypointByTag(sWay + GetTag(OBJECT_SELF) + "_" + IntToString(nTens) + IntToString(nNum));
|
||||
}
|
||||
}
|
||||
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Check Walkways
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This function checks the passed in object to
|
||||
see if they are supposed to be walking to
|
||||
day or night postings.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Preston Watamaniuk
|
||||
//:: Created On: Feb 26, 2002
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
int CheckWayPoints(object oWalker)
|
||||
{
|
||||
object oWay1;
|
||||
object oWay2;
|
||||
object oWay3;
|
||||
object oWay4;
|
||||
string sTag = GetTag(oWalker);
|
||||
if(GetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING))
|
||||
{
|
||||
oWay2 = GetWaypointByTag("NIGHT_" + sTag);
|
||||
oWay4 = GetWaypointByTag("WN_" + sTag + "_01");
|
||||
}
|
||||
|
||||
oWay1 = GetWaypointByTag("POST_" + sTag);
|
||||
oWay3 = GetWaypointByTag("WP_" + sTag + "_01");
|
||||
|
||||
if(GetIsObjectValid(oWay2) || GetIsObjectValid(oWay4) || GetIsObjectValid(oWay1) || GetIsObjectValid(oWay3))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns the string to use - depending on day or night.
|
||||
string GetStringPrefix(string sPrefix, object oWalker)
|
||||
{
|
||||
if(GetIsDay() || GetIsDawn())
|
||||
{
|
||||
return GetLocalString(OBJECT_SELF, sPrefix + "_DAY");
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetLocalString(OBJECT_SELF, sPrefix + "_NIGHT");
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/************************ [On Spawn: Archer] ***********************************
|
||||
Filename: j_sp_archer
|
||||
************************* [On Spawn: Archer] ***********************************
|
||||
Any-level archer. This man is pretty basic, and has really only the special
|
||||
archery stuff on.
|
||||
************************* [On Spawn: Archer] **********************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Random intelligence, 4-6.
|
||||
SetAIInteger(AI_INTELLIGENCE, 3 + d3());
|
||||
// Random morale
|
||||
SetAIInteger(AI_MORALE, 7 + d6());
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
// Range - very imporant! Basis for all ranged/spell attacks.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_PICK_UP_DISARMED_WEAPONS, AI_COMBAT_MASTER);
|
||||
// This sets to pick up weapons which are disarmed.
|
||||
SetAIInteger(AI_RANGED_WEAPON_RANGE, 2);
|
||||
// This is the range at which they go into melee (from using a ranged weapon). Default is 3 or 5.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ATTACKING, AI_COMBAT_MASTER);
|
||||
// For archers. If they have ally support, they'd rather move back & shoot then go into HTH.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_MOVE_BACK, AI_COMBAT_MASTER);
|
||||
// This forces the move back from attackers, and shoot bows. Very small chance to go melee.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_USE_BOW, AI_COMBAT_MASTER);
|
||||
// This will make the creature ALWAYs use any bows it has. ALWAYS.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_NO_POLYMORPHING, AI_OTHER_MASTER);
|
||||
// This will stop all polymorphing spells feats from being used.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
// no spells or items.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_ITEMS, AI_OTHER_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
|
||||
// Ambient animations
|
||||
if(GetIsEncounterCreature())
|
||||
{
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
}
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0f, SpawnWalkWayPoints());
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
/************************ [On Spawn: Dragon] ***********************************
|
||||
Filename: j_sp_dragon
|
||||
************************* [On Spawn: Dragon] ***********************************
|
||||
Dragons are highly intelligent, and can...fly!
|
||||
|
||||
They do have a few improved spellcasting bits, and like to target lower AC
|
||||
more then anything.
|
||||
|
||||
Flying is also on, so they can jump to enemies far away.
|
||||
************************* [On Spawn: Dragon] **********************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Maximum "intelligence"
|
||||
SetAIInteger(AI_INTELLIGENCE, 10);
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
AI_SetAITargetingValues(TARGETING_AC, TARGET_LOWER, 1, 6);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_INSTANT_DEATH_SPELLS, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_IMMUNITY_CHECKING, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SPECIFIC_SPELL_IMMUNITY, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_LONGER_RANGED_SPELLS_FIRST, AI_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
// Dragon stuff
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_FLYING, AI_COMBAT_MASTER);
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0f, SpawnWalkWayPoints());
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
/************************ [On Spawn: High-Level Mage] **************************
|
||||
Filename: j_sp_highmage
|
||||
************************* [On Spawn: High-Level Mage] **************************
|
||||
A mage who is higher level - ok, so it has many stuff from the default spawn
|
||||
file, but this one has some of the mage behaviours set, such as long range
|
||||
attacking and fast buffing, but no spell triggers.
|
||||
************************* [On Spawn: High-Level Mage] *************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Random intelligence, 7-9.
|
||||
SetAIInteger(AI_INTELLIGENCE, 6 + d3());
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
|
||||
// Less mantals, and less saves is all we target
|
||||
AI_SetAITargetingValues(TARGETING_MANTALS, TARGET_LOWER, 1, 4);
|
||||
AI_SetAITargetingValues(TARGETING_SAVES, TARGET_LOWER, 1, 2);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_PICK_UP_DISARMED_WEAPONS, AI_COMBAT_MASTER);
|
||||
// This sets to pick up weapons which are disarmed.
|
||||
SetAIInteger(AI_RANGED_WEAPON_RANGE, 2);
|
||||
// This is the range at which they go into melee (from using a ranged weapon). Default is 3 or 5.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_IN_ORDER, AI_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_INSTANT_DEATH_SPELLS, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SUMMON_TARGETING, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_IMMUNITY_CHECKING, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SPECIFIC_SPELL_IMMUNITY, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_LONGER_RANGED_SPELLS_FIRST, AI_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
// no spells or items.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_ITEMS, AI_OTHER_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
|
||||
// Ambient animations
|
||||
if(GetIsEncounterCreature())
|
||||
{
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
}
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0f, SpawnWalkWayPoints());
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
/************************ [On Spawn: Human Leader] *****************************
|
||||
Filename: j_sp_humleader
|
||||
************************* [On Spawn: Human Leader] *****************************
|
||||
A human leader sample spawn script.
|
||||
|
||||
Maximum intelligence, some sample shouts/taunts and the leader settings are
|
||||
on. He does, however, never run, and always likes melee.
|
||||
|
||||
Shouldn't be a spellcaster, should only be a fighter primarily geared for HTH
|
||||
fighting.
|
||||
************************* [On Spawn: Human Leader] ****************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Maximum "intelligence"
|
||||
SetAIInteger(AI_INTELLIGENCE, 10);
|
||||
// We are fearless
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
// Range - very imporant! Basis for all ranged/spell attacks.
|
||||
AI_SetAITargetingValues(TARGETING_AC, TARGET_LOWER, 2, 6);
|
||||
// AC is used for all phisical attacks. Lower targets lower (By default).
|
||||
// Fighter/Clerics (It is over a mages BAB + 1 (IE 0.5 BAB/Level) target lower
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_LOWER, 2, 6);
|
||||
// Base attack bonus. Used for spells and phisical attacks. Checked with GetBaseAttackBonus.
|
||||
AI_SetAITargetingValues(TARGETING_BAB, TARGET_LOWER, 1, 4);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
// Forces them to not flee. This may be set with AI_SetMaybeFearless at the end.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_PICK_UP_DISARMED_WEAPONS, AI_COMBAT_MASTER);
|
||||
// This sets to pick up weapons which are disarmed.
|
||||
|
||||
SetAIInteger(AI_RANGED_WEAPON_RANGE, 6);
|
||||
// This is the range at which they go into melee (from using a ranged weapon). Default is 3 or 5.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_BETTER_AT_HAND_TO_HAND, AI_COMBAT_MASTER);
|
||||
// Set if you want them to move forwards into HTH sooner. Will always
|
||||
// if the enemy is a mage/archer, else % based on range.
|
||||
|
||||
// Set all leader variables
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER);
|
||||
// Special leader. Can issuse some orders. See readme for details.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_BOSS_MONSTER_SHOUT, AI_OTHER_COMBAT_MASTER);
|
||||
// Boss shout. 1 time use - calls all creatures in X meters (below) for battle!
|
||||
//SetAIInteger(AI_BOSS_MONSTER_SHOUT_RANGE, 60);
|
||||
// Defaults to a 60 M range. This can change it. Note: 1 toolset square = 10M.
|
||||
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_NO_POLYMORPHING, AI_OTHER_MASTER);
|
||||
// This will stop all polymorphing spells feats from being used.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_REST_AFTER_COMBAT, AI_OTHER_MASTER);
|
||||
// When combat is over, creature rests. Useful for replenising health.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_NO_PLAYING_VOICE_CHAT, AI_OTHER_MASTER);
|
||||
|
||||
// Can uncomment these if the leader has no spells or items.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_ITEMS, AI_OTHER_MASTER);
|
||||
// The creature doesn't check for, or use any items that cast spells.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
//The creature doesn't ever cast spells (and never checks them)
|
||||
|
||||
// Combat
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_EQUAL, 10, 4, "You don't stand a chance!", "Men, Attack!", "For Glory!!", "Eat steel!");
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_THEM_OVER_US, 10, 4, "Your might is no match for my brains!", "Tough man, are we?", "You won't kill me!", "Pah! I am no coward! I fight on!");
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_US_OVER_THEM, 10, 4, "No mercy!", "Hope for a quick death!", "Men! Kill the lot!", "There is no chance!");
|
||||
|
||||
// Our leader shouts!
|
||||
// - As this is a human, very orderly
|
||||
AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_SEND_RUNNER, "Soldier! Go find help!");
|
||||
AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_ATTACK_TARGET, "Direct your attacks here, men!");
|
||||
|
||||
// Ambient animations
|
||||
if(GetIsEncounterCreature())
|
||||
{
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
}
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0f, SpawnWalkWayPoints());
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
/************************ [On Spawn: Lich] *************************************
|
||||
Filename: j_sp_lichboss
|
||||
************************* [On Spawn: Lich] *************************************
|
||||
A high-powered lich, who takes advantage of spell triggers!
|
||||
|
||||
He should be geared towards higher level spells, and once he runs out, he
|
||||
does cheat-cast several 1-3 level spells.
|
||||
|
||||
The spell triggers stop quite a bit of damage, with Premonition, greater
|
||||
spell mantal and Energy Buffer. He also has some taunts he uses most combat
|
||||
rounds, as well as using longer ranged spells first.
|
||||
|
||||
As he is a boss, he is a leader status, and also gets a free harm at 30% HP.
|
||||
************************* [On Spawn: Lich] ************************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Maximum intelligence
|
||||
SetAIInteger(AI_INTELLIGENCE, 10);
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_MANTALS, TARGET_LOWER, 1, 12);
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
AI_SetAITargetingValues(TARGETING_AC, TARGET_LOWER, 3, 6);
|
||||
AI_SetAITargetingValues(TARGETING_SAVES, TARGET_LOWER, 3, 4);
|
||||
// Mages target higher. (the lowest BAB, under half our hit dice in BAB)
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_HIGHER, 1, 5);
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_BAB, TARGET_LOWER, 1, 4);
|
||||
AI_SetAITargetingValues(TARGETING_HITDICE, TARGET_LOWER, 1, 3);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_IN_ORDER, AI_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_INSTANT_DEATH_SPELLS, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SUMMON_TARGETING, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_IMMUNITY_CHECKING, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SPECIFIC_SPELL_IMMUNITY, AI_COMBAT_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_WILL_RAISE_ALLIES_IN_BATTLE, AI_OTHER_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER);
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_LONGER_RANGED_SPELLS_FIRST, AI_COMBAT_MASTER);
|
||||
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_EQUAL, 900, 4, "Curse your life!", "Nothing can kill the undead!", "MUhahaHaHahahha!!", "Prepare to DIE!");
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_THEM_OVER_US, 900, 4, "Curse your life!", "Nothing can kill the undead!", "MUhahaHaHahahha!!", "Prepare to DIE!");
|
||||
AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_US_OVER_THEM, 900, 4, "Curse your life!", "Nothing can kill the undead!", "MUhahaHaHahahha!!", "Prepare to DIE!");
|
||||
|
||||
// Spell triggers
|
||||
SetSpellTrigger(SPELLTRIGGER_START_OF_COMBAT, FALSE, 1, SPELL_DEATH_ARMOR, SPELL_FOXS_CUNNING, SPELL_SHADOW_SHIELD);
|
||||
|
||||
// Damamged
|
||||
SetSpellTrigger(SPELLTRIGGER_DAMAGED_AT_PERCENT, 30, 1, SPELL_HARM);
|
||||
|
||||
// Immobile
|
||||
SetSpellTrigger(SPELLTRIGGER_IMMOBILE, FALSE, 1, SPELL_FREEDOM_OF_MOVEMENT);
|
||||
|
||||
// Normal defensive
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 1, SPELL_PREMONITION);
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 2, SPELL_PREMONITION);
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 3, SPELL_GREATER_SPELL_MANTLE);
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 4, SPELL_GREATER_SPELL_MANTLE);
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 5, SPELL_ENERGY_BUFFER);
|
||||
SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 6, SPELL_ENERGY_BUFFER);
|
||||
|
||||
// Cheat spells
|
||||
SetAICheatCastSpells(SPELL_MAGIC_MISSILE, SPELL_MAGIC_MISSILE, SPELL_MAGIC_MISSILE, SPELL_FIREBALL, SPELL_MELFS_ACID_ARROW, SPELL_MELFS_ACID_ARROW);
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0, SpawnWalkWayPoints());
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
/************************ [On Spawn: Low Intelligence] *************************
|
||||
Filename: j_sp_lowintel
|
||||
************************* [On Spawn: Low Intelligence] *************************
|
||||
Low intelligence creatures, such as Goblins, might not have an advanced a
|
||||
way of picking who to best attack, nor as much AI intelligence.
|
||||
************************* [On Spawn: Low Intelligence] ************************/
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "j_inc_spawnin"
|
||||
|
||||
void main()
|
||||
{
|
||||
// 1 or 2 intelligence.
|
||||
SetAIInteger(AI_INTELLIGENCE, d2());
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
|
||||
// Probably worse for the AI to have these set - acts less intelligently.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_EQUIP_MOST_DAMAGING, AI_OTHER_MASTER);
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_LAG_TARGET_NEAREST_ENEMY, AI_OTHER_MASTER);
|
||||
|
||||
// Lots of other stuff is affected by having 1 or 2 intelligence anyway.
|
||||
// Removed a few of the immunity-checking bits, to lower effectivness.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0f, SpawnWalkWayPoints());
|
||||
}
|
38
_module/nss/no_ai_atk.nss
Normal file
38
_module/nss/no_ai_atk.nss
Normal file
@@ -0,0 +1,38 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Attacked
|
||||
//:: NW_C2_DEFAULT5
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Set attacker as an enemy if they are not a friend
|
||||
or enemy (ie/ neutral), and initiate combat AI if
|
||||
it is not already running.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oA = GetLastAttacker();
|
||||
|
||||
if ( GetIsObjectValid( oA ) )
|
||||
{
|
||||
/*
|
||||
if ( GetIsFriend( oA ) )
|
||||
{
|
||||
PrintString( GetName( OBJECT_SELF ) + " attacked by friend " + GetName( oA ) );
|
||||
}
|
||||
*/
|
||||
if ( !GetIsFriend( oA ) && !GetIsEnemy( oA ) && GetMaster( OBJECT_SELF ) != oA )
|
||||
{
|
||||
//neutrals
|
||||
SetIsTemporaryEnemy( oA, OBJECT_SELF, TRUE, 300.0 );
|
||||
}
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(1005));
|
||||
}
|
||||
}
|
36
_module/nss/no_ai_blk.nss
Normal file
36
_module/nss/no_ai_blk.nss
Normal file
@@ -0,0 +1,36 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Default On Heartbeat
|
||||
//:: NW_C2_DEFAULTE
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This will cause blocked creatures to open
|
||||
or smash down doors depending on int and
|
||||
str.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Preston Watamaniuk
|
||||
//:: Created On: Nov 23, 2001
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
NOTE: Unmodified except for this comment. Makes this
|
||||
script show up as a script for this module for completeness.
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
object oDoor = GetBlockingDoor();
|
||||
|
||||
if(GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 5)
|
||||
{
|
||||
if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_OPEN) && GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE) >= 7 )
|
||||
{
|
||||
DoDoorAction(oDoor, DOOR_ACTION_OPEN);
|
||||
}
|
||||
else if(GetIsDoorActionPossible(oDoor, DOOR_ACTION_BASH))
|
||||
{
|
||||
DoDoorAction(oDoor, DOOR_ACTION_BASH);
|
||||
}
|
||||
}
|
||||
}
|
20
_module/nss/no_ai_cmb.nss
Normal file
20
_module/nss/no_ai_cmb.nss
Normal file
@@ -0,0 +1,20 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: End of Combat Round
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Calls the end of combat script every round
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
//SetReadyStatus();
|
||||
//DoCombat();
|
||||
InitCombat();
|
||||
//signal combat to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1003 ) );
|
||||
}
|
162
_module/nss/no_ai_cnv.nss
Normal file
162
_module/nss/no_ai_cnv.nss
Normal file
@@ -0,0 +1,162 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Conversation
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
by the generic script after dialogue or a
|
||||
shout is initiated.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oT = OBJECT_INVALID;
|
||||
object oM = GetMaster( OBJECT_SELF );
|
||||
object oBroadcaster = GetLastSpeaker();
|
||||
int iBroadcast = GetListenPatternNumber();
|
||||
int iR = 0;
|
||||
|
||||
if ( iBroadcast == -1 )
|
||||
{
|
||||
ClearAllActions();
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
//ActionStartConversation( oBroadcaster );
|
||||
BeginConversation();
|
||||
//DoQueueShutdown( 6.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GetIsObjectValid( oM ) && oBroadcaster == oM )
|
||||
{
|
||||
if ( iBroadcast == ASSOCIATE_COMMAND_STANDGROUND )
|
||||
{
|
||||
//stand ground
|
||||
SetLocalLocation( OBJECT_SELF, "#SGLOC", GetLocation( OBJECT_SELF ) );
|
||||
SetLocalInt( OBJECT_SELF, "#STANDGROUND", 1 );
|
||||
ClearAllActions();
|
||||
PlayVoiceChat( VOICE_CHAT_TASKCOMPLETE );
|
||||
ActionMoveToLocation( GetLocation( OBJECT_SELF ) ); //stop here
|
||||
}
|
||||
else if ( iBroadcast == ASSOCIATE_COMMAND_ATTACKNEAREST )
|
||||
{
|
||||
//attack nearest
|
||||
DeleteLocalInt( OBJECT_SELF, "#STANDGROUND" );
|
||||
oT = GetTarget();
|
||||
if ( GetIsObjectValid( oT ) )
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_GOODIDEA );
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1003 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANTDO );
|
||||
}
|
||||
}
|
||||
else if ( iBroadcast == ASSOCIATE_COMMAND_HEALMASTER )
|
||||
{
|
||||
//heal master
|
||||
DeleteLocalInt( OBJECT_SELF, "#STANDGROUND" );
|
||||
if ( DoSpellHeal( oM ) )
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANDO );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANTDO );
|
||||
}
|
||||
}
|
||||
else if ( iBroadcast == ASSOCIATE_COMMAND_FOLLOWMASTER )
|
||||
{
|
||||
//follow master
|
||||
DeleteLocalLocation( OBJECT_SELF, "#STANDGROUND" );
|
||||
ClearAllActions();
|
||||
ActionForceFollowObject( oM, 3.0 );
|
||||
}
|
||||
else if ( iBroadcast == ASSOCIATE_COMMAND_GUARDMASTER )
|
||||
{
|
||||
//guard master
|
||||
DeleteLocalInt( OBJECT_SELF, "#STANDGROUND" );
|
||||
if ( !GetIsObjectValid( oT = GetLastHostileActor( oM ) ) )
|
||||
{
|
||||
if ( !GetIsObjectValid( oT = GetLastAttacker( oM ) ) )
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANTDO );
|
||||
}
|
||||
}
|
||||
//list of actions to try against oT
|
||||
if ( GetIsObjectValid( oT ) && ( GetObjectSeen( oT ) || GetObjectHeard( oT ) ) )
|
||||
{
|
||||
if ( !( iR = DoSpellDirect( oT ) ) )
|
||||
{
|
||||
if ( !( iR = DoTouch( oT ) ) )
|
||||
{
|
||||
if ( !( iR = DoAttackRanged( oT ) ) )
|
||||
{
|
||||
if ( !( iR = DoAttackMelee( oT ) ) )
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANTDO );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( iR )
|
||||
{
|
||||
PlayVoiceChat( VOICE_CHAT_CANDO );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( iBroadcast == 699 ) //COMBAT going on nearby
|
||||
{
|
||||
//respond
|
||||
if ( GetArea( oBroadcaster ) == GetArea( OBJECT_SELF ) && GetDistanceBetween( oBroadcaster, OBJECT_SELF ) <= GetResponseRange( BC_FIGHTING ) )
|
||||
{
|
||||
object oE = GetTarget();
|
||||
if ( !GetIsObjectValid( oE ) )
|
||||
{
|
||||
//I've heard combat but I can't see the combat or any enemies
|
||||
//PrintString( "CHM: " + GetName( OBJECT_SELF ) + " moving to support " + GetName( oBroadcaster ) );
|
||||
DoMoveToObject( oBroadcaster, TRUE, 5.0 );
|
||||
DoFightBroadcast();
|
||||
}
|
||||
else
|
||||
{
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//hearing something from another area or from out of our response range
|
||||
//SpeakString( "Ignoring combat sounds" );
|
||||
}
|
||||
}
|
||||
else if ( iBroadcast == 691 ) //DEAD
|
||||
{
|
||||
//if ( GetIsFriend( oBroadcaster ) )
|
||||
if ( GetFactionEqual( oBroadcaster ) )
|
||||
{
|
||||
DoVoiceChat( VOICE_CHAT_CUSS );
|
||||
}
|
||||
else if ( GetIsEnemy( oBroadcaster ) )
|
||||
{
|
||||
if ( Random( 2 ) )
|
||||
{
|
||||
DoVoiceChat( VOICE_CHAT_CHEER );
|
||||
}
|
||||
else
|
||||
{
|
||||
DoVoiceChat( VOICE_CHAT_LAUGH );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//signal conversation to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1004 ) );
|
||||
}
|
54
_module/nss/no_ai_dam.nss
Normal file
54
_module/nss/no_ai_dam.nss
Normal file
@@ -0,0 +1,54 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Damaged
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Set damager as an enemy if they are not a friend
|
||||
or enemy (ie/ neutral), and initiate combat AI if
|
||||
it is not already running.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
float fHP;
|
||||
object oDam = GetLastDamager();
|
||||
object oT = OBJECT_INVALID;
|
||||
|
||||
//if timestamp has elapsed and there is a friendly nearby
|
||||
if ( !GetLocalInt( OBJECT_SELF, "#HEALDEL" ) &&
|
||||
GetIsObjectValid( GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, 1, CREATURE_TYPE_IS_ALIVE, TRUE ) ) )
|
||||
{
|
||||
fHP = IntToFloat( GetCurrentHitPoints( OBJECT_SELF ) ) / GetMaxHitPoints( OBJECT_SELF );
|
||||
//only start calling for healing once we've taken 50%
|
||||
if ( fHP < 0.51 )
|
||||
{
|
||||
//broadcast request for healing for display purposes
|
||||
DoVoiceChat( VOICE_CHAT_HEALME );
|
||||
//do not broadcast again until next combat round event when this int is cleared
|
||||
SetLocalInt( OBJECT_SELF, "#HEALDEL", 1 );
|
||||
DelayCommand( 3.0, DeleteLocalInt( OBJECT_SELF, "#HEALDEL" ) );
|
||||
}
|
||||
}
|
||||
if ( GetIsObjectValid( oDam ) )
|
||||
{
|
||||
/*
|
||||
if ( GetIsFriend( oDam ) )
|
||||
{
|
||||
PrintString( GetName( OBJECT_SELF ) + " damaged by friend " + GetName( oDam ) );
|
||||
}
|
||||
*/
|
||||
if ( !GetIsFriend( oDam ) && !GetIsEnemy( oDam ) && GetMaster( OBJECT_SELF ) != oDam )
|
||||
{
|
||||
//neutrals
|
||||
SetIsTemporaryEnemy( oDam, OBJECT_SELF, TRUE, 300.0 );
|
||||
}
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
//signal damage to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1006 ) );
|
||||
}
|
||||
}
|
38
_module/nss/no_ai_dis.nss
Normal file
38
_module/nss/no_ai_dis.nss
Normal file
@@ -0,0 +1,38 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Default: On Disturbed
|
||||
//:: NW_C2_DEFAULT8
|
||||
//:: Copyright (c) 2001 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Calls the end of combat script every round
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Preston Watamaniuk
|
||||
//:: Created On: Oct 16, 2001
|
||||
//::///////////////////////////////////////////
|
||||
|
||||
// * Make me hostile the faction of my last attacker (TEMP)
|
||||
// AdjustReputation(OBJECT_SELF,GetFaction(GetLastAttacker()),-100);
|
||||
// * Determined Combat Round
|
||||
|
||||
/*
|
||||
NOTE: Blocked to stop interference.
|
||||
Update coming in next version.
|
||||
*/
|
||||
|
||||
//#include "NW_I0_GENERIC"
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oT = GetLastDisturbed();
|
||||
|
||||
if ( GetIsObjectValid( oT ) )
|
||||
{
|
||||
SetIsTemporaryEnemy( oT, OBJECT_SELF, TRUE, 300.0 );
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(1008));
|
||||
}
|
||||
}
|
32
_module/nss/no_ai_dth.nss
Normal file
32
_module/nss/no_ai_dth.nss
Normal file
@@ -0,0 +1,32 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Death
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Shouts to allies that they have been killed
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
//float fDieDelay = GetLocalFloat( OBJECT_SELF, "#DECAYDELAY" );
|
||||
//corpse decay deactivated for Murray module
|
||||
float fDieDelay = 10.0;
|
||||
|
||||
ClearAllActions();
|
||||
//broadcast death
|
||||
SpeakString( "BC_DEAD", TALKVOLUME_SILENT_TALK );
|
||||
//PrintString( GetName( OBJECT_SELF ) + " killed by " + GetName( GetLastKiller() ) );
|
||||
if ( GetName( GetItemInSlot( INVENTORY_SLOT_CARMOUR, OBJECT_SELF ) ) == "Balor Properties" )
|
||||
{
|
||||
ExecuteScript( "nw_s3_balordeth", OBJECT_SELF );
|
||||
}
|
||||
DelayCommand( fDieDelay, ExecuteScript( "no_scr_cleanvars", OBJECT_SELF ) );
|
||||
DelayCommand( fDieDelay + 0.5, ExecuteScript( "no_scr_excorpse", OBJECT_SELF ) );
|
||||
//signal death to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1007 ) );
|
||||
}
|
||||
|
121
_module/nss/no_ai_hrt.nss
Normal file
121
_module/nss/no_ai_hrt.nss
Normal file
@@ -0,0 +1,121 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Heartbeat
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This script will have people perform default
|
||||
animations.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
//if the AI level is very low and the combat AI is not active do nothing
|
||||
//need this change so that combat AI can shut itself down properly before ignoring heartbeats
|
||||
if ( GetAILevel() == AI_LEVEL_VERY_LOW && !IsActive() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( IsActive() )
|
||||
{
|
||||
//if combat AI is active this is the only segment of the heartbeat that will run
|
||||
int iE = GetHostileCount( 50.0 );
|
||||
if ( iE == 0 )
|
||||
{
|
||||
object oA = GetFurthestActiveAlly( 50.0 );
|
||||
if ( GetIsObjectValid( oA ) && GetDistanceBetween( OBJECT_SELF, oA ) > 20.0 && !GetIsPerceived( oA ) )
|
||||
{
|
||||
DoMoveToObject( oA, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteScript( "no_scr_shutdown", OBJECT_SELF );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//combat AI isn't active
|
||||
if( GetSpawnInCondition( NW_FLAG_DAY_NIGHT_POSTING ) )
|
||||
{
|
||||
int nDay = FALSE;
|
||||
if( GetIsDay() || GetIsDawn() )
|
||||
{
|
||||
nDay = TRUE;
|
||||
}
|
||||
if( GetLocalInt( OBJECT_SELF, "NW_GENERIC_DAY_NIGHT" ) != nDay )
|
||||
{
|
||||
if( nDay == TRUE )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "NW_GENERIC_DAY_NIGHT", TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "NW_GENERIC_DAY_NIGHT", FALSE );
|
||||
}
|
||||
WalkWayPoints();
|
||||
}
|
||||
}
|
||||
|
||||
if( CanAct() )
|
||||
{
|
||||
object oE = GetTarget();
|
||||
if( !GetIsPostOrWalking() )
|
||||
{
|
||||
if( !GetIsObjectValid( GetAttemptedAttackTarget() ) && !GetIsObjectValid( GetAttemptedSpellTarget() ) )
|
||||
{
|
||||
//if( !GetIsObjectValid( GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN) ) )
|
||||
if ( !GetIsObjectValid( oE ) )
|
||||
{
|
||||
if( /*!GetBehaviorState( NW_FLAG_BEHAVIOR_SPECIAL ) &&*/ !IsInConversation( OBJECT_SELF ) )
|
||||
{
|
||||
if( GetSpawnInCondition( NW_FLAG_AMBIENT_ANIMATIONS ) || GetSpawnInCondition( NW_FLAG_AMBIENT_ANIMATIONS_AVIAN ) )
|
||||
{
|
||||
PlayMobileAmbientAnimations();
|
||||
}
|
||||
else if( GetIsEncounterCreature() )
|
||||
//won't be here unless this next condition is true so it is redundant to check it
|
||||
//!GetIsObjectValid( GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN ) ) )
|
||||
{
|
||||
PlayMobileAmbientAnimations();
|
||||
}
|
||||
else if( GetSpawnInCondition( NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS ) )
|
||||
//won't be in here unless this next condition is true so it is redundant to check it
|
||||
//!GetIsObjectValid( GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN ) ) )
|
||||
{
|
||||
PlayImmobileAmbientAnimations();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DetermineSpecialBehavior();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//DetermineCombatRound()
|
||||
InitCombat();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetSpawnInCondition( NW_FLAG_SLEEPING_AT_NIGHT ) )
|
||||
{
|
||||
effect eVis = EffectVisualEffect( VFX_IMP_SLEEP );
|
||||
if( d10() > 6 )
|
||||
{
|
||||
ApplyEffectToObject( DURATION_TYPE_INSTANT, eVis, OBJECT_SELF );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Signal heart beat event to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1001 ) );
|
||||
}
|
98
_module/nss/no_ai_per.nss
Normal file
98
_module/nss/no_ai_per.nss
Normal file
@@ -0,0 +1,98 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Percieve
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Checks to see if the perceived target is an
|
||||
enemy and if so fires the Determine Combat
|
||||
Round function
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPer = GetLastPerceived();
|
||||
|
||||
if ( !GetIsObjectValid( oPer ) )
|
||||
{
|
||||
//invalid object, do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
//for associates
|
||||
if ( !GetLocalInt( OBJECT_SELF, "#ACTIVE" ) && GetIsMaster( oPer ) )
|
||||
{
|
||||
ActionForceFollowObject( oPer, GetFollowDist() );
|
||||
}
|
||||
|
||||
//main
|
||||
if ( GetLastPerceptionSeen() && GetIsPerceived( oPer, NO_PERCEPTION_SEEN ) )
|
||||
{
|
||||
if ( GetIsEnemy( oPer ) && !GetIsDead( oPer ) )
|
||||
{
|
||||
//trigger combat
|
||||
//PrintString( "ENEMY: " + GetName( OBJECT_SELF ) + " -> " + GetName( oPer ) );
|
||||
DoVoiceChat( VOICE_CHAT_ENEMIES );
|
||||
if ( GetIsFastBuffer() == TRUE && GetIsFastBuffed() == FALSE )
|
||||
{
|
||||
//only to this once per start up
|
||||
ClearAllActions();
|
||||
if ( DoFastBuffs() )
|
||||
{
|
||||
//PrintString( "FASTBUFF: " + GetName( OBJECT_SELF ) );
|
||||
}
|
||||
SetIsFastBuffed( TRUE );
|
||||
}
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
DelayCommand( 0.5, InitCombat() );
|
||||
}
|
||||
else if ( !GetLocalInt( OBJECT_SELF, "#ACTIVE" ) )
|
||||
{
|
||||
if ( GetIsFriend( oPer ) && GetIsDead( oPer ) && GetHasRaisingAbility() )
|
||||
{
|
||||
ClearAllActions();
|
||||
if ( DoSpellRaise( oPer ) )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
DoQueueShutdown( 12.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( GetLastPerceptionHeard() && GetIsPerceived( oPer, NO_PERCEPTION_HEARD ) )
|
||||
{
|
||||
if ( !GetIsObjectValid( GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE ) ) )
|
||||
{
|
||||
if ( GetIsEnemy( oPer ) && GetObjectType( oPer ) == OBJECT_TYPE_CREATURE && !GetIsDead( oPer ) )
|
||||
{
|
||||
//check perceptions
|
||||
if ( !GetIsPerceived( oPer, NO_PERCEPTION_SEEN ) )
|
||||
{
|
||||
//heard something that is not visible, no visible enemies, respond
|
||||
//SetLocalInt( OBJECT_SELF, "#VANISHED", 1 );
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
DelayCommand( 0.5, InitCombat() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( GetLastPerceptionVanished() && GetIsPerceived( oPer, NO_PERCEPTION_VANISHED ) )
|
||||
{
|
||||
//make sure it isn't a corpse that just faded out
|
||||
//report vanished enemies who have not just died
|
||||
if ( GetIsEnemy( oPer ) )
|
||||
{
|
||||
if( !GetIsDead( oPer ) )
|
||||
{
|
||||
DoVoiceChat( VOICE_CHAT_CUSS );
|
||||
SetLocalInt( OBJECT_SELF, "#VANISHED", 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
//signal perception to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1002 ) );
|
||||
}
|
||||
|
26
_module/nss/no_ai_rst.nss
Normal file
26
_module/nss/no_ai_rst.nss
Normal file
@@ -0,0 +1,26 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Default: On Rested
|
||||
//:: NW_C2_DEFAULTA
|
||||
//:: Copyright (c) 2002 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just rested.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Don Moar
|
||||
//:: Created On: April 28, 2002
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
NOTE: Unmodified except for this comment. Makes this
|
||||
script show up as a script for this module for completeness.
|
||||
*/
|
||||
|
||||
void main()
|
||||
{
|
||||
// enter desired behaviour here
|
||||
|
||||
return;
|
||||
|
||||
}
|
70
_module/nss/no_ai_spt.nss
Normal file
70
_module/nss/no_ai_spt.nss
Normal file
@@ -0,0 +1,70 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spell Cast At
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This determines if the spell just cast at the
|
||||
target is harmful or not.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
int iS = GetLastSpell();
|
||||
int iH = GetLastSpellHarmful();
|
||||
object oC = GetLastSpellCaster();
|
||||
|
||||
if ( !iH )
|
||||
{
|
||||
if ( iS == SPELL_RAISE_DEAD || iS == SPELL_RESURRECTION )
|
||||
{
|
||||
SetCommandable( TRUE, OBJECT_SELF );
|
||||
DeleteLocalObject( OBJECT_SELF, "#RAISER" );
|
||||
}
|
||||
else if ( iS == SPELL_HEAL || iS == SPELL_CURE_CRITICAL_WOUNDS ||
|
||||
iS == SPELL_CURE_SERIOUS_WOUNDS || iS == SPELL_CURE_MODERATE_WOUNDS ||
|
||||
iS == SPELL_CURE_LIGHT_WOUNDS || iS == SPELL_CURE_MINOR_WOUNDS )
|
||||
{
|
||||
if ( oC != OBJECT_SELF && GetIsFriend( oC ) )
|
||||
{
|
||||
DoVoiceChat( VOICE_CHAT_THANKS );
|
||||
}
|
||||
DeleteLocalObject( OBJECT_SELF, "#HEALER" );
|
||||
}
|
||||
else if ( iS == SPELL_DARKVISION )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#DARKNESS" );
|
||||
DeleteLocalObject( OBJECT_SELF, "#VISION" );
|
||||
}
|
||||
else if ( iS == SPELL_SEE_INVISIBILITY )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#VANISHED" );
|
||||
DeleteLocalObject( OBJECT_SELF, "#VISION" );
|
||||
}
|
||||
else if ( iS == SPELL_TRUE_SEEING )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#DARKNESS" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#VANISHED" );
|
||||
DeleteLocalObject( OBJECT_SELF, "#VISION" );
|
||||
}
|
||||
}
|
||||
if ( iS == SPELL_DARKNESS )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "#DARKNESS", 1 );
|
||||
}
|
||||
if ( iH )
|
||||
{
|
||||
if ( !GetIsFriend( oC ) && !GetIsEnemy( oC ) && GetMaster( OBJECT_SELF ) != oC )
|
||||
{
|
||||
//neutrals
|
||||
SetIsTemporaryEnemy( oC, OBJECT_SELF, TRUE, 300.0 );
|
||||
}
|
||||
//DoQueueCombat( 8.0, 8.0 );
|
||||
InitCombat();
|
||||
}
|
||||
//signal spell at to userdef
|
||||
SignalEvent( OBJECT_SELF, EventUserDefined( 1011 ) );
|
||||
}
|
10
_module/nss/no_inc.nss
Normal file
10
_module/nss/no_inc.nss
Normal file
@@ -0,0 +1,10 @@
|
||||
//#include "no_lib_data"
|
||||
#include "no_inc_ptypes"
|
||||
#include "no_lib_bio"
|
||||
#include "no_lib_priority"
|
||||
#include "no_lib_magic"
|
||||
#include "no_lib_analysis"
|
||||
#include "no_lib_feat"
|
||||
#include "no_lib_melee"
|
||||
#include "no_lib_ranged"
|
||||
#include "no_lib_actions"
|
408
_module/nss/no_inc_ptypes.nss
Normal file
408
_module/nss/no_inc_ptypes.nss
Normal file
@@ -0,0 +1,408 @@
|
||||
//constants
|
||||
|
||||
//can broadcasting use DM channel
|
||||
const int NO_CAN_USE_DM_CHANNEL = 1;
|
||||
|
||||
//broadcast constants
|
||||
const int BC_FIGHTING = 699;
|
||||
|
||||
//effect weights
|
||||
const int NO_EFFECT_GENERIC = 1;
|
||||
const int NO_EFFECT_DISEASE = 2;
|
||||
const int NO_EFFECT_CURSE = 4;
|
||||
const int NO_EFFECT_POISON = 8;
|
||||
const int NO_EFFECT_DEAF = 16;
|
||||
const int NO_EFFECT_BLINDNESS = 32;
|
||||
const int NO_EFFECT_SILENCE = 64;
|
||||
const int NO_EFFECT_NEGATIVELEVEL = 128;
|
||||
const int NO_EFFECT_DAZED = 256;
|
||||
const int NO_EFFECT_FRIGHTENED = 512;
|
||||
const int NO_EFFECT_CONFUSED = 1024;
|
||||
const int NO_EFFECT_CHARMED = 2048;
|
||||
const int NO_EFFECT_SLEEP = 4096;
|
||||
const int NO_EFFECT_STUNNED = 8192;
|
||||
const int NO_EFFECT_DOMINATED = 16384;
|
||||
const int NO_EFFECT_PETRIFY = 32768;
|
||||
const int NO_EFFECT_PARALYZE = 65536;
|
||||
|
||||
//spell level cut offs
|
||||
const int NO_LVL8_MIN_LVL = 24;
|
||||
const int NO_LVL7_MIN_LVL = 21;
|
||||
const int NO_LVL6_MIN_LVL = 18;
|
||||
const int NO_LVL5_MIN_LVL = 15;
|
||||
const int NO_LVL4_MIN_LVL = 12;
|
||||
const int NO_LVL3_MIN_LVL = 9;
|
||||
const int NO_LVL2_MIN_LVL = 6;
|
||||
const int NO_LVL1_MIN_LVL = 3;
|
||||
|
||||
//associate orders
|
||||
const int NO_ORDER_ATTACK = 1;
|
||||
const int NO_ORDER_FOLLOW = 2;
|
||||
const int NO_ORDER_GUARD = 4;
|
||||
const int NO_ORDER_HEAL = 8;
|
||||
const int NO_ORDER_STANDGROUND = 16;
|
||||
|
||||
//voice chat defines
|
||||
const int NO_VC_DEFAULT = 1000;
|
||||
const int NO_VC_MELEE = 1001;
|
||||
const int NO_VC_RANGED = 1003;
|
||||
const int NO_VC_MELEEASSIST = 1004;
|
||||
|
||||
//perception types
|
||||
const int NO_PERCEPTION_SEEN = 1;
|
||||
const int NO_PERCEPTION_HEARD = 2;
|
||||
const int NO_PERCEPTION_VANISHED = 4;
|
||||
|
||||
//special attack minimum hit dice ratios
|
||||
const float NO_THRESH_SMITE = 0.75;
|
||||
const float NO_THRESH_STUNNING_FIST = 0.5;
|
||||
const float NO_THRESH_QUIVERING_PALM = 0.75;
|
||||
const float NO_THRESH_ARROW_SLAYING = 0.75;
|
||||
const float NO_THRESH_KI_DAMAGE = 0.5;
|
||||
|
||||
//illithid abilities
|
||||
const int CODI_MIND_BLAST = 1522;
|
||||
const int CODI_BRAIN_EXTRACT = 1523;
|
||||
|
||||
//beholder constants
|
||||
const int BEHOLDER_MAX_RAYS = 10;
|
||||
const int SPELL_BEHRAY_FINGER_OF_DEATH = 776;
|
||||
const int SPELL_BEHRAY_TELEKINESIS = 777;
|
||||
const int SPELL_BEHRAY_FLESH_TO_STONE = 778;
|
||||
const int SPELL_BEHRAY_CHARM = 779;
|
||||
const int SPELL_BEHRAY_SLOW = 780;
|
||||
const int SPELL_BEHRAY_INFLICT_WOUNDS = 783;
|
||||
const int SPELL_BEHRAY_FEAR = 784;
|
||||
const int SPELL_BEH_ANTIMAGIC_CONE = 727;
|
||||
|
||||
//missing epic spell definition
|
||||
const int SPELL_EPIC_WARDING = 695;
|
||||
|
||||
//miscellaneous missing constants
|
||||
const int SPELLABILITY_DRAGON_BREATH_RDD = 690;
|
||||
const int SPELLABILITY_DRAGON_BREATH_PRISMATIC = 771;
|
||||
const int SPELLABILITY_DEFLECTING_FORCE = 774;
|
||||
|
||||
//string constants
|
||||
const string s_BEHOLDER_CENTRAL_EYE_FLAG = "#BEHCENEYE";
|
||||
|
||||
#include "no_lib_data"
|
||||
|
||||
//Master prototype list
|
||||
|
||||
// NO_LIB_ACTIONS
|
||||
// support functions
|
||||
void NO_ActionCastSpellAtLocation( int iSpell, location lTargetLocation, int iMetaMagic=METAMAGIC_ANY, int iCheat=FALSE, int iProjectilePathType=PROJECTILE_PATH_TYPE_DEFAULT, int iInstantSpell=FALSE, int iDefensive=TRUE );
|
||||
void NO_ActionCastSpellAtObject( int iSpell, object oTarget, int iMetaMagic=METAMAGIC_ANY, int iCheat=FALSE, int iDomainLevel=0, int iProjectilePathType=PROJECTILE_PATH_TYPE_DEFAULT, int iInstantSpell=FALSE, int iDefensive=TRUE );
|
||||
void NO_ActionUseTalentAtLocation( talent tChosenTalent, location lTargetLocation, int iDefensive=TRUE );
|
||||
void NO_ActionUseTalentOnObject( talent tChosenTalent, object oTarget, int iDefensive=TRUE );
|
||||
void ActivateCombatMode( int iMode=0, object oE=OBJECT_SELF );
|
||||
void DeactivateCombatModes( int iException=0, object oE=OBJECT_SELF );
|
||||
int DoHideInPlainSight( object oE=OBJECT_SELF );
|
||||
void DoFireBeholderRay( int iS, object oT );
|
||||
void DoMoveToLocation( location lDest, int bRun=FALSE );
|
||||
void DoMoveToObject( object oDest, int bRun=FALSE, float fDist=1.0f );
|
||||
void DoTeleport( location lLoc );
|
||||
object GetTarget();
|
||||
float DotProduct( vector v1, vector v2 );
|
||||
location GetFlankLoc( object oT, location lL );
|
||||
void DoEquipMelee( object oT );
|
||||
talent GetTalentSpell( int iCat, int iD );
|
||||
void DoFightBroadcast();
|
||||
int GetTimeSinceLastCombat();
|
||||
void DoConditionalRestart( float fT=6.0 );
|
||||
void DoQueueShutdown( float fT=0.0 );
|
||||
void DoQueueCombat( float fD=6.0, float fT=6.0 );
|
||||
void InitCombat( object oE=OBJECT_INVALID );
|
||||
void DoVoiceChat( int iV=-1 );
|
||||
void DoMainCombatLoop();
|
||||
void DoCombat();
|
||||
// action functions
|
||||
int DoAttackMelee( object oT=OBJECT_INVALID );
|
||||
int DoAttackRanged( object oT=OBJECT_INVALID );
|
||||
int DoCounterSpell( object oT=OBJECT_INVALID );
|
||||
int DoEvacAOE();
|
||||
int DoRegroup( object oT=OBJECT_INVALID );
|
||||
int DoDefendSelf();
|
||||
int DoDefendSingle( object oT=OBJECT_INVALID );
|
||||
int DoEnhanceSelf();
|
||||
int DoEnhanceSingle( object oT=OBJECT_INVALID );
|
||||
int DoSpellHelp( object oT=OBJECT_INVALID );
|
||||
int DoSpellHeal( object oT=OBJECT_INVALID );
|
||||
int DoSpellRaise( object oT=OBJECT_INVALID );
|
||||
int DoSpellBreach( object oT=OBJECT_INVALID );
|
||||
int DoSpellDirect( object oT=OBJECT_INVALID );
|
||||
int DoTouch( object oT=OBJECT_INVALID );
|
||||
int DoSpellArea();
|
||||
int DoSpellSummon();
|
||||
int DoSpellCharm();
|
||||
int DoFeatEnhance();
|
||||
int DoAvoidMelee();
|
||||
int DoTimeStop();
|
||||
int DoVision();
|
||||
int DoBreathWeapon();
|
||||
int DoTurning();
|
||||
int DoSpellCone();
|
||||
int DoHealSelf();
|
||||
int DoSpellGroupEnhance();
|
||||
int DoSpellGroupHeal();
|
||||
int DoDispelPersAOE();
|
||||
int DoDispelSingle();
|
||||
int DoDismissal();
|
||||
int DoFastBuffs();
|
||||
int DoMeleeAssist();
|
||||
int DoFlank( object oE=OBJECT_INVALID );
|
||||
int DoMindBlast();
|
||||
int DoBrainExtraction();
|
||||
int DoAvoidEnemies();
|
||||
int DoGrenade();
|
||||
int DoBeholderRays();
|
||||
int DoBeholderCentralEye();
|
||||
|
||||
// NO_LIB_ANALYSIS
|
||||
int GetAOEThreat( object oArea, object oEnt=OBJECT_SELF );
|
||||
int GetAOECount( float fRad=10.0f, object oEnt=OBJECT_SELF );
|
||||
vector GetAOEVector( float fRad=10.0f, object oEnt=OBJECT_SELF );
|
||||
int GetHostileAOECount( float fRad=10.0f, object oEnt=OBJECT_SELF );
|
||||
vector GetHostileAOEVector( float fRad=10.0f, object oEnt=OBJECT_SELF );
|
||||
vector GetAOEEvacVector( vector vS, object oEnt=OBJECT_SELF );
|
||||
object GetMostDamagedAlly( float fRad=15.0f, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
object GetLowestHPAlly( float fRad=15.0, int iLim=0, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
object GetLowestHPAllyNoHealer( float fRad=15.0, int iLim=0, object oEnt=OBJECT_SELF, int iSee=FALSE, int iLive=TRUE );
|
||||
object GetNearestDeadAlly( float fRad=15.0f, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
object GetNearestDeadAllyNoRaiser( float fRad=15.0f, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
object GetNearestPetrifiedAllyNoHelper( float fRad=15.0f, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
int GetEffectsOnObject( object oEnt=OBJECT_SELF );
|
||||
object GetMostHamperedAlly( float fRad=15.0f, object oEnt=OBJECT_SELF, int iSee=FALSE );
|
||||
vector GetAreaTarget( int iS, float fRad, float fMinRad=7.5, float fMaxRad=30.0, int iEffChk=TRUE, object oCaster=OBJECT_SELF );
|
||||
vector GetFriendlyAreaTarget( float fRad, int iSpell=0, int iType=0, object oCaster=OBJECT_SELF );
|
||||
int CanAct( object oSelf=OBJECT_SELF );
|
||||
int GetIsWeapon( object oWeapon );
|
||||
int GetIsLightWeapon( object oWeapon, int iCanBeInvalid=FALSE );
|
||||
int GetIsDoubleWeapon( object oWeapon );
|
||||
int GetCasterCount( float fRad=5.0, object oEnt=OBJECT_SELF );
|
||||
int GetAttackerCount( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetHostileCount( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetOmniscientHostileCount( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetAllyCount( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetAttackerHD( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetHostileHD( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
int GetAllyHD( float fRad=5.0, object oEnt=OBJECT_SELF, object oS=OBJECT_SELF );
|
||||
vector GetHostileVector( float fRad=10.0f, object oEnt=OBJECT_SELF );
|
||||
vector GetHostileEvacVector( vector vS, object oEnt=OBJECT_SELF );
|
||||
int GetIsCaster( object oEnt=OBJECT_SELF );
|
||||
int DoAbilityCheck( int iAbil, int iDC, object oEnt=OBJECT_SELF );
|
||||
int DoCombatKnowledgeCheck( int iBAB=FALSE, int iDC=10, object oE=OBJECT_SELF );
|
||||
float GetFriendFoeRatio( location lLoc, float fRad, object oEnt=OBJECT_SELF );
|
||||
float GetFriendFoeTolerance( object oEnt=OBJECT_SELF );
|
||||
object GetNearestEnemyCaster( int iMaxLvl=20, int iMinLvl=1, object oEnt=OBJECT_SELF );
|
||||
int GetAverageEnemyLevel( float fRad=60.0, object oEnt=OBJECT_SELF );
|
||||
int GetSafeAverageEnemyLevel( float fRad=40.0, object oEnt=OBJECT_SELF );
|
||||
object GetLeastMagicDefendedEnemy( float fRad=5.0, object oEnt=OBJECT_SELF );
|
||||
vector GetTurningVector( object oEnt=OBJECT_SELF );
|
||||
int GetIsValidTurnTarget( object oT, int iL=0, object oEnt=OBJECT_SELF );
|
||||
int GetPotionHealAmount( object oP );
|
||||
int GetTalentPotionHealAmount( talent tP );
|
||||
vector GetAreaHealTarget( float fRad=0.0, int iH=0, object oEnt=OBJECT_SELF );
|
||||
float GetAllyDamageStats( location lT, float fRad=0.0, object oEnt=OBJECT_SELF );
|
||||
object GetMostBuffedEnemy( float fRad=10.0, object oEnt=OBJECT_SELF );
|
||||
object GetLeastBuffedAlly( float fRad=10.0, int iMelee=FALSE, object oEnt=OBJECT_SELF );
|
||||
int GetIsBuffEffect( effect eT );
|
||||
int GetAverageEffectCasterLevel( object oT=OBJECT_SELF );
|
||||
object GetStrongestEnemySummonedAssociateOwner( float fRad=10.0, object oEnt=OBJECT_SELF );
|
||||
vector GetEnemySummonedAssociatesVector( float fRad=10.0, object oEnt=OBJECT_SELF );
|
||||
vector GetEnemyPlanarVector( float fRad=10.0, object oEnt=OBJECT_SELF );
|
||||
object GetVisionDeprived( float fRad=10.0, object oT=OBJECT_SELF );
|
||||
object GetLeastDefendedAlly( float fRad=10.0, object oC=OBJECT_SELF );
|
||||
int GetHasRangedCapability( object oEnt=OBJECT_SELF );
|
||||
int GetIsRangedWeapon( object oW=OBJECT_INVALID );
|
||||
object GetMostDistantEnemy( float fR=30.0, int iS=TRUE, object oC=OBJECT_SELF );
|
||||
vector GetSaves( object oT=OBJECT_SELF );
|
||||
vector GetBaseSavesByClass( int iC, int iL );
|
||||
vector GetAverageEnemySaveInArea( vector vP, float fR=5.0, object oC=OBJECT_SELF );
|
||||
int IsImmuneToPetrification(object oCreature);
|
||||
object GetNearestAddledEnemy( float fRange=10.0, object oE=OBJECT_SELF );
|
||||
object GetNearestAddledEnemyNoExtractor( float fRange=10.0, object oE=OBJECT_SELF );
|
||||
int IsBrainExtractable( object oT );
|
||||
int GetCreatureAttackBonus( object oC=OBJECT_SELF );
|
||||
int GetGrappleBonus( object oC=OBJECT_SELF );
|
||||
int GetIsMaster( object oM, object oE=OBJECT_SELF );
|
||||
int GetIsPerceived( object oP, int iP=0, object oE=OBJECT_SELF );
|
||||
object GetNearestPerceivedCreature( int iP=NO_PERCEPTION_SEEN, object oE=OBJECT_SELF );
|
||||
object GetNearestActiveAlly( object oE=OBJECT_SELF );
|
||||
object GetFurthestActiveAlly( float fD=50.0, object oE=OBJECT_SELF );
|
||||
int EstimateAttackBonus( object oC=OBJECT_SELF );
|
||||
int GetDualWieldingPenalty( object oC=OBJECT_SELF, object oR=OBJECT_INVALID, object oL=OBJECT_INVALID );
|
||||
int GetHasWeaponFocus( object oR, object oC=OBJECT_SELF );
|
||||
int GetIsArmed( object oEnt=OBJECT_SELF );
|
||||
int GetRelativeEnemyWeaponSize( object oT, object oEnt=OBJECT_SELF );
|
||||
int GetWeaponSize( object oEnt=OBJECT_SELF );
|
||||
float GetAverageDistanceToEnemy( float fRad=60.0, object oEnt=OBJECT_SELF );
|
||||
int GetCombatModeModifier( int iMode=0 );
|
||||
int GetCombatConcentration( object oE=OBJECT_SELF );
|
||||
int GetTurningLevel( object oC=OBJECT_SELF );
|
||||
void SetIsCentralEyeOpen( int iS=FALSE, object oB=OBJECT_SELF );
|
||||
int GetIsCentralEyeOpen( object oB=OBJECT_SELF );
|
||||
|
||||
// NO_LIB_FEAT
|
||||
int GetEnhanceFeat( object oEnt=OBJECT_SELF );
|
||||
int GetGroupEnhanceFeat( object oEnt=OBJECT_SELF );
|
||||
float GetGroupEnhanceFeatRadius( int iFeat );
|
||||
|
||||
// NO_LIB_MAGIC
|
||||
int GetBestMagicDefenseSelf( object oEnt=OBJECT_SELF );
|
||||
int GetBestMagicDefenseSingle( object oEnt=OBJECT_SELF, object oC=OBJECT_SELF );
|
||||
int GetBestPhysDefenseSelf( object oEnt=OBJECT_SELF );
|
||||
int GetBestPhysDefenseSingle( object oEnt=OBJECT_SELF, object oC=OBJECT_SELF );
|
||||
int GetBestGenericProtection( object oEnt=OBJECT_SELF );
|
||||
struct sSpellDefStatus EvaluateSpellDefenses( object oTarget=OBJECT_SELF );
|
||||
struct sPhysDefStatus EvaluatePhysicalDefenses( object oTarget=OBJECT_SELF );
|
||||
int GetBestHeal( object oEnt=OBJECT_SELF, int iMin=10 );
|
||||
int GetGroupHealSpell( int iMinLvl=0, object oCaster=OBJECT_SELF );
|
||||
int GetGroupHealSpellAmount( int iH=0, object oCaster=OBJECT_SELF );
|
||||
float GetGroupHealSpellRadius( int iH=0 );
|
||||
int GetBestRaise( int iCombat=FALSE );
|
||||
int GetHasHealingAbility( object oCaster=OBJECT_SELF );
|
||||
int GetHasRaisingAbility( object oCaster=OBJECT_SELF );
|
||||
int GetHasHelpingAbility( object oCaster=OBJECT_SELF );
|
||||
int GetBestHelp( object oEnt, object oCaster=OBJECT_SELF );
|
||||
int GetAreaSpell( vector vS, int iDisc=FALSE, int iMinLvl=0, float fR=40.0, object oCaster=OBJECT_SELF );
|
||||
float GetAreaSpellRadius( int iSpell );
|
||||
int GetDirectSpell( object oT, int iDisc=FALSE, int iMinLvl=0, object oCaster=OBJECT_SELF );
|
||||
int GetTouchSpell( object oT, int iMinLvl=0, object oCaster=OBJECT_SELF );
|
||||
int GetSummonSpell( int iMinLvl=1, object oCaster=OBJECT_SELF );
|
||||
int GetEnhanceSpellSelf( int iMinLvl=1, object oCaster=OBJECT_SELF );
|
||||
int GetEnhanceSpellSingle( int iMinLvl=1, object oEnt=OBJECT_SELF, object oCaster=OBJECT_SELF );
|
||||
int GetBestBreach( int iLim=30, object oEnt=OBJECT_SELF );
|
||||
int GetBestDispel( int iCLvl=20, int iDLvl=20, object oEnt=OBJECT_SELF );
|
||||
int GetIsDiscriminantSpell( int iSpell );
|
||||
int GetBreathWeapon( object oEnt=OBJECT_SELF );
|
||||
int GetConeSpell( int iMinLvl = 1, object oCaster=OBJECT_SELF );
|
||||
int GetGroupEnhanceSpell( int iMinLvl = 1, object oCaster=OBJECT_SELF );
|
||||
float GetGroupEnhanceSpellRadius( int iSpell );
|
||||
int GetDispelSpell( object oEnt=OBJECT_SELF );
|
||||
int GetMaxDispelCasterLevel( object oEnt=OBJECT_SELF );
|
||||
int GetVisionSpellNeeded( object oS=OBJECT_SELF, object oC=OBJECT_SELF );
|
||||
int GetHasVisionSpells( object oC=OBJECT_SELF );
|
||||
int GenerateFastBuffList( object oC=OBJECT_SELF );
|
||||
float GetSpellRange( int iS );
|
||||
int IsCone( int iS=0 );
|
||||
int IsDragonBreath( int iS=0 );
|
||||
int IsHowl( int iS=0 );
|
||||
int IsPulse( int iS=0 );
|
||||
void InitializeBeholderRaySelection( object oB=OBJECT_SELF );
|
||||
void ClearBeholderRaySelection( object oB=OBJECT_SELF );
|
||||
void RemoveBeholderRayFromSelection( int iS=0, object oB=OBJECT_SELF );
|
||||
int MatchRayToTarget( object oT, object oB=OBJECT_SELF );
|
||||
|
||||
// NO_LIB_MELEE
|
||||
int GetBestMeleeSpecial( object oTarget, int iPenalty=0, int iChance=50, object oEnt=OBJECT_SELF );
|
||||
int SelectMeleeCombatModes( object oT, int iC=50, object oEnt=OBJECT_SELF );
|
||||
|
||||
// NO_LIB_RANGED
|
||||
int GetBestRangedSpecial( object oTarget, int iPenalty=0, int iChance=50, object oEnt=OBJECT_SELF );
|
||||
int SelectRangedCombatModes( object oT, int iC=50, object oEnt=OBJECT_SELF );
|
||||
|
||||
// NO_LIB_PRIORITY
|
||||
void AddBehaviour( string sB, int iC, object oEnt=OBJECT_SELF );
|
||||
string GetPriority( int iP=1, object oEnt=OBJECT_SELF );
|
||||
int GetPriorityChance( int iP=1, object oEnt=OBJECT_SELF );
|
||||
void SetVoiceChat( int iV, int iC, object oE=OBJECT_SELF );
|
||||
float GetFollowDist( object oE=OBJECT_SELF );
|
||||
void SetPerceptionRange( int iP, float fP=50.0, object oE=OBJECT_SELF );
|
||||
void SetPerceptionRanges( float fS=50.0, float fH=50.0, float fV=50.0, object oE=OBJECT_SELF );
|
||||
float GetPerceptionRange( int iP, object oE=OBJECT_SELF );
|
||||
void SetReadyStatus( int iS=1, object oE=OBJECT_SELF );
|
||||
int IsReadyToAct( object oE=OBJECT_SELF );
|
||||
int ShortAction( object oE=OBJECT_SELF );
|
||||
int IsActive( object oE=OBJECT_SELF );
|
||||
void SetActive( object oE=OBJECT_SELF );
|
||||
void SetIsActive( int iA=TRUE, object oE=OBJECT_SELF );
|
||||
float GetResponseRange( int iT, object oE=OBJECT_SELF );
|
||||
void SetResponseRange( int iT, float fR=50.0, object oE=OBJECT_SELF );
|
||||
void SetIsTeleporter( object oE=OBJECT_SELF );
|
||||
int GetIsTeleporter( object oE=OBJECT_SELF );
|
||||
void SetIsFastBuffer( int iS, object oE=OBJECT_SELF );
|
||||
int GetIsFastBuffer( object oE=OBJECT_SELF );
|
||||
void SetIsFastBuffed( int iS, object oE=OBJECT_SELF );
|
||||
int GetIsFastBuffed( object oE=OBJECT_SELF );
|
||||
void AddFastBuff( int iS, object oE=OBJECT_SELF );
|
||||
int CountFastBuffs( object oE=OBJECT_SELF );
|
||||
void SetLastAction( string sA, object oE=OBJECT_SELF );
|
||||
string GetLastAction( object oE=OBJECT_SELF );
|
||||
void SetLastActionTimestamp( object oE=OBJECT_SELF );
|
||||
int GetLastActionTimestamp( object oE=OBJECT_SELF );
|
||||
void SetCorpseDelay( int iT=60, object oC=OBJECT_SELF );
|
||||
void SetIsFlier( int iF=FALSE, object oF=OBJECT_SELF );
|
||||
int GetIsFlier( object oF=OBJECT_SELF );
|
||||
|
||||
// NO_LIB_BIO
|
||||
void SetSpawnInCondition(int nCondition, int bValid = TRUE);
|
||||
int GetSpawnInCondition(int nCondition);
|
||||
void SetSpawnInLocals(int nCondition);
|
||||
void SetListeningPatterns();
|
||||
void WalkWayPoints(int nRun = FALSE, float fPause = 1.0);
|
||||
void RunNextCircuit(int nRun = FALSE, float fPause = 1.0);
|
||||
void RunCircuit(int nTens, int nNum, int nRun = FALSE, float fPause = 1.0);
|
||||
int CheckWayPoints(object oWalker = OBJECT_SELF);
|
||||
int GetIsPostOrWalking(object oWalker = OBJECT_SELF);
|
||||
//void SetBehaviorState(int nCondition, int bValid = TRUE);
|
||||
//int GetBehaviorState(int nCondition);
|
||||
void PlayMobileAmbientAnimations();
|
||||
//void PlayImmobileAmbientAnimations();
|
||||
void DetermineSpecialBehavior(object oIntruder = OBJECT_INVALID);
|
||||
void ClearActions(int nClearConstant=0, int bClearCombat=FALSE);
|
||||
//SoU animation craziness
|
||||
void AnimDebug(string sMsg);
|
||||
int GetAnimationCondition(int nCondition, object oCreature=OBJECT_SELF);
|
||||
void SetAnimationCondition(int nCondition, int bValid=TRUE, object oCreature=OBJECT_SELF);
|
||||
int GetIsBusyWithAnimation(object oCreature);
|
||||
object GetRandomFriend(float fMaxDistance);
|
||||
object GetRandomObjectByTag(string sTag, float fMaxDistance);
|
||||
object GetRandomObjectByType(int nObjType, float fMaxDistance);
|
||||
object GetRandomStop(float fMaxDistance);
|
||||
void SetCreatureHomeWaypoint();
|
||||
object GetCreatureHomeWaypoint();
|
||||
void SetCurrentFriend(object oFriend);
|
||||
object GetCurrentFriend();
|
||||
void SetCurrentInteractionTarget(object oTarget);
|
||||
object GetCurrentInteractionTarget();
|
||||
void CheckIsCivilized();
|
||||
void CheckCurrentModes();
|
||||
int CheckIsAnimActive(object oCreature);
|
||||
int CheckCurrentAction();
|
||||
void AnimInitialization();
|
||||
void PlayMobileAmbientAnimations_NonAvian();
|
||||
void PlayMobileAmbientAnimations_Avian();
|
||||
void PlayImmobileAmbientAnimations();
|
||||
void AnimActionPlayRandomImmobile();
|
||||
void AnimActionPlayRandomCloseRange();
|
||||
void AnimActionPlayRandomMobile();
|
||||
void AnimActionPlayRandomUncivilized();
|
||||
void AnimActionStartInteracting(object oPlaceable);
|
||||
void AnimActionStopInteracting();
|
||||
void AnimActionStartTalking(object oFriend, int nHDiff=0);
|
||||
void AnimActionStopTalking(object oFriend, int nHDiff=0);
|
||||
void AnimActionPlayRandomGreeting(int nHDiff=0);
|
||||
void AnimActionPlayRandomGoodbye(int nHDiff);
|
||||
void AnimActionRandomMoveAway(object oSource, float fDistance);
|
||||
void AnimActionShakeHead();
|
||||
void AnimActionLookAround();
|
||||
void AnimActionTurnAround();
|
||||
void AnimActionGoThroughDoor(object oDoor);
|
||||
int AnimActionCloseRandomDoor();
|
||||
int AnimActionSitInChair(float fMaxDistance);
|
||||
int AnimActionGetUpFromChair();
|
||||
int AnimActionGoInside();
|
||||
int AnimActionGoOutside();
|
||||
int AnimActionGoToStop(float fMaxDistance);
|
||||
int AnimActionFindFriend(float fMaxDistance);
|
||||
int AnimActionFindPlaceable(float fMaxDistance);
|
||||
int AnimActionRest();
|
||||
int AnimActionGoHome();
|
||||
int AnimActionLeaveHome();
|
||||
int AnimActionChallengeIntruder();
|
||||
void AnimActionPlayRandomInteractAnimation(object oPlaceable);
|
||||
void AnimActionPlayRandomTalkAnimation(int nHDiff);
|
||||
void AnimActionPlayRandomBasicAnimation();
|
||||
void AnimActionPlayRandomAnimation();
|
2899
_module/nss/no_lib_actions.nss
Normal file
2899
_module/nss/no_lib_actions.nss
Normal file
File diff suppressed because it is too large
Load Diff
2901
_module/nss/no_lib_analysis.nss
Normal file
2901
_module/nss/no_lib_analysis.nss
Normal file
File diff suppressed because it is too large
Load Diff
2173
_module/nss/no_lib_bio.nss
Normal file
2173
_module/nss/no_lib_bio.nss
Normal file
File diff suppressed because it is too large
Load Diff
15
_module/nss/no_lib_data.nss
Normal file
15
_module/nss/no_lib_data.nss
Normal file
@@ -0,0 +1,15 @@
|
||||
struct sSpellDefStatus {
|
||||
int iTotal;
|
||||
int iMantle;
|
||||
int iElem;
|
||||
int iDeath;
|
||||
int iMind;
|
||||
int iInvis;
|
||||
int iBlocker;
|
||||
};
|
||||
|
||||
struct sPhysDefStatus {
|
||||
int iTotal;
|
||||
int iDamred;
|
||||
int iConceal;
|
||||
};
|
95
_module/nss/no_lib_feat.nss
Normal file
95
_module/nss/no_lib_feat.nss
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "no_inc_ptypes"
|
||||
|
||||
//functions
|
||||
int GetEnhanceFeat( object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iCnt = 0;
|
||||
int iFeat = 0;
|
||||
|
||||
if ( GetHasFeat( FEAT_EMPTY_BODY, oEnt ) && !GetHasFeatEffect( FEAT_EMPTY_BODY, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_EMPTY_BODY );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_MIGHTY_RAGE, oEnt ) )
|
||||
{
|
||||
if ( !GetHasFeatEffect( FEAT_MIGHTY_RAGE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_MIGHTY_RAGE );
|
||||
}
|
||||
}
|
||||
else if ( GetHasFeat( FEAT_BARBARIAN_RAGE, oEnt ) && !GetHasFeatEffect( FEAT_BARBARIAN_RAGE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_BARBARIAN_RAGE );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_BARD_SONGS, oEnt ) && !GetHasFeatEffect( FEAT_BARD_SONGS, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_BARD_SONGS );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_CURSE_SONG, oEnt ) && !GetHasFeatEffect( FEAT_CURSE_SONG, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_CURSE_SONG );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_DIVINE_WRATH, oEnt ) && GetAbilityModifier( ABILITY_CHARISMA, oEnt ) > 0 && !GetHasFeatEffect( FEAT_DIVINE_WRATH, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_DIVINE_WRATH );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE, oEnt ) && !GetHasFeatEffect( FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_EPIC_BLINDING_SPEED, oEnt ) && !GetHasFeatEffect( FEAT_EPIC_BLINDING_SPEED, oEnt ) &&
|
||||
!GetHasSpellEffect( SPELL_HASTE, oEnt ) && !GetHasSpellEffect( SPELL_MASS_HASTE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_EPIC_BLINDING_SPEED );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_SHADOW_EVADE, oEnt ) && !GetHasFeatEffect( FEAT_SHADOW_EVADE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_SHADOW_EVADE );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_DIVINE_MIGHT, oEnt ) && GetHasFeat( FEAT_TURN_UNDEAD, oEnt ) && !GetHasFeatEffect( FEAT_DIVINE_MIGHT, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_DIVINE_MIGHT );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_DIVINE_SHIELD, oEnt ) && GetHasFeat( FEAT_TURN_UNDEAD, oEnt ) && !GetHasFeatEffect( FEAT_DIVINE_SHIELD, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_DIVINE_SHIELD );
|
||||
}
|
||||
if ( GetHasFeat( FEAT_TYMORAS_SMILE, oEnt ) && !GetHasFeatEffect( FEAT_TYMORAS_SMILE, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_TYMORAS_SMILE );
|
||||
}
|
||||
|
||||
iFeat = GetLocalInt( oEnt, "#FEAT_" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#FEAT_" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iFeat;
|
||||
}
|
||||
|
||||
int GetGroupEnhanceFeat( object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iCnt = 0;
|
||||
int iFeat = 0;
|
||||
|
||||
if ( GetHasFeat( FEAT_BARD_SONGS, oEnt ) && !GetHasFeatEffect( FEAT_BARD_SONGS, oEnt ) )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT_" + IntToString( ++iCnt ), FEAT_BARD_SONGS );
|
||||
}
|
||||
|
||||
iFeat = GetLocalInt( oEnt, "#FEAT_" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#FEAT_" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iFeat;
|
||||
}
|
||||
|
||||
float GetGroupEnhanceFeatRadius( int iFeat )
|
||||
{
|
||||
if ( iFeat == FEAT_BARD_SONGS )
|
||||
{
|
||||
return RADIUS_SIZE_COLOSSAL;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
3982
_module/nss/no_lib_magic.nss
Normal file
3982
_module/nss/no_lib_magic.nss
Normal file
File diff suppressed because it is too large
Load Diff
300
_module/nss/no_lib_melee.nss
Normal file
300
_module/nss/no_lib_melee.nss
Normal file
@@ -0,0 +1,300 @@
|
||||
#include "no_inc_ptypes"
|
||||
|
||||
//functions
|
||||
int GetBestMeleeSpecial( object oTarget, int iPenalty=0, int iChance=50, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iCnt = 0;
|
||||
int iFeat;
|
||||
int iMyAtk;
|
||||
int iEnemyAtk;
|
||||
int iMyAC;
|
||||
int iEnemyAC;
|
||||
int iF1;
|
||||
int iF2;
|
||||
int iD;
|
||||
int iT;
|
||||
|
||||
if ( !GetIsObjectValid( oTarget ) || Random( 100 ) > iChance )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//get target's discipline skill as it opposes some melee specials
|
||||
iD = GetSkillRank( SKILL_DISCIPLINE, oTarget ) + GetAbilityModifier( ABILITY_STRENGTH, oTarget ) + 3 * GetHasFeat( FEAT_SKILL_FOCUS_DISCIPLINE, oTarget );
|
||||
|
||||
//use either my intelligence or BAB to check for creature knowledge on some of these, whichever is better
|
||||
//if iT == TRUE we will use BAB, otherwise use intelligence modifier
|
||||
iT = GetBaseAttackBonus( OBJECT_SELF ) < GetAbilityModifier( ABILITY_INTELLIGENCE ) ? FALSE : TRUE;
|
||||
|
||||
iMyAtk = EstimateAttackBonus( oEnt ) + iPenalty; //include penalty from active combat mode if any
|
||||
//iEnemyAtk = EstimateAttackBonus( oTarget );
|
||||
//iMyAC = GetAC( oEnt ) - 10;
|
||||
iEnemyAC = GetAC( oTarget ) - 10;
|
||||
|
||||
//KNOCKDOWN
|
||||
iF1 = GetHasFeat( FEAT_KNOCKDOWN, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_IMPROVED_KNOCKDOWN, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( !GetHasFeatEffect( FEAT_KNOCKDOWN, oTarget ) && !GetHasFeatEffect( FEAT_IMPROVED_KNOCKDOWN, oTarget ) )
|
||||
{
|
||||
//figure out target's discipline
|
||||
|
||||
if ( iF2 ) //improved knockdown
|
||||
{
|
||||
//compare my improved knockdown attack roll to target's AC and Discipline check
|
||||
if ( iMyAtk >= iEnemyAC && iMyAtk > iD )
|
||||
{
|
||||
iFeat = FEAT_IMPROVED_KNOCKDOWN;
|
||||
}
|
||||
}
|
||||
else //no iF2 means we must have iF1
|
||||
{
|
||||
//compare my knockdown attack roll to target's AC and Discipline check
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 4 >= iEnemyAC && iMyAtk - 4 > iD ) )
|
||||
{
|
||||
iFeat = FEAT_KNOCKDOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//CALLED SHOT
|
||||
if ( GetHasFeat( FEAT_CALLED_SHOT, oEnt ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 4 >= iEnemyAC && iMyAtk - 4 > iD ) )
|
||||
{
|
||||
iFeat = FEAT_CALLED_SHOT;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//DISARM
|
||||
iF1 = GetHasFeat( FEAT_DISARM, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_IMPROVED_DISARM, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
int iMod = 4 * GetRelativeEnemyWeaponSize( oTarget );
|
||||
iFeat = 0;
|
||||
if ( GetIsArmed( oTarget) )
|
||||
{
|
||||
if ( iF2 ) //improved disarm
|
||||
{
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 4 + iMod >= iEnemyAC && iMyAtk - 4 + iMod > iD ) )
|
||||
{
|
||||
iFeat = FEAT_IMPROVED_DISARM;
|
||||
}
|
||||
}
|
||||
else //disarm
|
||||
{
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 6 + iMod >= iEnemyAC && iMyAtk - 6 + iMod > iD ) )
|
||||
{
|
||||
iFeat = FEAT_DISARM;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//STUNNING FIST
|
||||
if ( GetHasFeat( FEAT_STUNNING_FIST, oEnt ) && !GetHasFeatEffect( FEAT_STUNNING_FIST, oTarget ) &&
|
||||
FloatToInt( NO_THRESH_STUNNING_FIST * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) &&
|
||||
( DoAbilityCheck( ABILITY_INTELLIGENCE, 10 ) == FALSE || !GetIsImmune( oTarget, IMMUNITY_TYPE_STUN ) ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || iMyAtk - 4 >= iEnemyAC )
|
||||
{
|
||||
iFeat = FEAT_STUNNING_FIST;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//QUIVERING PALM
|
||||
if ( GetHasFeat( FEAT_QUIVERING_PALM, oEnt ) &&
|
||||
FloatToInt( NO_THRESH_QUIVERING_PALM * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) &&
|
||||
( DoAbilityCheck( ABILITY_INTELLIGENCE, 10 ) == FALSE || !GetIsImmune( oTarget, IMMUNITY_TYPE_DEATH ) ) )
|
||||
{
|
||||
iFeat = FEAT_QUIVERING_PALM;
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
|
||||
//SMITE EVIL
|
||||
if ( GetHasFeat( FEAT_SMITE_EVIL, oEnt ) && FloatToInt( NO_THRESH_SMITE * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) &&
|
||||
( DoAbilityCheck( ABILITY_INTELLIGENCE, 2 ) == FALSE || GetAlignmentGoodEvil( oTarget ) == ALIGNMENT_EVIL ) )
|
||||
{
|
||||
iFeat = FEAT_SMITE_EVIL;
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
|
||||
//SMITE GOOD
|
||||
//This feat definition was missing in nwscript pre-HotU, now it's in, uncommenting this block
|
||||
if ( GetHasFeat( FEAT_SMITE_GOOD, oEnt ) && FloatToInt( NO_THRESH_SMITE * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) &&
|
||||
( DoAbilityCheck( ABILITY_INTELLIGENCE, 2 ) == FALSE || GetAlignmentGoodEvil( oTarget ) == ALIGNMENT_GOOD ) )
|
||||
{
|
||||
iFeat = FEAT_SMITE_GOOD;
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
|
||||
//WHIRLWIND
|
||||
iF1 = GetHasFeat( FEAT_WHIRLWIND_ATTACK, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_IMPROVED_WHIRLWIND, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
iFeat = 0;
|
||||
|
||||
if ( iF2 ) //improved whirlwind
|
||||
{
|
||||
//check to see if there are multiple enemies in melee range
|
||||
//if so, check to see if there are at least as many as our number of attacks divided by 2
|
||||
//tail end attacks probably miss anyway, so only count the top end of the attack sequence
|
||||
//if there are enough, use whirlwind as we get full BAB on every attack with whirlwind
|
||||
if ( GetHostileCount( 3.0 ) > GetBaseAttackBonus( oEnt ) / 10 )
|
||||
{
|
||||
iFeat = FEAT_IMPROVED_WHIRLWIND;
|
||||
}
|
||||
}
|
||||
else //whirlwind
|
||||
{
|
||||
if ( GetHostileCount( 3.0 ) > GetBaseAttackBonus( oEnt ) / 10 )
|
||||
{
|
||||
iFeat = FEAT_WHIRLWIND_ATTACK;
|
||||
}
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//KI DAMAGE
|
||||
if ( GetHasFeat( FEAT_KI_DAMAGE, oEnt ) && FloatToInt( NO_THRESH_KI_DAMAGE * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) )
|
||||
{
|
||||
iFeat = FEAT_KI_DAMAGE;
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
|
||||
iFeat = GetLocalInt( oEnt, "#FEAT" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#FEAT" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iFeat;
|
||||
}
|
||||
|
||||
int SelectMeleeCombatModes( object oT, int iC=50, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iPenalty = 0; //accumulate penalty from attack modes
|
||||
int iMyAtk;
|
||||
int iEnemyAtk;
|
||||
int iMyAC;
|
||||
int iEnemyAC;
|
||||
int iF1;
|
||||
int iF2;
|
||||
int iCnt = 0;
|
||||
int iMode;
|
||||
int iT;
|
||||
|
||||
if ( !GetIsObjectValid( oT ) || Random( 100 ) > iC )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iMyAtk = EstimateAttackBonus( oEnt );
|
||||
iEnemyAtk = EstimateAttackBonus( oT );
|
||||
iMyAC = GetAC( oEnt ) - 10;
|
||||
iEnemyAC = GetAC( oT ) - 10;
|
||||
|
||||
//use either my intelligence or BAB to check for creature knowledge on some of these, whichever is better
|
||||
//if iT == TRUE we will use BAB, otherwise use intelligence modifier
|
||||
iT = GetBaseAttackBonus( OBJECT_SELF ) < GetAbilityModifier( ABILITY_INTELLIGENCE ) ? FALSE : TRUE;
|
||||
|
||||
//POWER ATTACK, IMPROVED POWER ATTACK
|
||||
iF1 = GetHasFeat( FEAT_POWER_ATTACK, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_IMPROVED_POWER_ATTACK, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
iMode = 0;
|
||||
if ( iF2 ) //improved power attack
|
||||
{
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || iMyAtk - 10 >= iEnemyAC )
|
||||
{
|
||||
iMode = FEAT_IMPROVED_POWER_ATTACK;
|
||||
}
|
||||
}
|
||||
if ( iF1 && iMode == 0 ) //we don't have or didn't choose improved power attack
|
||||
{
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || iMyAtk - 5 >= iEnemyAC )
|
||||
{
|
||||
iMode = FEAT_POWER_ATTACK;
|
||||
}
|
||||
}
|
||||
if ( iMode )
|
||||
{
|
||||
SetLocalInt( oEnt, "#COMBATMODE" + IntToString( ++iCnt ), iMode );
|
||||
}
|
||||
}
|
||||
|
||||
//FLURRY OF BLOWS
|
||||
if ( GetHasFeat( FEAT_FLURRY_OF_BLOWS, oEnt ) )
|
||||
{
|
||||
iMode = 0;
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || iMyAtk - 2 >= iEnemyAC )
|
||||
{
|
||||
iMode = FEAT_FLURRY_OF_BLOWS;
|
||||
}
|
||||
if ( iMode )
|
||||
{
|
||||
SetLocalInt( oEnt, "#COMBATMODE" + IntToString( ++iCnt ), iMode );
|
||||
}
|
||||
}
|
||||
|
||||
//EXPERTISE, IMPROVED EXPERTISE
|
||||
iF1 = GetHasFeat( FEAT_EXPERTISE, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_IMPROVED_EXPERTISE, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
iMode = 0;
|
||||
if ( iF2 ) //improved expertise
|
||||
{
|
||||
//check if I can afford a -10 on attack, and if my enemy has a high enough attack to bother
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 10 >= iEnemyAC && iEnemyAtk >= iMyAC ) )
|
||||
{
|
||||
iMode = FEAT_IMPROVED_EXPERTISE;
|
||||
}
|
||||
}
|
||||
if ( iF1 && iMode == 0 ) //we don't have or didn't choose improved expertise
|
||||
{
|
||||
//check if I can afford a -5 on attack, and if my enemy has a high enough attack to bother
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 5 >= iEnemyAC && iEnemyAtk >= iMyAC ) )
|
||||
{
|
||||
iMode = FEAT_EXPERTISE;
|
||||
}
|
||||
}
|
||||
if ( iMode )
|
||||
{
|
||||
SetLocalInt( oEnt, "#COMBATMODE" + IntToString( ++iCnt ), iMode );
|
||||
}
|
||||
}
|
||||
|
||||
iMode = GetLocalInt( oEnt, "#COMBATMODE" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#COMBATMODE" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iMode;
|
||||
}
|
320
_module/nss/no_lib_priority.nss
Normal file
320
_module/nss/no_lib_priority.nss
Normal file
@@ -0,0 +1,320 @@
|
||||
#include "no_inc_ptypes"
|
||||
|
||||
//functions
|
||||
void AddBehaviour( string sB, int iC, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iL = GetLocalInt( oEnt, "PRITOTAL" ) + 1;
|
||||
|
||||
//update count
|
||||
SetLocalInt( oEnt, "PRITOTAL", iL );
|
||||
|
||||
//make sure the chance is valid
|
||||
iC = iC < 0 ? 0 : iC;
|
||||
iC = iC > 100 ? 100 : iC;
|
||||
|
||||
//set up the behaviour
|
||||
SetLocalString( oEnt, "PRID_" + IntToString( iL ), sB );
|
||||
SetLocalInt( oEnt, "PRIC_" + IntToString( iL ), iC );
|
||||
}
|
||||
|
||||
string GetPriority( int iP=1, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
//retrieve priority iP
|
||||
return GetLocalString( oEnt, "PRID_" + IntToString( iP ) );
|
||||
}
|
||||
|
||||
int GetPriorityChance( int iP=1, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
//retrieve priority chance iP
|
||||
return GetLocalInt( oEnt, "PRIC_" + IntToString( iP ) );
|
||||
}
|
||||
|
||||
void SetVoiceChat( int iV, int iC, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( iC < 0 )
|
||||
{
|
||||
iC = -1;
|
||||
}
|
||||
else if ( iC > 100 )
|
||||
{
|
||||
iC = 100;
|
||||
}
|
||||
if ( iV == NO_VC_DEFAULT )
|
||||
{
|
||||
if ( iC == 0 )
|
||||
{
|
||||
//delete the config for default voicechat chance
|
||||
DeleteLocalInt( oE, "#VCC" );
|
||||
}
|
||||
else
|
||||
{
|
||||
//set the config for default voicechat chance
|
||||
SetLocalInt( oE, "#VCC", iC );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( iC == 0 )
|
||||
{
|
||||
//delete the config for this voicechat chance
|
||||
DeleteLocalInt( oE, "#VCC_" + IntToString( iV ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
//set the config for this voicechat chance
|
||||
SetLocalInt( oE, "#VCC_" + IntToString( iV ), iC );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float GetFollowDist( object oE=OBJECT_SELF )
|
||||
{
|
||||
float fF = -1.0;
|
||||
|
||||
if ( GetIsObjectValid( oE ) )
|
||||
{
|
||||
fF = GetLocalFloat( OBJECT_SELF, "#FOLLOWDIST" );
|
||||
|
||||
if ( fF == 0.0 )
|
||||
{
|
||||
//default distance if none is set
|
||||
fF = 3.0;
|
||||
}
|
||||
}
|
||||
return fF;
|
||||
}
|
||||
|
||||
void SetPerceptionRange( int iP, float fP=50.0, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( iP == NO_PERCEPTION_SEEN )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_SEEN_RANGE", fP );
|
||||
}
|
||||
else if ( iP == NO_PERCEPTION_HEARD )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_HEARD_RANGE", fP );
|
||||
}
|
||||
else if ( iP == NO_PERCEPTION_VANISHED )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_VANISHED_RANGE", fP );
|
||||
}
|
||||
}
|
||||
|
||||
void SetPerceptionRanges( float fS=50.0, float fH=50.0, float fV=50.0, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( fS != -1.0 )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_SEEN_RANGE", fS );
|
||||
}
|
||||
if ( fH != -1.0 )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_HEARD_RANGE", fH );
|
||||
}
|
||||
if ( fV != -1.0 )
|
||||
{
|
||||
SetLocalFloat( oE, "#PER_VANISHED_RANGE", fV );
|
||||
}
|
||||
}
|
||||
|
||||
float GetPerceptionRange( int iP, object oE=OBJECT_SELF )
|
||||
{
|
||||
float fP = 0.0;
|
||||
|
||||
if ( iP == NO_PERCEPTION_SEEN )
|
||||
{
|
||||
fP = GetLocalFloat( oE, "#PER_SEEN_RANGE" );
|
||||
}
|
||||
else if ( iP == NO_PERCEPTION_HEARD )
|
||||
{
|
||||
fP = GetLocalFloat( oE, "#PER_HEARD_RANGE" );
|
||||
}
|
||||
else if ( iP == NO_PERCEPTION_VANISHED )
|
||||
{
|
||||
fP = GetLocalFloat( oE, "#PER_VANISHED_RANGE" );
|
||||
}
|
||||
//set max range if no setting found
|
||||
if ( fP == 0.0 )
|
||||
{
|
||||
fP = 50.0;
|
||||
}
|
||||
return fP;
|
||||
}
|
||||
|
||||
void SetReadyStatus( int iS=1, object oE=OBJECT_SELF )
|
||||
{
|
||||
SetLocalInt( oE, "#READYTOACT", iS );
|
||||
}
|
||||
|
||||
int IsReadyToAct( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( oE, "#READYTOACT" );
|
||||
}
|
||||
|
||||
int ShortAction( object oE=OBJECT_SELF )
|
||||
{
|
||||
string sAct = GetLastAction( oE );
|
||||
|
||||
if ( sAct == "+EVACAOE" || sAct == "+REGROUP" || sAct == "+AVOIDMELEE" || sAct == "+FLANK" || sAct == "+AVOIDENEMY" )
|
||||
//|| sAct == "+EYERAYS" )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int IsActive( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( oE, "#ACTIVE" );
|
||||
}
|
||||
|
||||
void SetActive( object oE=OBJECT_SELF )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
}
|
||||
|
||||
void SetIsActive( int iA=TRUE, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( iA == TRUE )
|
||||
{
|
||||
SetLocalInt( oE, "#ACTIVE", 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt( oE, "#ACTIVE" );
|
||||
}
|
||||
}
|
||||
|
||||
float GetResponseRange( int iT, object oE=OBJECT_SELF )
|
||||
{
|
||||
float fR = GetLocalFloat( oE, "#RESPOND_RANGE_" + IntToString( iT ) );
|
||||
|
||||
if ( fR == 0.0 )
|
||||
{
|
||||
//default range
|
||||
fR = 50.0;
|
||||
}
|
||||
return fR;
|
||||
}
|
||||
|
||||
void SetResponseRange( int iT, float fR=50.0, object oE=OBJECT_SELF )
|
||||
{
|
||||
float fRange = fR > 0.0 ? fR : 0.0;
|
||||
|
||||
SetLocalFloat( oE, "#RESPOND_RANGE_" + IntToString( iT ), fRange );
|
||||
}
|
||||
|
||||
void SetIsTeleporter( object oE=OBJECT_SELF )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "TELEPORTER", 1 );
|
||||
}
|
||||
|
||||
int GetIsTeleporter( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( OBJECT_SELF, "TELEPORTER" );
|
||||
}
|
||||
|
||||
void SetIsFastBuffer( int iS, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( iS == 1 )
|
||||
{
|
||||
SetLocalInt( oE, "#FASTBUFFER", 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt( oE, "#FASTBUFFER" );
|
||||
}
|
||||
}
|
||||
|
||||
int GetIsFastBuffer( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( oE, "#FASTBUFFER" );
|
||||
}
|
||||
|
||||
void SetIsFastBuffed( int iS, object oE=OBJECT_SELF )
|
||||
{
|
||||
if ( iS == 1 )
|
||||
{
|
||||
SetLocalInt( oE, "#FASTBUFFED", 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt( oE, "#FASTBUFFED" );
|
||||
}
|
||||
}
|
||||
|
||||
int GetIsFastBuffed( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( oE, "#FASTBUFFED" );
|
||||
}
|
||||
|
||||
void AddFastBuff( int iS, object oE=OBJECT_SELF )
|
||||
{
|
||||
int iC = CountFastBuffs( oE ) + 1;
|
||||
|
||||
SetLocalInt( oE, "#SPN_FB" + IntToString( iC ), iS );
|
||||
}
|
||||
|
||||
int CountFastBuffs( object oE=OBJECT_SELF )
|
||||
{
|
||||
int iC = 0;
|
||||
int iS = 1;
|
||||
|
||||
while ( GetLocalInt( oE, "#SPN_FB" + IntToString( iS++ ) ) != 0 )
|
||||
{
|
||||
iC++;
|
||||
}
|
||||
|
||||
return iC;
|
||||
}
|
||||
|
||||
void SetLastAction( string sA, object oE=OBJECT_SELF )
|
||||
{
|
||||
SetLocalString( oE, "#LASTACTION", sA );
|
||||
}
|
||||
|
||||
string GetLastAction( object oE=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalString( oE, "#LASTACTION" );
|
||||
}
|
||||
|
||||
void SetLastActionTimestamp( object oE=OBJECT_SELF )
|
||||
{
|
||||
SetLocalInt( oE, "#LASTACTIONTIME", GetTimeSecond() );
|
||||
}
|
||||
|
||||
int GetLastActionTimestamp( object oE=OBJECT_SELF )
|
||||
{
|
||||
int iS = GetLocalInt( oE, "#LASTACTIONTIME" );
|
||||
int iT = GetTimeSecond();
|
||||
int iL = iT < iS ? iT + 60 : iT;
|
||||
|
||||
return iL - iS;
|
||||
}
|
||||
|
||||
void SetCorpseDelay( int iT=60, object oC=OBJECT_SELF )
|
||||
{
|
||||
if ( GetRacialType( oC ) != RACIAL_TYPE_UNDEAD && GetStringLeft( GetTag( oC ), 6 ) != "NO_AI_" &&
|
||||
GetName( GetItemInSlot( INVENTORY_SLOT_CARMOUR, oC ) ) != "Gargoyle Properties" )
|
||||
{
|
||||
//not summoned, not undead, default decay time
|
||||
AssignCommand( oC, SetIsDestroyable( FALSE, TRUE, TRUE ) );
|
||||
SetLocalFloat( oC, "#DECAYDELAY", 60.0 ); //default corpse decay time
|
||||
}
|
||||
}
|
||||
|
||||
void SetIsFlier( int iF=FALSE, object oF=OBJECT_SELF )
|
||||
{
|
||||
if ( iF == TRUE || GetRacialType( oF ) == RACIAL_TYPE_DRAGON )
|
||||
{
|
||||
SetLocalInt( oF, "FLIER", 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt( oF, "FLIER" );
|
||||
}
|
||||
}
|
||||
|
||||
int GetIsFlier( object oF=OBJECT_SELF )
|
||||
{
|
||||
return GetLocalInt( oF, "FLIER" );
|
||||
}
|
172
_module/nss/no_lib_ranged.nss
Normal file
172
_module/nss/no_lib_ranged.nss
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "no_inc_ptypes"
|
||||
|
||||
//functions
|
||||
int GetBestRangedSpecial( object oTarget, int iPenalty=0, int iChance=50, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iCnt = 0;
|
||||
int iFeat;
|
||||
int iMyAtk;
|
||||
int iEnemyAtk;
|
||||
int iMyAC;
|
||||
int iEnemyAC;
|
||||
int iF1;
|
||||
int iF2;
|
||||
int iD;
|
||||
int iT;
|
||||
|
||||
if ( !GetIsObjectValid( oTarget ) || Random( 100 ) > iChance )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iD = GetSkillRank( SKILL_DISCIPLINE, oTarget ) + GetAbilityModifier( ABILITY_STRENGTH, oTarget ) + 3 * GetHasFeat( FEAT_SKILL_FOCUS_DISCIPLINE, oTarget );
|
||||
iMyAtk = EstimateAttackBonus( oEnt ) + iPenalty; //include penalty from active combat mode if any
|
||||
//iEnemyAtk = EstimateAttackBonus( oTarget );
|
||||
//iMyAC = GetAC( oEnt ) - 10;
|
||||
iEnemyAC = GetAC( oTarget ) - 10;
|
||||
|
||||
//use either my intelligence or BAB to check for creature knowledge on some of these, whichever is better
|
||||
//if iT == TRUE we will use BAB, otherwise use intelligence modifier
|
||||
iT = GetBaseAttackBonus( OBJECT_SELF ) < GetAbilityModifier( ABILITY_INTELLIGENCE ) ? FALSE : TRUE;
|
||||
|
||||
//CALLED SHOT
|
||||
if ( GetHasFeat( FEAT_CALLED_SHOT, oEnt ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 4 >= iEnemyAC && iMyAtk - 4 > iD ) )
|
||||
{
|
||||
iFeat = FEAT_CALLED_SHOT;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//SEEKER ARROW
|
||||
// Arcane Archer feats are not defined in nwscript?
|
||||
// FIX: They are in HotU but not SoU. When updating these for HotU update this block and add the rest.
|
||||
iF1 = GetHasFeat( FEAT_PRESTIGE_SEEKER_ARROW_1, oEnt );
|
||||
iF2 = GetHasFeat( FEAT_PRESTIGE_SEEKER_ARROW_2, oEnt );
|
||||
if ( iF1 || iF2 )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( iMyAtk + 8 < iEnemyAC ) //if I can't hit even with a high roll use a seeker arrow
|
||||
{
|
||||
if ( iF2 )
|
||||
{
|
||||
iFeat = FEAT_PRESTIGE_SEEKER_ARROW_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
iFeat = FEAT_PRESTIGE_SEEKER_ARROW_1;
|
||||
}
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//IMBUE ARROW
|
||||
if ( GetHasFeat( FEAT_PRESTIGE_IMBUE_ARROW, oEnt ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( GetAllyCount( RADIUS_SIZE_HUGE, oTarget, oEnt ) > GetHostileCount( RADIUS_SIZE_HUGE, oTarget, oEnt ) )
|
||||
{
|
||||
iFeat = FEAT_PRESTIGE_IMBUE_ARROW;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//HAIL OF ARROWS
|
||||
if ( GetHasFeat( FEAT_PRESTIGE_HAIL_OF_ARROWS, oEnt ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( GetHostileCount( 30.0 ) > GetBaseAttackBonus( oEnt ) / 10 )
|
||||
{
|
||||
iFeat = FEAT_PRESTIGE_HAIL_OF_ARROWS;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//ARROW OF SLAYING
|
||||
if ( GetHasFeat( FEAT_PRESTIGE_ARROW_OF_DEATH, oEnt ) )
|
||||
{
|
||||
iFeat = 0;
|
||||
if ( FloatToInt( NO_THRESH_ARROW_SLAYING * GetHitDice( oEnt ) ) < GetHitDice( oTarget ) &&
|
||||
( DoAbilityCheck( ABILITY_INTELLIGENCE, 10 ) == FALSE || GetIsImmune( oTarget, IMMUNITY_TYPE_DEATH ) == FALSE ) )
|
||||
{
|
||||
//target has sufficient hit dice to warrant use of an arrow of death
|
||||
//either oEnt failed its intelligence check or it passed and determined that target is not immune to death effects
|
||||
iFeat = FEAT_PRESTIGE_ARROW_OF_DEATH;
|
||||
}
|
||||
if ( iFeat )
|
||||
{
|
||||
SetLocalInt( oEnt, "#FEAT" + IntToString( ++iCnt ), iFeat );
|
||||
}
|
||||
}
|
||||
|
||||
//randomly select one of the feats that was deemed suitable for use
|
||||
iFeat = GetLocalInt( oEnt, "#FEAT" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#FEAT" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iFeat;
|
||||
}
|
||||
|
||||
int SelectRangedCombatModes( object oT, int iC=50, object oEnt=OBJECT_SELF )
|
||||
{
|
||||
int iPenalty = 0; //accumulate penalty from attack modes
|
||||
int iMyAtk;
|
||||
//int iEnemyAtk;
|
||||
//int iMyAC;
|
||||
int iEnemyAC;
|
||||
int iF1;
|
||||
int iF2;
|
||||
int iCnt = 0;
|
||||
int iMode;
|
||||
int iT;
|
||||
|
||||
if ( !GetIsObjectValid( oT ) || Random( 100 ) > iC )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iMyAtk = EstimateAttackBonus( oEnt );
|
||||
//iEnemyAtk = EstimateAttackBonus( oT );
|
||||
//iMyAC = GetAC( oEnt ) - 10;
|
||||
iEnemyAC = GetAC( oT ) - 10;
|
||||
|
||||
//use either my intelligence or BAB to check for creature knowledge on some of these, whichever is better
|
||||
//if iT == TRUE we will use BAB, otherwise use intelligence modifier
|
||||
iT = GetBaseAttackBonus( OBJECT_SELF ) < GetAbilityModifier( ABILITY_INTELLIGENCE ) ? FALSE : TRUE;
|
||||
|
||||
//RAPID SHOT
|
||||
if ( GetHasFeat( FEAT_RAPID_SHOT, oEnt ) )
|
||||
{
|
||||
iMode = 0;
|
||||
if ( DoCombatKnowledgeCheck( iT, 10 ) == FALSE || ( iMyAtk - 2 >= iEnemyAC ) )
|
||||
{
|
||||
iMode = FEAT_RAPID_SHOT;
|
||||
}
|
||||
if ( iMode )
|
||||
{
|
||||
SetLocalInt( oEnt, "#COMBATMODE" + IntToString( ++iCnt ), iMode );
|
||||
}
|
||||
}
|
||||
|
||||
iMode = GetLocalInt( oEnt, "#COMBATMODE" + IntToString( Random( iCnt ) + 1 ) );
|
||||
while ( iCnt )
|
||||
{
|
||||
DeleteLocalInt( oEnt, "#COMBATMODE" + IntToString( iCnt-- ) );
|
||||
}
|
||||
return iMode;
|
||||
}
|
5
_module/nss/no_scr_asclis.nss
Normal file
5
_module/nss/no_scr_asclis.nss
Normal file
@@ -0,0 +1,5 @@
|
||||
void main()
|
||||
{
|
||||
SetListening( OBJECT_SELF, TRUE );
|
||||
SetAssociateListenPatterns( OBJECT_SELF );
|
||||
}
|
108
_module/nss/no_scr_cleanvars.nss
Normal file
108
_module/nss/no_scr_cleanvars.nss
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "no_lib_priority"
|
||||
|
||||
void main()
|
||||
{
|
||||
//clean up variables on dying creature
|
||||
int iCnt;
|
||||
|
||||
//don't proceed if we're alive again
|
||||
if ( GetIsDead( OBJECT_SELF ) || GetLocalInt( OBJECT_SELF, "TEMPDIE" ) )
|
||||
{
|
||||
//clear teleporter status variable
|
||||
DeleteLocalInt( OBJECT_SELF, "TELEPORTER" );
|
||||
|
||||
//clear balor death throes variable
|
||||
DeleteLocalInt( OBJECT_SELF, "BALORDEATH" );
|
||||
|
||||
//clear dragon flight variables
|
||||
DeleteLocalInt( OBJECT_SELF, "FLIER" );
|
||||
DeleteLocalInt( OBJECT_SELF, "DRAGONFLIGHTDEL" );
|
||||
|
||||
//dragon fear variable
|
||||
DeleteLocalInt( OBJECT_SELF, "#DRAGFEAR" );
|
||||
|
||||
//clear caster flag
|
||||
DeleteLocalInt( OBJECT_SELF, "#CASTER" );
|
||||
|
||||
//clear avoid melee trackers
|
||||
DeleteLocalLocation( OBJECT_SELF, "#LASTHOTSPOT" );
|
||||
DeleteLocalFloat( OBJECT_SELF, "#LASTAMANGLE" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#LASTHSRETRIES" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#LASTDEST" );
|
||||
DeleteLocalLocation( OBJECT_SELF, "#LASTDEST" );
|
||||
|
||||
//clear dragon breath weapon delay flag
|
||||
DeleteLocalInt( OBJECT_SELF, "#BDEL" );
|
||||
|
||||
//clear BC_HEAL anti-spam flag
|
||||
DeleteLocalInt( OBJECT_SELF, "#HEALDEL" );
|
||||
|
||||
//delete combat setting
|
||||
DeleteLocalInt( OBJECT_SELF, "#INCOMBAT" );
|
||||
|
||||
//delete last combat round end broadcast timestamp
|
||||
DeleteLocalInt( OBJECT_SELF, "#LASTCREBC" );
|
||||
|
||||
//clear tail of summon chain variable
|
||||
DeleteLocalObject( OBJECT_SELF, "MASTCHAIN" );
|
||||
|
||||
//clear vision flags
|
||||
DeleteLocalInt( OBJECT_SELF, "#DARKNESS" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#VANISHED" );
|
||||
DeleteLocalObject( OBJECT_SELF, "#VISION" );
|
||||
|
||||
//clear last rest marker
|
||||
DeleteLocalInt( OBJECT_SELF, "#LASTREST" );
|
||||
|
||||
//clear fast buffer markers
|
||||
DeleteLocalInt( OBJECT_SELF, "#FASTBUFFER" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#FASTBUFFED" );
|
||||
|
||||
//delete activity marker
|
||||
DeleteLocalInt( OBJECT_SELF, "#ACTIVE" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" );
|
||||
|
||||
//delete logged spawn point
|
||||
DeleteLocalInt( OBJECT_SELF, "#RETSPNLOC" );
|
||||
DeleteLocalLocation( OBJECT_SELF, "#SPAWNLOC" );
|
||||
|
||||
//delete stand ground variables
|
||||
DeleteLocalInt( OBJECT_SELF, "#STANDGROUND" );
|
||||
DeleteLocalLocation( OBJECT_SELF, "#SGLOC" );
|
||||
|
||||
//delete corpse decay delay variable
|
||||
DeleteLocalFloat( OBJECT_SELF, "#DECAYDELAY" );
|
||||
|
||||
//clear spell list and fastbuff list
|
||||
//these shouldn't be necessary, but just in case there is an interruption
|
||||
iCnt = 1;
|
||||
while ( GetLocalInt( OBJECT_SELF, "#SPL_" + IntToString( iCnt ) ) )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#SPL_" + IntToString( iCnt++ ) );
|
||||
}
|
||||
iCnt = 1;
|
||||
while ( GetLocalInt( OBJECT_SELF, "#SPL_FB" + IntToString( iCnt ) ) )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#SPL_FB" + IntToString( iCnt++ ) );
|
||||
}
|
||||
iCnt = 1;
|
||||
while ( GetLocalInt( OBJECT_SELF, "#SPN_FB" + IntToString( iCnt ) ) )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#SPN_FB" + IntToString( iCnt++ ) );
|
||||
}
|
||||
iCnt = 1;
|
||||
while ( GetLocalInt( OBJECT_SELF, "#FEAT_" + IntToString( iCnt ) ) )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#FEAT_" + IntToString( iCnt++ ) );
|
||||
}
|
||||
|
||||
//clear priority lists
|
||||
DeleteLocalInt( OBJECT_SELF, "PRITOTAL" );
|
||||
iCnt = 1;
|
||||
while ( GetLocalInt( OBJECT_SELF, "PRIC_" + IntToString( iCnt ) ) )
|
||||
{
|
||||
DeleteLocalString( OBJECT_SELF, "PRID_" + IntToString( iCnt ) );
|
||||
DeleteLocalInt( OBJECT_SELF, "PRIC_" + IntToString( iCnt++ ) );
|
||||
}
|
||||
}
|
||||
}
|
13
_module/nss/no_scr_excorpse.nss
Normal file
13
_module/nss/no_scr_excorpse.nss
Normal file
@@ -0,0 +1,13 @@
|
||||
void main()
|
||||
{
|
||||
//don't proceed if we're alive again
|
||||
if ( GetIsDead( OBJECT_SELF ) || GetLocalInt( OBJECT_SELF, "TEMPDIE" ) )
|
||||
{
|
||||
//clear death marker
|
||||
DeleteLocalInt( OBJECT_SELF, "TEMPDIE" );
|
||||
|
||||
//time to die
|
||||
SetIsDestroyable( TRUE, FALSE, FALSE );
|
||||
DestroyObject( OBJECT_SELF );
|
||||
}
|
||||
}
|
14
_module/nss/no_scr_logeq.nss
Normal file
14
_module/nss/no_scr_logeq.nss
Normal file
@@ -0,0 +1,14 @@
|
||||
void main()
|
||||
{
|
||||
object oL = GetItemInSlot( INVENTORY_SLOT_LEFTHAND );
|
||||
object oR = GetItemInSlot( INVENTORY_SLOT_RIGHTHAND );
|
||||
|
||||
if ( GetIsObjectValid( oL ) )
|
||||
{
|
||||
SetLocalObject( OBJECT_SELF, "LHAND", oL );
|
||||
}
|
||||
if ( GetIsObjectValid( oR ) )
|
||||
{
|
||||
SetLocalObject( OBJECT_SELF, "RHAND", oR );
|
||||
}
|
||||
}
|
5
_module/nss/no_scr_logspnloc.nss
Normal file
5
_module/nss/no_scr_logspnloc.nss
Normal file
@@ -0,0 +1,5 @@
|
||||
void main()
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "#RETSPNLOC", 1 );
|
||||
SetLocalLocation( OBJECT_SELF, "#SPAWNLOC", GetLocation( OBJECT_SELF ) );
|
||||
}
|
72
_module/nss/no_scr_shutdown.nss
Normal file
72
_module/nss/no_scr_shutdown.nss
Normal file
@@ -0,0 +1,72 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Shutdown
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This script will shutdown the combat AI.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
|
||||
void main()
|
||||
{
|
||||
int iCnt = GetLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" );
|
||||
int iCombat = 0;
|
||||
//object oEnemy;
|
||||
int iRestWait = 30;
|
||||
|
||||
//delete queue marker
|
||||
DeleteLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" );
|
||||
|
||||
//SpeakString( "CFS" );
|
||||
//if ( !GetIsInCombat() && GetLocalInt( OBJECT_SELF, "#ACTIVE" ) && !IsInConversation( OBJECT_SELF ) )
|
||||
if ( !IsInConversation( OBJECT_SELF ) )
|
||||
{
|
||||
//oEnemy = GetNearestCreature( CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_IS_ALIVE, TRUE );
|
||||
int iE = GetHostileCount( 50.0 );
|
||||
if ( iE )
|
||||
{
|
||||
InitCombat();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
DeleteLocalInt( OBJECT_SELF, "#FASTBUFFED" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#ACTIVE" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#VANISHED" );
|
||||
//SetReadyStatus();
|
||||
ActionForceFollowObject( GetMaster( OBJECT_SELF ), 3.0 );
|
||||
return;
|
||||
}
|
||||
//else if ( !GetLocalInt( OBJECT_SELF, "#LASTREST" ) && GetTimeSinceLastCombat() > iRestWait )
|
||||
else if ( GetTimeSinceLastCombat() > iRestWait )
|
||||
{
|
||||
//PrintString( "RESTING: " + GetName( OBJECT_SELF ) );
|
||||
DeleteLocalInt( OBJECT_SELF, "#FASTBUFFED" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" );
|
||||
DeleteLocalInt( OBJECT_SELF, "#ACTIVE" ); //shutdown AI heartbeats until an opponent shows up
|
||||
DeleteLocalInt( OBJECT_SELF, "#VANISHED" );
|
||||
//SetReadyStatus();
|
||||
if ( !GetLocalInt( OBJECT_SELF, "#LASTREST" ) )
|
||||
{
|
||||
ActionRest(); //no enemies seen for 30 seconds, rest
|
||||
SetLocalInt( OBJECT_SELF, "#LASTREST", 1 );
|
||||
}
|
||||
ActionDoCommand( WalkWayPoints() ); //start walking waypoints if applicable
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !GetLocalInt( OBJECT_SELF, "#QUEUESHUTDOWN" ) && GetLocalInt( OBJECT_SELF, "#ACTIVE" ) )
|
||||
{
|
||||
//DelayCommand( 12.0, ExecuteScript( "no_scr_shutdown", OBJECT_SELF ) );
|
||||
DoQueueShutdown( 12.0 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
121
_module/nss/no_spn_beh.nss
Normal file
121
_module/nss/no_spn_beh.nss
Normal file
@@ -0,0 +1,121 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+AVOIDMELEE", 50 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 80 ); //evac AOEs
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 20 ); //regroup
|
||||
AddBehaviour( "+FEATENHANCE", 10 ); //enhance self via feats
|
||||
AddBehaviour( "+CENTRALEYE", 10 ); //beholder antimagic cone
|
||||
AddBehaviour( "+EYERAYS", 100 ); //beholder eye rays
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
157
_module/nss/no_spn_clr.nss
Normal file
157
_module/nss/no_spn_clr.nss
Normal file
@@ -0,0 +1,157 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 );
|
||||
AddBehaviour( "+REGROUP", 80 );
|
||||
AddBehaviour( "+FLANK", 20 );
|
||||
AddBehaviour( "+SUMMON", 40 );
|
||||
AddBehaviour( "+RAISE", 60 );
|
||||
AddBehaviour( "+GROUPHEAL", 60 );
|
||||
AddBehaviour( "+HELP", 60 );
|
||||
AddBehaviour( "+HEAL", 60 );
|
||||
AddBehaviour( "+VIS", 60 );
|
||||
AddBehaviour( "+DEFSELF", 40 );
|
||||
AddBehaviour( "+DEFSING", 40 );
|
||||
AddBehaviour( "+GROUPENHANCE", 40 );
|
||||
AddBehaviour( "+ENHANCESING", 40 );
|
||||
AddBehaviour( "+ENHANCESELF", 40 );
|
||||
AddBehaviour( "+FEATENHANCE", 40 );
|
||||
AddBehaviour( "+DISPEL", 40 );
|
||||
AddBehaviour( "+DISPELAOE", 40 );
|
||||
AddBehaviour( "+DISMISSAL", 40 );
|
||||
AddBehaviour( "+TURN", 40 );
|
||||
AddBehaviour( "+AREA", 40 );
|
||||
AddBehaviour( "+DIRECT", 40 );
|
||||
AddBehaviour( "+TOUCH", 40 );
|
||||
AddBehaviour( "+EVACAOE", 50 );
|
||||
AddBehaviour( "+ATKMELEE", 100 );
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
/*
|
||||
if ( GetRacialType( OBJECT_SELF ) != RACIAL_TYPE_UNDEAD && GetStringLeft( GetTag( OBJECT_SELF ), 6 ) != "NO_AI_" &&
|
||||
GetName( GetItemInSlot( INVENTORY_SLOT_CARMOUR, OBJECT_SELF ) ) != "Gargoyle Properties" )
|
||||
{
|
||||
//not summoned, not undead, default decay time
|
||||
SetIsDestroyable( FALSE, TRUE, TRUE );
|
||||
SetLocalFloat( OBJECT_SELF, "#DECAYDELAY", 60.0 ); //default corpse decay time
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
SetListening( OBJECT_SELF, TRUE );
|
||||
SetListenPattern( OBJECT_SELF, "BC_DEAD", 691 );
|
||||
SetListenPattern( OBJECT_SELF, "BC_FIGHTING", 699 );
|
||||
*/
|
||||
|
||||
if ( GetName( GetItemInSlot( INVENTORY_SLOT_CARMOUR, OBJECT_SELF ) ) == "Balor Properties" )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "BALORDEATH", 1 );
|
||||
}
|
||||
|
||||
if ( GetRacialType( OBJECT_SELF ) == RACIAL_TYPE_DRAGON )
|
||||
{
|
||||
SetLocalInt( OBJECT_SELF, "FLIER", 1 );
|
||||
}
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
GenerateNPCTreasure(); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
135
_module/nss/no_spn_fiend.nss
Normal file
135
_module/nss/no_spn_fiend.nss
Normal file
@@ -0,0 +1,135 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 10 ); //flank
|
||||
AddBehaviour( "+AVOIDMELEE", 10 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 20 ); //evac AOEs
|
||||
AddBehaviour( "+SUMMON", 20 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 10 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 10 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 10 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 10 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 10 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 10 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 10 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 10 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 10 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 10 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 10 ); //time stop
|
||||
AddBehaviour( "+AREA", 25 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
//AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
121
_module/nss/no_spn_ftr.nss
Normal file
121
_module/nss/no_spn_ftr.nss
Normal file
@@ -0,0 +1,121 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+FEATENHANCE", 80 ); //enhance self via feats
|
||||
AddBehaviour( "+REGROUP", 80 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+MELEEASSIST", 100 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_melcast1.nss
Normal file
136
_module/nss/no_spn_melcast1.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 20 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 20 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 20 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 20 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 20 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 20 ); //enhance self via feats
|
||||
//AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
//AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 20 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_melcast2.nss
Normal file
136
_module/nss/no_spn_melcast2.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 20 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 20 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 20 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 20 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 20 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 20 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 20 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 20 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 20 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_melcast3.nss
Normal file
136
_module/nss/no_spn_melcast3.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 20 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 20 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 20 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 20 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 20 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 20 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 20 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 20 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 20 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 20 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 20 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_melenh.nss
Normal file
136
_module/nss/no_spn_melenh.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
//AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 40 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 40 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 40 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 40 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 40 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 40 ); //enhance self via feats
|
||||
//AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
//AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
//AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
//AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
//AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
//AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
121
_module/nss/no_spn_rftr.nss
Normal file
121
_module/nss/no_spn_rftr.nss
Normal file
@@ -0,0 +1,121 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+FEATENHANCE", 80 ); //enhance self via feats
|
||||
AddBehaviour( "+REGROUP", 80 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+MELEEASSIST", 100 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_rftrcast1.nss
Normal file
136
_module/nss/no_spn_rftrcast1.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 40 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 40 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 40 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 40 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 40 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 40 ); //enhance self via feats
|
||||
//AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
//AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_rngcast3.nss
Normal file
136
_module/nss/no_spn_rngcast3.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+AVOIDMELEE", 80 ); //avoid melee
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 20 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 20 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 20 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 20 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 20 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 20 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 20 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 20 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 20 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 20 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 20 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
//AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
122
_module/nss/no_spn_rog.nss
Normal file
122
_module/nss/no_spn_rog.nss
Normal file
@@ -0,0 +1,122 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+FEATENHANCE", 80 ); //enhance self via feats
|
||||
AddBehaviour( "+REGROUP", 80 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+AREA", 60 ); //area attack spells
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+MELEEASSIST", 100 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_rogcast1.nss
Normal file
136
_module/nss/no_spn_rogcast1.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 40 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 40 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 40 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 40 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 40 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 40 ); //enhance self via feats
|
||||
//AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
//AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_rogcast3.nss
Normal file
136
_module/nss/no_spn_rogcast3.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 20 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 20 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 20 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 20 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 20 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 20 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 20 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 20 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 20 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 20 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 20 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 20 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 20 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_rogenh.nss
Normal file
136
_module/nss/no_spn_rogenh.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
//AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
//AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
//AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 40 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 40 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 40 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 40 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 40 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 40 ); //enhance self via feats
|
||||
//AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
//AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
//AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
//AddBehaviour( "+BREACH", 40 ); //breach
|
||||
//AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
//AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
//AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
//AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
//AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
//AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creatureed Event 1007
|
||||
}
|
125
_module/nss/no_spn_rogtel.nss
Normal file
125
_module/nss/no_spn_rogtel.nss
Normal file
@@ -0,0 +1,125 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+FEATENHANCE", 80 ); //enhance self via feats
|
||||
AddBehaviour( "+REGROUP", 80 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+AREA", 60 ); //area attack spells
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+MELEEASSIST", 100 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//flag as a teleport capable creature
|
||||
SetIsTeleporter();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
136
_module/nss/no_spn_summ.nss
Normal file
136
_module/nss/no_spn_summ.nss
Normal file
@@ -0,0 +1,136 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 40 ); //regroup
|
||||
AddBehaviour( "+FLANK", 20 ); //flank
|
||||
AddBehaviour( "+AVOIDMELEE", 20 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 50 ); //evac AOEs
|
||||
AddBehaviour( "+SUMMON", 60 ); //summon spells
|
||||
AddBehaviour( "+HELP", 40 ); //help
|
||||
AddBehaviour( "+VIS", 40 ); //vision
|
||||
AddBehaviour( "+DEFSING", 40 ); //defend single
|
||||
AddBehaviour( "+DEFSELF", 40 ); //defend self
|
||||
AddBehaviour( "+GROUPENHANCE", 40 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 40 ); //enhance single
|
||||
AddBehaviour( "+ENHANCESELF", 40 ); //enhance self
|
||||
AddBehaviour( "+FEATENHANCE", 40 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 40 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 40 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 40 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 40 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
AddBehaviour( "+BREATH", 40 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+MELEEASSIST", 50 ); //assist allies in melee
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
AddBehaviour( "+ATKMELEE", 100 ); //melee attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
135
_module/nss/no_spn_wiz.nss
Normal file
135
_module/nss/no_spn_wiz.nss
Normal file
@@ -0,0 +1,135 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: On Spawn In
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Determines the course of action to be taken
|
||||
after having just been spawned in
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "no_lib_data"
|
||||
#include "no_inc"
|
||||
#include "nw_o2_coninclude"
|
||||
#include "x0_i0_treasure"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Behaviour config
|
||||
AddBehaviour( "+AVOIDMELEE", 50 ); //avoid melee
|
||||
AddBehaviour( "+EVACAOE", 80 ); //evac AOEs
|
||||
AddBehaviour( "+HEALSELF", 100 ); //heal self
|
||||
AddBehaviour( "+REGROUP", 20 ); //regroup
|
||||
AddBehaviour( "+SUMMON", 50 ); //summon spells
|
||||
AddBehaviour( "+HELP", 50 ); //help
|
||||
AddBehaviour( "+VIS", 50 ); //vision
|
||||
AddBehaviour( "+DEFSELF", 10 ); //defend self
|
||||
AddBehaviour( "+DEFSING", 5 ); //defend single
|
||||
AddBehaviour( "+ENHANCESELF", 10 ); //enhance self
|
||||
AddBehaviour( "+GROUPENHANCE", 5 ); //enhance group
|
||||
AddBehaviour( "+ENHANCESING", 5 ); //enhance single
|
||||
AddBehaviour( "+FEATENHANCE", 10 ); //enhance self via feats
|
||||
AddBehaviour( "+DISPEL", 10 ); //dispel single
|
||||
AddBehaviour( "+DISPELAOE", 10 ); //dispel AOEs
|
||||
AddBehaviour( "+DISMISSAL", 10 ); //dismiss summons
|
||||
AddBehaviour( "+BREACH", 10 ); //breach
|
||||
AddBehaviour( "+TIMESTOP", 20 ); //time stop
|
||||
AddBehaviour( "+AREA", 80 ); //area attack spells
|
||||
AddBehaviour( "+DIRECT", 80 ); //direct attack spells
|
||||
AddBehaviour( "+TOUCH", 80 ); //touch attack spells
|
||||
AddBehaviour( "+ATKRANGED", 100 ); //ranged attack
|
||||
|
||||
//Other config
|
||||
//Corpse decay set up and exclusions
|
||||
SetCorpseDelay();
|
||||
|
||||
//Set whether the creature can use EffectDisappearAppear when moving
|
||||
SetIsFlier();
|
||||
|
||||
if ( GetIsObjectValid( GetMaster( OBJECT_SELF ) ) )
|
||||
{
|
||||
//I am probably a summoned creature, possibly a henchman
|
||||
SetAssociateListenPatterns();
|
||||
}
|
||||
|
||||
//set voice chat config
|
||||
SetVoiceChat( NO_VC_DEFAULT, 10 );
|
||||
|
||||
//configure perception ranges
|
||||
SetPerceptionRanges();
|
||||
|
||||
//set response range for fighting broadcast
|
||||
SetResponseRange( BC_FIGHTING, 50.0 );
|
||||
|
||||
//tell creature it is ready to act
|
||||
//SetReadyStatus();
|
||||
|
||||
//set fastbuffer status, should always be left on
|
||||
SetIsFastBuffer( TRUE );
|
||||
//SetLocalInt( OBJECT_SELF, "#FASTBUFFER", 1 );
|
||||
//SetLocalInt( OBJECT_SELF, "#ACTIVE", 1 );
|
||||
|
||||
//log starting location
|
||||
ExecuteScript( "no_scr_logspnloc", OBJECT_SELF );
|
||||
|
||||
//log loaded melee weapons
|
||||
ExecuteScript( "no_scr_logeq", OBJECT_SELF );
|
||||
|
||||
// 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_SLEEP);
|
||||
//Creatures that spawn in during the night will be asleep.
|
||||
//SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING);
|
||||
//SetSpawnInCondition(NW_FLAG_APPEAR_SPAWN_IN_ANIMATION);
|
||||
//SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS);
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
SetAnimationCondition(NW_ANIM_FLAG_CONSTANT);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
//This will play Ambient Animations until the NPC sees an enemy or is cleared.
|
||||
//NOTE that these animations will play automatically for Encounter Creatures.
|
||||
|
||||
// NOTE: ONLY ONE OF THE FOLOOWING ESCAPE COMMANDS SHOULD EVER BE ACTIVATED AT ANY ONE TIME.
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_RETURN); // OPTIONAL BEHAVIOR (Flee to a way point and return a short time later.)
|
||||
//SetSpawnInCondition(NW_FLAG_ESCAPE_LEAVE); // OPTIONAL BEHAVIOR (Flee to a way point and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_LEAVE); // OPTIONAL BEHAVIOR (Teleport to safety and do not return.)
|
||||
//SetSpawnInCondition(NW_FLAG_TELEPORT_RETURN); // OPTIONAL BEHAVIOR (Teleport to safety and return a short time later.)
|
||||
|
||||
// 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 user 1000 - 1010
|
||||
*/
|
||||
//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
|
||||
|
||||
SetListeningPatterns(); // Goes through and sets up which shouts the NPC will listen to.
|
||||
WalkWayPoints(); // Optional Parameter: void WalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
||||
// 1. Looks to see if any Way Points in the module have the tag "WP_" + NPC TAG + "_0X", if so walk them
|
||||
// 2. If the tag of the Way Point is "POST_" + NPC TAG the creature will return this way point after
|
||||
// combat.
|
||||
CTG_GenerateNPCTreasure(TREASURE_TYPE_MONSTER, OBJECT_SELF); //* Use this to create a small amount of treasure on the creature
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
/*/////////////////////// [On Heartbeat] ///////////////////////////////////////
|
||||
Filename: nw_c2_default1 or J_AI_OnHeartbeat
|
||||
///////////////////////// [On Heartbeat] ///////////////////////////////////////
|
||||
Removed stupid stuff, special behaviour, sleep.
|
||||
|
||||
Also, note please, I removed waypoints and day/night posting from this.
|
||||
It can be re-added if you like, but it does reduce heartbeats.
|
||||
|
||||
Added in better checks to see if we should fire this script. Stops early if
|
||||
some conditions (like we can't move, low AI settings) are set.
|
||||
|
||||
Hint: If nothing is used within this script, either remove it from creatures
|
||||
or create one witch is blank, with just a "void main(){}" at the top.
|
||||
|
||||
Hint 2: You could add this very small file to your catche of scripts in the
|
||||
module properties, as it runs on every creature every 6 seconds (ow!)
|
||||
|
||||
This also uses a system of Execute Script :-D This means the heartbeat, when
|
||||
compiled, should be very tiny.
|
||||
|
||||
Note: NO Debug strings!
|
||||
Note 2: Remember, I use default SoU Animations/normal animations. As it is
|
||||
executed, we can check the prerequisists here, and then do it VIA
|
||||
execute script.
|
||||
|
||||
-Working- Best possible, fast compile.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added more "buffs" to fast buff.
|
||||
- Fixed animations (they both WORK and looping ones do loop right!)
|
||||
- Loot behaviour!
|
||||
- Randomly moving nearer a PC in 25M if set.
|
||||
- Removed silly day/night optional setting. Anything we can remove, is a good idea.
|
||||
1.4 - Removed AI level setting. Not good to use, I mistakenly added it.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This fires off every 6 seconds (with PCs in the area, or AI_LEVEL_HIGH without)
|
||||
and therefore is intensive.
|
||||
|
||||
It fires of ExecutesScript things for the different parts - saves CPU stuff
|
||||
if the bits are not used.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: Basically, none. Nothing activates this script. Fires every 6 seconds.
|
||||
///////////////////////// [On Heartbeat] /////////////////////////////////////*/
|
||||
|
||||
// - This includes J_Inc_Constants
|
||||
#include "J_INC_HEARTBEAT"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Special - Runner from the leader shouts, each heartbeat, to others to get thier
|
||||
// attention that they are being attacked.
|
||||
// - Includes fleeing making sure (so it resets the ActionMoveTo each 6 seconds -
|
||||
// this is not too bad)
|
||||
// - Includes door bashing stop heartbeat
|
||||
if(PerformSpecialAction()) return;
|
||||
|
||||
// Pre-heartbeat-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, EVENT_HEARTBEAT_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff() || GetSpawnInCondition(AI_FLAG_OTHER_LAG_IGNORE_HEARTBEAT, AI_OTHER_MASTER)) return;
|
||||
|
||||
// Define the enemy and player to use.
|
||||
object oEnemy = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY);
|
||||
object oPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
|
||||
|
||||
// We can skip to the end if we are in combat, or something...
|
||||
if(!JumpOutOfHeartBeat() && // We don't stop due to effects.
|
||||
!GetIsInCombat() && // We are not in combat.
|
||||
!GetIsObjectValid(GetAttackTarget()) && // Second combat check.
|
||||
!GetObjectSeen(oEnemy)) // Nearest enemy is not seen.
|
||||
{
|
||||
// Fast buffing...if we have the spawn in condition...
|
||||
if(GetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER) &&
|
||||
GetIsObjectValid(oEnemy) && GetDistanceToObject(oEnemy) <= 40.0)
|
||||
{
|
||||
// ...we may do an advanced buff. If we cannot see/hear oEnemy, but oEnemy
|
||||
// is within 40M, we cast many defensive spells instantly...
|
||||
ExecuteScript(FILE_HEARTBEAT_TALENT_BUFF, OBJECT_SELF);
|
||||
//...if TRUE (IE it does something) we turn of future calls.
|
||||
DeleteSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
// This MUST STOP the heartbeat event - else, the actions may be interrupted.
|
||||
return;
|
||||
}
|
||||
// Execute waypoints file if we have waypoints set up.
|
||||
if(GetWalkCondition(NW_WALK_FLAG_CONSTANT))
|
||||
{
|
||||
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
||||
}
|
||||
// We can't have any waypoints for the other things
|
||||
else
|
||||
{
|
||||
// We must have animations set, and not be "paused", so doing a
|
||||
// longer looping one
|
||||
// - Need a valid player.
|
||||
if(GetIsObjectValid(oPlayer) && !IsInConversation(OBJECT_SELF))
|
||||
{
|
||||
// We may search for PC enemies, 25% chance to move closer to PC's
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_SEARCH_IF_ENEMIES_NEAR, AI_OTHER_MASTER) &&
|
||||
!GetLocalTimer(AI_TIMER_SEARCHING) && d4() == 1)
|
||||
{
|
||||
ExecuteScript(FILE_HEARTBEAT_WALK_TO_PC, OBJECT_SELF);
|
||||
}
|
||||
// Else, Do we have any animations to speak of?
|
||||
// If we have a nearby PC, we do animations.
|
||||
else if(GetHasValidAnimations())
|
||||
{
|
||||
ExecuteScript(FILE_HEARTBEAT_ANIMATIONS, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_HEARTBEAT_EVENT, EVENT_HEARTBEAT_EVENT);
|
||||
}
|
@@ -1,225 +0,0 @@
|
||||
/*/////////////////////// [On Percieve] ////////////////////////////////////////
|
||||
Filename: J_AI_OnPercieve or nw_c2_default2
|
||||
///////////////////////// [On Percieve] ////////////////////////////////////////
|
||||
If the target is an enemy, attack
|
||||
Will determine combat round on that person, is an enemy, basically.
|
||||
Includes shouting for a big radius - if the spawn in condition is set to this.
|
||||
|
||||
NOTE: Debug strings in this file will be uncommented for speed by default.
|
||||
- It is one of the most intensive scripts as it runs so often.
|
||||
- Attempted to optimise as much as possible.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - We include j_inc_other_ai to initiate combat (or go into combat again)
|
||||
- j_inc_other_ai holds all other needed functions/integers ETC.
|
||||
- Turn off hide things.
|
||||
- Added "Only attack if attacked"
|
||||
- Removed special conversation things. Almost no one uses them, and the taunt system is easier.
|
||||
- Should now search around if they move to a dead body, and only once they get there.
|
||||
1.4 - TO DO:
|
||||
|
||||
1. Perception needs checking - attacking outside perception ranges!
|
||||
2. Vanishing targets, etc. test, improve.
|
||||
3. Problems with dispelling invisibility. Maybe either do change the line to create placable, or, of course, cast at location (dispells cannot be metamagiked or whatever) Source
|
||||
4. No Effect Type Ethereal. Source
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
It fires:
|
||||
|
||||
- When a creature enters it perception range (Set in creature properties) and
|
||||
is seen or heard.
|
||||
* Tests show (and in general) it fires HEARD first, then immediantly SEEN if,
|
||||
of course, they are visible. Odd really, but true.
|
||||
- When a creature uses invisiblity/leaves the area in the creatures perception
|
||||
range
|
||||
- When a creature appears suddenly, already in the perception range (not
|
||||
the other way round, normally)
|
||||
- When a creature moves out of the creatures perception range, and therefore
|
||||
becomes unseen.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastPerceived, GetLastPerceptionSeen, GetLastPerceptionHeard,
|
||||
GetLastPerceptionVanished, GetLastPerceptionInaudible.
|
||||
///////////////////////// [On Percieve] //////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-percieve-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_PERCIEVE_PRE_EVENT, EVENT_PERCIEVE_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
//:: Skip commoners unless the are beign attacked
|
||||
string sCommoner = GetTag(OBJECT_SELF);
|
||||
|
||||
if (!GetIsInCombat() && FindSubString(sCommoner, "NPC_COM_")) return;
|
||||
|
||||
// Declare main things.
|
||||
// - We declare OUTSIDE if's JUST IN CASE!
|
||||
object oPerceived = GetLastPerceived();
|
||||
object oAttackTarget = GetAttackTarget();
|
||||
// 1.4: Very rarely is our attack target valid, so we will set it to
|
||||
// what we would have melee attacked when DCR was called.
|
||||
if(GetIgnoreNoFriend(oAttackTarget) || oAttackTarget == OBJECT_SELF)
|
||||
{
|
||||
oAttackTarget = GetAIObject(AI_LAST_MELEE_TARGET);
|
||||
}
|
||||
int bSeen = GetLastPerceptionSeen();
|
||||
int bHeard = GetLastPerceptionHeard();
|
||||
int bVanished = GetLastPerceptionVanished();
|
||||
int bInaudiable = GetLastPerceptionInaudible();
|
||||
|
||||
// Debug
|
||||
DebugActionSpeak("*** PER ***: " + GetName(oPerceived) + "| SEEN: " + IntToString(bSeen) +
|
||||
"| HEARD: " + IntToString(bHeard) + "| VANISHED: " + IntToString(bVanished) +
|
||||
"| INAUDIABLE: " + IntToString(bInaudiable));
|
||||
|
||||
// Need to be valid and not ignorable.
|
||||
if(GetIsObjectValid(oPerceived) &&
|
||||
!GetIsDM(oPerceived) &&
|
||||
!GetIgnore(oPerceived))
|
||||
{
|
||||
// First, easy enemy checks.
|
||||
if(GetIsEnemy(oPerceived) && !GetFactionEqual(oPerceived))
|
||||
{
|
||||
DebugActionSpeak("*** PER *** ENEMY");
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oPerceived);
|
||||
|
||||
// Well, are we both inaudible and vanished?
|
||||
// * the GetLastPerception should only say what specific event has fired!
|
||||
if(bVanished || bInaudiable)
|
||||
{
|
||||
DebugActionSpeak("*** PER *** VANISHED OR INAUDIBLE");
|
||||
// If they just became invisible because of the spell
|
||||
// invisiblity, or improved invisiblity...we set a local object.
|
||||
// - Beta: Added in ethereal as well.
|
||||
if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oPerceived) ||
|
||||
GetHasEffect(EFFECT_TYPE_SANCTUARY, oPerceived) ||
|
||||
GetStealthMode(oPerceived) == STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
// Set object, AND the location they went invisible!
|
||||
SetAIObject(AI_LAST_TO_GO_INVISIBLE, oPerceived);
|
||||
// We also set thier location for AOE dispelling - same name
|
||||
SetAILocation(AI_LAST_TO_GO_INVISIBLE, GetLocation(oPerceived));
|
||||
}
|
||||
|
||||
// If they were our target, follow! >:-D
|
||||
// - Optional, on spawn option, for following through areas.
|
||||
if(oAttackTarget == oPerceived)
|
||||
{
|
||||
DebugActionSpeak("*** PER *** VANISHED OR INAUDIBLE AND IS CURRENT TARGET");
|
||||
// This means they have exited the area! follow!
|
||||
if(GetArea(oPerceived) != GetArea(OBJECT_SELF))
|
||||
{
|
||||
ClearAllActions();
|
||||
// 51: "[Perception] Our Enemy Target changed areas. Stopping, moving too...and attack... [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(51, oPerceived);
|
||||
// Call to stop silly moving to enemies if we are fleeing
|
||||
ActionMoveToEnemy(oPerceived);
|
||||
}
|
||||
// - Added check for not casting a spell. If we are, we finnish
|
||||
// (EG: AOE spell) and automatically carry on.
|
||||
// 1.4: If we are using a targetted spell, we do cancle our
|
||||
// spellcasting if it is them.
|
||||
else if(GetCurrentAction() != ACTION_CASTSPELL ||
|
||||
GetAttackTarget() == oPerceived)
|
||||
{
|
||||
ClearAllActions();
|
||||
// 52: "[Perception] Enemy Vanished (Same area) Retargeting/Searching [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(52, oPerceived);
|
||||
DetermineCombatRound(oPerceived);
|
||||
}
|
||||
}
|
||||
}// End if just gone out of perception
|
||||
// ELSE they have been SEEN or HEARD. We don't check specifics.
|
||||
else //if(bSeen || bHeard)
|
||||
{
|
||||
// If they have been made seen, and they are our attack target,
|
||||
// we must re-do combat round - unless we are casting a spell.
|
||||
if(bSeen && GetCurrentAction() != ACTION_CASTSPELL &&
|
||||
(oAttackTarget == oPerceived || !GetObjectSeen(oAttackTarget)))
|
||||
{
|
||||
// 53: "[Perception] Enemy seen, and was old enemy/cannot see current. Re-evaluating (no spell) [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(53, oPerceived);
|
||||
DetermineCombatRound(oPerceived);
|
||||
|
||||
// Shout to allies to attack oPerceived
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
// Else We check if we are already attacking.
|
||||
else if(!CannotPerformCombatRound() &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_ONLY_ATTACK_IF_ATTACKED, AI_OTHER_MASTER))
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Special shout, d1000 though!
|
||||
SpeakArrayString(AI_TALK_ON_PERCIEVE_ENEMY, TRUE);
|
||||
}
|
||||
|
||||
// Stop stuff because of facing point - New enemy
|
||||
HideOrClear();
|
||||
|
||||
// Get all allies in 60M to come to thier aid. Talkvolume silent
|
||||
// shout does not seem to work well.
|
||||
// - void function. Checks for the spawn int. in it.
|
||||
// - Turns it off in it too (5 minutes - 1.4)
|
||||
// - Variable range On Spawn
|
||||
ShoutBossShout(oPerceived);
|
||||
|
||||
// 54: "[Perception] Enemy Seen. Not in combat, attacking. [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(54, oPerceived);
|
||||
|
||||
// 1.4 change: SetFacingPoint(GetPosition(oPerceived));
|
||||
// Is now part of DetermineCombatRound().
|
||||
// * This means other events will work similarily.
|
||||
DetermineCombatRound(oPerceived);
|
||||
|
||||
// Warn others
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else, they are an equal faction, or not an enemy (or both)
|
||||
else
|
||||
{
|
||||
// If they are dead, or fighting, eg: we saw something on
|
||||
// waypoints, we charge in to investigate.
|
||||
// * Higher intelligence will buff somewhat as well!
|
||||
if((GetIsDead(oPerceived) || GetIsInCombat(oPerceived)) &&
|
||||
(bSeen || bHeard))
|
||||
{
|
||||
if(GetIsDead(oPerceived))
|
||||
{
|
||||
// 55: "[Perception] Percieved Dead Friend! Moving into investigate [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(55, oPerceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 56: "[Perception] Percieved Alive Fighting Friend! Moving to and attacking. [Percieved] " + GetName(oPerceived)
|
||||
DebugActionSpeakByInt(56, oPerceived);
|
||||
}
|
||||
// Check if we can attack
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Hide or clear actions
|
||||
HideOrClear();
|
||||
|
||||
// If we were called to arms, react
|
||||
CallToArmsResponse(oPerceived);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Warn others even if we don't, or cannot, attack
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End of Percieve event
|
||||
FireUserEvent(AI_FLAG_UDE_PERCIEVE_EVENT, EVENT_PERCIEVE_EVENT);
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
/*/////////////////////// [On Combat Round End] ////////////////////////////////
|
||||
Filename: nw_c2_default3 or J_AI_OnCombatrou
|
||||
///////////////////////// [On Combat Round End] ////////////////////////////////
|
||||
This is run every 3 or 6 seconds, if the creature is in combat. It is
|
||||
executed only in combat automatically.
|
||||
|
||||
It runs what the AI should do, bascially.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Executes same script as the other parts of the AI to cuase a new action
|
||||
1.4 -
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Calls the combat AI file using the J_INC_OTHER_AI include function,
|
||||
DetermineCombatRound.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetAttackTarget, GetLastHostileActor, GetAttemptedAttackTarget,
|
||||
GetAttemptedSpellTarget (Or these are useful at least!)
|
||||
///////////////////////// [On Combat Round End] //////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-combat-round-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_END_COMBAT_ROUND_PRE_EVENT, EVENT_END_COMBAT_ROUND_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// It is our normal call (every 3 or 6 seconds, when we can change actions)
|
||||
// so no need to delete, and we fire the UDE's.
|
||||
|
||||
// Determine combat round against an invalid target (as default)
|
||||
DetermineCombatRound();
|
||||
|
||||
// Fire End of end combat round event
|
||||
FireUserEvent(AI_FLAG_UDE_END_COMBAT_ROUND_EVENT, EVENT_END_COMBAT_ROUND_EVENT);
|
||||
}
|
@@ -1,160 +0,0 @@
|
||||
/*/////////////////////// [On Conversation] ////////////////////////////////////
|
||||
Filename: J_AI_OnConversat or nw_c2_default4
|
||||
///////////////////////// [On Conversation] ////////////////////////////////////
|
||||
OnConversation/ Listen to shouts.
|
||||
Documented, and checked. -Working-
|
||||
|
||||
Added spawn in condition - Never clear actions when talking.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in conversation thing - IE we can set speakstrings, no need for conversation file.
|
||||
- Sorted more shouts out.
|
||||
- Should work right, and not cause too many actions (as we ignore
|
||||
shouts for normally 12 or so seconds before letting them affect us again).
|
||||
1.4 - Deafness incorpreated.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Uses RespondToShout to react to allies' shouts, and just attacks any enemy
|
||||
who speaks, or at least moves to them. (OK, dumb if they are invisible, but
|
||||
oh well, they shouldn't talk so loud!)
|
||||
|
||||
Remember, whispers are never heard if too far away, speakstrings don't go
|
||||
through walls, and shouts are always heard (so we don't go off to anyone
|
||||
not in our area, remember)
|
||||
|
||||
Deafness causes us to never hear battle, so unless we see the target speaking
|
||||
we do not react. Doesn't apply to normal conversations - although if we cannot
|
||||
talk (also restricted by deafness) then so be it.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetListenPatternNumber, GetLastSpeaker, TestStringAgainstPattern,
|
||||
GetMatchedSubstring
|
||||
///////////////////////// [On Conversation] //////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-conversation-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ON_DIALOGUE_PRE_EVENT, EVENT_ON_DIALOGUE_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Declarations
|
||||
int nMatch = GetListenPatternNumber();
|
||||
object oShouter = GetLastSpeaker();
|
||||
string sSpoken = GetMatchedSubstring(0);
|
||||
|
||||
// We can ignore everything under special cases - EG no valid shouter,
|
||||
// we are fleeing, its us, or we are not in the same area.
|
||||
// - We break out of the script if this happens.
|
||||
if(!GetIsObjectValid(oShouter) || /* Must be a valid speaker! */
|
||||
oShouter == OBJECT_SELF || /* Not us! */
|
||||
GetIsPerformingSpecialAction() || /* Not fleeing */
|
||||
GetIgnore(oShouter) || /* Not ignoring the shouter */
|
||||
GetArea(oShouter) != GetArea(OBJECT_SELF))/* Same area (Stops loud yellow shouts getting NPCs) */
|
||||
{
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
return;
|
||||
}
|
||||
|
||||
// Conversation if not a shout.
|
||||
if(nMatch == -1)
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Make sure it is a PC and we are not fighting.
|
||||
if(!GetIsFighting() && (GetIsPC(oShouter) || GetIsDMPossessed(oShouter)))
|
||||
{
|
||||
// If we have something random (or not) to say instead of
|
||||
// the conversation, we will say that.
|
||||
if(GetLocalInt(OBJECT_SELF, ARRAY_SIZE + AI_TALK_ON_CONVERSATION))
|
||||
{
|
||||
ClearAllActions();// Stop
|
||||
SetFacingPoint(GetPosition(oShouter));// Face
|
||||
SpeakArrayString(AI_TALK_ON_CONVERSATION);// Speak string
|
||||
PlayAnimation(ANIMATION_LOOPING_TALK_NORMAL, 1.0, 3.0);// "Talk", then resume potitions.
|
||||
ActionDoCommand(ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are set to NOT clear all actions, we won't.
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_NO_CLEAR_ACTIONS_BEFORE_CONVERSATION, AI_OTHER_MASTER))
|
||||
{
|
||||
ClearAllActions();
|
||||
}
|
||||
BeginConversation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it is a valid shout...and a valid shouter.
|
||||
// - Not a DM. Not ignoring shouting. Not a Debug String.
|
||||
else if(!GetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID) &&// Not listening (IE heard already)
|
||||
!GetIsDM(oShouter) && FindSubString(sSpoken, "[Debug]") == -1 &&
|
||||
// 1.4 - Deafness (or they are seen) check, for fun.
|
||||
(!GetHasEffect(EFFECT_TYPE_DEAF) || GetObjectSeen(oShouter)))
|
||||
{
|
||||
if(GetIsFriend(oShouter) || GetFactionEqual(oShouter))
|
||||
{
|
||||
// If they are a friend, not a PC, and a valid number, react.
|
||||
// In the actual RespondToShout call, we do check to see if we bother.
|
||||
// - Is PC - or is...master?
|
||||
// - Shouts which are not negative, and not AI_ANYTHING_SAID_CONSTANT.
|
||||
if(nMatch >= 0 && nMatch != AI_SHOUT_ANYTHING_SAID_CONSTANT &&
|
||||
!GetIsPC(oShouter) && !GetIsPC(GetMaster(oShouter)))
|
||||
{
|
||||
// Respond to the shout
|
||||
RespondToShout(oShouter, nMatch);
|
||||
}
|
||||
// Else either is PC or is shout 0 (everything!)
|
||||
// - not if we are in combat, or they are not.
|
||||
else if(!CannotPerformCombatRound() &&
|
||||
GetIsInCombat(oShouter) &&
|
||||
GetObjectType(oShouter) == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// 57: "[Shout] Friend (may be PC) in combat. Attacking! [Friend] " + GetName(oShouter)
|
||||
DebugActionSpeakByInt(57, oShouter);
|
||||
|
||||
// Respond to oShouter
|
||||
IWasAttackedResponse(oShouter);
|
||||
}
|
||||
}
|
||||
else if(GetIsEnemy(oShouter) && GetObjectType(oShouter) == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// If we hear anything said by an enemy, and are not fighting, attack them!
|
||||
if(!CannotPerformCombatRound())
|
||||
// the negatives are associate shouts, Normally (!)
|
||||
// 0+ are my shouts. 0 is anything
|
||||
{
|
||||
// We make sure it isn't an emote (set by default)
|
||||
if(nMatch == AI_SHOUT_ANYTHING_SAID_CONSTANT &&
|
||||
GetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER))
|
||||
{
|
||||
// Jump out if its an emote - "*Nods*"
|
||||
if(GetStringLeft(sSpoken, 1) == EMOTE_STAR &&
|
||||
GetStringRight(sSpoken, 1) == EMOTE_STAR)
|
||||
{
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 58: "[Shout] Responding to shout [Enemy] " + GetName(oShouter) + " Who has spoken!"
|
||||
DebugActionSpeakByInt(58, oShouter);
|
||||
|
||||
// Short non-respond
|
||||
SetLocalTimer(AI_TIMER_SHOUT_IGNORE_ANYTHING_SAID, 6.0);
|
||||
|
||||
// Attack the enemy!
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oShouter);
|
||||
|
||||
// Shout to allies to attack the shouter
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire End of Dialogue event
|
||||
FireUserEvent(AI_FLAG_UDE_ON_DIALOGUE_EVENT, EVENT_ON_DIALOGUE_EVENT);
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
/*/////////////////////// [On Phisical Attacked] ///////////////////////////////
|
||||
Filename: J_AI_OnPhiAttack or nw_c2_default5
|
||||
///////////////////////// [On Phisical Attacked] ///////////////////////////////
|
||||
On Attacked
|
||||
No checking for fleeing or warnings.
|
||||
Very boring really!
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added hiding things
|
||||
1.4 - Missing Silent Shouts have been added.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Got some simple Knockdown timer, so that we use heal sooner if we keep getting
|
||||
a creature who is attempting to knock us down.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastAttacker, GetLastWeaponUsed, GetLastAttackMode, GetLastAttackType
|
||||
///////////////////////// [On Phisical Attacked] /////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-attacked-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ATTACK_PRE_EVENT, EVENT_ATTACK_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Set up objects.
|
||||
object oAttacker = GetLastAttacker();
|
||||
object oWeapon = GetLastWeaponUsed(oAttacker);
|
||||
//int nMode = GetLastAttackMode(oAttacker); // Currently unused
|
||||
int nAttackType = GetLastAttackType(oAttacker);
|
||||
|
||||
// Check if they are valid, a DM, we are ignoring them, they are dead now, or invalid
|
||||
if(!GetIgnoreNoFriend(oAttacker))
|
||||
{
|
||||
// Adjust automatically if set.
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oAttacker))
|
||||
{
|
||||
AdjustReputation(oAttacker, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
// If we were attacked by knockdown, for a timer of X seconds, we make
|
||||
// sure we attempt healing at a higher level.
|
||||
if(!GetLocalTimer(AI_TIMER_KNOCKDOWN) &&
|
||||
(nAttackType == SPECIAL_ATTACK_IMPROVED_KNOCKDOWN ||
|
||||
nAttackType == SPECIAL_ATTACK_KNOCKDOWN) &&
|
||||
!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_KNOCKDOWN) &&
|
||||
GetBaseAttackBonus(oAttacker) + 20 >= GetAC(OBJECT_SELF))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_KNOCKDOWN, 30.0);
|
||||
}
|
||||
|
||||
// Set last hostile, valid attacker (Used in the On Damaged event)
|
||||
SetAIObject(AI_STORED_LAST_ATTACKER, oAttacker);
|
||||
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Speak the phisically attacked string, if applicable.
|
||||
// Speak the damaged string, if applicable.
|
||||
SpeakArrayString(AI_TALK_ON_PHISICALLY_ATTACKED);
|
||||
}
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oAttacker);
|
||||
|
||||
// We set if we are attacked in HTH onto a low-delay timer.
|
||||
// - Not currently used
|
||||
/*if(!GetLocalTimer(AI_TIMER_ATTACKED_IN_HTH))
|
||||
{
|
||||
// If the weapon is not ranged, or is not valid, set the timer.
|
||||
if(!GetIsObjectValid(oWeapon) ||
|
||||
!GetWeaponRanged(oWeapon))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_ATTACKED_IN_HTH, f18);
|
||||
}
|
||||
}*/
|
||||
|
||||
// If we are not fighting, and they are in the area, attack. Else, determine anyway.
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Must be in our area to go after now.
|
||||
if(GetArea(oAttacker) == GetArea(OBJECT_SELF))
|
||||
{
|
||||
// 59: "[Phisically Attacked] Attacking back. [Attacker(enemy)] " + GetName(oAttacker)
|
||||
DebugActionSpeakByInt(59, oAttacker);
|
||||
|
||||
// Attack the attacker
|
||||
DetermineCombatRound(oAttacker);
|
||||
|
||||
// Shout to allies to attack the enemy who attacked me
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// 60: "[Phisically Attacked] Not same area. [Attacker(enemy)] " + GetName(oAttacker)
|
||||
DebugActionSpeakByInt(60, oAttacker);
|
||||
|
||||
// May find another hostile to attack...
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// Else, invalid, DM, ally, etc...must be prepared at least (could be
|
||||
// they are charmed or something!)
|
||||
else
|
||||
{
|
||||
// If we are not fighting, prepare for battle. Something bad must have
|
||||
// happened.
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Respond to oAttacker as if they shouted for help.
|
||||
IWasAttackedResponse(oAttacker);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End of Attacked event
|
||||
FireUserEvent(AI_FLAG_UDE_ATTACK_EVENT, EVENT_ATTACK_EVENT);
|
||||
}
|
@@ -1,241 +0,0 @@
|
||||
/*/////////////////////// [On Damaged] /////////////////////////////////////////
|
||||
Filename: nw_c2_default6 or J_AI_OnDamaged
|
||||
///////////////////////// [On Damaged] /////////////////////////////////////////
|
||||
We attack any damager if same area (and not already fighting
|
||||
then search for enemies (defaults to searching if there are no enemies left).
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - If we have a damager, not equal faction, and not a DM...
|
||||
- We set Max Elemental damage.
|
||||
- Sets the highest damager and amount (if the new damager is seen/heard)
|
||||
- Polymorph improved a little
|
||||
- Hide check
|
||||
- Morale penalty (if set)
|
||||
1.4 - Elemental damage fixed with bugfixed introduced in later patches.
|
||||
- Moved things around, more documentation, a little more ordered.
|
||||
- Added the missing silent shout strings to get allies to attack.
|
||||
- Damaged taunting will not happen if we are dead.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Now with fixes, we can correctly set physical damage done (and elemental
|
||||
damage).
|
||||
|
||||
Otherwise, this acts like a hositile spell, or a normal attack or pickpocket
|
||||
attempt would - and attack the damn person who dares damage us!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetTotalDamageDealt, GetLastDamager, GetCurrentHitPoints (and max),
|
||||
GetDamageDealtByType (must be done seperatly for each, doesn't count melee damage)
|
||||
///////////////////////// [On Damaged] ///////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-damaged-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DAMAGED_PRE_EVENT, EVENT_DAMAGED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Define Objects/Integers.
|
||||
int nDamage = GetTotalDamageDealt();
|
||||
object oDamager = GetLastDamager();
|
||||
// Check to see if we will polymorph.
|
||||
int nPolymorph = GetAIConstant(AI_POLYMORPH_INTO);
|
||||
|
||||
// Total up the physical damage
|
||||
|
||||
// Polymorph check.
|
||||
if(nPolymorph >= 0)
|
||||
{
|
||||
// We won't polymorph if already so
|
||||
if(!GetHasEffect(EFFECT_TYPE_POLYMORPH))
|
||||
{
|
||||
// Polymorph into the requested shape. Cannot be dispelled.
|
||||
effect eShape = SupernaturalEffect(EffectPolymorph(nPolymorph));
|
||||
effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD);
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eShape, OBJECT_SELF));
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF));
|
||||
}
|
||||
DeleteAIConstant(AI_POLYMORPH_INTO);// We set it to invalid (sets to 0).
|
||||
}
|
||||
// First, we check AOE spells...
|
||||
if(GetObjectType(oDamager) == OBJECT_TYPE_AREA_OF_EFFECT)
|
||||
{
|
||||
// Set the damage done by it (the last damage)
|
||||
// Set to the tag of the AOE, prefixed AI style to be sure.
|
||||
// - Note, doesn't matter about things like
|
||||
if(nDamage > 0)
|
||||
{
|
||||
// Set it to object to string, which we will delete later anywho.
|
||||
SetAIInteger(ObjectToString(oDamager), nDamage);
|
||||
}
|
||||
}
|
||||
// Hostile attacker...but it doesn't matter (at the moment) if they even
|
||||
// did damage.
|
||||
// * GetIgnoreNoFriend() wrappers DM, Validity, Faction Equal and Dead checks in one
|
||||
else if(!GetIgnoreNoFriend(oDamager))
|
||||
{
|
||||
// Adjust automatically if set. (and not an AOE)
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oDamager) && !GetFactionEqual(oDamager))
|
||||
{
|
||||
AdjustReputation(oDamager, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oDamager);
|
||||
|
||||
// Did they do damage to use? (IE: No DR) Some things are inapproprate
|
||||
// to check if no damage was actually done.
|
||||
if(nDamage > 0)
|
||||
{
|
||||
// Speak the damaged string, if applicable.
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
SpeakArrayString(AI_TALK_ON_DAMAGED);
|
||||
}
|
||||
// 1.4 note: These two variables are currently *unused* apart from
|
||||
// healing. When healing a being (even another NPC) they are checked
|
||||
// for massive damage. Can not bother to set the highest damager for now.
|
||||
// NEW:
|
||||
int nHighestDamage = GetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
if(nDamage >= nHighestDamage)
|
||||
{
|
||||
SetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT, nDamage);
|
||||
}
|
||||
|
||||
/* OLD:
|
||||
|
||||
// Get the previous highest damager, and highest damage amount
|
||||
object oHighestDamager = GetAIObject(AI_HIGHEST_DAMAGER);
|
||||
int nHighestDamage = GetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
// Set the highest damager, if they are seen or heard, and have done loads.
|
||||
if((GetObjectSeen(oDamager) || GetObjectHeard(oDamager)) &&
|
||||
nDamage >= nHighestDamage || !GetIsObjectValid(oHighestDamager))
|
||||
{
|
||||
SetAIObject(AI_HIGHEST_DAMAGER, oDamager);
|
||||
SetAIInteger(AI_HIGHEST_DAMAGE_AMOUNT, nDamage);
|
||||
}
|
||||
// Else, if the original was not valid...or not seen/heard, we
|
||||
// delete it so we don't bother to use it later.
|
||||
else if(!GetIsObjectValid(oHighestDamager) ||
|
||||
(!GetObjectSeen(oHighestDamager) && !GetObjectHeard(oHighestDamager)))
|
||||
{
|
||||
DeleteAIObject(AI_HIGHEST_DAMAGER);
|
||||
DeleteAIInteger(AI_HIGHEST_DAMAGE_AMOUNT);
|
||||
}
|
||||
*/
|
||||
|
||||
// Get all the physical damage. Elemental damage is then nDamage minus
|
||||
// the physical damage.
|
||||
int nPhysical = GetDamageDealtByType(DAMAGE_TYPE_BASE_WEAPON |
|
||||
DAMAGE_TYPE_BLUDGEONING |
|
||||
DAMAGE_TYPE_PIERCING |
|
||||
DAMAGE_TYPE_SLASHING);
|
||||
// If they are all -1, then we make nPhysical 0.
|
||||
if(nPhysical <= -1) nPhysical = 0;
|
||||
|
||||
// Physical damage - only sets if the last damager is the last attacker.
|
||||
if(GetAIObject(AI_STORED_LAST_ATTACKER) == oDamager)
|
||||
{
|
||||
// Get the previous highest damage and test it
|
||||
if(nPhysical > GetAIInteger(AI_HIGHEST_PHISICAL_DAMAGE_AMOUNT))
|
||||
{
|
||||
// If higher, and was a melee/ranged attacker, set it.
|
||||
// This does include other additional physical damage - EG:
|
||||
// weapon property: Bonus Damage.
|
||||
SetAIInteger(AI_HIGHEST_PHISICAL_DAMAGE_AMOUNT, nPhysical);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the max elemental damage done, for better use of elemental
|
||||
// protections. This is set for the most damage...so it could be
|
||||
// 1 (for a +1 fire weapon, any number of hits) or over 50 (good
|
||||
// fireball/flame storm etc.)
|
||||
int nElemental = nDamage - nPhysical;
|
||||
if(nElemental > GetAIInteger(MAX_ELEMENTAL_DAMAGE))
|
||||
{
|
||||
SetAIInteger(MAX_ELEMENTAL_DAMAGE, nElemental);
|
||||
}
|
||||
// Set the last damage done, may set to 0 of course :-P
|
||||
// * This is only set if they did damage us at all, however.
|
||||
SetAIInteger(LAST_ELEMENTAL_DAMAGE, nElemental);
|
||||
|
||||
// Morale: We may get a penalty if it does more than a cirtain amount of HP damage.
|
||||
// Other: We set highest damager and amount.
|
||||
if(!GetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER))
|
||||
{
|
||||
// Get penalty and how much damage at once needs to be done
|
||||
int nPenalty = GetBoundriedAIInteger(AI_DAMAGE_AT_ONCE_PENALTY, 6, 50, 1);
|
||||
int nToDamage = GetBoundriedAIInteger(AI_DAMAGE_AT_ONCE_FOR_MORALE_PENALTY, GetMaxHitPoints()/6, GetMaxHitPoints(), 1);
|
||||
if(nDamage > nToDamage)
|
||||
{
|
||||
// 61: "[Damaged] Morale Penalty for 600 seconds [Penalty]" + IntToString(iPenalty)
|
||||
DebugActionSpeakByInt(61, OBJECT_INVALID, nPenalty);
|
||||
// Apply penalty
|
||||
SetMoralePenalty(nPenalty, 300.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we are not attacking anything, and not in combat, react!
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// 62: "[Damaged] Not in combat: DCR [Damager]" + GetName(oDamager)
|
||||
DebugActionSpeakByInt(62, oDamager);
|
||||
|
||||
// Check if they are in the same area. Can be a left AOE spell.
|
||||
// Don't attack purposly across area's.
|
||||
if(GetArea(oDamager) == GetArea(OBJECT_SELF))
|
||||
{
|
||||
// Shout to allies to attack the enemy who attacked me
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
DetermineCombatRound(oDamager);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// Else it is friendly, or invalid damager
|
||||
else
|
||||
{
|
||||
// Still will react - eg: A left AOE spell (which might mean a battle
|
||||
// just happened)
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Shout to allies to attack generally. No target to specifically attack,
|
||||
// as it is an ally.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// 63: [Damaged] Not in combat: DCR. Ally hit us. [Damager(Ally?)]" + GetName(oDamager)
|
||||
DebugActionSpeakByInt(63, oDamager);
|
||||
DetermineCombatRound();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
// User defined event - for normally immoral creatures.
|
||||
if(GetCurrentHitPoints() == 1)
|
||||
{
|
||||
// Fire the immortal damaged at 1 HP event.
|
||||
FireUserEvent(AI_FLAG_UDE_DAMAGED_AT_1_HP, EVENT_DAMAGED_AT_1_HP);
|
||||
}
|
||||
// Fire End of Damaged event
|
||||
FireUserEvent(AI_FLAG_UDE_DAMAGED_EVENT, EVENT_DAMAGED_EVENT);
|
||||
}
|
@@ -1,164 +0,0 @@
|
||||
/*/////////////////////// [On Death] ///////////////////////////////////////////
|
||||
Filename: J_AI_OnDeath or nw_c2_default7
|
||||
///////////////////////// [On Death] ///////////////////////////////////////////
|
||||
Speeded up no end, when compiling, with seperate Include.
|
||||
Cleans up all un-droppable items, all ints and all local things when destroyed.
|
||||
|
||||
Check down near the bottom for a good place to add XP or corpse lines ;-)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in Turn of corpses toggle
|
||||
- Added in appropriate space for XP awards, marked with ideas (effect death)
|
||||
1.4 - Removed the redudnant notes on the "You have gained 0 experience" message
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
You can edit this for experience, there is a seperate section for it.
|
||||
|
||||
It will use DeathCheck to execute a cleanup-and-destroy script, that removes
|
||||
any coprse, named "j_ai_destroyself".
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastKiller.
|
||||
///////////////////////// [On Death] /////////////////////////////////////////*/
|
||||
|
||||
// We only require the constants/debug file. We have 1 function, not worth another include.
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// We need a wrapper. If the amount of deaths, got in this, is not equal to iDeaths,
|
||||
// we don't execute the script, else we do. :-P
|
||||
void DeathCheck(int nDeaths);
|
||||
|
||||
void main()
|
||||
{
|
||||
// If we are set to, don't fire this script at all
|
||||
if(GetAIInteger(I_AM_TOTALLY_DEAD)) return;
|
||||
|
||||
// Pre-death-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DEATH_PRE_EVENT, EVENT_DEATH_PRE_EVENT)) return;
|
||||
|
||||
// Note: No AI on/off check here.
|
||||
|
||||
// Who killed us? (alignment changing, debug, XP).
|
||||
object oKiller = GetLastKiller();
|
||||
|
||||
// Stops if we just applied EffectDeath to ourselves.
|
||||
if(GetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH)) return;
|
||||
|
||||
// Special: To stop giving out multiple amounts of XP, we use EffectDeath
|
||||
// to change the killer, so the XP systems will NOT award MORE XP.
|
||||
// - Even the default one suffers from this!
|
||||
if(GetAIInteger(WE_HAVE_DIED_ONCE))
|
||||
{
|
||||
if(!GetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH))
|
||||
{
|
||||
// Don't apply effect death to self more then once per 2 seconds.
|
||||
SetLocalTimer(AI_TIMER_DEATH_EFFECT_DEATH, 2.0);
|
||||
// This should make the last killer us.
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), OBJECT_SELF);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(GetMaxHitPoints()), OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
else if(oKiller != OBJECT_SELF)
|
||||
{
|
||||
// Set have died once, stops giving out mulitple amounts of XP.
|
||||
SetAIInteger(WE_HAVE_DIED_ONCE, TRUE);
|
||||
|
||||
/*/////////////////////// [Experience] /////////////////////////////////////////
|
||||
THIS is the place for it, below this comment.
|
||||
|
||||
It is useful to use GetFirstFactionMember (and Next), GiveXPToCreature,
|
||||
GetXP, SetXP, GetChallengeRating (of self) all are really useful.
|
||||
|
||||
Bug note: GetFirstFactionMember/Next with the PC parameter means either ONLY PC,
|
||||
and so NPC henchmen, unless FALSE is used, will not be even recognised.
|
||||
///////////////////////// [Experience] ///////////////////////////////////////*/
|
||||
// Do XP things (Use object "oKiller" for who killed us).
|
||||
|
||||
|
||||
|
||||
/*/////////////////////// [Experience] ///////////////////////////////////////*/
|
||||
}
|
||||
|
||||
// Note: Here we do a simple way of checking how many times we have died.
|
||||
// Nothing special. Debugging most useful aspect.
|
||||
int nDeathCounterNew = GetAIInteger(AMOUNT_OF_DEATHS);
|
||||
nDeathCounterNew++;
|
||||
SetAIInteger(AMOUNT_OF_DEATHS, nDeathCounterNew);
|
||||
|
||||
// Here is the last time (in game seconds) we died. It is used in the executed script
|
||||
// to make sure we don't prematurly remove areselves.
|
||||
|
||||
// We may want some sort of visual effect - like implosion or something, to fire.
|
||||
int nDeathEffect = GetAIConstant(AI_DEATH_VISUAL_EFFECT);
|
||||
|
||||
// Valid constants from 0 and up. Apply to our location (not to us, who will go!)
|
||||
if(nDeathEffect >= 0)
|
||||
{
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(nDeathEffect), GetLocation(OBJECT_SELF));
|
||||
}
|
||||
// Default Commoner alignment changing. (If the commoner is not evil!)
|
||||
if(GetLevelByClass(CLASS_TYPE_COMMONER) > 0 &&
|
||||
GetAlignmentGoodEvil(OBJECT_SELF) != ALIGNMENT_EVIL &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_NO_COMMONER_ALIGNMENT_CHANGE, AI_OTHER_MASTER))
|
||||
{
|
||||
if(GetIsPC(oKiller))
|
||||
{
|
||||
AdjustAlignment(oKiller, ALIGNMENT_EVIL, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it is a summon, henchmen or familar of a PC, we adust the PC itself
|
||||
// Clever, eh?
|
||||
object oMaster = GetMaster(oKiller);
|
||||
if(GetIsObjectValid(oMaster) && GetIsPC(oMaster))
|
||||
{
|
||||
AdjustAlignment(oMaster, ALIGNMENT_EVIL, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Always shout when we are killed. Reactions - Morale penalty, and
|
||||
// attack the killer.
|
||||
AISpeakString(AI_SHOUT_I_WAS_KILLED);
|
||||
|
||||
// Speaks the set death speak, like "AGGGGGGGGGGGGGGGGGGG!! NOOOO!" for instance :-)
|
||||
// Note for 1.4: No need for "CanSpeak()" for this, of course.
|
||||
SpeakArrayString(AI_TALK_ON_DEATH);
|
||||
|
||||
// First check - do we use "destroyable corpses" or not? (default, yes)
|
||||
if(!GetSpawnInCondition(AI_FLAG_OTHER_TURN_OFF_CORPSES, AI_OTHER_MASTER))
|
||||
{
|
||||
// We will actually dissapear after 30.0 seconds if not raised.
|
||||
int nTime = GetAIInteger(AI_CORPSE_DESTROY_TIME);
|
||||
if(nTime == 0) // Error checking
|
||||
{
|
||||
nTime = 30;
|
||||
}
|
||||
// 64: "[Death] Checking corpse status in " + IntToString(nTime) + " [Killer] " + GetName(oKiller) + " [Times Died Now] " + IntToString(nDeathCounterNew)
|
||||
DebugActionSpeakByInt(64, oKiller, nTime, IntToString(nDeathCounterNew));
|
||||
// Delay check
|
||||
DelayCommand(IntToFloat(nTime), DeathCheck(nDeathCounterNew));
|
||||
}
|
||||
else
|
||||
{
|
||||
/************************ [Alternative Corpses] ********************************
|
||||
This is where you can add some alternative corpse code - EG looting
|
||||
and so on, without disrupting the rest of the AI (as the corpses
|
||||
are turned off).
|
||||
************************* [Alternative Corpses] *******************************/
|
||||
// Add alternative corpse code here
|
||||
|
||||
|
||||
/************************ [Alternative Corpses] *******************************/
|
||||
}
|
||||
// Signal the death event.
|
||||
FireUserEvent(AI_FLAG_UDE_DEATH_EVENT, EVENT_DEATH_EVENT);
|
||||
}
|
||||
|
||||
// We need a wrapper. If the amount of deaths, got in this, is not equal to iDeaths,
|
||||
// we don't execute the script, else we do. :-P
|
||||
void DeathCheck(int nDeaths)
|
||||
{
|
||||
// Do the deaths imputted equal the amount we have suffered?
|
||||
if(GetAIInteger(AMOUNT_OF_DEATHS) == nDeaths)
|
||||
{
|
||||
// - This now includes a check for Bioware's lootable functions and using them.
|
||||
ExecuteScript(FILE_DEATH_CLEANUP, OBJECT_SELF);
|
||||
}
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
/*/////////////////////// [On Disturbed] ///////////////////////////////////////
|
||||
Filename: J_AI_OnDisturbed or nw_c2_default8
|
||||
///////////////////////// [On Disturbed] ///////////////////////////////////////
|
||||
This will attack pickpockets, and inventory disturbers. Note: Stupidly, Bioware
|
||||
made this only affect the creature by stealing. Still, oh well :-(
|
||||
|
||||
This means that the only event which fires it is pickpocketing.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Changed why we determine combat round
|
||||
- Any change in inventory will trigger appropriate SetWeapons again.
|
||||
- Added turn of hide things.
|
||||
1.4 - Cleaned up a bit. Removed unused declared variable.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Only fired by stealing, great. Oh well, it will attack any disturber anyway.
|
||||
|
||||
It *might* not be fired if the natural spot check to notice a theft doesn't
|
||||
work. No idea personally.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetInventoryDisturbItem, GetLastDisturbed,
|
||||
GetInventoryDisturbType (I think it is always be stolen :-( ).
|
||||
///////////////////////// [On Disturbed] /////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-disturbed-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_DISTURBED_PRE_EVENT, EVENT_DISTURBED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Declare major variables
|
||||
object oDisturber = GetLastDisturbed();
|
||||
object oItem = GetInventoryDisturbItem();
|
||||
int nType = GetInventoryDisturbType();
|
||||
int nBase = GetBaseItemType(oItem);
|
||||
|
||||
// We will reset weapons if it is a weapon.
|
||||
// Reset weapons, or specifically healers kits.
|
||||
if(GetIsObjectValid(oItem))
|
||||
{
|
||||
// Kits
|
||||
if(nBase == BASE_ITEM_HEALERSKIT)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_WEAPONSETTING_SETWEAPONS, 2);
|
||||
ExecuteScript(FILE_RE_SET_WEAPONS, OBJECT_SELF);
|
||||
}
|
||||
else // Think it is a weapon. Saves time :-)
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_WEAPONSETTING_SETWEAPONS, 1);
|
||||
ExecuteScript(FILE_RE_SET_WEAPONS, OBJECT_SELF);
|
||||
}
|
||||
}
|
||||
// Fight! Or search!
|
||||
if(!GetIgnoreNoFriend(oDisturber) &&
|
||||
(nType == INVENTORY_DISTURB_TYPE_STOLEN || GetIsEnemy(oDisturber)))
|
||||
{
|
||||
// Turn of hiding, a timer to activate Hiding in the main file. This is
|
||||
// done in each of the events, with the opposition checking seen/heard.
|
||||
TurnOffHiding(oDisturber);
|
||||
|
||||
// Can we attack?
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Someone specific to attack
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// One debug speak. We always do one.
|
||||
// 65: "[Disturbed] (pickpocket) Attacking Enemy Distrube [Disturber] " + GetName(oTarget) + " [Type] " + IntToString(iType)
|
||||
DebugActionSpeakByInt(65, oDisturber, nType);
|
||||
|
||||
// Attack the disturber
|
||||
DetermineCombatRound(oDisturber);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get allies interested.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
}
|
||||
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_DISTURBED_EVENT, EVENT_DISTURBED_EVENT);
|
||||
}
|
@@ -1,644 +0,0 @@
|
||||
/*/////////////////////// [On Spawn] ///////////////////////////////////////////
|
||||
Filename: J_AI_OnSpawn or nw_c2_default9
|
||||
///////////////////////// [On Spawn] ///////////////////////////////////////////
|
||||
This file contains options that will determine some AI behaviour, and a lot
|
||||
of toggles for turning things on/off. A big read, but might be worthwhile.
|
||||
|
||||
The documentation is actually fully in the readme files, under the name
|
||||
"On Spawn.html", under "AI File Explanations".
|
||||
|
||||
The order of the options:
|
||||
|
||||
- Important Spawn Settings N/A
|
||||
- Targeting & Fleeing (AI_TARGETING_FLEE_MASTER)
|
||||
- Fighting & Spells (AI_COMBAT_MASTER)
|
||||
- Other Combat - Healing, Skills & Bosses (AI_OTHER_COMBAT_MASTER)
|
||||
- Other - Death corpses, minor things (AI_OTHER_MASTER)
|
||||
- User Defined (AI_UDE_MASTER)
|
||||
- Shouts N/A
|
||||
- Default Bioware settings (WP's, Anims) (NW_GENERIC_MASTER)
|
||||
|
||||
The OnSpawn file is a settings file. These things are set onto a creature, to
|
||||
define cirtain actions. If more than one creature has this script, they all
|
||||
use the settings, unless If/Else statements are used somehow. There is also
|
||||
the process of setting any spells/feats availible, and hiding and walk waypoints
|
||||
are started.
|
||||
|
||||
Other stuff:
|
||||
- Targeting is imporant :-D
|
||||
- If you delete this script, there is a template for the On Spawn file
|
||||
in the zip it came in, for use in the "scripttemplate" directory.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
Note: I have removed:
|
||||
- Default "Teleporting" and exit/return (this seemed bugged anyway, or useless)
|
||||
- Spawn in animation. This can be, of course, re-added.
|
||||
- Day/night posting. This is uneeded, with a changed walk waypoints that does it automatically.
|
||||
|
||||
1.0-1.2 - Used short amount of spawn options.
|
||||
1.3 - All constants names are changed, I am afraid.
|
||||
- Added Set/Delete/GetAIInteger/Constant/Object. This makes sure that the AI
|
||||
doesn't ever interfere with other things - it pre-fixes all stored things
|
||||
with AI_INTEGER_ (and so on)
|
||||
1.4 - TO DO: Clear up some old non-working ones
|
||||
- Added in User Defined part of the script, an auto-turn-off-spells for
|
||||
Ranger and Paladin classes. Need to test - perhaps 1.64 fixed it?
|
||||
|
||||
|
||||
Spawn options changed:
|
||||
- Removed AI level settings (can still be done manually)
|
||||
- Added optional (and off by default) fear-visual for fleeing
|
||||
|
||||
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Note: You can do without all the comments (it may be that you don't want
|
||||
the extra KB it adds or something, although it does not at all slow down a module)
|
||||
so as long as you have these at the end:
|
||||
|
||||
AI_SetUpEndOfSpawn();
|
||||
DelayCommand(2.0, SpawnWalkWayPoints());
|
||||
|
||||
Oh, and the include file (Below, "j_inc_spawnin") must be at the top like
|
||||
here. Also recommended is the AI_INTELLIGENCE and AI_MORALE being set (if
|
||||
not using custom AI).
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetIsEncounterCreature
|
||||
///////////////////////// [On Spawn] /////////////////////////////////////////*/
|
||||
|
||||
// Treasure Includes - See end of spawn for uncomment options.
|
||||
|
||||
//#include "nw_o2_coninclude"
|
||||
// Uncomment this if you want default NwN Treasure - Uses line "GenerateNPCTreasure()" at the end of spawn.
|
||||
// - This generates random things from the default pallet based on the creatures level + race
|
||||
|
||||
//#include "x0_i0_treasure"
|
||||
// Uncomment this if you want the SoU Treasure - Uses line "CTG_GenerateNPCTreasure()" at the end of spawn.
|
||||
// - This will spawn treasure based on chests placed in the module. See "x0_i0_treasure" for more information.
|
||||
|
||||
// This is required for all spawn in options!
|
||||
#include "J_INC_SPAWNIN"
|
||||
|
||||
void main()
|
||||
{
|
||||
/************************ [Important Spawn Settings] **************************/
|
||||
SetAIInteger(AI_INTELLIGENCE, 10);
|
||||
// Intelligence value of the creauture. Can be 1-10, read readme's for help.
|
||||
SetAIInteger(AI_MORALE, 10);
|
||||
// Will save (See readme). Remember: -1 or below means they always flee.
|
||||
//SetCustomAIFileName("CUSTOM_AI_FILE");
|
||||
// Sets our custom AI file. Really, only animation settings will apply when this is set.
|
||||
// - Can sort actions against a imputted target (EG: On Percieved enemy) by
|
||||
// "GetLocalObject(OBJECT_SELF, "AI_TEMP_SET_TARGET");"
|
||||
/************************ [Important Spawn Settings] **************************/
|
||||
|
||||
/************************ [Targeting] ******************************************
|
||||
All targeting settings.
|
||||
************************* [Targeting] *****************************************/
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_HP, AI_TARGETING_FLEE_MASTER);
|
||||
// We only attack the lowest current HP.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_AC, AI_TARGETING_FLEE_MASTER);
|
||||
// We only attack the lowest AC (as in 1.2).
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_LOWER_HD, AI_TARGETING_FLEE_MASTER);
|
||||
// Target the lowest hit dice
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_MAGE_CLASSES, AI_TARGETING_FLEE_MASTER);
|
||||
// We go straight for mages/sorcerors. Nearest one.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_ARCHERS, AI_TARGETING_FLEE_MASTER);
|
||||
// We go for the nearest enemy with a ranged weapon equipped.
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_LIKE_PCS, AI_TARGETING_FLEE_MASTER);
|
||||
// We go for the nearest seen PC enemy.
|
||||
|
||||
//SetAIConstant(AI_FAVOURED_ENEMY_RACE, RACIAL_TYPE_HUMAN);
|
||||
// The AI attacks the nearest enemy, seen, of this race. Use the RACIAL_* constants.
|
||||
//SetAIConstant(AI_FAVOURED_ENEMY_CLASS, CLASS_TYPE_BARD);
|
||||
// The AI attacks the nearest enemy, seen, of this class. Use the CLASS_* constants.
|
||||
|
||||
// Target changing - see readme for info.
|
||||
//SetAIInteger(AI_MAX_TURNS_TO_ATTACK_ONE_TARGET, 6);
|
||||
// Maximum rounds to attack the current target, before re-checking.
|
||||
// % Chance to re-set each target type each round (Could result in current target still)
|
||||
//SetAIInteger(AI_MELEE_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
//SetAIInteger(AI_RANGED_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
//SetAIInteger(AI_SPELL_LAST_TO_NEW_TARGET_CHANCE, 20);
|
||||
|
||||
// We only target PC's if there are any in range if this is set
|
||||
//SetSpawnInCondition(AI_FLAG_TARGETING_FILTER_FOR_PC_TARGETS, AI_TARGETING_FLEE_MASTER);
|
||||
|
||||
// Main explanation of AI_SetAITargetingValues, see the AI readme (spawn file)
|
||||
// - Remember, uncommenting one will just ignore it (so will never check target's
|
||||
// AC without TARGETING_AC on)
|
||||
|
||||
AI_SetAITargetingValues(TARGETING_MANTALS, TARGET_LOWER, 1, 12);
|
||||
// Spell mantals are checked only for the spell target. Either Absense of or got any.
|
||||
AI_SetAITargetingValues(TARGETING_RANGE, TARGET_HIGHER, 2, 9);
|
||||
// Range - very imporant! Basis for all ranged/spell attacks.
|
||||
AI_SetAITargetingValues(TARGETING_AC, TARGET_LOWER, 2, 6);
|
||||
// AC is used for all phisical attacks. Lower targets lower (By default).
|
||||
AI_SetAITargetingValues(TARGETING_SAVES, TARGET_LOWER, 2, 4);
|
||||
// Used for spell attacks. Saves are sorta a AC versus spells.
|
||||
|
||||
// Phisical protections. Used by spells, ranged and melee.
|
||||
// Jasperre - simple check if we are a fighter (hit lower phisicals) or a
|
||||
// mage (attack higher!)
|
||||
if(GetBaseAttackBonus(OBJECT_SELF) > ((GetHitDice(OBJECT_SELF)/2) + 1))
|
||||
{
|
||||
// Fighter/Clerics (It is over a mages BAB + 1 (IE 0.5 BAB/Level) target lower
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_LOWER, 2, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mages target higher (so dispel/elemental attack those who fighters
|
||||
// cannot hit as much). (the lowest BAB, under half our hit dice in BAB)
|
||||
AI_SetAITargetingValues(TARGETING_PHISICALS, TARGET_HIGHER, 1, 5);
|
||||
}
|
||||
// Base attack bonus. Used for spells and phisical attacks. Checked with GetBaseAttackBonus.
|
||||
AI_SetAITargetingValues(TARGETING_BAB, TARGET_LOWER, 1, 4);
|
||||
// Hit dice - how powerful in levels the enemy is. Used for all checks.
|
||||
AI_SetAITargetingValues(TARGETING_HITDICE, TARGET_LOWER, 1, 3);
|
||||
|
||||
//AI_SetAITargetingValues(TARGETING_HP_PERCENT, TARGET_LOWER, 1, 3);
|
||||
//AI_SetAITargetingValues(TARGETING_HP_CURRENT, TARGET_LOWER, 1, 3);
|
||||
//AI_SetAITargetingValues(TARGETING_HP_MAXIMUM, TARGET_LOWER, 1, 3);
|
||||
// The HP's are the last thing to choose a target with.
|
||||
/************************ [Targeting] *****************************************/
|
||||
|
||||
/************************ [Fleeing] ********************************************
|
||||
Fleeing - these are toggled on/off by FEARLESS flag.
|
||||
|
||||
3 or under intelligence will just run away. 4 or more will know where allies
|
||||
are, and if there are none, will not run.
|
||||
************************* [Fleeing] *******************************************/
|
||||
SetSpawnInCondition(AI_FLAG_FLEEING_FEARLESS, AI_TARGETING_FLEE_MASTER);
|
||||
// Forces them to not flee. This may be set with AI_SetMaybeFearless at the end.
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_NEVER_FIGHT_IMPOSSIBLE_ODDS, AI_TARGETING_FLEE_MASTER);
|
||||
// This will make the creature never fight against impossible odds (8HD+ different)
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_TURN_OFF_GROUP_MORALE, AI_TARGETING_FLEE_MASTER);
|
||||
// This turns OFF any sort of group morale bonuses.
|
||||
|
||||
//SetAIInteger(AMOUNT_OF_HD_DIFFERENCE_TO_CHECK, -2);
|
||||
// If enemy is within this amount of HD, we do not check morale.
|
||||
SetAIInteger(BASE_MORALE_SAVE, 5);
|
||||
// Base DC of the will save. It is set to 20 + HD difference - Morale - Group morale mod.
|
||||
//SetAIInteger(HP_PERCENT_TO_CHECK_AT, 80);
|
||||
// %HP needed to be at to check morale. This doesn't affect "Never fight impossible odds"
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_NO_OVERRIDING_HP_AMOUNT, AI_TARGETING_FLEE_MASTER);
|
||||
// This will turn off overriding HP checks. AI may decide to run even
|
||||
// not at the %HP above, this turns the checks off.
|
||||
|
||||
//SetAIInteger(AI_DAMAGE_AT_ONCE_FOR_MORALE_PENALTY, GetMaxHitPoints()/6);
|
||||
// Damage needed to be done at once to get a massive morale penalty (Below)
|
||||
//SetAIInteger(AI_DAMAGE_AT_ONCE_PENALTY, 6);
|
||||
// Penalty for the above, set for some time to negativly affect morale. Added to save DC for fleeing.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_FLEE_TO_NEAREST_NONE_SEEN, AI_TARGETING_FLEE_MASTER);
|
||||
// If set, just runs to nearest non-seen ally, and removes the loop for a good group of allies to run to.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_FLEE_TO_OBJECT, AI_TARGETING_FLEE_MASTER);
|
||||
// They will flee to the nearest object of the tag below, if set.
|
||||
//SetLocalString(OBJECT_SELF, AI_FLEE_OBJECT, "BOSS_TAG_OR_WHATEVER");
|
||||
// This needs setting if the above is to work.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_FLEEING_USE_VISUAL_EFFECT, AI_TARGETING_FLEE_MASTER);
|
||||
// If this is on, we play a visual effect while we flee.
|
||||
/************************ [Fleeing] *******************************************/
|
||||
|
||||
/************************ [Combat - Fighters] **********************************
|
||||
Fighter (Phiscal attacks, really) specific stuff - disarmed weapons, better
|
||||
at hand to hand, and archer behaviour.
|
||||
************************* [Combat - Fighters] *********************************/
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_PICK_UP_DISARMED_WEAPONS, AI_COMBAT_MASTER);
|
||||
// This sets to pick up weapons which are disarmed.
|
||||
|
||||
//SetAIInteger(AI_RANGED_WEAPON_RANGE, 3);
|
||||
// This is the range at which they go into melee (from using a ranged weapon). Default is 3 or 5.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_BETTER_AT_HAND_TO_HAND, AI_COMBAT_MASTER);
|
||||
// Set if you want them to move forwards into HTH sooner. Will always
|
||||
// if the enemy is a mage/archer, else % based on range.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ATTACKING, AI_COMBAT_MASTER);
|
||||
// For archers. If they have ally support, they'd rather move back & shoot then go into HTH.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_MOVE_BACK, AI_COMBAT_MASTER);
|
||||
// This forces the move back from attackers, and shoot bows. Very small chance to go melee.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_ARCHER_ALWAYS_USE_BOW, AI_COMBAT_MASTER);
|
||||
// This will make the creature ALWAYs use any bows it has. ALWAYS.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NO_GO_FOR_THE_KILL, AI_COMBAT_MASTER);
|
||||
// Turns off any attempts to kill dying PCs, or attack low hit point people.
|
||||
// This is only ever attempted at 9 or 10 intelligence anyway.
|
||||
/************************ [Combat - Fighters] *********************************/
|
||||
|
||||
/************************ [Combat - Spell Casters] *****************************
|
||||
Spellcaster AI has been improved significantly. As well as adding all new spells,
|
||||
now spellcasters more randomly choose spells from the same level (EG: they
|
||||
may choose not to cast magic missile, and cast negative energy ray instead).
|
||||
|
||||
There are also options here for counterspelling, fast buffing, Cheat cast spells,
|
||||
dispelling, spell triggers, long ranged spells first, immunity toggles, and AOE settings.
|
||||
************************* [Combat - Spell Casters] ****************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_LONGER_RANGED_SPELLS_FIRST, AI_COMBAT_MASTER);
|
||||
// Casts spells only if the caster would not move into range to cast them.
|
||||
// IE long range spells, then medium, then short (unless the enemy comes to us!)
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_FLAG_FAST_BUFF_ENEMY, AI_COMBAT_MASTER);
|
||||
// When an enemy comes in 40M, we fast-cast many defensive spells, as if prepared.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_SUMMON_FAMILIAR, AI_COMBAT_MASTER);
|
||||
// The caster summons thier familiar/animal companion. Either a nameless Bat or Badger respectivly.
|
||||
|
||||
// Counterspelling/Dispelling...
|
||||
// It checks for these classes within the 20M counterspell range.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_ARCANE, AI_COMBAT_MASTER);
|
||||
// If got dispels, it counterspells Arcane (Mage/Sorceror) spellcasters.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_DIVINE, AI_COMBAT_MASTER);
|
||||
// If got dispels, it counterspells Divine (Cleric/Druid) spellcasters.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_COUNTER_SPELL_ONLY_IN_GROUP, AI_COMBAT_MASTER);
|
||||
// Recommended. Only counterspells with 5+ allies in group.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_MAGES_MORE, AI_COMBAT_MASTER);
|
||||
// Targets seen mages to dispel, else uses normal spell target.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_DISPEL_IN_ORDER, AI_COMBAT_MASTER);
|
||||
// This will make the mage not dispel just anything all the time, but important (spell-stopping)
|
||||
// things first, others later, after some spells. If off, anything is dispelled.
|
||||
|
||||
// AOE's
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NEVER_HIT_ALLIES, AI_COMBAT_MASTER);
|
||||
// Override toggle. Forces to never cast AOE's if it will hit an ally + harm them.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_AOE_DONT_MIND_IF_THEY_SURVIVE, AI_COMBAT_MASTER);
|
||||
// Allies who will survive the blast are ignored for calculating best target.
|
||||
//SetAIInteger(AI_AOE_ALLIES_LOWEST_IN_AOE, 3);
|
||||
// Defualt: 3. If amount of allies in blast radius are equal or more then
|
||||
// this, then that location is ignored.
|
||||
//SetAIInteger(AI_AOE_HD_DIFFERENCE, -8);
|
||||
// Very weak allies (who are not comparable to us) are ignored if we would hit them.
|
||||
|
||||
// For these 2, if neither are set, the AI will choose AOE more if there are
|
||||
// lots of enemies, or singles if there are not many.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_SINGLE_TARGETING, AI_COMBAT_MASTER);
|
||||
// For Same-level spells, single target spells are used first.
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_MANY_TARGETING, AI_COMBAT_MASTER);
|
||||
// For Same-level spells, AOE spells are used first.
|
||||
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_INSTANT_DEATH_SPELLS, AI_COMBAT_MASTER);
|
||||
// A few Death spells may be cast top-prioritory if the enemy will always fail saves.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SUMMON_TARGETING, AI_COMBAT_MASTER);
|
||||
// Will use a better target to summon a creature at (EG: Ranged attacker)
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_IMMUNITY_CHECKING, AI_COMBAT_MASTER);
|
||||
// Turns On "GetIsImmune" checks. Auto on for 7+ Intel.
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_IMPROVED_SPECIFIC_SPELL_IMMUNITY, AI_COMBAT_MASTER);
|
||||
// Turns On checks for Globes & levels of spells. Auto on for 9+ Intel.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_MORE_ALLY_BUFFING_SPELLS, AI_COMBAT_MASTER);
|
||||
// This will make the caster buff more allies - or, in fact, use spells
|
||||
// to buff allies which they might have not used before.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_USE_ALL_POTIONS, AI_COMBAT_MASTER);
|
||||
// Uses all buffing spells before melee.
|
||||
|
||||
//SetAICheatCastSpells(SPELL_MAGIC_MISSILE, SPELL_ICE_DAGGER, SPELL_HORIZIKAULS_BOOM, SPELL_MELFS_ACID_ARROW, SPELL_NEGATIVE_ENERGY_RAY, SPELL_FLAME_ARROW);
|
||||
// Special: Mages cast for ever with this set.
|
||||
|
||||
// Spell triggers
|
||||
//SetSpellTrigger(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, FALSE, 1, SPELL_PREMONITION);
|
||||
// This is just an example. See readme for more info.
|
||||
|
||||
/************************ [Combat - Spell Casters] ****************************/
|
||||
|
||||
/************************ [Combat - Dragons] ***********************************
|
||||
I have a fondness for dragons - in NWN they are deprived of many abilities. Here
|
||||
are some new ones for your enjoyment! Switches and flying for ANYTHING! :-)
|
||||
************************* [Combat - Dragons] **********************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_COMBAT_NO_WING_BUFFET, AI_COMBAT_MASTER);
|
||||
//This sets so there is no Dragon wing buffet. Readme has details of it.
|
||||
//SetAIInteger(AI_DRAGON_FREQUENCY_OF_BUFFET, 3);
|
||||
// Min. Amount of Rounds between each buffet. See readme for counter defaults. Def: 3
|
||||
//SetAIInteger(AI_DRAGON_FREQUENCY_OF_BREATH, 3);
|
||||
// Min. Amount of Rounds between each breath use. See readme for counter defaults. Def: 3
|
||||
|
||||
// Default checks for dragon flying automatic turning on of flying.
|
||||
if(GetLevelByClass(CLASS_TYPE_DRAGON) || MyPRCGetRacialType(OBJECT_SELF) == RACIAL_TYPE_DRAGON)
|
||||
{
|
||||
SetSpawnInCondition(AI_FLAG_COMBAT_FLYING, AI_COMBAT_MASTER);
|
||||
// This turns ON combat flying. I think anything winged looks A-OK. See readme for info.
|
||||
}
|
||||
/************************ [Combat - Dragons] **********************************/
|
||||
|
||||
/************************ [Combat Other - Healers/Healing] *********************
|
||||
Healing behaviour - not specifically clerics. See readme.
|
||||
************************* [Combat Other - Healers/Healing] ********************/
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_HEAL_AT_PERCENT_NOT_AMOUNT, AI_OTHER_COMBAT_MASTER);
|
||||
// if this is set, we ignore the amount we need to be damaged, as long
|
||||
// as we are under AI_HEALING_US_PERCENT.
|
||||
//SetAIInteger(AI_HEALING_US_PERCENT, 50);
|
||||
// % of HP we need to be at until we heal us at all. Default: 50
|
||||
//SetAIInteger(AI_HEALING_ALLIES_PERCENT, 60);
|
||||
// % of HP allies would need to be at to heal them Readme = info. Default: 60
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_WILL_RAISE_ALLIES_IN_BATTLE, AI_OTHER_COMBAT_MASTER);
|
||||
// Turns on rasing dead with Resurrection/Raise dead.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_CURING, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off all healing.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_ONLY_CURE_SELF, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off ally healing.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_ONLY_RESTORE_SELF, AI_OTHER_COMBAT_MASTER);
|
||||
// This turns off ally restoring (Remove/Restoration).
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_USE_BAD_HEALING_SPELLS, AI_OTHER_COMBAT_MASTER);
|
||||
// This forces all cure spells to be used, check readme.
|
||||
//SetAIInteger(SECONDS_BETWEEN_STATUS_CHECKS, 30);
|
||||
// Seconds between when we loop everyone for bad effects like Fear/stun ETC. If not set, done each round.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GIVE_POTIONS_TO_HELP, AI_OTHER_COMBAT_MASTER);
|
||||
// ActionGiveItem standard healing potion's to allies who need them, if they possess them.
|
||||
|
||||
/************************ [Combat Other - Healers/Healing] ********************/
|
||||
|
||||
/************************ [Combat Other - Skills] ******************************
|
||||
Skills are a part of fighting - EG Taunt. These are mainly on/off switches.
|
||||
A creature will *may* use it if they are not set to "NO_" for the skill.
|
||||
************************* [Combat Other - Skills] *****************************/
|
||||
|
||||
// "NO" - This is for forcing the skill NEVER to be used by the combat AI.
|
||||
// "FORCE" - This forces it on (and to be used), except if they have no got the skill.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PICKPOCKETING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_TAUNTING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_EMPATHY, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_HIDING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_USING_HEALING_KITS, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_PARRYING, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_SEARCH, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_SEARCH, AI_OTHER_COMBAT_MASTER);
|
||||
// - Concentration - special notes in the readme
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_CONCENTRATION, AI_OTHER_COMBAT_MASTER);
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_FORCE_CONCENTRATION, AI_OTHER_COMBAT_MASTER);
|
||||
|
||||
/************************ [Combat Other - Skills] *****************************/
|
||||
|
||||
/************************ [Combat Other - Leaders] *****************************
|
||||
Leaders/Bosses can be set to issue some orders and inspire more morale - and bring
|
||||
a lot of allies to a battle at once!
|
||||
************************* [Combat Other - Leaders] ****************************/
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_GROUP_LEADER, AI_OTHER_COMBAT_MASTER);
|
||||
// Special leader. Can issuse some orders. See readme for details.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_COMBAT_BOSS_MONSTER_SHOUT, AI_OTHER_COMBAT_MASTER);
|
||||
// Boss shout. 1 time use - calls all creatures in X meters (below) for battle!
|
||||
//SetAIInteger(AI_BOSS_MONSTER_SHOUT_RANGE, 60);
|
||||
// Defaults to a 60 M range. This can change it. Note: 1 toolset square = 10M.
|
||||
|
||||
/************************ [Combat Other - Leaders] ****************************/
|
||||
|
||||
/************************ [Other - Behaviour/Generic] **************************
|
||||
This is generic behaviours - alright, really it is all things that cannot
|
||||
really be categorised.
|
||||
************************* [Other - Behaviour/Generic] *************************/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_CLEAR_ACTIONS_BEFORE_CONVERSATION, AI_OTHER_MASTER);
|
||||
// No ClearAllActions() before BeginConversation. May keep a creature sitting.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_POLYMORPHING, AI_OTHER_MASTER);
|
||||
// This will stop all polymorphing spells feats from being used.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_CHEAT_MORE_POTIONS, AI_OTHER_MASTER);
|
||||
// If at low HP, and no potion, create one and use it.
|
||||
//SetAIConstant(AI_POLYMORPH_INTO, POLYMORPH_TYPE_WEREWOLF);
|
||||
// Polymorph to this creature when damaged (once, natural effect).
|
||||
|
||||
//AI_CreateRandomStats(-3, 3, 6);
|
||||
// Create (Effect-applied) random statistics.
|
||||
//AI_CreateRandomOther(-2, 2, -2, 2, -2, 2, -2, 2);
|
||||
// Create (Effect-applied) random HP, saves, AC.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_RETURN_TO_SPAWN_LOCATION, AI_OTHER_MASTER);
|
||||
// This will store our spawn location, and then move back there after combat.
|
||||
SetSpawnInCondition(AI_FLAG_OTHER_DONT_RESPOND_TO_EMOTES, AI_OTHER_MASTER);
|
||||
// This will ignore ALL chat by PC's (Enemies) who speak actions in Stars - *Bow*
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_DONT_SHOUT, AI_OTHER_MASTER);
|
||||
// Turns off all silent talking NPC's do to other NPC's.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_SEARCH_IF_ENEMIES_NEAR, AI_OTHER_MASTER);
|
||||
// Move randomly closer to enemies in range set below.
|
||||
//SetAIInteger(AI_SEARCH_IF_ENEMIES_NEAR_RANGE, 25);
|
||||
// This is the range creatures use, in metres.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_ONLY_ATTACK_IF_ATTACKED, AI_OTHER_MASTER);
|
||||
// One shot. We won't instantly attack a creature we see. See readme.
|
||||
|
||||
//SetAIInteger(AI_DOOR_INTELLIGENCE, 1);
|
||||
// 3 Special "What to do with Doors" settings. See readme. Good for animals.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_REST_AFTER_COMBAT, AI_OTHER_MASTER);
|
||||
// When combat is over, creature rests. Useful for replenising health.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_NO_PLAYING_VOICE_CHAT, AI_OTHER_MASTER);
|
||||
// Stops any use of "PlayVoiceChat". Use with Custom speakstrings.
|
||||
|
||||
/*** Death settings - still under AI_OTHER_MASTER ***/
|
||||
|
||||
//AI_SetDeathResRef("Resref Here");
|
||||
// Creates a creature from the string set. Instantly destroys this creatures body on death.
|
||||
|
||||
//SetAIConstant(AI_DEATH_VISUAL_EFFECT, VFX_FNF_IMPLOSION);
|
||||
// Fires this visual effect number instantly on death. Use FNF and IMP ones.
|
||||
|
||||
//SetAIInteger(AI_CORPSE_DESTROY_TIME, 30);
|
||||
// Seconds before body finally gets destroyed. Used for Clerical Raise Dead on NPC's.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_TURN_OFF_CORPSES, AI_OTHER_MASTER);
|
||||
// This turns off the SetDestroyable() usually performed, and the above timer.
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_USE_BIOWARE_LOOTING, AI_OTHER_MASTER);
|
||||
// Makes the death file use Bioware's cool SetLootable() feature when corpses would disappear.
|
||||
|
||||
/*** Lag and a few performance settings - still under AI_OTHER_MASTER ***/
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_ITEMS, AI_OTHER_MASTER);
|
||||
// The creature doesn't check for, or use any items that cast spells.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
//The creature doesn't ever cast spells (and never checks them)
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_LISTENING, AI_OTHER_MASTER);
|
||||
// The creature doesn't have SetListening() set. Turns of the basic listening for shouts.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_EQUIP_MOST_DAMAGING, AI_OTHER_MASTER);
|
||||
// Uses EquipMostDamaging(), like Bioware code. No shield/second weapon equipped.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_CURING_ALLIES, AI_OTHER_MASTER);
|
||||
// This will stop checks for and curing of allies ailments.
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_IGNORE_HEARTBEAT, AI_OTHER_MASTER);
|
||||
// Stops the heartbeat running (Except Pre-Heartbeat-event).
|
||||
//SetSpawnInCondition(AI_FLAG_OTHER_LAG_TARGET_NEAREST_ENEMY, AI_OTHER_MASTER);
|
||||
// Ignores targeting settings. VERY good for lag/bad AI. Attacks nearest seen enemy.
|
||||
|
||||
/************************ [Other - Behaviour/Generic] *************************/
|
||||
|
||||
/************************ [User Defined and Shouts] ****************************
|
||||
The user defined events, set up to fire here.
|
||||
- New "Start combat attack" and "End Combat Attack" events
|
||||
- New "Pre" events. Use these to optionally stop a script from firing
|
||||
under cirtain circumstances as well! (Read nw_c2_defaultd or j_ai_onuserdef)
|
||||
(User Defined Event = UDE)
|
||||
************************* [User Defined and Shouts] ***************************/
|
||||
|
||||
// This is REQUIRED if we use any Pre-events. If not there, it will default
|
||||
// to the default User Defined Event script for the default AI.
|
||||
SetCustomUDEFileName("k_ai_onuserdef");
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_EVENT, AI_UDE_MASTER); // UDE 1001
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, AI_UDE_MASTER); // UDE 1021
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_PERCIEVE_EVENT, AI_UDE_MASTER); // UDE 1002
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_PERCIEVE_PRE_EVENT, AI_UDE_MASTER); // UDE 1022
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_END_COMBAT_ROUND_EVENT, AI_UDE_MASTER); // UDE 1003
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_END_COMBAT_ROUND_PRE_EVENT, AI_UDE_MASTER); // UDE 1023
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_DIALOGUE_EVENT, AI_UDE_MASTER); // UDE 1004
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_DIALOGUE_PRE_EVENT, AI_UDE_MASTER); // UDE 1024
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ATTACK_EVENT, AI_UDE_MASTER); // UDE 1005
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ATTACK_PRE_EVENT, AI_UDE_MASTER); // UDE 1025
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_EVENT, AI_UDE_MASTER); // UDE 1006
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_PRE_EVENT, AI_UDE_MASTER); // UDE 1026
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DEATH_EVENT, AI_UDE_MASTER); // UDE 1007
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DEATH_PRE_EVENT, AI_UDE_MASTER); // UDE 1027
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DISTURBED_EVENT, AI_UDE_MASTER); // UDE 1008
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DISTURBED_PRE_EVENT, AI_UDE_MASTER); // UDE 1028
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_RESTED_EVENT, AI_UDE_MASTER); // UDE 1009
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_RESTED_PRE_EVENT, AI_UDE_MASTER); // UDE 1029
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_SPELL_CAST_AT_EVENT, AI_UDE_MASTER); // UDE 1011
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_SPELL_CAST_AT_PRE_EVENT, AI_UDE_MASTER); // UDE 1031
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_BLOCKED_EVENT, AI_UDE_MASTER); // UDE 1015
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, AI_UDE_MASTER); // UDE 1035
|
||||
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_COMBAT_ACTION_EVENT, AI_UDE_MASTER); // UDE 1012
|
||||
// Fires when we have finnished all combat actions.
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_COMBAT_ACTION_PRE_EVENT, AI_UDE_MASTER); // UDE 1032
|
||||
// This fires at the start of DetermineCombatRound() *IF they can do an action*.
|
||||
//SetSpawnInCondition(AI_FLAG_UDE_DAMAGED_AT_1_HP, AI_UDE_MASTER); // UDE 1014
|
||||
// Fires when we are damaged, and are at 1 HP. Use for immortal-flagged creatures.
|
||||
|
||||
/*** Speakstrings - as it were, said under cirtain conditions % chance each time ***/
|
||||
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_CONVERSATION, 100, 4, "Hello there", "I hope you enjoy your stay", "Do you work here too?", "*Hic*");
|
||||
// On Conversation - see readme. Replaces BeginConversation().
|
||||
|
||||
// Morale
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_MORALE_BREAK, 100, 3, "No more!", "I'm outta here!", "Catch me if you can!");
|
||||
// Spoken at running point, if they run to a group of allies.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_CANNOT_RUN, 100, 3, "Never give up! Never surrender!", "I've no where to run, so make my day!", "RRRAAAAA!!!");
|
||||
// Spoken at running point, if they can find no ally to run to, and 4+ Intelligence. See readme
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_STUPID_RUN, "Ahhhhgggg! NO MORE! Run!!");
|
||||
// As above, when morale breaks + no ally, but they panic and run from enemy at 3 or less intelligence.
|
||||
|
||||
// Combat
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_EQUAL, 5, 4, "Come on!", "You won't win!", "We are not equals! I am better!", "Nothing will stop me!");
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_THEM_OVER_US, 5, 4, "I'll try! try! and try again!", "Tough man, are we?", "Trying out your 'skills'? Pathetic excuse!", "Nothing good will come from killing me!");
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_COMBAT_ROUND_US_OVER_THEM, 5, 4, "My strength is mighty then yours!", "You will definatly die!", "NO chance for you!", "No mercy! Not for YOU!");
|
||||
// Spoken each DetermineCombatRound. % is /1000. See readme for Equal/Over/Under values.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_TAUNT, 100, 3, "You're going down!", "No need to think, let my blade do it for you!", "Time to meet your death!");
|
||||
// If the creature uses thier skill, taunt, on an enemy this will be said.
|
||||
|
||||
// Event-driven.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_PERCIEVE_ENEMY, 70, 6, "Stand and fight, lawbreaker!", "Don't run from the law!", "I have my orders!", "I am ready for violence!", "CHARGE!", "Time you died!");
|
||||
// This is said when they see/hear a new enemy, and start attacking them.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_DAMAGED, 20, 2, "Ouch, damn you!", "Haha! Nothing will stop me!");
|
||||
// A random value is set to speak when damaged, and may fire same time as below ones.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_PHISICALLY_ATTACKED, 20, 2, "Hah! Mear weapons won't defeat me!", "Pah! You cannot defeat me with such rubbish!");
|
||||
// This is said when an enemy attacks the creature with a melee/ranged weapon.
|
||||
//AI_SetSpawnInSpeakArray(AI_TALK_ON_HOSTILE_SPELL_CAST_AT, 20, 2, "No one spell will stop me!", "Is that all you have!?!");
|
||||
// This is said when an enemy attacks the creature with a hostile spell.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_DEATH, "Agggggg!");
|
||||
// This will ALWAYS be said, whenever the creature dies.
|
||||
|
||||
// Specific potion ones.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_WE_PASS_POTION, "Here! Catch!");
|
||||
// This will be spoken when the creature passes a potion to an ally. See readme.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_WE_GOT_POTION, "Got it!");
|
||||
// This will be spoken by the creature we pass the potion too, using AssignCommand().
|
||||
|
||||
// Leader ones
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_SEND_RUNNER, "Quickly! We need help!");
|
||||
// This will be said when the leader, if this creature, sends a runner.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_ATTACK_TARGET, "Help attack this target!");
|
||||
// When the leader thinks target X should be attacked, it will say this.
|
||||
//AI_SetSpawnInSpeakValue(AI_TALK_ON_LEADER_BOSS_SHOUT, "Come my minions! To battle!");
|
||||
// This will be said when the leader, if this creature, sees an enemy and uses his "Boss Monster Shout", if turned on.
|
||||
|
||||
|
||||
/************************ [User Defined and Shouts] ***************************/
|
||||
|
||||
/************************ [Bioware: Animations/Waypoints/Treasure] *************
|
||||
All Bioware Stuff. I'd check out "x0_c2_spwn_def" for the SoU/Hordes revisions.
|
||||
************************* [Bioware: Animations/Waypoints/Treasure] ************/
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_STEALTH, NW_GENERIC_MASTER);
|
||||
// SetSpawnInCondition(NW_FLAG_SEARCH, NW_GENERIC_MASTER);
|
||||
// Uses said skill while WalkWaypoints()
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_DAY_NIGHT_POSTING, NW_GENERIC_MASTER);
|
||||
// Separate the NPC's waypoints into day & night. See comment in "nw_i0_generic" for use.
|
||||
|
||||
// SetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
// This will cause an NPC to use common animations it possesses,
|
||||
// and use social ones to any other nearby friendly NPCs.
|
||||
// SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
// Same as above, except NPC will wander randomly around the area.
|
||||
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_CIVILIZED);
|
||||
// Interacts with placeables + More civilized actions. See Readme.
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_CHATTER);
|
||||
// Will use random voicechats during animations, if Civilized
|
||||
// SetAnimationCondition(NW_ANIM_FLAG_IS_MOBILE_CLOSE_RANGE);
|
||||
// Will move around the area a bit more, if using Immobile Animations. See readme.
|
||||
|
||||
// Treasure generating.
|
||||
//CTG_GenerateNPCTreasure();
|
||||
// SoU. Requires "x0_i0_treasure" to be uncommented. See readme.
|
||||
//GenerateNPCTreasure();
|
||||
// Default NwN. Requires "nw_o2_coninclude" to be uncommented. See readme.
|
||||
|
||||
/************************ [Bioware: Animations/Waypoints/Treasure] ************/
|
||||
|
||||
// AI Behaviour. DO NOT CHANGE! DO NOT CHANGE!!!
|
||||
AI_SetUpEndOfSpawn();
|
||||
// This MUST be called. It fires these events:
|
||||
// SetUpSpells, SetUpSkillToUse, SetListeningPatterns, SetWeapons, AdvancedAuras.
|
||||
// These MUST be called! the AI might fail to work correctly if they don't fire!
|
||||
|
||||
/************************ [User] ***********************************************
|
||||
This is the ONLY place you should add user things, on spawn, such as
|
||||
visual effects or anything, as it is after SetUpEndOfSpawn. By default, this
|
||||
does have encounter animations on. This is here, so is easily changed :-D
|
||||
|
||||
Be careful otherwise.
|
||||
|
||||
Notes:
|
||||
- SetListening is already set to TRUE, unless AI_FLAG_OTHER_LAG_NO_LISTENING is on.
|
||||
- SetListenPattern's are set from 0 to 7.
|
||||
- You can use the wrappers AI_SpawnInInstantVisual and AI_SpawnInPermamentVisual
|
||||
for visual effects (Instant/Permament as appropriate).
|
||||
************************* [User] **********************************************/
|
||||
// Example (and default) of user addition:
|
||||
// - If we are from an encounter, set mobile (move around) animations.
|
||||
if(GetIsEncounterCreature())
|
||||
{
|
||||
SetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS, NW_GENERIC_MASTER);
|
||||
}
|
||||
// Leave this in if you use the variable for creature attacks, as for golems. Bioware's code.
|
||||
int nNumber = GetLocalInt(OBJECT_SELF, "CREATURE_VAR_NUMBER_OF_ATTACKS");
|
||||
if(nNumber > 0)
|
||||
{
|
||||
SetBaseAttackBonus(nNumber);
|
||||
}
|
||||
|
||||
// If we are a ranger or paladin class, do not cast spells. This can be
|
||||
// manually removed if wished. To get the spells they have working correctly,
|
||||
// remove this, and use Monster Abilties instead of thier normal class spells.
|
||||
// if(GetLevelByClass(CLASS_TYPE_RANGER) >= 1 || GetLevelByClass(CLASS_TYPE_PALADIN) >= 1)
|
||||
// {
|
||||
// SetSpawnInCondition(AI_FLAG_OTHER_LAG_NO_SPELLS, AI_OTHER_MASTER);
|
||||
// }
|
||||
|
||||
/************************ [User] **********************************************/
|
||||
|
||||
// Note: You shouldn't really remove this, even if they have no waypoints.
|
||||
DelayCommand(2.0, SpawnWalkWayPoints());
|
||||
// Delayed walk waypoints, as to not upset instant combat spawning.
|
||||
// This will also check if to change to day/night posts during the walking, no heartbeats.
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
/*/////////////////////// [On Rested] //////////////////////////////////////////
|
||||
Filename: J_AI_OnRest or nw_c2_defaulta
|
||||
///////////////////////// [On Rested] //////////////////////////////////////////
|
||||
This will play the sitting animation for 6 seconds, just something for resting.
|
||||
Also, walks waypoints (as resting would stop this) :-) and signals event (if so be)
|
||||
Feel free to edit.
|
||||
|
||||
It does have the spell trigger information resetting, however. This can
|
||||
only be removed if they have no spell triggers, although it is hardly worth it.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added sitting.
|
||||
1.4 - Will be editing this down. No need to reset anything on rest, for a
|
||||
better working AI.
|
||||
IDEA: Change so that we will work through all spells/feats in order.
|
||||
If, at cirtain levels, we do not have any spells to cast from that
|
||||
level (set in a global stored integer in the general AI) we ignore all
|
||||
spells in that level. Same for each talent category (no need to use
|
||||
talents for them in the spawn script).
|
||||
|
||||
If not in combat (EG: In heartbeat) we reset the integers saying "don't
|
||||
bother checking those spells" to false.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This fires once, at the END of resting.
|
||||
|
||||
If ClearAllActions is added, the resting is actually stopped, or so it seems.
|
||||
|
||||
It doesn't fire more then once.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: None, it seems.
|
||||
///////////////////////// [On Rested] ////////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
// Resets all spell triggers used for sString
|
||||
void LoopResetTriggers(string sString, object oTrigger);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-rest-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_RESTED_PRE_EVENT, EVENT_RESTED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// Simple debug.
|
||||
// 66: "[Rested] Resting. Type: " + IntToString(GetLastRestEventType())
|
||||
DebugActionSpeakByInt(66, OBJECT_INVALID, GetLastRestEventType());
|
||||
|
||||
// Reset all spell triggers.
|
||||
// Set all triggers
|
||||
object oTrigger = GetAIObject(AI_SPELL_TRIGGER_CREATURE);
|
||||
if(GetIsObjectValid(oTrigger))
|
||||
{
|
||||
LoopResetTriggers(SPELLTRIGGER_NOT_GOT_FIRST_SPELL, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_DAMAGED_AT_PERCENT, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_IMMOBILE, oTrigger);
|
||||
LoopResetTriggers(SPELLTRIGGER_START_OF_COMBAT, oTrigger);
|
||||
}
|
||||
// Some sitting for a few seconds.
|
||||
ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0, 6.0);
|
||||
DelayCommand(9.0, ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF));
|
||||
|
||||
// Fire End-heartbeat-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_RESTED_EVENT, EVENT_RESTED_EVENT);
|
||||
}
|
||||
|
||||
// Resets all spell triggers used for sString
|
||||
void LoopResetTriggers(string sString, object oTrigger)
|
||||
{
|
||||
int nCnt, bBreak, bUsed;
|
||||
for(nCnt = 1; bBreak != TRUE; nCnt++)
|
||||
{
|
||||
// Check max for this setting
|
||||
bUsed = GetLocalInt(oTrigger, sString + USED);
|
||||
if(bUsed)
|
||||
{
|
||||
DeleteLocalInt(oTrigger, sString + USED);
|
||||
}
|
||||
else
|
||||
{
|
||||
bBreak = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,493 +0,0 @@
|
||||
/*/////////////////////// [On Spell Cast At] ///////////////////////////////////
|
||||
Filename: j_ai_onspellcast or nw_c2_defaultb
|
||||
///////////////////////// [On Spell Cast At] ///////////////////////////////////
|
||||
What does this do? Well...
|
||||
- Any AOE spell effects are set in a timer, so we can react to them right
|
||||
- Reacts to hostile casters, or allies in combat
|
||||
|
||||
And the normal attack :-)
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added special AOE checks.
|
||||
- Hide checks.
|
||||
1.4 - Added more silent shouts. Edited the formatting. Moved a few things around.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
This is fired when EventSpellCastAt(object oCaster, int nSpell, int bHarmful=TRUE)
|
||||
is signaled on the creature.
|
||||
|
||||
GetLastSpellCaster() = oCaster (Door, Placeable, Creature who cast it)
|
||||
GetLastSpell() = nSpell (The spell cast at us)
|
||||
GetLastSpellHarmful()= bHarmful (If it is harmful!)
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetLastSpellCaster, GetLastSpellHarmful GetLastSpell()
|
||||
///////////////////////// [On Spell Cast At] /////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
// Sets a local timer if the spell is an AOE one
|
||||
void SetAOESpell(int nSpellCast, object oCaster);
|
||||
// Gets the nearest AOE cast by oCaster, of sTag.
|
||||
object GetNearestAOECastBy(string sTag, object oCaster);
|
||||
// Gets the amount of protections we have - IE globes
|
||||
int GetOurSpellLevelImmunity();
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-spell cast at-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_SPELL_CAST_AT_PRE_EVENT, EVENT_SPELL_CAST_AT_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
object oCaster = GetLastSpellCaster();
|
||||
int bHarmful = GetLastSpellHarmful();
|
||||
int nSpellCast = GetLastSpell();
|
||||
object oAttackerOfCaster;
|
||||
|
||||
// If harmful, we set the spell to a timer, if an AOE one.
|
||||
if(bHarmful && GetIsObjectValid(oCaster))
|
||||
{
|
||||
// Might set AOE spell to cast.
|
||||
SetAOESpell(nSpellCast, oCaster);
|
||||
}
|
||||
// If not a creature, probably an AOE or trap.
|
||||
if(GetObjectType(oCaster) != OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// 67: "[Spell] Caster isn't a creature! May look for target [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(67, oCaster);
|
||||
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// Attack anyone else around
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// Determine Combat Round
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
// If a friend, or dead, or a DM, or invalid, or self, we ignore them.
|
||||
else if(!GetIgnoreNoFriend(oCaster) && oCaster != OBJECT_SELF)
|
||||
{
|
||||
// 1.3 changes here:
|
||||
// - We do NOT need to know if it is hostile or not, except if it is hostile
|
||||
// and they are not our faction! We do, however, use bHarmful for speakstrings.
|
||||
|
||||
// If harmful, we attack anyone! (and if is enemy)
|
||||
// 1.4: Faction equal check in GetIgnoreNoFriend()
|
||||
if(bHarmful || GetIsEnemy(oCaster))
|
||||
{
|
||||
// Spawn in condition hostile thingy
|
||||
if(GetSpawnInCondition(AI_FLAG_OTHER_CHANGE_FACTIONS_TO_HOSTILE_ON_ATTACK, AI_OTHER_MASTER))
|
||||
{
|
||||
if(!GetIsEnemy(oCaster))
|
||||
{
|
||||
AdjustReputation(oCaster, OBJECT_SELF, -100);
|
||||
}
|
||||
}
|
||||
|
||||
if(bHarmful)
|
||||
{
|
||||
// * Don't speak when dead. 1.4 change (an obvious one to make)
|
||||
if(CanSpeak())
|
||||
{
|
||||
// Hostile spell speaksting, if set.
|
||||
SpeakArrayString(AI_TALK_ON_HOSTILE_SPELL_CAST_AT);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn of hiding check
|
||||
TurnOffHiding(oCaster);
|
||||
|
||||
// We attack
|
||||
if(!CannotPerformCombatRound())
|
||||
{
|
||||
// 68: "[Spell:Enemy/Hostile] Not in combat. Attacking: [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(68, oCaster);
|
||||
DetermineCombatRound(oCaster);
|
||||
}
|
||||
|
||||
// Shout to allies to attack the enemy who attacked me, got via. Last Hostile Actor.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
}
|
||||
// Else, was neutral perhaps. Don't attack them anyway.
|
||||
else
|
||||
{
|
||||
// 69: "[Spell] (ally). Not in combat. May Attack/Move [Caster] " + GetName(oCaster)
|
||||
DebugActionSpeakByInt(69, oCaster);
|
||||
|
||||
// Set special action to investigate - as if this event was triggered
|
||||
// by I_WAS_ATTACKED.
|
||||
|
||||
// If we are already attacking, we do not move
|
||||
if(CannotPerformCombatRound())
|
||||
{
|
||||
// Shout to allies to attack, or be prepared.
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We react as if the caster, a neutral, called for help ala
|
||||
// I_WAS_ATTACKED (they might not have, might just be
|
||||
// preperation for something), but normally, this is a neutral
|
||||
// casting a spell. Do not respond to PC's.
|
||||
if(!GetIsPC(oCaster))
|
||||
{
|
||||
IWasAttackedResponse(oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If they are not a faction equal, and valid, we help them.
|
||||
else if(GetIsObjectValid(oCaster) && GetFactionEqual(oCaster))
|
||||
{
|
||||
IWasAttackedResponse(oCaster);
|
||||
}
|
||||
// Fire End-spell cast at-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_SPELL_CAST_AT_EVENT, EVENT_SPELL_CAST_AT_EVENT);
|
||||
}
|
||||
|
||||
// Sets a local timer if the spell is an AOE one
|
||||
void SetAOESpell(int nSpellCast, object oCaster)
|
||||
{
|
||||
// Check it is one we can check
|
||||
int bStop = TRUE;
|
||||
switch(nSpellCast)
|
||||
{
|
||||
case SPELL_ACID_FOG:
|
||||
case SPELL_MIND_FOG:
|
||||
case SPELL_STORM_OF_VENGEANCE:
|
||||
case SPELL_GREASE:
|
||||
case SPELL_CREEPING_DOOM:
|
||||
case SPELL_SILENCE:
|
||||
case SPELL_BLADE_BARRIER:
|
||||
case SPELL_CLOUDKILL:
|
||||
case SPELL_STINKING_CLOUD:
|
||||
case SPELL_WALL_OF_FIRE:
|
||||
case SPELL_INCENDIARY_CLOUD:
|
||||
case SPELL_ENTANGLE:
|
||||
case SPELL_EVARDS_BLACK_TENTACLES:
|
||||
case SPELL_CLOUD_OF_BEWILDERMENT:
|
||||
case SPELL_STONEHOLD:
|
||||
case SPELL_VINE_MINE:
|
||||
case SPELL_SPIKE_GROWTH:
|
||||
case SPELL_VINE_MINE_HAMPER_MOVEMENT:
|
||||
case SPELL_VINE_MINE_ENTANGLE:
|
||||
{
|
||||
bStop = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Check immune level
|
||||
int nImmuneLevel = GetOurSpellLevelImmunity();
|
||||
if(nImmuneLevel >= 9)
|
||||
{
|
||||
bStop = TRUE;
|
||||
}
|
||||
// Check
|
||||
if(bStop == TRUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// We do use intelligence here...
|
||||
int nAIInt = GetBoundriedAIInteger(AI_INTELLIGENCE);
|
||||
int bIgnoreSaves;
|
||||
int bIgnoreImmunities;
|
||||
object oAOE;
|
||||
|
||||
// If it is low, we ignore all things that we could ignore with it...
|
||||
if(nAIInt <= 3)
|
||||
{
|
||||
bIgnoreSaves = TRUE;
|
||||
bIgnoreImmunities = TRUE;
|
||||
}
|
||||
// Average ignores saves
|
||||
else if(nAIInt <= 7)
|
||||
{
|
||||
bIgnoreSaves = TRUE;
|
||||
bIgnoreImmunities = FALSE;
|
||||
}
|
||||
// Else, we do both.
|
||||
else
|
||||
{
|
||||
bIgnoreSaves = FALSE;
|
||||
bIgnoreImmunities = FALSE;
|
||||
}
|
||||
|
||||
int bSetAOE = FALSE;// TRUE means set to timer
|
||||
int nSaveDC = 11;
|
||||
|
||||
// Get the caster DC, the most out of WIS, INT or CHA...
|
||||
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE, oCaster);
|
||||
int nWis = GetAbilityModifier(ABILITY_WISDOM, oCaster);
|
||||
int nCha = GetAbilityModifier(ABILITY_CHARISMA, oCaster);
|
||||
|
||||
if(nInt > nWis && nInt > nCha)
|
||||
{
|
||||
nSaveDC += nInt;
|
||||
}
|
||||
else if(nWis > nCha)
|
||||
{
|
||||
nSaveDC += nWis;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSaveDC += nCha;
|
||||
}
|
||||
// Note:
|
||||
// - No reaction type/friendly checks. Signal Event is only fired if the
|
||||
// spell WILL pierce any PvP/Friendly/Area settings
|
||||
|
||||
// We check immunities here, please note...
|
||||
switch(nSpellCast)
|
||||
{
|
||||
// First: IS GetIsReactionTypeHostile ones.
|
||||
case SPELL_EVARDS_BLACK_TENTACLES:
|
||||
// Fortitude save, but if we are immune to the hits, its impossible to hurt us
|
||||
{
|
||||
// If save immune OR AC immune, we ignore this.
|
||||
if(25 >= GetAC(OBJECT_SELF) && nImmuneLevel < 4 &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 2) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Nearest string of tag
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_EVARDS_BLACK_TENTACLES, oCaster);
|
||||
}
|
||||
}
|
||||
case SPELL_SPIKE_GROWTH:
|
||||
case SPELL_VINE_MINE_HAMPER_MOVEMENT:
|
||||
// d4 damage. LOTS of speed loss.
|
||||
// Reflex save, or immunity, would stop the speed
|
||||
{
|
||||
if(nImmuneLevel < 3 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_MOVEMENT_SPEED_DECREASE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 5) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Both use ENTANGLE AOE's
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_ENTANGLE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_ENTANGLE:
|
||||
case SPELL_VINE_MINE_ENTANGLE:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_ENTANGLE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 4) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Both use ENTANGLE AOE's
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_ENTANGLE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_WEB:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_ENTANGLE) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 4) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Web AOE
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WEB, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Fort save
|
||||
case SPELL_STINKING_CLOUD:
|
||||
{
|
||||
if(nImmuneLevel < 3 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_POISON) || bIgnoreImmunities) &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_DAZED) || bIgnoreImmunities) &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 6) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Stinking cloud persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGSTINK, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Fort save
|
||||
case SPELL_CLOUD_OF_BEWILDERMENT:
|
||||
{
|
||||
if(nImmuneLevel < 2 &&
|
||||
((GetFortitudeSavingThrow(OBJECT_SELF) < nSaveDC + 7) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Bewilderment cloud persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGBEWILDERMENT, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: Mind save is the effect.
|
||||
case SPELL_STONEHOLD:
|
||||
{
|
||||
if(nImmuneLevel < 6 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_MIND_SPELLS) || bIgnoreImmunities) &&
|
||||
((GetWillSavingThrow(OBJECT_SELF) < nSaveDC + 7) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Stonehold persistant AOE.
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_STONEHOLD, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: EFFECT_TYPE_SAVING_THROW_DECREASE is the effect.
|
||||
case SPELL_MIND_FOG:
|
||||
{
|
||||
if(nImmuneLevel < 5 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_SAVING_THROW_DECREASE) || bIgnoreImmunities) &&
|
||||
((GetWillSavingThrow(OBJECT_SELF) < nSaveDC + 6) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Mind fog
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGMIND, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Special: Feats, knockdown
|
||||
case SPELL_GREASE:
|
||||
{
|
||||
if(nImmuneLevel < 1 &&
|
||||
(!GetIsImmune(OBJECT_SELF, IMMUNITY_TYPE_KNOCKDOWN) || bIgnoreImmunities) &&
|
||||
(!GetHasFeat(FEAT_WOODLAND_STRIDE, OBJECT_SELF) || bIgnoreImmunities) &&
|
||||
((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 2) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Grease
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_GREASE, oCaster);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// All other ReactionType ones. Some have different saves though!
|
||||
case SPELL_BLADE_BARRIER: // Reflex
|
||||
case SPELL_INCENDIARY_CLOUD:// reflex
|
||||
case SPELL_WALL_OF_FIRE:// Reflex
|
||||
{
|
||||
if(nImmuneLevel < 6 &&
|
||||
(((GetReflexSavingThrow(OBJECT_SELF) < nSaveDC + 6) &&
|
||||
!GetHasFeat(FEAT_IMPROVED_EVASION) &&
|
||||
!GetHasFeat(FEAT_EVASION)) || bIgnoreSaves))
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
if(nSpellCast == SPELL_BLADE_BARRIER)
|
||||
{
|
||||
// BB
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WALLBLADE, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_INCENDIARY_CLOUD)
|
||||
{
|
||||
// Fog of fire
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGFIRE, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_WALL_OF_FIRE)
|
||||
{
|
||||
// Wall of fire
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_WALLFIRE, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SPELL_ACID_FOG: // Fort: Half. No check, always damages.
|
||||
case SPELL_CLOUDKILL:// No save!
|
||||
case SPELL_CREEPING_DOOM: // No save!
|
||||
{
|
||||
if(nImmuneLevel < 6)
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
if(nSpellCast == SPELL_ACID_FOG)
|
||||
{
|
||||
// Acid fog
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGACID, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_CLOUDKILL)
|
||||
{
|
||||
// Cloud Kill
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_FOGKILL, oCaster);
|
||||
}
|
||||
else if(nSpellCast == SPELL_CREEPING_DOOM)
|
||||
{
|
||||
// Creeping doom
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_CREEPING_DOOM, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Storm - because the AI likes it, we stay in it if it is ours :-)
|
||||
case SPELL_STORM_OF_VENGEANCE: // Reflex partial. No check, always damages.
|
||||
{
|
||||
if(oCaster != OBJECT_SELF && nImmuneLevel < 9)
|
||||
{
|
||||
bSetAOE = TRUE;
|
||||
// Storm of vengance
|
||||
oAOE = GetNearestAOECastBy(AI_AOE_PER_STORM, oCaster);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bSetAOE)
|
||||
{
|
||||
if(!GetLocalTimer(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast)))
|
||||
{
|
||||
SetLocalTimer(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast), 18.0);
|
||||
// Set nearest AOE
|
||||
if(GetIsObjectValid(oAOE))
|
||||
{
|
||||
// Set nearest AOE of this spell to the local
|
||||
object oNearest = GetAIObject(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast));
|
||||
if(GetDistanceToObject(oAOE) < GetDistanceToObject(oNearest) ||
|
||||
!GetIsObjectValid(oNearest))
|
||||
{
|
||||
SetAIObject(AI_TIMER_AOE_SPELL_EVENT + IntToString(nSpellCast), oAOE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Gets the nearest AOE cast by oCaster, of sTag.
|
||||
object GetNearestAOECastBy(string sTag, object oCaster)
|
||||
{
|
||||
int nCnt = 1;
|
||||
object oAOE = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||||
object oReturn = OBJECT_INVALID;
|
||||
// Loop
|
||||
while(GetIsObjectValid(oAOE) && !GetIsObjectValid(oReturn))
|
||||
{
|
||||
// Check creator
|
||||
if(GetAreaOfEffectCreator(oAOE) == oCaster)
|
||||
{
|
||||
oReturn = oAOE;
|
||||
}
|
||||
nCnt++;
|
||||
oAOE = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||||
}
|
||||
return oReturn;
|
||||
}
|
||||
|
||||
// Gets the amount of protections we have - IE globes
|
||||
int GetOurSpellLevelImmunity()
|
||||
{
|
||||
int nNatural = GetLocalInt(OBJECT_SELF, AI_SPELL_IMMUNE_LEVEL);
|
||||
// Stop here, if natural is over 4
|
||||
if(nNatural > 4) return nNatural;
|
||||
|
||||
// Big globe affects 4 or lower spells
|
||||
if(GetHasSpellEffect(SPELL_GLOBE_OF_INVULNERABILITY, OBJECT_SELF) || nNatural >= 4)
|
||||
return 4;
|
||||
// Minor globe is 3 or under
|
||||
if(GetHasSpellEffect(SPELL_MINOR_GLOBE_OF_INVULNERABILITY, OBJECT_SELF) ||
|
||||
// Shadow con version
|
||||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MINOR_GLOBE, OBJECT_SELF) ||
|
||||
nNatural >= 3)
|
||||
return 3;
|
||||
// 2 and under is ethereal visage.
|
||||
if(GetHasSpellEffect(SPELL_ETHEREAL_VISAGE, OBJECT_SELF) || nNatural >= 2)
|
||||
return 2;
|
||||
// Ghostly Visarge affects 1 or 0 level spells, and any spell immunity.
|
||||
if(GetHasSpellEffect(SPELL_GHOSTLY_VISAGE, OBJECT_SELF) || nNatural >= 1 ||
|
||||
// Or shadow con version.
|
||||
GetHasSpellEffect(SPELL_GREATER_SHADOW_CONJURATION_MIRROR_IMAGE, OBJECT_SELF))
|
||||
return 1;
|
||||
// Return nNatural, which is 0-9
|
||||
return FALSE;
|
||||
}
|
@@ -1,326 +0,0 @@
|
||||
/*/////////////////////// [On User Defined] ////////////////////////////////////
|
||||
Filename: J_AI_OnUserDef or nw_c2_defaultd
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
1.4 Adds proper Pre-event functionality. Use this to make sure you keep the
|
||||
AI working, but making small additions using this event.
|
||||
|
||||
Can be deleted to save space if you want :-)
|
||||
|
||||
How to use user defined events (brief):
|
||||
|
||||
There are a set of optional Spawn In values you can set within the spawn file.
|
||||
If you set one of the Events to fire, it will activate this script. Then,
|
||||
under the correct choice (EG I choose the Pre-Heartbeat event, then I
|
||||
uncomment the line "SetSpawnInCondition(AI_FLAG_UDE_HEARTBEAT_PRE_EVENT, AI_UDE_MASTER);"
|
||||
and find, in this file, the section with EVENT_HEARTBEAT_PRE_EVENT above it).
|
||||
add in whatever to do.
|
||||
|
||||
With my Pre-heartbeat example, if I wanted it to check for a PC, then
|
||||
check for a combat dummy, and attack it, I'd add this between the brackets:
|
||||
|
||||
// Code:
|
||||
|
||||
// Not in combat, of course!
|
||||
if(!GetIsInCombat())
|
||||
{
|
||||
// Function in j_inc_npc_attack to get nearest PC
|
||||
object oPC = GetNearestPCCreature();
|
||||
// Why check for a PC? Well, it saves memory
|
||||
if(GetIsObjectValid(oPC) && GetDistanceToObject(oPC) <= 40.0)
|
||||
{
|
||||
object oDummy = GetNearestObjectByTag("DUMMY");
|
||||
if(GetIsObjectValid(oDummy))
|
||||
{
|
||||
ClearAllActions();
|
||||
ActionAttack(oDummy);
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_HEARTBEAT_PRE_EVENT);
|
||||
// Stop rest of script
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End code
|
||||
|
||||
Simple, no?
|
||||
|
||||
You can delete sections you don't need, and is recommended as long as you know
|
||||
how to use User Defined events.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.3 - Added in with some documentation
|
||||
1.4 - Changed Pre-events. Now, it uses Execute Script. Will need to set
|
||||
a special string on the creature to now what script to fire.
|
||||
- It means they work correctly, however!
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: Dependant on event. See seperate event scripts.
|
||||
///////////////////////// [On User Defined] //////////////////////////////////*/
|
||||
|
||||
// This contains a lot of useful things.
|
||||
// - Combat starting
|
||||
// - Constant values
|
||||
// - Get/Set spawn in values.
|
||||
#include "J_INC_OTHER_AI"
|
||||
// This contains some useful things to get NPC's to attack and so on.
|
||||
#include "J_INC_NPC_ATTACK"
|
||||
|
||||
/************************ [UDE Values] *****************************************
|
||||
These are uneeded, but here for reference. Use the constants in the file
|
||||
"j_inc_constants" like "EVENT_HEARTBEAT_PRE_EVENT" which is classed as 1021.
|
||||
* The normal death event might not fire before the creature has vanished.
|
||||
Use the Pre-event (but with no stopping the death event) if you want a special
|
||||
death event to happen.
|
||||
|
||||
Name Normal-End event - Pre-Event
|
||||
Heartbeat Event 1001 1021
|
||||
Percieve Event 1002 1022
|
||||
Combat Round Event 1003 1023
|
||||
Dialog Event 1004 1024
|
||||
Attack Event 1005 1025
|
||||
Damaged Event 1006 1026
|
||||
Death Event 1007 1027
|
||||
Disturbed Event 1008 1028
|
||||
Rested Event 1009 1029
|
||||
Spell Cast At Event 1011 1031
|
||||
Combat Action Event 1012 1032
|
||||
Damaged 1HP Event 1014 -
|
||||
Blocked Event 1015 1035
|
||||
************************* [UDE Values] ****************************************/
|
||||
|
||||
void main()
|
||||
{
|
||||
// Get the user defined number.
|
||||
// * NOTE: YOU MUST USE AI_GetUDENumber(), not GetUserDefinedEventNumber()!
|
||||
int nEvent = AI_GetUDENumber();
|
||||
|
||||
// Events.
|
||||
switch(nEvent)
|
||||
{
|
||||
// Event Heartbeat
|
||||
// Arguments: Basically, none. Nothing activates this script. Fires every 6 seconds.
|
||||
case EVENT_HEARTBEAT_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Heartbeat file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_HEARTBEAT_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_HEARTBEAT_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Heartbeat file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Percieve
|
||||
// Arguments: GetLastPerceived, GetLastPerceptionSeen, GetLastPerceptionHeard,
|
||||
// GetLastPerceptionVanished, GetLastPerceptionInaudible.
|
||||
case EVENT_PERCIEVE_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Percieve file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_PERCIEVE_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_PERCIEVE_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Percieve file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Combat Round End
|
||||
// Arguments: GetAttackTarget, GetLastHostileActor, GetAttemptedAttackTarget,
|
||||
// GetAttemptedSpellTarget (Or these are useful at least!)
|
||||
case EVENT_END_COMBAT_ROUND_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the On Combat Round End file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_END_COMBAT_ROUND_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_END_COMBAT_ROUND_EVENT:
|
||||
{
|
||||
// This fires after the rest of the On Combat Round End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Dialogue
|
||||
// Arguments: GetListenPatternNumber, GetLastSpeaker, TestStringAgainstPattern,
|
||||
// GetMatchedSubstring (I think),
|
||||
case EVENT_ON_DIALOGUE_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the dialog file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ON_DIALOGUE_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ON_DIALOGUE_EVENT:
|
||||
{
|
||||
// This fires after the rest of the dialog file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Attacked
|
||||
// Arguments: GetLastAttacker, GetLastWeaponUsed, GetLastAttackMode,
|
||||
// GetLastAttackType
|
||||
case EVENT_ATTACK_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Attacked file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ATTACK_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ATTACK_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Attacked file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Damaged
|
||||
// Arguments: GetTotalDamageDealt, GetLastDamager, GetCurrentHitPoints
|
||||
// (and max), GetDamageDealtByType
|
||||
case EVENT_DAMAGED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the damaged file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DAMAGED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DAMAGED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the damaged file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Death
|
||||
// Arguments: GetLastKiller
|
||||
case EVENT_DEATH_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the death file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DEATH_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DEATH_EVENT:
|
||||
{
|
||||
// This fires after the rest of the death file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Distrubed
|
||||
// Arguments: GetInventoryDisturbItem, GetLastDisturbed,
|
||||
// GetInventoryDisturbType (should always be stolen :-( ).
|
||||
case EVENT_DISTURBED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the disturbed file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_DISTURBED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_DISTURBED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the disturbed file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Rested
|
||||
// Arguments: None
|
||||
// Note: Not sure if this fires at the end of rest event, but the actual
|
||||
// duration of the rest is 0, so you never "see" it.
|
||||
case EVENT_RESTED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the rested file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_RESTED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_RESTED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the rested file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Spell cast at
|
||||
// Arguments: GetLastSpellCaster, GetLastSpellHarmful GetLastSpell()
|
||||
case EVENT_SPELL_CAST_AT_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Spell Cast At file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_SPELL_CAST_AT_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_SPELL_CAST_AT_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Spell Cast At End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Blocked
|
||||
// Arguements: GetBlockingDoor, GetIsDoorActionPossible, GetLocked,
|
||||
// GetLockKeyRequired, GetLockKeyTag, GetLockUnlockDC, GetPlotFlag.
|
||||
case EVENT_ON_BLOCKED_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the on blocked file does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_ON_BLOCKED_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_ON_BLOCKED_EVENT:
|
||||
{
|
||||
// This fires after the rest of the on blocked file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Combat Action
|
||||
// Arguments: GetAttackTarget(), and lots of others.
|
||||
// Note: Fires when DetermineCombatRound runs to perform an action.
|
||||
case EVENT_COMBAT_ACTION_PRE_EVENT:
|
||||
{
|
||||
// This fires before the rest of the Determine Combat Round call does
|
||||
|
||||
// Exit (Stop the rest of the script)
|
||||
SetToExitFromUDE(EVENT_COMBAT_ACTION_PRE_EVENT);
|
||||
}
|
||||
break;
|
||||
case EVENT_COMBAT_ACTION_EVENT:
|
||||
{
|
||||
// This fires after the rest of the Determine Combat Round call does
|
||||
// Calling ClearAllActions should stop any actions added in the call.
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// Event Damaged at 1 HP.
|
||||
// Arguments: None really.
|
||||
// Note: Fires OnDamaged, when we have exactly 1HP. Use for Immortal Creatures.
|
||||
case EVENT_DAMAGED_AT_1_HP:
|
||||
{
|
||||
// This fires after the rest of the On Combat Round End file does
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// End all in-built events. Add more in here, if you wish.
|
||||
}
|
||||
}
|
@@ -1,332 +0,0 @@
|
||||
/*/////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Filename: J_AI_OnBlocked or nw_c2_defaulte
|
||||
///////////////////////// [On Blocked] /////////////////////////////////////////
|
||||
Added in user defined constant - won't open any doors.
|
||||
0 = Default (even if not set) opens as appropriate
|
||||
1 = Always bashes the door.
|
||||
2 = Never open any doors
|
||||
3 = Never opens plot doors
|
||||
|
||||
They will: (int is intellgience needed)
|
||||
1. Open if not trapped (7 int)
|
||||
2. Unlock if possible, and rank is high enough, and it needs no key and is not trapped (7 int)
|
||||
3. Untrap the door, if possible, if trapped (7 int)
|
||||
4. Else, if has high enough stats, try Knock. (10 int)
|
||||
6. Else Equip appropriate weapons and bash (5 int)
|
||||
|
||||
Note: This also fires for blocking via. creatures. It is optimised, and
|
||||
works by re-targeting and doing a few small things to do with blocking.
|
||||
///////////////////////// [History] ////////////////////////////////////////////
|
||||
1.0 - Opens with Knock. Unlocks door. Ignores trapped doors.
|
||||
1.3 - Debug messages.
|
||||
- New events, even if the change of using them is small!
|
||||
- No ClearAllactions so any previous movings will carry on once the door is gone.
|
||||
- Removed debug messages
|
||||
- Added Creature reaction code
|
||||
1.4 - Need to add a "hands" check (done on spawn, to set a setting to not
|
||||
open doors at all, IE: We do NOT have hands, do not open doors), so
|
||||
its a little more realistic "out of the box"
|
||||
- Fixed an instance of GetObjectSeen being repeated.
|
||||
- Fixed the variable AI_DOOR_INTELLIGENCE not being got via GetAIInteger().
|
||||
- Removed unneeded else statement.
|
||||
///////////////////////// [Workings] ///////////////////////////////////////////
|
||||
Uses simple code to deal with a door in the best way possible.
|
||||
|
||||
Uses DoDoorAction, which is added to the top of an action queue and doesn't,
|
||||
therefore, delete any ActionAttack's and so on below it. (Or I hope it
|
||||
is like this)
|
||||
|
||||
Creatures are reacted by with ClearAllActions usually.
|
||||
///////////////////////// [Arguments] //////////////////////////////////////////
|
||||
Arguments: GetBlockingDoor, GetIsDoorActionPossible, GetLocked, GetLockKeyRequired
|
||||
GetLockKeyTag, GetLockUnlockDC, GetPlotFlag, DoDoorAction
|
||||
///////////////////////// [On Blocked] ///////////////////////////////////////*/
|
||||
|
||||
#include "J_INC_OTHER_AI"
|
||||
|
||||
// Fires the end-blocked event.
|
||||
void FireBlockedEvent();
|
||||
// Range attack oTarget.
|
||||
int RangedAttack(object oTarget = OBJECT_INVALID);
|
||||
|
||||
void main()
|
||||
{
|
||||
// Pre-on blocked-event. Returns TRUE if we interrupt this script call.
|
||||
if(FirePreUserEvent(AI_FLAG_UDE_ON_BLOCKED_PRE_EVENT, EVENT_ON_BLOCKED_PRE_EVENT)) return;
|
||||
|
||||
// AI status check. Is the AI on?
|
||||
if(GetAIOff()) return;
|
||||
|
||||
// This CAN return a blocking creature.
|
||||
object oBlocker = GetBlockingDoor();
|
||||
int nBlockerType = GetObjectType(oBlocker);
|
||||
|
||||
if(!GetIsObjectValid(oBlocker)) return;
|
||||
|
||||
// Anyone blocked by an enemy will re-target them (and attack them), blocked
|
||||
// by someone they cannot get they will cast seeing spells and react, and if
|
||||
// blocked by a friend, they may run back and use a ranged weapon if they
|
||||
// have one.
|
||||
if(nBlockerType == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
// Are we doing something that should not be overriden? (even fleeing,
|
||||
// if stuck, we can't do anything else then move again on heartbeat!)
|
||||
if(GetIsPerformingSpecialAction()) return;
|
||||
|
||||
// Blocked timer, we normally do an action. A small timer stops a lot
|
||||
// of lag.
|
||||
if(GetLocalTimer(AI_TIMER_BLOCKED)) return;
|
||||
|
||||
// Set the timer for 1 second
|
||||
SetLocalTimer(AI_TIMER_BLOCKED, 1.0);
|
||||
|
||||
// Is it an enemy?
|
||||
if(GetIsEnemy(oBlocker))
|
||||
{
|
||||
// Check if seen or heard
|
||||
if(GetObjectSeen(oBlocker) || GetObjectHeard(oBlocker))
|
||||
{
|
||||
// Enemy :-) We can re-target (as know of thier presence), using
|
||||
// them as a target.
|
||||
// - This overrides even casting a spell - basically, as we should
|
||||
// be moving, this will re-cast it at someone or something in range
|
||||
SetAIObject(AI_ATTACK_SPECIFIC_OBJECT, oBlocker);
|
||||
|
||||
// Check if we can do combat - if we cannot, we can re-do combat
|
||||
// next time
|
||||
if(!GetIsBusyWithAction())
|
||||
{
|
||||
// Attacks if we are not attacking
|
||||
ClearAllActions();
|
||||
DetermineCombatRound(oBlocker);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invisible? Not there? Some odd error? We set that we know of
|
||||
// someone invisible, and will attack if not in combat.
|
||||
if(GetHasEffect(EFFECT_TYPE_INVISIBILITY, oBlocker) ||
|
||||
GetStealthMode(oBlocker) == STEALTH_MODE_ACTIVATED)
|
||||
{
|
||||
SetAIObject(AI_LAST_TO_GO_INVISIBLE, oBlocker);
|
||||
}
|
||||
// Shout to allies
|
||||
AISpeakString(AI_SHOUT_CALL_TO_ARMS);
|
||||
|
||||
// Check if we can do combat
|
||||
if(!GetIsBusyWithAction())
|
||||
{
|
||||
// Attacks if we are not attacking
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else is non-enemy, a friend or neutral
|
||||
else
|
||||
{
|
||||
// As we are blocked by them, we re-do combat - we have a choice of
|
||||
// either using a Bow to attack our target (if that was what
|
||||
// we were doing) and move back a little, or re-initiate combat
|
||||
|
||||
// Were we attacking in combat?
|
||||
object oPrevious = GetAttackTarget();
|
||||
|
||||
// Check action
|
||||
if(GetCurrentAction() == ACTION_ATTACKOBJECT)
|
||||
{
|
||||
// This gets set to FALSE if we can cutthrough attack,
|
||||
// or whatever.
|
||||
|
||||
int bPreviousAttackFailed = FALSE;
|
||||
// Check if we can see our previous target
|
||||
if(GetObjectSeen(oPrevious) ||
|
||||
(GetObjectHeard(oPrevious) && LineOfSightObject(OBJECT_SELF, oPrevious)))
|
||||
{
|
||||
// We can! see if we can re-attack with ranged weapon, else
|
||||
// doesn't matter we can see them
|
||||
bPreviousAttackFailed = RangedAttack(oPrevious);
|
||||
}
|
||||
|
||||
// If we havn't added an action yet...
|
||||
if(bPreviousAttackFailed == FALSE)
|
||||
{
|
||||
// We have not stopped the script - so determine combat
|
||||
// round against nearest seen or heard enemy!
|
||||
if(!RangedAttack())
|
||||
{
|
||||
// Else normal round to try and get a new target
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
}
|
||||
}
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else // if(nAction == ACTION_CASTSPELL and others)
|
||||
{
|
||||
// Reinitate combat, but don't attack oPrevious
|
||||
ClearAllActions();
|
||||
DetermineCombatRound();
|
||||
|
||||
// Action attack, normally means melee attack. If we can, we
|
||||
// attack our previous target if seen, ELSE we will re-initate
|
||||
// combat.
|
||||
AISpeakString(AI_SHOUT_I_WAS_ATTACKED);
|
||||
|
||||
// Fire the On blocked event as normal
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Placeable - Currently not returned, however, added just in case!
|
||||
else if(nBlockerType == OBJECT_TYPE_PLACEABLE)
|
||||
{
|
||||
// Check for plot, and therefore attack it to bring it down.
|
||||
// - Remember, ActionAttack will re-initiate when combat round fires
|
||||
// again in 3 or 6 seconds (or less, if we just were moving)
|
||||
if(!GetPlotFlag(oBlocker) &&
|
||||
GetIsPlaceableObjectActionPossible(oBlocker, PLACEABLE_ACTION_BASH))
|
||||
{
|
||||
// Do placeable action
|
||||
DoPlaceableObjectAction(oBlocker, PLACEABLE_ACTION_BASH);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Door behaviour
|
||||
else if(nBlockerType == OBJECT_TYPE_DOOR)
|
||||
{
|
||||
int nDoorIntelligence = GetAIInteger(AI_DOOR_INTELLIGENCE);
|
||||
int nInt = GetAbilityScore(OBJECT_SELF, ABILITY_INTELLIGENCE);
|
||||
if(nDoorIntelligence == 1)// 1 = Always bashes the doors, plot, locked or anything.
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
// We re-initiate combat.
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(nDoorIntelligence == 2)// 2 = Never open anything, bashing or not.
|
||||
{
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
else if(nDoorIntelligence == 3)// 3 = Never tries anything against plot doors.
|
||||
{
|
||||
if(GetPlotFlag(oBlocker))
|
||||
{
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(nInt >= 5)
|
||||
{
|
||||
// Need some intelligence :-)
|
||||
if(nInt >= 7)
|
||||
{
|
||||
// Right, first, we may...shock...open it!!!
|
||||
// Checks Key, lock, trap and if the action is possible.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_OPEN) &&
|
||||
!GetLocked(oBlocker) &&
|
||||
!GetIsTrapped(oBlocker) &&
|
||||
(!GetLockKeyRequired(oBlocker) ||
|
||||
(GetLockKeyRequired(oBlocker) && GetItemPossessor(GetObjectByTag(GetLockKeyTag(oBlocker))) == OBJECT_SELF)))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_OPEN);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
// Unlock it with the skill, if it is not trapped and we can :-P
|
||||
// We take 20 off the door DC, thats our minimum roll, after all.
|
||||
if(GetLocked(oBlocker) &&
|
||||
!GetSpawnInCondition(AI_FLAG_OTHER_COMBAT_NO_OPENING_LOCKED_DOORS, AI_OTHER_COMBAT_MASTER) &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSkill(SKILL_OPEN_LOCK) &&
|
||||
GetIsDoorActionPossible(oBlocker, DOOR_ACTION_UNLOCK) && !GetIsTrapped(oBlocker) &&
|
||||
(GetSkillRank(SKILL_OPEN_LOCK) >= (GetLockLockDC(oBlocker) - 20)))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_UNLOCK);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
// Specilist thing - knock
|
||||
if(nInt >= 10)
|
||||
{
|
||||
if((GetIsDoorActionPossible(oBlocker, DOOR_ACTION_KNOCK)) &&
|
||||
GetLockUnlockDC(oBlocker) <= 25 &&
|
||||
!GetLockKeyRequired(oBlocker) && GetHasSpell(SPELL_KNOCK))
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_KNOCK);
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If Our Int is over 5, we will bash after everything else.
|
||||
if(GetIsDoorActionPossible(oBlocker, DOOR_ACTION_BASH) && !GetPlotFlag(oBlocker))
|
||||
{
|
||||
if(GetAttackTarget() != oBlocker)
|
||||
{
|
||||
DoDoorAction(oBlocker, DOOR_ACTION_BASH);
|
||||
}
|
||||
FireBlockedEvent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fire Blocked event
|
||||
FireBlockedEvent();
|
||||
}
|
||||
// Fires the end-blocked event.
|
||||
void FireBlockedEvent()
|
||||
{
|
||||
// Fire End-blocked-UDE
|
||||
FireUserEvent(AI_FLAG_UDE_ON_BLOCKED_EVENT, EVENT_ON_BLOCKED_EVENT);
|
||||
}
|
||||
// Range attack oTarget.
|
||||
int RangedAttack(object oTarget)
|
||||
{
|
||||
// If we are primarily melee, don't use this
|
||||
if(!GetSpawnInCondition(AI_FLAG_COMBAT_BETTER_AT_HAND_TO_HAND, AI_COMBAT_MASTER)) return FALSE;
|
||||
|
||||
object oRangedTarget = oTarget;
|
||||
if(!GetIsObjectValid(oRangedTarget))
|
||||
{
|
||||
oRangedTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oTarget))
|
||||
{
|
||||
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
// heard must be in LOS to attack, as we are probably stuck
|
||||
if(!GetIsObjectValid(oTarget) && LineOfSightObject(OBJECT_SELF, oRangedTarget))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Ranged weapon attack against oTarget
|
||||
// doesn't matter we can see them
|
||||
object oRanged = GetAIObject(AI_WEAPON_RANGED);
|
||||
int nAmmo = GetAIInteger(AI_WEAPON_RANGED_AMMOSLOT);
|
||||
|
||||
// Check ammo and validness
|
||||
if(GetIsObjectValid(oRanged) && (nAmmo == INVENTORY_SLOT_RIGHTHAND ||
|
||||
GetIsObjectValid(GetItemInSlot(nAmmo))))
|
||||
{
|
||||
// Attack with it
|
||||
ClearAllActions();
|
||||
ActionEquipItem(oRanged, INVENTORY_SLOT_RIGHTHAND);
|
||||
ActionAttack(oRangedTarget);
|
||||
// Stop
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
// Dimension Doors spawn in
|
||||
// This is the DimDoors varient. It requires "nw_c2_dimdoor" in the UDE
|
||||
|
||||
// Flags combat round event, and then fires the default spawn in script.
|
||||
|
||||
#include "J_INC_CONSTANTS"
|
||||
|
||||
void main()
|
||||
{
|
||||
// Spawn in condition
|
||||
SetSpawnInCondition(AI_FLAG_UDE_END_COMBAT_ROUND_EVENT, AI_UDE_MASTER);
|
||||
|
||||
// Execute the default On Spawn file.
|
||||
ExecuteScript("nw_c2_default9", OBJECT_SELF);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user