Author Topic: Triggering Encounters OnEnter for an Area  (Read 379 times)

Legacy_WoC_Builder

  • Sr. Member
  • ****
  • Posts: 425
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« on: November 26, 2011, 06:50:09 am »


               Is there any way to do this?  I was reading some lag pointers in the Lexicon, and they mentioned not having any placed creatures, but populate your areas with encounters.  However, sometimes there are small areas, and you don't want the NPC's popping up in plain sight.

So, this led me to wonder if you can do it with an OnEnter script for an area, but with encounters, all I see are set and get calls, but nothing that would let me fire one remotely, so to speak.

I would even do it via a PC opening a door if I could.

So, any ideas?

thanks '<img'>
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #1 on: November 26, 2011, 07:59:05 am »


               

WoC_Builder wrote...

Is there any way to do this?  I was reading some lag pointers in the Lexicon, and they mentioned not having any placed creatures, but populate your areas with encounters.  However, sometimes there are small areas, and you don't want the NPC's popping up in plain sight.

So, this led me to wonder if you can do it with an OnEnter script for an area, but with encounters, all I see are set and get calls, but nothing that would let me fire one remotely, so to speak.

I would even do it via a PC opening a door if I could.

So, any ideas?

thanks '<img'>


I haven't looked into this, but SetEncounterActive() (used in the Area's On-Enter) may be what you are looking for, with the encounter area encompassing the entry point for a triggering creature.  Have the triggering creature created and then destroyed with a short delay, setting the encounter back to inactive.
               
               

               


                     Modifié par WhiZard, 26 novembre 2011 - 08:05 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #2 on: November 26, 2011, 08:26:51 am »


                 Here's a quickie variable driven one I just made up for areas or doors.  It compiles, but I haven't tested it yet.  No reason it shouldn't work though.

// Variables used:  These go either on the area or door the script is attached to.
// "CREATURE_NUMBER", "WP_NUMBER" - int - not needed if there's only 1,
// as it goes from 0 up.  Equals number of creature resrefs or waypoints - 1.
// "WP_BASE" - string base tag name of waypoints, not counting the 0 - ...
// Added.  Example base:  "WP_FROZENHELL_", first WP tag would be "WP_FROZENHELL_0"
// "CREATURE_*" - String.  CREATURE_0 to CREATURE_... (No scripted upper limit.)
// The creature ResRef to create is set here.
// "CHALLENGE_MODIFIER" - int - 1 to ... (No scripted upper limit, but likely
// anything over 10 could create far too many with a high level character.
// If not set defaults to 1.
// "SPAWNED" - int - Set to TRUE on any creature spawned by this script.
// This makes it easier to despawn only these particular creatures from the
// areas on exit script.
void main()
{
 object oPC = GetEnteringObject();
 if (!GetIsPC (oPC)) return;
 int nCreature  = GetLocalInt (OBJECT_SELF, "CREATURE_NUMBER");
 int nWP        = GetLocalInt (OBJECT_SELF, "WP_NUMBER");
 string sBaseWP = GetLocalString (OBJECT_SELF, "WP_BASE");
 int nMod = GetLocalInt (OBJECT_SELF, "CHALLENGE_MODIFIER");
 if (nMod <= 0) nMod = 1;
 // This could also be done using GetFactionAverageLevel (oPC)
 int nHD = GetHitDice (oPC) * nMod;
 int nTestHD;
 string sCreature, sWP;
 object oCreature;
 while (nHD > 0)
    {
     sCreature = "CREATURE_" + IntToString (Random (nCreature));
     sWP       = sBaseWP     + IntToString (Random (nWP));
     oCreature = CreateObject (OBJECT_TYPE_CREATURE, sCreature, GetLocation (GetObjectByTag (sWP)));
     SetLocalInt (oCreature, "SPAWNED", TRUE);
     nTestHD   = GetHitDice (oCreature);
     // A sanity check of sorts, ensuring that the count decrements regardless
     // to prevent a TMI error.
     if (!nTestHD) nTestHD = 1;
     nHD -= nTestHD;
    }
}
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #3 on: November 26, 2011, 03:22:53 pm »


               This is my random spawn method:
http://nwvault.ign.c....Detail&id=3318

It's prettty simple and mainly just a template for creating your own scripts, though you could simply plug in your own monsters at the most rudimentary level.  More complex/complete systems such as Aman Shader's and NESS are on the vault.
               
               

               


                     Modifié par ffbj, 26 novembre 2011 - 03:24 .
                     
                  


            

Legacy_WoC_Builder

  • Sr. Member
  • ****
  • Posts: 425
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #4 on: November 27, 2011, 03:16:10 am »


               I think I need to clarify one thing.  This is not for random spawns of a like group of creatures, or spawning at one location.  This is to place the inhabitants of a cityscape, or say a tavern.  I want to place almost all NPC's at individual  spawn points, as that is where they need to be.
               
               

               
            

Legacy_henesua

  • Hero Member
  • *****
  • Posts: 6519
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #5 on: November 27, 2011, 03:27:06 am »


               Sounds like NESS is what you need.
               
               

               
            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #6 on: December 03, 2011, 01:36:27 am »


               If it's a specific list of NPC's such as "Barkeep" and "Waitress" and "TavernGuy1", "TavernGuy2", "TavernGirl1", etc...

Here's the quickest and easiest custom system I can think of. NESS is great, but it may be a bit overkill for something like this.


Create a custom waypoint. Give it a unique tag such as "MySpawnPoint".

Place a MySpawnPoint wp at each spot that you want someone to be spawned at.

Edit each of the wp's and add a string variable named something like "SpawnTemplate".

Set the SpawnTemplate string to the ResRef of the NPC that you want spawned at that location.

In the AreaEnter script, add a short block of code that cycles through each wp in the area with the MySpawnPoint tag and creates whatever ResRef is stored in its SpawnTemplate variable at the wp's location.


I'm at work right now, but let me know if you want to give something like that a shot. I can make you a working example if you need.
               
               

               


                     Modifié par wyldhunt1, 03 décembre 2011 - 01:41 .
                     
                  


            

Legacy_WoC_Builder

  • Sr. Member
  • ****
  • Posts: 425
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #7 on: February 21, 2012, 05:24:37 am »


               

wyldhunt1 wrote...

If it's a specific list of NPC's such as "Barkeep" and "Waitress" and "TavernGuy1", "TavernGuy2", "TavernGirl1", etc...

Here's the quickest and easiest custom system I can think of. NESS is great, but it may be a bit overkill for something like this.


Create a custom waypoint. Give it a unique tag such as "MySpawnPoint".

Place a MySpawnPoint wp at each spot that you want someone to be spawned at.

Edit each of the wp's and add a string variable named something like "SpawnTemplate".

Set the SpawnTemplate string to the ResRef of the NPC that you want spawned at that location.

In the AreaEnter script, add a short block of code that cycles through each wp in the area with the MySpawnPoint tag and creates whatever ResRef is stored in its SpawnTemplate variable at the wp's location.


I'm at work right now, but let me know if you want to give something like that a shot. I can make you a working example if you need.


Sorry, but just getting back to this.  If you are still game, of course I'd love the help!  '<img'>  If you can work up an on_exit counterpart to remove said creatures as well that would be fantastic.

And thank you very much!  '<img'>
               
               

               
            

Legacy_Tyndrel

  • Sr. Member
  • ****
  • Posts: 313
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #8 on: February 21, 2012, 07:35:23 am »


               Have you looked at "Killer Pub People" by Axe Murderer? 
               
               

               
            

Legacy_Birdman076

  • Sr. Member
  • ****
  • Posts: 320
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #9 on: February 21, 2012, 02:18:37 pm »


               This is what I use for OnEnter of an area hopefully the forums don't hammer the code, if they do i'll post them as .txt files for ease of use.

// -------------------------------------------------------------------------- //
//
// Script:  area_enter
//
// Use:     Re-spawns NPCs in area where it is used in the onEnter event.
//
// Created: 07.22.09
//
// Variables used in the properties of the area you use this script:
//
// NPC_TOTAL - How many NPCs should spawn in the area total
// NPC_WP - The waypoint of the NPC you want to spawn in (use NPC_WP0,1,2,3,etc for as many NPC's as you have)
// NPC_TAG - The Tag of the NPC you wish to spawn in (use NPC_TAG0,1,2,3,etc for as many NPCs as you have)
// NPC_RES - The Resref of the NPC you wish to spawn in (use NPC_RES0,1,2,3,etc for as many NPCs as you have)
// iExplore - Set to "1" to explore the area for the player
// -------------------------------------------------------------------------- //
#include "NW_I0_GENERIC"

void doNPCSpawn( object oArea, int iCount );

