[Zones] Convert IDLE_WHEN_EMPTY to a Zone Column (#3891)

* [Rules] Convert IDLE_WHEN_EMPTY to a rule

# Notes
- Converts `IDLE_WHEN_EMPTY` to `Zone:ZonesIdleWhenEmpty` so that we can change this on the fly or on a zone-by-zone basis instead of having to recompile to do this.
- Especially helpful for those using release binaries that do not compile their own source.

* Convert to zone column.

* Update ruletypes.h

* Update ruletypes.h

* Update entity.cpp

* Update entity.cpp

* Rename.

* Update database_update_manifest.cpp

* Update base_zone_repository.h

* Update zone.cpp

* seconds_before_idle

* Update database_update_manifest.cpp

* Getter/Setters/Private

* Update base_zone_repository.h

* IsIdle()/SetIsIdle()

* Update entity.cpp
This commit is contained in:
Alex King 2024-01-13 02:21:40 -05:00 committed by GitHub
parent d41bd8f963
commit 742b437f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 373 additions and 179 deletions

View File

@ -5186,7 +5186,19 @@ ALTER TABLE `instance_list`
ADD COLUMN `notes` varchar(50) NOT NULL DEFAULT '' AFTER `never_expires`; ADD COLUMN `notes` varchar(50) NOT NULL DEFAULT '' AFTER `never_expires`;
)", )",
}, },
ManifestEntry{
.version = 9252,
.description = "2024_01_07_zone_idle_when_empty.sql",
.check = "SHOW COLUMNS FROM `zone` LIKE 'idle_when_empty'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `zone`
ADD COLUMN `idle_when_empty` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `min_lava_damage`
ADD COLUMN `seconds_before_idle` int(11) UNSIGNED NOT NULL DEFAULT 60 AFTER `idle_when_empty`
)",
.content_schema_update = true
}
// -- template; copy/paste this when you need to create a new entry // -- template; copy/paste this when you need to create a new entry
// ManifestEntry{ // ManifestEntry{
// .version = 9228, // .version = 9228,

View File

@ -35,11 +35,6 @@ Core Zone features
*/ */
//Uncomment this to cause a zone to basically idle
//when there are no players in it, mobs stop wandering, etc..
#define IDLE_WHEN_EMPTY
#ifdef EMBPERL #ifdef EMBPERL
//Enable the new XS based perl parser //Enable the new XS based perl parser
#define EMBPERL_XS #define EMBPERL_XS

View File

