diff --git a/CMakeLists.txt b/CMakeLists.txt
index d58e2bd1f..6f3a25301 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -326,14 +326,10 @@ IF(ZLIB_FOUND)
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
ENDIF()
ELSE()
- # NOTE: This processing chain is broken.
- # Path "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" is added to ${SERVER_LIBS}..but, the current CMake process does not
- # 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.
+ MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
+ SET(EQEMU_BUILD_ZLIB ON)
INCLUDE_DIRECTORIES(BEFORE SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/libs/zlibng" "${CMAKE_CURRENT_SOURCE_DIR}/libs/zlibng")
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
- MESSAGE(STATUS "Could NOT find ZLIB - using ZLIBSTATIC package.")
ENDIF()
IF(WIN32)
diff --git a/README.md b/README.md
index e1126241c..5e4f919fe 100644
--- a/README.md
+++ b/README.md
@@ -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)
* CPPUnit - GLP StringUtilities - Apache
* LUA - MIT
+
+## Contributors
+
+
+
+
diff --git a/changelog.txt b/changelog.txt
index 6b9d00a80..3f69bf570 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,5 +1,8 @@
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 ==
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
diff --git a/common/emu_constants.h b/common/emu_constants.h
index 384aa3768..c6491b3b3 100644
--- a/common/emu_constants.h
+++ b/common/emu_constants.h
@@ -77,6 +77,10 @@ namespace EQEmu
} // namespace invtype
+ namespace DevTools {
+ const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
+ }
+
namespace popupresponse {
const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
const int32 MOB_INFO_DISMISS = 2000000001;
diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp
index 7569b4c5d..bb310a76c 100644
--- a/common/patches/sof.cpp
+++ b/common/patches/sof.cpp
@@ -1116,7 +1116,10 @@ namespace SoF
}
OUT(deity);
OUT(intoxication);
+
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
+ eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release
+
OUT(abilitySlotRefresh);
OUT(points); // Relocation Test
// OUT(unknown0166[4]);
@@ -1177,7 +1180,10 @@ namespace SoF
}
// OUT(unknown4184[128]);
+
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(platinum);
OUT(gold);
diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h
index 399ff8c1a..a03676f2d 100644
--- a/common/patches/sof_limits.h
+++ b/common/patches/sof_limits.h
@@ -328,7 +328,11 @@ namespace SoF
const int SPELL_ID_MAX = 15999;
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(CastingSlot::MaxGems);
+ const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration
const int LONG_BUFFS = 25;
const int SHORT_BUFFS = 15;
diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h
index 93b185e23..4d4a591e1 100644
--- a/common/patches/sof_structs.h
+++ b/common/patches/sof_structs.h
@@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
/*00160*/ uint32 deity; // deity
/*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;
/*00212*/ uint8 haircolor; // Player hair color
/*00213*/ uint8 beardcolor; // Player beard color
@@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets
/*04173*/ uint8 unknown02264[147]; // was [139]
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
/*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]
/*06464*/ uint32 platinum; // Platinum Pieces on player
/*06468*/ uint32 gold; // Gold Pieces on player
@@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
};
struct LoadSpellSet_Struct {
- uint32 spell[spells::SPELL_GEM_COUNT];
+ uint32 spell[spells::SPELL_GEM_PROFILE_SIZE];
uint32 unknown;
};
diff --git a/queryserv/database.cpp b/queryserv/database.cpp
index fcda884e4..1e06f229e 100644
--- a/queryserv/database.cpp
+++ b/queryserv/database.cpp
@@ -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) {
/*
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());
}
- safe_delete(pack);
safe_delete_array(queryBuffer);
}
diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl
index f05c2c266..b2a53b864 100644
--- a/utils/scripts/eqemu_server.pl
+++ b/utils/scripts/eqemu_server.pl
@@ -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 "\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 "
-
- login.eqemulator.net
- 5998
-
-
-
-
- 127.0.0.1
- 5998
-
-
-
+ \"loginserver1\" : {
+ \"account\" : \"\",
+ \"host\" : \"login.eqemulator.net\",
+ \"password\" : \"\",
+ \"port\" : \"5998\",
+ \"legacy\": \"1\"
+ },
+ \"loginserver2\" : {
+ \"account\" : \"\",
+ \"host\" : \"192.168.197.129\",
+ \"password\" : \"\",
+ \"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";
}
}
diff --git a/zone/client.cpp b/zone/client.cpp
index 17521b769..60a6d1d8c 100644
--- a/zone/client.cpp
+++ b/zone/client.cpp
@@ -136,6 +136,7 @@ Client::Client(EQStreamInterface* ieqs)
forget_timer(0),
autosave_timer(RuleI(Character, AutosaveIntervalS) * 1000),
client_scan_npc_aggro_timer(RuleI(Aggro, ClientAggroCheckInterval) * 1000),
+ client_zone_wide_full_position_update_timer(5 * 60 * 1000),
tribute_timer(Tribute_duration),
proximity_timer(ClientProximity_interval),
TaskPeriodic_Timer(RuleI(TaskSystem, PeriodicCheckTimer) * 1000),
@@ -9121,3 +9122,16 @@ bool Client::GotoPlayer(std::string player_name)
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;
+}
\ No newline at end of file
diff --git a/zone/client.h b/zone/client.h
index 586541ca6..29632d667 100644
--- a/zone/client.h
+++ b/zone/client.h
@@ -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.
+ void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
+ glm::vec4 &GetLastPositionBeforeBulkUpdate();
+
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);
@@ -1517,6 +1520,7 @@ private:
Timer forget_timer; // our 2 min everybody forgets you timer
Timer autosave_timer;
Timer client_scan_npc_aggro_timer;
+ Timer client_zone_wide_full_position_update_timer;
Timer tribute_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 */
glm::vec3 m_Proximity;
+ glm::vec4 last_position_before_bulk_update;
void BulkSendInventoryItems();
diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp
index 2c8636014..2bd6ed1ac 100644
--- a/zone/client_packet.cpp
+++ b/zone/client_packet.cpp
@@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "water_map.h"
#include "worldserver.h"
#include "zone.h"
+#include "mob_movement_manager.h"
#ifdef BOTS
#include "bot.h"
@@ -805,6 +806,8 @@ void Client::CompleteConnect()
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. */
if (firstlogon == 1) {
parse->EventPlayer(EVENT_CONNECT, this, "", 0);
@@ -1679,7 +1682,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/**
* 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());
if (DataBucket::GetData(dev_tools_window_key) == "true") {
dev_tools_window_enabled = false;
@@ -4464,16 +4467,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
/* Handle client aggro scanning timers NPCs */
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
-
+
if (is_client_moving) {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
client_scan_npc_aggro_timer.Disable();
client_scan_npc_aggro_timer.Start(500);
-
}
- } else {
+ }
+ else {
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
client_scan_npc_aggro_timer.GetDuration());
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
@@ -4481,7 +4484,51 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
client_scan_npc_aggro_timer.Start(3000);
}
}
-
+
+ /**
+ * 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);
int32 new_animation = ppu->animation;
diff --git a/zone/client_process.cpp b/zone/client_process.cpp
index 5c750f03a..244f36580 100644
--- a/zone/client_process.cpp
+++ b/zone/client_process.cpp
@@ -592,8 +592,8 @@ bool Client::Process() {
// only if client is not feigned
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
int npc_scan_count = 0;
- for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) {
- Mob *mob = it->first;
+ for (auto & close_mob : close_mobs) {
+ Mob *mob = close_mob.first;
if (!mob)
continue;
@@ -604,6 +604,7 @@ bool Client::Process() {
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
mob->AddToHateList(this, 25);
}
+
npc_scan_count++;
}
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
diff --git a/zone/command.cpp b/zone/command.cpp
index 16e4edd55..d95f07e8a 100755
--- a/zone/command.cpp
+++ b/zone/command.cpp
@@ -4490,7 +4490,7 @@ void command_gmzone(Client *c, const Seperator *sep)
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);
if (existing_zone_instance.length() > 0) {
diff --git a/zone/mob.cpp b/zone/mob.cpp
index ca844d459..3a307bf3f 100644
--- a/zone/mob.cpp
+++ b/zone/mob.cpp
@@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
UpdateActiveLight();
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.NPC = IsClient() ? 0 : 1;
diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp
index 1fcc19187..4bf1663d3 100644
--- a/zone/mob_movement_manager.cpp
+++ b/zone/mob_movement_manager.cpp
@@ -14,40 +14,41 @@
#include
extern double frame_time;
-extern Zone *zone;
+extern Zone *zone;
-class IMovementCommand
-{
+class IMovementCommand {
public:
IMovementCommand() = default;
virtual ~IMovementCommand() = default;
- virtual bool Process(MobMovementManager *mgr, Mob *m) = 0;
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob) = 0;
virtual bool Started() const = 0;
};
-class RotateToCommand : public IMovementCommand
-{
+class RotateToCommand : public IMovementCommand {
public:
- RotateToCommand(double rotate_to, double dir, MobMovementMode mode) {
- m_rotate_to = rotate_to;
- m_rotate_to_dir = dir;
- m_rotate_to_mode = mode;
- m_started = false;
+ RotateToCommand(double rotate_to, double dir, MobMovementMode mob_movement_mode)
+ {
+ m_rotate_to = rotate_to;
+ m_rotate_to_dir = dir;
+ m_rotate_to_mode = mob_movement_mode;
+ m_started = false;
}
- virtual ~RotateToCommand() {
+ virtual ~RotateToCommand()
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m) {
- if (!m->IsAIControlled()) {
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
+ {
+ if (!mob->IsAIControlled()) {
return true;
}
- auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 200.0 : 16.0; //todo: get this from mob
+ auto rotate_to_speed = m_rotate_to_mode == MovementRunning ? 200.0 : 16.0; //todo: get this from mob
- auto from = FixHeading(m->GetHeading());
- auto to = FixHeading(m_rotate_to);
+ auto from = FixHeading(mob->GetHeading());
+ auto to = FixHeading(m_rotate_to);
auto diff = to - from;
while (diff < -256.0) {
@@ -62,265 +63,282 @@ public:
if (!m_started) {
m_started = true;
- m->SetMoving(true);
-
+ mob->SetMoving(true);
+
if (dist > 15.0f && rotate_to_speed > 0.0 && rotate_to_speed <= 25.0) { //send basic rotation
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, m_rotate_to_dir * rotate_to_speed, 0, ClientRangeClose);
+ mob_movement_manager->SendCommandToClients(
+ mob,
+ 0.0,
+ 0.0,
+ 0.0,
+ m_rotate_to_dir * rotate_to_speed,
+ 0,
+ ClientRangeClose
+ );
}
}
-
+
auto td = rotate_to_speed * 19.0 * frame_time;
-
+
if (td >= dist) {
- m->SetHeading(to);
- m->SetMoving(false);
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
+ mob->SetHeading(to);
+ mob->SetMoving(false);
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
return true;
}
-
+
from += td * m_rotate_to_dir;
- m->SetHeading(FixHeading(from));
+ mob->SetHeading(FixHeading(from));
return false;
}
- virtual bool Started() const {
+ virtual bool Started() const
+ {
return m_started;
}
private:
- double m_rotate_to;
- double m_rotate_to_dir;
+ double m_rotate_to;
+ double m_rotate_to_dir;
MobMovementMode m_rotate_to_mode;
- bool m_started;
+ bool m_started;
};
-class MoveToCommand : public IMovementCommand
-{
+class MoveToCommand : public IMovementCommand {
public:
- MoveToCommand(float x, float y, float z, MobMovementMode mode) {
+ MoveToCommand(float x, float y, float z, MobMovementMode mob_movement_mode)
+ {
m_distance_moved_since_correction = 0.0;
- m_move_to_x = x;
- m_move_to_y = y;
- m_move_to_z = z;
- m_move_to_mode = mode;
- m_last_sent_time = 0.0;
- m_last_sent_speed = 0;
- m_started = false;
- m_total_h_dist = 0.0;
- m_total_v_dist = 0.0;
+ m_move_to_x = x;
+ m_move_to_y = y;
+ m_move_to_z = z;
+ m_move_to_mode = mob_movement_mode;
+ m_last_sent_time = 0.0;
+ m_last_sent_speed = 0;
+ m_started = false;
+ m_total_h_dist = 0.0;
+ m_total_v_dist = 0.0;
}
- virtual ~MoveToCommand() {
+ virtual ~MoveToCommand()
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m) {
- if (!m->IsAIControlled()) {
+ /**
+ * @param mob_movement_manager
+ * @param mob
+ * @return
+ */
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
+ {
+ if (!mob->IsAIControlled()) {
return true;
}
//Send a movement packet when you start moving
- double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
- int current_speed = 0;
+ double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
+ int current_speed = 0;
if (m_move_to_mode == MovementRunning) {
- if (m->IsFeared()) {
- current_speed = m->GetFearSpeed();
+ if (mob->IsFeared()) {
+ current_speed = mob->GetFearSpeed();
}
else {
- current_speed = m->GetRunspeed();
+ current_speed = mob->GetRunspeed();
}
}
else {
- current_speed = m->GetWalkspeed();
+ current_speed = mob->GetWalkspeed();
}
if (!m_started) {
m_started = true;
//rotate to the point
- m->SetMoving(true);
- m->SetHeading(m->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
+ mob->SetMoving(true);
+ mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- m_total_h_dist = DistanceNoZ(m->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
- m_total_v_dist = m_move_to_z - m->GetZ();
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
+ m_total_v_dist = m_move_to_z - mob->GetZ();
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//When speed changes
if (current_speed != m_last_sent_speed) {
if (RuleB(Map, FixZWhenPathing)) {
- m->FixZ();
+ mob->FixZ();
}
m_distance_moved_since_correction = 0.0;
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//If x seconds have passed without sending an update.
if (current_time - m_last_sent_time >= 5.0) {
if (RuleB(Map, FixZWhenPathing)) {
- m->FixZ();
+ mob->FixZ();
}
m_distance_moved_since_correction = 0.0;
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
- auto &p = m->GetPosition();
+ auto &p = mob->GetPosition();
glm::vec2 tar(m_move_to_x, m_move_to_y);
glm::vec2 pos(p.x, p.y);
- double len = glm::distance(pos, tar);
+ double len = glm::distance(pos, tar);
if (len == 0) {
return true;
}
- m->SetMoved(true);
+ mob->SetMoved(true);
- glm::vec2 dir = tar - pos;
- glm::vec2 ndir = glm::normalize(dir);
- double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
+ glm::vec2 dir = tar - pos;
+ glm::vec2 ndir = glm::normalize(dir);
+ double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
- if (distance_moved > len) {
- if (m->IsNPC()) {
- entity_list.ProcessMove(m->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
+ if (distance_moved > len) {
+ if (mob->IsNPC()) {
+ entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
}
- m->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
-
+ mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
+
if (RuleB(Map, FixZWhenPathing)) {
- m->FixZ();
+ mob->FixZ();
}
return true;
}
else {
glm::vec2 npos = pos + (ndir * static_cast(distance_moved));
-
+
len -= distance_moved;
double total_distance_traveled = m_total_h_dist - len;
- double start_z = m_move_to_z - m_total_v_dist;
- double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
+ double start_z = m_move_to_z - m_total_v_dist;
+ double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
- if (m->IsNPC()) {
- entity_list.ProcessMove(m->CastToNPC(), npos.x, npos.y, z_at_pos);
+ if (mob->IsNPC()) {
+ entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos);
}
- m->SetPosition(npos.x, npos.y, z_at_pos);
+ mob->SetPosition(npos.x, npos.y, z_at_pos);
if (RuleB(Map, FixZWhenPathing)) {
m_distance_moved_since_correction += distance_moved;
if (m_distance_moved_since_correction > RuleR(Map, DistanceCanTravelBeforeAdjustment)) {
m_distance_moved_since_correction = 0.0;
- m->FixZ();
+ mob->FixZ();
}
}
}
-
+
return false;
}
- virtual bool Started() const {
+ virtual bool Started() const
+ {
return m_started;
}
protected:
- double m_distance_moved_since_correction;
- double m_move_to_x;
- double m_move_to_y;
- double m_move_to_z;
+ double m_distance_moved_since_correction;
+ double m_move_to_x;
+ double m_move_to_y;
+ double m_move_to_z;
MobMovementMode m_move_to_mode;
- bool m_started;
+ bool m_started;
double m_last_sent_time;
- int m_last_sent_speed;
+ int m_last_sent_speed;
double m_total_h_dist;
double m_total_v_dist;
};
-class SwimToCommand : public MoveToCommand
-{
+class SwimToCommand : public MoveToCommand {
public:
- SwimToCommand(float x, float y, float z, MobMovementMode mode) : MoveToCommand(x, y, z, mode) {
+ SwimToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) : MoveToCommand(x, y, z, mob_movement_mode)
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m)
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
{
- if (!m->IsAIControlled()) {
+ if (!mob->IsAIControlled()) {
return true;
}
- //Send a movement packet when you start moving
- double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
- int current_speed = 0;
+ //Send a movement packet when you start moving
+ double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
+ int current_speed = 0;
if (m_move_to_mode == MovementRunning) {
- if (m->IsFeared()) {
- current_speed = m->GetFearSpeed();
+ if (mob->IsFeared()) {
+ current_speed = mob->GetFearSpeed();
}
else {
- current_speed = m->GetRunspeed();
+ current_speed = mob->GetRunspeed();
}
}
else {
- current_speed = m->GetWalkspeed();
+ current_speed = mob->GetWalkspeed();
}
if (!m_started) {
m_started = true;
//rotate to the point
- m->SetMoving(true);
- m->SetHeading(m->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
+ mob->SetMoving(true);
+ mob->SetHeading(mob->CalculateHeadingToTarget(m_move_to_x, m_move_to_y));
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- m_total_h_dist = DistanceNoZ(m->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
- m_total_v_dist = m_move_to_z - m->GetZ();
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ m_total_h_dist = DistanceNoZ(mob->GetPosition(), glm::vec4(m_move_to_x, m_move_to_y, 0.0f, 0.0f));
+ m_total_v_dist = m_move_to_z - mob->GetZ();
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//When speed changes
if (current_speed != m_last_sent_speed) {
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
//If x seconds have passed without sending an update.
if (current_time - m_last_sent_time >= 1.5) {
m_last_sent_speed = current_speed;
- m_last_sent_time = current_time;
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
+ m_last_sent_time = current_time;
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium);
}
- auto &p = m->GetPosition();
+ auto &p = mob->GetPosition();
glm::vec2 tar(m_move_to_x, m_move_to_y);
glm::vec2 pos(p.x, p.y);
- double len = glm::distance(pos, tar);
+ double len = glm::distance(pos, tar);
if (len == 0) {
return true;
}
- m->SetMoved(true);
+ mob->SetMoved(true);
- glm::vec2 dir = tar - pos;
- glm::vec2 ndir = glm::normalize(dir);
- double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
+ glm::vec2 dir = tar - pos;
+ glm::vec2 ndir = glm::normalize(dir);
+ double distance_moved = frame_time * current_speed * 0.4f * 1.45f;
if (distance_moved > len) {
- if (m->IsNPC()) {
- entity_list.ProcessMove(m->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
+ if (mob->IsNPC()) {
+ entity_list.ProcessMove(mob->CastToNPC(), m_move_to_x, m_move_to_y, m_move_to_z);
}
- m->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
+ mob->SetPosition(m_move_to_x, m_move_to_y, m_move_to_z);
return true;
}
else {
@@ -328,51 +346,54 @@ public:
len -= distance_moved;
double total_distance_traveled = m_total_h_dist - len;
- double start_z = m_move_to_z - m_total_v_dist;
- double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
+ double start_z = m_move_to_z - m_total_v_dist;
+ double z_at_pos = start_z + (m_total_v_dist * (total_distance_traveled / m_total_h_dist));
- if (m->IsNPC()) {
- entity_list.ProcessMove(m->CastToNPC(), npos.x, npos.y, z_at_pos);
+ if (mob->IsNPC()) {
+ entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos);
}
- m->SetPosition(npos.x, npos.y, z_at_pos);
+ mob->SetPosition(npos.x, npos.y, z_at_pos);
}
return false;
}
};
-class TeleportToCommand : public IMovementCommand
-{
+class TeleportToCommand : public IMovementCommand {
public:
- TeleportToCommand(float x, float y, float z, float heading) {
- m_teleport_to_x = x;
- m_teleport_to_y = y;
- m_teleport_to_z = z;
+ TeleportToCommand(float x, float y, float z, float heading)
+ {
+ m_teleport_to_x = x;
+ m_teleport_to_y = y;
+ m_teleport_to_z = z;
m_teleport_to_heading = heading;
}
- virtual ~TeleportToCommand() {
+ virtual ~TeleportToCommand()
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m) {
- if (!m->IsAIControlled()) {
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
+ {
+ if (!mob->IsAIControlled()) {
return true;
}
- if (m->IsNPC()) {
- entity_list.ProcessMove(m->CastToNPC(), m_teleport_to_x, m_teleport_to_y, m_teleport_to_z);
+ if (mob->IsNPC()) {
+ entity_list.ProcessMove(mob->CastToNPC(), m_teleport_to_x, m_teleport_to_y, m_teleport_to_z);
}
- m->SetPosition(m_teleport_to_x, m_teleport_to_y, m_teleport_to_z);
- m->SetHeading(mgr->FixHeading(m_teleport_to_heading));
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
+ mob->SetPosition(m_teleport_to_x, m_teleport_to_y, m_teleport_to_z);
+ mob->SetHeading(mob_movement_manager->FixHeading(m_teleport_to_heading));
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny);
return true;
}
- virtual bool Started() const {
+ virtual bool Started() const
+ {
return false;
}
@@ -384,93 +405,99 @@ private:
double m_teleport_to_heading;
};
-class StopMovingCommand : public IMovementCommand
-{
+class StopMovingCommand : public IMovementCommand {
public:
- StopMovingCommand() {
+ StopMovingCommand()
+ {
}
- virtual ~StopMovingCommand() {
+ virtual ~StopMovingCommand()
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m) {
- if (!m->IsAIControlled()) {
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
+ {
+ if (!mob->IsAIControlled()) {
return true;
}
- if (m->IsMoving()) {
- m->SetMoving(false);
+ if (mob->IsMoving()) {
+ mob->SetMoving(false);
if (RuleB(Map, FixZWhenPathing)) {
- m->FixZ();
+ mob->FixZ();
}
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
}
return true;
}
- virtual bool Started() const {
+ virtual bool Started() const
+ {
return false;
}
};
-class EvadeCombatCommand : public IMovementCommand
-{
+class EvadeCombatCommand : public IMovementCommand {
public:
- EvadeCombatCommand() {
+ EvadeCombatCommand()
+ {
}
- virtual ~EvadeCombatCommand() {
+ virtual ~EvadeCombatCommand()
+ {
}
- virtual bool Process(MobMovementManager *mgr, Mob *m) {
- if (!m->IsAIControlled()) {
+ virtual bool Process(MobMovementManager *mob_movement_manager, Mob *mob)
+ {
+ if (!mob->IsAIControlled()) {
return true;
}
- if (m->IsMoving()) {
- m->SetMoving(false);
- mgr->SendCommandToClients(m, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
+ if (mob->IsMoving()) {
+ mob->SetMoving(false);
+ mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeCloseMedium);
}
- m->BuffFadeAll();
- m->WipeHateList();
- m->Heal();
+ mob->BuffFadeAll();
+ mob->WipeHateList();
+ mob->Heal();
return true;
}
- virtual bool Started() const {
+ virtual bool Started() const
+ {
return false;
}
};
-struct MovementStats
-{
- MovementStats() {
- LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0;
- TotalSent = 0ULL;
+struct MovementStats {
+ MovementStats()
+ {
+ LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0;
+ TotalSent = 0ULL;
TotalSentMovement = 0ULL;
TotalSentPosition = 0ULL;
- TotalSentHeading = 0ULL;
+ TotalSentHeading = 0ULL;
}
- double LastResetTime;
+ double LastResetTime;
uint64_t TotalSent;
uint64_t TotalSentMovement;
uint64_t TotalSentPosition;
uint64_t TotalSentHeading;
};
-struct NavigateTo
-{
- NavigateTo() {
- navigate_to_x = 0.0;
- navigate_to_y = 0.0;
- navigate_to_z = 0.0;
+struct NavigateTo {
+ NavigateTo()
+ {
+ navigate_to_x = 0.0;
+ navigate_to_y = 0.0;
+ navigate_to_z = 0.0;
navigate_to_heading = 0.0;
- last_set_time = 0.0;
+ last_set_time = 0.0;
}
double navigate_to_x;
@@ -480,13 +507,13 @@ struct NavigateTo
double last_set_time;
};
-struct MobMovementEntry
-{
+struct MobMovementEntry {
std::deque> Commands;
- NavigateTo NavTo;
+ NavigateTo NavTo;
};
-void AdjustRoute(std::list &nodes, Mob *who) {
+void AdjustRoute(std::list &nodes, Mob *who)
+{
if (!zone->HasMap() || !zone->HasWaterMap()) {
return;
}
@@ -494,7 +521,7 @@ void AdjustRoute(std::list &nodes, Mob *who) {
auto offset = who->GetZOffset();
for (auto &node : nodes) {
- if(!zone->watermap->InLiquid(node.pos)) {
+ if (!zone->watermap->InLiquid(node.pos)) {
auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr);
if (best_z != BEST_Z_INVALID) {
node.pos.z = best_z + offset;
@@ -503,11 +530,10 @@ void AdjustRoute(std::list &nodes, Mob *who) {
}
}
-struct MobMovementManager::Implementation
-{
- std::map Entries;
- std::vector Clients;
- MovementStats Stats;
+struct MobMovementManager::Implementation {
+ std::map Entries;
+ std::vector Clients;
+ MovementStats Stats;
};
MobMovementManager::MobMovementManager()
@@ -522,12 +548,12 @@ MobMovementManager::~MobMovementManager()
void MobMovementManager::Process()
{
for (auto &iter : _impl->Entries) {
- auto &ent = iter.second;
+ auto &ent = iter.second;
auto &commands = ent.Commands;
while (true != commands.empty()) {
auto &cmd = commands.front();
- auto r = cmd->Process(this, iter.first);
+ auto r = cmd->Process(this, iter.first);
if (true != r) {
break;
@@ -538,35 +564,52 @@ void MobMovementManager::Process()
}
}
-void MobMovementManager::AddMob(Mob *m)
+/**
+ * @param mob
+ */
+void MobMovementManager::AddMob(Mob *mob)
{
- _impl->Entries.insert(std::make_pair(m, MobMovementEntry()));
+ _impl->Entries.insert(std::make_pair(mob, MobMovementEntry()));
}
-void MobMovementManager::RemoveMob(Mob *m)
+/**
+ * @param mob
+ */
+void MobMovementManager::RemoveMob(Mob *mob)
{
- _impl->Entries.erase(m);
+ _impl->Entries.erase(mob);
}
-void MobMovementManager::AddClient(Client *c)
+/**
+ * @param client
+ */
+void MobMovementManager::AddClient(Client *client)
{
- _impl->Clients.push_back(c);
+ _impl->Clients.push_back(client);
}
-void MobMovementManager::RemoveClient(Client *c)
+/**
+ * @param client
+ */
+void MobMovementManager::RemoveClient(Client *client)
{
auto iter = _impl->Clients.begin();
while (iter != _impl->Clients.end()) {
- if (c == *iter) {
+ if (client == *iter) {
_impl->Clients.erase(iter);
return;
}
-
+
++iter;
}
}
-void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mode)
+/**
+ * @param who
+ * @param to
+ * @param mob_movement_mode
+ */
+void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode)
{
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
@@ -574,20 +617,34 @@ void MobMovementManager::RotateTo(Mob *who, float to, MobMovementMode mode)
if (true != ent.second.Commands.empty()) {
return;
}
-
- PushRotateTo(ent.second, who, to, mode);
+
+ PushRotateTo(ent.second, who, to, mob_movement_mode);
}
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param heading
+ */
void MobMovementManager::Teleport(Mob *who, float x, float y, float z, float heading)
{
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
-
+
ent.second.Commands.clear();
PushTeleportTo(ent.second, x, y, z, heading);
}
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param mode
+ */
void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode)
{
if (IsPositionEqualWithinCertainZ(glm::vec3(x, y, z), glm::vec3(who->GetX(), who->GetY(), who->GetZ()), 6.0f)) {
@@ -601,8 +658,13 @@ void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMove
double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
if ((current_time - nav.last_set_time) > 0.5) {
//Can potentially recalc
-
- auto within = IsPositionWithinSimpleCylinder(glm::vec3(x, y, z), glm::vec3(nav.navigate_to_x, nav.navigate_to_y, nav.navigate_to_z), 1.5f, 6.0f);
+
+ auto within = IsPositionWithinSimpleCylinder(
+ glm::vec3(x, y, z),
+ glm::vec3(nav.navigate_to_x, nav.navigate_to_y, nav.navigate_to_z),
+ 1.5f,
+ 6.0f
+ );
auto heading_match = IsHeadingEqual(0.0, nav.navigate_to_heading);
if (false == within || false == heading_match || ent.second.Commands.size() == 0) {
@@ -610,23 +672,27 @@ void MobMovementManager::NavigateTo(Mob *who, float x, float y, float z, MobMove
//Path is no longer valid, calculate a new path
UpdatePath(who, x, y, z, mode);
- nav.navigate_to_x = x;
- nav.navigate_to_y = y;
- nav.navigate_to_z = z;
+ nav.navigate_to_x = x;
+ nav.navigate_to_y = y;
+ nav.navigate_to_z = z;
nav.navigate_to_heading = 0.0;
- nav.last_set_time = current_time;
+ nav.last_set_time = current_time;
}
}
}
-void MobMovementManager::StopNavigation(Mob *who) {
+/**
+ * @param who
+ */
+void MobMovementManager::StopNavigation(Mob *who)
+{
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
auto &nav = ent.second.NavTo;
- nav.navigate_to_x = 0.0;
- nav.navigate_to_y = 0.0;
- nav.navigate_to_z = 0.0;
+ nav.navigate_to_x = 0.0;
+ nav.navigate_to_y = 0.0;
+ nav.navigate_to_z = 0.0;
nav.navigate_to_heading = 0.0;
if (true == ent.second.Commands.empty()) {
@@ -643,24 +709,48 @@ void MobMovementManager::StopNavigation(Mob *who) {
PushStopMoving(ent.second);
}
-void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range)
+/**
+ * @param mob
+ * @param delta_x
+ * @param delta_y
+ * @param delta_z
+ * @param delta_heading
+ * @param anim
+ * @param range
+ * @param single_client
+ */
+void MobMovementManager::SendCommandToClients(
+ Mob *mob,
+ float delta_x,
+ float delta_y,
+ float delta_z,
+ float delta_heading,
+ int anim,
+ ClientRange range,
+ Client* single_client
+)
{
if (range == ClientRangeNone) {
return;
}
EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
- PlayerPositionUpdateServer_Struct *spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer;
- FillCommandStruct(spu, m, dx, dy, dz, dh, anim);
+ auto *spu = (PlayerPositionUpdateServer_Struct *) outapp.pBuffer;
+
+ FillCommandStruct(spu, mob, delta_x, delta_y, delta_z, delta_heading, anim);
if (range == ClientRangeAny) {
for (auto &c : _impl->Clients) {
+ if (single_client && c != single_client) {
+ continue;
+ }
+
_impl->Stats.TotalSent++;
if (anim != 0) {
_impl->Stats.TotalSentMovement++;
}
- else if (dh != 0) {
+ else if (delta_heading != 0) {
_impl->Stats.TotalSentHeading++;
}
else {
@@ -672,26 +762,30 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float
}
else {
float short_range = RuleR(Pathing, ShortMovementUpdateRange);
- float long_range = zone->GetMaxMovementUpdateRange();
+ float long_range = zone->GetNpcPositionUpdateDistance();
for (auto &c : _impl->Clients) {
- float dist = c->CalculateDistance(m->GetX(), m->GetY(), m->GetZ());
+ if (single_client && c != single_client) {
+ continue;
+ }
+
+ float distance = c->CalculateDistance(mob->GetX(), mob->GetY(), mob->GetZ());
bool match = false;
if (range & ClientRangeClose) {
- if (dist < short_range) {
+ if (distance < short_range) {
match = true;
}
}
if (!match && range & ClientRangeMedium) {
- if (dist >= short_range && dist < long_range) {
+ if (distance >= short_range && distance < long_range) {
match = true;
}
}
if (!match && range & ClientRangeLong) {
- if (dist >= long_range) {
+ if (distance >= long_range) {
match = true;
}
}
@@ -702,7 +796,7 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float
if (anim != 0) {
_impl->Stats.TotalSentMovement++;
}
- else if (dh != 0) {
+ else if (delta_heading != 0) {
_impl->Stats.TotalSentHeading++;
}
else {
@@ -715,6 +809,10 @@ void MobMovementManager::SendCommandToClients(Mob *m, float dx, float dy, float
}
}
+/**
+ * @param in
+ * @return
+ */
float MobMovementManager::FixHeading(float in)
{
auto h = in;
@@ -729,83 +827,139 @@ float MobMovementManager::FixHeading(float in)
return h;
}
-void MobMovementManager::DumpStats(Client *to)
+/**
+ * @param client
+ */
+void MobMovementManager::DumpStats(Client *client)
{
auto current_time = static_cast(Timer::GetCurrentTime()) / 1000.0;
- auto total_time = current_time - _impl->Stats.LastResetTime;
+ auto total_time = current_time - _impl->Stats.LastResetTime;
- to->Message(MT_System, "Dumping Movement Stats:");
- to->Message(MT_System, "Total Sent: %u (%.2f / sec)", _impl->Stats.TotalSent, static_cast(_impl->Stats.TotalSent) / total_time);
- to->Message(MT_System, "Total Heading: %u (%.2f / sec)", _impl->Stats.TotalSentHeading, static_cast(_impl->Stats.TotalSentHeading) / total_time);
- to->Message(MT_System, "Total Movement: %u (%.2f / sec)", _impl->Stats.TotalSentMovement, static_cast(_impl->Stats.TotalSentMovement) / total_time);
- to->Message(MT_System, "Total Position: %u (%.2f / sec)", _impl->Stats.TotalSentPosition, static_cast(_impl->Stats.TotalSentPosition) / total_time);
+ client->Message(MT_System, "Dumping Movement Stats:");
+ client->Message(
+ MT_System,
+ "Total Sent: %u (%.2f / sec)",
+ _impl->Stats.TotalSent,
+ static_cast(_impl->Stats.TotalSent) / total_time
+ );
+ client->Message(
+ MT_System,
+ "Total Heading: %u (%.2f / sec)",
+ _impl->Stats.TotalSentHeading,
+ static_cast(_impl->Stats.TotalSentHeading) / total_time
+ );
+ client->Message(
+ MT_System,
+ "Total Movement: %u (%.2f / sec)",
+ _impl->Stats.TotalSentMovement,
+ static_cast(_impl->Stats.TotalSentMovement) / total_time
+ );
+ client->Message(
+ MT_System,
+ "Total Position: %u (%.2f / sec)",
+ _impl->Stats.TotalSentPosition,
+ static_cast(_impl->Stats.TotalSentPosition) / total_time
+ );
}
void MobMovementManager::ClearStats()
{
- _impl->Stats.LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0;
- _impl->Stats.TotalSent = 0;
- _impl->Stats.TotalSentHeading = 0;
+ _impl->Stats.LastResetTime = static_cast(Timer::GetCurrentTime()) / 1000.0;
+ _impl->Stats.TotalSent = 0;
+ _impl->Stats.TotalSentHeading = 0;
_impl->Stats.TotalSentMovement = 0;
_impl->Stats.TotalSentPosition = 0;
}
-void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim)
+/**
+ * @param position_update
+ * @param mob
+ * @param delta_x
+ * @param delta_y
+ * @param delta_z
+ * @param delta_heading
+ * @param anim
+ */
+void MobMovementManager::FillCommandStruct(
+ PlayerPositionUpdateServer_Struct *position_update,
+ Mob *mob,
+ float delta_x,
+ float delta_y,
+ float delta_z,
+ float delta_heading,
+ int anim
+)
{
- memset(spu, 0x00, sizeof(PlayerPositionUpdateServer_Struct));
- spu->spawn_id = m->GetID();
- spu->x_pos = FloatToEQ19(m->GetX());
- spu->y_pos = FloatToEQ19(m->GetY());
- spu->z_pos = FloatToEQ19(m->GetZ());
- spu->heading = FloatToEQ12(m->GetHeading());
- spu->delta_x = FloatToEQ13(dx);
- spu->delta_y = FloatToEQ13(dy);
- spu->delta_z = FloatToEQ13(dz);
- spu->delta_heading = FloatToEQ10(dh);
- spu->animation = (m->IsBot() ? (int)((float)anim / 1.785714f) : anim);
+ memset(position_update, 0x00, sizeof(PlayerPositionUpdateServer_Struct));
+ position_update->spawn_id = mob->GetID();
+ position_update->x_pos = FloatToEQ19(mob->GetX());
+ position_update->y_pos = FloatToEQ19(mob->GetY());
+ position_update->z_pos = FloatToEQ19(mob->GetZ());
+ position_update->heading = FloatToEQ12(mob->GetHeading());
+ position_update->delta_x = FloatToEQ13(delta_x);
+ position_update->delta_y = FloatToEQ13(delta_y);
+ position_update->delta_z = FloatToEQ13(delta_z);
+ position_update->delta_heading = FloatToEQ10(delta_heading);
+ position_update->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim);
}
-void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param mob_movement_mode
+ */
+void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode)
{
if (!zone->HasMap() || !zone->HasWaterMap()) {
auto iter = _impl->Entries.find(who);
auto &ent = (*iter);
-
- PushMoveTo(ent.second, x, y, z, mode);
+
+ PushMoveTo(ent.second, x, y, z, mob_movement_mode);
PushStopMoving(ent.second);
return;
}
-
+
if (who->IsBoat()) {
- UpdatePathBoat(who, x, y, z, mode);
- } else if (who->IsUnderwaterOnly()) {
- UpdatePathUnderwater(who, x, y, z, mode);
+ UpdatePathBoat(who, x, y, z, mob_movement_mode);
+ }
+ else if (who->IsUnderwaterOnly()) {
+ UpdatePathUnderwater(who, x, y, z, mob_movement_mode);
}
else {
- UpdatePathGround(who, x, y, z, mode);
+ UpdatePathGround(who, x, y, z, mob_movement_mode);
}
}
-void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param mode
+ */
+void MobMovementManager::UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode)
{
PathfinderOptions opts;
opts.smooth_path = true;
- opts.step_size = RuleR(Pathing, NavmeshStepSize);
- opts.offset = who->GetZOffset();
- opts.flags = PathingNotDisabled ^ PathingZoneLine;
+ opts.step_size = RuleR(Pathing, NavmeshStepSize);
+ opts.offset = who->GetZOffset();
+ opts.flags = PathingNotDisabled ^ PathingZoneLine;
//This is probably pointless since the nav mesh tool currently sets zonelines to disabled anyway
auto partial = false;
- auto stuck = false;
- auto route = zone->pathing->FindPath(
+ auto stuck = false;
+ auto route = zone->pathing->FindPath(
glm::vec3(who->GetX(), who->GetY(), who->GetZ()),
glm::vec3(x, y, z),
partial,
stuck,
- opts);
+ opts
+ );
auto eiter = _impl->Entries.find(who);
- auto &ent = (*eiter);
+ auto &ent = (*eiter);
if (route.size() == 0) {
HandleStuckBehavior(who, x, y, z, mode);
@@ -813,31 +967,26 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z,
}
AdjustRoute(route, who);
-
-
-
+
//avoid doing any processing if the mob is stuck to allow normal stuck code to work.
- if (!stuck)
- {
+ if (!stuck) {
//there are times when the routes returned are no differen than where the mob is currently standing. What basically happens
- //is a mob will get 'stuck' in such a way that it should be moving but the 'moving' place is the exact same spot it is at.
- //this is a problem and creates an area of ground that if a mob gets to, will stay there forever. If socal this creates a
- //"Ball of Death" (tm). This code tries to prevent this by simply warping the mob to the requested x/y. Better to have a warp than
+ //is a mob will get 'stuck' in such a way that it should be moving but the 'moving' place is the exact same spot it is at.
+ //this is a problem and creates an area of ground that if a mob gets to, will stay there forever. If socal this creates a
+ //"Ball of Death" (tm). This code tries to prevent this by simply warping the mob to the requested x/y. Better to have a warp than
//have stuck mobs.
- auto routeNode = route.begin();
+ auto routeNode = route.begin();
bool noValidPath = true;
while (routeNode != route.end() && noValidPath == true) {
auto ¤tNode = (*routeNode);
- if (routeNode == route.end())
- {
+ if (routeNode == route.end()) {
continue;
}
- if (!(currentNode.pos.x == who->GetX() && currentNode.pos.y == who->GetY()))
- {
+ if (!(currentNode.pos.x == who->GetX() && currentNode.pos.y == who->GetY())) {
//if one of the nodes to move to, is not our current node, pass it.
noValidPath = false;
break;
@@ -847,47 +996,62 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z,
}
- if (noValidPath)
- {
+ if (noValidPath) {
//we are 'stuck' in a path, lets just get out of this by 'teleporting' to the next position.
- PushTeleportTo(ent.second, x, y, z,
- CalculateHeadingAngleBetweenPositions(who->GetX(), who->GetY(), x, y));
+ PushTeleportTo(
+ ent.second,
+ x,
+ y,
+ z,
+ CalculateHeadingAngleBetweenPositions(who->GetX(), who->GetY(), x, y)
+ );
+
return;
}
}
-
+
auto iter = route.begin();
+
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
+
bool first_node = true;
-
-
while (iter != route.end()) {
auto ¤t_node = (*iter);
-
+
iter++;
-
+
if (iter == route.end()) {
continue;
}
-
+
previous_pos = current_node.pos;
auto &next_node = (*iter);
-
+
if (first_node) {
-
+
if (mode == MovementWalking) {
auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y);
PushRotateTo(ent.second, who, h, mode);
}
-
+
first_node = false;
}
-
+
//move to / teleport to node + 1
if (next_node.teleport && next_node.pos.x != 0.0f && next_node.pos.y != 0.0f) {
- PushTeleportTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z,
- CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.y));
+ PushTeleportTo(
+ ent.second,
+ next_node.pos.x,
+ next_node.pos.y,
+ next_node.pos.z,
+ CalculateHeadingAngleBetweenPositions(
+ current_node.pos.x,
+ current_node.pos.y,
+ next_node.pos.x,
+ next_node.pos.y
+ )
+ );
}
else {
if (zone->watermap->InLiquid(previous_pos)) {
@@ -907,41 +1071,50 @@ void MobMovementManager::UpdatePathGround(Mob * who, float x, float y, float z,
}
}
-void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param movement_mode
+ */
+void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode)
{
auto eiter = _impl->Entries.find(who);
- auto &ent = (*eiter);
- if (zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) && zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) {
- PushSwimTo(ent.second, x, y, z, mode);
+ auto &ent = (*eiter);
+ if (zone->watermap->InLiquid(who->GetPosition()) && zone->watermap->InLiquid(glm::vec3(x, y, z)) &&
+ zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) {
+ PushSwimTo(ent.second, x, y, z, movement_mode);
PushStopMoving(ent.second);
return;
}
PathfinderOptions opts;
opts.smooth_path = true;
- opts.step_size = RuleR(Pathing, NavmeshStepSize);
- opts.offset = who->GetZOffset();
- opts.flags = PathingNotDisabled ^ PathingZoneLine;
+ opts.step_size = RuleR(Pathing, NavmeshStepSize);
+ opts.offset = who->GetZOffset();
+ opts.flags = PathingNotDisabled ^ PathingZoneLine;
auto partial = false;
- auto stuck = false;
- auto route = zone->pathing->FindPath(
+ auto stuck = false;
+ auto route = zone->pathing->FindPath(
glm::vec3(who->GetX(), who->GetY(), who->GetZ()),
glm::vec3(x, y, z),
partial,
stuck,
- opts);
+ opts
+ );
if (route.size() == 0) {
- HandleStuckBehavior(who, x, y, z, mode);
+ HandleStuckBehavior(who, x, y, z, movement_mode);
return;
}
AdjustRoute(route, who);
- auto iter = route.begin();
+ auto iter = route.begin();
glm::vec3 previous_pos(who->GetX(), who->GetY(), who->GetZ());
- bool first_node = true;
+ bool first_node = true;
while (iter != route.end()) {
auto ¤t_node = (*iter);
@@ -961,7 +1134,7 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float
}
if (route.size() == 0) {
- HandleStuckBehavior(who, x, y, z, mode);
+ HandleStuckBehavior(who, x, y, z, movement_mode);
return;
}
@@ -981,9 +1154,9 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float
if (first_node) {
- if (mode == MovementWalking) {
+ if (movement_mode == MovementWalking) {
auto h = who->CalculateHeadingToTarget(next_node.pos.x, next_node.pos.y);
- PushRotateTo(ent.second, who, h, mode);
+ PushRotateTo(ent.second, who, h, movement_mode);
}
first_node = false;
@@ -991,47 +1164,87 @@ void MobMovementManager::UpdatePathUnderwater(Mob *who, float x, float y, float
//move to / teleport to node + 1
if (next_node.teleport && next_node.pos.x != 0.0f && next_node.pos.y != 0.0f) {
- PushTeleportTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z,
- CalculateHeadingAngleBetweenPositions(current_node.pos.x, current_node.pos.y, next_node.pos.x, next_node.pos.y));
+ PushTeleportTo(
+ ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z,
+ CalculateHeadingAngleBetweenPositions(
+ current_node.pos.x,
+ current_node.pos.y,
+ next_node.pos.x,
+ next_node.pos.y
+ ));
}
else {
- PushSwimTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, mode);
+ PushSwimTo(ent.second, next_node.pos.x, next_node.pos.y, next_node.pos.z, movement_mode);
}
}
if (stuck) {
- HandleStuckBehavior(who, x, y, z, mode);
+ HandleStuckBehavior(who, x, y, z, movement_mode);
}
else {
PushStopMoving(ent.second);
}
}
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param mode
+ */
void MobMovementManager::UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode)
{
auto eiter = _impl->Entries.find(who);
- auto &ent = (*eiter);
+ auto &ent = (*eiter);
PushSwimTo(ent.second, x, y, z, mode);
PushStopMoving(ent.second);
}
+/**
+ * @param ent
+ * @param x
+ * @param y
+ * @param z
+ * @param heading
+ */
void MobMovementManager::PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading)
{
ent.Commands.push_back(std::unique_ptr(new TeleportToCommand(x, y, z, heading)));
}
-void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param ent
+ * @param x
+ * @param y
+ * @param z
+ * @param mob_movement_mode
+ */
+void MobMovementManager::PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode)
{
- ent.Commands.push_back(std::unique_ptr(new MoveToCommand(x, y, z, mode)));
+ ent.Commands.push_back(std::unique_ptr(new MoveToCommand(x, y, z, mob_movement_mode)));
}
-void MobMovementManager::PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param ent
+ * @param x
+ * @param y
+ * @param z
+ * @param mob_movement_mode
+ */
+void MobMovementManager::PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode)
{
- ent.Commands.push_back(std::unique_ptr(new SwimToCommand(x, y, z, mode)));
+ ent.Commands.push_back(std::unique_ptr(new SwimToCommand(x, y, z, mob_movement_mode)));
}
-void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode)
+/**
+ * @param ent
+ * @param who
+ * @param to
+ * @param mob_movement_mode
+ */
+void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode)
{
auto from = FixHeading(who->GetHeading());
to = FixHeading(to);
@@ -1050,46 +1263,59 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to,
diff -= 512.0;
}
- ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mode)));
+ ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mob_movement_mode)));
}
-void MobMovementManager::PushStopMoving(MobMovementEntry &ent)
+/**
+ * @param mob_movement_entry
+ */
+void MobMovementManager::PushStopMoving(MobMovementEntry &mob_movement_entry)
{
- ent.Commands.push_back(std::unique_ptr(new StopMovingCommand()));
+ mob_movement_entry.Commands.push_back(std::unique_ptr(new StopMovingCommand()));
}
-void MobMovementManager::PushEvadeCombat(MobMovementEntry &ent)
+/**
+ * @param mob_movement_entry
+ */
+void MobMovementManager::PushEvadeCombat(MobMovementEntry &mob_movement_entry)
{
- ent.Commands.push_back(std::unique_ptr(new EvadeCombatCommand()));
+ mob_movement_entry.Commands.push_back(std::unique_ptr(new EvadeCombatCommand()));
}
-void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode)
+/**
+ * @param who
+ * @param x
+ * @param y
+ * @param z
+ * @param mob_movement_mode
+ */
+void MobMovementManager::HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode)
{
- auto sb = who->GetStuckBehavior();
+ auto sb = who->GetStuckBehavior();
MobStuckBehavior behavior = RunToTarget;
if (sb >= 0 && sb < MaxStuckBehavior) {
- behavior = (MobStuckBehavior)sb;
+ behavior = (MobStuckBehavior) sb;
}
auto eiter = _impl->Entries.find(who);
- auto &ent = (*eiter);
+ auto &ent = (*eiter);
switch (sb) {
- case RunToTarget:
- PushMoveTo(ent.second, x, y, z, mode);
- PushStopMoving(ent.second);
- break;
- case WarpToTarget:
- PushTeleportTo(ent.second, x, y, z, 0.0f);
- PushStopMoving(ent.second);
- break;
- case TakeNoAction:
- PushStopMoving(ent.second);
- break;
- case EvadeCombat:
- //PushEvadeCombat(ent.second);
- PushStopMoving(ent.second);
- break;
+ case RunToTarget:
+ PushMoveTo(ent.second, x, y, z, mob_movement_mode);
+ PushStopMoving(ent.second);
+ break;
+ case WarpToTarget:
+ PushTeleportTo(ent.second, x, y, z, 0.0f);
+ PushStopMoving(ent.second);
+ break;
+ case TakeNoAction:
+ PushStopMoving(ent.second);
+ break;
+ case EvadeCombat:
+ //PushEvadeCombat(ent.second);
+ PushStopMoving(ent.second);
+ break;
}
}
diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h
index d9b2e7845..3c616cc5a 100644
--- a/zone/mob_movement_manager.h
+++ b/zone/mob_movement_manager.h
@@ -41,18 +41,29 @@ class MobMovementManager
public:
~MobMovementManager();
void Process();
- void AddMob(Mob *m);
- void RemoveMob(Mob *m);
- void AddClient(Client *c);
- void RemoveClient(Client *c);
+ void AddMob(Mob *mob);
+ void RemoveMob(Mob *mob);
+ void AddClient(Client *client);
+ 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 NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
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);
- void DumpStats(Client *to);
+ void DumpStats(Client *client);
void ClearStats();
static MobMovementManager &Get() {
@@ -65,18 +76,18 @@ private:
MobMovementManager(const MobMovementManager&);
MobMovementManager& operator=(const MobMovementManager&);
- void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
- void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
+ 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 mob_movement_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 PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
- void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
- void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
- void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode);
- void PushStopMoving(MobMovementEntry &ent);
- void PushEvadeCombat(MobMovementEntry &ent);
- void HandleStuckBehavior(Mob *who, 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 mob_movement_mode);
+ void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
+ void PushStopMoving(MobMovementEntry &mob_movement_entry);
+ void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
+ void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
struct Implementation;
std::unique_ptr _impl;
diff --git a/zone/spells.cpp b/zone/spells.cpp
index 8b1a08d19..fa09727a2 100644
--- a/zone/spells.cpp
+++ b/zone/spells.cpp
@@ -298,7 +298,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
if(IsClient()) {
char temp[64];
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()) {
char temp[64];
sprintf(temp, "%d", spell_id);
diff --git a/zone/zone.cpp b/zone/zone.cpp
index 2121642bb..d20b2934e 100755
--- a/zone/zone.cpp
+++ b/zone/zone.cpp
@@ -55,6 +55,7 @@
#include "zone_config.h"
#include "mob_movement_manager.h"
#include "npc_scale_manager.h"
+#include "../common/data_verification.h"
#include
#include
@@ -864,6 +865,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
m_last_ucss_update = 0;
mMovementManager = &MobMovementManager::Get();
+
+ SetNpcPositionUpdateDistance(0);
}
Zone::~Zone() {
@@ -1194,9 +1197,9 @@ uint32 Zone::CountAuth() {
bool Zone::Process() {
spawn_conditions.Process();
- if(spawn2_timer.Check()) {
+ if (spawn2_timer.Check()) {
- LinkedListIterator iterator(spawn2_list);
+ LinkedListIterator iterator(spawn2_list);
EQEmu::InventoryProfile::CleanDirty();
@@ -1212,10 +1215,15 @@ bool Zone::Process() {
}
}
- if(adv_data && !did_adventure_actions)
+ if (adv_data && !did_adventure_actions) {
DoAdventureActions();
+ }
+ if (GetNpcPositionUpdateDistance() == 0) {
+ CalculateNpcUpdateDistanceSpread();
+ }
}
+
if(initgrids_timer.Check()) {
//delayed grid loading stuff.
initgrids_timer.Disable();
@@ -2365,3 +2373,59 @@ void Zone::SetUCSServerAvailable(bool ucss_available, uint32 update_timestamp) {
if (m_last_ucss_update < update_timestamp)
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
+ );
+}
\ No newline at end of file
diff --git a/zone/zone.h b/zone/zone.h
index a7de25ab4..176fe0cb3 100755
--- a/zone/zone.h
+++ b/zone/zone.h
@@ -126,6 +126,9 @@ public:
bool Process();
bool SaveZoneCFG();
+ int GetNpcPositionUpdateDistance() const;
+ void SetNpcPositionUpdateDistance(int in_npc_position_update_distance);
+
char *adv_data;
const char *GetSpellBlockedMessage(uint32 spell_id, const glm::vec3 &location);
@@ -219,6 +222,7 @@ public:
void ChangeWeather();
void ClearBlockedSpells();
void ClearNPCTypeCache(int id);
+ void CalculateNpcUpdateDistanceSpread();
void DelAggroMob() { aggroedmobs--; }
void DeleteQGlobal(std::string name, uint32 npcID, uint32 charID, uint32 zoneID);
void Despawn(uint32 spawngroupID);
@@ -290,7 +294,7 @@ public:
*/
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');
entity_list.MessageStatus(
0,
@@ -345,6 +349,7 @@ private:
glm::vec4 m_Graveyard;
int default_ruleset;
int totalBS;
+ int npc_position_update_distance;
int32 aggroedmobs;
uint8 zone_type;
uint16 instanceversion;