void main()
{
  object oPC = GetEnteringObject();
  object oArea = GetArea( oPC );

  int iNPCs = GetLocalInt( oArea, "NPC_TOTAL" );  // NPC_TOTAL = how many NPCs should spawn in area
  int iNPCCurrent = GetLocalInt( oArea, "NPC_AMT" ); // Current number of NPCs spawned in, used in while loop next
  int iCount = 0;  // counter to add up in while loop number already spawned by loop

  AssignCommand( oPC, ClearAllActions( TRUE ) );

  if( GetIsPC( oPC ) )
  {

     if( iNPCs > 0 && iNPCCurrent == 0 )
    { //only if its a pc and we have more then zero npcs and we haven't started spawning them yet

      while( iCount < iNPCs )
      {
        DelayCommand( IntToFloat( iCount ) * 0.2, doNPCSpawn( oArea, iCount ) );
        SetLocalInt( oArea, "NPC_AMT", iCount ); // set the local int now so that if another player
        iCount++; //  comes into the area at the time they're spawning we don't start spawning again
      }
   }

 if( GetLocalInt( oArea, "iExplore" ) == 1 ) // if you want the area to be explored
      ExploreAreaForPlayer( oArea, oPC );
      }
  }
  void doNPCSpawn( object oArea, int iCount )
  {
  object oNPC_WP = GetWaypointByTag( GetLocalString( oArea, "NPC_WP" + IntToString( iCount ) ) );
  object oNPC;

  if( !GetIsObjectValid( GetNearestObjectByTag( GetLocalString( oArea, "NPC_TAG" + IntToString( iCount ) ), oNPC_WP ) ) )
    oNPC = CreateObject( OBJECT_TYPE_CREATURE, GetLocalString( oArea, "NPC_RES" + IntToString( iCount ) ), GetLocation( oNPC_WP ), FALSE );

  if( GetIsPostOrWalking( oNPC ) )
    DelayCommand( ( IntToFloat( iCount ) * 0.2 ) + 0.1, AssignCommand( oNPC, WalkWayPoints( FALSE ) ) );
}


This would be for OnExit

//::////////////////////////////////////////////////////////////////////////////
//::
//:: Script Name: npc_clear
//::
//:: Use: This script is used in conjuction with area_enter to clear the NPC's
//:: and trash from the area when the player leaves to reduce overhead on the
//:: system.
//::
//:: Created On: July 27, 2009
//::
//:: Note: This script is meant to be used in conjuction with "area_enter"
//::
//::////////////////////////////////////////////////////////////////////////////

// function removes all objects in inventory then object itself.
void TrashObject(object oObject)
{
     /* search and destroy contents of body bag's, others just destroy */
  if( GetHasInventory( oObject ) )
  {
    object oItem = GetFirstItemInInventory( oObject );

        /* recursively trash all items inside container */
    while( GetIsObjectValid( oItem ) )
    {
      TrashObject( oItem );

      oItem = GetNextItemInInventory( oObject );
    }
  }
  DestroyObject( oObject );
}

void main()
{
  object oPC = GetExitingObject();
  object oArea = OBJECT_SELF;

  // only execute for PC's exiting an area
  if( GetIsPC( oPC ) )
  {
    

  // Start up the loop, setting oPC now to the first PC
    oPC = GetFirstPC();

  // Continue looping until there are no more PCs left
    while( oPC != OBJECT_INVALID )
    {

  // Check the Area against the Area of the current PC, and if they are the same
  // exit the function, as we do not need to check anymore PCs
      if( oArea == GetArea( oPC ) )
        return;

  // If not, continue to the next PC
      else oPC = GetNextPC();
    }

  SetLocalInt( oArea, "NPC_AMT", 0 );

  // If we've made it this far, we know that there aren't any PCs in the area
  // Set oObject to the first object in the Area
    object oObject = GetFirstObjectInArea( oArea );

  // Continue looping until there are no more objects left
    while( oObject != oArea && GetIsObjectValid( oObject ) )
    {
  // Test to see if oObject is a creature spawned from an encounter and if so,
  // destroy the object
      switch( GetObjectType( oObject ) )
      {
        case OBJECT_TYPE_ITEM:
          TrashObject( oObject );
          break;
        case OBJECT_TYPE_PLACEABLE:
          if( GetTag( oObject ) == "BodyBag")
            TrashObject( oObject );
          break;
        case OBJECT_TYPE_CREATURE:
          if( GetMaster( oObject ) == OBJECT_INVALID )
          {
            AssignCommand( oObject, SetIsDestroyable( TRUE, FALSE, FALSE ) );
            TrashObject( oObject );
          }
          break;
        case OBJECT_TYPE_AREA_OF_EFFECT:
          DestroyObject( oObject );
          break;
      }

  // Move on to the next object
      oObject = GetNextObjectInArea( oArea );
    }
  }
}
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #10 on: February 21, 2012, 11:22:45 pm »


               That was likely my tutorial you were reading. We use the following general onenter script in all our areas. It spawns NPCs at locations, specifying resref, tag to set to, and locaation (usually by waypoint tag):


#include "hg_inc"
#include "hg_area_inc"
#include "hg_antiex_inc"
#include "fky_environ_inc"
#include "ac_qstatus_inc"

#include "tsk_inc"

#include "afx_sfunc"

void DoAreaEffects (object oArea, object oPC, int nDamAmount, int nDamType, int nDamVis, string sMessage) {
    if (GetArea(oPC) != oArea)
        return;

    if (!GetIsDead(oPC) && !GetPlotFlag(oPC)) {
        if (nDamType < 0) {
            if (nDamType == -1) {
                int nBreath = GetCanBreatheWater(oPC, TRUE);

                if (nBreath == 2)
                    return;

                if (!nBreath) {
                    if (GetLocalInt(oPC, "Area_WaterBreath_Warning") < 3) {
                        FloatingTextStringOnCreature("You cannot hold your breath much longer!", oPC, FALSE);
                        AddLocalInt(oPC, "Area_WaterBreath_Warning", 1);
                    } else {
                        FloatingTextStringOnCreature("You can no longer hold your breath!", oPC, FALSE);
                        DeleteLocalInt(oPC, "Area_WaterBreath_Warning");

                        ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDeath()), oPC);
                    }
                } else
                    DeleteLocalInt(oPC, "Area_WaterBreath_Warning");
            } else if (nDamType == -2) {
                int nLev = GetCanLevitate(oPC);

                if (nLev == 2)
                    return;

                if (!nLev) {
                    if (!GetIsResting(oPC))
                        FloatingTextStringOnCreature("You are unable to control your motion in the air!", oPC, FALSE);

                    RemoveEffectsOfType(EFFECT_TYPE_CUTSCENEIMMOBILIZE, oPC, oArea);

                    effect eEff = SupernaturalEffect(EffectCutsceneImmobilize());
                    DelayCommand(0.01, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEff, oPC, 9.0));
                }
            } else if (nDamType == -3) {
                /* passwall; do nothing */
                return;
            } else if (nDamType == -4) {
                int nFirewalk = GetCanFirewalk(oPC);

                if (nFirewalk == 2)
                    return;

                if (!nFirewalk) {
                    FloatingTextStringOnCreature("You are unable to breathe elemental fire!", oPC, FALSE);

                    ApplyDirectDamage(oPC, (GetMaxHitPoints(oPC) * 2) / 5, DAMAGE_TYPE_INTERNAL,
                                      DAMAGE_POWER_ENERGY, "Elemental Fire", "You burn to a crisp!");
                    ApplyVisualToObject(VFX_IMP_FLAME_M, oPC);
                }
            }
        } else {
            effect eDam = EffectDamage(d10(nDamAmount), nDamType);
            effect eVis = EffectVisualEffect(nDamVis);

            ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oPC);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);

            if (sMessage != "")
                FloatingTextStringOnCreature(sMessage, oPC, FALSE);
        }
    }
    DelayCommand(6.0, DoAreaEffects(oArea, oPC, nDamAmount, nDamType, nDamVis, sMessage));
}

void DoDust (object oPC, object oItem) {
    SetPlotFlag(oItem, FALSE);
    DestroyObject(oItem);
    CreateItemOnObject("drowdust", oPC);
}

object GetVFXLoopTarget (object oSource, string sTarget) {
    int nCount = 1;
    struct SubString ss = GetFirstSubString(sTarget, "#");

    if (ss.rest != "") {
    }

    return GetNearestObjectByTag(ss.first, oSource, nCount);
}

float GetVFXLoopVaryingFloat (float fRand) {
    int nVary = FloatToInt(fRand * 100.0);
    nVary = Random((nVary * 2) + 1) - nVary;

    return (nVary * 0.01);
}

void VoidBroadcastProjectileToObject (object oSource, object oTarget, int nSpellId, int nDelay) {
    BroadcastProjectileToObject(oSource, oTarget, nSpellId, nDelay);
}

