DMH-Online

Dungeon Masters Helper · Est. 2005

Spells Scripts

NWN Script: detect_evil.htm

Author It is here! Big E's Detect Evil Version 1.0
BigE Posted: Tuesday, 23 July 05:49PM
This first version works for creatures only. I haven't yet figured out how to get an alignment out of an item. I also haven't implemented any line of sight rules yet. This works using a 60ft (18 Metre) diameter range.

The first four functions are helpers for the actual Detect_Evil procedure.

I tried to keep it as close to the 3E Player's Handbook description as possible, but took some liberties in implementation. Particularly with the aura strength and the stun feature. I just decided that if the GoodEvil value of the creature was in the highest range, that was good enough to stun the caster if they are of a good alignment.

Other than that, it is pretty true to the actual spell. Round 1 shows presence of evil.
Round 2 shows the number of evil creatures and the strongest aura. If the strongest aura is overwhelming and the caster is of a good alignment, they are stunned for a round.
Round 3 shows the exact location of each aura using a distance and compass heading from the caster.

Feel free to make changes, but please keep my name on it

I'll post this in the sticky as well.

-E

NWScript:
//Author: Big E
//Date:   July 20, 2002
//Return a string describing the strength of the evil
string AuraPower(int iEvilPoints)
    {
    /*
      Given the GoodEvil value, return the aura strength.
      100 Good, 0 Evil
    */
    if((iEvilPoints <= 49) && (iEvilPoints >=  36))
        return "Faint";
    if((iEvilPoints <= 35) && (iEvilPoints >=  24))
        return "Moderate";
    if((iEvilPoints <= 23) && (iEvilPoints >=  12))
        return "Strong";
    if((iEvilPoints <= 11) && (iEvilPoints >=  0))
        return "Overwhelming";
    return "None";
    }
/*
  Author: Big E
  Date:   July 20, 2002
  Given the facing value (0-360), set the compass direction and diplay
  the loction and distance of the evil.
*/
void GetDirection(float fFacing,object oCaster,object oCreature, float nDistance)
    {
    //Correct the bug in GetFacing
    if (fFacing >= 360.0)
        fFacing  =  720.0 - fFacing;
    if (fFacing <    0.0)
        fFacing += (360.0);
    int iFacing = FloatToInt(fFacing);
    /*
      359 -  2  = E
        3 - 45  = NEE
       46 - 87  = NNE
       88 - 92  = N
       93 - 135 = NNW
      136 - 177 = NWW
      178 - 182 = W
      183 - 225 = SWW
      226 - 267 = SSW
      268 - 272 = S
      273 - 315 = SSE
      316 - 358 = SEE
    */
    string sDirection = "";
    if((iFacing >= 359) && (iFacing <=   2))
        sDirection = "E";
    if((iFacing >=   3) && (iFacing <=  45))
        sDirection = "NEE";
    if((iFacing >=  46) && (iFacing <=  87))
        sDirection = "NNE";
    if((iFacing >=  88) && (iFacing <=  92))
        sDirection = "N";
    if((iFacing >=  93) && (iFacing <= 135))
        sDirection = "NNW";
    if((iFacing >= 136) && (iFacing <= 177))
        sDirection = "NWW";
    if((iFacing >= 178) && (iFacing <= 182))
        sDirection = "W";
    if((iFacing >= 183) && (iFacing <= 225))
        sDirection = "SWW";
    if((iFacing >= 226) && (iFacing <= 267))
        sDirection = "SSW";
    if((iFacing >= 268) && (iFacing <= 272))
        sDirection = "S";
    if((iFacing >= 273) && (iFacing <= 315))
        sDirection = "SSE";
    if((iFacing >= 316) && (iFacing <= 358))
        sDirection = "SEE";
    string sDistance = FloatToString(nDistance);
    //Evil Power
    string sEvil = AuraPower(GetGoodEvilValue(oCreature));
    SendMessageToPC(oCaster, sEvil + " evil detected " + sDistance + " metres to the " + sDirection);
    }
//Author: Big E
//Date:   July 20, 2002
object GetNearest(object oCaster, int iCount)
    {
    return GetNearestObjectToLocation(OBJECT_TYPE_CREATURE,GetLocation(oCaster),iCount);
    }
