Added PnP Dire Rat.
Added PnP Dire Rat.
This commit is contained in:
277
nwn_dark_sun/j_inc_heartbeat.nss
Normal file
277
nwn_dark_sun/j_inc_heartbeat.nss
Normal file
@@ -0,0 +1,277 @@
|
||||
/************************ [Heartbeat Include] **********************************
|
||||
Filename: J_Inc_Heartbeat
|
||||
************************* [Heartbeat Include] **********************************
|
||||
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
|
||||
************************* [Workings] *******************************************
|
||||
This is included in nw_c2_default1 and j_ai_onheartbeat.
|
||||
|
||||
Contains things like in j_inc_other_ai
|
||||
************************* [Arguments] ******************************************
|
||||
Arguments: N/A
|
||||
************************* [Heartbeat Include] *********************************/
|
||||
|
||||
#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:
|
||||
// * Dead
|
||||
// * Uncommandable
|
||||
// * 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();
|
||||
|
||||
// Attempt to cast iSpell. TRUE if true.
|
||||
int FleeingSpellCast(int iSpell);
|
||||
|
||||
int JumpOutOfHeartBeat()
|
||||
{
|
||||
// What to return
|
||||
int iReturn = FALSE;
|
||||
// Checks:
|
||||
// * Dead + Uncommandable are in GetAIOff
|
||||
// * 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 iEffectType;
|
||||
while(GetIsEffectValid(eCheck) && iReturn == FALSE)
|
||||
{
|
||||
iEffectType = GetEffectType(eCheck);
|
||||
// Sleep is special
|
||||
if(iEffectType == EFFECT_TYPE_SLEEP)
|
||||
{
|
||||
iReturn = i2;// This immediantly breaks.
|
||||
}
|
||||
// ALL these stop heartbeat.
|
||||
else if(iEffectType == EFFECT_TYPE_PARALYZE || iEffectType == EFFECT_TYPE_STUNNED ||
|
||||
iEffectType == EFFECT_TYPE_FRIGHTENED || /* Removed sleep above */
|
||||
iEffectType == EFFECT_TYPE_TURNED || iEffectType == EFFECT_TYPE_PETRIFY ||
|
||||
iEffectType == EFFECT_TYPE_DAZED || iEffectType == EFFECT_TYPE_TIMESTOP ||
|
||||
iEffectType == EFFECT_TYPE_DISAPPEARAPPEAR || iEffectType == EFFECT_TYPE_CHARMED ||
|
||||
iEffectType == EFFECT_TYPE_DOMINATED || iEffectType == EFFECT_TYPE_CONFUSED)
|
||||
{
|
||||
iReturn = i1;// 1 = No Zzz. We continue to check for Zzz as well.
|
||||
}
|
||||
eCheck = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
// Do we fire the heartbeat event?
|
||||
if(iReturn != FALSE)
|
||||
{
|
||||
// If it is sleep... Zzzzz sometimes.
|
||||
if(iReturn == i2 && d6() == i1)
|
||||
{
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT,
|
||||
EffectVisualEffect(VFX_IMP_SLEEP),
|
||||
OBJECT_SELF);
|
||||
}
|
||||
FireUserEvent(
|
||||
AI_FLAG_UDE_HEARTBEAT_EVENT,
|
||||
EVENT_HEARTBEAT_EVENT);// Fire event 1001
|
||||
}
|
||||
return iReturn;
|
||||
}
|
||||
|
||||
// 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 iAction = GetCurrentSetAction();
|
||||
object oTarget = GetAttackTarget();
|
||||
object oRunTarget;
|
||||
switch(iAction)
|
||||
{
|
||||
// - 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(HELP_MY_FRIEND);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else run to them
|
||||
if(GetObjectHeard(oRunTarget))
|
||||
{
|
||||
AISpeakString(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, f3);
|
||||
}
|
||||
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
|
||||
DeleteAIInteger(AI_HEARTBEAT_FLEE_SPELLS);
|
||||
// Speak to allies to come :-)
|
||||
AISpeakString(HELP_MY_FRIEND);
|
||||
// Return FALSE.
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else flee!
|
||||
if(GetObjectHeard(oRunTarget))
|
||||
{
|
||||
AISpeakString(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, and we will run away
|
||||
// from the nearest enemy if heard.
|
||||
if(GetAIInteger(AI_INTELLIGENCE) <= i3)
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, i1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, i1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
||||
if(!GetIsObjectValid(oRunTarget))
|
||||
{
|
||||
oRunTarget = GetLastHostileActor();
|
||||
if(!GetIsObjectValid(oRunTarget) || GetIsDead(oRunTarget))
|
||||
{
|
||||
ResetCurrentAction();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Run from enemy
|
||||
ClearAllActions();
|
||||
ActionMoveAwayFromObject(oTarget, TRUE, f50);
|
||||
return TRUE;
|
||||
}
|
||||
ResetCurrentAction();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
// 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(FleeingSpellCast(SPELL_IMPROVED_INVISIBILITY)) return;
|
||||
if(FleeingSpellCast(SPELL_INVISIBILITY)) return;
|
||||
|
||||
// Haste
|
||||
if(FleeingSpellCast(SPELL_MASS_HASTE)) return;
|
||||
if(FleeingSpellCast(SPELL_HASTE)) return;
|
||||
if(FleeingSpellCast(SPELL_EXPEDITIOUS_RETREAT)) return;
|
||||
}
|
||||
|
||||
// Attempt to cast iSpell. TRUE if true.
|
||||
int FleeingSpellCast(int iSpell)
|
||||
{
|
||||
if(GetHasSpell(iSpell))
|
||||
{
|
||||
ActionCastSpellAtObject(iSpell, OBJECT_SELF);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
Reference in New Issue
Block a user