Modified CEP 2DA hak to remove extraneous creatures from palette. Added door closer script to most town doors. Added Amulet of Mighty Fists +1 through +5 to loot table. Fixed names on remainder of creatures. Updated PEPS. Set PEPS to server mode. Set module to server mode. Updated Class Title function in ms_name_inc. Updated dungeon areas to reset, globally & per player. Added "new" weapons to the Blacksmith. Added magical "new" weapons to the treasure tables. Fixed persistent storage.
166 lines
5.7 KiB
Plaintext
166 lines
5.7 KiB
Plaintext
|
|
// Clears out non-plot, non-immortal objects from the area
|
|
void CleanupArea(object oArea)
|
|
{
|
|
object oObj = GetFirstObjectInArea(oArea);
|
|
while (GetIsObjectValid(oObj))
|
|
{
|
|
int bDestroy = FALSE;
|
|
|
|
// Clean creatures
|
|
if (GetObjectType(oObj) == OBJECT_TYPE_CREATURE)
|
|
{
|
|
if (!GetPlotFlag(oObj) && !GetImmortal(oObj) && !GetIsPC(oObj))
|
|
{
|
|
bDestroy = TRUE;
|
|
}
|
|
}
|
|
|
|
// Clean items
|
|
else if (GetObjectType(oObj) == OBJECT_TYPE_ITEM)
|
|
{
|
|
if (!GetPlotFlag(oObj) && !GetImmortal(oObj))
|
|
{
|
|
bDestroy = TRUE;
|
|
}
|
|
}
|
|
|
|
// Clean placeables (note: static placeables can't be destroyed anyway)
|
|
else if (GetObjectType(oObj) == OBJECT_TYPE_PLACEABLE)
|
|
{
|
|
if (!GetPlotFlag(oObj) && !GetImmortal(oObj))
|
|
{
|
|
bDestroy = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bDestroy)
|
|
{
|
|
WriteTimestampedLogEntry("CleanupArea: Destroying object " + GetTag(oObj) + " in " + GetName(oArea));
|
|
DestroyObject(oObj);
|
|
}
|
|
|
|
oObj = GetNextObjectInArea(oArea);
|
|
}
|
|
}
|
|
|
|
|
|
void ResetPlayerDungeon(string sAreaTag, object oPC)
|
|
{
|
|
int bDebug = GetLocalInt(GetModule(), "MMD_DEBUG");
|
|
|
|
object oArea = GetObjectByTag(sAreaTag);
|
|
|
|
// Allow this PC to trigger spawns in this area again
|
|
DeleteLocalInt(oPC, "DungeonCooldown_" + sAreaTag);
|
|
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit >> ResetPlayerDungeon: Cooldown expired for area " + GetName(oArea)+" / ("+sAreaTag+").");
|
|
|
|
WriteTimestampedLogEntry("area_onexit >> ResetPlayerDungeon: Cooldown expired for PC " + GetName(oPC) + " in area " + GetName(oArea)+" / ("+sAreaTag+").");
|
|
}
|
|
|
|
void ResetDungeonIfEmpty(string sAreaTag)
|
|
{
|
|
int bDebug = GetLocalInt(GetModule(), "MMD_DEBUG");
|
|
|
|
object oArea = GetObjectByTag(sAreaTag);
|
|
if (oArea == OBJECT_INVALID) return;
|
|
|
|
// check if still empty
|
|
object oCheck = GetFirstObjectInArea(oArea);
|
|
while (oCheck != OBJECT_INVALID)
|
|
{
|
|
if (GetIsPC(oCheck)) return; // still occupied
|
|
oCheck = GetNextObjectInArea(oArea);
|
|
}
|
|
|
|
// clear waypoint flags so the dungeon can respawn
|
|
object oSpawn = GetFirstObjectInArea(oArea);
|
|
while (oSpawn != OBJECT_INVALID)
|
|
{
|
|
if (GetObjectType(oSpawn) == OBJECT_TYPE_WAYPOINT)
|
|
{
|
|
DeleteLocalInt(oSpawn, "done");
|
|
}
|
|
oSpawn = GetNextObjectInArea(oArea);
|
|
}
|
|
|
|
object oPC = GetFirstPC();
|
|
while (oPC != OBJECT_INVALID)
|
|
{
|
|
if (GetLocalInt(oPC, "DungeonCooldown_" + sAreaTag) == 1)
|
|
{
|
|
SetLocalInt(oPC, "DungeonCooldown_" + sAreaTag, 0);
|
|
WriteTimestampedLogEntry("area_onexit >> ResetDungeonIfEmpty: Cooldown cleared for " + GetName(oPC) + " in area " + GetName(oArea)+" / ("+sAreaTag+").");
|
|
}
|
|
oPC = GetNextPC();
|
|
}
|
|
|
|
if (bDebug) SpeakString("area_onexit >> ResetDungeonIfEmpty: Dungeon reset complete for area " + GetName(oPC) + " in area " + GetName(oArea)+" / ("+sAreaTag+").");
|
|
|
|
DelayCommand(0.0f, CleanupArea(oArea));
|
|
|
|
WriteTimestampedLogEntry("area_onexit >> ResetDungeonIfEmpty: Dungeon area " + GetName(oArea)+" / ("+sAreaTag+") is fully reset (no PCs present).");
|
|
}
|
|
|
|
void main()
|
|
{
|
|
object oPC = GetExitingObject();
|
|
object oDoor = OBJECT_SELF;
|
|
|
|
if (!GetIsPC(oPC)) return;
|
|
|
|
int bDebug = GetLocalInt(GetModule(), "MMD_DEBUG");
|
|
|
|
object oArea = GetArea(oDoor);
|
|
string sAreaTag = GetTag(oArea);
|
|
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Exiting area " + sAreaTag);
|
|
WriteTimestampedLogEntry("area_onexit: PC " + GetName(oPC) + " exited " + sAreaTag);
|
|
|
|
// If no timer is running for this PC/area, start one
|
|
int iCooldownActive = GetLocalInt(oPC, "DungeonCooldownRunning_" + sAreaTag);
|
|
if (!iCooldownActive)
|
|
{
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Scheduling cooldown reset for " + sAreaTag + " in 5 minutes.");
|
|
WriteTimestampedLogEntry("area_onexit: Starting cooldown timer for " + GetName(oPC) + " in area " + sAreaTag);
|
|
|
|
SetLocalInt(oPC, "DungeonCooldownRunning_" + sAreaTag, 1);
|
|
|
|
// 5-minute cooldown for THIS PC only
|
|
DelayCommand(300.0, ResetPlayerDungeon(sAreaTag, oPC));
|
|
DelayCommand(300.0, DeleteLocalInt(oPC, "DungeonCooldownRunning_" + sAreaTag));
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Cooldown already active for " + sAreaTag);
|
|
WriteTimestampedLogEntry("area_onexit: Cooldown already active for " + GetName(oPC) + " in area " + sAreaTag);
|
|
}
|
|
|
|
// check if any PCs remain
|
|
object oCheck = GetFirstObjectInArea(oArea);
|
|
while (oCheck != OBJECT_INVALID)
|
|
{
|
|
if (GetIsPC(oCheck) && oCheck != oPC)
|
|
{
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Another PC remains in area " + GetName(oArea)+" / ("+sAreaTag+"). Not resetting.");
|
|
WriteTimestampedLogEntry("area_onexit: Area " + sAreaTag + " not empty, skipping full reset.");
|
|
return; // still someone here
|
|
}
|
|
oCheck = GetNextObjectInArea(oArea);
|
|
}
|
|
|
|
// no PCs left -> schedule full dungeon reset in 5 minutes
|
|
if (sAreaTag != "area4_20") // exclude cow level
|
|
{
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Scheduling dungeon reset for " + GetName(oArea)+" / ("+sAreaTag+") in 5 minutes.");
|
|
WriteTimestampedLogEntry("area_onexit: Scheduling full reset for area " + GetName(oArea)+" / ("+sAreaTag+") in 5 minutes.");
|
|
DelayCommand(300.0, ResetDungeonIfEmpty(sAreaTag));
|
|
}
|
|
else
|
|
{
|
|
if (bDebug) SendMessageToPC(oPC, "area_onexit: Cow level excluded from reset.");
|
|
WriteTimestampedLogEntry("area_onexit: Cow level excluded from reset (" + sAreaTag + ")");
|
|
}
|
|
}
|