@ -115,6 +115,8 @@ public:
int32_t underworld_teleport_index; int32_t underworld_teleport_index;
int32_t lava_damage; int32_t lava_damage;
int32_t min_lava_damage; int32_t min_lava_damage;
uint8_t idle_when_empty;
uint32_t seconds_before_idle;
}; };
static std::string PrimaryKey() static std::string PrimaryKey()
@ -221,6 +223,8 @@ public:
"underworld_teleport_index", "underworld_teleport_index",
"lava_damage", "lava_damage",
"min_lava_damage", "min_lava_damage",
"idle_when_empty",
"seconds_before_idle",
}; };
} }
@ -323,6 +327,8 @@ public:
"underworld_teleport_index", "underworld_teleport_index",
"lava_damage", "lava_damage",
"min_lava_damage", "min_lava_damage",
"idle_when_empty",
"seconds_before_idle",
}; };
} }
@ -459,6 +465,8 @@ public:
e.underworld_teleport_index = 0; e.underworld_teleport_index = 0;
e.lava_damage = 50; e.lava_damage = 50;
e.min_lava_damage = 10; e.min_lava_damage = 10;
e.idle_when_empty = 1;
e.seconds_before_idle = 60;
return e; return e;
} }
@ -496,7 +504,7 @@ public:
Zone e{}; Zone e{};
e.short_name = row[0] ? row[0] : ""; e.short_name = row[0] ? row[0] : "";
e.id = static_cast<int32_t>(atoi(row[1])); e.id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.file_name = row[2] ? row[2] : ""; e.file_name = row[2] ? row[2] : "";
e.long_name = row[3] ? row[3] : ""; e.long_name = row[3] ? row[3] : "";
e.map_file_name = row[4] ? row[4] : ""; e.map_file_name = row[4] ? row[4] : "";
@ -508,10 +516,10 @@ public:
e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0; e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0;
e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255; e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255;
e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.zoneidnumber = static_cast<int32_t>(atoi(row[13])); e.zoneidnumber = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0; e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0;
e.timezone = static_cast<int32_t>(atoi(row[15])); e.timezone = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.maxclients = static_cast<int32_t>(atoi(row[16])); e.maxclients = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0; e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.note = row[18] ? row[18] : ""; e.note = row[18] ? row[18] : "";
e.underworld = row[19] ? strtof(row[19], nullptr) : 0; e.underworld = row[19] ? strtof(row[19], nullptr) : 0;
@ -549,48 +557,50 @@ public:
e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450; e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450;
e.fog_density = row[52] ? strtof(row[52], nullptr) : 0; e.fog_density = row[52] ? strtof(row[52], nullptr) : 0;
e.flag_needed = row[53] ? row[53] : ""; e.flag_needed = row[53] ? row[53] : "";
e.canbind = static_cast<int8_t>(atoi(row[54])); e.canbind = row[54] ? static_cast<int8_t>(atoi(row[54])) : 1;
e.cancombat = static_cast<int8_t>(atoi(row[55])); e.cancombat = row[55] ? static_cast<int8_t>(atoi(row[55])) : 1;
e.canlevitate = static_cast<int8_t>(atoi(row[56])); e.canlevitate = row[56] ? static_cast<int8_t>(atoi(row[56])) : 1;
e.castoutdoor = static_cast<int8_t>(atoi(row[57])); e.castoutdoor = row[57] ? static_cast<int8_t>(atoi(row[57])) : 1;
e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0; e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0;
e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0; e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0;
e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000; e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000;
e.peqzone = static_cast<int8_t>(atoi(row[61])); e.peqzone = row[61] ? static_cast<int8_t>(atoi(row[61])) : 1;
e.expansion = static_cast<int8_t>(atoi(row[62])); e.expansion = row[62] ? static_cast<int8_t>(atoi(row[62])) : 0;
e.bypass_expansion_check = static_cast<int8_t>(atoi(row[63])); e.bypass_expansion_check = row[63] ? static_cast<int8_t>(atoi(row[63])) : 0;
e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0; e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0;
e.rain_chance1 = static_cast<int32_t>(atoi(row[65])); e.rain_chance1 = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.rain_chance2 = static_cast<int32_t>(atoi(row[66])); e.rain_chance2 = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.rain_chance3 = static_cast<int32_t>(atoi(row[67])); e.rain_chance3 = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.rain_chance4 = static_cast<int32_t>(atoi(row[68])); e.rain_chance4 = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.rain_duration1 = static_cast<int32_t>(atoi(row[69])); e.rain_duration1 = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.rain_duration2 = static_cast<int32_t>(atoi(row[70])); e.rain_duration2 = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.rain_duration3 = static_cast<int32_t>(atoi(row[71])); e.rain_duration3 = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.rain_duration4 = static_cast<int32_t>(atoi(row[72])); e.rain_duration4 = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.snow_chance1 = static_cast<int32_t>(atoi(row[73])); e.snow_chance1 = row[73] ? static_cast<int32_t>(atoi(row[73])) : 0;
e.snow_chance2 = static_cast<int32_t>(atoi(row[74])); e.snow_chance2 = row[74] ? static_cast<int32_t>(atoi(row[74])) : 0;
e.snow_chance3 = static_cast<int32_t>(atoi(row[75])); e.snow_chance3 = row[75] ? static_cast<int32_t>(atoi(row[75])) : 0;
e.snow_chance4 = static_cast<int32_t>(atoi(row[76])); e.snow_chance4 = row[76] ? static_cast<int32_t>(atoi(row[76])) : 0;
e.snow_duration1 = static_cast<int32_t>(atoi(row[77])); e.snow_duration1 = row[77] ? static_cast<int32_t>(atoi(row[77])) : 0;
e.snow_duration2 = static_cast<int32_t>(atoi(row[78])); e.snow_duration2 = row[78] ? static_cast<int32_t>(atoi(row[78])) : 0;
e.snow_duration3 = static_cast<int32_t>(atoi(row[79])); e.snow_duration3 = row[79] ? static_cast<int32_t>(atoi(row[79])) : 0;
e.snow_duration4 = static_cast<int32_t>(atoi(row[80])); e.snow_duration4 = row[80] ? static_cast<int32_t>(atoi(row[80])) : 0;
e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4; e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4;
e.type = static_cast<int32_t>(atoi(row[82])); e.type = row[82] ? static_cast<int32_t>(atoi(row[82])) : 0;
e.skylock = static_cast<int8_t>(atoi(row[83])); e.skylock = row[83] ? static_cast<int8_t>(atoi(row[83])) : 0;
e.fast_regen_hp = static_cast<int32_t>(atoi(row[84])); e.fast_regen_hp = row[84] ? static_cast<int32_t>(atoi(row[84])) : 180;
e.fast_regen_mana = static_cast<int32_t>(atoi(row[85])); e.fast_regen_mana = row[85] ? static_cast<int32_t>(atoi(row[85])) : 180;
e.fast_regen_endurance = static_cast<int32_t>(atoi(row[86])); e.fast_regen_endurance = row[86] ? static_cast<int32_t>(atoi(row[86])) : 180;
e.npc_max_aggro_dist = static_cast<int32_t>(atoi(row[87])); e.npc_max_aggro_dist = row[87] ? static_cast<int32_t>(atoi(row[87])) : 600;
e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600; e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600;
e.min_expansion = static_cast<int8_t>(atoi(row[89])); e.min_expansion = row[89] ? static_cast<int8_t>(atoi(row[89])) : -1;
e.max_expansion = static_cast<int8_t>(atoi(row[90])); e.max_expansion = row[90] ? static_cast<int8_t>(atoi(row[90])) : -1;
e.content_flags = row[91] ? row[91] : ""; e.content_flags = row[91] ? row[91] : "";
e.content_flags_disabled = row[92] ? row[92] : ""; e.content_flags_disabled = row[92] ? row[92] : "";
e.underworld_teleport_index = static_cast<int32_t>(atoi(row[93])); e.underworld_teleport_index = row[93] ? static_cast<int32_t>(atoi(row[93])) : 0;
e.lava_damage = static_cast<int32_t>(atoi(row[94])); e.lava_damage = row[94] ? static_cast<int32_t>(atoi(row[94])) : 50;
e.min_lava_damage = static_cast<int32_t>(atoi(row[95])); e.min_lava_damage = row[95] ? static_cast<int32_t>(atoi(row[95])) : 10;
e.idle_when_empty = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 1;
e.seconds_before_idle = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 60;
return e; return e;
} }
@ -719,6 +729,8 @@ public:
v.push_back(columns[93] + " = " + std::to_string(e.underworld_teleport_index)); v.push_back(columns[93] + " = " + std::to_string(e.underworld_teleport_index));
v.push_back(columns[94] + " = " + std::to_string(e.lava_damage)); v.push_back(columns[94] + " = " + std::to_string(e.lava_damage));
v.push_back(columns[95] + " = " + std::to_string(e.min_lava_damage)); v.push_back(columns[95] + " = " + std::to_string(e.min_lava_damage));
v.push_back(columns[96] + " = " + std::to_string(e.idle_when_empty));
v.push_back(columns[97] + " = " + std::to_string(e.seconds_before_idle));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -836,6 +848,8 @@ public:
v.push_back(std::to_string(e.underworld_teleport_index)); v.push_back(std::to_string(e.underworld_teleport_index));
v.push_back(std::to_string(e.lava_damage)); v.push_back(std::to_string(e.lava_damage));
v.push_back(std::to_string(e.min_lava_damage)); v.push_back(std::to_string(e.min_lava_damage));
v.push_back(std::to_string(e.idle_when_empty));
v.push_back(std::to_string(e.seconds_before_idle));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -961,6 +975,8 @@ public:
v.push_back(std::to_string(e.underworld_teleport_index)); v.push_back(std::to_string(e.underworld_teleport_index));
v.push_back(std::to_string(e.lava_damage)); v.push_back(std::to_string(e.lava_damage));
v.push_back(std::to_string(e.min_lava_damage)); v.push_back(std::to_string(e.min_lava_damage));
v.push_back(std::to_string(e.idle_when_empty));
v.push_back(std::to_string(e.seconds_before_idle));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }
@ -995,7 +1011,7 @@ public:
Zone e{}; Zone e{};
e.short_name = row[0] ? row[0] : ""; e.short_name = row[0] ? row[0] : "";
e.id = static_cast<int32_t>(atoi(row[1])); e.id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.file_name = row[2] ? row[2] : ""; e.file_name = row[2] ? row[2] : "";
e.long_name = row[3] ? row[3] : ""; e.long_name = row[3] ? row[3] : "";
e.map_file_name = row[4] ? row[4] : ""; e.map_file_name = row[4] ? row[4] : "";
@ -1007,10 +1023,10 @@ public:
e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0; e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0;
e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255; e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255;
e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.zoneidnumber = static_cast<int32_t>(atoi(row[13])); e.zoneidnumber = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0; e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0;
e.timezone = static_cast<int32_t>(atoi(row[15])); e.timezone = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.maxclients = static_cast<int32_t>(atoi(row[16])); e.maxclients = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0; e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.note = row[18] ? row[18] : ""; e.note = row[18] ? row[18] : "";
e.underworld = row[19] ? strtof(row[19], nullptr) : 0; e.underworld = row[19] ? strtof(row[19], nullptr) : 0;
@ -1048,48 +1064,50 @@ public:
e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450; e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450;
e.fog_density = row[52] ? strtof(row[52], nullptr) : 0; e.fog_density = row[52] ? strtof(row[52], nullptr) : 0;
e.flag_needed = row[53] ? row[53] : ""; e.flag_needed = row[53] ? row[53] : "";
e.canbind = static_cast<int8_t>(atoi(row[54])); e.canbind = row[54] ? static_cast<int8_t>(atoi(row[54])) : 1;
e.cancombat = static_cast<int8_t>(atoi(row[55])); e.cancombat = row[55] ? static_cast<int8_t>(atoi(row[55])) : 1;
e.canlevitate = static_cast<int8_t>(atoi(row[56])); e.canlevitate = row[56] ? static_cast<int8_t>(atoi(row[56])) : 1;
e.castoutdoor = static_cast<int8_t>(atoi(row[57])); e.castoutdoor = row[57] ? static_cast<int8_t>(atoi(row[57])) : 1;
e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0; e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0;
e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0; e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0;
e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000; e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000;
e.peqzone = static_cast<int8_t>(atoi(row[61])); e.peqzone = row[61] ? static_cast<int8_t>(atoi(row[61])) : 1;
e.expansion = static_cast<int8_t>(atoi(row[62])); e.expansion = row[62] ? static_cast<int8_t>(atoi(row[62])) : 0;
e.bypass_expansion_check = static_cast<int8_t>(atoi(row[63])); e.bypass_expansion_check = row[63] ? static_cast<int8_t>(atoi(row[63])) : 0;
e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0; e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0;
e.rain_chance1 = static_cast<int32_t>(atoi(row[65])); e.rain_chance1 = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.rain_chance2 = static_cast<int32_t>(atoi(row[66])); e.rain_chance2 = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.rain_chance3 = static_cast<int32_t>(atoi(row[67])); e.rain_chance3 = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.rain_chance4 = static_cast<int32_t>(atoi(row[68])); e.rain_chance4 = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.rain_duration1 = static_cast<int32_t>(atoi(row[69])); e.rain_duration1 = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.rain_duration2 = static_cast<int32_t>(atoi(row[70])); e.rain_duration2 = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.rain_duration3 = static_cast<int32_t>(atoi(row[71])); e.rain_duration3 = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.rain_duration4 = static_cast<int32_t>(atoi(row[72])); e.rain_duration4 = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.snow_chance1 = static_cast<int32_t>(atoi(row[73])); e.snow_chance1 = row[73] ? static_cast<int32_t>(atoi(row[73])) : 0;
e.snow_chance2 = static_cast<int32_t>(atoi(row[74])); e.snow_chance2 = row[74] ? static_cast<int32_t>(atoi(row[74])) : 0;
e.snow_chance3 = static_cast<int32_t>(atoi(row[75])); e.snow_chance3 = row[75] ? static_cast<int32_t>(atoi(row[75])) : 0;
e.snow_chance4 = static_cast<int32_t>(atoi(row[76])); e.snow_chance4 = row[76] ? static_cast<int32_t>(atoi(row[76])) : 0;
e.snow_duration1 = static_cast<int32_t>(atoi(row[77])); e.snow_duration1 = row[77] ? static_cast<int32_t>(atoi(row[77])) : 0;
e.snow_duration2 = static_cast<int32_t>(atoi(row[78])); e.snow_duration2 = row[78] ? static_cast<int32_t>(atoi(row[78])) : 0;
e.snow_duration3 = static_cast<int32_t>(atoi(row[79])); e.snow_duration3 = row[79] ? static_cast<int32_t>(atoi(row[79])) : 0;
e.snow_duration4 = static_cast<int32_t>(atoi(row[80])); e.snow_duration4 = row[80] ? static_cast<int32_t>(atoi(row[80])) : 0;
e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4; e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4;
e.type = static_cast<int32_t>(atoi(row[82])); e.type = row[82] ? static_cast<int32_t>(atoi(row[82])) : 0;
e.skylock = static_cast<int8_t>(atoi(row[83])); e.skylock = row[83] ? static_cast<int8_t>(atoi(row[83])) : 0;
e.fast_regen_hp = static_cast<int32_t>(atoi(row[84])); e.fast_regen_hp = row[84] ? static_cast<int32_t>(atoi(row[84])) : 180;
e.fast_regen_mana = static_cast<int32_t>(atoi(row[85])); e.fast_regen_mana = row[85] ? static_cast<int32_t>(atoi(row[85])) : 180;
e.fast_regen_endurance = static_cast<int32_t>(atoi(row[86])); e.fast_regen_endurance = row[86] ? static_cast<int32_t>(atoi(row[86])) : 180;
e.npc_max_aggro_dist = static_cast<int32_t>(atoi(row[87])); e.npc_max_aggro_dist = row[87] ? static_cast<int32_t>(atoi(row[87])) : 600;
e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600; e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600;
e.min_expansion = static_cast<int8_t>(atoi(row[89])); e.min_expansion = row[89] ? static_cast<int8_t>(atoi(row[89])) : -1;
e.max_expansion = static_cast<int8_t>(atoi(row[90])); e.max_expansion = row[90] ? static_cast<int8_t>(atoi(row[90])) : -1;
e.content_flags = row[91] ? row[91] : ""; e.content_flags = row[91] ? row[91] : "";
e.content_flags_disabled = row[92] ? row[92] : ""; e.content_flags_disabled = row[92] ? row[92] : "";
e.underworld_teleport_index = static_cast<int32_t>(atoi(row[93])); e.underworld_teleport_index = row[93] ? static_cast<int32_t>(atoi(row[93])) : 0;
e.lava_damage = static_cast<int32_t>(atoi(row[94])); e.lava_damage = row[94] ? static_cast<int32_t>(atoi(row[94])) : 50;
e.min_lava_damage = static_cast<int32_t>(atoi(row[95])); e.min_lava_damage = row[95] ? static_cast<int32_t>(atoi(row[95])) : 10;
e.idle_when_empty = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 1;
e.seconds_before_idle = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 60;
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -1115,7 +1133,7 @@ public:
Zone e{}; Zone e{};
e.short_name = row[0] ? row[0] : ""; e.short_name = row[0] ? row[0] : "";
e.id = static_cast<int32_t>(atoi(row[1])); e.id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
e.file_name = row[2] ? row[2] : ""; e.file_name = row[2] ? row[2] : "";
e.long_name = row[3] ? row[3] : ""; e.long_name = row[3] ? row[3] : "";
e.map_file_name = row[4] ? row[4] : ""; e.map_file_name = row[4] ? row[4] : "";
@ -1127,10 +1145,10 @@ public:
e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0; e.min_level = row[10] ? static_cast<uint8_t>(strtoul(row[10], nullptr, 10)) : 0;
e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255; e.max_level = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 255;
e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0; e.min_status = row[12] ? static_cast<uint8_t>(strtoul(row[12], nullptr, 10)) : 0;
e.zoneidnumber = static_cast<int32_t>(atoi(row[13])); e.zoneidnumber = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0; e.version = row[14] ? static_cast<uint8_t>(strtoul(row[14], nullptr, 10)) : 0;
e.timezone = static_cast<int32_t>(atoi(row[15])); e.timezone = row[15] ? static_cast<int32_t>(atoi(row[15])) : 0;
e.maxclients = static_cast<int32_t>(atoi(row[16])); e.maxclients = row[16] ? static_cast<int32_t>(atoi(row[16])) : 0;
e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0; e.ruleset = row[17] ? static_cast<uint32_t>(strtoul(row[17], nullptr, 10)) : 0;
e.note = row[18] ? row[18] : ""; e.note = row[18] ? row[18] : "";
e.underworld = row[19] ? strtof(row[19], nullptr) : 0; e.underworld = row[19] ? strtof(row[19], nullptr) : 0;
@ -1168,48 +1186,50 @@ public:
e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450; e.fog_maxclip4 = row[51] ? strtof(row[51], nullptr) : 450;
e.fog_density = row[52] ? strtof(row[52], nullptr) : 0; e.fog_density = row[52] ? strtof(row[52], nullptr) : 0;
e.flag_needed = row[53] ? row[53] : ""; e.flag_needed = row[53] ? row[53] : "";
e.canbind = static_cast<int8_t>(atoi(row[54])); e.canbind = row[54] ? static_cast<int8_t>(atoi(row[54])) : 1;
e.cancombat = static_cast<int8_t>(atoi(row[55])); e.cancombat = row[55] ? static_cast<int8_t>(atoi(row[55])) : 1;
e.canlevitate = static_cast<int8_t>(atoi(row[56])); e.canlevitate = row[56] ? static_cast<int8_t>(atoi(row[56])) : 1;
e.castoutdoor = static_cast<int8_t>(atoi(row[57])); e.castoutdoor = row[57] ? static_cast<int8_t>(atoi(row[57])) : 1;
e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0; e.hotzone = row[58] ? static_cast<uint8_t>(strtoul(row[58], nullptr, 10)) : 0;
e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0; e.insttype = row[59] ? static_cast<uint8_t>(strtoul(row[59], nullptr, 10)) : 0;
e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000; e.shutdowndelay = row[60] ? strtoull(row[60], nullptr, 10) : 5000;
e.peqzone = static_cast<int8_t>(atoi(row[61])); e.peqzone = row[61] ? static_cast<int8_t>(atoi(row[61])) : 1;
e.expansion = static_cast<int8_t>(atoi(row[62])); e.expansion = row[62] ? static_cast<int8_t>(atoi(row[62])) : 0;
e.bypass_expansion_check = static_cast<int8_t>(atoi(row[63])); e.bypass_expansion_check = row[63] ? static_cast<int8_t>(atoi(row[63])) : 0;
e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0; e.suspendbuffs = row[64] ? static_cast<uint8_t>(strtoul(row[64], nullptr, 10)) : 0;
e.rain_chance1 = static_cast<int32_t>(atoi(row[65])); e.rain_chance1 = row[65] ? static_cast<int32_t>(atoi(row[65])) : 0;
e.rain_chance2 = static_cast<int32_t>(atoi(row[66])); e.rain_chance2 = row[66] ? static_cast<int32_t>(atoi(row[66])) : 0;
e.rain_chance3 = static_cast<int32_t>(atoi(row[67])); e.rain_chance3 = row[67] ? static_cast<int32_t>(atoi(row[67])) : 0;
e.rain_chance4 = static_cast<int32_t>(atoi(row[68])); e.rain_chance4 = row[68] ? static_cast<int32_t>(atoi(row[68])) : 0;
e.rain_duration1 = static_cast<int32_t>(atoi(row[69])); e.rain_duration1 = row[69] ? static_cast<int32_t>(atoi(row[69])) : 0;
e.rain_duration2 = static_cast<int32_t>(atoi(row[70])); e.rain_duration2 = row[70] ? static_cast<int32_t>(atoi(row[70])) : 0;
e.rain_duration3 = static_cast<int32_t>(atoi(row[71])); e.rain_duration3 = row[71] ? static_cast<int32_t>(atoi(row[71])) : 0;
e.rain_duration4 = static_cast<int32_t>(atoi(row[72])); e.rain_duration4 = row[72] ? static_cast<int32_t>(atoi(row[72])) : 0;
e.snow_chance1 = static_cast<int32_t>(atoi(row[73])); e.snow_chance1 = row[73] ? static_cast<int32_t>(atoi(row[73])) : 0;
e.snow_chance2 = static_cast<int32_t>(atoi(row[74])); e.snow_chance2 = row[74] ? static_cast<int32_t>(atoi(row[74])) : 0;
e.snow_chance3 = static_cast<int32_t>(atoi(row[75])); e.snow_chance3 = row[75] ? static_cast<int32_t>(atoi(row[75])) : 0;
e.snow_chance4 = static_cast<int32_t>(atoi(row[76])); e.snow_chance4 = row[76] ? static_cast<int32_t>(atoi(row[76])) : 0;
e.snow_duration1 = static_cast<int32_t>(atoi(row[77])); e.snow_duration1 = row[77] ? static_cast<int32_t>(atoi(row[77])) : 0;
e.snow_duration2 = static_cast<int32_t>(atoi(row[78])); e.snow_duration2 = row[78] ? static_cast<int32_t>(atoi(row[78])) : 0;
e.snow_duration3 = static_cast<int32_t>(atoi(row[79])); e.snow_duration3 = row[79] ? static_cast<int32_t>(atoi(row[79])) : 0;
e.snow_duration4 = static_cast<int32_t>(atoi(row[80])); e.snow_duration4 = row[80] ? static_cast<int32_t>(atoi(row[80])) : 0;
e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4; e.gravity = row[81] ? strtof(row[81], nullptr) : 0.4;
e.type = static_cast<int32_t>(atoi(row[82])); e.type = row[82] ? static_cast<int32_t>(atoi(row[82])) : 0;
e.skylock = static_cast<int8_t>(atoi(row[83])); e.skylock = row[83] ? static_cast<int8_t>(atoi(row[83])) : 0;
e.fast_regen_hp = static_cast<int32_t>(atoi(row[84])); e.fast_regen_hp = row[84] ? static_cast<int32_t>(atoi(row[84])) : 180;
e.fast_regen_mana = static_cast<int32_t>(atoi(row[85])); e.fast_regen_mana = row[85] ? static_cast<int32_t>(atoi(row[85])) : 180;
e.fast_regen_endurance = static_cast<int32_t>(atoi(row[86])); e.fast_regen_endurance = row[86] ? static_cast<int32_t>(atoi(row[86])) : 180;
e.npc_max_aggro_dist = static_cast<int32_t>(atoi(row[87])); e.npc_max_aggro_dist = row[87] ? static_cast<int32_t>(atoi(row[87])) : 600;
e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600; e.max_movement_update_range = row[88] ? static_cast<uint32_t>(strtoul(row[88], nullptr, 10)) : 600;
e.min_expansion = static_cast<int8_t>(atoi(row[89])); e.min_expansion = row[89] ? static_cast<int8_t>(atoi(row[89])) : -1;
e.max_expansion = static_cast<int8_t>(atoi(row[90])); e.max_expansion = row[90] ? static_cast<int8_t>(atoi(row[90])) : -1;
e.content_flags = row[91] ? row[91] : ""; e.content_flags = row[91] ? row[91] : "";
e.content_flags_disabled = row[92] ? row[92] : ""; e.content_flags_disabled = row[92] ? row[92] : "";
e.underworld_teleport_index = static_cast<int32_t>(atoi(row[93])); e.underworld_teleport_index = row[93] ? static_cast<int32_t>(atoi(row[93])) : 0;
e.lava_damage = static_cast<int32_t>(atoi(row[94])); e.lava_damage = row[94] ? static_cast<int32_t>(atoi(row[94])) : 50;
e.min_lava_damage = static_cast<int32_t>(atoi(row[95])); e.min_lava_damage = row[95] ? static_cast<int32_t>(atoi(row[95])) : 10;
e.idle_when_empty = row[96] ? static_cast<uint8_t>(strtoul(row[96], nullptr, 10)) : 1;
e.seconds_before_idle = row[97] ? static_cast<uint32_t>(strtoul(row[97], nullptr, 10)) : 60;
all_entries.push_back(e); all_entries.push_back(e);
} }
@ -1380,6 +1400,8 @@ public:
v.push_back(std::to_string(e.underworld_teleport_index)); v.push_back(std::to_string(e.underworld_teleport_index));
v.push_back(std::to_string(e.lava_damage)); v.push_back(std::to_string(e.lava_damage));
v.push_back(std::to_string(e.min_lava_damage)); v.push_back(std::to_string(e.min_lava_damage));
v.push_back(std::to_string(e.idle_when_empty));
v.push_back(std::to_string(e.seconds_before_idle));
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
@ -1498,6 +1520,8 @@ public:
v.push_back(std::to_string(e.underworld_teleport_index)); v.push_back(std::to_string(e.underworld_teleport_index));
v.push_back(std::to_string(e.lava_damage)); v.push_back(std::to_string(e.lava_damage));
v.push_back(std::to_string(e.min_lava_damage)); v.push_back(std::to_string(e.min_lava_damage));
v.push_back(std::to_string(e.idle_when_empty));
v.push_back(std::to_string(e.seconds_before_idle));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
} }

