forked from Jaysyn/PRC8
278 lines
11 KiB
Plaintext
278 lines
11 KiB
Plaintext
|
//::///////////////////////////////////////////////
|
|||
|
//:: Turn Undead
|
|||
|
//:: NW_S2_TurnDead
|
|||
|
//:: Copyright (c) 2001 Bioware Corp.
|
|||
|
//:://////////////////////////////////////////////
|
|||
|
/*
|
|||
|
Checks domain powers and class to determine
|
|||
|
the proper turning abilities of the casting
|
|||
|
character.
|
|||
|
*/
|
|||
|
//:://////////////////////////////////////////////
|
|||
|
//:: Created By: Preston Watamaniuk
|
|||
|
//:: Created On: Nov 2, 2001
|
|||
|
//:: Updated On: Jul 15, 2003 - Georg Zoeller
|
|||
|
//:://////////////////////////////////////////////
|
|||
|
|
|||
|
/*
|
|||
|
308 - turn undead
|
|||
|
1726 - Turn_Scaleykind
|
|||
|
1727 - Turn_Slime
|
|||
|
1728 - Turn_Spider
|
|||
|
1729 - Turn_Plant
|
|||
|
1730 - Turn_Air
|
|||
|
1731 - Turn_Earth
|
|||
|
1732 - Turn_Fire
|
|||
|
1733 - Turn_Water
|
|||
|
1734 - Turn_Blightspawned
|
|||
|
2259 - turn outsider
|
|||
|
3497 - Turn cold
|
|||
|
*/
|
|||
|
|
|||
|
#include "prc_inc_clsfunc"
|
|||
|
#include "prc_inc_domain"
|
|||
|
#include "prc_inc_turning"
|
|||
|
#include "prc_inc_factotum"
|
|||
|
|
|||
|
void main()
|
|||
|
{
|
|||
|
int nTurnType = GetSpellId();
|
|||
|
|
|||
|
if(nTurnType == VESTIGE_TENEBROUS_TURN)
|
|||
|
{
|
|||
|
if(!BindAbilCooldown(OBJECT_SELF, GetSpellId(), VESTIGE_TENEBROUS)) return;
|
|||
|
nTurnType = SPELL_TURN_UNDEAD;
|
|||
|
}
|
|||
|
|
|||
|
if(nTurnType == SPELL_OPPORTUNISTIC_PIETY_TURN)
|
|||
|
{
|
|||
|
if (!ExpendInspiration(OBJECT_SELF, 1))
|
|||
|
{
|
|||
|
IncrementRemainingFeatUses(OBJECT_SELF, FEAT_OPPORTUNISTIC_PIETY_TURN);
|
|||
|
return;
|
|||
|
}
|
|||
|
// We know we can cast it now
|
|||
|
nTurnType = SPELL_TURN_UNDEAD;
|
|||
|
DecrementRemainingFeatUses(OBJECT_SELF, FEAT_OPPORTUNISTIC_PIETY_HEAL);
|
|||
|
}
|
|||
|
|
|||
|
// Because Turn Undead/Outsider isn't from a domain, skip this check
|
|||
|
if(nTurnType != SPELL_TURN_UNDEAD && nTurnType != SPELL_TURN_OUTSIDER)
|
|||
|
{
|
|||
|
// Used by the uses per day check code for bonus domains
|
|||
|
if(!DecrementDomainUses(GetTurningDomain(nTurnType), OBJECT_SELF))
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
int bUndeadMastery = GetHasFeat(FEAT_UNDEAD_MASTERY);
|
|||
|
|
|||
|
//casters level for turning
|
|||
|
int nLevel = GetTurningClassLevel(OBJECT_SELF, nTurnType);
|
|||
|
int nCommandLevel = bUndeadMastery ? nLevel * 10 : nLevel;
|
|||
|
|
|||
|
//check alignment - we will need that later
|
|||
|
int nAlign = GetAlignmentGoodEvil(OBJECT_SELF);
|
|||
|
|
|||
|
//casters charisma modifier
|
|||
|
int nChaMod = GetTurningCharismaMod(nTurnType);
|
|||
|
|
|||
|
//key values for turning
|
|||
|
int nTurningTotalHD = d6(2) + nLevel + nChaMod;
|
|||
|
int nTurningCheck = d20() + nChaMod;
|
|||
|
|
|||
|
if(nTurnType == SPELL_TURN_UNDEAD) // Hallow spell, +4 for turning, -4 for commanding undead
|
|||
|
{
|
|||
|
if (nAlign == ALIGNMENT_EVIL && GetLocalInt(OBJECT_SELF, "HallowTurn")) nTurningCheck -= 4;
|
|||
|
else if (GetLocalInt(OBJECT_SELF, "HallowTurn")) nTurningCheck += 4;
|
|||
|
}
|
|||
|
|
|||
|
int nTurningMaxHD = GetTurningCheckResult(nLevel, nTurningCheck);
|
|||
|
|
|||
|
//these stack but dont multiply
|
|||
|
//so use a bonus amount and then add that on later
|
|||
|
|
|||
|
//apply maximize turning
|
|||
|
//+100% if good
|
|||
|
if((GetHasFeat(FEAT_MAXIMIZE_TURNING) && nAlign == ALIGNMENT_GOOD)
|
|||
|
|| GetLocalInt(OBJECT_SELF,"vMaximizeNextTurn"))
|
|||
|
{
|
|||
|
nTurningTotalHD += nTurningTotalHD;
|
|||
|
DeleteLocalInt(OBJECT_SELF,"vMaximizeNextTurn");
|
|||
|
DecrementRemainingFeatUses(OBJECT_SELF, FEAT_ML_MAXIMIZE_TURNING);
|
|||
|
}
|
|||
|
|
|||
|
//apply empowered turning
|
|||
|
//+50%
|
|||
|
//only if maximize doesnt apply
|
|||
|
else if(GetHasFeat(FEAT_EMPOWER_TURNING))
|
|||
|
nTurningTotalHD += nTurningTotalHD/2;
|
|||
|
|
|||
|
// Evil clerics rebuke, not turn, and have a different VFX
|
|||
|
effect eImpactVis = nAlign == ALIGNMENT_EVIL ? EffectVisualEffect(VFX_FNF_LOS_EVIL_30):
|
|||
|
EffectVisualEffect(VFX_FNF_LOS_HOLY_30);
|
|||
|
|
|||
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpactVis, GetLocation(OBJECT_SELF));
|
|||
|
|
|||
|
//zone of animation effect
|
|||
|
//"You can use a rebuke or command undead attempt to animate
|
|||
|
//corpses within range of your rebuke or command attempt.
|
|||
|
//You animate a total number of HD of undead equal to the
|
|||
|
//number of undead that would be commanded by your result
|
|||
|
//(though you can<61>t animate more undead than there are available
|
|||
|
//corpses within range). You can<61>t animate more undead with
|
|||
|
//any single attempt than the maximum number you can command
|
|||
|
//(including any undead already under your command). These
|
|||
|
//undead are automatically under your command, though your
|
|||
|
//normal limit of commanded undead still applies. If the
|
|||
|
//corpses are relatively fresh, the animated undead are zombies.
|
|||
|
//Otherwise, they are skeletons."
|
|||
|
//currently implemented ignoring corpses & what the corpses are of.
|
|||
|
if(GetLocalInt(OBJECT_SELF, "UsingZoneOfAnimation"))
|
|||
|
{
|
|||
|
//Undead Mastery multiplies total HD by 10
|
|||
|
int bUndeadMastery = GetHasFeat(FEAT_UNDEAD_MASTERY);
|
|||
|
if(bUndeadMastery)
|
|||
|
nLevel *= 10;
|
|||
|
//keep creating stuff
|
|||
|
int nCommandedTotalHD = GetCommandedTotalHD(nTurnType, bUndeadMastery);
|
|||
|
while(nCommandedTotalHD < nTurningTotalHD)
|
|||
|
{
|
|||
|
//skeletal blackguard
|
|||
|
string sResRef = "x2_s_bguard_18";
|
|||
|
object oCreated = CreateObject(OBJECT_TYPE_CREATURE, sResRef, GetLocation(OBJECT_SELF));
|
|||
|
|
|||
|
int nTargetHD = GetHitDiceForTurning(oCreated, nTurnType, RACIAL_TYPE_UNDEAD);
|
|||
|
|
|||
|
if(nCommandedTotalHD + nTargetHD <= nLevel)
|
|||
|
{
|
|||
|
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD), GetLocation(oCreated));
|
|||
|
DoCommand(oCreated);
|
|||
|
CorpseCrafter(OBJECT_SELF, oCreated);
|
|||
|
nCommandedTotalHD += nTargetHD;
|
|||
|
}
|
|||
|
//cant be commanded, clean it up
|
|||
|
else
|
|||
|
DestroyObject(oCreated);
|
|||
|
}
|
|||
|
//send feedback
|
|||
|
FloatingTextStringOnCreature("Currently commanding "+IntToString(nCommandedTotalHD)+"HD out of "+IntToString(nLevel)+"HD.", OBJECT_SELF, FALSE);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
FloatingTextStringOnCreature("You are turning "+IntToString(nTurningTotalHD)+"HD of creatures whose HD is equal or less than "+IntToString(nTurningMaxHD), OBJECT_SELF, FALSE);
|
|||
|
|
|||
|
int bDisplayCommandMessage = -1;
|
|||
|
int nCommandedTotalHD = GetCommandedTotalHD(nTurnType, bUndeadMastery);
|
|||
|
int nHDCount, nTurnOrRebuke, nTargetHD, nTargetRace;
|
|||
|
int i = 1;
|
|||
|
|
|||
|
object oTest = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, i);
|
|||
|
if (GetEssentiaInvestedFeat(OBJECT_SELF, FEAT_AZURE_TURNING) && nTurnType == SPELL_TURN_UNDEAD)
|
|||
|
{
|
|||
|
while(GetIsObjectValid(oTest) && GetDistanceToObject(oTest) < 20.0)
|
|||
|
{
|
|||
|
nTargetRace = MyPRCGetRacialType(oTest);
|
|||
|
if(nTargetRace == RACIAL_TYPE_UNDEAD && nTurningMaxHD >= GetHitDiceForTurning(oTest, nTurnType, nTargetRace))
|
|||
|
{
|
|||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d8(GetEssentiaInvestedFeat(OBJECT_SELF, FEAT_AZURE_TURNING)), DAMAGE_TYPE_DIVINE), oTest);
|
|||
|
}
|
|||
|
|
|||
|
//move to next test
|
|||
|
i++;
|
|||
|
oTest = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
i = 1;
|
|||
|
oTest = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, i);
|
|||
|
while(GetIsObjectValid(oTest) && nHDCount < nTurningTotalHD && GetDistanceToObject(oTest) < 20.0)//20 m = 60 ft
|
|||
|
{
|
|||
|
nTargetRace = MyPRCGetRacialType(oTest);
|
|||
|
nTurnOrRebuke = GetIsTurnOrRebuke(oTest, nTurnType, nTargetRace);
|
|||
|
if(nTurnOrRebuke)
|
|||
|
{
|
|||
|
int nTargetHD = GetHitDiceForTurning(oTest, nTurnType, nTargetRace);
|
|||
|
if(nTargetHD <= nTurningMaxHD && nHDCount+nTargetHD <= nTurningTotalHD)
|
|||
|
{
|
|||
|
nHDCount += nTargetHD;
|
|||
|
|
|||
|
//signal the event
|
|||
|
SignalEvent(oTest, EventSpellCastAt(OBJECT_SELF, nTurnType));
|
|||
|
|
|||
|
//sun domain
|
|||
|
//destroys instead of turn/rebuke/command
|
|||
|
//useable once per day only
|
|||
|
if(GetLocalInt(OBJECT_SELF, "UsingSunDomain"))
|
|||
|
{
|
|||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SUNSTRIKE), oTest);
|
|||
|
//Do not destroy until this script finishes, otherwise GetNearestCreature() will not work correctly
|
|||
|
DelayCommand(0.0, DoDestroy(oTest));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if(nTurnOrRebuke == ACTION_TURN)
|
|||
|
{
|
|||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SUNSTRIKE), oTest);
|
|||
|
//if half of level, destroy
|
|||
|
//otherwise turn
|
|||
|
if(nTargetHD < nLevel/2)
|
|||
|
DelayCommand(0.0, DoDestroy(oTest));
|
|||
|
else
|
|||
|
DoTurn(oTest);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
bDisplayCommandMessage = TRUE;
|
|||
|
//if half of level, command
|
|||
|
//otherwise rebuke
|
|||
|
if(nTargetHD < nLevel/2)
|
|||
|
{
|
|||
|
//undead mastery only applies to undead
|
|||
|
//so non-undead have thier HD multiplied by 10
|
|||
|
if(nTargetRace != RACIAL_TYPE_UNDEAD && bUndeadMastery)
|
|||
|
nTargetHD *= 10;
|
|||
|
|
|||
|
if(nCommandedTotalHD + nTargetHD <= nCommandLevel)
|
|||
|
{
|
|||
|
nCommandedTotalHD += nTargetHD;
|
|||
|
DoCommand(oTest);
|
|||
|
}
|
|||
|
//not enough commanding power left
|
|||
|
//rebuke instead
|
|||
|
else
|
|||
|
DoRebuke(oTest);
|
|||
|
}
|
|||
|
else
|
|||
|
DoRebuke(oTest);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Check for Exalted Turning
|
|||
|
// take 3d6 damage if they do
|
|||
|
// Only works on undead
|
|||
|
if(nAlign == ALIGNMENT_GOOD
|
|||
|
&& nTargetRace == RACIAL_TYPE_UNDEAD
|
|||
|
&& GetHasFeat(FEAT_EXALTED_TURNING))
|
|||
|
{
|
|||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(3), DAMAGE_TYPE_DIVINE), oTest);
|
|||
|
}
|
|||
|
|
|||
|
//Check for Holy Fire
|
|||
|
if(GetHasSpellEffect(SPELL_HOLY_FIRE, oTest))
|
|||
|
{
|
|||
|
int nFire = nTurningMaxHD / 2;
|
|||
|
int nHoly = nTurningMaxHD - nFire;
|
|||
|
effect eDam = EffectLinkEffects(EffectDamage(DAMAGE_TYPE_DIVINE, nHoly), EffectDamage(DAMAGE_TYPE_FIRE, nFire));
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTest);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//move to next test
|
|||
|
i++;
|
|||
|
oTest = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, OBJECT_SELF, i);
|
|||
|
}
|
|||
|
|
|||
|
if(bDisplayCommandMessage)
|
|||
|
FloatingTextStringOnCreature("Currently commanding "+IntToString(nCommandedTotalHD)+"HD out of "+IntToString(nCommandLevel)+"HD.", OBJECT_SELF, FALSE);
|
|||
|
}
|