#include "rd_spawnzones"
//#include "rd_misc"
#include "rd_quests"

void InitiateQuest(object oPC,object oGiver);
void GetNextStep(object oPC,object oGiver);
void SetupQuestStep(int iQuest, int iStep, object oPC, object oGiver);
object GetQuestItem(object oPC, object oBoss, object oSender, string sTag = "");
object GetRandomQuestMobs(object oPC, object oSender, int iRaceOnly=0, string sTag = "");
string GetQuestMob(object oPC, int iRaceOnly=0);
object GetQuestCreatures(object oPC,string sCampType, int iBase, int iBaseStart, int iBaseMax, int iCampType);
object GetQuestCamp(object oPC, object oSender, string sQuestCampType = "", int iSpecificZone = 0);
object GetDungeonCamp(object oPC, object oSender, string sQuestCampType = "", int iSpecificZone = 0);
int GetPrisoners(object oBoss,int iChance = 1);
int GetMaxQuestSpots(string sZone);
int GetMaxQuestCampSpots(string sZone);
void GetRandomThankyou();
string GetQuestItemTag(object oPC);
void GetDelivery(object oPC, object oSender, string sTag = "",string sNPC="");
object GetEscort(object oPC,object oSender, string sEscort = "", string sNPC = "");
string GetRandomDeliveryNPC(object oArea);
string GetDeliveryQuestItemTag(object oPC);
string GetAmbush(object oPC, int iAlways = FALSE, string sTag = "");
string GetAttackers(object oPC, object oSender, int iAlways = FALSE, string sTag = "");
string FixTokenLine(string sTokenLine, string sTokenFromStep);
int GetItemQuest(object oPC, int iQuest, int iMaxQuests);
void SetupZone(object oPC);
int GetRandomQuestGiver();
int GetRandomEvilQuestNPC();
void GetSpecialTreasure(object oZone);
void GetNPCQuestHelperList(object oZone);
void AddNPCQuestHelper(string sNPCHelper);
object GetSpecificCamp(object oPC, object oSender, string sZone, int iCamp, string sQuestCampType = "");
location RandomLoc(object oLoc);

void InitiateQuest(object oPC,object oGiver)
{
int iRandom;
int iQuest;
int iQuestStepType;

SetToken(oPC,oGiver,110,"Thank you.");

SetPartyString(oPC,"QuestStep1Token111","REPEAT");
SetPartyString(oPC,"QuestStep1Token112","REPEAT");
SetPartyString(oPC,"QuestStep1Token113","REPEAT");


iRandom = Random(100);
//iRandom = 99;

if (iRandom < 50)
    {
    iQuest = Random(8)+1;
    //iQuest=5;
    SetPartyInt(oPC,"QuestSteps",1);
    iQuestStepType = iQuest;
    }
else if (iRandom < 80)
    {
    iQuest = Random(3)+1;
    switch (iQuest)
        {
        case 1: iQuestStepType = GetQuest1(oPC); break;
        case 2: iQuestStepType = GetQuest2(oPC); break;
        case 3: iQuestStepType = GetQuest3(oPC); break;
        }
    }
else if (iRandom < 100)
    {
    iQuest = Random(8)+1;
    iQuest = GetItemQuest(oPC,iQuest,8);
    //iQuest=8;

    switch (iQuest)
        {
        case 1: iQuestStepType = GetItemQuest1(oPC); break;
        case 2: iQuestStepType = GetItemQuest2(oPC); break;
        case 3: iQuestStepType = GetItemQuest3(oPC); break;
        case 4: iQuestStepType = GetItemQuest4(oPC); break;
        case 5: iQuestStepType = GetItemQuest5(oPC); break;
        case 6: iQuestStepType = GetItemQuest6(oPC); break;
        case 7: iQuestStepType = GetItemQuest7(oPC); break;
        case 8: iQuestStepType = GetItemQuest8(oPC); break;
        }
    }
else
    {
    SetPartyInt(oPC,"QuestSteps",1);
    iQuestStepType = 1;
    }

SetPartyInt(oPC,"Quest",iQuest);
SetPartyInt(oPC,"QuestStep",1);
SetPartyString(oPC,"QuestGiver",GetTag(oGiver));
SetPartyString(oPC,"QuestZone",GetZone(oPC));
SetLocalInt(GetModule(),GetZone(oPC),1);
SetPartyInt(oPC,"QuestDone",0);

SetupQuestStep(iQuestStepType,1,oPC,oGiver);
}

void GetNextStep(object oPC,object oGiver)
{
int iStep;
int iSteps;
int iStepType;

iSteps = GetLocalInt(oPC,"QuestSteps");
iStep = GetLocalInt(oPC,"QuestStep");

//SendMessageToPC(GetFirstPC(),"iStep : " + IntToString(iStep));
//SendMessageToPC(GetFirstPC(),"iSteps : " + IntToString(iSteps));

if (iStep < iSteps)
    {
    iStep++;
    iStepType = GetLocalInt(oPC,"QuestStep" + IntToString(iStep));
    SetupQuestStep(iStepType,iStep,oPC,oGiver);
    } else {
    SetPartyInt(oPC,"QuestDone",1);
    }

}