View File

@ -338,7 +338,6 @@ RULE_BOOL(Zone, UseZoneController, true, "Enables the ability to use persistent
RULE_BOOL(Zone, EnableZoneControllerGlobals, false, "Enables the ability to use quest globals with the zone controller NPC") RULE_BOOL(Zone, EnableZoneControllerGlobals, false, "Enables the ability to use quest globals with the zone controller NPC")
RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc") RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc")
RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS") RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS")
RULE_INT(Zone, SecondsBeforeIdle, 60, "Seconds before IDLE_WHEN_EMPTY define kicks in")
RULE_INT(Zone, SpawnEventMin, 3, "When strict is set in spawn_events, specifies the max EQ minutes into the trigger hour a spawn_event will fire. Going below 3 may cause the spawn_event to not fire.") RULE_INT(Zone, SpawnEventMin, 3, "When strict is set in spawn_events, specifies the max EQ minutes into the trigger hour a spawn_event will fire. Going below 3 may cause the spawn_event to not fire.")
RULE_INT(Zone, ForageChance, 25, "Chance of foraging from zone table vs global table") RULE_INT(Zone, ForageChance, 25, "Chance of foraging from zone table vs global table")
RULE_CATEGORY_END() RULE_CATEGORY_END()

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/ */
#define CURRENT_BINARY_DATABASE_VERSION 9251 #define CURRENT_BINARY_DATABASE_VERSION 9252
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9041

