[Spawn] (imported from takp) Added min_time and max_time to spawnentry. This will prevent a NPC from… (#3685)

* Added mintime and maxtime to spawnentry. This will prevent a NPC from spawning outside of the times specified. NPCs spawned in this way will then behave like normal NPCs. They will not despawn on their own, unlike spawn_events/spawn_conditions. NPCs using this that are alone in their spawngroup will attempt to spawn after their respawn timer has expired if the time of day is outside their range. Otherwise, another NPC in the spawngroup will be chosen to spawn. The normal rules (chance, spawn_limit) still apply to these NPCs, this is just another rule added to the system.

mintime and maxtime both represent the in-game EQ Hour. Valid values are 1-24. If either or both of the values are 0, then the NPC will not have any time restriction.

Added a new rule World:BootHour. This allows server admins to specify the EQ hour the server will boot to. Valid options are 1-24. Setting this rule to 0 (default) disables it and world will use whatever time is specified in the DB.

* generated base_spawnentry_repository.h from script

* removed the rule insert from database_update_manifest.cpp.

* Add logging, initializers, minor cleanup

* Remove if/else branch

* Update eqtime.cpp

* Initializers, logging

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
regneq 2023-11-18 12:23:04 -08:00 committed by GitHub
parent 6ef182edfd
commit ded82ac6d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 184 additions and 76 deletions

View File

@ -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();

View File

@ -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,

View File

@ -100,6 +100,8 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Discord].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::QuestErrors].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::EqTime].log_to_gmsay = static_cast<uint8>(Logs::General);
/**
* RFC 5424

View File

@ -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",
};
}

View File

@ -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__);\

View File

@ -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;
}

View File

@ -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);

View File

@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
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<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(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<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(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<int32_t>(atoi(row[1]));
e.chance = static_cast<int16_t>(atoi(row[2]));
e.condition_value_filter = static_cast<int32_t>(atoi(row[3]));
e.min_expansion = static_cast<int8_t>(atoi(row[4]));
e.max_expansion = static_cast<int8_t>(atoi(row[5]));
e.content_flags = row[6] ? row[6] : "";
e.content_flags_disabled = row[7] ? row[7] : "";
e.min_time = static_cast<int16_t>(atoi(row[4]));
e.max_time = static_cast<int16_t>(atoi(row[5]));
e.min_expansion = static_cast<int8_t>(atoi(row[6]));
e.max_expansion = static_cast<int8_t>(atoi(row[7]));
e.content_flags = row[8] ? row[8] : "";
e.content_flags_disabled = row[9] ? row[9] : "";
all_entries.push_back(e);
}

View File

@ -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)

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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,

View File

@ -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(

View File

@ -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);

View File

@ -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) {

View File

@ -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]));

View File

@ -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

View File

@ -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]",