/* nw_s0_healharm Heal/Harm in the one script By: Flaming_Sword Created: Jun 14, 2006 Modified: Nov 21, 2006 Consolidation of heal/harm scripts Mass Heal vfx on target looks like heal added greater harm, mass harm */ #include "prc_sp_func" #include "prc_inc_sp_tch" #include "prc_inc_function" #include "prc_add_spell_dc" #include "inc_dispel" //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 nSpellID) { int bIsHeal = IsHeal(nSpellID); //whether it is a heal or harm spell int bMass = IsMassHealHarm(nSpellID); int nCasterLevel = PRCGetCasterLevel(oCaster); int nMetaMagic = PRCGetMetaMagicFeat(); int nHealVFX, nHurtVFX, nEnergyType, nDice, iBlastFaith, nHeal; float fRadius; string nSwitch; int nCap = 150; if(bIsHeal) { nHealVFX = VFX_IMP_HEALING_X; nHurtVFX = VFX_IMP_SUNSTRIKE; nEnergyType = DAMAGE_TYPE_POSITIVE; nSwitch = PRC_BIOWARE_HEAL; fRadius = RADIUS_SIZE_COLOSSAL; if(nSpellID == SPELL_MASS_HEAL) { nSwitch = PRC_BIOWARE_MASS_HEAL; nCap = 250; } } else { nHealVFX = VFX_IMP_HEALING_G; nHurtVFX = 246; nEnergyType = DAMAGE_TYPE_NEGATIVE; nSwitch = PRC_BIOWARE_HARM; fRadius = RADIUS_SIZE_HUGE; } int iHeal; int iAttackRoll = 1; if((nSpellID == SPELL_MASS_HARM) || (nSpellID == SPELL_GREATER_HARM)) { nDice = (nCasterLevel > 20) ? 20 : nCasterLevel; nHeal = d12(nDice); if((nMetaMagic & METAMAGIC_MAXIMIZE) || BlastInfidelOrFaithHeal(oCaster, oTarget, nEnergyType, TRUE)) nHeal = 12 * nDice; //in case higher level spell slots are available } else { nHeal = 10 * nCasterLevel; } if(nHeal > nCap && !GetPRCSwitch(nSwitch)) nHeal = nCap; location lLoc; if(bMass) { lLoc = (nSpellID == SPELL_MASS_HARM) ? GetLocation(oCaster) : PRCGetSpellTargetLocation(); oTarget = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lLoc); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(bIsHeal ? VFX_FNF_LOS_HOLY_30 : VFX_FNF_LOS_EVIL_20), lLoc); } float fDelay = 0.0; while(GetIsObjectValid(oTarget)) { if(bMass) fDelay = PRCGetRandomDelay(); int iTombTainted = GetHasFeat(FEAT_TOMB_TAINTED_SOUL, oTarget) && GetAlignmentGoodEvil(oTarget) != ALIGNMENT_GOOD; iHeal = GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && ((!bIsHeal && (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD || iTombTainted)) || (bIsHeal && MyPRCGetRacialType(oTarget) != RACIAL_TYPE_UNDEAD && !iTombTainted)); if (GetLocalInt(oTarget, "AcererakHealing")) iHeal = TRUE; if(iHeal && (spellsIsTarget(oTarget, SPELL_TARGET_ALLALLIES, oCaster) || (GetIsDead(oTarget) && (GetCurrentHitPoints(oTarget) > -10)))) { SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellID, FALSE)); //Warforged are only healed for half, none if they have Improved Fortification if(GetIsWarforged(oTarget)) nHeal /= 2; if(GetHasFeat(FEAT_IMPROVED_FORTIFICATION, oTarget)) nHeal = 0; DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(nHeal, oTarget), oTarget)); DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nHealVFX), oTarget)); // Code for FB to remove damage that would be caused at end of Frenzy SetLocalInt(oTarget, "PC_Damage", 0); } else if((GetObjectType(oTarget) != OBJECT_TYPE_CREATURE && !bIsHeal) || (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE && !iHeal)) { if(!GetIsReactionTypeFriendly(oTarget) && oTarget != oCaster) { SignalEvent(oTarget, EventSpellCastAt(oCaster, nSpellID)); iAttackRoll = PRCDoMeleeTouchAttack(oTarget); if(iAttackRoll) { if (!PRCDoResistSpell(oCaster, oTarget, nCasterLevel + SPGetPenetr())) { int nModify = d4(); iBlastFaith = BlastInfidelOrFaithHeal(oCaster, oTarget, nEnergyType, TRUE); if((nMetaMagic & METAMAGIC_MAXIMIZE) || iBlastFaith) { nModify = 1; } if((nSpellID == SPELL_MASS_HARM) || (nSpellID == SPELL_GREATER_HARM)) { nHeal = d12(nDice); if((nMetaMagic & METAMAGIC_MAXIMIZE) || iBlastFaith) nHeal = 12 * nDice; nHeal += SpellDamagePerDice(oCaster, nDice); } else { nHeal = 10 * nCasterLevel; } if(nHeal > nCap && !GetPRCSwitch(nSwitch)) nHeal = nCap; if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, OBJECT_SELF))) { nHeal /= 2; if (GetHasMettle(oTarget, SAVING_THROW_WILL)) // Ignores partial effects nHeal = 0; } int nHP = GetCurrentHitPoints(oTarget); if (nHeal > nHP - nModify) nHeal = nHP - nModify; DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, nHeal, nEnergyType), oTarget)); DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nHurtVFX), oTarget)); } } } } if(!bMass) break; oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lLoc); } //Spell Removal Check SpellRemovalCheck(oCaster, oTarget); return iAttackRoll; //return TRUE if spell charges should be decremented } void main() { if (DEBUG) DoDebug("nw_s0_healharm running "+IntToString(GetIsPC(OBJECT_SELF))); int nSpellID = PRCGetSpellId(); PRCSetSchool(GetSpellSchool(nSpellID)); // If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell if(X2PreSpellCastCode()) { object oCaster = OBJECT_SELF; object oTarget = PRCGetSpellTargetObject(); int nEvent = GetLocalInt(oCaster, PRC_SPELL_EVENT); //use bitwise & to extract flags if(!nEvent) //normal cast { if (DEBUG )DoDebug("nw_s0_healharm running normal casting"); if(IsTouchSpell(nSpellID) && GetLocalInt(oCaster, PRC_SPELL_HOLD) && oCaster == oTarget) { //holding the charge, casting spell on self SetLocalSpellVariables(oCaster, 1); //change 1 to number of charges if (DEBUG) DoDebug("nw_s0_healharm running returning"); return; } if (DEBUG) DoDebug("nw_s0_healharm running DoSpell"); DoSpell(oCaster, oTarget, nSpellID); } else { if (DEBUG) DoDebug("nw_s0_healharm running else casting"); if(nEvent & PRC_SPELL_EVENT_ATTACK) { if(DoSpell(oCaster, oTarget, nSpellID)) DecrementSpellCharges(oCaster); } } } PRCSetSchool(); }