fixed ground spawn that would automagically reappear just by zoning or relogging.

added 3 groundspawn rules.  decay timer, disarm decay timer, and random respawn.
This commit is contained in:
regneq 2025-09-06 12:01:41 -07:00
parent dee58f9a91
commit 10f67d103b
5 changed files with 52 additions and 11 deletions

View File

@ -1178,6 +1178,12 @@ RULE_INT(EvolvingItems, DelayUponEquipping, 30000, "Delay in ms before an evolvi
RULE_BOOL(EvolvingItems, DestroyAugmentsOnEvolve, false, "If this is enabled, any augments in an item will be destroyed when the item evolves. Otherwise, send augments to the player via the parcel system (requires that the Parcel System be enabled).") RULE_BOOL(EvolvingItems, DestroyAugmentsOnEvolve, false, "If this is enabled, any augments in an item will be destroyed when the item evolves. Otherwise, send augments to the player via the parcel system (requires that the Parcel System be enabled).")
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Groundspawns)
RULE_INT(Groundspawns, DecayTime, 300000, "Decay time of player dropped items.")
RULE_INT(Groundspawns, DisarmDecayTime, 300000, "Decay time of weapons dropped due to disarm")
RULE_BOOL(Groundspawns, RandomSpawn, true, "Determines if groundspawns with random spawn locs will periodically despawn and respawn elsewhere.")
RULE_CATEGORY_END()
#undef RULE_CATEGORY #undef RULE_CATEGORY
#undef RULE_INT #undef RULE_INT
#undef RULE_REAL #undef RULE_REAL

View File

@ -1483,9 +1483,11 @@ void EntityList::SendZoneObjects(Client *client)
{ {
auto it = object_list.begin(); auto it = object_list.begin();
while (it != object_list.end()) { while (it != object_list.end()) {
if (!it->second->IsGroundSpawn() || !it->second->RespawnTimerEnabled()) {
auto app = new EQApplicationPacket; auto app = new EQApplicationPacket;
it->second->CreateSpawnPacket(app); it->second->CreateSpawnPacket(app);
client->FastQueuePacket(&app); client->FastQueuePacket(&app);
}
++it; ++it;
} }
} }

View File

