diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 42da1cd94..90d2b1e0d 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -182,8 +182,9 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou } if (has_home == 0 || has_bind == 0) { - cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i AND %i & expansions = expansions", - cse->Class, cse->Deity, cse->Race, RuleI(World, ExpansionSettings)); + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); + cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i AND min_expansion <= %i AND max_expansion >= %i", + cse->Class, cse->Deity, cse->Race, latest_expansion, latest_expansion); auto results_bind = database.QueryDatabase(cquery); for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) { /* If a bind_id is specified, make them start there */ @@ -356,10 +357,11 @@ bool WorldDatabase::GetStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_pp->x = in_pp->y = in_pp->z = in_pp->heading = in_pp->zone_id = 0; in_pp->binds[0].x = in_pp->binds[0].y = in_pp->binds[0].z = in_pp->binds[0].zoneId = in_pp->binds[0].instance_id = 0; + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); // see if we have an entry for start_zone. We can support both titanium & SOF+ by having two entries per class/race/deity combo with different zone_ids std::string query = StringFormat("SELECT x, y, z, heading, start_zone, bind_id, bind_x, bind_y, bind_z FROM start_zones WHERE zone_id = %i " - "AND player_class = %i AND player_deity = %i AND player_race = %i AND %i & expansions = expansions", - in_cc->start_zone, in_cc->class_, in_cc->deity, in_cc->race, RuleI(World, ExpansionSettings)); + "AND player_class = %i AND player_deity = %i AND player_race = %i AND min_expansion <= %i AND max_expansion >= %i", + in_cc->start_zone, in_cc->class_, in_cc->deity, in_cc->race, latest_expansion, latest_expansion); auto results = QueryDatabase(query); if(!results.Success()) { return false; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 98105f155..56acb22d1 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -12305,9 +12305,10 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) uint32 zoneid = 0; uint32 startCity = (uint32)strtol((const char*)app->pBuffer, nullptr, 10); + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); std::string query = StringFormat("SELECT zone_id, bind_id, x, y, z FROM start_zones " - "WHERE player_class=%i AND player_deity=%i AND player_race=%i AND %i & expansions = expansions", - m_pp.class_, m_pp.deity, m_pp.race, RuleI(World, ExpansionSettings)); + "WHERE player_class=%i AND player_deity=%i AND player_race=%i AND auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings));", + m_pp.class_, m_pp.deity, m_pp.race, latest_expansion, latest_expansion); auto results = database.QueryDatabase(query); if (!results.Success()) { Log(Logs::General, Logs::Error, "No valid start zones found for /setstartcity"); @@ -12337,8 +12338,8 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app) } query = StringFormat("SELECT zone_id, bind_id FROM start_zones " - "WHERE player_class=%i AND player_deity=%i AND player_race=%i AND %i & expansions = expansions", - m_pp.class_, m_pp.deity, m_pp.race, RuleI(World, ExpansionSettings)); + "WHERE player_class=%i AND player_deity=%i AND player_race=%i AND min_expansion <= %i AND max_expansion >= %i", + m_pp.class_, m_pp.deity, m_pp.race, latest_expansion, latest_expansion); results = database.QueryDatabase(query); if (!results.Success()) return; diff --git a/zone/command.cpp b/zone/command.cpp index ce46550f3..51cbabd45 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3705,20 +3705,22 @@ void command_findzone(Client *c, const Seperator *sep) return; } + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); std::string query; int id = atoi((const char *)sep->arg[1]); if (id == 0) { // If id evaluates to 0, then search as if user entered a string. auto escName = new char[strlen(sep->arg[1]) * 2 + 1]; database.DoEscapeString(escName, sep->arg[1], strlen(sep->arg[1])); + query = StringFormat("SELECT zoneidnumber, short_name, long_name FROM zone " - "WHERE long_name RLIKE '%s' AND version = 0 AND %i & expansions = expansions", - escName, RuleI(World, ExpansionSettings)); + "WHERE long_name RLIKE '%s' AND version = 0 AND min_expansion <= %i AND max_expansion >= %i", + escName, latest_expansion, latest_expansion); safe_delete_array(escName); } else // Otherwise, look for just that zoneidnumber. query = StringFormat("SELECT zoneidnumber, short_name, long_name FROM zone " - "WHERE zoneidnumber = %i AND version = 0 AND %i & expansions = expansions", id, RuleI(World, ExpansionSettings)); + "WHERE zoneidnumber = %i AND version = 0 AND min_expansion <= %i AND max_expansion >= %i", id, latest_expansion, latest_expansion); auto results = database.QueryDatabase(query); if (!results.Success()) { diff --git a/zone/trap.cpp b/zone/trap.cpp index d4d742b4e..6eb42426c 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -399,9 +399,10 @@ void EntityList::ClearTrapPointers() bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) { + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); std::string query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, " "maxzdiff, radius, chance, message, respawn_time, respawn_var, level, " - "`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u AND %i & expansions = expansions", zonename, version, RuleI(World, ExpansionSettings)); + "`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u AND min_expansion <= %i AND max_expansion >= %i", zonename, version, latest_expansion, latest_expansion); auto results = QueryDatabase(query); if (!results.Success()) { @@ -481,18 +482,19 @@ bool ZoneDatabase::SetTrapData(Trap* trap, bool repopnow) { uint32 dbid = trap->db_id; std::string query; + auto latest_expansion = EQEmu::expansions::ConvertExpansionBitToExpansion(RuleI(World, ExpansionSettings)); if (trap->group > 0) { query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, " "maxzdiff, radius, chance, message, respawn_time, respawn_var, level, " - "triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND `group`=%d AND id != %d AND %i & expansions = expansions ORDER BY RAND() LIMIT 1", zone->GetShortName(), trap->group, dbid, RuleI(World, ExpansionSettings)); + "triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND `group`=%d AND id != %d AND min_expansion <= %i AND max_expansion >= %i ORDER BY RAND() LIMIT 1", zone->GetShortName(), trap->group, dbid, latest_expansion, latest_expansion); } else { // We could just use the existing data here, but querying the DB is not expensive, and allows content developers to change traps without rebooting. query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, " "maxzdiff, radius, chance, message, respawn_time, respawn_var, level, " - "triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND id = %d AND %i & expansions = expansions", zone->GetShortName(), dbid, RuleI(World, ExpansionSettings)); + "triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND id = %d AND min_expansion <= %i AND max_expansion >= %i", zone->GetShortName(), dbid, latest_expansion, latest_expansion); } auto results = QueryDatabase(query);