void SetupQuestStep(int iStepType, int iStep, object oPC,object oGiver)
{
int iQuestType;
int iItemUnknown;
string sCampTag;
string sAmbush;
string sCampDescription;
string sCampLocation;
string sGiver;
string sTag;
string sTokenLine;
string sAttackers;
string sQuestStep;
string sItemTag;
string sOldCamp;
string sToken111;
string sToken112;
string sToken113;
string sResponse;
string sOldItem;
string sEscort;
string sOldEscort;
string sReply;
object oBoss;
object oItem;

//SendMessageToPC(GetFirstPC(),"QuestStepType : " + IntToString(iStepType));
//SendMessageToPC(GetFirstPC(),"QuestStep : " + IntToString(iStep));

//CustomTokens
//101 = description of camp
//102 = location of camp
//103 = quest giver
//104 = item name
//105 = Boss name
//106 = NPC name
//107 = NPC location
//108 = Attackers
//99 = Random Thankyou
//110 = Quest Response
//120 = Quest Reply
//111-113 = Quest Information

SetPartyInt(oPC,"QuestStep",iStep);

SetCustomToken(111, "");
SetCustomToken(112, "");
SetCustomToken(113, "");

sGiver = GetName(oGiver);
SetToken(oPC,oGiver,103,sGiver);

GetRandomThankyou();

sQuestStep = "QuestStep" + IntToString(iStep);
sCampTag = GetLocalString(oPC,sQuestStep + "Mob");
sOldCamp = GetLocalString(oPC,"QuestCampType");
sOldItem = GetLocalString(oPC,"QuestItemTag");
sItemTag = GetLocalString(oPC,sQuestStep + "Item");
sOldEscort = GetLocalString(oPC,"QuestEscort");
sEscort = GetLocalString(oPC,sQuestStep + "Escort");
sToken111 = GetLocalString(oPC,sQuestStep + "Token111");
sToken112 = GetLocalString(oPC,sQuestStep + "Token112");
sToken113 = GetLocalString(oPC,sQuestStep + "Token113");

iItemUnknown = GetLocalInt(oPC,sQuestStep + "ItemUnknown");
SetPartyInt(oPC,"QuestItemUnknown",iItemUnknown);

sResponse = GetLocalString(oPC,sQuestStep + "Response");
if (sResponse == "")
    sResponse = "Thank you.";
SetToken(oPC,oGiver,110,sResponse);

sReply = GetLocalString(oPC,sQuestStep + "Reply");
if (sReply == "")
    sReply = "What do you need?";
SetToken(oPC,oGiver,120,sReply);


if (sCampTag == "REPEAT")
    sCampTag = sOldCamp;

//SendMessageToPC(GetFirstPC(),"Item = " + sItemTag + " | Old Item = " + sOldItem);

if (sItemTag == "REPEAT")
    sItemTag = sOldItem;

if (iStepType == 1)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetQuestCamp(oPC,oGiver,sCampTag);
    GetPrisoners(oBoss);
    SetPartyString(oPC,"QuestItemTag","");
    sTokenLine = "I spotted a some " + GetToken(101) + " and tracked them back to a full camp of " + GetToken(101) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " are located " + GetToken(102) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    sTokenLine = "I will reward you if you can eliminate them.";
    sTokenLine = FixTokenLine(sTokenLine,sToken113);
    SetToken(oPC,oGiver,113,sTokenLine);
    }

if (iStepType == 2)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetQuestCamp(oPC,oGiver,sCampTag);
    oItem = GetQuestItem(oPC,oBoss,oGiver,sItemTag);
    sTokenLine ="A " + GetToken(105) + " stole my " + GetToken(104) + ". I tracked the " + GetToken(105) + " but there were too many " + GetToken(101) + " for me.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " are located " + GetToken(102) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    sTokenLine ="If you could retrieve my " + GetToken(104) + " I would be grateful.";
    sTokenLine = FixTokenLine(sTokenLine,sToken113);
    SetToken(oPC,oGiver,113,sTokenLine);
    GetPrisoners(oBoss);
    }

if (iStepType == 3)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetRandomQuestMobs(oPC,oGiver,0,sCampTag);
    SetPartyString(oPC,"QuestItemTag","");
    sTokenLine = "I spotted a " + GetToken(101) + " and followed it, but it met up with others of its kind.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " and its brethen are located " + GetToken(102);
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    }

if (iStepType == 4)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetRandomQuestMobs(oPC,oGiver,0,sCampTag);
    oItem = GetQuestItem(oPC,oBoss,oGiver,sItemTag);
    sTokenLine = "A " + GetToken(101) + " stole my " + GetToken(104) + ".  I tracked the " + GetToken(101) + " but there were too many for me.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " and its brethen are located " + GetToken(102);
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    sTokenLine = "If you could retrieve my " + GetToken(104) + " I would be grateful.";
    sTokenLine = FixTokenLine(sTokenLine,sToken113);
    SetToken(oPC,oGiver,113,sTokenLine);
    }

if (iStepType == 5)
    {
    GetDelivery(oPC,oGiver,sItemTag);
    sAmbush = GetAmbush(oPC);
    sAttackers = GetAttackers(oPC, oGiver);
    sTokenLine = "I am very busy, else I would do this myself.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "I need you to deliver this " + GetToken(104) + " to " + GetToken(106) + " located " + GetToken(107) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    if (sAttackers != "")
        {
        sTokenLine = "I have word that " + GetToken(108) + " might try and stop you, so beware.";
        sTokenLine = FixTokenLine(sTokenLine,sToken113);
        SetToken(oPC,oGiver,113,sTokenLine);
        }
    }

if (iStepType == 6)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetDungeonCamp(oPC,oGiver,sCampTag);
    GetPrisoners(oBoss);
    SetPartyString(oPC,"QuestItemTag","");
    sTokenLine = "I have word of some " + GetToken(101) + " hiding out in the area.  We cannot allow their presence to grow stronger.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " are located " + GetToken(102) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    sTokenLine = "I will reward you if you can eliminate them.";
    sTokenLine = FixTokenLine(sTokenLine,sToken113);
    SetToken(oPC,oGiver,113,sTokenLine);
    }

