I need help figuring out why. It compiles so I know it works somewhat. Right now I'm using stock spells, once I get this working with regular spells, I'll begin making the rays. The drain is going to be individual, but to stay as close as possible to lore, I would try to make the drain also affect your items, though not permanently as in lore.
I am trying to make Gauth, the scourge of the trade of Sshamath.
They feed on magic, and sometimes meat, and raid caravans to steal powerful magic items to drain their powers. The conclave cannot get rid of them since when you kill one, two more will grow from the corpse in a few weeks and magic is completely useless as well.
Hidden: show
Code: Select all
//::///////////////////////////////////////////////
//:: x2_s1_gauthatt
//:: Gauth Attack Spell Logic
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
This spellscript is the core of the Gauth's
attack logic.
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: 2003-08-28
//:://////////////////////////////////////////////
#include "x2_inc_gauth"
void main()
{
int nApp = GetLocalInt(OBJECT_SELF,"gauth");
object oTarget = GetSpellTargetObject();
// Only if we are beholders and not beholder mages
/*
//* GZ: cut whole immunity thing because it was causing too much trouble
if (nApp == 472 ||nApp == 401 || nApp == 403)
{
CloseAntiMagicEye(oTarget);
}
*/
// need that to make them not drop out of combat
SignalEvent(oTarget,EventSpellCastAt(OBJECT_SELF,GetSpellId()));
struct gauth_target_struct stTargets = GetRayTargets(oTarget);
int nRay;
int nOdd;
int nRacial = GetRacialType(oTarget);
if (stTargets.nCount ==0)
{
//emergency fallback
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget1);
}
else if (stTargets.nCount ==1) // AI for only one target
{
nOdd=d4();
if (nOdd == 1)
{
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget1);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget1);
}
if (nOdd == 2)
{
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget1);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget1);
}
if (nOdd == 3)
{
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget1);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
}
if (nOdd == 4)
{
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget1);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget1);
}
if (d3()==1)
{
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget2);
}
}
else if (stTargets.nCount ==2)
{
if (nOdd)
{
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget2);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget2);
}
else
{
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget1);
if (d2()==1)
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget2);
}
if (d3()==1)
{
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget3);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget3);
}
}
else if (stTargets.nCount ==3)
{
if (nOdd)
{
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget3);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget3);
}
else
{
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_REPULSION,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_PARALYZATION,stTargets.oTarget3);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_WOUND,stTargets.oTarget2);
GauthDoFireBeam(GAUTH_RAY_DRAIN,stTargets.oTarget1);
GauthDoFireBeam(GAUTH_RAY_LIGHTNING_BOLT,stTargets.oTarget3);
GauthDoFireBeam(GAUTH_RAY_CONE_OF_COLD,stTargets.oTarget3);
}
}
// Only if we are beholders and not beholder mages
if (nApp != 1)
{
OpenFeebleEye(oTarget);
}
}
/*
*/Hidden: show
Code: Select all
//::///////////////////////////////////////////////
//:: Gauth AI and Attack Include
//:: x2_inc_gauth
//:: Copyright (c) 2003 Bioware Corp.
//:://////////////////////////////////////////////
/*
Include file for several Gauth functions
*/
//:://////////////////////////////////////////////
//:: Created By: Georg Zoeller
//:: Created On: August, 2003
//:://////////////////////////////////////////////
#include "x0_i0_spells"
const int GAUTH_RAY_CONE_OF_COLD = 1;
const int GAUTH_RAY_LIGHTNING_BOLT = 2;
const int GAUTH_RAY_WOUND = 3;
const int GAUTH_RAY_PARALYZATION = 4;
const int GAUTH_RAY_REPULSION = 5;
const int GAUTH_RAY_DRAIN = 6;
struct gauth_target_struct
{
object oTarget1;
int nRating1;
object oTarget2;
int nRating2;
object oTarget3;
int nRating3;
int nCount;
};
int GetFeebleEyeMakesSense ( object oTarget );
void OpenFeebleEye ( object oTarget );
void CloseFeebleEye ( object oTarget );
int GauthGetTargetThreatRating ( object oTarget );
int GauthDetermineHasEffect ( int nRay, object oCreature );
void GauthDoFireBeam ( int nRay, object oTarget );
struct gauth_target_struct GetRayTargets ( object oTarget );
int GetFeebleEyeMakesSense(object oTarget)
{
int bRet = TRUE;
int nType;
object oNear = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, oTarget);
float fDistance = GetDistanceBetween(oTarget, oNear);
effect eTest = GetFirstEffect(oTarget);
if (!GetIsEffectValid(eTest))
{
int nMag = GetLevelByClass(CLASS_TYPE_WIZARD,oTarget) + GetLevelByClass(CLASS_TYPE_SORCERER,oTarget) + GetLevelByClass(CLASS_TYPE_BARD,oTarget) + GetLevelByClass(CLASS_TYPE_RANGER,oTarget) + GetLevelByClass(CLASS_TYPE_PALADIN,oTarget);
// at least 3 levels of magic user classes... we better use anti magic anyway
if (nMag < 4)
{
bRet = FALSE;
}
}
else
{
while (GetIsEffectValid(eTest) && bRet == TRUE )
{
nType = GetEffectType(eTest);
if (nType == EFFECT_TYPE_STUNNED || nType == EFFECT_TYPE_PARALYZE )
{
bRet = FALSE;
}
eTest = GetNextEffect(oTarget);
}
}
if(fDistance > 30.0 || !GetIsInCombat(oNear))
{
bRet = FALSE;
}
if (GetHasSpellEffect(805,oTarget)) // already feeblemind
{
bRet = FALSE;
}
return bRet;
}
void OpenFeebleEye (object oTarget)
{
if (GetFeebleEyeMakesSense(oTarget))
{
ClearAllActions();
ActionCastSpellAtObject(805,GetSpellTargetObject(),METAMAGIC_ANY,TRUE,0, PROJECTILE_PATH_TYPE_DEFAULT,TRUE);
}
}
// being a badass gauth, we close our feeble eye only to attack with our eye rays
// and then reopen it...
void CloseFeebleEye(object oTarget)
{
RemoveSpellEffects(805,OBJECT_SELF,oTarget); // Do you think I actually still need this? - Moridin
}
// stacking protection
int GauthDetermineHasEffect(int nRay, object oCreature)
{
switch (nRay)
{
case GAUTH_RAY_PARALYZATION : if (GetHasEffect(EFFECT_TYPE_PARALYZE,oCreature))
return TRUE;
case GAUTH_RAY_DRAIN : if (GetHasEffect(EFFECT_TYPE_SPELL_FAILURE,oCreature))
return TRUE;
}
return FALSE;
}
int GauthGetTargetThreatRating(object oTarget)
{
if (oTarget == OBJECT_INVALID)
{
return 0;
}
int nRet = 20;
if (GetDistanceBetween(oTarget,OBJECT_SELF) <5.0f)
{
nRet += 5;
if(GetHitDice(OBJECT_SELF) <= GetHitDice(oTarget) - 3)
{
nRet += 3;
}
}
if (GetDistanceBetween(oTarget,OBJECT_SELF) >15.0f)
{
nRet += 3;
}
nRet += (GetHitDice(oTarget)-GetHitDice(OBJECT_SELF) /2);
if (GetLevelByClass(CLASS_TYPE_FIGHTER, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_BARBARIAN, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_MONK, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_RANGER, oTarget) > 3)
{
nRet += 3;
}
if (GetLevelByClass(CLASS_TYPE_ROGUE, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_WARLOCK, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_BARD, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_DRUID, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_PALADIN, oTarget) > 3)
{
nRet += 4;
}
if (GetLevelByClass(CLASS_TYPE_CLERIC, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_SORCERER, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_WIZARD, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_FAVORED_SOUL, oTarget) > 3 ||
GetLevelByClass(CLASS_TYPE_SPIRIT_SHAMAN, oTarget) > 3)
{
nRet += 5;
}
if (GetPlotFlag(oTarget)) //
{
nRet -= 6 ;
}
if (GetMaster(oTarget)!= OBJECT_INVALID)
{
nRet -= 4;
}
if (GetHasEffect(EFFECT_TYPE_PARALYZE,oTarget))
{
nRet -= 8;
}
if (GetHasEffect(EFFECT_TYPE_CONFUSED,oTarget))
{
nRet -=8;
}
if (GetArcaneSpellFailure(oTarget) == 100)
{
nRet -=10;
}
if (GetIsDead(oTarget))
{
nRet = 0;
}
return nRet;
}
struct gauth_target_struct GetRayTargets(object oTarget)
{
struct gauth_target_struct stRet;
object oTarget1;
object oTarget2;
object oTarget3;
int nTarget1;
int nTarget2;
int nTarget3;
int nCount = 0;
int nNth = 1;
int nCheck = 0;
if (oTarget != OBJECT_INVALID)
{
oTarget1 = oTarget;
nCount ++;
nTarget1 = GauthGetTargetThreatRating(oTarget1);
oTarget2 = GetNearestCreature(CREATURE_TYPE_IS_ALIVE,CREATURE_ALIVE_TRUE,oTarget1,nNth);
while(GetIsObjectValid(oTarget2) && nCheck != 1)
{
if(GetIsFriend(oTarget1, oTarget2))
{
nTarget2 = GauthGetTargetThreatRating(oTarget2);
nCount ++;
nCheck = 1;
}
else
{
nNth++;
oTarget2 = GetNearestCreature(CREATURE_TYPE_IS_ALIVE,CREATURE_ALIVE_TRUE,oTarget1,nNth);
}
}
nCheck=0;
nNth=1;
oTarget3 = GetNearestCreature(CREATURE_TYPE_IS_ALIVE,CREATURE_ALIVE_TRUE,oTarget2,nNth);
while(GetIsObjectValid(oTarget3) && nCheck != 1)
{
if(GetIsFriend(oTarget1, oTarget3))
{
nTarget3 = GauthGetTargetThreatRating(oTarget3);
nCount ++;
nCheck = 1;
}
else
{
nNth++;
oTarget3 = GetNearestCreature(CREATURE_TYPE_IS_ALIVE,CREATURE_ALIVE_TRUE,oTarget2,nNth);
}
}
}
stRet.oTarget1 = oTarget1;
stRet.nRating1 = nTarget1;
if (oTarget2 != OBJECT_INVALID)
{
stRet.oTarget2 = oTarget2;
stRet.nRating2 = nTarget2;
}
else
{
stRet.oTarget2 = oTarget1;
stRet.nRating2 = nTarget1;
nCount =2;
}
if (nCount ==3)
{
stRet.oTarget3 = oTarget3;
stRet.nRating3 = nTarget3;
}
stRet.nCount = nCount;
return stRet;
}
void GauthDoFireBeam(int nRay, object oTarget)
{
// don't use a ray if the target already has that effect
if (GauthDetermineHasEffect(nRay,oTarget))
{
return;
}
int bHit = TouchAttackRanged(oTarget,FALSE)>0;
int nProj;
switch (nRay)
{
case GAUTH_RAY_CONE_OF_COLD: nProj = 775;
break;
case GAUTH_RAY_LIGHTNING_BOLT: nProj = 851;
break;
case GAUTH_RAY_REPULSION: nProj = 112367;
break;
case GAUTH_RAY_WOUND: nProj = 391;
break;
case GAUTH_RAY_DRAIN: nProj = 727;
break;
case GAUTH_RAY_PARALYZATION: nProj = 833;
break;
}
if (bHit)
{
ActionCastSpellAtObject(nProj,oTarget,METAMAGIC_ANY,TRUE,0,PROJECTILE_PATH_TYPE_DEFAULT,TRUE);
}
else
{
location lFail = GetLocation(oTarget);
vector vFail = GetPositionFromLocation(lFail);
if (GetDistanceBetween(OBJECT_SELF,oTarget) > 6.0f)
{
vFail.x += IntToFloat(Random(3)) - 1.5;
vFail.y += IntToFloat(Random(3)) - 1.5;
vFail.z += IntToFloat(Random(2));
lFail = Location(GetArea(oTarget),vFail,0.0f);
}
//----------------------------------------------------------------------
// if we are fairly near, calculating a location could cause us to
// spin, so we use the same location all the time
//----------------------------------------------------------------------
else
{
vFail.z += 0.8;
vFail.y += 0.2;
vFail.x -= 0.2;
}
object oIpoint = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_ipoint ", lFail, FALSE, "beh_ip_ray_targ");
ActionCastSpellAtObject(nProj,oIpoint,METAMAGIC_ANY,TRUE,0,PROJECTILE_PATH_TYPE_DEFAULT,TRUE);
DestroyObject(oIpoint, 1.0);
}
}