From 5989edb6ecb01c83edddbc2dc0a4d9546930163d Mon Sep 17 00:00:00 2001 From: Noudess Date: Tue, 21 Apr 2020 09:09:30 -0400 Subject: [PATCH 1/8] Fix for static zone issue with mobs congregating after last player zones --- common/ruletypes.h | 1 + zone/entity.cpp | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 2f5b9f246..f4ca7c2d9 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -280,6 +280,7 @@ RULE_BOOL(Zone, UseZoneController, true, "Enables the ability to use persistent RULE_BOOL(Zone, EnableZoneControllerGlobals, false, "Enables the ability to use quest globals with the zone controller NPC") RULE_INT(Zone, GlobalLootMultiplier, 1, "Sets Global Loot drop multiplier for database based drops, useful for double, triple loot etc") RULE_BOOL(Zone, KillProcessOnDynamicShutdown, true, "When process has booted a zone and has hit its zone shut down timer, it will hard kill the process to free memory back to the OS") +RULE_INT(Zone, SecondsBeforeIdle, 60, "Seconds before IDLE_WHEN_EMPTY define kicks in") RULE_CATEGORY_END() RULE_CATEGORY(Map) diff --git a/zone/entity.cpp b/zone/entity.cpp index 23ff268fc..0441aac48 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -498,11 +498,30 @@ void EntityList::MobProcess() size_t sz = mob_list.size(); #ifdef IDLE_WHEN_EMPTY + static int old_client_count=0; + static Timer *mob_settle_timer = new Timer(); + + if (numclients == 0 && old_client_count > 0 && + RuleI(Zone, SecondsBeforeIdle) > 0) { + // Start Timer to allow any mobs that chased chars from zone + // to return home. + mob_settle_timer->Start(RuleI(Zone, SecondsBeforeIdle) * 1000); + } + + old_client_count = numclients; + + // Disable settle timer if someone zones into empty zone + if (numclients > 0 || mob_settle_timer->Check()) { + mob_settle_timer->Disable(); + } + if (numclients > 0 || - mob->GetWanderType() == 4 || mob->GetWanderType() == 6) { + mob->GetWanderType() == 4 || mob->GetWanderType() == 6 || + mob_settle_timer->Enabled()) { // Normal processing, or assuring that spawns that should // path and depop do that. Otherwise all of these type mobs - // will be up and at starting positions when idle zone wakes up. + // will be up and at starting positions, or waiting at the zoneline + // if they chased the PCs when idle zone wakes up. mob_dead = !mob->Process(); } else { From 2bcaf2a476913bb6407e6c887b169f4214d53f5a Mon Sep 17 00:00:00 2001 From: Noudess Date: Thu, 30 Apr 2020 11:35:09 -0400 Subject: [PATCH 2/8] Extended Movement Manager to have a FlyTo --- zone/mob_movement_manager.cpp | 164 ++++++++++++++++++++++++++++++++++ zone/mob_movement_manager.h | 1 + 2 files changed, 165 insertions(+) diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 4ac0c7f23..904bc5246 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -263,6 +263,146 @@ protected: double m_total_v_dist; }; +class FlyToCommand : public IMovementCommand { +public: + FlyToCommand(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 = 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 ~FlyToCommand() + { + + } + + /** + * @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; + + if (m_move_to_mode == MovementRunning) { + if (mob->IsFeared()) { + current_speed = mob->GetFearSpeed(); + } + else { + current_speed = mob->GetRunspeed(); + } + } + else { + current_speed = mob->GetWalkspeed(); + } + + if (!m_started) { + m_started = true; + //rotate to the point + 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(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_distance_moved_since_correction = 0.0; + m_last_sent_speed = current_speed; + 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 >= 0.5) { + m_distance_moved_since_correction = 0.0; + m_last_sent_speed = current_speed; + m_last_sent_time = current_time; + mob_movement_manager->SendCommandToClients(mob, 0.0, 0.0, 0.0, 0.0, current_speed, ClientRangeCloseMedium); + } + + 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); + if (len == 0) { + return 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; + + if (distance_moved > len) { + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), 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)) { + 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)); + + if (mob->IsNPC()) { + entity_list.ProcessMove(mob->CastToNPC(), npos.x, npos.y, z_at_pos); + } + + mob->SetPosition(npos.x, npos.y, z_at_pos); + } + + return false; + } + + 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; + MobMovementMode m_move_to_mode; + bool m_started; + + double m_last_sent_time; + int m_last_sent_speed; + double m_total_h_dist; + double m_total_v_dist; +}; + class SwimToCommand : public MoveToCommand { public: SwimToCommand(float x, float y, float z, MobMovementMode mob_movement_mode) : MoveToCommand(x, y, z, mob_movement_mode) @@ -921,6 +1061,8 @@ void MobMovementManager::FillCommandStruct( */ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode) { + Mob *target=who->GetTarget(); + if (!zone->HasMap() || !zone->HasWaterMap()) { auto iter = _impl->Entries.find(who); auto &ent = (*iter); @@ -936,6 +1078,16 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove else if (who->IsUnderwaterOnly()) { UpdatePathUnderwater(who, x, y, z, mob_movement_mode); } + // If we can fly, and we have a target and we have LoS, simply fly to them. + // if we ever lose LoS we go back to mesh run mode. + else if (target && who->GetFlyMode() == GravityBehavior::Flying && + who->CheckLosFN(x,y,z,target->GetSize())) { + auto iter = _impl->Entries.find(who); + auto &ent = (*iter); + + PushFlyTo(ent.second, x, y, z, mob_movement_mode); + PushStopMoving(ent.second); + } else { UpdatePathGround(who, x, y, z, mob_movement_mode); } @@ -1275,6 +1427,18 @@ void MobMovementManager::PushRotateTo(MobMovementEntry &ent, Mob *who, float to, ent.Commands.push_back(std::unique_ptr(new RotateToCommand(to, diff > 0 ? 1.0 : -1.0, mob_movement_mode))); } +/** + * @param ent + * @param x + * @param y + * @param z + * @param mob_movement_mode + */ +void MobMovementManager::PushFlyTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode) +{ + ent.Commands.push_back(std::unique_ptr(new FlyToCommand(x, y, z, mob_movement_mode))); +} + /** * @param mob_movement_entry */ diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h index ff7e08436..85d062804 100644 --- a/zone/mob_movement_manager.h +++ b/zone/mob_movement_manager.h @@ -85,6 +85,7 @@ private: void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading); 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 PushFlyTo(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); From 263ed3913b94aebfc9ac6ce959e43c469bf3b959 Mon Sep 17 00:00:00 2001 From: = <=isaacseniorx@gmail.com> Date: Wed, 6 May 2020 02:44:17 +0000 Subject: [PATCH 3/8] Don't scale 0 values --- zone/npc.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 39b1b046b..edc9f88c3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2443,18 +2443,27 @@ void NPC::LevelScale() { if (RuleB(NPC, NewLevelScaling)) { if (scalerate == 0 || maxlevel <= 25) { - // pre-pop seems to scale by 20 HP increments while newer by 100 - // We also don't want 100 increments on newer noobie zones, check level - if (zone->GetZoneID() < 200 || level < 48) { - max_hp += (random_level - level) * 20; - base_hp += (random_level - level) * 20; - } else { - max_hp += (random_level - level) * 100; - base_hp += (random_level - level) * 100; + // Don't add HP to dynamically scaled NPCs since this will be calculated later + if (max_hp > 0 || skip_auto_scale) + { + // pre-pop seems to scale by 20 HP increments while newer by 100 + // We also don't want 100 increments on newer noobie zones, check level + if (zone->GetZoneID() < 200 || level < 48) { + max_hp += (random_level - level) * 20; + base_hp += (random_level - level) * 20; + } else { + max_hp += (random_level - level) * 100; + base_hp += (random_level - level) * 100; + } + + current_hp = max_hp; + } + + // Don't add max_dmg to dynamically scaled NPCs since this will be calculated later + if (max_dmg > 0 || skip_auto_scale) + { + max_dmg += (random_level - level) * 2; } - - current_hp = max_hp; - max_dmg += (random_level - level) * 2; } else { uint8 scale_adjust = 1; From 0a42ded33f51bef4126fdeefe9be8a7810535ef7 Mon Sep 17 00:00:00 2001 From: Noudess Date: Fri, 8 May 2020 09:58:53 -0400 Subject: [PATCH 4/8] Expose client method NotifyNewTitlesAvailable for perl and lua --- zone/lua_client.cpp | 6 ++++++ zone/lua_client.h | 1 + zone/perl_client.cpp | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 955130922..e161c5e20 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1210,6 +1210,11 @@ void Lua_Client::OpenLFGuildWindow() { self->OpenLFGuildWindow(); } +void Lua_Client::NotifyNewTitlesAvailable() { + Lua_Safe_Call_Void(); + self->NotifyNewTitlesAvailable(); +} + void Lua_Client::Signal(uint32 id) { Lua_Safe_Call_Void(); self->Signal(id); @@ -1820,6 +1825,7 @@ luabind::scope lua_register_client() { .def("GetAllMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetAllMoney) .def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney) .def("OpenLFGuildWindow", (void(Lua_Client::*)(void))&Lua_Client::OpenLFGuildWindow) + .def("NotifyNewTitlesAvailable", (void(Lua_Client::*)(void))&Lua_Client::NotifyNewTitlesAvailable) .def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal) .def("AddAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddAlternateCurrencyValue) .def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::SetAlternateCurrencyValue) diff --git a/zone/lua_client.h b/zone/lua_client.h index b0eb719e8..600b594f2 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -269,6 +269,7 @@ public: uint64 GetAllMoney(); uint32 GetMoney(uint8 type, uint8 subtype); void OpenLFGuildWindow(); + void NotifyNewTitlesAvailable(); void Signal(uint32 id); void AddAlternateCurrencyValue(uint32 currency, int amount); void SetAlternateCurrencyValue(uint32 currency, int amount); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index e46b5e8d4..66cf78084 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5522,6 +5522,27 @@ XS(XS_Client_OpenLFGuildWindow) { XSRETURN_EMPTY; } +XS(XS_NotifyNewTitlesAvailable); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_NotifyNewTitlesAvailable) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::NotifyNewTitlesAvailable(THIS)"); + { + Client *THIS; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV *) SvRV(ST(0))); + THIS = INT2PTR(Client *, tmp); + } else + Perl_croak(aTHX_ "THIS is not of type Client"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + THIS->NotifyNewTitlesAvailable(); + } + XSRETURN_EMPTY; +} + XS(XS_Client_SignalClient); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_SignalClient) { dXSARGS; @@ -6568,6 +6589,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "NPCSpawn"), XS_Client_NPCSpawn, file, "$$$;$"); newXSproto(strcpy(buf, "NukeItem"), XS_Client_NukeItem, file, "$$;$"); newXSproto(strcpy(buf, "OpenLFGuildWindow"), XS_Client_OpenLFGuildWindow, file, "$"); + newXSproto(strcpy(buf, "NotifyNewTitlesAvailable"), XS_Client_NotifyNewTitlesAvailable, file, "$"); newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$"); newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$"); newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$"); From 572ad1b6ab4ecca91cd04eea1f5e4396562e3463 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 8 May 2020 12:56:10 -0400 Subject: [PATCH 5/8] Identify SubType in Item structs in some clients This maybe in older clients as well, but I couldn't verify it and those clients never did anything with this field so it doesn't matter. MQ2 calls this SubClass, but we call the field it's a "sub" of Type so I figured we'd call it SubType. We still need to rename the DB field and handle it server side etc --- common/patches/rof2_structs.h | 4 ++-- common/patches/rof_structs.h | 4 ++-- common/patches/uf_structs.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 10ce35654..92021c283 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4804,8 +4804,8 @@ struct ItemQuaternaryBodyStruct int32 HealAmt; int32 SpellDmg; int32 Clairvoyance; - uint8 unknown18; //Power Source Capacity or evolve filename? - uint32 evolve_string; // Some String, but being evolution related is just a guess + int32 SubType; + uint8 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; uint16 unknown20; uint8 unknown21; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 03f1a951a..bdf416724 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -4744,8 +4744,8 @@ struct ItemQuaternaryBodyStruct int32 HealAmt; int32 SpellDmg; int32 Clairvoyance; - uint8 unknown18; //Power Source Capacity or evolve filename? - uint32 evolve_string; // Some String, but being evolution related is just a guess + int32 SubType; + uint8 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; uint32 unknown20; // Bard Stuff? //uint32 unknown21; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index b6eb414e1..3a66e2a88 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -4215,8 +4215,8 @@ struct ItemQuaternaryBodyStruct int32 HealAmt; int32 SpellDmg; int32 Clairvoyance; - uint8 unknown18; //Power Source Capacity or evolve filename? - uint32 evolve_string; // Some String, but being evolution related is just a guess + int32 SubType; + uint8 evolve_string; // Some String, but being evolution related is just a guess uint8 unknown19; uint32 unknown20; // Bard Stuff? uint32 unknown21; From 5471774b4c677268ecd83aae6ad2ab8c6f134cc2 Mon Sep 17 00:00:00 2001 From: Noudess Date: Fri, 8 May 2020 18:24:25 -0400 Subject: [PATCH 6/8] Repair prototype --- zone/perl_client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 66cf78084..1c0c42bf5 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5522,7 +5522,7 @@ XS(XS_Client_OpenLFGuildWindow) { XSRETURN_EMPTY; } -XS(XS_NotifyNewTitlesAvailable); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_NotifyNewTitlesAvailable); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_NotifyNewTitlesAvailable) { dXSARGS; if (items != 1) From 914ea274066b4437dc3c2058e06284c6a9e13d42 Mon Sep 17 00:00:00 2001 From: Jose123456 Date: Sat, 9 May 2020 12:40:33 -0700 Subject: [PATCH 7/8] Compile on Freebsd (#1044) * Compile on Freebsd Small changes needed for compilation on Freebsd. Note that you'll have to pass -DEQEMU_BUILD_ZLIB=OFF on the cmake command line. The bundled zlib-ng does not build on Freebsd even though mainline zlib-ng does. * Fix build errors: typo --- CMakeLists.txt | 5 ++++- common/crash.cpp | 5 +++++ common/proc_launcher.h | 4 ++++ common/util/uuid.cpp | 13 +++++++++++++ zone/main.cpp | 8 +++++++- 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b12e2ee1..c164cfba4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,7 +328,10 @@ IF(UNIX) IF(NOT DARWIN) SET(SERVER_LIBS ${SERVER_LIBS} "rt") ENDIF() - SET(SERVER_LIBS ${SERVER_LIBS} "uuid") + # Freebsd provides uuids in the C library + IF(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + SET(SERVER_LIBS ${SERVER_LIBS} "uuid") + ENDIF() ENDIF() IF(EQEMU_BUILD_LOGIN AND NOT TLS_LIBRARY_ENABLED) diff --git a/common/crash.cpp b/common/crash.cpp index 155bfcf2a..cecb52f02 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -118,6 +118,11 @@ void set_exception_handler() { #include #include +#ifdef __FreeBSD__ +#include +#include +#endif + void print_trace() { auto uid = geteuid(); diff --git a/common/proc_launcher.h b/common/proc_launcher.h index 6289579cd..23b7e523c 100644 --- a/common/proc_launcher.h +++ b/common/proc_launcher.h @@ -24,6 +24,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + //I forced this object to become a singleton because it registers its //signal handler for UNIX class ProcLauncher { diff --git a/common/util/uuid.cpp b/common/util/uuid.cpp index c5b6b9a4d..633ffebaf 100644 --- a/common/util/uuid.cpp +++ b/common/util/uuid.cpp @@ -14,6 +14,10 @@ #include #endif +#ifdef __FreeBSD__ +#include +#endif + unsigned char hexDigitToChar(char ch) { if (ch > 47 && ch < 58) @@ -126,6 +130,15 @@ EQ::Util::UUID EQ::Util::UUID::Generate() return buffer; #endif + +#ifdef __FreeBSD__ + uuid_t l_id; + char l_uuid[37]; + uint32_t l_ignored; + uuid_create(&l_id, &l_ignored); + uuid_to_string(&l_id, (char**) &l_uuid, &l_ignored); + return FromString(l_uuid); +#endif } EQ::Util::UUID EQ::Util::UUID::FromString(const std::string &str) diff --git a/zone/main.cpp b/zone/main.cpp index 0445534d4..364df32b9 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -92,6 +92,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/unix.h" #endif +#ifdef __FreeBSD__ +#include +#endif + extern volatile bool is_zone_loaded; EntityList entity_list; @@ -431,8 +435,10 @@ int main(int argc, char** argv) { EQStreamIdentifier stream_identifier; RegisterAllPatches(stream_identifier); -#ifndef WIN32 +#ifdef __linux__ LogDebug("Main thread running with thread id [{}]", pthread_self()); +#elif defined(__FreeBSD__) + LogDebug("Main thread running with thread id [{}]", pthread_getthreadid_np()); #endif bool worldwasconnected = worldserver.Connected(); From 857b24727c96cbf15d4f66292f1f53674e827c57 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 10 May 2020 16:52:33 -0400 Subject: [PATCH 8/8] Add CrossZoneMessagePlayerByGuildID() to Perl/Lua. --- common/servertalk.h | 7 +++++++ world/zoneserver.cpp | 1 + zone/embparser_api.cpp | 18 ++++++++++++++++++ zone/lua_general.cpp | 5 +++++ zone/questmgr.cpp | 11 +++++++++++ zone/questmgr.h | 1 + zone/worldserver.cpp | 11 +++++++++++ 7 files changed, 54 insertions(+) diff --git a/common/servertalk.h b/common/servertalk.h index 032df1ddc..318e0cf06 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -198,6 +198,7 @@ #define ServerOP_UCSServerStatusRequest 0x4013 #define ServerOP_UCSServerStatusReply 0x4014 #define ServerOP_HotReloadQuests 0x4015 +#define ServerOP_CZMessageGuild 0x4021 /** * QueryServer @@ -1334,6 +1335,12 @@ struct CZMessagePlayer_Struct { char Message[512]; }; +struct CZMessageGuild_Struct { + uint32 Type; + int GuildID; + char Message[512]; +}; + struct WWMarquee_Struct { uint32 Type; uint32 Priority; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index 08ccbfaff..3f1c8eae0 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1238,6 +1238,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { } case ServerOP_CZSignalClientByName: case ServerOP_CZMessagePlayer: + case ServerOP_CZMessageGuild: case ServerOP_CZSignalNPC: case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index c65cd204c..55ca42c00 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3757,6 +3757,23 @@ XS(XS__crosszonemessageplayerbyname) { XSRETURN_EMPTY; } +XS(XS__crosszonemessageplayerbyguildid); +XS(XS__crosszonemessageplayerbyguildid) { + dXSARGS; + + if (items != 3) + Perl_croak(aTHX_ "Usage: quest::crosszonemessageplayerbyguildid(int typ, int guild_id, string message)"); + + if (items == 3) { + uint32 type = (uint32) SvIV(ST(0)); + int guild_id = (int) SvIV(ST(1)); + char *message = (char *) SvPV_nolen(ST(2)); + quest_manager.CrossZoneMessagePlayerByGuildID(type, guild_id, message); + } + + XSRETURN_EMPTY; +} + XS(XS__enablerecipe); XS(XS__enablerecipe) { dXSARGS; @@ -4173,6 +4190,7 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "creategroundobjectfrommodel"), XS__CreateGroundObjectFromModel, file); newXS(strcpy(buf, "createguild"), XS__createguild, file); newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file); + newXS(strcpy(buf, "crosszonemessageplayerbyguildid"), XS__crosszonemessageplayerbyguildid, file); newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file); newXS(strcpy(buf, "crosszonesetentityvariablebyclientname"), XS__crosszonesetentityvariablebyclientname, file); newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index d047238de..ee3318f31 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1034,6 +1034,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons quest_manager.CrossZoneMessagePlayerByName(type, player, message); } +void lua_cross_zone_message_player_by_guild_id(uint32 type, int guild_id, const char *message) { + quest_manager.CrossZoneMessagePlayerByGuildID(type, guild_id, message); +} + void lua_cross_zone_set_entity_variable_by_client_name(const char *player, const char *id, const char *m_var) { quest_manager.CrossZoneSetEntityVariableByClientName(player, id, m_var); } @@ -1841,6 +1845,7 @@ luabind::scope lua_register_general() { luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id), luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name), luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name), + luabind::def("cross_zone_message_player_by_guild_id", &lua_cross_zone_message_player_by_guild_id), luabind::def("cross_zone_set_entity_variable_by_client_name", &lua_cross_zone_set_entity_variable_by_client_name), luabind::def("world_wide_marquee", &lua_world_wide_marquee), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals), diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index ba6a5340c..38e6c808c 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3234,6 +3234,17 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam safe_delete(pack); } +void QuestManager::CrossZoneMessagePlayerByGuildID(uint32 Type, int GuildID, const char *Message){ + uint32 message_len = strlen(Message) + 1; + auto pack = new ServerPacket(ServerOP_CZMessageGuild, sizeof(CZMessageGuild_Struct) + message_len); + CZMessageGuild_Struct* CZGM = (CZMessageGuild_Struct*) pack->pBuffer; + CZGM->Type = Type; + CZGM->GuildID = GuildID; + strn0cpy(CZGM->Message, Message, 512); + worldserver.SendPacket(pack); + safe_delete(pack); +} + void QuestManager::CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var){ uint32 message_len = strlen(id) + 1; uint32 message_len2 = strlen(m_var) + 1; diff --git a/zone/questmgr.h b/zone/questmgr.h index 14ddea9c8..15c46f694 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -284,6 +284,7 @@ public: void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var); void CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var); void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message); + void CrossZoneMessagePlayerByGuildID(uint32 Type, int GuildID, const char *Message); void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 4b2034067..46bac74ed 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1933,6 +1933,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } break; } + case ServerOP_CZMessageGuild: + { + CZMessageGuild_Struct* CZGM = (CZMessageGuild_Struct*)pack->pBuffer; + auto client_list = entity_list.GetClientList(); + for (auto client : client_list) { + if (client.second->GuildID() > 0 && client.second->GuildID() == CZGM->GuildID) { + client.second->Message(CZGM->Type, CZGM->Message); + } + } + break; + } case ServerOP_CZSetEntityVariableByClientName: { CZSetEntVarByClientName_Struct* CZCS = (CZSetEntVarByClientName_Struct*)pack->pBuffer;