//Author: Big E
//Date:   July 20, 2002
//Detect Evil By Round
void Detect_Evil_By_Round(object oCaster,int iRound)
    {
    float RANGE              =  18.0;  //Range in metres
    int MIN_EVIL             =  49;    //The number at which the evil outweighs the good
    int iEvilCreatureCount   =  0;     //The number of evil auras in range
    int iMostEvil            =  0;     //The lowest GoodEvil value
    int iCount               =  1;     //A counter to cycle through creatures
    float nDistance          =  0.0;   //The distance away from the caster of the creature
    string sDistance         =  "";    //String version of nDistance
    string sEvil             =  "";    //Aura strength
    int bEvilDetected        =  FALSE; //Evil found?
    location lCreature;                //Location of the creature
    vector vCreature;                  //Vector location of the creature
    //Get the location of the caster
    location lCaster = GetLocation(oCaster);
    //Get the first closest creature to the caster
    object oCreature = GetNearest(oCaster,iCount);
    while((GetIsObjectValid(oCreature)) && (GetDistanceBetween(oCaster,oCreature) <= RANGE))
        {
        nDistance = GetDistanceBetween(oCaster,oCreature);
        if(GetGoodEvilValue(oCreature) >= MIN_EVIL) //Not Evil
            {
            //Go on to the next creature
            iCount++;
            oCreature = GetNearest(oCaster,iCount);
            continue;
            }
        bEvilDetected = TRUE; //Evil found
        lCreature = GetLocation(oCreature);
        //Round 1 - Evil presence detected
        if (iRound == 1)
            {
            if(GetLocation(oCaster) != GetLocalLocation(oCaster,"lPlayer"))
                {
                SendMessageToPC(oCaster, "Concentration broken.  Detect evil cancelled.");
                ClearAllActions();
                return;
                };
            SendMessageToPC(oCaster,"There is evil present.");
            return;
            }
        //Round 2 - Number of evil aura's
        if(iRound == 2)
            {
            if(GetLocation(oCaster) != GetLocalLocation(oCaster,"lPlayer"))
                {
                SendMessageToPC(oCaster, "Concentration broken.  Detect evil cancelled.");
                ClearAllActions();
                return;
                };
            iEvilCreatureCount++;
            if(GetGoodEvilValue(oCreature) > iMostEvil)
                iMostEvil = GetGoodEvilValue(oCreature);
            }
        //Round 3
        if(iRound == 3)
            {
            if(GetLocation(oCaster) != GetLocalLocation(oCaster,"lPlayer"))
                {
                SendMessageToPC(oCaster, "Concentration broken.  Detect evil cancelled.");
                ClearAllActions();
                return;
                };
            //Get the creature's vector
            vCreature = GetPosition(oCreature);
            //Face the creature
            AssignCommand(oCaster,SetFacingPoint (vCreature));
            //Get the compass direction of the creature
            AssignCommand(oCaster,GetDirection(GetFacing(oCaster),oCaster,oCreature,nDistance));
            }
        iCount++;
        oCreature = GetNearest(oCaster,iCount);
        }
    if((iRound == 2) && (bEvilDetected))
        {
        SendMessageToPC(oCaster,"There are " + IntToString(iEvilCreatureCount) + " evil creatures present.");
        if(iMostEvil <= 11)
            {
            //If the caster is good, they are stunned by the overwhelming evil
            if(GetAlignmentGoodEvil(oCaster)==ALIGNMENT_GOOD)
                {
                SendMessageToPC(oCaster,"The most evil is so " + AuraPower(iMostEvil) + " that you are mementarily stunned!");
                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectStunned(),oCaster,ROUND);
                AssignCommand(oCaster,ActionWait(ROUND));
                }
            }
        else
            SendMessageToPC(oCaster,"The most evil is " + AuraPower(iMostEvil));
        return;
        }
    }
//Author: Big E
//Date:   July 20, 2002
void Detect_Evil(object oCaster)
    {
    SetLocalLocation(oCaster,"lPlayer",GetLocation(oCaster));
    DelayCommand(ROUND,AssignCommand(oCaster,Detect_Evil_By_Round(oCaster,1)));
    DelayCommand(ROUND+ROUND,AssignCommand(oCaster,Detect_Evil_By_Round(oCaster,2)));
    DelayCommand(ROUND+ROUND+ROUND,AssignCommand(oCaster,Detect_Evil_By_Round(oCaster,3)));
    }

//Example using a ring of detect evil for event OnActivateItem
float ROUND = 6.0; //Need this defined.  I use a six second round
void main()
    {
    object oActivated = GetItemActivated();
    object oPlayer = GetItemPossessor(oActivated);
    if(GetName(oActivated) == "Ring of Detect Evil")
        Detect_Evil(oPlayer);
    }
⌂ All Scripts 👁 Category List

All Spells Scripts

📄 detect_evil