if (iStepType == 7)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    oBoss = GetDungeonCamp(oPC,oGiver,sCampTag);
    oItem = GetQuestItem(oPC,oBoss,oGiver,sItemTag);
    if (Random(2)==0)
        sTokenLine ="A " + GetToken(105) + " stole my " + GetToken(104) + ". I tracked the " + GetToken(105) + " but there were too many " + GetToken(101) + " for me.";
    else
        sTokenLine ="I lost my " + GetToken(104) + ".  But, when I went back to where I think I lost it some " + GetToken(101) + " were hanging around.";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "The " + GetToken(101) + " are located " + GetToken(102) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    sTokenLine ="If you could retrieve my " + GetToken(104) + " I would be grateful.";
    sTokenLine = FixTokenLine(sTokenLine,sToken113);
    SetToken(oPC,oGiver,113,sTokenLine);
    GetPrisoners(oBoss);
    }

if (iStepType == 8)
    {
    SetPartyInt(oPC,"QuestStep",iStep);
    SetPartyString(oPC,"QuestItemTag","");
    oBoss = GetEscort(oPC,oGiver,sEscort);
    sAttackers = GetAttackers(oPC, oGiver);
    sTokenLine = "I need you to escort a " + GetToken(104) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken111);
    SetToken(oPC,oGiver,111,sTokenLine);
    sTokenLine = "They need to get to " + GetToken(106) + " located " + GetToken(107) + ".";
    sTokenLine = FixTokenLine(sTokenLine,sToken112);
    SetToken(oPC,oGiver,112,sTokenLine);
    }

iQuestType = GetLocalInt(oPC,"QuestType");

RemoveJournalQuestEntry("jDelivery",oPC);
RemoveJournalQuestEntry("jCamp",oPC);

if (iQuestType == 1)
    AddJournalQuestEntry("jCamp",1,oPC);
else
    AddJournalQuestEntry("jDelivery",1,oPC);

}

void GetDelivery(object oPC, object oSender, string sTag = "",string sNPC="")
{
string sRandomNPC;
string sLocation;
object oItem;
object oNPC;
object oWP;

if (sNPC == "")
    sRandomNPC = GetRandomDeliveryNPC(GetArea(oSender));
else
    sRandomNPC = sNPC;

if (sTag == "")
    sTag = GetDeliveryQuestItemTag(oPC);

oItem = CreateItemOnObject(sTag,oPC);

oNPC = GetObjectByTag(sRandomNPC);
oWP = GetObjectByTag("POST_" + sRandomNPC);
sLocation = GetLocalString(oWP,"Description");

SetToken(oPC,oSender,104,GetName(oItem));
SetToken(oPC,oSender,106,GetName(oNPC));
SetToken(oPC,oSender,107,sLocation);

SetPartyInt(oPC,"QuestType",2);
SetPartyString(oPC,"QuestTargetNPC",sRandomNPC);
SetPartyString(oPC,"QuestItemTag",sTag);
}

object GetEscort(object oPC, object oSender, string sEscort = "", string sNPC = "")
{
string sLocation;
object oNPC;
object oEscort;
object oWP;

if (sEscort == "")
    sEscort = "en4_merchant" + IntToString(Random(2)+1);

if (sNPC == "")
    sNPC = GetRandomDeliveryNPC(GetArea(oPC));

oEscort = CreateObject(OBJECT_TYPE_CREATURE,sEscort,GetLocation(oPC));
AddHenchman(oPC,oEscort);

oNPC = GetObjectByTag(sNPC);
oWP = GetObjectByTag("POST_" + sNPC);
sLocation = GetLocalString(oWP,"Description");

SetToken(oPC,oSender,104,GetName(oEscort));
SetToken(oPC,oSender,106,GetName(oNPC));
SetToken(oPC,oSender,107,sLocation);

SetPartyInt(oPC,"QuestType",3);
SetPartyString(oPC,"QuestTargetNPC",sNPC);
SetPartyString(oPC,"QuestEscort",sEscort);

return oEscort;
}

string GetRandomDeliveryNPC(object oArea)
{
int iQuestNPCs;
int iRandom;
string sQuestNPC;
object oNPC;

iQuestNPCs = GetLocalInt(oArea,"QuestNPCs");

if (iQuestNPCs > 0)
    {
    iRandom = Random(iQuestNPCs) + 1;
    sQuestNPC = GetLocalString(oArea,"QuestNPC" + IntToString(iRandom));
    oNPC = GetObjectByTag(sQuestNPC);
    if (!GetIsObjectValid(oNPC))
        SendMessageToPC(GetFirstPC(),"Did not find " + sQuestNPC + ", if he has been killed he can be revived in the Church in Hightop City.");
    } else {
    sQuestNPC = "INSERT FALLBACK QUEST NPC HERE";
    }

return sQuestNPC;
}

string GetAttackers(object oPC, object oSender, int iAlways = FALSE, string sTag = "")
{
object oMod;
string sCampType;
string sAttackers;
int iDifficulty;
int iFlag;

if (Random(2) == 0)
    iFlag = TRUE;

if (iAlways == TRUE)
    iFlag = TRUE;

sCampType = "";
if (iFlag == TRUE)
    {
    oMod = GetModule();

    if (sTag == "")
        sCampType = GetQuestMob(oPC,1);
    else
        sCampType = sTag;

    SetLocalString(oPC,"QuestAttackers",sCampType);

    sAttackers = GetLocalString(oMod,"sCD");
    SetToken(oPC,oSender,108,sAttackers);

    SetLocalInt(oMod,"iBase",0);
    SetLocalInt(oMod,"iBaseStart",0);
    SetLocalInt(oMod,"iBaseMax",0);
    SetLocalInt(oMod,"iCampType",0);
    SetLocalString(oMod,"sCD","");

    iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
    iDifficulty++;
    SetPartyInt(oPC,"QuestDifficulty",iDifficulty);
    }

return sCampType;
}

