eqemu-server/zone/spawngroup.cpp
Knightly 7ab909ee47 Standardize Licensing
- License was intended to be GPLv3 per earlier commit of GPLv3 LICENSE FILE
- This is confirmed by the inclusion of libraries that are incompatible with GPLv2
- This is also confirmed by KLS and the agreement of KLS's predecessors
- Added GPLv3 license headers to the compilable source files
- Removed Folly licensing in strings.h since the string functions do not match the Folly functions and are standard functions - this must have been left over from previous implementations
- Removed individual contributor license headers since the project has been under the "developer" mantle for many years
- Removed comments on files that were previously automatically generated since they've been manually modified multiple times and there are no automatic scripts referencing them (removed in 2023)
2026-04-01 17:09:57 -07:00

403 lines
8.5 KiB
C++

/* EQEmu: EQEmulator
Copyright (C) 2001-2026 EQEmu Development Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "spawngroup.h"
#include "common/repositories/criteria/content_filter_criteria.h"
#include "common/types.h"
#include "zone/entity.h"
#include "zone/zone.h"
#include "zone/zonedb.h"
#include "fmt/format.h"
extern EntityList entity_list;
extern Zone *zone;
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(
uint32 in_id,
char *name,
int in_group_spawn_limit,
float dist,
float maxx,
float minx,
float maxy,
float miny,
int delay_in,
int despawn_in,
uint32 despawn_timer_in,
int min_delay_in,
bool wp_spawns_in
)
{
id = in_id;
strn0cpy(name_, name, 120);
group_spawn_limit = in_group_spawn_limit;
roambox[0] = maxx;
roambox[1] = minx;
roambox[2] = maxy;
roambox[3] = miny;
roamdist = dist;
min_delay = min_delay_in;
delay = delay_in;
despawn = despawn_in;
despawn_timer = despawn_timer_in;
wp_spawns = wp_spawns_in;
}
uint32 SpawnGroup::GetNPCType(uint16 in_filter)
{
int npcType = 0;
int totalchance = 0;
if (!entity_list.LimitCheckGroup(id, group_spawn_limit)) {
return (0);
}
std::list<SpawnEntry *> possible;
for (auto &it : list_) {
auto se = it.get();
if (!entity_list.LimitCheckType(se->NPCType, se->npc_spawn_limit)) {
continue;
}
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);
}
if (totalchance == 0) {
return 0;
}
int32 roll = 0;
roll = zone->random.Int(0, totalchance - 1);
for (auto se : possible) {
if (roll < se->chance) {
npcType = se->NPCType;
break;
}
else {
roll -= se->chance;
}
}
return npcType;
}
void SpawnGroup::AddSpawnEntry(std::unique_ptr<SpawnEntry> &newEntry)
{
list_.push_back(std::move(newEntry));
}
SpawnGroup::~SpawnGroup()
{
list_.clear();
}
SpawnGroupList::~SpawnGroupList()
{
m_spawn_groups.clear();
}
void SpawnGroupList::AddSpawnGroup(std::unique_ptr<SpawnGroup> &new_group)
{
if (new_group == nullptr) {
return;
}
m_spawn_groups[new_group->id] = std::move(new_group);
}
SpawnGroup *SpawnGroupList::GetSpawnGroup(uint32 in_id)
{
if (m_spawn_groups.count(in_id) != 1) {
return nullptr;
}
return (m_spawn_groups[in_id].get());
}
void SpawnGroupList::ReloadSpawnGroups()
{
ClearSpawnGroups();
content_db.LoadSpawnGroups(zone->GetShortName(), zone->GetInstanceVersion(), &zone->spawn_group_list);
}
void SpawnGroupList::ClearSpawnGroups()
{
m_spawn_groups.clear();
}
bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnGroupList *spawn_group_list)
{
std::string query = fmt::format(
SQL(
SELECT
DISTINCT(spawngroupID),
spawngroup.name,
spawngroup.spawn_limit,
spawngroup.dist,
spawngroup.max_x,
spawngroup.min_x,
spawngroup.max_y,
spawngroup.min_y,
spawngroup.delay,
spawngroup.despawn,
spawngroup.despawn_timer,
spawngroup.mindelay,
spawngroup.wp_spawns
FROM
spawn2,
spawngroup
WHERE
spawn2.spawngroupID = spawngroup.ID
AND
(spawn2.version = {} OR version = -1)
AND zone = '{}'
{}
),
version,
zone_name,
ContentFilterCriteria::apply()
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_group = std::make_unique<SpawnGroup>(
Strings::ToInt(row[0]),
row[1],
Strings::ToInt(row[2]),
Strings::ToFloat(row[3]),
Strings::ToFloat(row[4]),
Strings::ToFloat(row[5]),
Strings::ToFloat(row[6]),
Strings::ToFloat(row[7]),
Strings::ToInt(row[8]),
Strings::ToInt(row[9]),
Strings::ToInt(row[10]),
Strings::ToInt(row[11]),
Strings::ToInt(row[12])
);
spawn_group_list->AddSpawnGroup(new_spawn_group);
}
LogInfo("Loaded [{}] spawn group(s)", Strings::Commify(results.RowCount()));
query = fmt::format(
SQL(
SELECT
DISTINCT
spawnentry.spawngroupID,
npcid,
chance,
condition_value_filter,
npc_types.spawn_limit
AS sl,
min_time,
max_time
FROM
spawnentry,
spawn2,
npc_types
WHERE
spawnentry.npcID = npc_types.id
AND
spawnentry.spawngroupID = spawn2.spawngroupID
AND
zone = '{}'
{}
),
zone_name,
ContentFilterCriteria::apply("spawnentry")
);
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_entry = std::make_unique<SpawnEntry>(
Strings::ToInt(row[1]),
Strings::ToInt(row[2]),
Strings::ToInt(row[3]),
(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]));
if (!spawn_group) {
continue;
}
spawn_group->AddSpawnEntry(new_spawn_entry);
}
LogInfo("Loaded [{}] spawn entries", Strings::Commify(results.RowCount()));
return true;
}
/**
* @param spawn_group_id
* @param spawn_group_list
* @return
*/
bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn_group_list)
{
std::string query = fmt::format(
SQL(
SELECT DISTINCT
(spawngroup.id),
spawngroup.name,
spawngroup.spawn_limit,
spawngroup.dist,
spawngroup.max_x,
spawngroup.min_x,
spawngroup.max_y,
spawngroup.min_y,
spawngroup.delay,
spawngroup.despawn,
spawngroup.despawn_timer,
spawngroup.mindelay,
spawngroup.wp_spawns
FROM
spawngroup
WHERE
spawngroup.ID = '{}'
),
spawn_group_id
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
LogSpawnsDetail(
"Loading spawn_group spawn_group_id [{}] name [{}] spawn_limit [{}] dist [{}]",
row[0],
row[1],
row[2],
row[3]
);
auto new_spawn_group = std::make_unique<SpawnGroup>(
Strings::ToInt(row[0]),
row[1],
Strings::ToInt(row[2]),
Strings::ToFloat(row[3]),
Strings::ToFloat(row[4]),
Strings::ToFloat(row[5]),
Strings::ToFloat(row[6]),
Strings::ToFloat(row[7]),
Strings::ToInt(row[8]),
Strings::ToInt(row[9]),
Strings::ToInt(row[10]),
Strings::ToInt(row[11]),
Strings::ToInt(row[12])
);
spawn_group_list->AddSpawnGroup(new_spawn_group);
}
query = fmt::format(
SQL(
SELECT DISTINCT
(spawnentry.spawngroupID),
spawnentry.npcid,
spawnentry.chance,
spawnentry.condition_value_filter,
spawngroup.spawn_limit,
spawnentry.min_time,
spawnentry.max_time
FROM
spawnentry,
spawngroup
WHERE
spawnentry.spawngroupID = '{}'
AND spawngroup.spawn_limit = '0'
ORDER BY chance),
spawn_group_id
);
results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
for (auto row = results.begin(); row != results.end(); ++row) {
auto new_spawn_entry = std::make_unique<SpawnEntry>(
Strings::ToInt(row[1]),
Strings::ToInt(row[2]),
Strings::ToInt(row[3]),
(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 [{}] min_time [{}] max_time [{}] ",
row[0],
row[1],
row[2],
row[3],
row[4],
row[5],
row[6]
);
SpawnGroup *spawn_group = spawn_group_list->GetSpawnGroup(Strings::ToInt(row[0]));
if (!spawn_group) {
continue;
}
spawn_group->AddSpawnEntry(new_spawn_entry);
}
return true;
}