void DoVFXLoop (object oVFX, int nVis, float fCyc, float fDur, string sTarget, int bBeam,
                float fCycRand, float fDurRand, int nMulti, float fMultiInt, float fMultiRand) {
    if (GetLocalInt(OBJECT_SELF, "Area_Clear")) {
        AddLocalInt(OBJECT_SELF, "Area_VFX_Active", -1);
        return;
    }

    if (nMulti > 1) {
        /* ugly to have a second copy, but removes unnecessary delaycommands */
        int i;
        float fDelay = 0.0;

        for (i = 0; i < nMulti; i++) {
            float fDurVary = GetVFXLoopVaryingFloat(fDurRand);

            if (sTarget != "") {
                object oTarget = GetVFXLoopTarget(oVFX, sTarget);

                if (bBeam) {
                    effect eBeam = EffectBeam(nVis, oVFX, BODY_NODE_CHEST, (bBeam == 2));
                    DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam, oTarget, fDur + fDurVary));
                } else if (nVis < 0) {
                    DelayCommand(fDelay, VoidBroadcastProjectileToObject(oVFX, oTarget, -nVis, FloatToInt((fDur + fDurVary) * 1000.0)));
                } else if (fDur > 0.0) {
                    effect eVis = EffectVisualEffect(nVis);
                    DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, fDur + fDurVary));
                } else {
                    DelayCommand(fDelay, ApplyVisualToObject(nVis, oTarget));
                }
            } else {
                if (fDur > 0.0) {
                    effect eVis = EffectVisualEffect(nVis);
                    DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oVFX, fDur + fDurVary));
                } else {
                    DelayCommand(fDelay, ApplyVisualToObject(nVis, oVFX));
                }
            }

            fDelay += fMultiInt + GetVFXLoopVaryingFloat(fMultiRand);
        }
    } else {
        float fDurVary = GetVFXLoopVaryingFloat(fDurRand);

        if (sTarget != "") {
            object oTarget = GetVFXLoopTarget(oVFX, sTarget);

            if (bBeam) {
                effect eBeam = EffectBeam(nVis, oVFX, BODY_NODE_CHEST, (bBeam == 2));
                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBeam, oTarget, fDur + fDurVary);
            } else if (nVis < 0) {
                BroadcastProjectileToObject(oVFX, oTarget, -nVis, FloatToInt((fDur + fDurVary) * 1000.0));
            } else if (fDur > 0.0) {
                effect eVis = EffectVisualEffect(nVis);
                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget, fDur + fDurVary);
            } else {
                ApplyVisualToObject(nVis, oTarget);
            }
        } else {
            if (fDur > 0.0) {
                effect eVis = EffectVisualEffect(nVis);
                ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oVFX, fDur + fDurVary);
            } else {
                ApplyVisualToObject(nVis, oVFX);
            }
        }
    }

    float fCycVary = GetVFXLoopVaryingFloat(fCycRand);
    DelayCommand(fCyc + fCycVary, DoVFXLoop(oVFX, nVis, fCyc, fDur, sTarget, bBeam, fCycRand, fDurRand, nMulti, fMultiInt, fMultiRand));
}


void main () {
    object oPC = GetEnteringObject();
    object oArea = GetArea(oPC);

    if (GetIsPC(oPC)) {
        DeleteLocalInt(oArea, "Area_Clear");

        int bReveal = GetLocalInt(oArea, "Area_Reveal");
        if (bReveal > 0)
            ExploreAreaForPlayer(oArea, oPC, TRUE);

        //give pcs a brief lull before they are attacked
        effect eEnter = SupernaturalEffect(EffectEthereal());
        SetEffectSpellId(eEnter, SPELL_ETHEREALNESS);
        ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEnter, oPC, 6.0);
    }

    if (GetLocalString(oPC, "FKY_CHAT_PASSWORD_IP") == "CHECK")
        AssignCommand(GenCreator(), ApplyPasswordHold(oPC));

    /* execute specific onenter script if specified */
    string sScript = GetLocalString(oArea, "Area_OnEnter");
    if (sScript != "")
        ExecuteScript(sScript, oArea);

    /* PC and summons stuff only below here */
    if (!GetIsPCOrAlly(oPC, TRUE))
        return;

    /* area damage/underwater areas */
    /* TODO: enhance this to be more generic, e.g. Hells penalties */
    if (!GetIsDM(oPC)) {
        int nDamType = GetLocalInt(oArea, "Area_Damage_Type");
        if (GetLocalInt(oArea, "Area_Underwater"))
            nDamType = -1;
        else if (GetLocalInt(oArea, "Area_Aerial"))
            nDamType = -2;
        else if (GetLocalInt(oArea, "Area_Passwall"))
            nDamType = -3;
        else if (GetLocalInt(oArea, "Area_Firewalk"))
            nDamType = -4;

        if (nDamType) {
            int nDamAmount  = GetLocalInt(oArea, "Area_Damage_Amount");
            int nDamVis     = GetLocalInt(oArea, "Area_Damage_VFX");
            string sMessage = GetLocalString(oArea, "Area_Damage_Message");

            AssignCommand(oArea, DoAreaEffects(oArea, oPC, nDamAmount, nDamType, nDamVis, sMessage));
        }


        /* destroy items that cannot survive in daylight */
        if (GetIsDay()                &&
            !GetIsAreaInterior(oArea) &&
            GetIsAreaAboveGround(oArea)) {

            int i;
            object oItem;

            for (i = 0; i < NUM_INVENTORY_SLOTS; i++) {
                oItem = GetItemInSlot(i, oPC);

                if (GetStringLeft(GetTag(oItem), 4) == "asdf")
                    DoDust(oPC, oItem);
            }

            if (GetIsObjectValid(oItem = GetItemPossessedBy(oPC, "sealofshadows")))
                DestroyObject(oItem);
        }
    }

    /* PC-only stuff below here */
    if (!GetIsPC(oPC))
        return;

    /* if the PC is not allowed in the area, boot them and return */
    if (!CheckAreaTagRequirement(oArea, oPC))
        return;

    int nGuild = GetLocalInt(oArea, "Guild");
    if (nGuild && !GetLocalInt(oArea, "Guild_Entered")) {
        SetLocalInt(oArea, "Guild_Entered", 1);
        string sSQL = "INSERT INTO guild_hall_use VALUES ('" + SQLEncodeSpecialChars(GetGuildName(nGuild)) + "', NULL)";
        SQLExecDirect(sSQL);
    }

    if (GetLocalInt(oArea, "afx_flags"))
        afx_apply_effects(oPC, OBJECT_SELF);

    if (GetLocalInt(oArea, "Area_VFX_Objects") > 0 &&
        GetLocalInt(oArea, "Area_VFX_Active") == 0) {

        int i, nObjects = GetLocalInt(oArea, "Area_VFX_Objects");
        object oVFX;

        for (i = 0; i < nObjects; i++) {
            oVFX = GetLocalObject(oArea, "Area_VFX_Object_" + IntToString(i));
            if (GetIsObjectValid(oVFX)) {
                int    nVis       = GetLocalInt(oVFX,    "VFX_Loop");
                int    nMulti     = GetLocalInt(oVFX,    "VFX_Loop_Multi");
                int    bBeam      = GetLocalInt(oVFX,    "VFX_Loop_Beam");
                float  fCyc       = GetLocalFloat(oVFX,  "VFX_Loop_Cycle");
                float  fCycRand   = GetLocalFloat(oVFX,  "VFX_Loop_Cycle_Vary");
                float  fDur       = GetLocalFloat(oVFX,  "VFX_Loop_Dur");
                float  fDurRand   = GetLocalFloat(oVFX,  "VFX_Loop_Dur_Vary");
                float  fMultiInt  = GetLocalFloat(oVFX,  "VFX_Loop_Multi_Int");
                float  fMultiRand = GetLocalFloat(oVFX,  "VFX_Loop_Multi_Int_Vary");
                string sTarget    = GetLocalString(oVFX, "VFX_Loop_Target");

                AddLocalInt(oArea, "Area_VFX_Active", 1);
                AssignCommand(oArea, DelayCommand(fCyc, DoVFXLoop(oVFX, nVis, fCyc, fDur, sTarget, bBeam, fCycRand, fDurRand, nMulti, fMultiInt, fMultiRand)));
            }
        }
    }

    /*
        Restrict the places a pc can log into an area at - must be further than _Dis distance
        from waypoint _Way for one of the distance/waypoint sets specified, or they will
        be ported to Area_Entry_Locations_Default entry point. Leave _Dis (and _Way) blank to
        ensure they are ALWAYS ported to the entry point. Use negative _Dis distance to indicate
        a radius they must be within from waypoint _Way.
    */
    int nEntryLocs = GetLocalInt(oArea, "Area_Entry_Locations");
    if (nEntryLocs) {
        int i;
        int nOK = TRUE;
        string sKey;
        location lWay, lPC = GetLocation(oPC);
        float fDist, fRange;

        for (i = 1; i <= nEntryLocs; i++) {
            sKey = "Area_Entry_Location_" + IntToString(i);

            lWay = GetLocation(GetWaypointByTag(GetLocalString(oArea, sKey + "_Way")));
            fDist = GetDistanceBetweenLocations(lWay, lPC);
            fRange = GetLocalFloat(oArea, sKey + "_Dis");

            if (fDist < 0.0                         || //error - comparison outside area or other issue
                fRange == 0.0                       || //default float value (_Dis not set)
                (fRange > 0.0 && fDist < fRange)    ||
                (fRange < 0.0 && fDist > (-1.0*fRange))) {
                nOK = FALSE;
                break;
            }
        }

        if (!nOK) {
            location lEnter = GetLocation(GetWaypointByTag(GetLocalString(oArea, "Area_Entry_Locations_Default")));
            ForceJump(oPC, lEnter);
        }
    }

    /* Set specified variables on PCs */
    int nArVars = GetLocalInt(oArea, "Area_Vars");
    if (nArVars) {
        int i;
        string sType, sKey, sName, sVal;

        for (i = 1; i <= nArVars; i++) {
            sKey = "Area_Var_" + IntToString(i);
            sType = GetLocalString(oArea, sKey+"_Typ");
            sName = GetLocalString(oArea, sKey+"_Key");
            sVal =  GetLocalString(oArea, sKey+"_Val");
            if (sType == "INT")
                SetLocalInt(oPC, sName, StringToInt(sVal));
            else if (sType == "FLOAT")
                SetLocalFloat(oPC, sName, StringToFloat(sVal));
            else if (sType == "STRING")
                SetLocalString(oPC, sName, sVal);
        }
    }


    string sQuest = GetLocalString(oArea, "Area_Quest");
    if (sQuest != "")
        QSAddQuestStatus(sQuest, 1);

    /* for Hell and Limbo areas, set the Succor_ local */
    if (GetLocalInt(oArea, "notele") > 0)
        SetLocalInt(oPC, "Succor_" + GetResRef(oArea), 1);


    /* spawn anything specified in area locals */
    int nSpawns = GetLocalInt(oArea, "Area_Spawns");
    string sTask;
    struct IntList li;

    if (nSpawns > 0) {
        int i, nType;
        string sKey, sTag, sRes, sLoc, sLocType;
        object oSpawn;
        location lSpawn;

        for (i = 1; i <= nSpawns; i++) {
            sKey = "Area_Spawn_" + IntToString(i);
            sTag = GetLocalString(oArea, sKey + "_Tag");


            /* if the object has already been spawned, skip it */
            if (sTag != "") {
                if (GetIsObjectValid(GetNearestObjectByTag(sTag, oPC)))
                    continue;
            } else {
                if (GetIsObjectValid(GetLocalObject(oArea, sKey + "_Obj")))
                    continue;
            }


            sRes  = GetLocalString(oArea, sKey + "_Res");
            sLoc  = GetLocalString(oArea, sKey + "_Loc");
            nType = GetLocalInt(oArea, sKey + "_Type");

            if (nType == 0)
                nType = OBJECT_TYPE_CREATURE;

            sLocType = GetStringLeft(sLoc, 1);


            if (sLocType == "!")
                lSpawn = GetLocation(GetNearestObjectByTag(GetSubString(sLoc, 1, 64), oPC));
            else if (sLocType == "@")
                lSpawn = GetLocation(GetWaypointByTag(GetSubString(sLoc, 1, 64)));
            else if (sLocType == "&") {//designates task creature, only spawn if pc requires (uses waypoint)  ex: tsk_cr_1_2
                sTask = GetStringRight(sRes, (GetStringLength(sRes) - 7));
                li = GetIntList(sTask, "_");
                if (!GetPCHasTaskActive(oPC, li.i0) || (GetTaskCompleted(oPC, li.i0) != (li.i1 - 1)))//if they don't have the task active, don't spawn
                    continue;
                else
                    lSpawn = GetLocation(GetWaypointByTag(GetSubString(sLoc, 1, 64)));
            } else
                continue;


            if (GetAreaFromLocation(lSpawn) == oArea) {
                oSpawn = CreateObject(nType, sRes, lSpawn, FALSE, sTag);
                SetLocalObject(oArea, sKey + "_Obj", oSpawn);
            }
        }
    }


    /* respawn loot or other other respawnables */
    nSpawns = GetLocalInt(oArea, "Area_Respawns");

    if (nSpawns > 0) {
        int i, nType, nRespawnTime, nUptime = GetLocalInt(GetModule(), "uptime");
        string sKey, sVar;
        object oSpawn;

        for (i = 1; i <= nSpawns; i++) {
            sKey = IntToString(i);

            nRespawnTime = GetLocalInt(oArea, "Area_Respawn_" + sKey);
            if (nRespawnTime <= 0 ||
                nRespawnTime > nUptime ||
                GetIsObjectValid(GetLocalObject(oArea, "Area_Respawn_Obj_" + sKey)))
                continue;

            oSpawn = CreateObject(GetLocalInt(oArea, "Area_Respawn_Type_" + sKey),
                GetLocalString(oArea, "Area_Respawn_Res_" + sKey),
                GetLocalLocation(oArea, "Area_Respawn_Loc_" + sKey));

            SetLocalObject(oArea, "Area_Respawn_Obj_" + sKey, oSpawn);

            if ((sVar = GetLocalString(oArea, "Area_Respawn_Var_" + sKey)) != "")
                AssignCommand(oArea, DelayCommand(0.0, RestoreLocals(oSpawn, sVar)));
        }
    }

    /* clear despawn setting on area */
    if (GetLocalInt(oArea, "DespawnTrack")) {
        int nDespawnTime = GetLocalInt(oArea, "DespawnTime");
        if (nDespawnTime) {
            int nUptime = GetLocalInt(GetModule(), "uptime");
            if ((nUptime - 3600) > nDespawnTime) {
                DeleteLocalInt(oArea, "DespawnTime");
                DeleteLocalInt(oArea, "DespawnCount");
            }
        }
    }
}