string GetAmbush(object oPC, int iAlways = FALSE, string sTag = "")
{
int iDifficulty;
int iBase;
int iBaseStart;
int iBaseMax;
int iCampType;
int iLevel;
int iAdjustedLevel;
int iCreatureLevel;
int iCreatures;
int iIndex;
object oMod;
object oCreature;
object oGuard;
string sCampType;
string sNPC;
string sGuardTag;
int iFlag;

if (Random(2) == 0)
    iFlag = TRUE;

if (iAlways == TRUE)
    iFlag = TRUE;

sCampType = "";
if (iFlag == TRUE)
    {
    oMod = GetModule();

    sCampType = GetQuestMob(oPC,1);
    iBase = GetLocalInt(oMod,"iBase");
    iBaseStart = GetLocalInt(oMod,"iBaseStart");
    iBaseMax = GetLocalInt(oMod,"iBaseMax");
    iCampType = GetLocalInt(oMod,"iCampType");
    SetLocalInt(oMod,"iBase",0);
    SetLocalInt(oMod,"iBaseStart",0);
    SetLocalInt(oMod,"iBaseMax",0);
    SetLocalInt(oMod,"iCampType",0);
    SetLocalString(oMod,"sCD","");

    iLevel = GetHitDice(oPC);
    iAdjustedLevel = GetAdjustedLevel(oPC);
    iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

    iCreatureLevel = Random(3)+1;

    sNPC=GetLocalString(oPC,"QuestTargetNPC");

    sGuardTag = "AMBUSH_" + sNPC;
    oGuard = GetObjectByTag(sGuardTag);

    if (GetIsObjectValid(oGuard))
        {
        iCreatures = Random(3)+2;

        if (iLevel < 3 && iCreatures >2)
            iCreatures = 2;

        if (iLevel < 5 && iCreatures == 4)
            iCreatures = 3;

        iIndex = 1;
        while (iIndex <= iCreatures)
            {
            oCreature = GetCampMob(iCreatureLevel,sGuardTag,sCampType,iAdjustedLevel,iBaseStart,iBase,iBaseMax,iCampType, 0);
            //if (Random(4) == 0)
            //    {
                AssignCommand(oCreature,ActionRandomWalk());
                DelayCommand(6.0f,AssignCommand(oCreature,ClearAllActions()));
            //    }
            iIndex++;
            }
        }

    iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
    iDifficulty++;
    SetPartyInt(oPC,"QuestDifficulty",iDifficulty);
    }

return sCampType;
}

object GetQuestItem(object oPC, object oBoss, object oSender, string sTag = "")
{
object oItem;

if (sTag == "")
    sTag = GetQuestItemTag(oPC);

oItem=CreateItemOnObject(sTag,oBoss);
SetPartyString(oPC,"QuestItemTag",sTag);
SetToken(oPC,oSender,104,GetName(oItem));

return oItem;
}

object GetRandomQuestMobs(object oPC, object oSender, int iRaceOnly=0, string sTag = "")
{
object oCreature;
string sCampType;
string sCampDescription;
string sLocation;
int iDifficulty;
int iBase;
int iBaseStart;
int iBaseMax;
int iCampType;
object oMod;

oMod = GetModule();

if (sTag == "")
    sCampType = GetQuestMob(oPC,iRaceOnly);
else
    sCampType = GetSpecificCampType(sTag);

iBase = GetLocalInt(oMod,"iBase");
iBaseStart = GetLocalInt(oMod,"iBaseStart");
iBaseMax = GetLocalInt(oMod,"iBaseMax");
iCampType = GetLocalInt(oMod,"iCampType");
SetLocalInt(oMod,"iBase",0);
SetLocalInt(oMod,"iBaseStart",0);
SetLocalInt(oMod,"iBaseMax",0);
SetLocalInt(oMod,"iCampType",0);
SetLocalString(oMod,"sCD","");

oCreature = GetQuestCreatures(oPC,sCampType,iBase,iBaseStart,iBaseMax,iCampType);

sCampDescription = GetName(oCreature);
SetToken(oPC,oSender,101,sCampDescription);

sLocation = GetLocalString(oCreature,"Location");
SetToken(oPC,oSender,102,sLocation);

SetToken(oPC,oSender,105,GetName(oCreature));

SetLocalInt(oCreature,"iCampType",iCampType);
SetLocalString(oCreature,"sCampType",sCampType);

SetPartyInt(oPC,"QuestType",1);
SetPartyString(oPC,"QuestTargetNPC",GetTag(oSender));
//SetPartyString(oPC,"QuestCreatureTag",GetTag(oCreature));
SetPartyString(oPC,"QuestTargetMob",GetTag(oCreature));
SetPartyString(oPC,"QuestCampType",sCampType);
SetPartyInt(oPC,"QuestTargetMobDead",0);

iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
iDifficulty++;
SetPartyInt(oPC,"QuestDifficulty",iDifficulty);

return oCreature;
}

string GetQuestMob(object oPC, int iRaceOnly=0)
{
string sCampType;
int iLevel;
int iAdjustedLevel;
int iPCCount;


iLevel = GetHitDice(oPC);
iAdjustedLevel = GetAdjustedLevel(oPC);
iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

//Setup for races and allow indoors only to be spookiness
SetupCampTypes(iAdjustedLevel, 1, 1, 0, iRaceOnly);
sCampType = GetCampType();

return sCampType;
}

object GetQuestCreatures(object oPC,string sCampType, int iBase, int iBaseStart, int iBaseMax, int iCampType)
{
string sZone;
string sTag;
int iMaxSpots;
int iSpawn;
int iCreatureLevel;
int iCreatures;
int iIndex;
int iLevel;
object oCreature;
object oWP;
int iAdjustedLevel;
int iPCCount;

sZone = GetZone(oPC);
iMaxSpots = GetMaxQuestSpots(sZone);
iSpawn = Random(iMaxSpots)+1;
sTag = sZone + "_Q_" + IntToString(iSpawn);

iLevel = GetHitDice(oPC);
iAdjustedLevel = GetAdjustedLevel(oPC);
iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

iCreatureLevel = Random(3)+1;
iCreatures = Random(3)+2;
iIndex = 1;

while (iIndex <= iCreatures)
    {
    oCreature = GetCampMob(iCreatureLevel,sTag,sCampType,iAdjustedLevel,iBaseStart,iBase,iBaseMax,iCampType, 0);
    //SendMessageToPC(oPC,"Spawning " + GetName(oCreature));
    iIndex++;
    }

oWP = GetObjectByTag(sTag);
SetLocalString(oCreature,"Location",GetLocalString(oWP,"Description"));

return oCreature;
}

