PRC8/nwn/nwnprc/trunk/spells/sp_ctrl_plants.nss
Jaysyn904 246f8d56aa 2025/08/22 Update
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.
2025-08-22 17:54:55 -04:00

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");
}