diff --git a/common/database_schema.h b/common/database_schema.h index e92b7619a..de6f8472f 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -80,7 +80,7 @@ namespace DatabaseSchema { {"guild_members", "char_id"}, {"guilds", "id"}, {"instance_list_player", "id"}, - {"inventory", "charid"}, + {"inventory", "character_id"}, {"inventory_snapshots", "charid"}, {"keyring", "char_id"}, {"mail", "charid"}, diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index bf20f6502..ef4d376e6 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -324,6 +324,7 @@ union bool guild_show; bool trader; bool buyer; + bool untargetable; }; struct PlayerState_Struct { diff --git a/common/evolving_items.cpp b/common/evolving_items.cpp index 2b7eb38c6..b74efc17b 100644 --- a/common/evolving_items.cpp +++ b/common/evolving_items.cpp @@ -54,6 +54,10 @@ double EvolvingItemsManager::CalculateProgression(const uint64 current_amount, c void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_id, const EQ::ItemInstance &inst) const { + if (!inst) { + return; + } + inst.SetEvolveEquipped(false); if (inst.IsEvolving() && slot_id <= EQ::invslot::EQUIPMENT_END && slot_id >= EQ::invslot::EQUIPMENT_BEGIN) { inst.SetEvolveEquipped(true); @@ -87,6 +91,10 @@ void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_ uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const { + if (!inst) { + return 0; + } + const auto start_iterator = std::ranges::find_if( evolving_items_manager.GetEvolvingItemsCache().cbegin(), evolving_items_manager.GetEvolvingItemsCache().cend(), @@ -116,6 +124,10 @@ uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const uint32 EvolvingItemsManager::GetNextEvolveItemID(const EQ::ItemInstance &inst) const { + if (!inst) { + return 0; + } + int8 const current_level = inst.GetEvolveLvl(); const auto iterator = std::ranges::find_if( @@ -191,6 +203,10 @@ uint64 EvolvingItemsManager::GetTotalEarnedXP(const EQ::ItemInstance &inst) EvolveGetNextItem EvolvingItemsManager::GetNextItemByXP(const EQ::ItemInstance &inst_in, const int64 in_xp) { EvolveGetNextItem ets{}; + if (!inst_in) { + return ets; + } + const auto evolve_items = GetEvolveIDItems(inst_in.GetEvolveLoreID()); uint32 max_transfer_level = 0; int64 xp = in_xp; @@ -235,6 +251,9 @@ EvolveTransfer EvolvingItemsManager::DetermineTransferResults( ) { EvolveTransfer ets{}; + if (!inst_from || !inst_to) { + return ets; + } auto evolving_details_inst_from = evolving_items_manager.GetEvolveItemDetails(inst_from.GetID()); auto evolving_details_inst_to = evolving_items_manager.GetEvolveItemDetails(inst_to.GetID()); @@ -295,6 +314,10 @@ uint32 EvolvingItemsManager::GetFirstItemInLoreGroupByItemID(const uint32 item_i void EvolvingItemsManager::LoadPlayerEvent(const EQ::ItemInstance &inst, PlayerEvent::EvolveItem &e) { + if (!inst) { + return; + } + e.item_id = inst.GetID(); e.item_name = inst.GetItem() ? inst.GetItem()->Name : std::string(); e.level = inst.GetEvolveLvl(); diff --git a/common/evolving_items.h b/common/evolving_items.h index 463b58493..56f7e4be8 100644 --- a/common/evolving_items.h +++ b/common/evolving_items.h @@ -53,11 +53,11 @@ public: ItemsEvolvingDetailsRepository::ItemsEvolvingDetails GetEvolveItemDetails(uint64 id); EvolveTransfer DetermineTransferResults(const EQ::ItemInstance& inst_from, const EQ::ItemInstance& inst_to); EvolveGetNextItem GetNextItemByXP(const EQ::ItemInstance &inst_in, int64 in_xp); - std::map& GetEvolvingItemsCache() { return evolving_items_cache; } + std::map& GetEvolvingItemsCache() { return m_evolving_items_cache; } std::vector GetEvolveIDItems(uint32 evolve_id); private: - std::map evolving_items_cache; + std::map m_evolving_items_cache; Database * m_db; Database * m_content_db; }; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 1cbbb5c5d..1fcfcf67a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4688,7 +4688,7 @@ namespace RoF2 Bitfields->linkdead = 0; Bitfields->showhelm = emu->showhelm; Bitfields->trader = emu->trader ? 1 : 0; - Bitfields->targetable = 1; + Bitfields->targetable = emu->NPC ? emu->untargetable : 1; Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->showname = ShowName; diff --git a/common/repositories/trader_repository.h b/common/repositories/trader_repository.h index b9b3929eb..0354d6437 100644 --- a/common/repositories/trader_repository.h +++ b/common/repositories/trader_repository.h @@ -75,7 +75,6 @@ public: "JOIN character_data AS c ON t.char_id = c.id " "ORDER BY t.char_zone_instance_id ASC " "LIMIT {}", - char_zone_instance_id, max_results) ); } diff --git a/utils/scripts/build/should-release/go.mod b/utils/scripts/build/should-release/go.mod index 63b519f8d..b74fc2889 100644 --- a/utils/scripts/build/should-release/go.mod +++ b/utils/scripts/build/should-release/go.mod @@ -10,7 +10,7 @@ require ( require ( github.com/golang/protobuf v1.3.2 // indirect github.com/google/go-querystring v1.1.0 // indirect - golang.org/x/crypto v0.35.0 // indirect - golang.org/x/net v0.36.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.38.0 // indirect google.golang.org/appengine v1.6.7 // indirect ) diff --git a/utils/scripts/build/should-release/go.sum b/utils/scripts/build/should-release/go.sum index d42bb936b..88fd4be02 100644 --- a/utils/scripts/build/should-release/go.sum +++ b/utils/scripts/build/should-release/go.sum @@ -10,12 +10,12 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= -golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/world/wguild_mgr.cpp b/world/wguild_mgr.cpp index 4bacceb32..3c7050ba8 100644 --- a/world/wguild_mgr.cpp +++ b/world/wguild_mgr.cpp @@ -91,7 +91,7 @@ void WorldGuildManager::ProcessZonePacket(ServerPacket *pack) { } //broadcast this packet to all zones. - zoneserver_list.SendPacketToZonesWithGuild(s->guild_id, pack); + zoneserver_list.SendPacketToBootedZones(pack); break; } diff --git a/zone/bot.cpp b/zone/bot.cpp index af6723181..294e49963 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -12009,7 +12009,7 @@ bool Bot::DoCombatPositioning(const CombatPositioningInput& input) } else if (IsTaunting() || HasTargetReflection()) { // Taunting/Aggro adjustments adjustment_needed = - is_too_close || + (IsTaunting() && is_too_close) || los_adjust || (is_melee && !input.front_mob); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 0fcaef114..42121b8ca 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -468,7 +468,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas bool available_flag = false; - !database.botdb.QueryNameAvailablity(bot_name, available_flag); + !database.botdb.QueryNameAvailability(bot_name, available_flag); if (!available_flag) { bot_owner->Message( diff --git a/zone/bot_commands/bot.cpp b/zone/bot_commands/bot.cpp index 9fd87a830..8a8c4a277 100644 --- a/zone/bot_commands/bot.cpp +++ b/zone/bot_commands/bot.cpp @@ -130,7 +130,7 @@ void bot_command_clone(Client *c, const Seperator *sep) bool available_flag = false; - !database.botdb.QueryNameAvailablity(bot_name, available_flag); + !database.botdb.QueryNameAvailability(bot_name, available_flag); if (!available_flag) { c->Message( diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 088b8bf35..70e535711 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -182,7 +182,7 @@ bool BotDatabase::LoadBotSpellCastingChances() return true; } -bool BotDatabase::QueryNameAvailablity(const std::string& bot_name, bool& available_flag) +bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& available_flag) { if ( bot_name.empty() || diff --git a/zone/bot_database.h b/zone/bot_database.h index 407050079..7dcdebc28 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -48,7 +48,7 @@ public: /* Bot functions */ - bool QueryNameAvailablity(const std::string& bot_name, bool& available_flag); + bool QueryNameAvailability(const std::string& bot_name, bool& available_flag); bool QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count); bool LoadBotsList(const uint32 owner_id, std::list& bots_list, bool by_account = false); diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index c77b2fd12..e1259c77f 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -92,6 +92,16 @@ void Client::ProcessEvolvingItem(const uint64 exp, const Mob *mob) continue; } + if (!evolving_items_manager.GetEvolvingItemsCache().contains(inst->GetID())) { + LogEvolveItem( + "Character ID {} has an evolving item that is not found in the db. Please check your " + "items_evolving_details table for item id {}", + CharacterID(), + inst->GetID() + ); + continue; + } + auto const type = evolving_items_manager.GetEvolvingItemsCache().at(inst->GetID()).type; auto const sub_type = evolving_items_manager.GetEvolvingItemsCache().at(inst->GetID()).sub_type; @@ -283,24 +293,31 @@ void Client::DoEvolveItemDisplayFinalResult(const EQApplicationPacket *app) } std::unique_ptr const inst(database.CreateItem(item_id)); + if (!inst) { + return; + } LogEvolveItemDetail( "Character ID [{}] requested to view final evolve item id [{}] for evolve item id [{}]", CharacterID(), item_id, - evolving_items_manager.GetFirstItemInLoreGroupByItemID(item_id)); + evolving_items_manager.GetFirstItemInLoreGroupByItemID(item_id) + ); inst->SetEvolveProgression(100); - if (inst) { - LogEvolveItemDetail( - "Sending final result for item id [{}] to Character ID [{}]", item_id, CharacterID()); - SendItemPacket(0, inst.get(), ItemPacketViewLink); - } + LogEvolveItemDetail( + "Sending final result for item id [{}] to Character ID [{}]", item_id, CharacterID() + ); + SendItemPacket(0, inst.get(), ItemPacketViewLink); } bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst) { + if (!inst) { + return false; + } + if (inst.GetEvolveProgression() < 100 || inst.GetEvolveLvl() == inst.GetMaxEvolveLvl()) { return false; } diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 37aafc84b..bd28c2518 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -8,6 +8,11 @@ extern WorldServer worldserver; void command_task(Client *c, const Seperator *sep) { + if (!RuleB(TaskSystem, EnableTaskSystem)) { + c->Message(Chat::White, "This command cannot be used while the Task system is disabled."); + return; + } + const int arguments = sep->argnum; if (!arguments) { c->Message(Chat::White, "Syntax: #task [subcommand]"); diff --git a/zone/guild_mgr.cpp b/zone/guild_mgr.cpp index ab96fb1fd..aa2d9fd70 100644 --- a/zone/guild_mgr.cpp +++ b/zone/guild_mgr.cpp @@ -406,6 +406,7 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack) c.second->SendGuildDeletePacket(s->guild_id); c.second->RefreshGuildInfo(); c.second->MessageString(Chat::Guild, GUILD_DISBANDED); + c.second->SendGuildList(); } } diff --git a/zone/mob.cpp b/zone/mob.cpp index b411197e6..3b27482e2 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1312,7 +1312,8 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.NPC = IsClient() ? 0 : 1; ns->spawn.IsMercenary = IsMerc() ? 1 : 0; ns->spawn.targetable_with_hotkey = no_target_hotkey ? 0 : 1; // opposite logic! - + ns->spawn.untargetable = IsTargetable(); + ns->spawn.petOwnerId = ownerid; ns->spawn.haircolor = haircolor; diff --git a/zone/parcels.cpp b/zone/parcels.cpp index 7d2c27429..54d6ad2c4 100644 --- a/zone/parcels.cpp +++ b/zone/parcels.cpp @@ -409,6 +409,13 @@ void Client::DoParcelSend(const Parcel_Struct *parcel_in) parcel_out.aug_slot_6 = augs.at(5); } + if (!inst->IsDroppable(true)) { + Message(Chat::Yellow, "Unable to send a parcel that is NO-DROP or contains a NO-DROP item."); + SendParcelAck(); + DoParcelCancel(); + return; + } + auto result = CharacterParcelsRepository::InsertOne(database, parcel_out); if (!result.id) { LogError( diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 86b4a9fee..b9807703e 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2786,7 +2786,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level std::string test_name = name; bool available_flag = false; - if (!database.botdb.QueryNameAvailablity(test_name, available_flag)) { + if (!database.botdb.QueryNameAvailability(test_name, available_flag)) { initiator->Message( Chat::White, fmt::format( diff --git a/zone/zone_save_state.cpp b/zone/zone_save_state.cpp index 3401bc5e0..187d94d00 100644 --- a/zone/zone_save_state.cpp +++ b/zone/zone_save_state.cpp @@ -517,7 +517,7 @@ bool Zone::LoadZoneState( new_spawn->SetStoredLocation(glm::vec4(s.x, s.y, s.z, s.heading)); - if (spawn_time_left == 0) { + if (spawn_time_left == 0 && s.npc_id > 0) { new_spawn->SetResumedNPCID(s.npc_id); new_spawn->SetResumedFromZoneSuspend(true); new_spawn->SetEntityVariables(GetVariablesDeserialized(s.entity_variables));