Focus on the spawning section in main. Here's a sample showing how to spawn in 2 NPCs every time a pc enters, if they're not already spawned:
(all variables set on area)
Area_Spawns int 2
Area_Spawn_1_Loc string @WP_beetlecollect_01
Area_Spawn_1_Res string duefight007
Area_Spawn_1_Tag string beetlecollect
Area_Spawn_2_Loc string !shop_low_armor
Area_Spawn_2_Res string duefight006
Area_Spawn_2_Tag string mer_low_armor

The ! indicates an object tag for the location, the @ a waypoint.

Of course, you have to despawn them on area exit, so I'll post our onexit script below, in a new post.

Funky
               
               

               
            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #11 on: February 21, 2012, 11:26:05 pm »


               Here's the onexit script on all our areas. Focus on the DespawnArea function above main().


#include "hg_inc"

#include "afx_sfunc"
#include "ac_qstatus_inc"
#include "legendarybab_inc"
#include "gen_interact_inc"

void TrashObject (object oObject) {
    if (GetObjectType(oObject) == OBJECT_TYPE_PLACEABLE) {
        /* search and destroy contents of placeables */

        object oItem = GetFirstItemInInventory(oObject);

        while (GetIsObjectValid(oItem)) {
            SetPlotFlag(oItem, FALSE);
            DestroyObject(oItem);

            oItem = GetNextItemInInventory(oObject);
        }
    }

    SetPlotFlag(oObject, FALSE);
    DestroyObject(oObject);
}


/* -------------------- remove this section once the new loot system is in place -------------------- */
void RespawnObject(string sTag, int iType, location lLoc, int nLoot = 0) {
    object oPlace = CreateObject(iType, sTag, lLoc);

    if (nLoot != 0)
        SetLocalInt(oPlace, "RLoot", nLoot);
}

void DespawnRespawn(object oObject, float fDelay) {
    SetPlotFlag(oObject, FALSE);
    TrashObject(oObject);
    string sTag = GetResRef(oObject);
    int iType = GetObjectType(oObject);
    location lLoc = GetLocation(oObject);

    /* if this is set to 1, object spawns random loot, tag should be preserved */
    int nLoot = GetLocalInt(oObject, "RLoot");

    /* added nLoot paramenter to Respawn function to pass locals to respawned
     * version (avoids having to set them in the object palettes) */
    if (fDelay < 8000.0)
        AssignCommand(GetArea(oObject), DelayCommand(fDelay, RespawnObject(sTag, iType, lLoc, nLoot)));
}

void DespawnArea(object oArea) {

    if (!GetIsAreaEmpty(oArea))
        return;

    /* despawn the entire area */
    int bArena = GetLocalInt(oArea, "Arena");
    int nUptime = GetLocalInt(GetModule(), "uptime");
    int nDespawn, bDespawnTracking = GetLocalInt(oArea, "DespawnTrack");
    int bNoDespawnCreatures = GetLocalInt(oArea, "NoDespawnCreatures");
    string sBoss;

    object oObject;
    for (oObject = GetFirstObjectInArea(oArea);
         GetIsObjectValid(oObject);
         oObject = GetNextObjectInArea(oArea)) {

        switch (GetObjectType(oObject)) {
            case OBJECT_TYPE_PLACEABLE:
                /*
                if (GetTag(oObject) == "BodyBag" || GetLocalInt(oObject, "Despawn"))
                    TrashObject(oObject);
                 */

                /* ---- remove this section once the new loot system is in place ---- */
                nDespawn = GetLocalInt(oObject, "fkydespawn");

                if (GetTag(oObject) == "BodyBag" || nDespawn < 0)
                    TrashObject(oObject);
                else if (nDespawn)
                    DespawnRespawn(oObject, IntToFloat(nDespawn));

                /* ---- end section to be removed ----------------------------------- */
                break;

            case OBJECT_TYPE_ITEM:
                if (!bArena)
                    TrashObject(oObject);
                break;

            case OBJECT_TYPE_CREATURE:
                if (GetIsPC(oObject) || GetIsPC(GetMaster(oObject)) || bNoDespawnCreatures)
                    break;

                if ((sBoss = GetLocalString(oObject, "TrapArea_Waypoint")) != "") {
                    location lSelf = GetLocation(oObject);
                    object oTrapped, oTrapArea = GetArea(GetWaypointByTag(sBoss));
                    string sMessage = GetLocalString(oObject, "TrapArea_Escape");

                    if (GetIsObjectValid(oTrapArea)) {
                        for (oTrapped = GetFirstPC(); GetIsObjectValid(oTrapped); oTrapped = GetNextPC()) {
                            if (GetArea(oTrapped) == oTrapArea) {
                                SendMessageToPC(oTrapped, sMessage);
                                ForceJump(oTrapped, lSelf);
                            }
                        }
                    }
                }

                if ((sBoss = GetLocalString(oObject, "QSDeathTag")) != "") {
                    struct SubString ss = GetFirstSubString(sBoss, "~");

                    if (ss.first != "")
                        QSSetQuestStatus(ss.first, StringToInt(ss.rest) * -1);

                    SetPlotFlag(oObject, FALSE);
                    DestroyObject(oObject);
                }

                /* delete NPCs, encounter creatures, and spawned in
                 * creatures (with Despawn set). Don't delete creatures that
                 * have a PC as a master, as summons and dominates could be destroyed
                 * before they can zone out with their master. */
                if ((nDespawn = GetLocalInt(oObject, "Despawn")) ||
                    (GetIsEncounterCreature(oObject) && !GetIsPC(GetMaster(oObject)))) {

                    if (nDespawn >= 0 && bDespawnTracking) {
                        AddLocalInt(oArea, "DespawnCount", 1);
                        SetLocalInt(oArea, "DespawnTime", nUptime);
                    }

                    TrashObject(oObject);
                }
                break;

            case OBJECT_TYPE_TRIGGER:
                if (GetLocalInt(oObject, "Despawn"))
                    TrashObject(oObject);
                break;

        }
    }
}

