//:://///////////////////////////////////////////// //:: 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 //::////////////////////////////////////////////// //:: MODIFIED MARCH 5 2003 for Blackguards //:: MODIFIED JULY 24 2003 for Planar Turning to include turn resistance hd //:: Modified November 29, 2003 for Evil Cleric Rebuke/Command by Wes Baran //:: Modified December 29, 2003 for 1.61 patch // Checks to see if an evil cleric has control 'slots' to command // the specified undead // if TRUE, the cleric has enough levels of control to control the undead // if FALSE, the cleric will rebuke the undead instead // Checks to see if an evil cleric has control 'slots' to command // the specified undead // if TRUE, the cleric has enough levels of control to control the undead // if FALSE, the cleric will rebuke the undead instead int CanCommand(int nClassLevel, int nTargetHD) { int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots"); int nNew = nSlots + nTargetHD; //FloatingTextStringOnCreature("The variable is " + IntToString(nSlots), OBJECT_SELF); if(nClassLevel >= nNew) { return TRUE; } return FALSE; } void AddCommand(int nTargetHD) { int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots"); SetLocalInt(OBJECT_SELF, "wb_clr_comm_slots", nSlots + nTargetHD); } void SubCommand(int nTargetHD) { int nSlots = GetLocalInt(OBJECT_SELF, "wb_clr_comm_slots"); SetLocalInt(OBJECT_SELF, "wb_clr_comm_slots", nSlots - nTargetHD); } void RebukeUndead(int nTurnLevel, int nTurnHD, int nVermin, int nElemental, int nConstructs, int nOutsider, int nClassLevel, int nPlanar) { //Gets all creatures in a 20m radius around the caster and rebukes them or not. If the creatures //HD are 1/2 or less of the nClassLevel then the creature is commanded (dominated). int nCnt = 1; int nHD, nRacial, nHDCount, bValid, nDamage; nHDCount = 0; effect eVis = EffectVisualEffect(VFX_IMP_PULSE_NEGATIVE); effect eVisTurn = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DOMINATED); effect eDamage; effect eTurned = EffectCutsceneParalyze(); effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE); effect eLink = EffectLinkEffects(eVisTurn, eTurned); eLink = EffectLinkEffects(eLink, eDur); effect eDeath = SupernaturalEffect(EffectCutsceneDominated()); effect eDomin = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_NEGATIVE); effect eDeathLink = EffectLinkEffects(eDeath, eDomin); effect eImpactVis = EffectVisualEffect(VFX_FNF_LOS_EVIL_30); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpactVis, GetLocation(OBJECT_SELF)); //Get nearest enemy within 20m (60ft) //Why are you using GetNearest instead of GetFirstObjectInShape // Because ability description says "gets closest first" :P object oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC , OBJECT_SELF, nCnt); while(GetIsObjectValid(oTarget) && nHDCount < nTurnHD && GetDistanceToObject(oTarget) <= 20.0) { if(!GetIsFriend(oTarget)) { nHD = GetHitDice(oTarget) + GetTurnResistanceHD(oTarget); nRacial = GetRacialType(oTarget); if (nRacial == RACIAL_TYPE_OUTSIDER ) { if (nPlanar) { //Planar turning decreases spell resistance against turning by 1/2 nHD = GetHitDice(oTarget) + (GetSpellResistance(oTarget) /2) + GetTurnResistanceHD(oTarget); } else { nHD = GetHitDice(oTarget) + (GetSpellResistance(oTarget) + GetTurnResistanceHD(oTarget) ); } } else //(full turn resistance) { nHD = GetHitDice(oTarget) + GetTurnResistanceHD(oTarget); } if(nHD <= nTurnLevel && nHD <= (nTurnHD - nHDCount)) { //Check the various domain turning types if(nRacial == RACIAL_TYPE_UNDEAD) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_VERMIN && nVermin > 0) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_ELEMENTAL && nElemental > 0) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_CONSTRUCT && nConstructs > 0) { SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); nDamage = d3(nTurnLevel); eDamage = EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget); nHDCount += nHD; } else if (nRacial == RACIAL_TYPE_OUTSIDER && nOutsider > 0) { bValid = TRUE; } //Apply results of the turn if( bValid == TRUE) { ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); //if(IntToFloat(nClassLevel)/2.0 >= IntToFloat(nHD)) //{ if((nClassLevel/2) >= nHD && CanCommand(nClassLevel, nHD)) { //Fire cast spell at event for the specified target SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); //Destroy the target DelayCommand(0.1f, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDeathLink, oTarget, RoundsToSeconds(nClassLevel + 5))); //AssignCommand(oTarget, ClearAllActions()); //SetIsTemporaryFriend(oTarget, OBJECT_SELF, TRUE, RoundsToSeconds(nClassLevel + 5)); AddCommand(nHD); DelayCommand(RoundsToSeconds(nClassLevel + 5), SubCommand(nHD)); } else { //Turn the target //Fire cast spell at event for the specified target SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); //AssignCommand(oTarget, ActionMoveAwayFromObject(OBJECT_SELF, TRUE)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nClassLevel + 5)); } nHDCount = nHDCount + nHD; } } bValid = FALSE; } nCnt++; oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF, nCnt); } } void TurnUndead(int nTurnLevel, int nTurnHD, int nVermin, int nElemental, int nConstructs, int nOutsider, int nClassLevel, int nPlanar) { //Gets all creatures in a 20m radius around the caster and turns them or not. If the creatures //HD are 1/2 or less of the nClassLevel then the creature is destroyed. int nCnt = 1; int nHD, nRacial, nHDCount, bValid, nDamage; nHDCount = 0; effect eVis = EffectVisualEffect(VFX_IMP_SUNSTRIKE); effect eVisTurn = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_FEAR); effect eDamage; effect eTurned = EffectTurned(); effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE); effect eLink = EffectLinkEffects(eVisTurn, eTurned); eLink = EffectLinkEffects(eLink, eDur); effect eDeath = SupernaturalEffect(EffectDeath(TRUE)); effect eImpactVis = EffectVisualEffect(VFX_FNF_LOS_HOLY_30); ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpactVis, GetLocation(OBJECT_SELF)); //Get nearest enemy within 20m (60ft) //Why are you using GetNearest instead of GetFirstObjectInShape // Because ability description says "gets closest first" :P object oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC , OBJECT_SELF, nCnt); while(GetIsObjectValid(oTarget) && nHDCount < nTurnHD && GetDistanceToObject(oTarget) <= 20.0) { if(!GetIsFriend(oTarget)) { nHD = GetHitDice(oTarget) + GetTurnResistanceHD(oTarget); nRacial = GetRacialType(oTarget); if (nRacial == RACIAL_TYPE_OUTSIDER ) { if (nPlanar) { //Planar turning decreases spell resistance against turning by 1/2 nHD = GetHitDice(oTarget) + (GetSpellResistance(oTarget) /2) + GetTurnResistanceHD(oTarget); } else { nHD = GetHitDice(oTarget) + (GetSpellResistance(oTarget) + GetTurnResistanceHD(oTarget) ); } } else //(full turn resistance) { nHD = GetHitDice(oTarget) + GetTurnResistanceHD(oTarget); } if(nHD <= nTurnLevel && nHD <= (nTurnHD - nHDCount)) { //Check the various domain turning types if(nRacial == RACIAL_TYPE_UNDEAD) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_VERMIN && nVermin > 0) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_ELEMENTAL && nElemental > 0) { bValid = TRUE; } else if (nRacial == RACIAL_TYPE_CONSTRUCT && nConstructs > 0) { SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); nDamage = d3(nTurnLevel); eDamage = EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget); nHDCount += nHD; } else if (nRacial == RACIAL_TYPE_OUTSIDER && nOutsider > 0) { bValid = TRUE; } //Apply results of the turn if( bValid == TRUE) { ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget); //if(IntToFloat(nClassLevel)/2.0 >= IntToFloat(nHD)) //{ if((nClassLevel/2) >= nHD) { //Fire cast spell at event for the specified target SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); //Destroy the target DelayCommand(0.1f, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDeath, oTarget)); } else { //Turn the target //Fire cast spell at event for the specified target SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELLABILITY_TURN_UNDEAD)); AssignCommand(oTarget, ActionMoveAwayFromObject(OBJECT_SELF, TRUE)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, RoundsToSeconds(nClassLevel + 5)); } nHDCount = nHDCount + nHD; } } bValid = FALSE; } nCnt++; oTarget = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_NOT_PC, OBJECT_SELF, nCnt); } } void main() { int nClericLevel = GetLevelByClass(CLASS_TYPE_CLERIC); int nPaladinLevel = GetLevelByClass(CLASS_TYPE_PALADIN); int nBlackguardlevel = GetLevelByClass(CLASS_TYPE_BLACKGUARD); int nTotalLevel = GetHitDice(OBJECT_SELF); int nTurnLevel = nClericLevel; int nClassLevel = nClericLevel; // GZ: Since paladin levels stack when turning, blackguard levels should stack as well // GZ: but not with the paladin levels (thus else if). if((nBlackguardlevel - 2) > 0 && (nBlackguardlevel > nPaladinLevel)) { nClassLevel += (nBlackguardlevel - 2); nTurnLevel += (nBlackguardlevel - 2); } else if((nPaladinLevel - 2) > 0) { nClassLevel += (nPaladinLevel -2); nTurnLevel += (nPaladinLevel - 2); } //Flags for bonus turning types int nElemental = GetHasFeat(FEAT_AIR_DOMAIN_POWER) + GetHasFeat(FEAT_EARTH_DOMAIN_POWER) + GetHasFeat(FEAT_FIRE_DOMAIN_POWER) + GetHasFeat(FEAT_WATER_DOMAIN_POWER); int nVermin = GetHasFeat(FEAT_PLANT_DOMAIN_POWER) + GetHasFeat(FEAT_ANIMAL_COMPANION); int nConstructs = GetHasFeat(FEAT_DESTRUCTION_DOMAIN_POWER); int nOutsider = GetHasFeat(FEAT_GOOD_DOMAIN_POWER) + GetHasFeat(FEAT_EVIL_DOMAIN_POWER); int nPlanar = GetHasFeat(854); //Flag for improved turning ability int nSun = GetHasFeat(FEAT_SUN_DOMAIN_POWER); //Make a turning check roll, modify if have the Sun Domain int nChrMod = GetAbilityModifier(ABILITY_CHARISMA); int nTurnCheck = d20() + nChrMod; //The roll to apply to the max HD of undead that can be turned --> nTurnLevel int nTurnHD = d6(2) + nChrMod + nClassLevel; //The number of HD of undead that can be turned. if(nSun == TRUE) { nTurnCheck += d4(); nTurnHD += d6(); } //Determine the maximum HD of the undead that can be turned. if(nTurnCheck <= 0) { nTurnLevel -= 4; } else if(nTurnCheck >= 1 && nTurnCheck <= 3) { nTurnLevel -= 3; } else if(nTurnCheck >= 4 && nTurnCheck <= 6) { nTurnLevel -= 2; } else if(nTurnCheck >= 7 && nTurnCheck <= 9) { nTurnLevel -= 1; } else if(nTurnCheck >= 10 && nTurnCheck <= 12) { //Stays the same } else if(nTurnCheck >= 13 && nTurnCheck <= 15) { nTurnLevel += 1; } else if(nTurnCheck >= 16 && nTurnCheck <= 18) { nTurnLevel += 2; } else if(nTurnCheck >= 19 && nTurnCheck <= 21) { nTurnLevel += 3; } else if(nTurnCheck >= 22) { nTurnLevel += 4; } int nAlign = GetAlignmentGoodEvil(OBJECT_SELF); if(nAlign == ALIGNMENT_EVIL) { RebukeUndead(nTurnLevel, nTurnHD, nVermin, nElemental, nConstructs, nOutsider, nClassLevel, nPlanar); } else { TurnUndead(nTurnLevel, nTurnHD, nVermin, nElemental, nConstructs, nOutsider, nClassLevel, nPlanar); } }