#include "dungeon_inc"

void main()
{
    //Quit if the entering object is not a PC
    if (!GetIsPC(GetEnteringObject())) return;

    //Let's set this area's pseudo OnExit event (as a workaround for players quitting the game)
    SetLocalString(OBJECT_SELF, "OnExit", "pseudo_donexit");

    //A workaround to enable selecting this area in the OnClientLeave event, since GetArea returns OBJECT_INVALID there
    SetLocalObject(GetEnteringObject(), "StoredArea", OBJECT_SELF);

    //A workaround to prevent the OnEnter event body from firing after loading a saved game
    if (GetLocalInt(GetModule(), "LoadCooldown") == TRUE) return;

    //Add to the counter of PCs in the area
    if (GetLocalInt(GetEnteringObject(), "InTransition") == FALSE) SetLocalInt(OBJECT_SELF, "Players", GetLocalInt(OBJECT_SELF, "Players")+1);

    //FloatingTextStringOnCreature(IntToString(GetLocalInt(OBJECT_SELF, "Players")), GetFirstPC()); //TEST

    //Delete the variable signifying transition between the exterior and the interior area
    DeleteLocalInt(GetEnteringObject(), "InTransition");

    //Get the area we're in from the area variable, get the PC and declare some variables
    string sAreaString = GetLocalString(OBJECT_SELF, "AreaString");
    object oPC = GetEnteringObject();

    //Do nothing if there is already another PC in the area (and the area integer is TRUE)
    if (GetLocalInt(OBJECT_SELF, "IsPopulated") == TRUE) return;

    //Otherwise flag this area as populated, so that no event is generated for next players entering it
    SetLocalInt(OBJECT_SELF, "IsPopulated", TRUE);

    //Now select the leader of the entering party, stored earlied - we will delete this variable in the OnExit
    oPC = GetLocalObject(OBJECT_SELF, "PartyLeader");
    DeleteLocalObject(OBJECT_SELF, "PartyLeader");

    //Get the leader's level
    int nLevel = GetHitDice(oPC);

    //Count party members
    int nPCs;
    object oPartyMember = GetFirstFactionMember(oPC, TRUE);
    while (oPartyMember != OBJECT_INVALID)
    {
        nPCs++;

        //include henchmen in the count
        object oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPartyMember, 1);
        int k;
        for (k = 2; GetIsObjectValid(oAssociate); k++)
        {
            if (GetLocalInt(oAssociate, "HenchPosition") > 0) nPCs++;
            oAssociate = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPartyMember, k);
        }

        oPartyMember = GetNextFactionMember(oPC, TRUE);
    }

    //Delete this area from the list of free areas
    string sRegionString = GetStringLeft(sAreaString, 1);
    string sList = "sList"+sRegionString+"d";
    object oList = GetLocalObject(GetModule(), sList);
    int i;
    for (i = 1; i <= ListGetElementCount(oList); i++)
    {
        if (ListGetString(oList, i) == sAreaString) ListRemoveElement(oList, i);
    }

    //TEST
    for (i = 1; i <= ListGetElementCount(oList); i++)
    {
        WriteTimestampedLogEntry(GetName(oPC)+" "+ListGetString(oList, i));
        WriteTimestampedLogEntry(GetName(oPC)+" "+"entered darea "+sAreaString);
    }

    //Connect the dungeon entrance area to the dungeon interior area
    ConnectDungeonAreas();
    WriteTimestampedLogEntry("DonEnter fired"); //TEST

    //Fill the dungeon with creatures
    object oInArea = GetArea(GetWaypointByTag(GetLocalString(OBJECT_SELF, "DungeonWP")));
    SpawnDungeonMonsters(oInArea, oPC, nLevel, nPCs);

    //Spawn chests
    string sInAreaString = GetLocalString(oInArea, "AreaString");
    string sChestWP;
    object oChestSpotList = ListCreate("ChestSpots");
    for (i = 1; i <= 6; i++)
    {
        ListAddInt(oChestSpotList, i);
    }
    int nChestSpot = Random(ListGetElementCount(oChestSpotList))+1;
    ListRemoveElement(oChestSpotList, nChestSpot);
    sChestWP = sInAreaString + "_chest_" + IntToString(nChestSpot);
    SpawnTreasureChest(oPC, GetWaypointByTag(sChestWP));
    for (i = 1; i <= nPCs; i++)
    {
        nChestSpot = Random(ListGetElementCount(oChestSpotList))+1;
        ListRemoveElement(oChestSpotList, nChestSpot);
        sChestWP = sInAreaString + "_chest_" + IntToString(nChestSpot);
        SpawnTreasureChest(oPC, GetWaypointByTag(sChestWP));
    }

    //Spawn traps
    object oTrap;
    int nTrapDC;
    int nDetectDC;
    object oTrapSpotList = ListCreate("TrapSpots");
    for (i = 1; i <= 10; i++)
    {
        ListAddInt(oTrapSpotList, i);
    }
    int nTrapSpot;
    for (i = 1; i <= nPCs+5; i++)
    {
        nTrapSpot = Random(ListGetElementCount(oTrapSpotList))+1;
        ListRemoveElement(oTrapSpotList, nTrapSpot);
        nTrapDC = Random(nLevel)+21;
        nDetectDC = Random(nLevel)+11;
        oTrap = CreateTrapAtLocation(RandomTrap(nLevel), GetLocation(GetWaypointByTag(sInAreaString+"_trap_"+IntToString(nTrapSpot))), 5.0);
        SetTrapDisarmable(oTrap, TRUE);
        SetTrapDetectDC(oTrap, nDetectDC);
        SetTrapDisarmDC(oTrap, nTrapDC);
    }
}