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

    }