object GetQuestCamp(object oPC, object oSender, string sQuestCampType = "", int iSpecificZone = 0)
{
object oBoss;
object oWP;
string sZone;
string sLocation;
string sCampDescription;
int iCamp;
int iCamps;
int iLevel;
int iLeader;
int iDifficulty;
int iDeathAllowed;
int iDeathAjust;
int iAdjustedLevel;
int iPCCount;


iLevel = GetHitDice(oPC);
iAdjustedLevel = GetAdjustedLevel(oPC);
iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

if (iSpecificZone == 1) //Hightop Abandoned Sewers
    sZone = "HTS2";
else if (iSpecificZone == 2) //Hightop Graveyard
    sZone = "HTCG";
else if (iSpecificZone == 3) //Hightop Crypt
    sZone = "HTCC";
else
    sZone = GetZone(oPC);

iCamps = GetMaxQuestCampSpots(sZone);
iCamp = Random(iCamps)+1;

iLeader=1;
oBoss = SpawnQuestCamp(sZone,iCamp,iAdjustedLevel,iLeader,sQuestCampType);
sQuestCampType = GetLocalString(oBoss,"CampType");
oWP = GetObjectByTag(sZone + "_Q" + IntToString(iCamp) + "_Boss");
sLocation = GetLocalString(oWP,"Description");
SetLocalString(oBoss,"Location",sLocation);

sCampDescription = GetLocalString(oBoss,"Description");
SetToken(oPC,oSender,101,sCampDescription);
SetToken(oPC,oSender,102,sLocation);
SetToken(oPC,oSender,105,GetName(oBoss));

SetPartyInt(oPC,"QuestType",1);
SetPartyInt(oPC,"QuestCamp",iCamp);
SetPartyString(oPC,"QuestCampzone",sZone);
SetPartyString(oPC,"QuestTargetNPC",GetTag(oSender));
SetPartyString(oPC,"QuestTargetMob",GetTag(oBoss));
SetPartyInt(oPC,"QuestTargetMobDead",0);
SetPartyString(oPC,"QuestCampType",sQuestCampType);

iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
iDifficulty=iDifficulty + 2;
SetPartyInt(oPC,"QuestDifficulty",iDifficulty);

return oBoss;
}

object GetDungeonCamp(object oPC, object oSender, string sQuestCampType = "", int iSpecificZone = 0)
{
object oBoss;
object oArea;
object oWP;
string sDZone;
string sLocation;
string sCampDescription;
int iCamp;
int iCamps;
int iLevel;
int iLeader;
int iDifficulty;
int iAdjustedLevel;

iLevel = GetHitDice(oPC);
iAdjustedLevel = GetAdjustedLevel(oPC);
iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

if (iSpecificZone == 1) //Hightop Abandoned Sewers
    sDZone = "HTS2";
else if (iSpecificZone == 2) //Hightop Graveyard
    sDZone = "HTCG";
else if (iSpecificZone == 3) //Hightop Crypt
    sDZone = "HTCC";
else
    sDZone = GetZoneDungeonCamp(oPC);

iCamps = GetMaxQuestCampSpots(sDZone);
iCamp = Random(iCamps)+1;

iLeader=1;
oBoss = SpawnQuestCamp(sDZone,iCamp,iAdjustedLevel,iLeader,sQuestCampType);
sQuestCampType = GetLocalString(oBoss,"CampType");
oWP = GetObjectByTag(sDZone + "_Q" + IntToString(iCamp) + "_Boss");
sLocation = GetLocalString(oWP,"Description");
SetLocalString(oBoss,"Location",sLocation);

sCampDescription = GetLocalString(oBoss,"Description");
SetToken(oPC,oSender,101,sCampDescription);
SetToken(oPC,oSender,102,sLocation);
SetToken(oPC,oSender,105,GetName(oBoss));

//reset spawned to force respawn on dungeon/cave/tower/thingy
oArea = GetArea(oBoss);
SetLocalInt(oArea,"Spawned",0);

SetPartyInt(oPC,"QuestType",1);
SetPartyInt(oPC,"QuestCamp",iCamp);
SetPartyString(oPC,"QuestCampzone",sDZone);
SetPartyString(oPC,"QuestTargetNPC",GetTag(oSender));
SetPartyString(oPC,"QuestTargetMob",GetTag(oBoss));
SetPartyInt(oPC,"QuestTargetMobDead",0);
SetPartyString(oPC,"QuestCampType",sQuestCampType);
iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
iDifficulty=iDifficulty+3;
SetPartyInt(oPC,"QuestDifficulty",iDifficulty);

return oBoss;
}

