Added support to create duplicated zones of public zones (non city zone). Additionally spawn locations can be limited to the primary public zone and not replicated (for epics).
This commit is contained in:
parent
7f138c5bef
commit
42173ceef2
@ -793,7 +793,7 @@ void Entity::GetWeaponDamage(Item* item, int32* low_damage, int32* high_damage)
|
|||||||
|
|
||||||
Skill* masterySkill = ((Player*)this)->skill_list.GetSkill(item->generic_info.skill_req2);
|
Skill* masterySkill = ((Player*)this)->skill_list.GetSkill(item->generic_info.skill_req2);
|
||||||
if(masterySkill) {
|
if(masterySkill) {
|
||||||
LogWrite(PLAYER__ERROR, 0, "Player", "Item has skill %s %u requirement", masterySkill->name.data.c_str(), item->generic_info.skill_req2);
|
LogWrite(PLAYER__DEBUG, 0, "Player", "Item %s has skill %s %u requirement", item->name.c_str(), masterySkill->name.data.c_str(), item->generic_info.skill_req2);
|
||||||
int16 skillID = master_item_list.GetItemStatIDByName(masterySkill->name.data);
|
int16 skillID = master_item_list.GetItemStatIDByName(masterySkill->name.data);
|
||||||
int32 skill_chance = (int32)CalculateSkillWithBonus((char*)masterySkill->name.data.c_str(), master_item_list.GetItemStatIDByName(masterySkill->name.data), false);
|
int32 skill_chance = (int32)CalculateSkillWithBonus((char*)masterySkill->name.data.c_str(), master_item_list.GetItemStatIDByName(masterySkill->name.data), false);
|
||||||
if(skill_chance >= min_level_skill && skill_chance < rec_level_skill) {
|
if(skill_chance >= min_level_skill && skill_chance < rec_level_skill) {
|
||||||
|
@ -1623,6 +1623,7 @@ void LuaInterface::DeletePendingSpells(bool all) {
|
|||||||
for (del_itr = tmp_deletes.begin(); del_itr != tmp_deletes.end(); del_itr++) {
|
for (del_itr = tmp_deletes.begin(); del_itr != tmp_deletes.end(); del_itr++) {
|
||||||
spell = *del_itr;
|
spell = *del_itr;
|
||||||
|
|
||||||
|
spells_pending_delete.erase(spell);
|
||||||
SetLuaUserDataStale(spell);
|
SetLuaUserDataStale(spell);
|
||||||
RemoveCurrentSpell(spell->state, spell, false);
|
RemoveCurrentSpell(spell->state, spell, false);
|
||||||
|
|
||||||
@ -1639,9 +1640,10 @@ void LuaInterface::DeletePendingSpells(bool all) {
|
|||||||
if(!targetZone)
|
if(!targetZone)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
spellDeleted = true;
|
if(!spellDeleted)
|
||||||
|
targetZone->GetSpellProcess()->DeleteActiveSpell(spell, true);
|
||||||
|
|
||||||
targetZone->GetSpellProcess()->DeleteActiveSpell(spell, true);
|
spellDeleted = true;
|
||||||
}
|
}
|
||||||
spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
|
spell->MSpellTargets.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
@ -1650,8 +1652,6 @@ void LuaInterface::DeletePendingSpells(bool all) {
|
|||||||
spell->zone->GetSpellProcess()->DeleteActiveSpell(spell, true);
|
spell->zone->GetSpellProcess()->DeleteActiveSpell(spell, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spells_pending_delete.erase(spell);
|
|
||||||
|
|
||||||
if (spell->spell->IsCopiedSpell())
|
if (spell->spell->IsCopiedSpell())
|
||||||
{
|
{
|
||||||
@ -2694,7 +2694,7 @@ bool LuaInterface::RunRegionScript(string script_name, const char* function_name
|
|||||||
void LuaInterface::AddPendingSpellDelete(LuaSpell* spell) {
|
void LuaInterface::AddPendingSpellDelete(LuaSpell* spell) {
|
||||||
MSpellDelete.lock();
|
MSpellDelete.lock();
|
||||||
if ( spells_pending_delete.count(spell) == 0 )
|
if ( spells_pending_delete.count(spell) == 0 )
|
||||||
spells_pending_delete[spell] = Timer::GetCurrentTime2() + 10000;
|
spells_pending_delete[spell] = Timer::GetCurrentTime2() + 100;
|
||||||
MSpellDelete.unlock();
|
MSpellDelete.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +362,8 @@ void RuleManager::Init()
|
|||||||
RULE_INIT(R_Zone, UseMapUnderworldCoords, "1"); // use maps lowest Y coordinate to establish underworld markers
|
RULE_INIT(R_Zone, UseMapUnderworldCoords, "1"); // use maps lowest Y coordinate to establish underworld markers
|
||||||
RULE_INIT(R_Zone, MapUnderworldCoordOffset, "-200.0"); // adds (or in the case of negative value subtracts) so that the underworld marker is lower when map is using its lowest Y coordinate
|
RULE_INIT(R_Zone, MapUnderworldCoordOffset, "-200.0"); // adds (or in the case of negative value subtracts) so that the underworld marker is lower when map is using its lowest Y coordinate
|
||||||
|
|
||||||
|
RULE_INIT(R_Zone, SharedZoneMaxPlayers, "30"); // max players in a shared zone (non instanced) before splitting to another zone, city_zone flagged are exempt
|
||||||
|
|
||||||
RULE_INIT(R_Loot, LootRadius, "5.0");
|
RULE_INIT(R_Loot, LootRadius, "5.0");
|
||||||
RULE_INIT(R_Loot, AutoDisarmChest, "1");
|
RULE_INIT(R_Loot, AutoDisarmChest, "1");
|
||||||
RULE_INIT(R_Loot, ChestTriggerRadiusGroup, "10.0"); // radius at which chest will trigger against group members
|
RULE_INIT(R_Loot, ChestTriggerRadiusGroup, "10.0"); // radius at which chest will trigger against group members
|
||||||
|
@ -208,7 +208,8 @@ enum RuleType {
|
|||||||
HOTime,
|
HOTime,
|
||||||
UseMapUnderworldCoords,
|
UseMapUnderworldCoords,
|
||||||
MapUnderworldCoordOffset,
|
MapUnderworldCoordOffset,
|
||||||
|
SharedZoneMaxPlayers,
|
||||||
|
|
||||||
/* LOOT */
|
/* LOOT */
|
||||||
LootRadius,
|
LootRadius,
|
||||||
AutoDisarmChest, // if enabled disarm only works if you right click and disarm, clicking and opening chest won't attempt auto disarm
|
AutoDisarmChest, // if enabled disarm only works if you right click and disarm, clicking and opening chest won't attempt auto disarm
|
||||||
|
@ -150,6 +150,7 @@ Spawn::Spawn(){
|
|||||||
reset_movement = false;
|
reset_movement = false;
|
||||||
respawn_offset_low = 0;
|
respawn_offset_low = 0;
|
||||||
respawn_offset_high = 0;
|
respawn_offset_high = 0;
|
||||||
|
duplicated_spawn = true;
|
||||||
ResetKnockedBack();
|
ResetKnockedBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,7 +905,8 @@ public:
|
|||||||
void SetRespawnOffsetLow(sint32 time);
|
void SetRespawnOffsetLow(sint32 time);
|
||||||
sint32 GetRespawnOffsetHigh();
|
sint32 GetRespawnOffsetHigh();
|
||||||
void SetRespawnOffsetHigh(sint32 time);
|
void SetRespawnOffsetHigh(sint32 time);
|
||||||
|
bool DuplicatedSpawn() { return duplicated_spawn; }
|
||||||
|
void SetDuplicateSpawn(bool val) { duplicated_spawn = val; }
|
||||||
int32 GetExpireTime() { return expire_time; }
|
int32 GetExpireTime() { return expire_time; }
|
||||||
void SetExpireTime(int32 new_expire_time) { expire_time = new_expire_time; }
|
void SetExpireTime(int32 new_expire_time) { expire_time = new_expire_time; }
|
||||||
int32 GetExpireOffsetTime();
|
int32 GetExpireOffsetTime();
|
||||||
@ -1505,6 +1506,7 @@ private:
|
|||||||
int32 respawn;
|
int32 respawn;
|
||||||
sint32 respawn_offset_low;
|
sint32 respawn_offset_low;
|
||||||
sint32 respawn_offset_high;
|
sint32 respawn_offset_high;
|
||||||
|
bool duplicated_spawn;
|
||||||
int32 expire_time;
|
int32 expire_time;
|
||||||
int32 expire_offset;
|
int32 expire_offset;
|
||||||
float x_offset;
|
float x_offset;
|
||||||
|
@ -48,6 +48,7 @@ struct SpawnEntry{
|
|||||||
int32 respawn;
|
int32 respawn;
|
||||||
sint32 respawn_offset_low;
|
sint32 respawn_offset_low;
|
||||||
sint32 respawn_offset_high;
|
sint32 respawn_offset_high;
|
||||||
|
bool duplicated_spawn;
|
||||||
int32 expire_time;
|
int32 expire_time;
|
||||||
int32 expire_offset;
|
int32 expire_offset;
|
||||||
//devn00b: added spawn location overrides, added these to accomodate.
|
//devn00b: added spawn location overrides, added these to accomodate.
|
||||||
|
@ -23,9 +23,11 @@ along with EQ2Emu. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "../net.h"
|
#include "../net.h"
|
||||||
#include "../PlayerGroups.h"
|
#include "../PlayerGroups.h"
|
||||||
#include "HTTPSClientPool.h"
|
#include "HTTPSClientPool.h"
|
||||||
|
#include "../Rules/Rules.h"
|
||||||
|
|
||||||
extern NetConnection net;
|
extern NetConnection net;
|
||||||
extern HTTPSClientPool peer_https_pool;
|
extern HTTPSClientPool peer_https_pool;
|
||||||
|
extern RuleManager rule_manager;
|
||||||
|
|
||||||
// HealthCheck method definitions
|
// HealthCheck method definitions
|
||||||
void HealthCheck::updateStatus(HealthStatus newStatus) {
|
void HealthCheck::updateStatus(HealthStatus newStatus) {
|
||||||
@ -214,8 +216,11 @@ std::string PeerManager::getZonePeerId(const std::string& inc_zone_name, int32 i
|
|||||||
else if (!instance_zone && inc_zone_name.length() > 0 && strncasecmp(zone_name.c_str(), inc_zone_name.c_str(), inc_zone_name.length()) == 0) {
|
else if (!instance_zone && inc_zone_name.length() > 0 && strncasecmp(zone_name.c_str(), inc_zone_name.c_str(), inc_zone_name.length()) == 0) {
|
||||||
match = true;
|
match = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!instance_zone && num_players >= 30 && !city_zone) {
|
int32 max_players = rule_manager.GetZoneRule(zone_id, R_Zone, SharedZoneMaxPlayers)->GetInt32();
|
||||||
|
if(max_players < 1) // default of 30
|
||||||
|
max_players = 30;
|
||||||
|
if(!instance_zone && num_players >= max_players && !city_zone) {
|
||||||
match = false;
|
match = false;
|
||||||
setZonePeerData(opt_details, peerId, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, zone_file_name, zone_name, zone_id, instance_id,
|
setZonePeerData(opt_details, peerId, peer->worldAddr, peer->internalWorldAddr, peer->worldPort, peer->webAddr, peer->webPort, zone_file_name, zone_name, zone_id, instance_id,
|
||||||
safe_x, safe_y, safe_z, safe_heading, lock_state, min_status, min_level, max_level, min_version, default_lockout_time, default_reenter_time, instance_type, num_players, city_zone);
|
safe_x, safe_y, safe_z, safe_heading, lock_state, min_status, min_level, max_level, min_version, default_lockout_time, default_reenter_time, instance_type, num_players, city_zone);
|
||||||
@ -239,6 +244,50 @@ std::string PeerManager::getZonePeerId(const std::string& inc_zone_name, int32 i
|
|||||||
return fullZoneId;
|
return fullZoneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 PeerManager::getZoneHighestDuplicateId(const std::string& inc_zone_name, int32 inc_zone_id) {
|
||||||
|
int32 highestID = 0;
|
||||||
|
bool matched_zone = false;
|
||||||
|
for (auto& [peerId, peer] : peers) {
|
||||||
|
if (peer->healthCheck.status != HealthStatus::OK)
|
||||||
|
continue;
|
||||||
|
try {
|
||||||
|
std::lock_guard<std::mutex> lock(peer->dataMutex);
|
||||||
|
for (const auto& zone : peer->zone_tree->get_child("Zones")) {
|
||||||
|
// Access each field within the current zone
|
||||||
|
std::string zone_name = zone.second.get<std::string>("zone_name");
|
||||||
|
bool instance_zone = zone.second.get<std::string>("instance_zone") == "true";
|
||||||
|
std::string zone_file_name = zone.second.get<std::string>("zone_file_name");
|
||||||
|
int32 zone_id = zone.second.get<int32>("zone_id");
|
||||||
|
int32 instance_id = zone.second.get<int32>("instance_id");
|
||||||
|
int32 duplicate_id = zone.second.get<int32>("duplicated_id");
|
||||||
|
|
||||||
|
bool match = false;
|
||||||
|
if (!instance_zone && inc_zone_id > 0 && zone_id == inc_zone_id) {
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
else if (!instance_zone && inc_zone_name.length() > 0 && strncasecmp(zone_name.c_str(), inc_zone_name.c_str(), inc_zone_name.length()) == 0) {
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
matched_zone = true;
|
||||||
|
if(duplicate_id > highestID)
|
||||||
|
highestID = duplicate_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
LogWrite(PEERING__ERROR, 0, "Peering", "%s: Error Parsing Zones for %s:%u", __FUNCTION__, peer->webAddr.c_str(), peer->webPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(matched_zone) {
|
||||||
|
highestID++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return highestID;
|
||||||
|
}
|
||||||
|
|
||||||
void PeerManager::handlePrimaryConflict(const std::string& reconnectingPeerId) {
|
void PeerManager::handlePrimaryConflict(const std::string& reconnectingPeerId) {
|
||||||
// Compare IDs or priorities to decide on the primary role
|
// Compare IDs or priorities to decide on the primary role
|
||||||
auto currentPrimary = getCurrentPrimary();
|
auto currentPrimary = getCurrentPrimary();
|
||||||
|
@ -182,6 +182,7 @@ public:
|
|||||||
void SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0);
|
void SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0);
|
||||||
void sendZonePeerList(Client* client);
|
void sendZonePeerList(Client* client);
|
||||||
std::string getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details = nullptr, bool only_always_loaded = false);
|
std::string getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details = nullptr, bool only_always_loaded = false);
|
||||||
|
int32 getZoneHighestDuplicateId(const std::string& inc_zone_name, int32 inc_zone_id);
|
||||||
void setZonePeerData(ZoneChangeDetails* opt_details);
|
void setZonePeerData(ZoneChangeDetails* opt_details);
|
||||||
void setPrimary(const std::string& id);
|
void setPrimary(const std::string& id);
|
||||||
bool hasPrimary();
|
bool hasPrimary();
|
||||||
|
@ -504,6 +504,7 @@ void ZoneList::PopulateZoneList(boost::property_tree::ptree& pt) {
|
|||||||
zone_pt.put("instance_type", static_cast<int8>(tmp->GetInstanceType()));
|
zone_pt.put("instance_type", static_cast<int8>(tmp->GetInstanceType()));
|
||||||
zone_pt.put("always_loaded", tmp->AlwaysLoaded());
|
zone_pt.put("always_loaded", tmp->AlwaysLoaded());
|
||||||
zone_pt.put("duplicated_zone", tmp->DuplicatedZone());
|
zone_pt.put("duplicated_zone", tmp->DuplicatedZone());
|
||||||
|
zone_pt.put("duplicated_id", tmp->DuplicatedID());
|
||||||
|
|
||||||
maintree.push_back(std::make_pair("", zone_pt));
|
maintree.push_back(std::make_pair("", zone_pt));
|
||||||
}
|
}
|
||||||
@ -629,6 +630,7 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
|
|||||||
int32 zoneId = 0;
|
int32 zoneId = 0;
|
||||||
std::string zoneName("");
|
std::string zoneName("");
|
||||||
bool alwaysLoaded = false, duplicatedZone = false;
|
bool alwaysLoaded = false, duplicatedZone = false;
|
||||||
|
int32 duplicatedID = 0;
|
||||||
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
|
int32 minLevel = 0, maxLevel = 0, avgLevel = 0, firstLevel = 0;
|
||||||
if (auto inst_id = json_tree.get_optional<int32>("instance_id")) {
|
if (auto inst_id = json_tree.get_optional<int32>("instance_id")) {
|
||||||
instanceId = inst_id.get();
|
instanceId = inst_id.get();
|
||||||
@ -650,6 +652,10 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
|
|||||||
duplicatedZone = duplicated_zone.get();
|
duplicatedZone = duplicated_zone.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto duplicated_id = json_tree.get_optional<int32>("duplicated_id")) {
|
||||||
|
duplicatedID = duplicated_id.get();
|
||||||
|
}
|
||||||
|
|
||||||
if (auto level = json_tree.get_optional<int32>("min_level")) {
|
if (auto level = json_tree.get_optional<int32>("min_level")) {
|
||||||
minLevel = level.get();
|
minLevel = level.get();
|
||||||
}
|
}
|
||||||
@ -672,7 +678,16 @@ void World::Web_worldhandle_startzone(const http::request<http::string_body>& re
|
|||||||
if (!instanceId) {
|
if (!instanceId) {
|
||||||
if ((zone_list.GetZone(&details, zoneId, zoneName, true, false, false, false, false, alwaysLoaded, false, duplicatedZone))) {
|
if ((zone_list.GetZone(&details, zoneId, zoneName, true, false, false, false, false, alwaysLoaded, false, duplicatedZone))) {
|
||||||
if(details.zonePtr) {
|
if(details.zonePtr) {
|
||||||
((ZoneServer*)details.zonePtr)->SetDuplicatedZone(duplicatedZone);
|
ZoneServer* tmpZone = ((ZoneServer*)details.zonePtr);
|
||||||
|
tmpZone->SetDuplicatedZone(duplicatedZone);
|
||||||
|
tmpZone->SetDuplicatedID(duplicatedID);
|
||||||
|
if(duplicatedZone) {
|
||||||
|
std::string desc = "";
|
||||||
|
if(tmpZone->GetZoneDescription())
|
||||||
|
desc = std::string(tmpZone->GetZoneDescription());
|
||||||
|
desc += " " + std::to_string(duplicatedID);
|
||||||
|
tmpZone->SetZoneDescription((char*)desc.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
success = 1;
|
success = 1;
|
||||||
}
|
}
|
||||||
|
@ -699,8 +699,12 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
|
|||||||
if(!check_instances && tmp->IsInstanceZone())
|
if(!check_instances && tmp->IsInstanceZone())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
int32 max_players = rule_manager.GetZoneRule(tmp->GetZoneID(), R_Zone, SharedZoneMaxPlayers)->GetInt32();
|
||||||
|
if(max_players < 1) // default of 30
|
||||||
|
max_players = 30;
|
||||||
|
|
||||||
if(!tmp->isZoneShuttingDown() && ((opt_zone_id > 0 && tmp->GetZoneID() == opt_zone_id) || (opt_zone_name.length() > 0 && strncasecmp(tmp->GetZoneName(), opt_zone_name.c_str(), opt_zone_name.length())==0))){
|
if(!tmp->isZoneShuttingDown() && ((opt_zone_id > 0 && tmp->GetZoneID() == opt_zone_id) || (opt_zone_name.length() > 0 && strncasecmp(tmp->GetZoneName(), opt_zone_name.c_str(), opt_zone_name.length())==0))){
|
||||||
if(tmp->NumPlayers() < 30 || tmp->IsCityZone()) {
|
if(tmp->NumPlayers() < max_players || tmp->IsCityZone()) {
|
||||||
ret = tmp;
|
ret = tmp;
|
||||||
if(increment_zone) {
|
if(increment_zone) {
|
||||||
ret->IncrementIncomingClients();
|
ret->IncrementIncomingClients();
|
||||||
@ -719,8 +723,10 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
|
|||||||
if(!ret && check_peers) {
|
if(!ret && check_peers) {
|
||||||
std::string peerId = peer_manager.getZonePeerId(opt_zone_name, opt_zone_id, 0, zone_details, only_always_loaded);
|
std::string peerId = peer_manager.getZonePeerId(opt_zone_name, opt_zone_id, 0, zone_details, only_always_loaded);
|
||||||
if(peerId.size() > 0) {
|
if(peerId.size() > 0) {
|
||||||
|
int32 max_players = rule_manager.GetZoneRule(zone_details->zoneId, R_Zone, SharedZoneMaxPlayers)->GetInt32();
|
||||||
if(zone_details->instanceType == 0 && zone_details->numPlayers >= 30 && !zone_details->isCityZone) {
|
if(max_players < 1) // default of 30
|
||||||
|
max_players = 30;
|
||||||
|
if(zone_details->instanceType == 0 && zone_details->numPlayers >= max_players && !zone_details->isCityZone) {
|
||||||
LogWrite(WORLD__WARNING, 0, "World", "Peer %s is providing zone %s for zone %s id %u, however the zone is full, omitting result.", peerId.c_str(), zone_details->zoneName.c_str(), opt_zone_name.c_str(), opt_zone_id);
|
LogWrite(WORLD__WARNING, 0, "World", "Peer %s is providing zone %s for zone %s id %u, however the zone is full, omitting result.", peerId.c_str(), zone_details->zoneName.c_str(), opt_zone_name.c_str(), opt_zone_id);
|
||||||
hadFullZone = true;
|
hadFullZone = true;
|
||||||
}
|
}
|
||||||
@ -750,6 +756,7 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
|
|||||||
root.put("zone_id", std::to_string(opt_zone_id));
|
root.put("zone_id", std::to_string(opt_zone_id));
|
||||||
root.put("always_loaded", only_always_loaded);
|
root.put("always_loaded", only_always_loaded);
|
||||||
root.put("duplicated_zone", hadFullZone);
|
root.put("duplicated_zone", hadFullZone);
|
||||||
|
root.put("duplicated_id", zone_list.GetHighestDuplicateID(opt_zone_name, opt_zone_id));
|
||||||
|
|
||||||
root.put("min_level", minLevel);
|
root.put("min_level", minLevel);
|
||||||
root.put("max_level", maxLevel);
|
root.put("max_level", maxLevel);
|
||||||
@ -772,6 +779,14 @@ bool ZoneList::GetZone(ZoneChangeDetails* zone_details, int32 opt_zone_id, std::
|
|||||||
tmp = new ZoneServer(opt_zone_name.c_str());
|
tmp = new ZoneServer(opt_zone_name.c_str());
|
||||||
database.LoadZoneInfo(tmp, minLevel, maxLevel, avgLevel, firstLevel);
|
database.LoadZoneInfo(tmp, minLevel, maxLevel, avgLevel, firstLevel);
|
||||||
tmp->SetDuplicatedZone(hadFullZone);
|
tmp->SetDuplicatedZone(hadFullZone);
|
||||||
|
if(hadFullZone) {
|
||||||
|
tmp->SetDuplicatedID(zone_list.GetHighestDuplicateID(opt_zone_name, opt_zone_id));
|
||||||
|
std::string desc = "";
|
||||||
|
if(tmp->GetZoneDescription())
|
||||||
|
desc = std::string(tmp->GetZoneDescription());
|
||||||
|
desc += " " + std::to_string(tmp->DuplicatedID());
|
||||||
|
tmp->SetZoneDescription((char*)desc.c_str());
|
||||||
|
}
|
||||||
tmp->Init();
|
tmp->Init();
|
||||||
tmp->SetAlwaysLoaded(only_always_loaded);
|
tmp->SetAlwaysLoaded(only_always_loaded);
|
||||||
}
|
}
|
||||||
@ -835,6 +850,8 @@ bool ZoneList::GetZoneByInstance(ZoneChangeDetails* zone_details, int32 instance
|
|||||||
root.put("zone_name", zonename);
|
root.put("zone_name", zonename);
|
||||||
root.put("zone_id", std::to_string(zone_id));
|
root.put("zone_id", std::to_string(zone_id));
|
||||||
root.put("always_loaded", false);
|
root.put("always_loaded", false);
|
||||||
|
root.put("duplicated_zone", false); // instances dont duplicate, only shared zones
|
||||||
|
root.put("duplicated_id", 0);
|
||||||
|
|
||||||
root.put("min_level", minLevel);
|
root.put("min_level", minLevel);
|
||||||
root.put("max_level", maxLevel);
|
root.put("max_level", maxLevel);
|
||||||
@ -1590,6 +1607,40 @@ void ZoneList::ReloadSpawns() {
|
|||||||
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32 ZoneList::GetHighestDuplicateID(const std::string& inc_zone_name, int32 inc_zone_id)
|
||||||
|
{
|
||||||
|
list<ZoneServer*>::iterator zone_iter;
|
||||||
|
ZoneServer* tmp = 0;
|
||||||
|
int32 highest_id = peer_manager.getZoneHighestDuplicateId(inc_zone_name, inc_zone_id);
|
||||||
|
MZoneList.readlock(__FUNCTION__, __LINE__);
|
||||||
|
bool match = false;
|
||||||
|
bool matched_peer = (highest_id>0);
|
||||||
|
for(zone_iter=zlist.begin(); zone_iter!=zlist.end(); zone_iter++)
|
||||||
|
{
|
||||||
|
tmp = *zone_iter;
|
||||||
|
|
||||||
|
if(tmp->IsInstanceZone())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(((inc_zone_id > 0 && tmp->GetZoneID() == inc_zone_id) || (inc_zone_name.length() > 0 && strncasecmp(tmp->GetZoneName(), inc_zone_name.c_str(), inc_zone_name.length())==0))){
|
||||||
|
if(tmp->DuplicatedID() > highest_id) {
|
||||||
|
highest_id = tmp->DuplicatedID();
|
||||||
|
matched_peer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MZoneList.releasereadlock(__FUNCTION__, __LINE__);
|
||||||
|
|
||||||
|
if(match && !matched_peer)
|
||||||
|
highest_id++;
|
||||||
|
|
||||||
|
return highest_id;
|
||||||
|
}
|
||||||
|
|
||||||
bool World::ReportBug(string data, char* player_name, int32 account_id, const char* spawn_name, int32 spawn_id, int32 zone_id){
|
bool World::ReportBug(string data, char* player_name, int32 account_id, const char* spawn_name, int32 spawn_id, int32 zone_id){
|
||||||
//loginserver
|
//loginserver
|
||||||
vector<string> list;
|
vector<string> list;
|
||||||
|
@ -511,7 +511,9 @@ class ZoneList {
|
|||||||
void ShutDownZones();
|
void ShutDownZones();
|
||||||
void ReloadMail();
|
void ReloadMail();
|
||||||
void ReloadSpawns();
|
void ReloadSpawns();
|
||||||
|
|
||||||
|
int32 GetHighestDuplicateID(const std::string& inc_zone_name, int32 inc_zone_id);
|
||||||
|
|
||||||
void WatchdogHeartbeat();
|
void WatchdogHeartbeat();
|
||||||
|
|
||||||
void SendTimeUpdate();
|
void SendTimeUpdate();
|
||||||
|
@ -3278,6 +3278,8 @@ void WorldDatabase::LoadSpecialZones(){
|
|||||||
if(zone) {
|
if(zone) {
|
||||||
LogWrite(ZONE__INFO, 0, "Zone", "Static zone %s will be spundown due to another peer taking over.", row[1]);
|
LogWrite(ZONE__INFO, 0, "Zone", "Static zone %s will be spundown due to another peer taking over.", row[1]);
|
||||||
zone->SetAlwaysLoaded(false);
|
zone->SetAlwaysLoaded(false);
|
||||||
|
zone->SetDuplicatedZone(true);
|
||||||
|
zone->SetDuplicatedID(zone_list.GetHighestDuplicateID(std::string(zone->GetZoneName()), zone->GetZoneID()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3465,25 +3467,26 @@ int32 WorldDatabase::ProcessSpawnLocations(ZoneServer* zone, const char* sql_que
|
|||||||
entry->respawn = atoul(row[11]);
|
entry->respawn = atoul(row[11]);
|
||||||
entry->respawn_offset_low = atoi(row[12]);
|
entry->respawn_offset_low = atoi(row[12]);
|
||||||
entry->respawn_offset_high = atoi(row[13]);
|
entry->respawn_offset_high = atoi(row[13]);
|
||||||
entry->expire_time = atoul(row[16]);
|
entry->duplicated_spawn = atoul(row[14]);
|
||||||
entry->expire_offset = atoul(row[17]);
|
entry->expire_time = atoul(row[17]);
|
||||||
|
entry->expire_offset = atoul(row[18]);
|
||||||
//devn00b add stat overrides. Just a slight increase in size. Used in ZoneServer::AddNPCSpawn.
|
//devn00b add stat overrides. Just a slight increase in size. Used in ZoneServer::AddNPCSpawn.
|
||||||
entry->lvl_override = atoul(row[21]);
|
entry->lvl_override = atoul(row[22]);
|
||||||
entry->hp_override = atoul(row[22]);
|
entry->hp_override = atoul(row[23]);
|
||||||
entry->mp_override = atoul(row[23]);
|
entry->mp_override = atoul(row[24]);
|
||||||
entry->str_override = atoul(row[24]);
|
entry->str_override = atoul(row[25]);
|
||||||
entry->sta_override = atoul(row[25]);
|
entry->sta_override = atoul(row[26]);
|
||||||
entry->wis_override = atoul(row[26]);
|
entry->wis_override = atoul(row[27]);
|
||||||
entry->int_override = atoul(row[27]);
|
entry->int_override = atoul(row[28]);
|
||||||
entry->agi_override = atoul(row[28]);
|
entry->agi_override = atoul(row[29]);
|
||||||
entry->heat_override = atoul(row[29]);
|
entry->heat_override = atoul(row[30]);
|
||||||
entry->cold_override = atoul(row[30]);
|
entry->cold_override = atoul(row[31]);
|
||||||
entry->magic_override = atoul(row[31]);
|
entry->magic_override = atoul(row[32]);
|
||||||
entry->mental_override = atoul(row[32]);
|
entry->mental_override = atoul(row[33]);
|
||||||
entry->divine_override = atoul(row[33]);
|
entry->divine_override = atoul(row[34]);
|
||||||
entry->disease_override = atoul(row[34]);
|
entry->disease_override = atoul(row[35]);
|
||||||
entry->poison_override = atoul(row[35]);
|
entry->poison_override = atoul(row[36]);
|
||||||
entry->difficulty_override = atoul(row[36]);
|
entry->difficulty_override = atoul(row[37]);
|
||||||
spawn_location->x = atof(row[2]);
|
spawn_location->x = atof(row[2]);
|
||||||
spawn_location->y = atof(row[3]);
|
spawn_location->y = atof(row[3]);
|
||||||
spawn_location->z = atof(row[4]);
|
spawn_location->z = atof(row[4]);
|
||||||
@ -3491,12 +3494,12 @@ int32 WorldDatabase::ProcessSpawnLocations(ZoneServer* zone, const char* sql_que
|
|||||||
spawn_location->y_offset = atof(row[6]);
|
spawn_location->y_offset = atof(row[6]);
|
||||||
spawn_location->z_offset = atof(row[7]);
|
spawn_location->z_offset = atof(row[7]);
|
||||||
spawn_location->heading = atof(row[8]);
|
spawn_location->heading = atof(row[8]);
|
||||||
spawn_location->pitch = atof(row[18]);
|
spawn_location->pitch = atof(row[19]);
|
||||||
spawn_location->roll = atof(row[19]);
|
spawn_location->roll = atof(row[20]);
|
||||||
spawn_location->conditional = atoi(row[20]);
|
spawn_location->conditional = atoi(row[21]);
|
||||||
spawn_location->total_percentage += entry->spawn_percentage;
|
spawn_location->total_percentage += entry->spawn_percentage;
|
||||||
spawn_location->grid_id = strtoul(row[14], NULL, 0);
|
spawn_location->grid_id = strtoul(row[15], NULL, 0);
|
||||||
spawn_location->placement_id = strtoul(row[15], NULL, 0);
|
spawn_location->placement_id = strtoul(row[16], NULL, 0);
|
||||||
spawn_location->AddSpawn(entry);
|
spawn_location->AddSpawn(entry);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -3535,21 +3538,21 @@ void WorldDatabase::LoadSpawns(ZoneServer* zone)
|
|||||||
LogWrite(SPAWN__TRACE, 0, "Spawn", "Enter LoadSpawns");
|
LogWrite(SPAWN__TRACE, 0, "Spawn", "Enter LoadSpawns");
|
||||||
|
|
||||||
if(zone->GetInstanceID() == 0) {
|
if(zone->GetInstanceID() == 0) {
|
||||||
npcs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_npcs sn where sn.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_NPC);
|
npcs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_npcs sn where sn.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_NPC);
|
||||||
objects = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_objects so where so.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_OBJECT);
|
objects = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_objects so where so.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_OBJECT);
|
||||||
widgets = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_widgets sw where sw.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_WIDGET);
|
widgets = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_widgets sw where sw.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_WIDGET);
|
||||||
signs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_signs ss where ss.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_SIGN);
|
signs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_signs ss where ss.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_SIGN);
|
||||||
ground_spawns = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_ground sg where sg.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_GROUNDSPAWN);
|
ground_spawns = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_ground sg where sg.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%u and slp.instance_id=%u ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_GROUNDSPAWN);
|
||||||
spawn_groups = LoadSpawnLocationGroups(zone);
|
spawn_groups = LoadSpawnLocationGroups(zone);
|
||||||
spawn_group_associations = LoadSpawnLocationGroupAssociations(zone);
|
spawn_group_associations = LoadSpawnLocationGroupAssociations(zone);
|
||||||
spawn_group_chances = LoadSpawnGroupChances(zone);
|
spawn_group_chances = LoadSpawnGroupChances(zone);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
npcs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_npcs sn where sn.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_NPC);
|
npcs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_npcs sn where sn.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_NPC);
|
||||||
objects = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_objects so where so.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_OBJECT);
|
objects = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_objects so where so.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_OBJECT);
|
||||||
widgets = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_widgets sw where sw.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_WIDGET);
|
widgets = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_widgets sw where sw.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_WIDGET);
|
||||||
signs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_signs ss where ss.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_SIGN);
|
signs = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_signs ss where ss.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_SIGN);
|
||||||
ground_spawns = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_ground sg where sg.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_GROUNDSPAWN);
|
ground_spawns = ProcessSpawnLocations(zone, "SELECT sln.id, sle.id, slp.x, slp.y, slp.z, slp.x_offset, slp.y_offset, slp.z_offset, slp.heading, sle.spawn_id, sle.spawnpercentage, slp.respawn, slp.respawn_offset_low, slp.respawn_offset_high, slp.duplicated_spawn, slp.grid_id, slp.id, slp.expire_timer, slp.expire_offset, slp.pitch, slp.roll, sle.condition, slp.lvl_override, slp.hp_override, slp.mp_override, slp.str_override, slp.sta_override, slp.wis_override, slp.int_override, slp.agi_override, slp.heat_override, slp.cold_override, slp.magic_override, slp.mental_override, slp.divine_override, slp.disease_override, slp.poison_override, difficulty_override FROM spawn_location_placement slp, spawn_location_name sln, spawn_location_entry sle, spawn_ground sg where sg.spawn_id = sle.spawn_id and sln.id = sle.spawn_location_id and sln.id = slp.spawn_location_id and slp.zone_id=%i and (slp.instance_id = 0 or slp.instance_id=%u) ORDER BY sln.id, sle.id", SPAWN_ENTRY_TYPE_GROUNDSPAWN);
|
||||||
spawn_groups = LoadSpawnLocationGroups(zone);
|
spawn_groups = LoadSpawnLocationGroups(zone);
|
||||||
spawn_group_associations = LoadSpawnLocationGroupAssociations(zone);
|
spawn_group_associations = LoadSpawnLocationGroupAssociations(zone);
|
||||||
spawn_group_chances = LoadSpawnGroupChances(zone);
|
spawn_group_chances = LoadSpawnGroupChances(zone);
|
||||||
|
@ -185,6 +185,7 @@ ZoneServer::ZoneServer(const char* name) {
|
|||||||
is_initialized = false;
|
is_initialized = false;
|
||||||
isInstance = false;
|
isInstance = false;
|
||||||
duplicated_zone = false;
|
duplicated_zone = false;
|
||||||
|
duplicated_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef map <int32, bool> ChangedSpawnMapType;
|
typedef map <int32, bool> ChangedSpawnMapType;
|
||||||
@ -2525,7 +2526,9 @@ Spawn* ZoneServer::ProcessSpawnLocation(SpawnLocation* spawnlocation, map<int32,
|
|||||||
{
|
{
|
||||||
if(spawnlocation->entities[i]->spawn_percentage == 0)
|
if(spawnlocation->entities[i]->spawn_percentage == 0)
|
||||||
continue;
|
continue;
|
||||||
|
if(DuplicatedZone() && !spawnlocation->entities[i]->duplicated_spawn) {
|
||||||
|
return nullptr; // dupe public/shared zone, we have turned off duplicating spawns for this location
|
||||||
|
}
|
||||||
|
|
||||||
int32 spawnTime = 1;
|
int32 spawnTime = 1;
|
||||||
|
|
||||||
@ -2994,6 +2997,7 @@ NPC* ZoneServer::AddNPCSpawn(SpawnLocation* spawnlocation, SpawnEntry* spawnentr
|
|||||||
npc->SetRespawnTime(spawnentry->respawn);
|
npc->SetRespawnTime(spawnentry->respawn);
|
||||||
npc->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
npc->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
||||||
npc->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
npc->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
||||||
|
npc->SetDuplicateSpawn(spawnentry->duplicated_spawn);
|
||||||
npc->SetExpireTime(spawnentry->expire_time);
|
npc->SetExpireTime(spawnentry->expire_time);
|
||||||
|
|
||||||
//devn00b add overrides for some spawns
|
//devn00b add overrides for some spawns
|
||||||
@ -3417,6 +3421,7 @@ Sign* ZoneServer::AddSignSpawn(SpawnLocation* spawnlocation, SpawnEntry* spawnen
|
|||||||
sign->SetRespawnTime(spawnentry->respawn);
|
sign->SetRespawnTime(spawnentry->respawn);
|
||||||
sign->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
sign->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
||||||
sign->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
sign->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
||||||
|
sign->SetDuplicateSpawn(spawnentry->duplicated_spawn);
|
||||||
sign->SetExpireTime(spawnentry->expire_time);
|
sign->SetExpireTime(spawnentry->expire_time);
|
||||||
if (spawnentry->expire_time > 0)
|
if (spawnentry->expire_time > 0)
|
||||||
AddSpawnExpireTimer(sign, spawnentry->expire_time, spawnentry->expire_offset);
|
AddSpawnExpireTimer(sign, spawnentry->expire_time, spawnentry->expire_offset);
|
||||||
@ -3448,6 +3453,7 @@ Widget* ZoneServer::AddWidgetSpawn(SpawnLocation* spawnlocation, SpawnEntry* spa
|
|||||||
widget->SetRespawnTime(spawnentry->respawn);
|
widget->SetRespawnTime(spawnentry->respawn);
|
||||||
widget->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
widget->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
||||||
widget->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
widget->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
||||||
|
widget->SetDuplicateSpawn(spawnentry->duplicated_spawn);
|
||||||
widget->SetExpireTime(spawnentry->expire_time);
|
widget->SetExpireTime(spawnentry->expire_time);
|
||||||
widget->SetSpawnOrigHeading(widget->GetHeading());
|
widget->SetSpawnOrigHeading(widget->GetHeading());
|
||||||
if (spawnentry->expire_time > 0)
|
if (spawnentry->expire_time > 0)
|
||||||
@ -3474,6 +3480,7 @@ Object* ZoneServer::AddObjectSpawn(SpawnLocation* spawnlocation, SpawnEntry* spa
|
|||||||
object->SetRespawnTime(spawnentry->respawn);
|
object->SetRespawnTime(spawnentry->respawn);
|
||||||
object->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
object->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
||||||
object->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
object->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
||||||
|
object->SetDuplicateSpawn(spawnentry->duplicated_spawn);
|
||||||
object->SetExpireTime(spawnentry->expire_time);
|
object->SetExpireTime(spawnentry->expire_time);
|
||||||
if (spawnentry->expire_time > 0)
|
if (spawnentry->expire_time > 0)
|
||||||
AddSpawnExpireTimer(object, spawnentry->expire_time, spawnentry->expire_offset);
|
AddSpawnExpireTimer(object, spawnentry->expire_time, spawnentry->expire_offset);
|
||||||
@ -3499,6 +3506,7 @@ GroundSpawn* ZoneServer::AddGroundSpawn(SpawnLocation* spawnlocation, SpawnEntry
|
|||||||
spawn->SetRespawnTime(spawnentry->respawn);
|
spawn->SetRespawnTime(spawnentry->respawn);
|
||||||
spawn->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
spawn->SetRespawnOffsetLow(spawnentry->respawn_offset_low);
|
||||||
spawn->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
spawn->SetRespawnOffsetHigh(spawnentry->respawn_offset_high);
|
||||||
|
spawn->SetDuplicateSpawn(spawnentry->duplicated_spawn);
|
||||||
spawn->SetExpireTime(spawnentry->expire_time);
|
spawn->SetExpireTime(spawnentry->expire_time);
|
||||||
|
|
||||||
if(spawn->GetRandomizeHeading()) {
|
if(spawn->GetRandomizeHeading()) {
|
||||||
@ -5280,7 +5288,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
|
|||||||
else if ( dead->IsObject ( ) )
|
else if ( dead->IsObject ( ) )
|
||||||
database.CreateInstanceSpawnRemoved(dead->GetSpawnLocationID(),SPAWN_ENTRY_TYPE_OBJECT, dead->GetRespawnTime(),dead->GetZone()->GetInstanceID());
|
database.CreateInstanceSpawnRemoved(dead->GetSpawnLocationID(),SPAWN_ENTRY_TYPE_OBJECT, dead->GetRespawnTime(),dead->GetZone()->GetInstanceID());
|
||||||
}
|
}
|
||||||
else if(!groupMemberAlive && dead->GetSpawnLocationID() > 0) {
|
else if(!groupMemberAlive && dead->GetSpawnLocationID() > 0 && !DuplicatedZone()) {
|
||||||
if(dead->IsNPC())
|
if(dead->IsNPC())
|
||||||
database.CreatePersistedRespawn(dead->GetSpawnLocationID(),SPAWN_ENTRY_TYPE_NPC,dead->GetRespawnTime(),GetZoneID());
|
database.CreatePersistedRespawn(dead->GetSpawnLocationID(),SPAWN_ENTRY_TYPE_NPC,dead->GetRespawnTime(),GetZoneID());
|
||||||
else if(dead->IsObject())
|
else if(dead->IsObject())
|
||||||
|
@ -532,9 +532,11 @@ public:
|
|||||||
inline bool IsCityZone() { return cityzone; }
|
inline bool IsCityZone() { return cityzone; }
|
||||||
inline bool AlwaysLoaded() { return always_loaded; }
|
inline bool AlwaysLoaded() { return always_loaded; }
|
||||||
inline bool DuplicatedZone() { return duplicated_zone; }
|
inline bool DuplicatedZone() { return duplicated_zone; }
|
||||||
|
inline int32 DuplicatedID() { return duplicated_id; }
|
||||||
void SetCityZone(bool val) { cityzone = val; }
|
void SetCityZone(bool val) { cityzone = val; }
|
||||||
void SetAlwaysLoaded(bool val) { always_loaded = val; }
|
void SetAlwaysLoaded(bool val) { always_loaded = val; }
|
||||||
void SetDuplicatedZone(bool val) { duplicated_zone = val; }
|
void SetDuplicatedZone(bool val) { duplicated_zone = val; }
|
||||||
|
void SetDuplicatedID(int32 id) { duplicated_id = id; }
|
||||||
int32 NumPlayers() { return pNumPlayers; }
|
int32 NumPlayers() { return pNumPlayers; }
|
||||||
void SetMinimumStatus(sint16 minStatus) { minimumStatus = minStatus; }
|
void SetMinimumStatus(sint16 minStatus) { minimumStatus = minStatus; }
|
||||||
sint16 GetMinimumStatus() { return minimumStatus; }
|
sint16 GetMinimumStatus() { return minimumStatus; }
|
||||||
@ -939,6 +941,7 @@ private:
|
|||||||
bool cityzone;
|
bool cityzone;
|
||||||
bool always_loaded;
|
bool always_loaded;
|
||||||
bool duplicated_zone;
|
bool duplicated_zone;
|
||||||
|
int32 duplicated_id;
|
||||||
bool isInstance;
|
bool isInstance;
|
||||||
|
|
||||||
std::atomic<int32> pNumPlayers;
|
std::atomic<int32> pNumPlayers;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user