181 lines
6.7 KiB
Plaintext
181 lines
6.7 KiB
Plaintext
|
/************************ [Necromancer (Low) Custom AI] ************************
|
||
|
Filename: J_CAI_Necro
|
||
|
************************* [Necromancer (Low) Custom AI] ************************
|
||
|
This is a custom AI file for necromancers.
|
||
|
|
||
|
It will summon 3 skeletons (by creating them, and adding them as faction
|
||
|
members) until it has 3, 1 each round. Healing is done normally, so it
|
||
|
should be a non-undead necromancer (Necromancers are meant to be not undead!)
|
||
|
|
||
|
It will cheat-cast negative spells, "Negative Energy Ray" and "Negative energy
|
||
|
Burst". Spells it'll cast on self ar "Negative energy protection" and
|
||
|
"Mage armor". Pretty odd selection, but this is only a sample AI.
|
||
|
|
||
|
Also note the skeletons hang around at the end. It could be scripted to
|
||
|
destroy all skeletons OnDeath too.
|
||
|
|
||
|
Note:
|
||
|
- Add negative spells to heal undead allies.
|
||
|
- All other spells are cheat-cast (when cast at enemies)
|
||
|
- CR of necromancer should be 4-8.
|
||
|
|
||
|
Ideas:
|
||
|
- Modify to summon "Deer" for a ranger, or "Dogs" for a dog trainer, the functions
|
||
|
ActionCreateAlly() and CountCreaturesOfTagInFaction() can be changed to
|
||
|
check for amounts of these exsisting, and "summon" new ones.
|
||
|
************************* [History] ********************************************
|
||
|
1.3 - Added as sample
|
||
|
************************* [Workings] *******************************************
|
||
|
Uses Combat_GetAITargetObject, to see if we saw something new or something.
|
||
|
|
||
|
Then we do:
|
||
|
|
||
|
- Summon an extra skeleton (From default pallet) if we have under 5
|
||
|
- Healing self with normal arrangements
|
||
|
- Heal undead around us
|
||
|
- Defend self with spells
|
||
|
- Use negative attacks
|
||
|
************************* [Arguments] ******************************************
|
||
|
Arguments: N/A
|
||
|
************************* [Necromancer (Low) Custom AI] ***********************/
|
||
|
|
||
|
// Useful custom AI functions here
|
||
|
#include "J_INC_BASIC"
|
||
|
|
||
|
// Amount of skeletons to summon. 1-4 are OK, 5-7 are a hell of a lot! 8+ are too many.
|
||
|
const int SKELETONS_MAX = 3;
|
||
|
|
||
|
// Counts amount of creatures of tag sTag, that are in the area and in the same
|
||
|
// faction as the caster.
|
||
|
int CountCreaturesOfTagInFaction(string sTag);
|
||
|
// Summon a undead ally of sResRef, with casting animations and effects, using
|
||
|
// nVisEffect for the visual effect applied to the created creature.
|
||
|
void ActionCreateAlly(string sResRef, int nVisEffect = VFX_FNF_SUMMON_UNDEAD);
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
// If we have summoned an undead in the last 3 seconds, stop. Set in ActionCreateAlly.
|
||
|
if(GetLocalInt(OBJECT_SELF, "SUMMONING")) return;
|
||
|
|
||
|
// Get the target to attack
|
||
|
object oTarget = Combat_GetAITargetObject();
|
||
|
|
||
|
// Check if valid
|
||
|
// - Can be seen or heard
|
||
|
if(!Combat_GetTargetValid(oTarget))
|
||
|
{
|
||
|
// Nearest seen or heard enemy. If not valid, stop the script.
|
||
|
oTarget = Combat_GetNearestSeenOrHeardEnemy();
|
||
|
if(!GetIsObjectValid(oTarget))
|
||
|
{
|
||
|
// Heal ourselves after combat.
|
||
|
if(Combat_HealTarget(OBJECT_SELF)) return;
|
||
|
// Walk waypoints if we do not heal
|
||
|
Combat_WalkWaypoints();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Do combat.
|
||
|
|
||
|
// Heal ourselves first, if under 50% HP.
|
||
|
Combat_HealTarget(OBJECT_SELF);
|
||
|
|
||
|
// Get amount of skeletons by tag "NW_SKELWARR01"
|
||
|
int nFollowers = CountCreaturesOfTagInFaction("NW_SKELWARR01");
|
||
|
|
||
|
// May also check for the second skeleton that we create, "NW_SKELWARR02",
|
||
|
// and check how many of them there are.
|
||
|
if(nFollowers < SKELETONS_MAX)
|
||
|
{
|
||
|
// Add it onto the exsisting nFollowers.
|
||
|
nFollowers += CountCreaturesOfTagInFaction("NW_SKELWARR02");
|
||
|
}
|
||
|
|
||
|
// We will summon more if nFollowers is < SKELETONS_MAX (Default: 3).
|
||
|
if(nFollowers < SKELETONS_MAX)
|
||
|
{
|
||
|
// Stop, and summon
|
||
|
// There are 2 suitable undead - warriors that is.
|
||
|
// - Skeleton Warrior 6 nw_skelwarr01 NW_SKELWARR01
|
||
|
// - Skeleton Warrior 6 nw_skelwarr02 NW_SKELWARR02
|
||
|
string sUse = "nw_skelwarr0" + IntToString(d2());
|
||
|
// Use function created for it (so we could modify to make it, say,
|
||
|
// summon deer).
|
||
|
ActionCreateAlly(sUse);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Heal undead allies (or other allies) using spells we know
|
||
|
object oMostDamaged = GetFactionMostDamagedMember();
|
||
|
|
||
|
// Check if undead
|
||
|
if(GetIsObjectValid(oMostDamaged))
|
||
|
{
|
||
|
if(GetRacialType(oMostDamaged) == RACIAL_TYPE_UNDEAD)
|
||
|
{
|
||
|
// Heal this undead with negative spells
|
||
|
if(Combat_CastAtObject(SPELL_NEGATIVE_ENERGY_BURST, oMostDamaged)) return;
|
||
|
if(Combat_CastAtObject(SPELL_NEGATIVE_ENERGY_RAY, oMostDamaged)) return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Normal heal
|
||
|
Combat_HealTarget(oMostDamaged);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Cheat cast hostile, and defensive, spells.
|
||
|
|
||
|
// Negative energy protection - 90
|
||
|
if(Combat_CheatRandomSpellAtObject(SPELL_NEGATIVE_ENERGY_PROTECTION, OBJECT_SELF, 90)) return;
|
||
|
|
||
|
// Mage armor - 60
|
||
|
if(Combat_CheatRandomSpellAtObject(SPELL_MAGE_ARMOR, OBJECT_SELF, 60)) return;
|
||
|
|
||
|
// Negative energy burst - 50
|
||
|
if(Combat_CheatRandomSpellAtObject(SPELL_NEGATIVE_ENERGY_BURST, oTarget, 50)) return;
|
||
|
|
||
|
// Negative energy ray - 100
|
||
|
if(Combat_CheatRandomSpellAtObject(SPELL_NEGATIVE_ENERGY_RAY, oTarget, 100)) return;
|
||
|
}
|
||
|
|
||
|
// Counts amount of creatures of tag sTag, that are in the area and in the same
|
||
|
// faction as the caster.
|
||
|
int CountCreaturesOfTagInFaction(string sTag)
|
||
|
{
|
||
|
// Get amount of followers to return
|
||
|
int nFollowers = 0;
|
||
|
int nCnt = 1;
|
||
|
object oUndead = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||
|
while(GetIsObjectValid(oUndead))
|
||
|
{
|
||
|
if(GetFactionEqual(oUndead))
|
||
|
{
|
||
|
// Add 1 to the followers
|
||
|
nFollowers++;
|
||
|
}
|
||
|
nCnt++;
|
||
|
oUndead = GetNearestObjectByTag(sTag, OBJECT_SELF, nCnt);
|
||
|
}
|
||
|
return nFollowers;
|
||
|
}
|
||
|
// Summon a undead ally of sResRef, with casting animations and effects, using
|
||
|
// nVisEffect for the visual effect applied to the created creature.
|
||
|
void ActionCreateAlly(string sResRef, int nVisEffect = VFX_FNF_SUMMON_UNDEAD)
|
||
|
{
|
||
|
// Stop, and summon
|
||
|
ClearAllActions();
|
||
|
// Fake cast spell
|
||
|
ActionCastFakeSpellAtObject(SPELL_CREATE_GREATER_UNDEAD, OBJECT_SELF);
|
||
|
object oNewUndead = CreateObject(OBJECT_TYPE_CREATURE, sResRef, GetLocation(OBJECT_SELF));
|
||
|
// Add to our faction
|
||
|
ChangeFaction(oNewUndead, OBJECT_SELF);
|
||
|
// Apply visual effect to new creature after a few seconds
|
||
|
effect eVis = EffectVisualEffect(nVisEffect);
|
||
|
DelayCommand(0.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oNewUndead));
|
||
|
SetLocalInt(OBJECT_SELF, "SUMMONING", TRUE);
|
||
|
DelayCommand(3.0, DeleteLocalInt(OBJECT_SELF, "SUMMONING"));
|
||
|
return;
|
||
|
}
|