object GetSpecificCamp(object oPC, object oSender, string sZone, int iCamp, string sQuestCampType = "")
{
object oBoss;
object oWP;
//string sZone;
string sLocation;
string sCampDescription;
//int iCamp;
int iCamps;
int iLevel;
int iLeader;
int iDifficulty;
int iDeathAllowed;
int iDeathAjust;
int iAdjustedLevel;
int iPCCount;


iLevel = GetHitDice(oPC);
iAdjustedLevel = GetAdjustedLevel(oPC);
iAdjustedLevel = ZoneLevel(GetArea(oPC),iAdjustedLevel);

//sZone = GetZone(oPC);
//iCamps = GetMaxQuestCampSpots(sZone);
//iCamp = Random(iCamps)+1;

iLeader=1;
oBoss = SpawnQuestCamp(sZone,iCamp,iAdjustedLevel,iLeader,sQuestCampType);
sQuestCampType = GetLocalString(oBoss,"CampType");
oWP = GetObjectByTag(sZone + "_Q" + IntToString(iCamp) + "_Boss");
sLocation = GetLocalString(oWP,"Description");
SetLocalString(oBoss,"Location",sLocation);

sCampDescription = GetLocalString(oBoss,"Description");
SetToken(oPC,oSender,101,sCampDescription);
SetToken(oPC,oSender,102,sLocation);
SetToken(oPC,oSender,105,GetName(oBoss));

SetPartyInt(oPC,"QuestType",1);
SetPartyInt(oPC,"QuestCamp",iCamp);
SetPartyString(oPC,"QuestCampzone",sZone);
SetPartyString(oPC,"QuestTargetNPC",GetTag(oSender));
SetPartyString(oPC,"QuestTargetMob",GetTag(oBoss));
SetPartyInt(oPC,"QuestTargetMobDead",0);
SetPartyString(oPC,"QuestCampType",sQuestCampType);

iDifficulty = GetLocalInt(oPC,"QuestDifficulty");
iDifficulty=iDifficulty + 2;
SetPartyInt(oPC,"QuestDifficulty",iDifficulty);

return oBoss;
}

int GetMaxQuestSpots(string sZone)
{
string sTag;
int iIndex;
int iFlag;
object oSpawn;

iIndex = 0;
iFlag = 0;

while (iFlag==0)
    {
    iIndex++;
    sTag = sZone + "_Q_" + IntToString(iIndex);
    oSpawn=GetObjectByTag(sTag);
    if (!(GetIsObjectValid(oSpawn)))
        iFlag = 1;
    }
iIndex--;

return iIndex;
}

int GetMaxQuestCampSpots(string sZone)
{
string sTag;
int iIndex;
int iFlag;
object oSpawn;

iIndex = 0;
iFlag = 0;

while (iFlag==0)
    {
    iIndex++;
    sTag = sZone + "_Q" + IntToString(iIndex) + "_Boss";
    oSpawn=GetObjectByTag(sTag);
    if (!(GetIsObjectValid(oSpawn)))
        iFlag = 1;
    }
iIndex--;

return iIndex;
}

int GetPrisoners(object oBoss,int iChance = 1)
{
location lHostage;
string sHostage;
int iCount;
int iRandom;

iCount = 0;

if (GetLocalInt(oBoss,"iCampType") == 1)
        {
        iRandom = Random(10) + 1;
        if (iRandom<=iChance)
            {
            iCount++;
            lHostage = GetLocation(oBoss);
            sHostage = "en3_hostage" + IntToString(Random(6)+1);
            CreateObject(OBJECT_TYPE_CREATURE,sHostage,lHostage);
            if (Random(4)==0)
                {
                iCount++;
                sHostage = "en3_hostage" + IntToString(Random(6)+1);
                CreateObject(OBJECT_TYPE_CREATURE,sHostage,lHostage);
                }
            }
        }
return iCount;
}

string GetQuestItemTag(object oPC)
{
int iRandom;
int iDialogue;
string sTag;

sTag = "en4_qamulet1";

iDialogue = 1;
iRandom = Random(4)+1;

switch (iRandom)
    {
    case 1: sTag = "en4_qamulet1"; break;
    case 2: sTag = "en4_ring1"; break;
    case 3: sTag = "en4_pendant1"; break;
    case 4: sTag = "en4_ring2"; break;
    }

//SetPartyInt(oPC,"QuestDialogue",iDialogue);

return sTag;
}

string GetDeliveryQuestItemTag(object oPC)
{
int iRandom;
int iDialogue;
string sTag;

sTag = "en4_letter1";

iDialogue = 1;
iRandom = Random(1)+1;
iRandom = 2;

switch (iRandom)
    {
    case 1: sTag = "en4_letter1"; break;
    case 2: sTag = "en4_letter1"; iDialogue = 2; break;
    }

SetPartyInt(oPC,"QuestDialogue",iDialogue);

return sTag;
}

void GetRandomThankyou()
{
string sThankyou;
int iRandom;

iRandom = Random(5)+1;
switch (iRandom)
    {
    case 1: sThankyou = "Thanks"; break;
    case 2: sThankyou = "Excellent"; break;
    case 3: sThankyou = "Awesome"; break;
    case 4: sThankyou = "Good job"; break;
    case 5: sThankyou = "Well done"; break;
    }
SetCustomToken(99,sThankyou);
}

string FixTokenLine(string sTokenLine, string sTokenFromStep)
{
string sToken;
string sLeft;
string sRight;
int iPlace;

if (sTokenFromStep == "REPEAT")
    sToken = sTokenLine;
else
    sToken = sTokenFromStep;


iPlace = FindSubString(sToken,"[101]");
if (iPlace>0)
    {
    sLeft=GetStringLeft(sToken,iPlace);
    sRight=GetSubString(sToken,iPlace+5,GetStringLength(sToken)-iPlace);
    sToken = sLeft + GetToken(101) + sRight;
    }

iPlace = FindSubString(sToken,"[101]");
if (iPlace>0)
    {
    sLeft=GetStringLeft(sToken,iPlace);
    sRight=GetSubString(sToken,iPlace+5,GetStringLength(sToken)-iPlace);
    sToken = sLeft + GetToken(101) + sRight;
    }

iPlace = FindSubString(sToken,"[104]");
if (iPlace>0)
    {
    sLeft=GetStringLeft(sToken,iPlace);
    sRight=GetSubString(sToken,iPlace+5,GetStringLength(sToken)-iPlace);
    sToken = sLeft + GetToken(104) + sRight;
}

iPlace = FindSubString(sToken,"[105]");
if (iPlace>0)
    {
    sLeft=GetStringLeft(sToken,iPlace);
    sRight=GetSubString(sToken,iPlace+5,GetStringLength(sToken)-iPlace);
    sToken = sLeft + GetToken(105) + sRight;
    }

return sToken;
}