View File

@ -1341,3 +1341,37 @@ int ZoneStore::GetZoneMinimumLavaDamage(uint32 zone_id, int version)
return 0; return 0;
} }
uint8 ZoneStore::GetZoneIdleWhenEmpty(uint32 zone_id, int version)
{
for (auto &z: m_zones) {
if (z.zoneidnumber == zone_id && z.version == version) {
return z.idle_when_empty;
}
}
for (auto &z: m_zones) {
if (z.zoneidnumber == zone_id && z.version == 0) {
return z.idle_when_empty;
}
}
return 1;
}
uint32 ZoneStore::GetZoneSecondsBeforeIdle(uint32 zone_id, int version)
{
for (auto &z: m_zones) {
if (z.zoneidnumber == zone_id && z.version == version) {
return z.seconds_before_idle;
}
}
for (auto &z: m_zones) {
if (z.zoneidnumber == zone_id && z.version == 0) {
return z.seconds_before_idle;
}
}
return 60;
}

View File

@ -100,6 +100,8 @@ public:
int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0); int GetZoneUnderworldTeleportIndex(uint32 zone_id, int version = 0);
int GetZoneLavaDamage(uint32 zone_id, int version = 0); int GetZoneLavaDamage(uint32 zone_id, int version = 0);
int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0); int GetZoneMinimumLavaDamage(uint32 zone_id, int version = 0);
uint8 GetZoneIdleWhenEmpty(uint32 zone_id, int version = 0);
uint32 GetZoneSecondsBeforeIdle(uint32 zone_id, int version = 0);
private: private:
std::vector<ZoneRepository::Zone> m_zones; std::vector<ZoneRepository::Zone> m_zones;

