mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-15 16:41:29 +00:00
Merge branch 'master' of https://github.com/EQEmu/Server into kick_events
This commit is contained in:
commit
69bad593cd
@ -326,14 +326,10 @@ IF(ZLIB_FOUND)
|
|||||||
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ELSE()
|
ELSE()
|
||||||
# NOTE: This processing chain is broken.
|
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
||||||
# Path "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" is added to ${SERVER_LIBS}..but, the current CMake process does not
|
SET(EQEMU_BUILD_ZLIB ON)
|
||||||
# generate the "${CMAKE_CURRENT_SOURCE_DIR}/build/lib/zlibng" and create the required "zconf.h" file. A path to
|
|
||||||
# a valid ZLIB package is required to trigger this process. "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng/zconf.h" is not
|
|
||||||
# valid due to the extension name change to "../zlibng/zconf.h.in" during the ZLIB project creation process.
|
|
||||||
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
|
||||||
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
|
||||||
MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(WIN32)
|
IF(WIN32)
|
||||||
|
|||||||
@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties.
|
|||||||
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
|
||||||
* CPPUnit - GLP StringUtilities - Apache
|
* CPPUnit - GLP StringUtilities - Apache
|
||||||
* LUA - MIT
|
* LUA - MIT
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
<a href="https://github.com/EQEmu/server/graphs/contributors">
|
||||||
|
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
|
||||||
|
</a>
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 8/6/2019 ==
|
||||||
|
Akkadius: Optimizations to movement updates to eliminate ghosting possibilities in larger zones
|
||||||
|
|
||||||
== 7/22/2019 ==
|
== 7/22/2019 ==
|
||||||
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
|
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
|
||||||
|
|
||||||
|
|||||||
@ -77,6 +77,10 @@ namespace EQEmu
|
|||||||
|
|
||||||
} // namespace invtype
|
} // namespace invtype
|
||||||
|
|
||||||
|
namespace DevTools {
|
||||||
|
const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
|
||||||
|
}
|
||||||
|
|
||||||
namespace popupresponse {
|
namespace popupresponse {
|
||||||
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
|
||||||
const int32 MOB_INFO_DISMISS = 2000000001;
|
const int32 MOB_INFO_DISMISS = 2000000001;
|
||||||
|
|||||||
@ -1116,7 +1116,10 @@ namespace SoF
|
|||||||
}
|
}
|
||||||
OUT(deity);
|
OUT(deity);
|
||||||
OUT(intoxication);
|
OUT(intoxication);
|
||||||
|
|
||||||
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
|
||||||
|
eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release
|
||||||
|
|
||||||
OUT(abilitySlotRefresh);
|
OUT(abilitySlotRefresh);
|
||||||
OUT(points); // Relocation Test
|
OUT(points); // Relocation Test
|
||||||
// OUT(unknown0166[4]);
|
// OUT(unknown0166[4]);
|
||||||
@ -1177,7 +1180,10 @@ namespace SoF
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OUT(unknown4184[128]);
|
// OUT(unknown4184[128]);
|
||||||
|
|
||||||
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
|
||||||
|
eq->mem_spells[9] = 0xFFFFFFFFU; // 10th slot is not valid in this release
|
||||||
|
|
||||||
// OUT(unknown04396[32]);
|
// OUT(unknown04396[32]);
|
||||||
OUT(platinum);
|
OUT(platinum);
|
||||||
OUT(gold);
|
OUT(gold);
|
||||||
|
|||||||
@ -328,7 +328,11 @@ namespace SoF
|
|||||||
|
|
||||||
const int SPELL_ID_MAX = 15999;
|
const int SPELL_ID_MAX = 15999;
|
||||||
const int SPELLBOOK_SIZE = 480;
|
const int SPELLBOOK_SIZE = 480;
|
||||||
|
// Be careful not to confuse these two..SoF disc release has a special requirement...
|
||||||
|
// - The number of available spell gems HAS NOT increased from 9 at this point
|
||||||
|
// - The profile allocation HAS increased to 10 at this point
|
||||||
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
|
||||||
|
const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration
|
||||||
|
|
||||||
const int LONG_BUFFS = 25;
|
const int LONG_BUFFS = 25;
|
||||||
const int SHORT_BUFFS = 15;
|
const int SHORT_BUFFS = 15;
|
||||||
|
|||||||
@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
|
|||||||
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
|
||||||
/*00160*/ uint32 deity; // deity
|
/*00160*/ uint32 deity; // deity
|
||||||
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
|
||||||
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each
|
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_PROFILE_SIZE]; // Refresh time (millis) - 4 Octets Each
|
||||||
/*00208*/ uint32 abilitySlotRefresh;
|
/*00208*/ uint32 abilitySlotRefresh;
|
||||||
/*00212*/ uint8 haircolor; // Player hair color
|
/*00212*/ uint8 haircolor; // Player hair color
|
||||||
/*00213*/ uint8 beardcolor; // Player beard color
|
/*00213*/ uint8 beardcolor; // Player beard color
|
||||||
@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets
|
|||||||
/*04173*/ uint8 unknown02264[147]; // was [139]
|
/*04173*/ uint8 unknown02264[147]; // was [139]
|
||||||
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
|
||||||
/*06232*/ uint8 unknown4184[128]; // was [136]
|
/*06232*/ uint8 unknown4184[128]; // was [136]
|
||||||
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized
|
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_PROFILE_SIZE]; // List of spells memorized
|
||||||
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
|
||||||
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
/*06464*/ uint32 platinum; // Platinum Pieces on player
|
||||||
/*06468*/ uint32 gold; // Gold Pieces on player
|
/*06468*/ uint32 gold; // Gold Pieces on player
|
||||||
@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LoadSpellSet_Struct {
|
struct LoadSpellSet_Struct {
|
||||||
uint32 spell[spells::SPELL_GEM_COUNT];
|
uint32 spell[spells::SPELL_GEM_PROFILE_SIZE];
|
||||||
uint32 unknown;
|
uint32 unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -379,6 +379,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this function does not delete the ServerPacket, so it must be handled at call site
|
||||||
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
void Database::GeneralQueryReceive(ServerPacket *pack) {
|
||||||
/*
|
/*
|
||||||
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
|
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
|
||||||
@ -393,7 +394,6 @@ void Database::GeneralQueryReceive(ServerPacket *pack) {
|
|||||||
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_delete(pack);
|
|
||||||
safe_delete_array(queryBuffer);
|
safe_delete_array(queryBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1587,22 +1587,24 @@ sub add_login_server_firewall_rules {
|
|||||||
print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n";
|
print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n";
|
||||||
print "\n";
|
print "\n";
|
||||||
print "[Install] Instructions \n";
|
print "[Install] Instructions \n";
|
||||||
print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n";
|
print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.json to your local server similar to the following:\n";
|
||||||
print "
|
print "
|
||||||
<loginserver1>
|
\"loginserver1\" : {
|
||||||
<host>login.eqemulator.net</host>
|
\"account\" : \"\",
|
||||||
<port>5998</port>
|
\"host\" : \"login.eqemulator.net\",
|
||||||
<account></account>
|
\"password\" : \"\",
|
||||||
<password></password>
|
\"port\" : \"5998\",
|
||||||
</loginserver1>
|
\"legacy\": \"1\"
|
||||||
<loginserver2>
|
},
|
||||||
<host>127.0.0.1</host>
|
\"loginserver2\" : {
|
||||||
<port>5998</port>
|
\"account\" : \"\",
|
||||||
<account></account>
|
\"host\" : \"192.168.197.129\",
|
||||||
<password></password>
|
\"password\" : \"\",
|
||||||
</loginserver2>
|
\"port\" : \"5998\"
|
||||||
|
},
|
||||||
|
\"localaddress\" : \"192.168.197.129\",
|
||||||
";
|
";
|
||||||
print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n";
|
print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 192.168.197.129) in the eqhosts.txt file\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -136,6 +136,7 @@ Client::Client(EQStreamInterface* ieqs)
|
|||||||
forget_timer(0),
|
forget_timer(0),
|
||||||
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
|
||||||
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
|
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
|
||||||
|
client_zone_wide_full_position_update_timer(5 * 60 * 1000),
|
||||||
tribute_timer(Tribute_duration),
|
tribute_timer(Tribute_duration),
|
||||||
proximity_timer(ClientProximity_interval),
|
proximity_timer(ClientProximity_interval),
|
||||||
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
|
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
|
||||||
@ -9121,3 +9122,16 @@ bool Client::GotoPlayer(std::string player_name)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec4 &Client::GetLastPositionBeforeBulkUpdate()
|
||||||
|
{
|
||||||
|
return last_position_before_bulk_update;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in_last_position_before_bulk_update
|
||||||
|
*/
|
||||||
|
void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update)
|
||||||
|
{
|
||||||
|
Client::last_position_before_bulk_update = in_last_position_before_bulk_update;
|
||||||
|
}
|
||||||
@ -1309,6 +1309,9 @@ public:
|
|||||||
|
|
||||||
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
|
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
|
||||||
|
|
||||||
|
void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
|
||||||
|
glm::vec4 &GetLastPositionBeforeBulkUpdate();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Mob;
|
friend class Mob;
|
||||||
void CalcItemBonuses(StatBonuses* newbon);
|
void CalcItemBonuses(StatBonuses* newbon);
|
||||||
@ -1517,6 +1520,7 @@ private:
|
|||||||
Timer forget_timer; // our 2 min everybody forgets you timer
|
Timer forget_timer; // our 2 min everybody forgets you timer
|
||||||
Timer autosave_timer;
|
Timer autosave_timer;
|
||||||
Timer client_scan_npc_aggro_timer;
|
Timer client_scan_npc_aggro_timer;
|
||||||
|
Timer client_zone_wide_full_position_update_timer;
|
||||||
Timer tribute_timer;
|
Timer tribute_timer;
|
||||||
|
|
||||||
Timer proximity_timer;
|
Timer proximity_timer;
|
||||||
@ -1539,6 +1543,7 @@ private:
|
|||||||
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
||||||
|
|
||||||
glm::vec3 m_Proximity;
|
glm::vec3 m_Proximity;
|
||||||
|
glm::vec4 last_position_before_bulk_update;
|
||||||
|
|
||||||
void BulkSendInventoryItems();
|
void BulkSendInventoryItems();
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "water_map.h"
|
#include "water_map.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
|
#include "mob_movement_manager.h"
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
@ -805,6 +806,8 @@ void Client::CompleteConnect()
|
|||||||
|
|
||||||
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
|
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
|
||||||
|
|
||||||
|
SetLastPositionBeforeBulkUpdate(GetPosition());
|
||||||
|
|
||||||
/* This sub event is for if a player logs in for the first time since entering world. */
|
/* This sub event is for if a player logs in for the first time since entering world. */
|
||||||
if (firstlogon == 1) {
|
if (firstlogon == 1) {
|
||||||
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
|
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
|
||||||
@ -1679,7 +1682,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
/**
|
/**
|
||||||
* DevTools Load Settings
|
* DevTools Load Settings
|
||||||
*/
|
*/
|
||||||
if (Admin() >= 200) {
|
if (Admin() >= EQEmu::DevTools::GM_ACCOUNT_STATUS_LEVEL) {
|
||||||
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
|
std::string dev_tools_window_key = StringFormat("%i-dev-tools-window-disabled", AccountID());
|
||||||
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
if (DataBucket::GetData(dev_tools_window_key) == "true") {
|
||||||
dev_tools_window_enabled = false;
|
dev_tools_window_enabled = false;
|
||||||
@ -4471,9 +4474,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
||||||
client_scan_npc_aggro_timer.Disable();
|
client_scan_npc_aggro_timer.Disable();
|
||||||
client_scan_npc_aggro_timer.Start(500);
|
client_scan_npc_aggro_timer.Start(500);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
|
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
|
||||||
client_scan_npc_aggro_timer.GetDuration());
|
client_scan_npc_aggro_timer.GetDuration());
|
||||||
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
|
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
|
||||||
@ -4482,6 +4485,50 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On a normal basis we limit mob movement updates based on distance
|
||||||
|
* This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes
|
||||||
|
*
|
||||||
|
* For very large zones we will also force a full update based on distance
|
||||||
|
*
|
||||||
|
* We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear
|
||||||
|
* to full stop when they are actually still pathing
|
||||||
|
*/
|
||||||
|
|
||||||
|
float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition());
|
||||||
|
bool moved_far_enough_before_bulk_update = distance_moved >= zone->GetNpcPositionUpdateDistance();
|
||||||
|
bool is_ready_to_update = (
|
||||||
|
client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update
|
||||||
|
);
|
||||||
|
|
||||||
|
if (is_client_moving && is_ready_to_update) {
|
||||||
|
Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName());
|
||||||
|
|
||||||
|
auto &mob_movement_manager = MobMovementManager::Get();
|
||||||
|
auto &mob_list = entity_list.GetMobList();
|
||||||
|
|
||||||
|
for (auto &it : mob_list) {
|
||||||
|
Mob *entity = it.second;
|
||||||
|
if (!entity->IsNPC()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int animation_speed = 0;
|
||||||
|
if (entity->IsMoving()) {
|
||||||
|
if (entity->IsRunning()) {
|
||||||
|
animation_speed = (entity->IsFeared() ? entity->GetFearSpeed() : entity->GetRunspeed());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
animation_speed = entity->GetWalkspeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, animation_speed, ClientRangeAny, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetLastPositionBeforeBulkUpdate(GetPosition());
|
||||||
|
}
|
||||||
|
|
||||||
float new_heading = EQ12toFloat(ppu->heading);
|
float new_heading = EQ12toFloat(ppu->heading);
|
||||||
int32 new_animation = ppu->animation;
|
int32 new_animation = ppu->animation;
|
||||||
|
|
||||||
|
|||||||
@ -592,8 +592,8 @@ bool Client::Process() {
|
|||||||
// only if client is not feigned
|
// only if client is not feigned
|
||||||
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
|
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
|
||||||
int npc_scan_count = 0;
|
int npc_scan_count = 0;
|
||||||
for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) {
|
for (auto & close_mob : close_mobs) {
|
||||||
Mob *mob = it->first;
|
Mob *mob = close_mob.first;
|
||||||
|
|
||||||
if (!mob)
|
if (!mob)
|
||||||
continue;
|
continue;
|
||||||
@ -604,6 +604,7 @@ bool Client::Process() {
|
|||||||
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
|
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
|
||||||
mob->AddToHateList(this, 25);
|
mob->AddToHateList(this, 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
npc_scan_count++;
|
npc_scan_count++;
|
||||||
}
|
}
|
||||||
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
|
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
|
||||||
|
|||||||
@ -4490,7 +4490,7 @@ void command_gmzone(Client *c, const Seperator *sep)
|
|||||||
identifier = sep->arg[3];
|
identifier = sep->arg[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
|
std::string bucket_key = StringFormat("%s-%s-%u-instance", zone_short_name, identifier.c_str(), zone_version);
|
||||||
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
||||||
|
|
||||||
if (existing_zone_instance.length() > 0) {
|
if (existing_zone_instance.length() > 0) {
|
||||||
|
|||||||
@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
|
|||||||
UpdateActiveLight();
|
UpdateActiveLight();
|
||||||
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
|
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
|
||||||
|
|
||||||
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
|
if (IsNPC() && race == ERUDITE)
|
||||||
|
ns->spawn.showhelm = 1;
|
||||||
|
else
|
||||||
|
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
|
||||||
|
|
||||||
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
|
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
|
||||||
ns->spawn.NPC = IsClient() ? 0 : 1;
|
ns->spawn.NPC = IsClient() ? 0 : 1;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -41,18 +41,29 @@ class MobMovementManager
|
|||||||
public:
|
public:
|
||||||
~MobMovementManager();
|
~MobMovementManager();
|
||||||
void Process();
|
void Process();
|
||||||
void AddMob(Mob *m);
|
void AddMob(Mob *mob);
|
||||||
void RemoveMob(Mob *m);
|
void RemoveMob(Mob *mob);
|
||||||
void AddClient(Client *c);
|
void AddClient(Client *client);
|
||||||
void RemoveClient(Client *c);
|
void RemoveClient(Client *client);
|
||||||
|
|
||||||
void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning);
|
void RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode = MovementRunning);
|
||||||
void Teleport(Mob *who, float x, float y, float z, float heading);
|
void Teleport(Mob *who, float x, float y, float z, float heading);
|
||||||
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
|
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
|
||||||
void StopNavigation(Mob *who);
|
void StopNavigation(Mob *who);
|
||||||
void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range);
|
|
||||||
|
void SendCommandToClients(
|
||||||
|
Mob *mob,
|
||||||
|
float delta_x,
|
||||||
|
float delta_y,
|
||||||
|
float delta_z,
|
||||||
|
float delta_heading,
|
||||||
|
int anim,
|
||||||
|
ClientRange range,
|
||||||
|
Client* single_client = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
float FixHeading(float in);
|
float FixHeading(float in);
|
||||||
void DumpStats(Client *to);
|
void DumpStats(Client *client);
|
||||||
void ClearStats();
|
void ClearStats();
|
||||||
|
|
||||||
static MobMovementManager &Get() {
|
static MobMovementManager &Get() {
|
||||||
@ -65,18 +76,18 @@ private:
|
|||||||
MobMovementManager(const MobMovementManager&);
|
MobMovementManager(const MobMovementManager&);
|
||||||
MobMovementManager& operator=(const MobMovementManager&);
|
MobMovementManager& operator=(const MobMovementManager&);
|
||||||
|
|
||||||
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
|
void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim);
|
||||||
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
|
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||||
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
|
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||||
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode);
|
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode);
|
||||||
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
|
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||||
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
|
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
|
||||||
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||||
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||||
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode);
|
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
|
||||||
void PushStopMoving(MobMovementEntry &ent);
|
void PushStopMoving(MobMovementEntry &mob_movement_entry);
|
||||||
void PushEvadeCombat(MobMovementEntry &ent);
|
void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
|
||||||
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode);
|
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
|
||||||
|
|
||||||
struct Implementation;
|
struct Implementation;
|
||||||
std::unique_ptr<Implementation> _impl;
|
std::unique_ptr<Implementation> _impl;
|
||||||
|
|||||||
@ -298,7 +298,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
if(IsClient()) {
|
if(IsClient()) {
|
||||||
char temp[64];
|
char temp[64];
|
||||||
sprintf(temp, "%d", spell_id);
|
sprintf(temp, "%d", spell_id);
|
||||||
parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0);
|
if (parse->EventPlayer(EVENT_CAST_BEGIN, CastToClient(), temp, 0) != 0)
|
||||||
|
return false;
|
||||||
} else if(IsNPC()) {
|
} else if(IsNPC()) {
|
||||||
char temp[64];
|
char temp[64];
|
||||||
sprintf(temp, "%d", spell_id);
|
sprintf(temp, "%d", spell_id);
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
#include "zone_config.h"
|
#include "zone_config.h"
|
||||||
#include "mob_movement_manager.h"
|
#include "mob_movement_manager.h"
|
||||||
#include "npc_scale_manager.h"
|
#include "npc_scale_manager.h"
|
||||||
|
#include "../common/data_verification.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@ -864,6 +865,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
|||||||
m_last_ucss_update = 0;
|
m_last_ucss_update = 0;
|
||||||
|
|
||||||
mMovementManager = &MobMovementManager::Get();
|
mMovementManager = &MobMovementManager::Get();
|
||||||
|
|
||||||
|
SetNpcPositionUpdateDistance(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Zone::~Zone() {
|
Zone::~Zone() {
|
||||||
@ -1194,9 +1197,9 @@ uint32 Zone::CountAuth() {
|
|||||||
bool Zone::Process() {
|
bool Zone::Process() {
|
||||||
spawn_conditions.Process();
|
spawn_conditions.Process();
|
||||||
|
|
||||||
if(spawn2_timer.Check()) {
|
if (spawn2_timer.Check()) {
|
||||||
|
|
||||||
LinkedListIterator<Spawn2*> iterator(spawn2_list);
|
LinkedListIterator<Spawn2 *> iterator(spawn2_list);
|
||||||
|
|
||||||
EQEmu::InventoryProfile::CleanDirty();
|
EQEmu::InventoryProfile::CleanDirty();
|
||||||
|
|
||||||
@ -1212,10 +1215,15 @@ bool Zone::Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(adv_data && !did_adventure_actions)
|
if (adv_data && !did_adventure_actions) {
|
||||||
DoAdventureActions();
|
DoAdventureActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetNpcPositionUpdateDistance() == 0) {
|
||||||
|
CalculateNpcUpdateDistanceSpread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(initgrids_timer.Check()) {
|
if(initgrids_timer.Check()) {
|
||||||
//delayed grid loading stuff.
|
//delayed grid loading stuff.
|
||||||
initgrids_timer.Disable();
|
initgrids_timer.Disable();
|
||||||
@ -2365,3 +2373,59 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
|
|||||||
if (m_last_ucss_update < update_timestamp)
|
if (m_last_ucss_update < update_timestamp)
|
||||||
m_ucss_available = ucss_available;
|
m_ucss_available = ucss_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Zone::GetNpcPositionUpdateDistance() const
|
||||||
|
{
|
||||||
|
return npc_position_update_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Zone::SetNpcPositionUpdateDistance(int in_npc_position_update_distance)
|
||||||
|
{
|
||||||
|
Zone::npc_position_update_distance = in_npc_position_update_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Zone::CalculateNpcUpdateDistanceSpread()
|
||||||
|
{
|
||||||
|
float max_x = 0;
|
||||||
|
float max_y = 0;
|
||||||
|
float min_x = 0;
|
||||||
|
float min_y = 0;
|
||||||
|
|
||||||
|
auto &mob_list = entity_list.GetMobList();
|
||||||
|
|
||||||
|
for (auto &it : mob_list) {
|
||||||
|
Mob *entity = it.second;
|
||||||
|
if (!entity->IsNPC()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity->GetX() <= min_x) {
|
||||||
|
min_x = entity->GetX();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity->GetY() <= min_y) {
|
||||||
|
min_y = entity->GetY();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity->GetX() >= max_x) {
|
||||||
|
max_x = entity->GetX();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entity->GetY() >= max_y) {
|
||||||
|
max_y = entity->GetY();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x_spread = int(abs(max_x - min_x));
|
||||||
|
int y_spread = int(abs(max_y - min_y));
|
||||||
|
int combined_spread = int(abs((x_spread + y_spread) / 2));
|
||||||
|
int update_distance = EQEmu::ClampLower(int(combined_spread / 4), int(zone->GetMaxMovementUpdateRange()));
|
||||||
|
|
||||||
|
SetNpcPositionUpdateDistance(update_distance);
|
||||||
|
|
||||||
|
Log(Logs::General, Logs::Debug,
|
||||||
|
"NPC update spread distance set to [%i] combined_spread [%i]",
|
||||||
|
update_distance,
|
||||||
|
combined_spread
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -126,6 +126,9 @@ public:
|
|||||||
bool Process();
|
bool Process();
|
||||||
bool SaveZoneCFG();
|
bool SaveZoneCFG();
|
||||||
|
|
||||||
|
int GetNpcPositionUpdateDistance() const;
|
||||||
|
void SetNpcPositionUpdateDistance(int in_npc_position_update_distance);
|
||||||
|
|
||||||
char *adv_data;
|
char *adv_data;
|
||||||
|
|
||||||
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
|
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
|
||||||
@ -219,6 +222,7 @@ public:
|
|||||||
void ChangeWeather();
|
void ChangeWeather();
|
||||||
void ClearBlockedSpells();
|
void ClearBlockedSpells();
|
||||||
void ClearNPCTypeCache(int id);
|
void ClearNPCTypeCache(int id);
|
||||||
|
void CalculateNpcUpdateDistanceSpread();
|
||||||
void DelAggroMob() { aggroedmobs--; }
|
void DelAggroMob() { aggroedmobs--; }
|
||||||
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
|
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
|
||||||
void Despawn(uint32 spawngroupID);
|
void Despawn(uint32 spawngroupID);
|
||||||
@ -290,7 +294,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
find_replace(message, std::string("%"), std::string("."));
|
find_replace(message, std::string("%"), std::string("."));
|
||||||
|
|
||||||
if (message.find("\n") != std::string::npos) {
|
if (message.find('\n') != std::string::npos) {
|
||||||
auto message_split = SplitString(message, '\n');
|
auto message_split = SplitString(message, '\n');
|
||||||
entity_list.MessageStatus(
|
entity_list.MessageStatus(
|
||||||
0,
|
0,
|
||||||
@ -345,6 +349,7 @@ private:
|
|||||||
glm::vec4 m_Graveyard;
|
glm::vec4 m_Graveyard;
|
||||||
int default_ruleset;
|
int default_ruleset;
|
||||||
int totalBS;
|
int totalBS;
|
||||||
|
int npc_position_update_distance;
|
||||||
int32 aggroedmobs;
|
int32 aggroedmobs;
|
||||||
uint8 zone_type;
|
uint8 zone_type;
|
||||||
uint16 instanceversion;
|
uint16 instanceversion;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user