int GetItemQuest(object oPC, int iQuest, int iMaxQuests)
{
int iFlag;
int iOriginalQuest;

iOriginalQuest = iQuest;

if (GetLocalInt(oPC,"ItemQuest" + IntToString(iQuest)) == 1)
    iQuest = Random(iMaxQuests) + 1;

if (GetLocalInt(oPC,"ItemQuest" + IntToString(iQuest)) == 1)
    iQuest = Random(iMaxQuests) + 1;

if (GetLocalInt(oPC,"ItemQuest" + IntToString(iQuest)) == 1)
    {
    iOriginalQuest = iQuest;
    iFlag = 0;
    while (iFlag == 0)
        {
        iQuest++;
        if (GetLocalInt(oPC,"ItemQuest" + IntToString(iQuest)) == 0)
            iFlag = 1;
        if (iQuest >= iMaxQuests)
            iQuest = 0;
        if (iQuest == iOriginalQuest)
            iFlag = 1;
        }
    }

return iQuest;
}

void SetupZone(object oPC)
{
int iRandom;
int iRandomNPC;
int iRandomSpot;
int iIndex;
string sNPC;
string sNPCLoc;
string sLocation;
object oNPC;
object oWP;
location lLoc;

Randomize();

SetLocalInt(GetArea(oPC),"X2_L_WILD_MAGIC",TRUE);
SetLocalInt(GetArea(oPC),"EN4_SetupZone",1);
sLocation = GetZone(oPC);

iRandom = Random(3)+1;
WriteTimestampedLogEntry(sLocation + " spawned " + IntToString (iRandom) + " Questgivers");
iIndex = 0;

while (iIndex < iRandom)
    {
    iIndex++;
    iRandomNPC = GetRandomQuestGiver();
    sNPC = "en4_questgiver" + IntToString(iRandomNPC);
    iRandomSpot = Random(4)+1;
    sNPCLoc = sLocation + "_QuestGiver" + IntToString(iRandomSpot);

    if (sNPCLoc == "RP1_QuestGiver4")
        lLoc = GetLocation(GetObjectByTag(sNPCLoc));
    else
        lLoc = RandomLoc(GetObjectByTag(sNPCLoc));
    oNPC = CreateObject(OBJECT_TYPE_CREATURE, sNPC, lLoc);

    if (!GetIsObjectValid(oNPC))
        oNPC = CreateObject(OBJECT_TYPE_CREATURE, sNPC, GetLocation(GetObjectByTag(sNPCLoc)));
    //AssignCommand(oNPC,ActionRandomWalk());
    //DelayCommand(12.0f,AssignCommand(oNPC,ClearAllActions()));
    if (GetIsObjectValid(oNPC))
        {
        WriteTimestampedLogEntry(GetName(oNPC) + " spawned at " + sNPCLoc);
        } else {
        WriteTimestampedLogEntry(sNPC + " failed to spawn at " + sNPCLoc);
        //SendMessageToPC(GetFirstPC(),"ERROR: " + sNPC + " failed to spawn at " + sNPCLoc);
        }
    }

GetSpecialTreasure(GetArea(oPC));
GetNPCQuestHelperList(GetArea(oPC));

if (Random(5)==0)
    RandomEvent(oPC,sLocation);

}

int GetRandomQuestGiver()
{
int iRandomNPC;
int iMaxNPC;
int iStartRandom;
int iFlag;
string sTag;

//QuestNPC
iMaxNPC = 42;
iRandomNPC = Random(iMaxNPC)+1;
iStartRandom = iRandomNPC;

iFlag = 0;
while (iFlag == 0)
    {
    sTag = "en4_questgiver" + IntToString(iRandomNPC);
    if (GetLocalInt(GetModule(),sTag) == 0)
        {
        iFlag = 1;
        SetLocalInt(GetModule(),sTag,1);
        } else {
        iRandomNPC++;
        if (iRandomNPC > iMaxNPC)
            iRandomNPC = 1;
        if (iRandomNPC == iStartRandom)
            iFlag = 1;
        }
    }

return iRandomNPC;
}

int GetRandomEvilQuestNPC()
{
int iRandomNPC;
int iMaxNPC;
int iStartRandom;
int iFlag;
string sTag;

iMaxNPC = 8;
iRandomNPC = Random(iMaxNPC)+1;
iStartRandom = iRandomNPC;

iFlag = 0;
while (iFlag == 0)
    {
    sTag = "rd_evilquest" + IntToString(iRandomNPC);
    if (GetLocalInt(GetModule(),sTag) == 0)
        {
        iFlag = 1;
        SetLocalInt(GetModule(),sTag,1);
        } else {
        iRandomNPC++;
        if (iRandomNPC > iMaxNPC)
            iRandomNPC = 1;
        if (iRandomNPC == iStartRandom)
            iFlag = 1;
        }
    }

return iRandomNPC;
}

