Files
PRC8/nwn/nwnprc/trunk/spells/nw_s0_darkness.nss
Jaysyn904 da1ff48ac3 2026/05/26 Update
Updated PRC8 version number.
Added SoundImpact to Damning Darkness in vfx_persistent.2da.
Updated CheckPRCLimitations() to make Darkness, Deeper Darkness & Damning Darkness work better.
Fixed PnP Darkness & PnP Damning Darkness.
Fixed Oversized Two-Weapon Fighting.
Updated TLK for Attune Gem.
Fixed typo in Calm Emotions description.
Updated changelog.
2026-05-26 22:53:34 -04:00

160 lines
6.4 KiB
Plaintext

/*
nw_s0_darkness
Creates a globe of darkness around those in the area
of effect.
By: Preston Watamaniuk
Created: Jan 7, 2002
Modified: June 12, 2006
Flaming_Sword: Added touch attack roll
Fixed by: Jaysyn
Date: 2026-05-26 19:53:19
*/
#include "prc_sp_func"
#include "prc_inc_sp_tch"
#include "prc_inc_itmrstr"
#include "prc_add_spell_dc"
//Implements the spell impact, put code here
// if called in many places, return TRUE if
// stored charges should be decreased
// eg. touch attack hits
//
// Variables passed may be changed if necessary
int DoSpell(object oCaster, object oTarget, int nCasterLevel)
{
//Declare major variables including Area of Effect Object
int iAttackRoll = 1;
int nMetaMagic = PRCGetMetaMagicFeat();
int nPnP = GetPRCSwitch(PRC_PNP_DARKNESS);
float fDuration = nPnP ? TurnsToSeconds(nCasterLevel * 10) : RoundsToSeconds(nCasterLevel);//10min/level for PnP
effect eAOE = EffectAreaOfEffect(AOE_PER_DARKNESS);
//Make sure duration does no equal 0
if(fDuration < 6.0f)
fDuration = 6.0f;
//Check Extend metamagic feat.
if(nMetaMagic & METAMAGIC_EXTEND)
fDuration *= 2;
int nShadow = PRCMax(GetLocalInt(oCaster, "ShadowMantle_Shoulder"), GetLocalInt(oTarget, "ShadowMantle_Shoulder"));
if (nShadow) nPnP = FALSE;
if (DEBUG) DoDebug("nw_s0_darkness: oCaster "+GetName(oCaster)+" oTarget "+GetName(oTarget)+" nSwitch "+IntToString(nPnP));
if(!nPnP)
{
if (nShadow)
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAOE, oCaster, fDuration);
else
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAOE, PRCGetSpellTargetLocation(), fDuration);
object oAoE = GetAreaOfEffectObject(GetSpellTargetLocation(), "VFX_PER_DARKNESS");
SetAllAoEInts(SPELL_DARKNESS, oAoE, PRCGetSpellSaveDC(SPELL_DARKNESS, SPELL_SCHOOL_EVOCATION), 0, nCasterLevel);
}
else
{
object oItemTarget = oTarget;
if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE)
{ //touch attack roll if target creature is not an ally
if(!spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster))
iAttackRoll = PRCDoMeleeTouchAttack(oTarget);
if(iAttackRoll > 0)
{
oItemTarget = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
if(DEBUG) DoDebug("Darkness: Chest item = " + DebugObject2Str(oItemTarget));
if(!GetIsObjectValid(oItemTarget))
{
//no armor, check other slots
int i;
for(i=0;i<14;i++)
{
oItemTarget = GetItemInSlot(i, oTarget);
if(GetIsObjectValid(oItemTarget))
{
if(DEBUG) DoDebug("Darkness: Found item in slot " + IntToString(i));
break;//end for loop
}
}
}
// Apply item property if valid item found
if(GetIsObjectValid(oItemTarget))
{
if(DEBUG) DoDebug("Darkness: Applying IP to " + DebugObject2Str(oItemTarget));
itemproperty ipDarkness = ItemPropertyAreaOfEffect(IP_CONST_AOE_DARKNESS, nCasterLevel);
IPSafeAddItemProperty(oItemTarget, ipDarkness, fDuration);
if(DEBUG) DoDebug("Darkness: IP applied");
DelayCommand(0.1, VoidCheckPRCLimitations(oItemTarget, OBJECT_INVALID));
}
// Otherwise fall through to location-based AOE
}
else
{
// Touch attack failed - do nothing
return 0;
}
}
else if(GetObjectType(oTarget) == OBJECT_TYPE_PLACEABLE)
{
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAOE, PRCGetSpellTargetLocation(), fDuration);
object oAoE = GetAreaOfEffectObject(GetSpellTargetLocation(), "VFX_PER_DARKNESS");
SetAllAoEInts(SPELL_DARKNESS, oAoE, PRCGetSpellSaveDC(SPELL_DARKNESS, SPELL_SCHOOL_EVOCATION), 0, nCasterLevel);
}
// Ground casting or creatures with no equipment - location-based AOE
else if(GetObjectType(oTarget) != OBJECT_TYPE_CREATURE || !GetIsObjectValid(oItemTarget))
{
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAOE, PRCGetSpellTargetLocation(), fDuration);
object oAoE = GetAreaOfEffectObject(GetSpellTargetLocation(), "VFX_PER_DARKNESS");
SetAllAoEInts(SPELL_DARKNESS, oAoE, PRCGetSpellSaveDC(SPELL_DARKNESS, SPELL_SCHOOL_EVOCATION), 0, nCasterLevel);
}
// Valid item found on creature - apply item property
else
{
if(DEBUG) DoDebug("Darkness: Applying IP to " + DebugObject2Str(oItemTarget));
itemproperty ipDarkness = ItemPropertyAreaOfEffect(IP_CONST_AOE_DARKNESS, nCasterLevel);
IPSafeAddItemProperty(oItemTarget, ipDarkness, fDuration);
if(DEBUG) DoDebug("Darkness: IP applied");
DelayCommand(0.1, VoidCheckPRCLimitations(oItemTarget, OBJECT_INVALID));
}
}
return iAttackRoll; //return TRUE if spell charges should be decremented
}
void main()
{
if(!X2PreSpellCastCode()) return;
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
object oCaster = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
int nCasterLevel = PRCGetCasterLevel(oCaster);
int nEvent = GetLocalInt(oCaster, PRC_SPELL_EVENT); //use bitwise & to extract flags
if(!nEvent) //normal cast
{
if(GetLocalInt(oCaster, PRC_SPELL_HOLD) && oCaster == oTarget)
{ //holding the charge, casting spell on self
SetLocalSpellVariables(oCaster, 1); //change 1 to number of charges
return;
}
DoSpell(oCaster, oTarget, nCasterLevel);
}
else
{
if(nEvent & PRC_SPELL_EVENT_ATTACK)
{
if(DoSpell(oCaster, oTarget, nCasterLevel))
DecrementSpellCharges(oCaster);
}
}
PRCSetSchool();
}