583 lines
20 KiB
Plaintext
583 lines
20 KiB
Plaintext
/************************ [Include - Basic AI] *********************************
|
|
Filename: J_INC_BASIC
|
|
************************* [Include - Basic AI] *********************************
|
|
A few functions - mostly for animations and AI files.
|
|
|
|
This is included in:
|
|
- All Basic AI files
|
|
- Any custom AI files in the packages you import.
|
|
|
|
- Includes a few fighting things that help in combat (like Healing functions)
|
|
************************* [Workings] *******************************************
|
|
A few settings for animations, as well as some AI combat functions to help
|
|
make custom combat easier.
|
|
************************* [Include - Basic AI] ********************************/
|
|
|
|
// Special: Bioware SoU Waypoints/Animations constants
|
|
// - Here so I know where they are :-P
|
|
const string sAnimCondVarname = "NW_ANIM_CONDITION";
|
|
// This is the name of the local variable that holds the spawn-in conditions
|
|
string sSpawnCondVarname = "NW_GENERIC_MASTER";
|
|
|
|
// AI for waypoints
|
|
const string FILE_WALK_WAYPOINTS = "j_ai_walkwaypoin";
|
|
const string WAYPOINT_RUN = "WAYPOINT_RUN";
|
|
const string WAYPOINT_PAUSE = "WAYPOINT_PAUSE";
|
|
|
|
// Bioware constants.
|
|
const int NW_FLAG_STEALTH = 0x00000004;
|
|
const int NW_FLAG_SEARCH = 0x00000008;
|
|
const int NW_FLAG_AMBIENT_ANIMATIONS = 0x00080000;
|
|
const int NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 0x00200000;
|
|
const int NW_FLAG_DAY_NIGHT_POSTING = 0x00400000;
|
|
const int NW_FLAG_AMBIENT_ANIMATIONS_AVIAN = 0x00800000;
|
|
|
|
|
|
// 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 the specified spawn-in condition on the caller as directed.
|
|
// * Only used for animations
|
|
void SetSpawnInCondition(int nCondition, int bValid = TRUE);
|
|
|
|
// Base for moving round thier waypoints
|
|
// - Uses ExectuteScript to run the waypoint walking.
|
|
void SpawnWalkWayPoints(int nRun = FALSE, float fPause = 1.0);
|
|
|
|
// Sets the custom AI file to sString to use.
|
|
// - "AI_TEMP_SET_TARGET" is set to anything passed to this script.
|
|
void SetAIFileName(string sString);
|
|
|
|
// Gets the custom AI file set to us.
|
|
string GetAIFileName();
|
|
|
|
// Determines a combat round.
|
|
void DetermineCombatRound(object oTarget = OBJECT_INVALID);
|
|
|
|
// Returns any pre-set target object
|
|
object Combat_GetAITargetObject();
|
|
// Sets the pre-set target object to attack
|
|
void SetAITargetObject(object oTarget);
|
|
|
|
// Gets the nearest seen or heard enemy.
|
|
// * bSeenOnly - If set to TRUE, it will only return a valid seen enemy (if any!)
|
|
object Combat_GetNearestSeenOrHeardEnemy(int bSeenOnly = FALSE);
|
|
// Gets if the object is valid, and we can see, or hear it.
|
|
// * bSeenOnly - If set to TRUE, it must be seen.
|
|
// TRUE if oTarget is valid.
|
|
int Combat_GetTargetValid(object oTarget, int bSeenOnly = FALSE);
|
|
|
|
// This will call a random voicechat to be called, if iPercent is met.
|
|
void Combat_Taunt(int iPercent = 10);
|
|
|
|
// This will heal oTarget with the best spell possible.
|
|
// - Like the Bioware function.
|
|
// - Will force healing if bForce is TRUE, ELSE, it will only heal at 50% HP.
|
|
// - TRUE if it heals oTarget
|
|
int Combat_HealTarget(object oTarget, int bForce = FALSE);
|
|
// This will loop all seen allies. If any of them need healing, it will heal
|
|
// them and return TRUE.
|
|
// - Uses Combat_HealTarget to check if they need healing.
|
|
int Combat_HealAllies();
|
|
|
|
// Only for use in "Combat_TurnUndead", it checks if there are any non-turned
|
|
// undead within 10M, of iRace.
|
|
int Combat_TurningAnyOfRaceValid(int iRace);
|
|
|
|
// This will check if we can turn undead, and check if there are anythings we can
|
|
// turn, and turn if so. Uses mainly Bioware stuff.
|
|
int Combat_TurnUndead();
|
|
|
|
// This attempt to use the best potions the creature has.
|
|
// * Will return FALSE if they use none, or they already have the effects
|
|
// * Uses any Potection First (EG: stoneskin), then Benificial (EG: Bulls strength)
|
|
// then Enhancement (EG: Invisibility)
|
|
int Combat_UseAnyPotions();
|
|
|
|
// Attack oTarget with a melee weapon, and melee feats if we can hit them.
|
|
// - VERY basic!
|
|
void Combat_AttackMelee(object oTarget);
|
|
// Attack oTarget with a ranged weapon (if we have any), and ranged feats if we can hit them.
|
|
// - VERY basic!
|
|
void Combat_AttackRanged(object oTarget);
|
|
|
|
// This will check if the caller has nSpell, and casts it at oObject if so.
|
|
// - Will not cast if oTarget has the effect of nSpell.
|
|
// - Returns TRUE if they cast nSpell.
|
|
int Combat_CastAtObject(int nSpell, object oTarget);
|
|
// This will check if the caller has nSpell, and casts it at oObject's location if so.
|
|
// - Will not cast if oTarget has the effect of nSpell.
|
|
// - Returns TRUE if they cast nSpell.
|
|
int Combat_CastAtLocation(int nSpell, object oTarget);
|
|
// Checks if tUse is TRUE, and uses it against oTarget if not got the effects.
|
|
int Combat_TalentAtObject(talent tUse, object oTarget);
|
|
|
|
// Cheat-Casts nSpell, if under iPercent.
|
|
// * Doesn't cast if iPercent fails, or oTarget has nSpell's effects.
|
|
// Use this to make sure a caster doesn't run out of spells.
|
|
int Combat_CheatRandomSpellAtObject(int nSpell, object oTarget, int iPercent);
|
|
|
|
// This will loop oTarget's effects, and return TRUE if any are equal to
|
|
// iEffect, which is a constant EFFECT_TYPE_*
|
|
int Combat_GetHasEffect(int iEffect, object oTarget = OBJECT_SELF);
|
|
|
|
// This will walk the waypoints of the creature (re-activate them)
|
|
// Use this if the creature is not in combat/not attacking/no target to attack/
|
|
void Combat_WalkWaypoints();
|
|
|
|
// Functions start.
|
|
|
|
// Sets the specified spawn-in condition on the caller as directed.
|
|
void SetSpawnInCondition(int nCondition, int bValid = TRUE)
|
|
{
|
|
int nSpawnInConditions = GetLocalInt(OBJECT_SELF, sSpawnCondVarname);
|
|
if(bValid == TRUE)
|
|
{
|
|
// Add the given spawn-in condition
|
|
nSpawnInConditions = nSpawnInConditions | nCondition;
|
|
SetLocalInt(OBJECT_SELF, sSpawnCondVarname, nSpawnInConditions);
|
|
}
|
|
else if (bValid == FALSE)
|
|
{
|
|
// Remove the given spawn-in condition
|
|
nSpawnInConditions = nSpawnInConditions & ~nCondition;
|
|
SetLocalInt(OBJECT_SELF, sSpawnCondVarname, nSpawnInConditions);
|
|
}
|
|
}
|
|
|
|
// Mark that the given creature has the given condition set
|
|
// * Bioware SoU animations thing.
|
|
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);
|
|
}
|
|
}
|
|
|
|
// Base for moving round thier waypoints
|
|
// - Uses ExectuteScript to run the waypoint walking.
|
|
void SpawnWalkWayPoints(int nRun = FALSE, float fPause = 1.0)
|
|
{
|
|
SetLocalInt(OBJECT_SELF, WAYPOINT_RUN, nRun);
|
|
SetLocalFloat(OBJECT_SELF, WAYPOINT_PAUSE, fPause);
|
|
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
|
}
|
|
|
|
// Sets the custom AI file to sString to use.
|
|
// - "AI_TEMP_TARGET_OBJECT" is set to anything passed to this script.
|
|
void SetAIFileName(string sString)
|
|
{
|
|
SetLocalString(OBJECT_SELF, "AI_FILENAME", sString);
|
|
}
|
|
|
|
// Gets the custom AI file set to us.
|
|
string GetAIFileName()
|
|
{
|
|
return GetLocalString(OBJECT_SELF, "AI_FILENAME");
|
|
}
|
|
|
|
// Determines a combat round.
|
|
void DetermineCombatRound(object oTarget = OBJECT_INVALID)
|
|
{
|
|
// Set local object
|
|
SetAITargetObject(oTarget);
|
|
// Execute the AI file set.
|
|
ExecuteScript(GetAIFileName(), OBJECT_SELF);
|
|
}
|
|
|
|
// Returns any pre-set target object
|
|
object Combat_GetAITargetObject()
|
|
{
|
|
return GetLocalObject(OBJECT_SELF, "AI_TEMP_SET_TARGET");
|
|
}
|
|
|
|
// Sets the pre-set target object to attack
|
|
void SetAITargetObject(object oTarget)
|
|
{
|
|
SetLocalObject(OBJECT_SELF, "AI_TEMP_SET_TARGET", oTarget);
|
|
}
|
|
|
|
// Gets the nearest seen or heard enemy.
|
|
object Combat_GetNearestSeenOrHeardEnemy(int bSeenOnly = FALSE)
|
|
{
|
|
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
|
if(!GetIsObjectValid(oTarget) && bSeenOnly == FALSE)
|
|
{
|
|
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_HEARD, CREATURE_TYPE_IS_ALIVE, TRUE);
|
|
if(!GetIsObjectValid(oTarget))
|
|
{
|
|
return OBJECT_INVALID;
|
|
}
|
|
}
|
|
return oTarget;
|
|
}
|
|
// Gets if the object is valid, and we can see, or hear it.
|
|
// * bSeenOnly - If set to TRUE, it must be seen.
|
|
// TRUE if oTarget is valid.
|
|
int Combat_GetTargetValid(object oTarget, int bSeenOnly = FALSE)
|
|
{
|
|
// Check if valid
|
|
if(!GetIsObjectValid(oTarget)) return FALSE;
|
|
|
|
// Check if seen
|
|
if(!GetObjectSeen(oTarget) && bSeenOnly == TRUE) return FALSE;
|
|
|
|
// Check if heard
|
|
if(!GetObjectHeard(oTarget)) return FALSE;
|
|
|
|
// Valid == TRUE
|
|
return TRUE;
|
|
}
|
|
|
|
// This will call a random voicechat to be called, if iPercent is met.
|
|
void Combat_Taunt(int iPercent = 10)
|
|
{
|
|
if(d100() <= iPercent)
|
|
{
|
|
int iVoice = VOICE_CHAT_BATTLECRY1;
|
|
switch(d6())
|
|
{
|
|
case 1: iVoice = VOICE_CHAT_ATTACK; break;
|
|
case 2: iVoice = VOICE_CHAT_BATTLECRY1; break;
|
|
case 3: iVoice = VOICE_CHAT_BATTLECRY2; break;
|
|
case 4: iVoice = VOICE_CHAT_BATTLECRY3; break;
|
|
case 5: iVoice = VOICE_CHAT_LAUGH; break;
|
|
case 6: iVoice = VOICE_CHAT_TAUNT; break;
|
|
}
|
|
PlayVoiceChat(iVoice);
|
|
}
|
|
}
|
|
|
|
// This will heal oTarget with the best spell possible.
|
|
// - Like the Bioware function.
|
|
// - Will force healing if bForce is TRUE, ELSE, it will only heal at 50% HP.
|
|
// - TRUE if it heals oTarget
|
|
int Combat_HealTarget(object oTarget, int bForce = FALSE)
|
|
{
|
|
// Taken from Bioware AI and modified.
|
|
talent tUse;
|
|
int nCurrent = GetCurrentHitPoints(OBJECT_SELF) * 2;
|
|
int nBase = GetMaxHitPoints(OBJECT_SELF);
|
|
|
|
// Check HP.
|
|
if( (nCurrent < nBase) || (bForce == TRUE) )
|
|
{
|
|
if(oTarget == OBJECT_SELF)
|
|
{
|
|
tUse = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_HEALING_POTION, 20);
|
|
if(Combat_TalentAtObject(tUse, oTarget))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
tUse = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_HEALING_TOUCH, 20);
|
|
if(Combat_TalentAtObject(tUse, oTarget))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
tUse = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_HEALING_AREAEFFECT, 20);
|
|
if(Combat_TalentAtObject(tUse, oTarget))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
// This will loop all seen allies. If any of them need healing, it will heal
|
|
// them and return TRUE.
|
|
// - Uses Combat_HealTarget to check if they need healing.
|
|
int Combat_HealAllies()
|
|
{
|
|
int iCnt = 1;
|
|
// Loop seen allies who are not dead
|
|
object oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, iCnt, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
|
while(GetIsObjectValid(oAlly))
|
|
{
|
|
if(Combat_HealTarget(oAlly))
|
|
{
|
|
// Stop - healed someone
|
|
return TRUE;
|
|
}
|
|
iCnt++;
|
|
oAlly = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_FRIEND, OBJECT_SELF, iCnt, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_IS_ALIVE, TRUE);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Only for use in "Combat_TurnUndead", it checks if there are any non-turned
|
|
// undead within 10M, of iRace.
|
|
int Combat_TurningAnyOfRaceValid(int iRace)
|
|
{
|
|
int nCnt = 1;
|
|
int nCount = 0;
|
|
object oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_RACIAL_TYPE, iRace);
|
|
while(GetIsObjectValid(oTarget) && GetDistanceToObject(oTarget) <= 10.0)
|
|
{
|
|
if(!Combat_GetHasEffect(EFFECT_TYPE_TURNED, oTarget) && !GetIsDead(oTarget))
|
|
{
|
|
return TRUE;
|
|
}
|
|
nCnt++;
|
|
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, 1, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_RACIAL_TYPE, iRace);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This will check if we can turn undead, and check if there are anythings we can
|
|
// turn, and turn if so. Uses mainly Bioware stuff.
|
|
int Combat_TurnUndead()
|
|
{
|
|
if(GetHasFeat(FEAT_TURN_UNDEAD))
|
|
{
|
|
object oUndead = Combat_GetNearestSeenOrHeardEnemy();
|
|
if(Combat_GetHasEffect(EFFECT_TYPE_TURNED, oUndead) ||
|
|
GetHitDice(OBJECT_SELF) <= GetHitDice(oUndead))
|
|
{
|
|
return FALSE;
|
|
}
|
|
int nCount;
|
|
int nElemental = GetHasFeat(FEAT_AIR_DOMAIN_POWER)
|
|
+ GetHasFeat(FEAT_EARTH_DOMAIN_POWER)
|
|
+ GetHasFeat(FEAT_FIRE_DOMAIN_POWER)
|
|
+ GetHasFeat(FEAT_FIRE_DOMAIN_POWER);
|
|
int nVermin = GetHasFeat(FEAT_PLANT_DOMAIN_POWER)
|
|
+ GetHasFeat(FEAT_ANIMAL_COMPANION);
|
|
int nConstructs = GetHasFeat(FEAT_DESTRUCTION_DOMAIN_POWER);
|
|
int nOutsider = GetHasFeat(FEAT_GOOD_DOMAIN_POWER)
|
|
+ GetHasFeat(FEAT_EVIL_DOMAIN_POWER)
|
|
+ GetHasFeat(854); // planar turning
|
|
|
|
if(nElemental == TRUE)
|
|
nCount += Combat_TurningAnyOfRaceValid(RACIAL_TYPE_ELEMENTAL);
|
|
|
|
if(nVermin == TRUE)
|
|
nCount += Combat_TurningAnyOfRaceValid(RACIAL_TYPE_VERMIN);
|
|
|
|
if(nOutsider == TRUE)
|
|
nCount += Combat_TurningAnyOfRaceValid(RACIAL_TYPE_OUTSIDER);
|
|
|
|
if(nConstructs == TRUE)
|
|
nCount += Combat_TurningAnyOfRaceValid(RACIAL_TYPE_CONSTRUCT);
|
|
|
|
nCount += Combat_TurningAnyOfRaceValid(RACIAL_TYPE_UNDEAD);
|
|
|
|
if(nCount > 0)
|
|
{
|
|
ClearAllActions();
|
|
ActionUseFeat(FEAT_TURN_UNDEAD, OBJECT_SELF);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This attempt to use the best potions the creature has.
|
|
// * Will return FALSE if they use none, or they already have the effects
|
|
// * Uses any Potection First (EG: stoneskin), then Enhancement (EG: Bulls strength)
|
|
// then Conditional (EG: Clarity)
|
|
int Combat_UseAnyPotions()
|
|
{
|
|
talent tPotion = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_PROTECTION_POTION, 20);
|
|
|
|
// Get if valid, and not got the effects
|
|
if(Combat_TalentAtObject(tPotion, OBJECT_SELF))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// Else get the next one, Enhancement
|
|
tPotion = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_ENHANCEMENT_POTION, 20);
|
|
// Get if valid, and not got the effects
|
|
if(Combat_TalentAtObject(tPotion, OBJECT_SELF))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// Else get the next one, Conditional
|
|
tPotion = GetCreatureTalentBest(TALENT_CATEGORY_BENEFICIAL_CONDITIONAL_POTION, 20);
|
|
// Get if valid, and not got the effects
|
|
if(Combat_TalentAtObject(tPotion, OBJECT_SELF))
|
|
{
|
|
return TRUE;
|
|
}
|
|
// No potion used/no potion not got effect of.
|
|
return FALSE;
|
|
}
|
|
|
|
// Attack oTarget with a melee weapon, and melee feats if we can hit them.
|
|
// - VERY basic!
|
|
void Combat_AttackMelee(object oTarget)
|
|
{
|
|
// Equip best
|
|
ClearAllActions();
|
|
ActionEquipMostDamagingMelee(oTarget);
|
|
|
|
// Attack with feat if we can hit them
|
|
int iRandom = 5 + d10();
|
|
if(GetBaseAttackBonus(OBJECT_SELF) + iRandom >= GetAC(oTarget))
|
|
{
|
|
// Getting the melee talent category for melee feats is useful in a short
|
|
// AI script. Not useful in a longer one.
|
|
// - We can get feats Knockdown (Improved), Disarm (Improved), Sap,
|
|
// Stunning fist, Expertise (Improved), Flurry of Blows, Called Shot,
|
|
// and Power Attack (Improved) from this talent
|
|
talent tMelee = GetCreatureTalentRandom(TALENT_CATEGORY_HARMFUL_MELEE);
|
|
|
|
// Can't use ranged feats - and make sure the feat is valid
|
|
if(GetIsTalentValid(tMelee) &&
|
|
GetTypeFromTalent(tMelee) == TALENT_TYPE_FEAT)
|
|
{
|
|
int iTalentID = GetIdFromTalent(tMelee);
|
|
if(iTalentID == FEAT_RAPID_SHOT)
|
|
{
|
|
// Can't use ranged feats in melee, so just normal attack
|
|
ActionAttack(oTarget);
|
|
}
|
|
else
|
|
{
|
|
// Else, use the feat, and attack
|
|
ActionUseTalentOnObject(tMelee, oTarget);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ActionAttack(oTarget);
|
|
}
|
|
}
|
|
// Attack oTarget with a ranged weapon (if we have any), and ranged feats if we can hit them.
|
|
// - VERY basic!
|
|
void Combat_AttackRanged(object oTarget)
|
|
{
|
|
// Equip best
|
|
ClearAllActions();
|
|
ActionEquipMostDamagingRanged(oTarget);
|
|
|
|
// Check if we did equip a ranged
|
|
if(!GetWeaponRanged(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)))
|
|
{
|
|
ActionAttack(oTarget);
|
|
return;
|
|
}
|
|
|
|
// Attack with feat if we can hit them
|
|
int iRandom = 5 + d10();
|
|
if(GetBaseAttackBonus(OBJECT_SELF) >= GetAC(oTarget) - iRandom)
|
|
{
|
|
// Feats for Range
|
|
if(GetHasFeat(FEAT_RAPID_SHOT))
|
|
{
|
|
ActionUseFeat(FEAT_RAPID_SHOT, oTarget);
|
|
return;
|
|
}
|
|
else if(GetHasFeat(FEAT_CALLED_SHOT))
|
|
{
|
|
ActionUseFeat(FEAT_CALLED_SHOT, oTarget);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
ActionAttack(oTarget);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ActionAttack(oTarget);
|
|
}
|
|
}
|
|
|
|
|
|
// This will check if the caller has nSpell, and casts it at oObject if so.
|
|
int Combat_CastAtObject(int nSpell, object oTarget)
|
|
{
|
|
if(GetHasSpell(nSpell) && !GetHasSpellEffect(nSpell, oTarget))
|
|
{
|
|
ClearAllActions();
|
|
ActionCastSpellAtObject(nSpell, oTarget);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
// This will check if the caller has nSpell, and casts it at oObject's location if so.
|
|
int Combat_CastAtLocation(int nSpell, object oTarget)
|
|
{
|
|
if(GetHasSpell(nSpell) && !GetHasSpellEffect(nSpell, oTarget))
|
|
{
|
|
ClearAllActions();
|
|
ActionCastSpellAtLocation(nSpell, GetLocation(oTarget));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Checks if tUse is TRUE, and uses it against oTarget if not got the effects.
|
|
int Combat_TalentAtObject(talent tUse, object oTarget)
|
|
{
|
|
if(GetIsTalentValid(tUse))
|
|
{
|
|
int iType = GetTypeFromTalent(tUse);
|
|
int iID = GetIdFromTalent(tUse);
|
|
// If it is a feat, check if they have the effect.
|
|
if(iType == TALENT_TYPE_FEAT && GetHasFeatEffect(iID, oTarget))
|
|
{
|
|
return FALSE;
|
|
}
|
|
// If a spell, check if got the spell effect
|
|
else if(iType == TALENT_TYPE_SPELL && GetHasSpellEffect(iID, oTarget))
|
|
{
|
|
return FALSE;
|
|
}
|
|
// Use it.
|
|
ClearAllActions();
|
|
ActionUseTalentOnObject(tUse, oTarget);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Cheat-Casts nSpell, if under iPercent.
|
|
// * Doesn't cast if iPercent fails, or oTarget has nSpell's effects.
|
|
// Use this to make sure a caster doesn't run out of spells.
|
|
int Combat_CheatRandomSpellAtObject(int nSpell, object oTarget, int iPercent)
|
|
{
|
|
// Check %
|
|
if(d100() <= iPercent && !GetHasSpellEffect(nSpell, oTarget))
|
|
{
|
|
// Cheat cast it at oTarget
|
|
ClearAllActions();
|
|
ActionCastSpellAtObject(nSpell, oTarget, METAMAGIC_ANY, TRUE);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This will loop oTarget's effects, and return TRUE if any are equal to
|
|
// iEffect, which is a constant EFFECT_TYPE_*
|
|
int Combat_GetHasEffect(int iEffect, object oTarget = OBJECT_SELF)
|
|
{
|
|
effect eCheck = GetFirstEffect(oTarget);
|
|
while(GetIsEffectValid(eCheck))
|
|
{
|
|
if(GetEffectType(eCheck) == iEffect)
|
|
{
|
|
return TRUE;
|
|
}
|
|
eCheck = GetNextEffect(oTarget);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// This will walk the waypoints of the creature (re-activate them)
|
|
// Use this if the creature is not in combat/not attacking/no target to attack/
|
|
void Combat_WalkWaypoints()
|
|
{
|
|
ExecuteScript(FILE_WALK_WAYPOINTS, OBJECT_SELF);
|
|
}
|