void GetSpecialTreasure(object oZone)
{
int iRandomArea;
int iRandom;
int iFlag;
int iIndex;
int iIndex2;
int iTreasureType;
int iMaxLevel;
int iMinLevel;
string sPrefix;
string sCampTest;
string sTreasureTest;
object oEncounter;
object oTreasure;

iRandomArea = Random(3)+1;

if (iRandomArea == 1)
    sPrefix = GetLocalString(oZone,"Prefix");
else
    sPrefix = GetLocalString(oZone,"Dungeon");


iFlag = 0;
iIndex = 0;
iIndex2 = 0;
while (iFlag == 0)
    {
    iIndex++;
    sCampTest = sPrefix + "_C" + IntToString(iIndex) + "_Boss";
    oEncounter = GetObjectByTag(sCampTest);
    if (GetIsObjectValid(oEncounter))
        {
        sTreasureTest = sPrefix + "_C" + IntToString(iIndex) + "_Treasure";
        oTreasure = GetObjectByTag(sTreasureTest);
        if (GetIsObjectValid(oTreasure))
            {
            iIndex2++;
            SetLocalString(oZone,"SpecialTreasure" + IntToString(iIndex2),sTreasureTest);
            //Debug Line
            //WriteTimestampedLogEntry("Tag " + sTreasureTest + " as SpecialTreasure" + IntToString(iIndex2));
            }
        } else {
        iFlag=1;
        }
    }

iRandom = Random(iIndex2)+1;
sTreasureTest = GetLocalString(oZone,"SpecialTreasure" + IntToString(iRandom));
oTreasure = GetObjectByTag(sTreasureTest);

iMaxLevel = GetLocalInt(oZone,"MaximumLevel");
iMinLevel = GetLocalInt(oZone,"MinimumLevel");
if (iMaxLevel == 0)
    iMaxLevel = 40;

if (iMaxLevel < 5)
    {
    iTreasureType = Random(2)+1;
    }
else if (iMaxLevel < 8)
    {
    iTreasureType = Random(3)+1;
    }
else if (iMaxLevel < 14)
    {
    iTreasureType = Random(4)+2;
    }
else if (iMaxLevel < 21)
    {
    iTreasureType = 5;
    }
else if (iMaxLevel < 31 && iMinLevel > 15)
    {
    iTreasureType = 5;
    if (Random(6) == 0)
        iTreasureType = 99;
    }
else if (iMaxLevel < 36 && iMinLevel > 25)
    {
    iTreasureType = 5;
    if (Random(3) == 0)
        iTreasureType = 99;
    }
else if (iMaxLevel < 41 && iMinLevel > 32)
    {
    iTreasureType = 5;
    if (Random(2) == 0)
        iTreasureType = 99;
    }
else if (iMaxLevel < 41)
    iTreasureType = 5;
else
    iTreasureType = Random(5)+1;

SetLocalInt(oTreasure,"EN4_SpecialTreasureType",iTreasureType);
WriteTimestampedLogEntry(sPrefix + " Special Chest set to " + IntToString(iTreasureType) + " on " +  sTreasureTest);
}

void GetNPCQuestHelperList(object oZone)
{
string sNPCHelper;

sNPCHelper = GetLocalString(oZone,"QuestNPC1");
if (!(sNPCHelper == ""))
    AddNPCQuestHelper(sNPCHelper);

sNPCHelper = GetLocalString(oZone,"QuestNPC2");
if (!(sNPCHelper == ""))
    AddNPCQuestHelper(sNPCHelper);

}

void AddNPCQuestHelper(string sNPCHelper)
{
int iNPCHelpers;
int iIndex;
int iFlag;
string sNPCTest;

iNPCHelpers = GetLocalInt(GetModule(),"QuestNPCHelpers");
iIndex = 0;
iFlag = 0;

while (iIndex < iNPCHelpers)
    {
    iIndex++;
    sNPCTest = "QuestNPCHelper" + IntToString(iIndex);
    if (GetLocalString(GetModule(),sNPCTest) == sNPCHelper)
        iFlag = 1;
    }

if (iFlag == 0)
    {
    iNPCHelpers++;
    SetLocalInt(GetModule(),"QuestNPCHelpers",iNPCHelpers);
    sNPCTest = "QuestNPCHelper" + IntToString(iNPCHelpers);
    SetLocalString(GetModule(),sNPCTest,sNPCHelper);
    }
}

location RandomLoc(object oLoc)
{
vector vLoc;
vector vNew;
int iRndX;
int iRndY;
location lLoc;

vLoc = GetPosition(oLoc);
iRndX = Random(6) + 1;
iRndY = Random(6) + 1;
if (Random(2) == 1) iRndX=iRndX * -1;
if (Random(2) == 1) iRndY=iRndY * -1;
vNew = vLoc + Vector( iRndX/1.0, iRndY/1.0, 0.0 );
lLoc = Location(GetArea(oLoc), vNew, VectorToAngle( -1.0 * vNew ));

return lLoc;
}


//start debug
//this code can be run in Initiate Quest to debug NPC's and quest locations
/*
string sZone;
int iCamp;
int iCamps;
object oWP;
string sLocation;
sZone = GetZone(oPC);

iCamps = GetMaxQuestSpots(sZone);
iCamp = 1;
SendMessageToPC(oPC,"Quest Spots : " + IntToString(iCamps));
while (iCamp <= iCamps)
    {
    oWP = GetObjectByTag(sZone + "_Q_" + IntToString(iCamp));
    sLocation = GetLocalString(oWP,"Description");
    SendMessageToPC(oPC,"Quest Spot " + IntToString(iCamp) + " : " + sLocation);
    iCamp++;
    }

iCamps = GetMaxQuestCampSpots(sZone);
iCamp = 1;
SendMessageToPC(oPC,"Quest Camps : " + IntToString(iCamps));
while (iCamp <= iCamps)
    {
    oWP = GetObjectByTag(sZone + "_Q" + IntToString(iCamp) + "_Boss");
    sLocation = GetLocalString(oWP,"Description");
    SendMessageToPC(oPC,"Quest Camp " + IntToString(iCamp) + " : " + sLocation);
    iCamp++;
    }

oWP = GetObjectByTag(GetLocalString(GetArea(oPC),"Dungeon") + "_Q1_Boss");
sLocation = GetLocalString(oWP,"Description");
SendMessageToPC(oPC,"Dungeon Camp : " + sLocation);
*/
//end debug