From bfa76eb1eaff9eac3defc4a95fb0923385c33ac1 Mon Sep 17 00:00:00 2001 From: Flibe-XI Date: Wed, 18 Feb 2026 22:24:38 -0500 Subject: [PATCH] Brigand chart: Make chests fishable --- scripts/globals/brigands_chart.lua | 2 + sql/npc_list.sql | 10 +-- src/map/utils/fishingutils.cpp | 98 +++++++++++++++++++++--------- src/map/utils/fishingutils.h | 2 + 4 files changed, 79 insertions(+), 33 deletions(-) diff --git a/scripts/globals/brigands_chart.lua b/scripts/globals/brigands_chart.lua index a75b57278b0..344d20ad5f5 100644 --- a/scripts/globals/brigands_chart.lua +++ b/scripts/globals/brigands_chart.lua @@ -24,6 +24,7 @@ local function resetEvent() player:changeMusic(1, 0) player:changeMusic(2, 101) player:changeMusic(3, 102) + player:setLocalVar('bChartActive', 0) end qm1:resetLocalVars() @@ -111,6 +112,7 @@ xi.brigandsChart.onEventUpdate = function(player, csid, option, npc) player:confirmTrade() npc:setLocalVar('bChartSpawnerID', player:getID()) + player:setLocalVar('bChartActive', 1) player:changeMusic(0, 136) player:changeMusic(1, 136) diff --git a/sql/npc_list.sql b/sql/npc_list.sql index 8e6a605bade..8cb009b2a24 100644 --- a/sql/npc_list.sql +++ b/sql/npc_list.sql @@ -15083,11 +15083,11 @@ INSERT INTO `npc_list` VALUES (17257136,'qm','???',0,0.000,0.000,0.000,0,50,50,0 -- Buburimu Peninsula (Zone 118) -- ------------------------------------------------------------ -INSERT INTO `npc_list` VALUES (17261035,'Jade_Etui','Jade Etui',0,0.000,0.000,0.000,0,40,40,0,0,0,6,3,0x0000320000000000000000000000000000000000,0,NULL,1); -INSERT INTO `npc_list` VALUES (17261036,'Jade_Etui','Jade Etui',20,-90.635,19.500,-330.111,6,40,40,0,16,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); -INSERT INTO `npc_list` VALUES (17261037,'Jade_Etui','Jade Etui',75,-86.678,19.500,-330.204,7,40,40,0,16,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); -INSERT INTO `npc_list` VALUES (17261038,'Jade_Etui','Jade Etui',0,0.000,0.000,0.000,0,40,40,0,0,0,6,3,0x0000320000000000000000000000000000000000,0,NULL,1); -INSERT INTO `npc_list` VALUES (17261039,'Jade_Etui','Jade Etui',0,0.000,0.000,0.000,0,40,40,0,0,0,6,3,0x0000320000000000000000000000000000000000,0,NULL,1); +INSERT INTO `npc_list` VALUES (17261035,'Jade_Etui','Jade Etui',0,1.000,0.000,0.000,0,40,40,0,0,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); +INSERT INTO `npc_list` VALUES (17261036,'Jade_Etui','Jade Etui',0,1.000,0.000,0.000,0,40,40,0,0,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); +INSERT INTO `npc_list` VALUES (17261037,'Jade_Etui','Jade Etui',0,1.000,0.000,0.000,0,40,40,0,0,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); +INSERT INTO `npc_list` VALUES (17261038,'Jade_Etui','Jade Etui',0,1.000,0.000,0.000,0,40,40,0,0,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); +INSERT INTO `npc_list` VALUES (17261039,'Jade_Etui','Jade Etui',0,1.000,0.000,0.000,0,40,40,0,0,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); INSERT INTO `npc_list` VALUES (17261053,'VCS_Crate','VCS Crate',17,-13.479,14.482,-257.592,7,40,40,0,8,0,6,2179,0x0000C00300000000000000000000000000000000,0,NULL,1); INSERT INTO `npc_list` VALUES (17261054,'VCS_Crate','VCS Crate',0,0.000,0.000,0.000,0,40,40,0,8,0,6,131,0x0000C00300000000000000000000000000000000,0,NULL,1); diff --git a/src/map/utils/fishingutils.cpp b/src/map/utils/fishingutils.cpp index 3402d33e461..0add795fad8 100644 --- a/src/map/utils/fishingutils.cpp +++ b/src/map/utils/fishingutils.cpp @@ -69,6 +69,7 @@ namespace fishingutils uint16 MessageOffset[MAX_ZONEID]; fishing_area_pool FishingPools[MAX_ZONEID]; std::map FishList; +std::map> ChestList; std::map FishingRods; std::map FishingBaits; std::map> FishZoneMobList; // zoneid, mobid, mob @@ -437,7 +438,7 @@ uint8 CalculateRegen(uint8 fishingSkill, rod_t* rod, FISHINGCATCHTYPE catchType, { if (fishingSkill > catchSkill) { - regen -= std::max((uint8)xirand::GetRandomNumber(3, 5), regen); + regen -= (uint8)std::floor((fishingSkill - catchSkill) / 5); } } @@ -1124,6 +1125,21 @@ std::vector GetMobPool(uint16 zoneId) return pool; } +std::vector GetChestPool(uint16 zoneId) +{ + std::vector pool; + + if (!ChestList[zoneId].empty()) + { + for (uint32 chestId : ChestList[zoneId]) + { + pool.emplace_back(chestId); + } + } + + return pool; +} + uint16 GetMessageOffset(uint16 ZoneID) { return MessageOffset[ZoneID]; @@ -1631,13 +1647,10 @@ int32 CatchMonster(CCharEntity* PChar, uint32 MobID) int32 CatchChest(CCharEntity* PChar, uint32 NpcID, uint8 distance, int8 angle) { - /* Disabled catching Chests until further notice. - - uint16 MessageOffset = GetMessageOffset(PChar->getZone()); - // @todo: get chest npc (i.e. jade etui) - CNpcEntity* Chest = dynamic_cast(zoneutils::GetEntity(NpcID, TYPE_NPC)); + uint16 MessageOffset = GetMessageOffset(PChar->getZone()); + CNpcEntity* Chest = dynamic_cast(zoneutils::GetEntity(NpcID, TYPE_NPC)); - if (Chest == nullptr || (Chest != nullptr && Chest->GetLocalVar("catchable") == 0)) + if (Chest == nullptr) { ShowError("Invalid NpcID %i for fished chest", NpcID); PChar->animation = ANIMATION_FISHING_STOP; @@ -1658,14 +1671,11 @@ int32 CatchChest(CCharEntity* PChar, uint32 NpcID, uint8 distance, int8 angle) m.z = p.z + distance * (float)sin(Radians); m.rotation = p.rotation; // getangle(m, p); - Chest->loc.p = m; // This line is returning an error in CI, and I don't know how to fix it. Probably has to do with that "todo" above. + Chest->loc.p = m; Chest->status = STATUS_TYPE::NORMAL; Chest->SetLocalVar("owner", PChar->id); Chest->updatemask |= UPDATE_COMBAT; return 1; - */ - - return 0; // Remove when catching chests is enabled. } /************************************************************************ @@ -2065,9 +2075,7 @@ void ReelInCatch(CCharEntity* PChar) break; case FISHINGCATCHTYPE_CHEST: PChar->hookedFish->successtype = FISHINGSUCCESSTYPE_CATCHCHEST; - - // TODO: Below function is currently not implemented. - // CatchChest(PChar, PChar->hookedFish->catchid, PChar->hookedFish->distance, PChar->hookedFish->angle); + CatchChest(PChar, PChar->hookedFish->catchid, PChar->hookedFish->distance, PChar->hookedFish->angle); break; } } @@ -2168,14 +2176,15 @@ fishresponse_t* FishingCheck(CCharEntity* PChar, uint8 fishingSkill, rod_t* rod, int8 ChestAngle = 0; // Get Fish and Item Lists - std::map FishPool; - std::vector ItemPool; - std::vector MobPool; - std::map> ChestPool; + std::map FishPool; + std::vector ItemPool; + std::vector MobPool; + std::vector ChestPool; - FishPool = GetFishPool(PChar->getZone(), area->areaId, bait->baitID); - ItemPool = GetItemPool(PChar->getZone(), area->areaId); - MobPool = GetMobPool(PChar->getZone()); + FishPool = GetFishPool(PChar->getZone(), area->areaId, bait->baitID); + ItemPool = GetItemPool(PChar->getZone(), area->areaId); + MobPool = GetMobPool(PChar->getZone()); + ChestPool = GetChestPool(PChar->getZone()); std::set RemoveList; std::set NoCatchList; @@ -2437,11 +2446,19 @@ fishresponse_t* FishingCheck(CCharEntity* PChar, uint8 fishingSkill, rod_t* rod, if (!ChestPool.empty()) { - uint16 hookSelect = xirand::GetRandomNumber((uint16)ChestPool.size()); - auto chestItr = ChestPool.begin(); - std::advance(chestItr, hookSelect); - ChestSelection = chestItr->first; - ChestAngle = chestItr->second.begin()->second; + // Brigand's Chart Quest + if (PChar->GetLocalVar("bChartActive") == 1) + { + for (uint32 chestId : ChestPool) + { + CNpcEntity* Chest = dynamic_cast(zoneutils::GetEntity(chestId, TYPE_NPC)); + if (Chest != nullptr && Chest->GetLocalVar("owner") == 0) + { + ChestSelection = chestId; + break; + } + } + } } else { @@ -2449,8 +2466,8 @@ fishresponse_t* FishingCheck(CCharEntity* PChar, uint8 fishingSkill, rod_t* rod, ChestPoolWeight = 0; } - // Pirate's Chart quest pool weighting: just catch items - if (PChar->GetLocalVar("pChartActive") == 1 && PChar->getZone() == ZONE_VALKURM_DUNES && area->areaId == 2) + // Pirate's Chart quest pool weighting: Catch items. + if (PChar->getZone() == ZONE_VALKURM_DUNES && PChar->GetLocalVar("pChartActive") == 1 && area->areaId == 2) { FishPoolWeight = 0; ItemPoolWeight = 100; @@ -2459,6 +2476,16 @@ fishresponse_t* FishingCheck(CCharEntity* PChar, uint8 fishingSkill, rod_t* rod, NoCatchWeight = 0; } + // Brigand's Chart quest pool weighting: Catch chests. + else if (PChar->getZone() == ZONE_BUBURIMU_PENINSULA && PChar->GetLocalVar("bChartActive") == 1) + { + FishPoolWeight = 0; + ItemPoolWeight = 0; + MobPoolWeight = !MobHookPool.empty() ? 25 : 0; + ChestPoolWeight = ChestSelection > 0 ? 75 : 0; + NoCatchWeight = 0; + } + if (FishPoolWeight == 0 && ItemPoolWeight == 0 && MobPoolWeight == 0 && ChestPoolWeight == 0) { NoCatchWeight = 1000; @@ -3043,6 +3070,20 @@ void LoadFishItems() } } +void LoadChests() +{ + const auto rset = db::preparedStmt("SELECT distinct " + "npcid, (npcid & 0xFFF000) >> 12 as zoneid " + "FROM npc_list " + "WHERE name = 'Jade_Etui'"); + FOR_DB_MULTIPLE_RESULTS(rset) + { + uint32 chestId = rset->get("npcid"); + uint16 zoneId = rset->get("zoneid"); + ChestList[zoneId].emplace_back(chestId); + } +} + void LoadFishMobs() { const auto rset = db::preparedStmt("SELECT mobid, name, level, difficulty, " @@ -3186,6 +3227,7 @@ void InitializeFishingSystem() LoadFishingMessages(); LoadFishItems(); LoadFishMobs(); + LoadChests(); LoadFishingRods(); LoadFishingBaits(); LoadFishingBaitAffinities(); diff --git a/src/map/utils/fishingutils.h b/src/map/utils/fishingutils.h index c10e1b1b6f8..e005d40a953 100644 --- a/src/map/utils/fishingutils.h +++ b/src/map/utils/fishingutils.h @@ -951,6 +951,7 @@ uint8 GetBaitPower(bait_t* bait, fish_t* fish); std::map GetFishPool(uint16 zoneID, uint8 areaID, uint16 BaitID); std::vector GetItemPool(uint16 zoneID, uint8 areaID); std::vector GetMobPool(uint16 zoneId); +std::vector GetChestPool(uint16 zoneId); uint16 GetMessageOffset(uint16 ZoneID); bool IsFish(CItem* fish); fish_t* GetFish(uint32 fishId); @@ -996,6 +997,7 @@ void LoadFishingMessages(); void LoadFishingAreas(); void LoadFishItems(); void LoadFishMobs(); +void LoadChests(); void LoadFishingRods(); void LoadFishingBaits(); void LoadFishingBaitAffinities();