diff --git a/common/version.h b/common/version.h index 7b66c1dc4..af6a207e5 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9164 +#define CURRENT_BINARY_DATABASE_VERSION 9165 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 071a20e14..55c8facd7 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -418,6 +418,7 @@ 9162|2021_02_17_server_scheduled_events.sql|SELECT * FROM db_version WHERE version >= 9162|empty| 9163|2021_04_17_zone_safe_heading_changes.sql|SHOW COLUMNS FROM `zone` LIKE 'safe_heading'|empty| 9164|2021_04_23_character_exp_modifiers.sql|SHOW TABLES LIKE 'character_exp_modifiers'|empty| +9165|2021_04_28_idle_pathing.sql|SHOW COLUMNS FROM `spawn2` LIKE 'path_when_zone_idle'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2021_04_28_idle_pathing.sql b/utils/sql/git/required/2021_04_28_idle_pathing.sql new file mode 100644 index 000000000..c146b9f24 --- /dev/null +++ b/utils/sql/git/required/2021_04_28_idle_pathing.sql @@ -0,0 +1,13 @@ +-- Add new path_when_zone_idle flag to allow some spawns to path in empty zones +ALTER TABLE spawn2 ADD COLUMN path_when_zone_idle tinyint(1) NOT NULL DEFAULT 0 AFTER pathgrid; + +-- Update spawns that used to path in empty zones because of their grid type +-- to behave the same using the new mechanism. The code that checked path grid +-- types has been removed as it was coincidentally coupled to idle movement. +-- The new flag path_when_zone_idle is the new mechanism, and allows any moving +-- mob, not just those on grids, to path while the zone is idle. +UPDATE spawn2 s +LEFT JOIN zone z on z.short_name = s.zone +LEFT JOIN grid g on g.id = s.pathgrid AND g.zoneid = z.zoneidnumber +SET path_when_zone_idle = 1 +WHERE pathgrid != 0 AND g.type in (4, 6) diff --git a/zone/entity.cpp b/zone/entity.cpp index bf6e44a2d..5cc12dc72 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -517,13 +517,15 @@ void EntityList::MobProcess() 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 (zone->process_mobs_while_empty || numclients > 0 || - mob->GetWanderType() == 4 || mob->GetWanderType() == 6 || - mob_settle_timer->Enabled()) { - // Normal processing, or assuring that spawns that should - // path and depop do that. Otherwise all of these type mobs - // will be up and at starting positions, or waiting at the zoneline - // if they chased the PCs when idle zone wakes up. + (s2 && s2->PathWhenZoneIdle()) || mob_settle_timer->Enabled()) { mob_dead = !mob->Process(); } else { diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 62f0544c7..e01e32549 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1732,6 +1732,7 @@ void lua_add_spawn_point(luabind::adl::object table) { uint32 variance; uint32 timeleft = 0; uint32 grid = 0; + bool path_when_zone_idle = false; int condition_id = 0; int condition_min_value = 0; bool enabled = true; @@ -1841,6 +1842,14 @@ void lua_add_spawn_point(luabind::adl::object table) { } } + cur = table["path_when_zone_idle"]; + if(luabind::type(cur) != LUA_TNIL) { + try { + path_when_zone_idle = luabind::object_cast(cur); + } catch(luabind::cast_failed &) { + } + } + cur = table["condition_id"]; if(luabind::type(cur) != LUA_TNIL) { try { @@ -1875,8 +1884,10 @@ void lua_add_spawn_point(luabind::adl::object table) { lua_remove_spawn_point(spawn2_id); - auto t = new Spawn2(spawn2_id, spawngroup_id, x, y, z, heading, respawn, variance, timeleft, grid, - condition_id, condition_min_value, enabled, static_cast(animation)); + auto t = new Spawn2(spawn2_id, spawngroup_id, x, y, z, heading, respawn, + variance, timeleft, grid, path_when_zone_idle, condition_id, + condition_min_value, enabled, static_cast(animation)); + zone->spawn2_list.Insert(t); } } diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 37b8cc943..b6689d715 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -70,7 +70,8 @@ CREATE TABLE spawn_events ( Spawn2::Spawn2(uint32 in_spawn2_id, uint32 spawngroup_id, float in_x, float in_y, float in_z, float in_heading, uint32 respawn, uint32 variance, uint32 timeleft, uint32 grid, - uint16 in_cond_id, int16 in_min_value, bool in_enabled, EmuAppearance anim) + bool in_path_when_zone_idle, uint16 in_cond_id, int16 in_min_value, + bool in_enabled, EmuAppearance anim) : timer(100000), killcount(0) { spawn2_id = in_spawn2_id; @@ -82,6 +83,7 @@ Spawn2::Spawn2(uint32 in_spawn2_id, uint32 spawngroup_id, respawn_ = respawn; variance_ = variance; grid_ = grid; + path_when_zone_idle = in_path_when_zone_idle; condition_id = in_cond_id; condition_min_value = in_min_value; npcthis = nullptr; @@ -474,6 +476,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList "respawntime, " "variance, " "pathgrid, " + "path_when_zone_idle, " "_condition, " "cond_value, " "enabled, " @@ -494,7 +497,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList uint32 spawn_time_left = 0; Spawn2* new_spawn = 0; - bool perl_enabled = atoi(row[11]) == 1 ? true : false; + bool perl_enabled = atoi(row[12]) == 1 ? true : false; if (spawn_times.count(atoi(row[0])) != 0) spawn_time_left = spawn_times[atoi(row[0])]; @@ -508,21 +511,22 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList if (mob_distance > repop_distance) continue; - new_spawn = new Spawn2( // - atoi(row[0]), // uint32 in_spawn2_id - atoi(row[1]), // uint32 spawngroup_id - atof(row[2]), // float in_x - atof(row[3]), // float in_y - atof(row[4]), // float in_z - atof(row[5]), // float in_heading - atoi(row[6]), // uint32 respawn - atoi(row[7]), // uint32 variance - spawn_time_left, // uint32 timeleft - atoi(row[8]), // uint32 grid - atoi(row[9]), // uint16 in_cond_id - atoi(row[10]), // int16 in_min_value - perl_enabled, // bool in_enabled - (EmuAppearance)atoi(row[12]) // EmuAppearance anim + new_spawn = new Spawn2( + atoi(row[0]), // uint32 in_spawn2_id + atoi(row[1]), // uint32 spawngroup_id + atof(row[2]), // float in_x + atof(row[3]), // float in_y + atof(row[4]), // float in_z + atof(row[5]), // float in_heading + atoi(row[6]), // uint32 respawn + atoi(row[7]), // uint32 variance + spawn_time_left, // uint32 timeleft + atoi(row[8]), // uint32 grid + (bool)atoi(row[9]), // bool path_when_zone_idle + atoi(row[10]), // uint16 in_cond_id + atoi(row[11]), // int16 in_min_value + perl_enabled, // bool in_enabled + (EmuAppearance)atoi(row[13]) // EmuAppearance anim ); spawn2_list.Insert(new_spawn); @@ -578,6 +582,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa "respawntime, " "variance, " "pathgrid, " + "path_when_zone_idle, " "_condition, " "cond_value, " "enabled, " @@ -598,26 +603,27 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa uint32 spawn_time_left = 0; Spawn2* new_spawn = 0; - bool perl_enabled = atoi(row[11]) == 1 ? true : false; + bool perl_enabled = atoi(row[12]) == 1 ? true : false; if (spawn_times.count(atoi(row[0])) != 0) spawn_time_left = spawn_times[atoi(row[0])]; - new_spawn = new Spawn2( // - atoi(row[0]), // uint32 in_spawn2_id - atoi(row[1]), // uint32 spawngroup_id - atof(row[2]), // float in_x - atof(row[3]), // float in_y - atof(row[4]), // float in_z - atof(row[5]), // float in_heading - atoi(row[6]), // uint32 respawn - atoi(row[7]), // uint32 variance - spawn_time_left, // uint32 timeleft - atoi(row[8]), // uint32 grid - atoi(row[9]), // uint16 in_cond_id - atoi(row[10]), // int16 in_min_value - perl_enabled, // bool in_enabled - (EmuAppearance)atoi(row[12]) // EmuAppearance anim + new_spawn = new Spawn2( + atoi(row[0]), // uint32 in_spawn2_id + atoi(row[1]), // uint32 spawngroup_id + atof(row[2]), // float in_x + atof(row[3]), // float in_y + atof(row[4]), // float in_z + atof(row[5]), // float in_heading + atoi(row[6]), // uint32 respawn + atoi(row[7]), // uint32 variance + spawn_time_left, // uint32 timeleft + atoi(row[8]), // uint32 grid + (bool)atoi(row[9]), // bool path_when_zone_idle + atoi(row[10]), // uint16 in_cond_id + atoi(row[11]), // int16 in_min_value + perl_enabled, // bool in_enabled + (EmuAppearance)atoi(row[13]) // EmuAppearance anim ); spawn2_list.Insert(new_spawn); @@ -632,9 +638,10 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa Spawn2* ZoneDatabase::LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2id, uint32 timeleft) { std::string query = StringFormat("SELECT id, spawngroupID, x, y, z, heading, " - "respawntime, variance, pathgrid, _condition, " - "cond_value, enabled, animation FROM spawn2 " - "WHERE id = %i", spawn2id); + "respawntime, variance, pathgrid, " + "path_when_zone_idle, _condition, " + "cond_value, enabled, animation FROM spawn2 " + "WHERE id = %i", spawn2id); auto results = QueryDatabase(query); if (!results.Success()) { return nullptr; @@ -646,11 +653,12 @@ Spawn2* ZoneDatabase::LoadSpawn2(LinkedList &spawn2_list, uint32 spawn2 auto row = results.begin(); - bool perl_enabled = atoi(row[11]) == 1 ? true : false; + bool perl_enabled = atoi(row[12]) == 1 ? true : false; - auto newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), atof(row[3]), atof(row[4]), atof(row[5]), - atoi(row[6]), atoi(row[7]), timeleft, atoi(row[8]), atoi(row[9]), atoi(row[10]), - perl_enabled, (EmuAppearance)atoi(row[12])); + auto newSpawn = new Spawn2(atoi(row[0]), atoi(row[1]), atof(row[2]), + atof(row[3]), atof(row[4]), atof(row[5]), atoi(row[6]), atoi(row[7]), + timeleft, atoi(row[8]), (bool) atoi(row[9]), atoi(row[10]), + atoi(row[11]), perl_enabled, (EmuAppearance)atoi(row[13])); spawn2_list.Insert(newSpawn); diff --git a/zone/spawn2.h b/zone/spawn2.h index bf6530876..3f8b2e8ee 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -32,7 +32,7 @@ public: Spawn2(uint32 spawn2_id, uint32 spawngroup_id, float x, float y, float z, float heading, uint32 respawn, uint32 variance, - uint32 timeleft = 0, uint32 grid = 0, + uint32 timeleft = 0, uint32 grid = 0, bool in_path_when_zone_idle=false, uint16 cond_id = SC_AlwaysEnabled, int16 min_value = 0, bool in_enabled = true, EmuAppearance anim = eaStanding); ~Spawn2(); @@ -54,6 +54,7 @@ public: float GetY() { return y; } float GetZ() { return z; } float GetHeading() { return heading; } + bool PathWhenZoneIdle() { return path_when_zone_idle; } void SetRespawnTimer(uint32 newrespawntime) { respawn_ = newrespawntime; }; void SetVariance(uint32 newvariance) { variance_ = newvariance; } const uint32 GetVariance() const { return variance_; } @@ -86,6 +87,7 @@ private: float heading; uint32 variance_; uint32 grid_; + bool path_when_zone_idle; uint16 condition_id; int16 condition_min_value; bool enabled;