Reverted to 4.56 to track down a bug that started in 4.57. Bugfixed back to 4.61. It's amazing the damage that one skipped case statement can do.
120 lines
4.4 KiB
Plaintext
120 lines
4.4 KiB
Plaintext
//:://////////////////////////////////////////////
|
|
//:: ;-. ,-. ,-. ,-.
|
|
//:: | ) | ) / ( )
|
|
//:: |-' |-< | ;-:
|
|
//:: | | \ \ ( )
|
|
//:: ' ' ' `-' `-'
|
|
//:://////////////////////////////////////////////
|
|
//::
|
|
/*
|
|
Control Plants
|
|
Transmutation
|
|
Level: Drd 8, Plant 8
|
|
Components: V, S, DF
|
|
Casting Time: 1 standard action
|
|
Range: Close (25 ft. + 5 ft./2 levels)
|
|
Targets: Up to 2 HD/level of plant creatures,
|
|
no two of which can be more than 30 ft.
|
|
apart
|
|
Duration: 1 min./level
|
|
Saving Throw: Will negates
|
|
Spell Resistance: No
|
|
|
|
This spell enables you to control the actions of one
|
|
or more plant creatures for a short period of time. You
|
|
command the creatures by voice and they understand you,
|
|
no matter what language you speak. Even if vocal
|
|
communication is impossible the controlled plants do
|
|
not attack you. At the end of the spell, the subjects
|
|
revert to their normal behavior.
|
|
|
|
Suicidal or self-destructive commands are simply ignored.
|
|
*/
|
|
//::
|
|
//:://////////////////////////////////////////////
|
|
//:: Script: sp_ctrl_plants
|
|
//:: Author: Jaysyn
|
|
//:: Created: 2025-08-11 22:28:40
|
|
//:://////////////////////////////////////////////
|
|
#include "prc_inc_spells"
|
|
#include "prc_add_spell_dc"
|
|
|
|
void main()
|
|
{
|
|
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
|
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_TRANSMUTATION);
|
|
|
|
if (!X2PreSpellCastCode())
|
|
return;
|
|
|
|
int nMetaMagic = PRCGetMetaMagicFeat();
|
|
int CasterLvl = PRCGetCasterLevel(OBJECT_SELF);
|
|
|
|
if (GetLevelByClass(CLASS_TYPE_VERDANT_LORD, OBJECT_SELF) >= 4)
|
|
{
|
|
CasterLvl = CasterLvl + 3;
|
|
}
|
|
|
|
int nDuration = CasterLvl; // minutes
|
|
int nHDLimit = CasterLvl * 2; // RAW
|
|
|
|
if (nMetaMagic & METAMAGIC_EXTEND)
|
|
nDuration *= 2;
|
|
|
|
int nPenetr = CasterLvl + SPGetPenetr();
|
|
|
|
// Close range in NWN terms: 25 ft. + 5 ft./2 levels
|
|
float fMaxRange = 25.0 + (IntToFloat(CasterLvl / 2) * 5.0);
|
|
|
|
object oTarget = PRCGetSpellTargetObject();
|
|
location lTarget = GetLocation(oTarget);
|
|
object oCreature = GetFirstObjectInShape(SHAPE_SPHERE, fMaxRange, lTarget, TRUE);
|
|
|
|
while (GetIsObjectValid(oCreature) && nHDLimit > 0)
|
|
{
|
|
if (MyPRCGetRacialType(oCreature) == RACIAL_TYPE_PLANT
|
|
&& !GetIsReactionTypeFriendly(oCreature)
|
|
&& GetDistanceBetweenLocations(lTarget, GetLocation(oCreature)) <= 30.0
|
|
&& GetHitDice(oCreature) <= nHDLimit)
|
|
{
|
|
// Fire cast spell at event for the specified target
|
|
SignalEvent(oCreature, EventSpellCastAt(OBJECT_SELF, SPELL_CONTROL_PLANTS));
|
|
|
|
if (!PRCDoResistSpell(OBJECT_SELF, oCreature, nPenetr))
|
|
{
|
|
if (!PRCMySavingThrow(SAVING_THROW_WILL, oCreature, PRCGetSaveDC(oCreature, OBJECT_SELF),
|
|
SAVING_THROW_TYPE_NONE, OBJECT_SELF, 1.0))
|
|
{
|
|
// Remove old domination if present
|
|
effect eCheck = GetFirstEffect(oCreature);
|
|
while (GetIsEffectValid(eCheck))
|
|
{
|
|
int nType = GetEffectType(eCheck);
|
|
if (nType == EFFECT_TYPE_DOMINATED || nType == EFFECT_TYPE_CUTSCENE_DOMINATED)
|
|
RemoveEffect(oCreature, eCheck);
|
|
|
|
eCheck = GetNextEffect(oCreature);
|
|
}
|
|
|
|
// Apply domination
|
|
effect eControl = EffectCutsceneDominated();
|
|
effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DOMINATED);
|
|
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
|
effect eVis = EffectVisualEffect(VFX_IMP_DOMINATE_S);
|
|
effect eLink = EffectLinkEffects(eMind, eControl);
|
|
eLink = EffectLinkEffects(eLink, eDur);
|
|
|
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oCreature);
|
|
DelayCommand(1.0, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oCreature,
|
|
MinutesToSeconds(nDuration), TRUE, -1, CasterLvl));
|
|
|
|
nHDLimit -= GetHitDice(oCreature);
|
|
}
|
|
}
|
|
}
|
|
oCreature = GetNextObjectInShape(SHAPE_SPHERE, fMaxRange, lTarget, TRUE);
|
|
}
|
|
|
|
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
|
}
|