/* -------------------- end section to be removed -------------------- */


void main () {
    object oPC = GetExitingObject();
    object oObject, oArea = OBJECT_SELF;

    /* deplot everything leaving an area, to prevent invulnerability exploits -
     * exceptions for BBoD, DMs, and intentionally invulnerable summons */
    if (GetResRef(oPC) != "x2_s_bblade" && !GetLocalInt(oPC, "FKY_CHAT_INVULN") && !GetLocalInt(oPC, "PlotSummons"))
        SetPlotFlag(oPC, FALSE);

    /* destroy all dominated creatures unless specifically allowed to transition */
    if (!GetIsPC(oPC)                                  &&
        GetHasEffectOfType(EFFECT_TYPE_DOMINATED, oPC) &&
        !GetLocalInt(oPC, "DomTransition")) {

        DestroyObject(oPC);
        return;
    }

    /* only players and DMs are tagged with ID */
    if (GetLocalString(oPC, "ID") == "" || GetIsDM(oPC))
        return;

    /* fire off custom script for area exit if specified */
    string sExecuteExit = GetLocalString(oArea, "Area_OnExit");
    if (sExecuteExit != "")
        ExecuteScript(sExecuteExit, oArea);

    /* de-AFK players on any transition */
    DeleteLocalInt(oPC, "FKY_CHAT_AFK");
    DeleteLocalObject(oPC, "FKY_CHAT_BULK_TARGET");

    if (GetHasSpellEffect(HGEFFECT_AREA_PENALTIES, oPC)) {
        RemoveEffectsFromSpell(HGEFFECT_AREA_PENALTIES, oPC);
        CheckLegendaryBABEffect(oPC);
    }

    /* remove supernatural darkness from area */
    RemoveEffectsOfType(EFFECT_TYPE_DARKNESS, oPC, oArea);

    /* removes effects of underwater bubbles if any */
    if (GetHasSpellEffect(HGEFFECT_UNDERWATER_BUBBLES, oPC))
        RemoveEffectsFromSpell(HGEFFECT_UNDERWATER_BUBBLES, oPC);


    /* scan to see if there are any PCs left in the area */
    oPC = GetFirstPC();
    while (GetIsObjectValid(oPC)) {
        if (GetArea(oPC) == oArea && oPC != oArea && !GetIsDM(oPC))
            return;

        oPC = GetNextPC();
    }

    SetLocalInt(oArea, "Area_Clear", 1);

    /* fire off custom script for pc-free area if specififed */
    string sExecuteClear = GetLocalString(oArea, "Area_OnClear");
    if (sExecuteClear != "")
        ExecuteScript(sExecuteClear, oArea);

    /* reset any interaction triggers in need of it, and shut off any interactions
       marked for area-exit shutoff */
    int nTriggerResetCount = GetLocalInt(oArea, "Interact_Triggers_To_Reset");
    if (nTriggerResetCount) {

        int nX, nY, nZ, nInteractions, nObjMask;
        object oTriggerToReset, oLoop;
        string sObjTag;
        for (nX = 1; nX <= nTriggerResetCount; nX++) {

            oTriggerToReset = GetLocalObject(oArea, "Interact_Trigger_Reset_" + IntToString(nX));
            nInteractions = GetLocalInt(oTriggerToReset, "Interact_Count");
            for (nY = 1; nY <= nInteractions; nY++) {

                if (GetLocalInt(oTriggerToReset, "Interact_Trigger_Shutoff_" + IntToString(nY)) == 2)
                    DeleteLocalInt(oTriggerToReset, "Interact_Off_" + IntToString(nY));
                if (GetLocalInt(oTriggerToReset, "Interact_Interaction_Shutoff_" + IntToString(nY)) == 2) {
                    sObjTag = GetLocalString(OBJECT_SELF, "Interact_Object_Tag_" + IntToString(nY));
                    if (sObjTag == "")
                        sObjTag = "gen_interact_obj";
                    nObjMask = GetLocalInt(OBJECT_SELF, "Interact_Object_Mask_" + IntToString(nY));
                    nZ = 1;
                    oLoop = GetNearestObjectByTag(sObjTag, oTriggerToReset, 1);
                    while (GetIsObjectValid(oLoop)) {

                        if ((GetLocalInt(oLoop, "Interact_Object_Mask") & nObjMask) &&
                            (GetLocalInt(OBJECT_SELF, "Interact_Interaction_Shutoff_"
                                + IntToString(nY)) == 1))
                            ShutOffInteraction(oLoop, nY);

                        nZ++;
                        oLoop = GetNearestObjectByTag(sObjTag, oTriggerToReset, nZ);
                    }
                }
            }
        }
    }
    float fDelay = 180.0;
    if (GetLocalInt(oArea, "Arena"))
        fDelay = 0.0;
    AssignCommand(oArea, DelayCommand(fDelay, DespawnArea(oArea)));

}



The NPCs in the show in question have the Despawn variable set on them.

Funky
               
               

               
            

Legacy_Knight_Shield

  • Hero Member
  • *****
  • Posts: 812
  • Karma: +0/-0
Triggering Encounters OnEnter for an Area
« Reply #12 on: February 22, 2012, 01:34:29 am »


               I would like to know are you guys concerned about encounters or NPC's.
I was wondering myself if I had gone thru the trouble of spawning all my NPC for no good reason because I see other downloadable mods that do not spawn their NPC.

Here is the NPC spawn script I copied from some where .// An area's OnEnter script.

// Area OnEnter script.
//::////////////////////////////////////////////////////////////////
#include "_quest_npc_inc"