@ -1838,7 +1838,7 @@ void NPC::Disarm(Client* client, int chance) {
CalcBonuses(); CalcBonuses();
if (inst) { if (inst) {
// create a ground item // create a ground item
Object* object = new Object(inst, GetX(), GetY(), GetZ(), 0.0f, 300000); Object* object = new Object(inst, GetX(), GetY(), GetZ(), 0.0f, RuleI(Groundspawns, DisarmDecayTime));
entity_list.AddObject(object, true); entity_list.AddObject(object, true);
object->StartDecay(); object->StartDecay();
safe_delete(inst); safe_delete(inst);

View File

@ -53,7 +53,8 @@ Object::Object(
bool fix_z bool fix_z
) : ) :
respawn_timer(0), respawn_timer(0),
decay_timer(300000) decay_timer(RuleI(Groundspawns, DecayTime)),
random_timer(0)
{ {
user = nullptr; user = nullptr;
last_user = nullptr; last_user = nullptr;
@ -78,6 +79,7 @@ decay_timer(300000)
memset(m_display_name, 0, sizeof(m_display_name)); memset(m_display_name, 0, sizeof(m_display_name));
respawn_timer.Disable(); respawn_timer.Disable();
random_timer.Disable();
// Set drop_id to zero - it will be set when added to zone with SetID() // Set drop_id to zero - it will be set when added to zone with SetID()
m_data.drop_id = 0; m_data.drop_id = 0;
@ -104,7 +106,8 @@ Object::Object(
bool fix_z bool fix_z
) : ) :
respawn_timer(respawn_timer_ * 1000), respawn_timer(respawn_timer_ * 1000),
decay_timer(300000) decay_timer(RuleI(Groundspawns, DecayTime)),
random_timer(respawn_timer)
{ {
user = nullptr; user = nullptr;
@ -131,6 +134,12 @@ decay_timer(300000)
m_data.zone_id = zone->GetZoneID(); m_data.zone_id = zone->GetZoneID();
respawn_timer.Disable(); respawn_timer.Disable();
if (!RuleB(Groundspawns, RandomSpawn) || m_min_x == m_max_x || m_min_y == m_max_y) {
random_timer.Disable();
}
else {
random_timer.Start();
}
strcpy(m_data.object_name, name.c_str()); strcpy(m_data.object_name, name.c_str());
@ -152,7 +161,8 @@ Object::Object(
const EQ::ItemInstance* inst const EQ::ItemInstance* inst
) : ) :
respawn_timer(0), respawn_timer(0),
decay_timer(300000) decay_timer(RuleI(Groundspawns, DecayTime)),
random_timer(0)
{ {
user = nullptr; user = nullptr;
last_user = nullptr; last_user = nullptr;
@ -185,6 +195,7 @@ decay_timer(300000)
decay_timer.Start(); decay_timer.Start();
respawn_timer.Disable(); respawn_timer.Disable();
random_timer.Disable();
// Hardcoded portion for unknown members // Hardcoded portion for unknown members
m_data.unknown024 = 0x7f001194; m_data.unknown024 = 0x7f001194;
@ -226,7 +237,8 @@ Object::Object(
bool fix_z bool fix_z
) : ) :
respawn_timer(0), respawn_timer(0),
decay_timer(decay_time) decay_timer(decay_time),
random_timer(0)
{ {
user = nullptr; user = nullptr;
last_user = nullptr; last_user = nullptr;
@ -255,6 +267,7 @@ decay_timer(decay_time)
} }
respawn_timer.Disable(); respawn_timer.Disable();
random_timer.Disable();
// Hardcoded portion for unknown members // Hardcoded portion for unknown members
m_data.unknown024 = 0x7f001194; m_data.unknown024 = 0x7f001194;
@ -298,7 +311,8 @@ Object::Object(
uint32 decay_time uint32 decay_time
) : ) :
respawn_timer(0), respawn_timer(0),
decay_timer(decay_time) decay_timer(decay_time),
random_timer(0)
{ {
user = nullptr; user = nullptr;
last_user = nullptr; last_user = nullptr;
@ -331,6 +345,7 @@ decay_timer(decay_time)
} }
respawn_timer.Disable(); respawn_timer.Disable();
random_timer.Disable();
// Hardcoded portion for unknown members // Hardcoded portion for unknown members
m_data.unknown024 = 0x7f001194; m_data.unknown024 = 0x7f001194;
@ -533,8 +548,24 @@ bool Object::Process(){
return false; return false;
} }
if (m_ground_spawn && respawn_timer.Check()){ if (m_ground_spawn) {
if (respawn_timer.Enabled()) {
// respawn_timer is enabled if item was picked up, and waiting to respawn
if (respawn_timer.Check()) {
// when random_timer is enabled, RandomSpawn() will send a despawn packet
bool rand_respawn = random_timer.Enabled();
random_timer.Disable();
RandomSpawn(true); RandomSpawn(true);
respawn_timer.Disable();
// re-start random_timer if it was running
if (rand_respawn) {
random_timer.Start();
}
}
}
else if (random_timer.Check()) {
RandomSpawn(true);
}
} }
if (user && !entity_list.GetClientByCharID(user->CharacterID())) { if (user && !entity_list.GetClientByCharID(user->CharacterID())) {

View File

@ -221,6 +221,7 @@ public:
std::vector<std::string> GetEntityVariables(); std::vector<std::string> GetEntityVariables();
void SetEntityVariable(std::string variable_name, std::string variable_value); void SetEntityVariable(std::string variable_name, std::string variable_value);
bool EntityVariableExists(std::string variable_name); bool EntityVariableExists(std::string variable_name);
bool RespawnTimerEnabled() { return respawn_timer.Enabled(); };
protected: protected:
void ResetState(); // Set state back to original void ResetState(); // Set state back to original
@ -245,6 +246,7 @@ protected:
Client *user; Client *user;
Client *last_user; Client *last_user;
Timer random_timer;
Timer respawn_timer; Timer respawn_timer;
Timer decay_timer; Timer decay_timer;
void FixZ(); void FixZ();