diff --git a/common/database.cpp b/common/database.cpp index 738fc0d82..e9fb58dac 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -2097,37 +2097,45 @@ void Database::ClearInvSnapshots(bool from_now) { struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) { - - TimeOfDay_Struct eqTime; - std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); + TimeOfDay_Struct t{}; + std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0){ + if (!results.Success() || results.RowCount() == 0) { LogInfo("Loading EQ time of day failed. Using defaults"); - eqTime.minute = 0; - eqTime.hour = 9; - eqTime.day = 1; - eqTime.month = 1; - eqTime.year = 3100; + t.minute = 0; + t.hour = 9; + t.day = 1; + t.month = 1; + t.year = 3100; realtime = time(nullptr); - } - else{ - auto row = results.begin(); - - eqTime.minute = Strings::ToUnsignedInt(row[0]); - eqTime.hour = Strings::ToUnsignedInt(row[1]); - eqTime.day = Strings::ToUnsignedInt(row[2]); - eqTime.month = Strings::ToUnsignedInt(row[3]); - eqTime.year = Strings::ToUnsignedInt(row[4]); - realtime = Strings::ToBigInt(row[5]); + return t; } - return eqTime; + auto row = results.begin(); + + uint8 hour = Strings::ToUnsignedInt(row[1]); + time_t realtime_ = Strings::ToBigInt(row[5]); + if (RuleI(World, BootHour) > 0 && RuleI(World, BootHour) <= 24) { + hour = RuleI(World, BootHour); + realtime_ = time(nullptr); + } + + t.minute = Strings::ToUnsignedInt(row[0]); + t.hour = hour; + t.day = Strings::ToUnsignedInt(row[2]); + t.month = Strings::ToUnsignedInt(row[3]); + t.year = Strings::ToUnsignedInt(row[4]); + realtime = realtime_; + + LogEqTime("Setting hour to [{}]", hour); + + return t; } bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year) { - std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(0)); + std::string query = StringFormat("UPDATE eqtime set minute = %d, hour = %d, day = %d, month = %d, year = %d, realtime = %d limit 1", minute, hour, day, month, year, time(nullptr)); auto results = QueryDatabase(query); return results.Success(); diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 1787337a0..6121515a6 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5018,7 +5018,18 @@ INSERT INTO spawn2_disabled (spawn2_id, disabled) SELECT id, 1 FROM spawn2 WHERE ALTER TABLE `spawn2` DROP COLUMN `enabled`; )" }, - + ManifestEntry{ + .version = 9242, + .description = "2023_11_7_mintime_maxtime_spawnentry.sql", + .check = "SHOW COLUMNS FROM `spawnentry` LIKE 'min_time'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `spawnentry` +ADD COLUMN `min_time` smallint(4) NOT NULL DEFAULT 0 AFTER `condition_value_filter`, +ADD COLUMN `max_time` smallint(4) NOT NULL DEFAULT 0 AFTER `min_time`; +)" + }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ // .version = 9228, diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index df6508daf..3509baa7b 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -100,6 +100,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() log_settings[Logs::Discord].log_to_console = static_cast(Logs::General); log_settings[Logs::QuestErrors].log_to_gmsay = static_cast(Logs::General); log_settings[Logs::QuestErrors].log_to_console = static_cast(Logs::General); + log_settings[Logs::EqTime].log_to_console = static_cast(Logs::General); + log_settings[Logs::EqTime].log_to_gmsay = static_cast(Logs::General); /** * RFC 5424 diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index cbbbd1e6f..d158fbc36 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -139,6 +139,7 @@ namespace Logs { PlayerEvents, DataBuckets, Zoning, + EqTime, MaxCategoryID /* Don't Remove this */ }; @@ -237,6 +238,7 @@ namespace Logs { "PlayerEvents", "DataBuckets", "Zoning", + "EqTime", }; } diff --git a/common/eqemu_logsys_log_aliases.h b/common/eqemu_logsys_log_aliases.h index 07b031c9c..b4c90bbbb 100644 --- a/common/eqemu_logsys_log_aliases.h +++ b/common/eqemu_logsys_log_aliases.h @@ -814,6 +814,16 @@ OutF(LogSys, Logs::Detail, Logs::Zoning, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ } while (0) +#define LogEqTime(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::General, Logs::EqTime))\ + OutF(LogSys, Logs::General, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + +#define LogEqTimeDetail(message, ...) do {\ + if (LogSys.IsLogEnabled(Logs::Detail, Logs::EqTime))\ + OutF(LogSys, Logs::Detail, Logs::EqTime, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ +} while (0) + #define Log(debug_level, log_category, message, ...) do {\ if (LogSys.IsLogEnabled(debug_level, log_category))\ LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\ diff --git a/common/eqtime.cpp b/common/eqtime.cpp index 49d5f32c3..1478dafd8 100644 --- a/common/eqtime.cpp +++ b/common/eqtime.cpp @@ -46,16 +46,16 @@ EQTime::EQTime() timezone = 0; memset(&eqTime, 0, sizeof(eqTime)); //Defaults for time - TimeOfDay_Struct start; - start.day = 1; - start.hour = 9; - start.minute = 0; - start.month = 1; - start.year = 3100; + TimeOfDay_Struct t{}; + t.day = 1; + t.hour = 9; + t.minute = 0; + t.month = 1; + t.year = 3100; //Set default time zone timezone = 0; //Start EQTimer - SetCurrentEQTimeOfDay(start, time(0)); + SetCurrentEQTimeOfDay(t, time(nullptr)); } //getEQTimeOfDay - Reads timeConvert and writes the result to eqTimeOfDay @@ -202,7 +202,7 @@ void EQTime::ToString(TimeOfDay_Struct *t, std::string &str) { } bool EQTime::IsDayTime() { - TimeOfDay_Struct tod; //Day time is 5am to 6:59pm (14 hours in-game) + TimeOfDay_Struct tod{}; //Day time is 5am to 6:59pm (14 hours in-game) GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero? if (tod.hour >= 5 || tod.hour < 19) { @@ -213,7 +213,7 @@ bool EQTime::IsDayTime() { } bool EQTime::IsNightTime() { - TimeOfDay_Struct tod; //Night time is 7pm to 4:59am (10 hours in-game) + TimeOfDay_Struct tod{}; //Night time is 7pm to 4:59am (10 hours in-game) GetCurrentEQTimeOfDay(&tod); //TODO: what if it fails and returns zero? if (tod.hour >= 19 || tod.hour < 5) { @@ -222,3 +222,25 @@ bool EQTime::IsNightTime() { return false; } + +bool EQTime::IsInbetweenTime(uint8 min_time, uint8 max_time) { + TimeOfDay_Struct tod{}; + GetCurrentEQTimeOfDay(&tod); + + if (min_time == 0 || max_time == 0 || min_time > 24 || max_time > 24) { + return true; + } + + if (max_time < min_time) { + if ((tod.hour >= min_time && tod.hour > max_time) || (tod.hour < min_time && tod.hour <= max_time)) { + return true; + } + } + else { + if (tod.hour >= min_time && tod.hour <= max_time) { + return true; + } + } + + return false; +} diff --git a/common/eqtime.h b/common/eqtime.h index c55689a0f..f79d274f8 100644 --- a/common/eqtime.h +++ b/common/eqtime.h @@ -30,6 +30,7 @@ public: uint32 getEQTimeZoneMin() { return timezone%60; } bool IsDayTime(); bool IsNightTime(); + bool IsInbetweenTime(uint8 min_time, uint8 max_time); //Set functions int SetCurrentEQTimeOfDay(TimeOfDay_Struct start_eq, time_t start_real); diff --git a/common/repositories/base/base_spawnentry_repository.h b/common/repositories/base/base_spawnentry_repository.h index 1632a4c79..99f6c2ae0 100644 --- a/common/repositories/base/base_spawnentry_repository.h +++ b/common/repositories/base/base_spawnentry_repository.h @@ -16,6 +16,7 @@ #include "../../strings.h" #include + class BaseSpawnentryRepository { public: struct Spawnentry { @@ -23,6 +24,8 @@ public: int32_t npcID; int16_t chance; int32_t condition_value_filter; + int16_t min_time; + int16_t max_time; int8_t min_expansion; int8_t max_expansion; std::string content_flags; @@ -41,6 +44,8 @@ public: "npcID", "chance", "condition_value_filter", + "min_time", + "max_time", "min_expansion", "max_expansion", "content_flags", @@ -55,6 +60,8 @@ public: "npcID", "chance", "condition_value_filter", + "min_time", + "max_time", "min_expansion", "max_expansion", "content_flags", @@ -103,6 +110,8 @@ public: e.npcID = 0; e.chance = 0; e.condition_value_filter = 1; + e.min_time = 0; + e.max_time = 0; e.min_expansion = -1; e.max_expansion = -1; e.content_flags = ""; @@ -132,8 +141,9 @@ public: { auto results = db.QueryDatabase( fmt::format( - "{} WHERE id = {} LIMIT 1", + "{} WHERE {} = {} LIMIT 1", BaseSelect(), + PrimaryKey(), spawnentry_id ) ); @@ -146,10 +156,12 @@ public: e.npcID = static_cast(atoi(row[1])); e.chance = static_cast(atoi(row[2])); e.condition_value_filter = static_cast(atoi(row[3])); - e.min_expansion = static_cast(atoi(row[4])); - e.max_expansion = static_cast(atoi(row[5])); - e.content_flags = row[6] ? row[6] : ""; - e.content_flags_disabled = row[7] ? row[7] : ""; + e.min_time = static_cast(atoi(row[4])); + e.max_time = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; return e; } @@ -187,10 +199,12 @@ public: v.push_back(columns[1] + " = " + std::to_string(e.npcID)); v.push_back(columns[2] + " = " + std::to_string(e.chance)); v.push_back(columns[3] + " = " + std::to_string(e.condition_value_filter)); - v.push_back(columns[4] + " = " + std::to_string(e.min_expansion)); - v.push_back(columns[5] + " = " + std::to_string(e.max_expansion)); - v.push_back(columns[6] + " = '" + Strings::Escape(e.content_flags) + "'"); - v.push_back(columns[7] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); + v.push_back(columns[4] + " = " + std::to_string(e.min_time)); + v.push_back(columns[5] + " = " + std::to_string(e.max_time)); + v.push_back(columns[6] + " = " + std::to_string(e.min_expansion)); + v.push_back(columns[7] + " = " + std::to_string(e.max_expansion)); + v.push_back(columns[8] + " = '" + Strings::Escape(e.content_flags) + "'"); + v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags_disabled) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -216,6 +230,8 @@ public: v.push_back(std::to_string(e.npcID)); v.push_back(std::to_string(e.chance)); v.push_back(std::to_string(e.condition_value_filter)); + v.push_back(std::to_string(e.min_time)); + v.push_back(std::to_string(e.max_time)); v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.max_expansion)); v.push_back("'" + Strings::Escape(e.content_flags) + "'"); @@ -253,6 +269,8 @@ public: v.push_back(std::to_string(e.npcID)); v.push_back(std::to_string(e.chance)); v.push_back(std::to_string(e.condition_value_filter)); + v.push_back(std::to_string(e.min_time)); + v.push_back(std::to_string(e.max_time)); v.push_back(std::to_string(e.min_expansion)); v.push_back(std::to_string(e.max_expansion)); v.push_back("'" + Strings::Escape(e.content_flags) + "'"); @@ -294,10 +312,12 @@ public: e.npcID = static_cast(atoi(row[1])); e.chance = static_cast(atoi(row[2])); e.condition_value_filter = static_cast(atoi(row[3])); - e.min_expansion = static_cast(atoi(row[4])); - e.max_expansion = static_cast(atoi(row[5])); - e.content_flags = row[6] ? row[6] : ""; - e.content_flags_disabled = row[7] ? row[7] : ""; + e.min_time = static_cast(atoi(row[4])); + e.max_time = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; all_entries.push_back(e); } @@ -326,10 +346,12 @@ public: e.npcID = static_cast(atoi(row[1])); e.chance = static_cast(atoi(row[2])); e.condition_value_filter = static_cast(atoi(row[3])); - e.min_expansion = static_cast(atoi(row[4])); - e.max_expansion = static_cast(atoi(row[5])); - e.content_flags = row[6] ? row[6] : ""; - e.content_flags_disabled = row[7] ? row[7] : ""; + e.min_time = static_cast(atoi(row[4])); + e.max_time = static_cast(atoi(row[5])); + e.min_expansion = static_cast(atoi(row[6])); + e.max_expansion = static_cast(atoi(row[7])); + e.content_flags = row[8] ? row[8] : ""; + e.content_flags_disabled = row[9] ? row[9] : ""; all_entries.push_back(e); } diff --git a/common/ruletypes.h b/common/ruletypes.h index 05e4ffbd6..179a12c21 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -303,6 +303,7 @@ RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for cha RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)") RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt") RULE_INT(World, MaximumQuestErrors, 30, "Changes the maximum number of quest errors that can be displayed in #questerrors, default is 30") +RULE_INT(World, BootHour, 0, "Sets the in-game hour world will set when it first boots. 0-24 are valid options, where 0 disables this rule") RULE_CATEGORY_END() RULE_CATEGORY(Zone) diff --git a/common/version.h b/common/version.h index 79417407f..ac979a1a7 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9241 +#define CURRENT_BINARY_DATABASE_VERSION 9242 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9040 diff --git a/world/main.cpp b/world/main.cpp index a01c57ed1..4ad11a356 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -424,12 +424,21 @@ int main(int argc, char **argv) } if (EQTimeTimer.Check()) { - TimeOfDay_Struct tod; - zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(0), &tod); - if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) - LogError("Failed to save eqtime"); - else - LogDebug("EQTime successfully saved"); + TimeOfDay_Struct tod{}; + zoneserver_list.worldclock.GetCurrentEQTimeOfDay(time(nullptr), &tod); + if (!database.SaveTime(tod.minute, tod.hour, tod.day, tod.month, tod.year)) { + LogEqTime("Failed to save eqtime"); + } + else { + LogEqTime( + "EQTime successfully saved - time is now [{}:{}:{}:{}:{}]", + tod.year, + tod.month, + tod.day, + tod.hour, + tod.minute + ); + } } zoneserver_list.Process(); diff --git a/zone/embparser.cpp b/zone/embparser.cpp index b64c8d8f8..299810bd4 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -1440,7 +1440,7 @@ void PerlembParser::ExportZoneVariables(std::string &package_name) ExportVar(package_name.c_str(), "zonesn", zone->GetShortName()); ExportVar(package_name.c_str(), "instanceid", zone->GetInstanceID()); ExportVar(package_name.c_str(), "instanceversion", zone->GetInstanceVersion()); - TimeOfDay_Struct eqTime; + TimeOfDay_Struct eqTime{}; zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); ExportVar(package_name.c_str(), "zonehour", eqTime.hour - 1); ExportVar(package_name.c_str(), "zonemin", eqTime.minute); diff --git a/zone/gm_commands/set/date.cpp b/zone/gm_commands/set/date.cpp index cac21e061..5531db20d 100755 --- a/zone/gm_commands/set/date.cpp +++ b/zone/gm_commands/set/date.cpp @@ -14,14 +14,14 @@ void SetDate(Client *c, const Seperator *sep) return; } - TimeOfDay_Struct eq_time; - zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eq_time); + TimeOfDay_Struct t{}; + zone->zone_time.GetCurrentEQTimeOfDay(time(0), &t); const uint16 year = Strings::ToUnsignedInt(sep->arg[2]); const uint8 month = Strings::ToUnsignedInt(sep->arg[3]); const uint8 day = Strings::ToUnsignedInt(sep->arg[4]); - const uint8 hour = !sep->IsNumber(5) ? eq_time.hour : Strings::ToUnsignedInt(sep->arg[5]) + 1; - const uint8 minute = !sep->IsNumber(6) ? eq_time.minute : Strings::ToUnsignedInt(sep->arg[6]); + const uint8 hour = !sep->IsNumber(5) ? t.hour : Strings::ToUnsignedInt(sep->arg[5]) + 1; + const uint8 minute = !sep->IsNumber(6) ? t.minute : Strings::ToUnsignedInt(sep->arg[6]); c->Message( Chat::White, diff --git a/zone/gm_commands/set/time.cpp b/zone/gm_commands/set/time.cpp index 6cd3ab57b..228a69fcd 100755 --- a/zone/gm_commands/set/time.cpp +++ b/zone/gm_commands/set/time.cpp @@ -6,7 +6,7 @@ void SetTime(Client *c, const Seperator *sep) if (arguments < 2 || !sep->IsNumber(2)) { c->Message(Chat::White, "Usage: #set time [Hour] [Minute]"); - TimeOfDay_Struct world_time; + TimeOfDay_Struct world_time{}; zone->zone_time.GetCurrentEQTimeOfDay(time(0), &world_time); auto time_string = fmt::format( diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 3604c146f..616376dcd 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1273,7 +1273,7 @@ int lua_get_zone_weather() { } luabind::adl::object lua_get_zone_time(lua_State *L) { - TimeOfDay_Struct eqTime; + TimeOfDay_Struct eqTime{}; zone->zone_time.GetCurrentEQTimeOfDay(time(0), &eqTime); luabind::adl::object ret = luabind::newtable(L); diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index efb435c1d..7985cf42a 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -692,7 +692,7 @@ void SpawnConditionManager::Process() { //check each spawn event. //get our current time - TimeOfDay_Struct tod; + TimeOfDay_Struct tod{}; zone->zone_time.GetCurrentEQTimeOfDay(&tod); //see if time is past our nearest event. @@ -745,7 +745,7 @@ void SpawnConditionManager::ExecEvent(SpawnEvent &event, bool send_update) { return; //unable to find the spawn condition to operate on } - TimeOfDay_Struct tod; + TimeOfDay_Struct tod{}; zone->zone_time.GetCurrentEQTimeOfDay(&tod); if(event.strict && (event.next.hour != tod.hour || event.next.day != tod.day || event.next.month != tod.month || event.next.year != tod.year)) { @@ -956,7 +956,7 @@ bool SpawnConditionManager::LoadSpawnConditions(const char* zone_name, uint32 in //spawn points which get turned on. Im too lazy to figure out a //better solution, and I just dont care thats much. //get our current time - TimeOfDay_Struct tod; + TimeOfDay_Struct tod{}; zone->zone_time.GetCurrentEQTimeOfDay(&tod); for(auto cur = spawn_events.begin(); cur != spawn_events.end(); ++cur) { diff --git a/zone/spawngroup.cpp b/zone/spawngroup.cpp index a25fbedfc..acf03f071 100644 --- a/zone/spawngroup.cpp +++ b/zone/spawngroup.cpp @@ -29,12 +29,13 @@ extern EntityList entity_list; extern Zone *zone; -SpawnEntry::SpawnEntry(uint32 in_NPCType, int in_chance, uint16 in_filter, uint8 in_npc_spawn_limit) -{ +SpawnEntry::SpawnEntry(uint32 in_NPCType, int in_chance, uint16 in_filter, uint8 in_npc_spawn_limit, uint8 in_min_time, uint8 in_max_time) { NPCType = in_NPCType; chance = in_chance; condition_value_filter = in_filter; npc_spawn_limit = in_npc_spawn_limit; + min_time = in_min_time; + max_time = in_max_time; } SpawnGroup::SpawnGroup( @@ -85,8 +86,15 @@ uint32 SpawnGroup::GetNPCType(uint16 in_filter) continue; } - if (se->condition_value_filter != in_filter) + if (se->min_time != 0 && se->max_time != 0 && se->min_time <= 24 && se->max_time <= 24) { + if (!zone->zone_time.IsInbetweenTime(se->min_time, se->max_time)) { + continue; + } + } + + if (se->condition_value_filter != in_filter) { continue; + } totalchance += se->chance; possible.push_back(se); @@ -224,7 +232,9 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG chance, condition_value_filter, npc_types.spawn_limit - AS sl + AS sl, + min_time, + max_time FROM spawnentry, spawn2, @@ -251,7 +261,9 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG Strings::ToInt(row[1]), Strings::ToInt(row[2]), Strings::ToInt(row[3]), - (row[4] ? Strings::ToInt(row[4]) : 0) + (row[4] ? Strings::ToInt(row[4]) : 0), + Strings::ToInt(row[5]), + Strings::ToInt(row[6]) ); SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(Strings::ToInt(row[0])); @@ -340,7 +352,9 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn spawnentry.npcid, spawnentry.chance, spawnentry.condition_value_filter, - spawngroup.spawn_limit + spawngroup.spawn_limit, + spawnentry.min_time, + spawnentry.max_time FROM spawnentry, spawngroup @@ -361,16 +375,20 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn Strings::ToInt(row[1]), Strings::ToInt(row[2]), Strings::ToInt(row[3]), - (row[4] ? Strings::ToInt(row[4]) : 0) + (row[4] ? Strings::ToInt(row[4]) : 0), + Strings::ToInt(row[5]), + Strings::ToInt(row[6]) ); LogSpawnsDetail( - "Loading spawn_entry spawn_group_id [{}] npc_id [{}] chance [{}] condition_value_filter [{}] spawn_limit [{}]", + "Loading spawn_entry spawn_group_id [{}] npc_id [{}] chance [{}] condition_value_filter [{}] spawn_limit [{}] min_time [{}] max_time [{}] ", row[0], row[1], row[2], row[3], - row[4] + row[4], + row[5], + row[6] ); SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(Strings::ToInt(row[0])); diff --git a/zone/spawngroup.h b/zone/spawngroup.h index f5cf437df..9fee72996 100644 --- a/zone/spawngroup.h +++ b/zone/spawngroup.h @@ -26,10 +26,12 @@ class SpawnEntry { public: - SpawnEntry(uint32 in_NPCType, int in_chance, uint16 in_filter, uint8 in_npc_spawn_limit); + SpawnEntry(uint32 in_NPCType, int in_chance, uint16 in_filter, uint8 in_npc_spawn_limit, uint8 in_min_time, uint8 in_max_time); ~SpawnEntry() {} uint32 NPCType; int chance; + uint8 min_time; + uint8 max_time; uint16 condition_value_filter; //this is a cached value from npc_types, for speed diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index e1bc27cbe..290cf1a17 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -965,7 +965,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) char time_message[255]; time_t current_time = time(nullptr); - TimeOfDay_Struct eq_time; + TimeOfDay_Struct eq_time{}; zone->zone_time.GetCurrentEQTimeOfDay(current_time, &eq_time); sprintf(time_message, "EQTime [%02d:%s%d %s]",