void main()
{ if( !GetIsPC( GetEnteringObject())) return;

 DelayCommand(1.0,SpawnQuestNPCsIntoArea( OBJECT_SELF));
ExecuteScript("_cleanupenter",OBJECT_SELF);
ExecuteScript("map",OBJECT_SELF);
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------
This one is called in the onenter script above.
_cleanupenter
// An area's OnEnter script.
//
// Partner script for the area cleaning script (OnExit).

void main()
{
    // Only fire for PCs.
    if ( !GetIsPC(GetEnteringObject()) )
        return;
    // Cancel any scheduled cleanup.
    SetLocalInt(OBJECT_SELF, "AREA_CLEANUP_CONTROL",
        GetLocalInt(OBJECT_SELF, "AREA_CLEANUP_CONTROL") + 1);
}


-----------------------------------------------------------------------------------------------------------------------------------------------------------


// An area's OnExit script.
//
// Clears all spawns and resets encounters if no living PC is in the area in the
// next 30 seconds.
// Requires a partner OnEnter event to detect PCs entering the area in the
// 30-second timeframe.
// Returns a living PC in oArea, if any.
// Returns OBJECT_INVALID otherwise.
object GetLivingPCInArea(object oArea);
// Handles the actual cleanup of oArea.
void CleanupArea(object oArea, int nControl);
void main()
{
   object oArea = OBJECT_SELF;
   // Only fire for PCs (for efficiency).
   if ( !GetIsPC(GetExitingObject()) )
       return;
   // Check for a lack of living PCs in the area.
   if ( GetLivingPCInArea(oArea) == OBJECT_INVALID )
       // Schedule a cleanup.
       DelayCommand(30.0, CleanupArea(oArea, GetLocalInt(oArea, "AREA_CLEANUP_CONTROL")));
}
// -----------------------------------------------------------------------------
// Handles the actual cleanup of oArea.
void CleanupArea(object oArea, int nControl)
{
   if ( nControl != GetLocalInt(oArea, "AREA_CLEANUP_CONTROL") )
       // Someone entered the area. Abort.
       return;
   // Double-check that there are no living PCs in the area.
   // (Should not be necessary, but just in case...)
   if ( GetLivingPCInArea(oArea) == OBJECT_INVALID )
   {
       // Loop through objects in the area.
       object oObject = GetFirstObjectInArea(oArea);
       while ( oObject != OBJECT_INVALID )
       {
           switch ( GetObjectType(oObject) )
           {
               case OBJECT_TYPE_CREATURE:
                       // Eliminate spawns.
                       DestroyObject(oObject);
                       break;
               case OBJECT_TYPE_ENCOUNTER:
                       // Reset encounters.
                       DelayCommand(0.1, SetEncounterActive(TRUE, oObject));
                       break;

               case OBJECT_TYPE_ITEM:
                       DestroyObject(oObject);
                       break;
           }
           // Update the loop.
           oObject = GetNextObjectInArea(oArea);
       }
   }
   // Cancel any remaining scheduled cleanups.
   SetLocalInt(OBJECT_SELF, "AREA_CLEANUP_CONTROL", nControl + 1);
}
// Returns a living PC in oArea, if any.
// Returns OBJECT_INVALID otherwise.
object GetLivingPCInArea(object oArea)
{
   return GetNearestCreatureToLocation(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC,
                                       Location(oArea, Vector(), 0.0), 1,
                                       CREATURE_TYPE_IS_ALIVE, TRUE);
}


------------------------------------------------------------------------------------------------------------------------------------------------------------

// Quest NPC Spawning System Library
//:://////////////////////////////////////////////////////////
// _quest_npc_inc
//:://////////////////////////////////////////////////////////
struct NPCinfo
{ string resref;
 string waypoint;
};
struct NPCinfo GetQuestNPCInfo( string sNPCTag)
{ struct NPCinfo stQuestNPC;
 stQuestNPC.resref   = "";
 stQuestNPC.waypoint = "";
 if( sNPCTag == "") return stQuestNPC;
 // Fill in this part for all quest NPCs in your module.
 if( sNPCTag == "bing")
 { stQuestNPC.resref   = "bing";
   stQuestNPC.waypoint = "POST_bing";
 }
 else if( sNPCTag == "ancientlibrarian")
 { stQuestNPC.resref   = "ancientlibrarian";
   stQuestNPC.waypoint = "WP_ancientlibrarian_01";
 }
 else if( sNPCTag == "bingsdog")
 { stQuestNPC.resref   = "bingsdog";
   stQuestNPC.waypoint = "POST_bingsdog";
 }
 else if( sNPCTag == "towncrier")
 { stQuestNPC.resref   = "towncrier";
   stQuestNPC.waypoint = "WP_towncrier_01";
 }
 else if( sNPCTag == "BBS_SCRIBE")
 { stQuestNPC.resref   = "bbs_scribe_bp";
   stQuestNPC.waypoint = "WP_BBS_SCRIBE_01";
 }
 else if( sNPCTag == "crystalport003")
 { stQuestNPC.resref   = "crystalport003";
   stQuestNPC.waypoint = "crystalport003";
 }
 else if( sNPCTag == "winterkeepgua002")
 { stQuestNPC.resref   = "winterkeepgua002";
   stQuestNPC.waypoint = "winterkeepgua002";
 }
 else if( sNPCTag == "winter001")
 { stQuestNPC.resref   = "winter001";
   stQuestNPC.waypoint = "winter001";
 }
 else if( sNPCTag == "doorguard")
 { stQuestNPC.resref   = "doorguard";
   stQuestNPC.waypoint = "doorguard";
 }
 else if( sNPCTag == "CUSTOMER")
 { stQuestNPC.resref   = "humsailor001";
   stQuestNPC.waypoint = "WP_02";
 }
 else if( sNPCTag == "piratewomen")
 { stQuestNPC.resref   = "piratewomen";
   stQuestNPC.waypoint = "WP_01";
 }
  else if( sNPCTag == "guard003")
 { stQuestNPC.resref   = "guard003";
   stQuestNPC.waypoint = "WP_03";
 }
 else if( sNPCTag == "guard004")
 { stQuestNPC.resref   = "guard004";
   stQuestNPC.waypoint = "WP_04";
 }
 else if( sNPCTag == "Drunk")
 { stQuestNPC.resref   = "drunk";
   stQuestNPC.waypoint = "Drunk_Post";
 }
 else if( sNPCTag == "marina")
 { stQuestNPC.resref   = "marina";
   stQuestNPC.waypoint = "WP_05";
 }
 else if( sNPCTag == "LANCE")
 { stQuestNPC.resref   = "lance";
   stQuestNPC.waypoint = "WP_06";
 }
 else if( sNPCTag == "COOK")
 { stQuestNPC.resref   = "vastin";
   stQuestNPC.waypoint = "WP_COOK_01";
 }
 else if( sNPCTag == "BARMAID_STATE")
 { stQuestNPC.resref   = "kacy";
   stQuestNPC.waypoint = "WP_BAR";
 }
  else if( sNPCTag == "BARTEND")
 { stQuestNPC.resref   = "kati";
   stQuestNPC.waypoint = "WP_BARTEND_01";
 }
  else if( sNPCTag == "don")
 { stQuestNPC.resref   = "don";
   stQuestNPC.waypoint = "WP_don_01";
 }
  else if( sNPCTag == "DOCKMASTER")
 { stQuestNPC.resref   = "dockmaster";
   stQuestNPC.waypoint = "POST_DOCKMASTER";
 }
 else if( sNPCTag == "Mayor")
 { stQuestNPC.resref   = "mayor";
   stQuestNPC.waypoint = "WP_Mayor_01";
 }
 else if( sNPCTag == "claire")
 { stQuestNPC.resref   = "claire";
   stQuestNPC.waypoint = "WP_claire_01";
 }
 else if( sNPCTag == "Sasha")
 { stQuestNPC.resref   = "sasha";
   stQuestNPC.waypoint = "POST_Sasha";
 }
 else if( sNPCTag == "Guard")
 { stQuestNPC.resref   = "guard005";
   stQuestNPC.waypoint = "WP_Guard_01";
 }
 else if( sNPCTag == "Norio")
 { stQuestNPC.resref   = "norio";
   stQuestNPC.waypoint = "WP_Norio_01";
 }
 else if( sNPCTag == "TheNamer")
 { stQuestNPC.resref   = "thenamer";
   stQuestNPC.waypoint = "WP_TheNamer_01";
 }
 else if( sNPCTag == "leena")
 { stQuestNPC.resref   = "leena";
   stQuestNPC.waypoint = "POST_leena";
 }
 else if( sNPCTag == "omegasmith02")
 { stQuestNPC.resref   = "omegasmith02";
   stQuestNPC.waypoint = "WP_omegasmith02_01";
 }
  else if( sNPCTag == "Holly")
 { stQuestNPC.resref   = "holly";
   stQuestNPC.waypoint = "POST_Holly";
 }
   else if( sNPCTag == "TailoringModel")
 { stQuestNPC.resref   = "tailoringmodel01";
   stQuestNPC.waypoint = "WP007";
 }
  else if( sNPCTag == "TailoringModel2")
 { stQuestNPC.resref   = "tailoringmode001";
   stQuestNPC.waypoint = "WP009";
 }
  else if( sNPCTag == "TailoringModel3")
 { stQuestNPC.resref   = "tailoringmode003";
   stQuestNPC.waypoint = "WP0010";
 }
  else if( sNPCTag == "TailoringModel4")
 { stQuestNPC.resref   = "tailoringmode004";
   stQuestNPC.waypoint = "WP0011";
 }
 else if( sNPCTag == "Kate")
 { stQuestNPC.resref   = "kate";
   stQuestNPC.waypoint = "WP_Kate_01";
 }
 else if( sNPCTag == "omegasmith01")
 { stQuestNPC.resref   = "omegasmith01";
   stQuestNPC.waypoint = "WP_omegasmith01_01";
 }
 else if( sNPCTag == "omegasmith5")
 { stQuestNPC.resref   = "omegasmith5";
   stQuestNPC.waypoint = "WP_omegasmith5_01";
 }
 else if( sNPCTag == "omegasmith4")
 { stQuestNPC.resref   = "ilridentifier";
   stQuestNPC.waypoint = "WP_omegasmith4_01";
 }
 else if( sNPCTag == "omegasmith03")
 { stQuestNPC.resref   = "omegasmith03";
   stQuestNPC.waypoint = "WP_omegasmith03_01";
 }
 else if( sNPCTag == "Guard4")
 { stQuestNPC.resref   = "guard4";
   stQuestNPC.waypoint = "POST_Guard4";
 }
 else if( sNPCTag == "Guard3")
 { stQuestNPC.resref   = "guard3";
   stQuestNPC.waypoint = "POST_Guard3";
 }
 else if( sNPCTag == "sb")
 { stQuestNPC.resref   = "sb";
   stQuestNPC.waypoint = "WP_sb_01";
 }
 else if( sNPCTag == "Guard10")
 { stQuestNPC.resref   = "guard10";
   stQuestNPC.waypoint = "POST_Guard10";
 }
 else if( sNPCTag == "Guard2")
 { stQuestNPC.resref   = "guard2";
   stQuestNPC.waypoint = "POST_Guard2";
 }
 else if( sNPCTag == "manus")
 { stQuestNPC.resref   = "manus";
   stQuestNPC.waypoint = "WP_manus_01";
 }
  else if( sNPCTag == "frostkeepgateguard1")
 { stQuestNPC.resref   = "frostkeepgate1";
   stQuestNPC.waypoint = "WP_frostkeepgateguard1_01";
 }
  else if( sNPCTag == "frostkeepgateguard2")
 { stQuestNPC.resref   = "frostkeepgate2";
   stQuestNPC.waypoint = "WP_frostkeepgateguard2_01";
 }
  else if( sNPCTag == "CaptainSamantha")
 { stQuestNPC.resref   = "captainsamantha";
   stQuestNPC.waypoint = "POST_CaptainSamantha";
 }
 else if( sNPCTag == "tikis")
 { stQuestNPC.resref   = "tikis";
   stQuestNPC.waypoint = "WP_tikis_01";
 }
 else if( sNPCTag == "Halaster")
 { stQuestNPC.resref   = "halaster001";
   stQuestNPC.waypoint = "WP_Halaster_01";
 }
 else if( sNPCTag == "Rolo")
 { stQuestNPC.resref   = "rolo";
   stQuestNPC.waypoint = "WP_Rolo_01";
 }
 else if( sNPCTag == "Lucky")
 { stQuestNPC.resref   = "captainsamant005";
   stQuestNPC.waypoint = "WP_Lucky_01";
 }
 else if( sNPCTag == "links")
 { stQuestNPC.resref   = "links";
   stQuestNPC.waypoint = "WP_links_01";
 }
 else if( sNPCTag == "guss")
 { stQuestNPC.resref   = "guss";
   stQuestNPC.waypoint = "WP_guss_01";
 }
 else if( sNPCTag == "NW_BARTENDER")
 { stQuestNPC.resref   = "bartender001";
   stQuestNPC.waypoint = "WP_NW_BARTENDER_01";
 }
 else if( sNPCTag == "helga")
 { stQuestNPC.resref   = "helga";
   stQuestNPC.waypoint = "helga";
 }
 else if( sNPCTag == "elring")
 { stQuestNPC.resref   = "elring";
   stQuestNPC.waypoint = "elring";
 }
 else if( sNPCTag == "Guard11")
 { stQuestNPC.resref   = "guard001";
   stQuestNPC.waypoint = "WP_Guard11_01";
 }
 else if( sNPCTag == "OutPostGuard")
 { stQuestNPC.resref   = "outpostguard";
   stQuestNPC.waypoint = "WP_OutPostGuard_01";
 }
 else if( sNPCTag == "General")
 { stQuestNPC.resref   = "general002";
   stQuestNPC.waypoint = "WP_General_01";
 }
 else if( sNPCTag == "Legan")
 { stQuestNPC.resref   = "general";
   stQuestNPC.waypoint = "WP_Legan_01";
 }
 else if( sNPCTag == "fing")
 { stQuestNPC.resref   = "feng";
   stQuestNPC.waypoint = "WP_fing_01";
 }
 else if( sNPCTag == "Oberon")
 { stQuestNPC.resref   = "oberon";
   stQuestNPC.waypoint = "WP_Oberon_01";
 }
  else if( sNPCTag == "Lolir")
 { stQuestNPC.resref   = "lolir";
   stQuestNPC.waypoint = "WP_Lolir_01";
 }
  else if( sNPCTag == "CaptainoftheGuard")
 { stQuestNPC.resref   = "captainoftheguar";
   stQuestNPC.waypoint = "WP_CaptainoftheGuard_01";
 }
 else if( sNPCTag == "Moigan")
 { stQuestNPC.resref   = "moigan";
   stQuestNPC.waypoint = "WP_Moigan_01";
 }
 else if( sNPCTag == "KingVidor")
 { stQuestNPC.resref   = "kingvidor001";
   stQuestNPC.waypoint = "WP_KingVidor_01";
 }
 else if( sNPCTag == "Father_Richo")
 { stQuestNPC.resref   = "father001";
   stQuestNPC.waypoint = "WP_Father_Richo_01";
 }
 else if( sNPCTag == "duefight002")
 { stQuestNPC.resref   = "duefight002";
   stQuestNPC.waypoint = "WP_duefight002_01";
 }
  else if( sNPCTag == "Morris")
 { stQuestNPC.resref   = "morris001";
   stQuestNPC.waypoint = "WP_Morris_01";
 }
  else if( sNPCTag == "MrsBingle")
 { stQuestNPC.resref   = "dona001";
   stQuestNPC.waypoint = "WP_MrsBingle_01";
 }
  else if( sNPCTag == "Toman")
 { stQuestNPC.resref   = "toman001";
   stQuestNPC.waypoint = "WP_Toman_01";
 }
 else if( sNPCTag == "Lagnar")
 { stQuestNPC.resref   = "lagnar001";
   stQuestNPC.waypoint = "WP_Lagnar_01";
 }
 else if( sNPCTag == "captcliff")
 { stQuestNPC.resref   = "captcliff";
   stQuestNPC.waypoint = "WP_captcliff_01";
 }
 else if( sNPCTag == "captcliff2")
 { stQuestNPC.resref   = "captcliff2";
   stQuestNPC.waypoint = "WP_captcliff2_01";
 }
 else if( sNPCTag == "InnKeeper")
 { stQuestNPC.resref   = "innkeeper";
   stQuestNPC.waypoint = "WP_InnKeeper_01";
 }
 else if( sNPCTag == "CaptainKorin")
 { stQuestNPC.resref   = "captainkorin";
   stQuestNPC.waypoint = "WP_CaptainKorin_01";
 }
 else if( sNPCTag == "CaptainKorin2")
 { stQuestNPC.resref   = "captainkorin001";
   stQuestNPC.waypoint = "WP_CaptainKorin2_01";
 }
 else if( sNPCTag == "Potion_11")
 { stQuestNPC.resref   = "gypmale001";
   stQuestNPC.waypoint = "WP_NW_GYPMALE_01";
 }
 else if( sNPCTag == "Vens")
 { stQuestNPC.resref   = "vens";
   stQuestNPC.waypoint = "WP_Vens_01";
 }
 else if( sNPCTag == "servant")
 { stQuestNPC.resref   = "guard006";
   stQuestNPC.waypoint = "WP_servant_01";
 }
 else if( sNPCTag == "notes_postman")
 { stQuestNPC.resref   = "notes_postman001";
   stQuestNPC.waypoint = "WP_notes_postman_01";
 }
 else if( sNPCTag == "NW_IMP")
 { stQuestNPC.resref   = "imp003";
   stQuestNPC.waypoint = "WP_NW_IMP_01";
 }
 else if( sNPCTag == "Gormak")
 { stQuestNPC.resref   = "bandit007";
   stQuestNPC.waypoint = "WP_Gormak_01";
 }
 else if( sNPCTag == "Merise")
 { stQuestNPC.resref   = "merise";
   stQuestNPC.waypoint = "WP_Merise_01";
 }
 else if( sNPCTag == "JailPermanentResident")
 { stQuestNPC.resref   = "convict001";
   stQuestNPC.waypoint = "WP_JailPermanentResident_01";
 }
 else if( sNPCTag == "BrinToris")
 { stQuestNPC.resref   = "brintoris";
   stQuestNPC.waypoint = "WP_BrinToris_01";
 }
  // ... etc for all quest NPCs
  return stQuestNPC;
}
void AddQuestNPCToArea( object oArea, string sNPCTag)
{ if( !GetIsObjectValid( oArea) || (GetArea( oArea) != oArea) || (sNPCTag == "")) return;
 int iNPCNum = GetLocalInt( oArea, "QuestNPCCount") +1;
 SetLocalInt( oArea, "QuestNPCCount", iNPCNum);
 SetLocalString( oArea, "QuestNPC_" +IntToString( iNPCNum), sNPCTag);
}
void InitializeQuestNPCsInArea( object oArea)
{ if( !GetIsObjectValid( oArea) || (GetArea( oArea) != oArea) || (GetLocalInt( oArea, "QuestNPCCount") > 0)) return;
 DeleteLocalInt( oArea, "QuestNPCCount");
 string sAreaTag = GetTag( oArea);
 // Fill in this part according to your module's layout.
 if( sAreaTag == "bingspawn")
 { AddQuestNPCToArea( oArea, "bing");
 }
 else if( sAreaTag == "ancientlibrary")
 { AddQuestNPCToArea( oArea, "ancientlibrarian");
 }
 else if( sAreaTag == "winterkeep")
 { AddQuestNPCToArea( oArea, "BBS_SCRIBE");
   AddQuestNPCToArea( oArea, "towncrier");
   AddQuestNPCToArea( oArea, "bingsdog");
   AddQuestNPCToArea( oArea, "crystalport003");
   AddQuestNPCToArea( oArea, "winterkeepgua002");
   AddQuestNPCToArea( oArea, "winter001");
   AddQuestNPCToArea( oArea, "doorguard");
 }
 else if( sAreaTag == "ElfsongTavern")
 { AddQuestNPCToArea( oArea, "CUSTOMER");
   AddQuestNPCToArea( oArea, "piratewomen");
   AddQuestNPCToArea( oArea, "guard003");
   AddQuestNPCToArea( oArea, "guard004");
   AddQuestNPCToArea( oArea, "Drunk");
   AddQuestNPCToArea( oArea, "marina");
   AddQuestNPCToArea( oArea, "LANCE");
   AddQuestNPCToArea( oArea, "COOK");
   AddQuestNPCToArea( oArea, "BARMAID_STATE");
   AddQuestNPCToArea( oArea, "BARTEND");
 }
 else if( sAreaTag == "RusIsleHavenSmithy")
 { AddQuestNPCToArea( oArea, "duefight002");
   AddQuestNPCToArea( oArea, "duefight002");
 }
 else if( sAreaTag == "winterkeepdocks")
 { AddQuestNPCToArea( oArea, "don");
   AddQuestNPCToArea( oArea, "DOCKMASTER");
 }
 else if( sAreaTag == "TagnarsForge")
 { AddQuestNPCToArea( oArea, "manus");
   AddQuestNPCToArea( oArea, "manus");
 }
 else if( sAreaTag == "jail2")
 { AddQuestNPCToArea( oArea, "Mayor");
 }
 else if( sAreaTag == "clairesbooks")
 { AddQuestNPCToArea( oArea, "claire");
 }
 else if( sAreaTag == "SashasScrollShop")
 { AddQuestNPCToArea( oArea, "Sasha");
 }
  else if( sAreaTag == "jail")
 { AddQuestNPCToArea( oArea, "Guard");
   AddQuestNPCToArea( oArea, "JailPermanentResident");
 }
 else if( sAreaTag == "NoriosBrews")
 { AddQuestNPCToArea( oArea, "Norio");
 }
 else if( sAreaTag == "customarmorshop")
 { AddQuestNPCToArea( oArea, "TheNamer");
 }
 else if( sAreaTag == "Temple")
 { AddQuestNPCToArea( oArea, "leena");
 }
 else if( sAreaTag == "KusilsForge")
 { AddQuestNPCToArea( oArea, "omegasmith02");
 }
 else if( sAreaTag == "HorseFarmHouseBoutique")
 { AddQuestNPCToArea( oArea, "Holly");
   AddQuestNPCToArea( oArea, "TailoringModel");
   AddQuestNPCToArea( oArea, "TailoringModel2");
   AddQuestNPCToArea( oArea, "TailoringModel3");
   AddQuestNPCToArea( oArea, "TailoringModel4");
 }
 else if( sAreaTag == "_module")
 { AddQuestNPCToArea( oArea, "Kate");
 }
 else if( sAreaTag == "DM_Forge")
 { AddQuestNPCToArea( oArea, "omegasmith01");
   AddQuestNPCToArea( oArea, "omegasmith5");
   AddQuestNPCToArea( oArea, "omegasmith4");
 }
 else if( sAreaTag == "ODCforgebarracks")
 { AddQuestNPCToArea( oArea, "omegasmith03");
 }
 else if( sAreaTag == "FrostKeep")
 { AddQuestNPCToArea( oArea, "Guard4");
   AddQuestNPCToArea( oArea, "Guard3");
   AddQuestNPCToArea( oArea, "sb");
   AddQuestNPCToArea( oArea, "Guard10");
   AddQuestNPCToArea( oArea, "Guard2");
   AddQuestNPCToArea( oArea, "frostkeepgateguard1");
   AddQuestNPCToArea( oArea, "frostkeepgateguard2");
   AddQuestNPCToArea( oArea, "CaptainSamantha");
   AddQuestNPCToArea( oArea, "CaptainKorin");
 }
 else if( sAreaTag == "TikisTailor")
 { AddQuestNPCToArea( oArea, "tikis");
 }
  else if( sAreaTag == "OldHalsHut")
 { AddQuestNPCToArea( oArea, "Halaster");
 }
  else if( sAreaTag == "OldBlackStoneInn")
 { AddQuestNPCToArea( oArea, "Rolo");
 }
  else if( sAreaTag == "PawnShop")
 { AddQuestNPCToArea( oArea, "Lucky");
 }
  else if( sAreaTag == "LinksTrinkets")
 { AddQuestNPCToArea( oArea, "links");
 }
  else if( sAreaTag == "temple")
 { AddQuestNPCToArea( oArea, "guss");
 }
 else if( sAreaTag == "drunkenbarbarian")
 { AddQuestNPCToArea( oArea, "NW_BARTENDER");
   AddQuestNPCToArea( oArea, "helga");
   AddQuestNPCToArea( oArea, "elring");
 }
 else if( sAreaTag == "FrostKeepOutPost")
 { AddQuestNPCToArea( oArea, "Guard11");
   AddQuestNPCToArea( oArea, "OutPostGuard");
   AddQuestNPCToArea( oArea, "General");
 }
 else if( sAreaTag == "OutPostStorage")
 { AddQuestNPCToArea( oArea, "Legan");
 }
 else if( sAreaTag == "chateau")
 { AddQuestNPCToArea( oArea, "fing");
 }
 else if( sAreaTag == "WolfShire")
 { AddQuestNPCToArea( oArea, "Oberon");
 }
 else if( sAreaTag == "WinterAlePub")
 { AddQuestNPCToArea( oArea, "Lolir");
 }
 else if( sAreaTag == "winterkeepbarracks")
 { AddQuestNPCToArea( oArea, "CaptainoftheGuard");
 }
 else if( sAreaTag == "OutPostBarracks")
 { AddQuestNPCToArea( oArea, "Moigan");
 }
 else if( sAreaTag == "RusIslandHavenKeep")
 { AddQuestNPCToArea( oArea, "CaptainoftheGuard");
 }
 else if( sAreaTag == "RusIslandTemple")
 { AddQuestNPCToArea( oArea, "Father_Richo");
 }
 else if( sAreaTag == "RusIsleInn1stFloor")
 { AddQuestNPCToArea( oArea, "Morris");
   AddQuestNPCToArea( oArea, "MrsBingle");
 }
  else if( sAreaTag == "RusIsleBuildingInteriors")
 { AddQuestNPCToArea( oArea, "Toma");
 }
  else if( sAreaTag == "RusIsleHavenSmithy")
 { AddQuestNPCToArea( oArea, "Lagnar");
 }
 else if( sAreaTag == "WatersEdge")
 { AddQuestNPCToArea( oArea, "captcliff");
 }
 else if( sAreaTag == "RusIslePirateHaven")
 { AddQuestNPCToArea( oArea, "captcliff2");
 }
 else if( sAreaTag == "Caravan")
 { AddQuestNPCToArea( oArea, "InnKeeper");
 }
  else if( sAreaTag == "cityofmadness")
 { AddQuestNPCToArea( oArea, "CaptainKorin2");
 }
   else if( sAreaTag == "hunterslodge")
 { AddQuestNPCToArea( oArea, "Potion_11");
 }
   else if( sAreaTag == "RusIsleGeneralStore")
 { AddQuestNPCToArea( oArea, "Vens");
 }
  else if( sAreaTag == "los")
 { AddQuestNPCToArea( oArea, "servant");
 }
   else if( sAreaTag == "postoffice")
 { AddQuestNPCToArea( oArea, "notes_postman");
 }
   else if( sAreaTag == "thegrandhall")
 { AddQuestNPCToArea( oArea, "NW_IMP");
 }
   else if( sAreaTag == "frostmug")
 { AddQuestNPCToArea( oArea, "Gormak");
   AddQuestNPCToArea( oArea, "Merise");
 }
    else if( sAreaTag == "WinterKeepBank")
 { AddQuestNPCToArea( oArea, "BrinToris");
 }
 // ... etc for all areas containing quest NPCs

}
int GetIsNPCInArea( string sNPCTag, object oArea)
{ if( (sNPCTag == "") || !GetIsObjectValid( oArea) || (GetArea( oArea) != oArea)) return FALSE;

 object oFirst = GetFirstObjectInArea( oArea);
 if( (GetObjectType( oFirst) == OBJECT_TYPE_CREATURE) && (GetTag( oFirst) == sNPCTag)) return TRUE;

 int iNth = 1;
 object oNPC = GetNearestObjectByTag( sNPCTag, oFirst);
 while( GetIsObjectValid( oNPC))
 { if( GetObjectType( oNPC) == OBJECT_TYPE_CREATURE) return TRUE;
   oNPC = GetNearestObjectByTag( sNPCTag, oFirst, ++iNth);
 }
 return FALSE;
}
object GetWaypointInArea( string sWaypointTag, object oArea)
{ if( (sWaypointTag == "") || !GetIsObjectValid( oArea) || (GetArea( oArea) != oArea)) return OBJECT_INVALID;

 object oFirst = GetFirstObjectInArea( oArea);
 if( GetTag( oFirst) == sWaypointTag) return oFirst;

 return GetNearestObjectByTag( sWaypointTag, oFirst);
}
void SpawnQuestNPCsIntoArea( object oArea)
{ if( !GetIsObjectValid( oArea) || (GetArea( oArea) != oArea)) return;
 InitializeQuestNPCsInArea( oArea);
 int iNPC = GetLocalInt( oArea, "QuestNPCCount") +1;
 while( --iNPC > 0)
 { string sNPCTag = GetLocalString( oArea, "QuestNPC_" +IntToString( iNPC));
   if( (sNPCTag != "") && !GetIsNPCInArea( sNPCTag, oArea))
   { struct NPCinfo stQuestNPC = GetQuestNPCInfo( sNPCTag);
     if( (stQuestNPC.resref != "") && (stQuestNPC.waypoint != ""))
     { object oWaypoint = GetWaypointInArea( stQuestNPC.waypoint, oArea);
       if( GetIsObjectValid( oWaypoint)) CreateObject( OBJECT_TYPE_CREATURE, stQuestNPC.resref, GetLocation( oWaypoint), FALSE, sNPCTag);
     }
   }
 }
}
               
               

               


                     Modifié par Knight_Shield, 22 février 2012 - 09:47 .