View File

@ -5703,6 +5703,26 @@ int Perl__GetZoneMinimumLavaDamage(uint32 zone_id, int version)
return zone_store.GetZoneMinimumLavaDamage(zone_id, version); return zone_store.GetZoneMinimumLavaDamage(zone_id, version);
} }
uint8 Perl__GetZoneIdleWhenEmpty(uint32 zone_id)
{
return zone_store.GetZoneIdleWhenEmpty(zone_id);
}
uint8 Perl__GetZoneIdleWhenEmpty(uint32 zone_id, int version)
{
return zone_store.GetZoneIdleWhenEmpty(zone_id, version);
}
uint32 Perl__GetZoneSecondsBeforeIdle(uint32 zone_id)
{
return zone_store.GetZoneSecondsBeforeIdle(zone_id);
}
uint32 Perl__GetZoneSecondsBeforeIdle(uint32 zone_id, int version)
{
return zone_store.GetZoneSecondsBeforeIdle(zone_id, version);
}
void Perl__send_channel_message(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message) void Perl__send_channel_message(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message)
{ {
quest_manager.SendChannelMessage(channel_number, guild_id, language_id, language_skill, message); quest_manager.SendChannelMessage(channel_number, guild_id, language_id, language_skill, message);
@ -5810,6 +5830,8 @@ void perl_register_quest()
package.add("GetZoneGraveyardID", (float(*)(uint32, int))&Perl__GetZoneGraveyardID); package.add("GetZoneGraveyardID", (float(*)(uint32, int))&Perl__GetZoneGraveyardID);
package.add("GetZoneHotzone", (uint8(*)(uint32))&Perl__GetZoneHotzone); package.add("GetZoneHotzone", (uint8(*)(uint32))&Perl__GetZoneHotzone);
package.add("GetZoneHotzone", (uint8(*)(uint32, int))&Perl__GetZoneHotzone); package.add("GetZoneHotzone", (uint8(*)(uint32, int))&Perl__GetZoneHotzone);
package.add("GetZoneIdleWhenEmpty", (uint8(*)(uint32))&Perl__GetZoneIdleWhenEmpty);
package.add("GetZoneIdleWhenEmpty", (uint8(*)(uint32, int))&Perl__GetZoneIdleWhenEmpty);
package.add("GetZoneInstanceType", (uint8(*)(uint32))&Perl__GetZoneInstanceType); package.add("GetZoneInstanceType", (uint8(*)(uint32))&Perl__GetZoneInstanceType);
package.add("GetZoneInstanceType", (uint8(*)(uint32, int))&Perl__GetZoneInstanceType); package.add("GetZoneInstanceType", (uint8(*)(uint32, int))&Perl__GetZoneInstanceType);
package.add("GetZoneID", &Perl__GetZoneID); package.add("GetZoneID", &Perl__GetZoneID);
@ -5890,6 +5912,8 @@ void perl_register_quest()
package.add("GetZoneSafeY", (float(*)(uint32, int))&Perl__GetZoneSafeY); package.add("GetZoneSafeY", (float(*)(uint32, int))&Perl__GetZoneSafeY);
package.add("GetZoneSafeZ", (float(*)(uint32))&Perl__GetZoneSafeZ); package.add("GetZoneSafeZ", (float(*)(uint32))&Perl__GetZoneSafeZ);
package.add("GetZoneSafeZ", (float(*)(uint32, int))&Perl__GetZoneSafeZ); package.add("GetZoneSafeZ", (float(*)(uint32, int))&Perl__GetZoneSafeZ);
package.add("GetZoneSecondsBeforeIdle", (uint32(*)(uint32))&Perl__GetZoneSecondsBeforeIdle);
package.add("GetZoneSecondsBeforeIdle", (uint32(*)(uint32, int))&Perl__GetZoneSecondsBeforeIdle);
package.add("GetZoneShutdownDelay", (uint64(*)(uint32))&Perl__GetZoneShutdownDelay); package.add("GetZoneShutdownDelay", (uint64(*)(uint32))&Perl__GetZoneShutdownDelay);
package.add("GetZoneShutdownDelay", (uint64(*)(uint32, int))&Perl__GetZoneShutdownDelay); package.add("GetZoneShutdownDelay", (uint64(*)(uint32, int))&Perl__GetZoneShutdownDelay);
package.add("GetZoneSky", (uint8(*)(uint32))&Perl__GetZoneSky); package.add("GetZoneSky", (uint8(*)(uint32))&Perl__GetZoneSky);

View File

@ -411,10 +411,12 @@ void EntityList::RaidProcess()
void EntityList::DoorProcess() void EntityList::DoorProcess()
{ {
#ifdef IDLE_WHEN_EMPTY if (zone && zone->IsIdleWhenEmpty()) {
if (numclients < 1) if (numclients < 1) {
return; return;
#endif }
}
if (door_list.empty()) { if (door_list.empty()) {
door_timer.Disable(); door_timer.Disable();
return; return;
@ -480,46 +482,76 @@ void EntityList::MobProcess()
size_t sz = mob_list.size(); size_t sz = mob_list.size();
#ifdef IDLE_WHEN_EMPTY static int old_client_count = 0;
static int old_client_count=0;
static Timer *mob_settle_timer = new Timer(); static Timer *mob_settle_timer = new Timer();
if (numclients == 0 && old_client_count > 0 && if (zone->IsIdleWhenEmpty()) {
RuleI(Zone, SecondsBeforeIdle) > 0) { if (
// Start Timer to allow any mobs that chased chars from zone numclients == 0 &&
// to return home. old_client_count > 0 &&
mob_settle_timer->Start(RuleI(Zone, SecondsBeforeIdle) * 1000); zone->GetSecondsBeforeIdle() > 0
} ) {
if (!zone->IsIdle()) {
LogInfo(
"Zone will go into an idle state after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
}
old_client_count = numclients; mob_settle_timer->Start(zone->GetSecondsBeforeIdle() * 1000);
}
// Disable settle timer if someone zones into empty zone old_client_count = numclients;
if (numclients > 0 || mob_settle_timer->Check()) {
mob_settle_timer->Disable();
}
Spawn2* s2 = mob->CastToNPC()->respawn2; if (numclients == 0 && mob_settle_timer->Check()) {
if (!zone->IsIdle()) {
LogInfo(
"Zone has gone idle after [{}] second{}.",
zone->GetSecondsBeforeIdle(),
zone->GetSecondsBeforeIdle() != 1 ? "s" : ""
);
// Perform normal mob processing if any of these are true: zone->SetIsIdle(true);
// -- zone is not empty }
// -- a quest has turned it on for this zone while zone is idle }
// -- the entity's spawn2 point is marked as path_while_zone_idle
// -- the zone is newly empty and we're allowing mobs to settle // Disable settle timer if someone zones into empty zone
if (zone->process_mobs_while_empty || numclients > 0 || if (numclients > 0 || mob_settle_timer->Check()) {
(s2 && s2->PathWhenZoneIdle()) || mob_settle_timer->Enabled()) { if (zone->IsIdle()) {
LogInfo("Zone is no longer idle.");
zone->SetIsIdle(false);
}
mob_settle_timer->Disable();
}
Spawn2* s2 = mob->CastToNPC()->respawn2;
// Perform normal mob processing if any of these are true:
// -- zone is not empty
// -- a quest has turned it on for this zone while zone is idle
// -- the entity's spawn2 point is marked as path_while_zone_idle
// -- the zone is newly empty and we're allowing mobs to settle
if (
numclients > 0 ||
(s2 && s2->PathWhenZoneIdle()) ||
mob_settle_timer->Enabled()
) {
mob_dead = !mob->Process();
} else {
// spawn_events can cause spawns and deaths while zone empty.
// At the very least, process that.
mob_dead = mob->CastToNPC()->GetDepop();
}
} else {
mob_dead = !mob->Process(); mob_dead = !mob->Process();
} }
else {
// spawn_events can cause spawns and deaths while zone empty.
// At the very least, process that.
mob_dead = mob->CastToNPC()->GetDepop();
}
#else
mob_dead = !mob->Process();
#endif
size_t a_sz = mob_list.size(); size_t a_sz = mob_list.size();
if(a_sz > sz) { if (a_sz > sz) {
//increased size can potentially screw with iterators so reset it to current value //increased size can potentially screw with iterators so reset it to current value
//if buckets are re-orderered we may skip a process here and there but since //if buckets are re-orderered we may skip a process here and there but since
//process happens so often it shouldn't matter much //process happens so often it shouldn't matter much
@ -529,30 +561,30 @@ void EntityList::MobProcess()
++it; ++it;
} }
if(mob_dead) { if (mob_dead) {
if(mob->IsMerc()) { if (mob->IsMerc()) {
entity_list.RemoveMerc(id); entity_list.RemoveMerc(id);
} } else if (mob->IsBot()) {
else if(mob->IsBot()) {
entity_list.RemoveBot(id); entity_list.RemoveBot(id);
} } else if (mob->IsNPC()) {
else if(mob->IsNPC()) {
entity_list.RemoveNPC(id); entity_list.RemoveNPC(id);
} } else {
else {
#ifdef _WINDOWS #ifdef _WINDOWS
struct in_addr in; struct in_addr in;
in.s_addr = mob->CastToClient()->GetIP(); in.s_addr = mob->CastToClient()->GetIP();
LogInfo("Dropping client: Process=false, ip=[{}] port=[{}]", inet_ntoa(in), mob->CastToClient()->GetPort()); LogInfo("Dropping client: Process=false, ip=[{}] port=[{}]", inet_ntoa(in), mob->CastToClient()->GetPort());
#endif #endif
Group *g = GetGroupByMob(mob);
if(g) { Group* g = GetGroupByMob(mob);
if (g) {
g->DelMember(mob); g->DelMember(mob);
} }
Raid *r = entity_list.GetRaidByClient(mob->CastToClient());
if(r) { Raid* r = entity_list.GetRaidByClient(mob->CastToClient());
if (r) {
r->MemberZoned(mob->CastToClient()); r->MemberZoned(mob->CastToClient());
} }
entity_list.RemoveClient(id); entity_list.RemoveClient(id);
} }

View File

@ -4743,6 +4743,26 @@ int lua_get_zone_minimum_lava_damage(uint32 zone_id, int version)
return zone_store.GetZoneMinimumLavaDamage(zone_id, version); return zone_store.GetZoneMinimumLavaDamage(zone_id, version);
} }
uint8 lua_get_zone_idle_when_empty(uint32 zone_id)
{
return zone_store.GetZoneIdleWhenEmpty(zone_id);
}
uint8 lua_get_zone_idle_when_empty(uint32 zone_id, int version)
{
return zone_store.GetZoneIdleWhenEmpty(zone_id, version);
}
uint32 lua_get_zone_seconds_before_idle(uint32 zone_id)
{
return zone_store.GetZoneSecondsBeforeIdle(zone_id);
}
uint32 lua_get_zone_seconds_before_idle(uint32 zone_id, int version)
{
return zone_store.GetZoneSecondsBeforeIdle(zone_id, version);
}
void lua_send_channel_message(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message) void lua_send_channel_message(uint8 channel_number, uint32 guild_id, uint8 language_id, uint8 language_skill, const char* message)
{ {
quest_manager.SendChannelMessage(channel_number, guild_id, language_id, language_skill, message); quest_manager.SendChannelMessage(channel_number, guild_id, language_id, language_skill, message);
@ -6034,6 +6054,10 @@ luabind::scope lua_register_general() {
luabind::def("get_zone_lava_damage", (int(*)(uint32,int))&lua_get_zone_lava_damage), luabind::def("get_zone_lava_damage", (int(*)(uint32,int))&lua_get_zone_lava_damage),
luabind::def("get_zone_minimum_lava_damage", (int(*)(uint32))&lua_get_zone_minimum_lava_damage), luabind::def("get_zone_minimum_lava_damage", (int(*)(uint32))&lua_get_zone_minimum_lava_damage),
luabind::def("get_zone_minimum_lava_damage", (int(*)(uint32,int))&lua_get_zone_minimum_lava_damage), luabind::def("get_zone_minimum_lava_damage", (int(*)(uint32,int))&lua_get_zone_minimum_lava_damage),
luabind::def("get_zone_idle_when_empty", (uint8(*)(uint32))&lua_get_zone_idle_when_empty),
luabind::def("get_zone_idle_when_empty", (uint8(*)(uint32,int))&lua_get_zone_idle_when_empty),
luabind::def("get_zone_seconds_before_idle", (uint32(*)(uint32))&lua_get_zone_seconds_before_idle),
luabind::def("get_zone_seconds_before_idle", (uint32(*)(uint32,int))&lua_get_zone_seconds_before_idle),
luabind::def("send_channel_message", (void(*)(uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message), luabind::def("send_channel_message", (void(*)(uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message),
luabind::def("send_channel_message", (void(*)(Lua_Client,uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message), luabind::def("send_channel_message", (void(*)(Lua_Client,uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message),
luabind::def("send_channel_message", (void(*)(Lua_Client,const char*,uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message), luabind::def("send_channel_message", (void(*)(Lua_Client,const char*,uint8,uint32,uint8,uint8,const char*))&lua_send_channel_message),

View File

@ -933,12 +933,13 @@ void QuestManager::repopzone() {
} }
} }
void QuestManager::processmobswhilezoneempty(bool on) { void QuestManager::processmobswhilezoneempty(bool idle_when_empty) {
if(zone) { if (zone) {
zone->process_mobs_while_empty = on; zone->SetIdleWhenEmpty(idle_when_empty);
} } else {
else { LogQuests(
LogQuests("QuestManager::processmobswhilezoneempty called with nullptr zone. Probably syntax error in quest file"); "QuestManager::processmobswhilezoneempty called with nullptr zone. Probably syntax error in quest file"
);
} }
} }

View File

@ -106,7 +106,7 @@ public:
void depopall(int npc_type = 0); void depopall(int npc_type = 0);
void depopzone(bool StartSpawnTimer = true); void depopzone(bool StartSpawnTimer = true);
void repopzone(); void repopzone();
void processmobswhilezoneempty(bool on); void processmobswhilezoneempty(bool idle_when_empty);
void settarget(const char *type, int target_id); void settarget(const char *type, int target_id);
void follow(int entity_id, int distance); void follow(int entity_id, int distance);
void sfollow(); void sfollow();

View File

@ -974,7 +974,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
default_ruleset = 0; default_ruleset = 0;
is_zone_time_localized = false; is_zone_time_localized = false;
process_mobs_while_empty = false;
loglevelvar = 0; loglevelvar = 0;
merchantvar = 0; merchantvar = 0;
@ -984,13 +983,17 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
short_name = strcpy(new char[strlen(in_short_name)+1], in_short_name); short_name = strcpy(new char[strlen(in_short_name)+1], in_short_name);
strlwr(short_name); strlwr(short_name);
memset(file_name, 0, sizeof(file_name)); memset(file_name, 0, sizeof(file_name));
long_name = 0;
aggroedmobs =0; long_name = 0;
aggroedmobs = 0;
m_graveyard_id = 0; m_graveyard_id = 0;
pgraveyard_zoneid = 0; pgraveyard_zoneid = 0;
m_max_clients = 0; m_max_clients = 0;
pvpzone = false; pvpzone = false;
SetIdleWhenEmpty(true);
SetSecondsBeforeIdle(60);
if (database.GetServerType() == 1) { if (database.GetServerType() == 1) {
pvpzone = true; pvpzone = true;
} }
@ -1006,6 +1009,9 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
m_graveyard_id = z->graveyard_id; m_graveyard_id = z->graveyard_id;
m_max_clients = z->maxclients; m_max_clients = z->maxclients;
SetIdleWhenEmpty(z->idle_when_empty);
SetSecondsBeforeIdle(z->seconds_before_idle);
if (z->file_name.empty()) { if (z->file_name.empty()) {
strcpy(file_name, short_name); strcpy(file_name, short_name);
} }
@ -1391,6 +1397,9 @@ bool Zone::LoadZoneCFG(const char* filename, uint16 instance_version)
m_graveyard_id = z->graveyard_id; m_graveyard_id = z->graveyard_id;
m_max_clients = z->maxclients; m_max_clients = z->maxclients;
SetIdleWhenEmpty(z->idle_when_empty);
SetSecondsBeforeIdle(z->seconds_before_idle);
// safe coordinates // safe coordinates
m_safe_points.x = z->safe_x; m_safe_points.x = z->safe_x;
m_safe_points.y = z->safe_y; m_safe_points.y = z->safe_y;
@ -3230,3 +3239,33 @@ void Zone::SetEXPModifier(Client* c, float exp_modifier)
m m
); );
} }
bool Zone::IsIdleWhenEmpty() const
{
return m_idle_when_empty;
}
void Zone::SetIdleWhenEmpty(bool idle_when_empty)
{
Zone::m_idle_when_empty = idle_when_empty;
}
uint32 Zone::GetSecondsBeforeIdle() const
{
return m_seconds_before_idle;
}
void Zone::SetSecondsBeforeIdle(uint32 seconds_before_idle)
{
Zone::m_seconds_before_idle = seconds_before_idle;
}
bool Zone::IsIdle() const
{
return m_is_idle;
}
void Zone::SetIsIdle(bool m_is_idle)
{
Zone::m_is_idle = m_is_idle;
}

View File

@ -105,7 +105,12 @@ public:
AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id);
AA::Rank *GetAlternateAdvancementRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id);
bool is_zone_time_localized; bool is_zone_time_localized;
bool process_mobs_while_empty; bool IsIdle() const;
void SetIsIdle(bool m_is_idle);
bool IsIdleWhenEmpty() const;
void SetIdleWhenEmpty(bool idle_when_empty);
uint32 GetSecondsBeforeIdle() const;
void SetSecondsBeforeIdle(uint32 seconds_before_idle);
bool AggroLimitReached() { return (aggroedmobs > 10) ? true : false; } bool AggroLimitReached() { return (aggroedmobs > 10) ? true : false; }
bool AllowMercs() const { return (allow_mercs); } bool AllowMercs() const { return (allow_mercs); }
bool CanBind() const { return (can_bind); } bool CanBind() const { return (can_bind); }
@ -436,6 +441,9 @@ private:
uint32 m_max_clients; uint32 m_max_clients;
uint32 zoneid; uint32 zoneid;
uint32 m_last_ucss_update; uint32 m_last_ucss_update;
bool m_idle_when_empty;
uint32 m_seconds_before_idle;
bool m_is_idle;
GlobalLootManager m_global_loot; GlobalLootManager m_global_loot;
LinkedList<ZoneClientAuth_Struct *> client_auth_list; LinkedList<ZoneClientAuth_Struct *> client_auth_list;