From 54561bf3212c57fbac00febe4cb8763ace10cc5c Mon Sep 17 00:00:00 2001 From: WinterSolstice8 <60417494+wintersolstice8@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:53:48 -0600 Subject: [PATCH] [core] Actually instansiate CFlowerPot --- scripts/enum/item_type.lua | 1 + sql/item_basic.sql | 21 ++++---- src/map/enums/item_types.h | 1 + src/map/items/exdata.cpp | 11 ++-- src/map/items/item.cpp | 2 +- src/map/items/item.h | 5 +- src/map/items/item_flowerpot.cpp | 1 + src/map/items/item_furnishing.cpp | 12 +---- .../packets/c2s/0x0fc_myroom_plant_add.cpp | 25 +++++++-- .../packets/c2s/0x0fd_myroom_plant_check.cpp | 51 ++++++++++++------- .../packets/c2s/0x0fe_myroom_plant_crop.cpp | 45 +++++++++++----- .../packets/c2s/0x0ff_myroom_plant_stop.cpp | 2 +- src/map/utils/gardenutils.cpp | 8 +-- src/map/utils/itemutils.cpp | 9 ++++ 14 files changed, 124 insertions(+), 70 deletions(-) diff --git a/scripts/enum/item_type.lua b/scripts/enum/item_type.lua index ebc1e00f82d..d353151b27e 100644 --- a/scripts/enum/item_type.lua +++ b/scripts/enum/item_type.lua @@ -15,4 +15,5 @@ xi.itemType = CURRENCY = 0x20, FURNISHING = 0x40, LINKSHELL = 0x80, + FLOWERPOT = 0x100, } diff --git a/sql/item_basic.sql b/sql/item_basic.sql index 0be0bf696ee..a492542e5ca 100644 --- a/sql/item_basic.sql +++ b/sql/item_basic.sql @@ -110,6 +110,7 @@ SET @USABLE_TYPE = 5; SET @EQUIPMENT_TYPE = 6; SET @WEAPON_TYPE = 7; SET @CURRENCY_TYPE = 8; +SET @FLOWERPOT_TYPE = 9; -- Item Flags SET @FLAG_AUG_SENDABLE = 1; -- 0x00001 @@ -284,12 +285,12 @@ INSERT INTO `item_basic` VALUES (212,0,'water_lamp','water_lamp','ウォータ INSERT INTO `item_basic` VALUES (213,0,'light_lamp','light_lamp','ライトランプ',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX | @FLAG_INSCRIBABLE,@FURNISHINGS,0); INSERT INTO `item_basic` VALUES (214,0,'dark_lamp','dark_lamp','ダークランプ',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX | @FLAG_INSCRIBABLE,@FURNISHINGS,0); INSERT INTO `item_basic` VALUES (215,0,'set_of_festival_dolls','festival_dolls','ヒナドールズ',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY,@NONE,0); -INSERT INTO `item_basic` VALUES (216,0,'porcelain_flowerpot','porc._flowerpot','磁器の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); -INSERT INTO `item_basic` VALUES (217,0,'brass_flowerpot','brass_flowerpot','黄銅の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,200); -INSERT INTO `item_basic` VALUES (218,0,'earthen_flowerpot','earthen_flowerpot','土師器の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); -INSERT INTO `item_basic` VALUES (219,0,'ceramic_flowerpot','ceramic_flowerpot','陶器の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); -INSERT INTO `item_basic` VALUES (220,0,'wooden_flowerpot','wooden_flowerpot','木の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,1428); -INSERT INTO `item_basic` VALUES (221,0,'arcane_flowerpot','arcane_flowerpot','謎の植木鉢',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,3900); +INSERT INTO `item_basic` VALUES (216,0,'porcelain_flowerpot','porc._flowerpot','磁器の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); +INSERT INTO `item_basic` VALUES (217,0,'brass_flowerpot','brass_flowerpot','黄銅の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,200); +INSERT INTO `item_basic` VALUES (218,0,'earthen_flowerpot','earthen_flowerpot','土師器の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); +INSERT INTO `item_basic` VALUES (219,0,'ceramic_flowerpot','ceramic_flowerpot','陶器の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,194); +INSERT INTO `item_basic` VALUES (220,0,'wooden_flowerpot','wooden_flowerpot','木の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,1428); +INSERT INTO `item_basic` VALUES (221,0,'arcane_flowerpot','arcane_flowerpot','謎の植木鉢',@FLOWERPOT_TYPE,1,@FLAG_MYSTERY_BOX,@FURNISHINGS,3900); INSERT INTO `item_basic` VALUES (222,0,'fighting_fish_tank','fighting_fish_tank','闘魚鉢',@FURNISHING_TYPE,1,@FLAG_INSCRIBABLE,@FURNISHINGS,1662); INSERT INTO `item_basic` VALUES (223,0,'river_aquarium','river_aquarium','アクアリウム〔川〕',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX | @FLAG_INSCRIBABLE,@FURNISHINGS,2091); INSERT INTO `item_basic` VALUES (224,0,'bay_aquarium','bay_aquarium','アクアリウム〔湾〕',@FURNISHING_TYPE,1,@FLAG_MYSTERY_BOX | @FLAG_INSCRIBABLE,@FURNISHINGS,3912); @@ -3715,10 +3716,10 @@ INSERT INTO `item_basic` VALUES (3740,0,'model_synergy_furnace','model_synergy_f INSERT INTO `item_basic` VALUES (3741,0,'model_synergy_furnace_ii','model_syn._furn._ii','模倣錬成窯II',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); INSERT INTO `item_basic` VALUES (3742,0,'painting_of_a_mercenary','merc._painting','ようじんぼうの絵画',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX | @FLAG_RARE,@NONE,0); INSERT INTO `item_basic` VALUES (3743,0,'moogle_bed','moogle_bed','モーグリベッド',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); -INSERT INTO `item_basic` VALUES (3744,0,'mandragora_pot','mandragora_pot','マンドラ植木鉢',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); -INSERT INTO `item_basic` VALUES (3745,0,'korrigan_pot','korrigan_pot','コリガン植木鉢',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); -INSERT INTO `item_basic` VALUES (3746,0,'adenium_pot','adenium_pot','アデニウム植木鉢',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); -INSERT INTO `item_basic` VALUES (3747,0,'citrullus_pot','citrullus_pot','キトルルス植木鉢',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); +INSERT INTO `item_basic` VALUES (3744,0,'mandragora_pot','mandragora_pot','マンドラ植木鉢',@FLOWERPOT_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); +INSERT INTO `item_basic` VALUES (3745,0,'korrigan_pot','korrigan_pot','コリガン植木鉢',@FLOWERPOT_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); +INSERT INTO `item_basic` VALUES (3746,0,'adenium_pot','adenium_pot','アデニウム植木鉢',@FLOWERPOT_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); +INSERT INTO `item_basic` VALUES (3747,0,'citrullus_pot','citrullus_pot','キトルルス植木鉢',@FLOWERPOT_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); INSERT INTO `item_basic` VALUES (3748,0,'leafkin_bed','leafkin_bed','リフキンベッド',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); INSERT INTO `item_basic` VALUES (3749,0,'chemistry_set','chemistry_set','試験薬セット',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX,@NONE,0); INSERT INTO `item_basic` VALUES (3750,0,'qiqirn_sack','qiqirn_sack','キキルンの願い箱',@FURNISHING_TYPE,1,@FLAG_NOAUCTION | @FLAG_NOSALE | @FLAG_NODELIVERY | @FLAG_EX | @FLAG_RARE,@NONE,0); diff --git a/src/map/enums/item_types.h b/src/map/enums/item_types.h index e22696c6fa1..45b990b4628 100644 --- a/src/map/enums/item_types.h +++ b/src/map/enums/item_types.h @@ -31,4 +31,5 @@ enum class ItemType : uint8_t Equipment = 6, // CItemEquipment Weapon = 7, // CItemWeapon Currency = 8, // CItemCurrency + FlowerPot = 9, // CItemFlowerpot }; diff --git a/src/map/items/exdata.cpp b/src/map/items/exdata.cpp index 95cabc7f4c5..3687c2c7191 100644 --- a/src/map/items/exdata.cpp +++ b/src/map/items/exdata.cpp @@ -151,6 +151,12 @@ auto getType(const CItem* item) -> Type return Type::Escutcheon; } + // Flowerpot check has to go before Furnishing because isType is a bitwise check and flowerpots are a child class + if (item->isType(ITEM_FLOWERPOT)) + { + return Type::FlowerPot; + } + if (item->isType(ITEM_FURNISHING)) { if (item->isMannequin()) @@ -158,11 +164,6 @@ auto getType(const CItem* item) -> Type return Type::Mannequin; } - if (static_cast(item)->isGardeningPot()) - { - return Type::FlowerPot; - } - return Type::Furniture; } diff --git a/src/map/items/item.cpp b/src/map/items/item.cpp index a64d8131188..4161e3f4455 100644 --- a/src/map/items/item.cpp +++ b/src/map/items/item.cpp @@ -167,7 +167,7 @@ uint8 CItem::getAHCat() const * * ************************************************************************/ -void CItem::setType(uint8 type) +void CItem::setType(uint16 type) { m_type |= type; } diff --git a/src/map/items/item.h b/src/map/items/item.h index 94ef5e069e4..438f5d10d2e 100644 --- a/src/map/items/item.h +++ b/src/map/items/item.h @@ -46,6 +46,7 @@ enum ITEM_TYPE ITEM_CURRENCY = 0x20, ITEM_FURNISHING = 0x40, ITEM_LINKSHELL = 0x80, + ITEM_FLOWERPOT = 0x100, }; // Additional type of object m_subtype @@ -142,12 +143,12 @@ class CItem } protected: - void setType(uint8); + void setType(uint16); private: uint16 m_id; uint16 m_subid; - uint8 m_type; + uint16 m_type; uint8 m_subtype; uint32 m_quantity; // Current number of items uint32 m_reserve; diff --git a/src/map/items/item_flowerpot.cpp b/src/map/items/item_flowerpot.cpp index 9f5f4f54a00..5152ddc6529 100644 --- a/src/map/items/item_flowerpot.cpp +++ b/src/map/items/item_flowerpot.cpp @@ -26,6 +26,7 @@ CItemFlowerpot::CItemFlowerpot(uint16 id) : CItemFurnishing(id) { + setType(ITEM_FLOWERPOT); } CItemFlowerpot::CItemFlowerpot(const CItemFlowerpot& other) diff --git a/src/map/items/item_furnishing.cpp b/src/map/items/item_furnishing.cpp index 7d88738772c..4969cc46165 100644 --- a/src/map/items/item_furnishing.cpp +++ b/src/map/items/item_furnishing.cpp @@ -223,15 +223,5 @@ void CItemFurnishing::setSignature(const std::string& signature) bool CItemFurnishing::isGardeningPot() const { - const auto id = CItem::getID(); - return id == 216 || // porcelain_flowerpot - id == 217 || // brass_flowerpot - id == 218 || // earthen_flowerpot - id == 219 || // ceramic_flowerpot - id == 220 || // wooden_flowerpot - id == 221 || // arcane_flowerpot - id == 3744 || // mandragora_pot - id == 3745 || // korrigan_pot - id == 3746 || // adenium_pot - id == 3747; // citrullus_pot + return this->isType(ITEM_FLOWERPOT); } diff --git a/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp b/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp index c432370943a..ae9fc8386da 100644 --- a/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp +++ b/src/map/packets/c2s/0x0fc_myroom_plant_add.cpp @@ -51,10 +51,27 @@ auto GP_CLI_COMMAND_MYROOM_PLANT_ADD::validate(MapSession* PSession, const CChar void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* PChar) const { - CItemContainer* PPotItemContainer = PChar->getStorage(this->MyroomPlantCategory); - auto* PPotItem = static_cast(PPotItemContainer->GetItem(this->MyroomPlantItemIndex)); + CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); + auto* PItem = PItemContainer->GetItem(this->MyroomPlantItemIndex); + auto* PPotItem = dynamic_cast(PItem); + if (PPotItem == nullptr) { + if (PItem) + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_ADD::process: {} has tried to use invalid gardening pot {} ({})", + PChar->getName(), + PItem->getID(), + PItem->getName())); + return; + } + else + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_ADD::process: {} has tried to use invalid gardening pot item (MyroomPlantCategory = {}, MyroomPlantItemIndex = {})", + PChar->getName(), + this->MyroomPlantCategory, + this->MyroomPlantItemIndex)); + } return; } @@ -67,8 +84,6 @@ void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* return; } - CItemContainer* PItemContainer = PChar->getStorage(this->MyroomAddCategory); - const CItem* PItem = PItemContainer->GetItem(this->MyroomAddItemIndex); if (PItem == nullptr || PItem->getQuantity() < 1) { return; @@ -87,7 +102,7 @@ void GP_CLI_COMMAND_MYROOM_PLANT_ADD::process(MapSession* PSession, CCharEntity* gardenutils::GrowToNextStage(PPotItem); updatedPot = true; } - else if (this->MyroomAddItemNo >= FIRE_CRYSTAL && this->MyroomAddItemNo <= DARK_CLUSTER) + else if (this->MyroomAddItemNo >= FIRE_CRYSTAL && this->MyroomAddItemNo <= DARK_CRYSTAL) { // Feeding the plant a crystal PChar->pushPacket(this->MyroomAddItemNo, MsgStd::MoogleUsesItemOnPLant); diff --git a/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp b/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp index 1d333bf556c..d70d0383c9d 100644 --- a/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp +++ b/src/map/packets/c2s/0x0fd_myroom_plant_check.cpp @@ -45,22 +45,39 @@ auto GP_CLI_COMMAND_MYROOM_PLANT_CHECK::validate(MapSession* PSession, const CCh void GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process(MapSession* PSession, CCharEntity* PChar) const { CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); - auto* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); - if (PItem == nullptr) + auto* PItem = PItemContainer->GetItem(this->MyroomPlantItemIndex); + auto* PPotItem = dynamic_cast(PItem); + + if (PPotItem == nullptr) { + if (PItem) + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process: {} has tried to use invalid gardening pot {} ({})", + PChar->getName(), + PItem->getID(), + PItem->getName())); + return; + } + else + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process: {} has tried to use invalid gardening pot item (MyroomPlantCategory = {}, MyroomPlantItemIndex = {})", + PChar->getName(), + this->MyroomPlantCategory, + this->MyroomPlantItemIndex)); + } return; } - if (PItem->isPlanted()) + if (PPotItem->isPlanted()) { - PChar->pushPacket(PChar, PChar, CItemFlowerpot::getSeedID(PItem->getPlant()), 0, MsgBasic::GardeningSeedSown); - if (PItem->isTree()) + PChar->pushPacket(PChar, PChar, CItemFlowerpot::getSeedID(PPotItem->getPlant()), 0, MsgBasic::GardeningSeedSown); + if (PPotItem->isTree()) { - if (PItem->getStage() > FLOWERPOT_STAGE_FIRST_SPROUTS_CRYSTAL) + if (PPotItem->getStage() > FLOWERPOT_STAGE_FIRST_SPROUTS_CRYSTAL) { - if (PItem->getExtraCrystalFeed() != FLOWERPOT_ELEMENT_NONE) + if (PPotItem->getExtraCrystalFeed() != FLOWERPOT_ELEMENT_NONE) { - PChar->pushPacket(PChar, PChar, CItemFlowerpot::getItemFromElement(PItem->getExtraCrystalFeed()), 0, MsgBasic::GardeningCrystalUsed); + PChar->pushPacket(PChar, PChar, CItemFlowerpot::getItemFromElement(PPotItem->getExtraCrystalFeed()), 0, MsgBasic::GardeningCrystalUsed); } else { @@ -68,11 +85,11 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process(MapSession* PSession, CCharEntit } } } - if (PItem->getStage() > FLOWERPOT_STAGE_SECOND_SPROUTS_CRYSTAL) + if (PPotItem->getStage() > FLOWERPOT_STAGE_SECOND_SPROUTS_CRYSTAL) { - if (PItem->getCommonCrystalFeed() != FLOWERPOT_ELEMENT_NONE) + if (PPotItem->getCommonCrystalFeed() != FLOWERPOT_ELEMENT_NONE) { - PChar->pushPacket(PChar, PChar, CItemFlowerpot::getItemFromElement(PItem->getCommonCrystalFeed()), 0, MsgBasic::GardeningCrystalUsed); + PChar->pushPacket(PChar, PChar, CItemFlowerpot::getItemFromElement(PPotItem->getCommonCrystalFeed()), 0, MsgBasic::GardeningCrystalUsed); } else { @@ -80,17 +97,17 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CHECK::process(MapSession* PSession, CCharEntit } } - if (!PItem->wasExamined()) + if (!PPotItem->wasExamined()) { - PItem->markExamined(); + PPotItem->markExamined(); db::preparedStmt("UPDATE char_inventory SET extra = ? WHERE charid = ? AND location = ? AND slot = ? LIMIT 1", - PItem->m_extra, + PPotItem->m_extra, PChar->id, - PItem->getLocationID(), - PItem->getSlotID()); + PPotItem->getLocationID(), + PPotItem->getSlotID()); } } - PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); + PChar->pushPacket(PPotItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); } diff --git a/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp b/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp index 62f5d1c7764..f556c3b7979 100644 --- a/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp +++ b/src/map/packets/c2s/0x0fe_myroom_plant_crop.cpp @@ -49,30 +49,47 @@ auto GP_CLI_COMMAND_MYROOM_PLANT_CROP::validate(MapSession* PSession, const CCha void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity* PChar) const { CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); - CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); - if (PItem == nullptr) + auto* PItem = PItemContainer->GetItem(this->MyroomPlantItemIndex); + auto* PPotItem = dynamic_cast(PItem); + + if (PPotItem == nullptr) { + if (PItem) + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(: {} has tried to use invalid gardening pot {} ({})", + PChar->getName(), + PItem->getID(), + PItem->getName())); + return; + } + else + { + ShowWarning(fmt::format("GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(: {} has tried to use invalid gardening pot item (MyroomPlantCategory = {}, MyroomPlantItemIndex = {})", + PChar->getName(), + this->MyroomPlantCategory, + this->MyroomPlantItemIndex)); + } return; } // Try to catch packet abuse, leading to gardening pots being placed on 2nd floor. - if (PItem->getOn2ndFloor() && PItem->isGardeningPot()) + if (PPotItem->getOn2ndFloor() && PPotItem->isGardeningPot()) { ShowWarning(fmt::format("{} has tried to uproot gardening pot {} ({}) on 2nd floor", PChar->getName(), - PItem->getID(), - PItem->getName())); + PPotItem->getID(), + PPotItem->getName())); return; } - if (PItem->isPlanted()) + if (PPotItem->isPlanted()) { - if (this->CancellFlg == 0 && PItem->getStage() == FLOWERPOT_STAGE_MATURE_PLANT) + if (this->CancellFlg == 0 && PPotItem->getStage() == FLOWERPOT_STAGE_MATURE_PLANT) { // Harvesting plant uint16 resultID = 0; uint8 totalQuantity = 0; - std::tie(resultID, totalQuantity) = gardenutils::CalculateResults(PChar, PItem); + std::tie(resultID, totalQuantity) = gardenutils::CalculateResults(PChar, PPotItem); const uint8 stackSize = xi::items::lookup(resultID)->getStackSize(); const uint8 requiredSlots = (uint8)ceil(float(totalQuantity) / stackSize); const uint8 totalFreeSlots = PChar->getStorage(LOC_MOGSAFE)->GetFreeSlotsCount() + PChar->getStorage(LOC_MOGSAFE2)->GetFreeSlotsCount(); @@ -94,16 +111,16 @@ void GP_CLI_COMMAND_MYROOM_PLANT_CROP::process(MapSession* PSession, CCharEntity PChar->pushPacket(resultID, totalQuantity, 134); // Your moogle from the plant! } - PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); - PItem->cleanPot(); + PChar->pushPacket(PPotItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); + PPotItem->cleanPot(); db::preparedStmt("UPDATE char_inventory SET extra = ? WHERE charid = ? AND location = ? AND slot = ? LIMIT 1", - PItem->m_extra, + PPotItem->m_extra, PChar->id, - PItem->getLocationID(), - PItem->getSlotID()); + PPotItem->getLocationID(), + PPotItem->getSlotID()); - PChar->pushPacket(PItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); + PChar->pushPacket(PPotItem, static_cast(this->MyroomPlantCategory), this->MyroomPlantItemIndex); PChar->pushPacket(PChar); } } diff --git a/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp b/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp index 6c8af2314f7..9cf134a2bf7 100644 --- a/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp +++ b/src/map/packets/c2s/0x0ff_myroom_plant_stop.cpp @@ -48,7 +48,7 @@ auto GP_CLI_COMMAND_MYROOM_PLANT_STOP::validate(MapSession* PSession, const CCha void GP_CLI_COMMAND_MYROOM_PLANT_STOP::process(MapSession* PSession, CCharEntity* PChar) const { CItemContainer* PItemContainer = PChar->getStorage(this->MyroomPlantCategory); - CItemFlowerpot* PItem = static_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); + CItemFlowerpot* PItem = dynamic_cast(PItemContainer->GetItem(this->MyroomPlantItemIndex)); if (PItem != nullptr && PItem->isPlanted() && PItem->getStage() > FLOWERPOT_STAGE_INITIAL && PItem->getStage() < FLOWERPOT_STAGE_WILTED && !PItem->isDried()) { diff --git a/src/map/utils/gardenutils.cpp b/src/map/utils/gardenutils.cpp index 2d34c7d8786..097dedc73ca 100644 --- a/src/map/utils/gardenutils.cpp +++ b/src/map/utils/gardenutils.cpp @@ -95,14 +95,14 @@ void UpdateGardening(CCharEntity* PChar, SendPacket sendPacket) for (int slotID = 0; slotID < PContainer->GetSize(); ++slotID) { CItem* PItem = PContainer->GetItem(slotID); - if (PItem != nullptr && PItem->isType(ITEM_FURNISHING)) + if (PItem != nullptr && PItem->isType(ITEM_FLOWERPOT)) { CItemFlowerpot* PPotItem = dynamic_cast(PItem); if (PPotItem != nullptr && PPotItem->canGrow() && vanatime >= PPotItem->getStageTimestamp()) { - uint8 stageDuration = GetStageDuration(PPotItem); - uint32 daysSinceStageChange = (vanatime - PPotItem->getStageTimestamp()) / VANADAY_SECONDS; - uint8 wiltTime = VANADAYS_TO_WILT + PChar->getMod(Mod::GARDENING_WILT_BONUS); + uint32 stageDuration = GetStageDuration(PPotItem); + uint32 daysSinceStageChange = std::floor(std::max(0.f, static_cast(vanatime - PPotItem->getStageTimestamp()) / static_cast(VANADAY_SECONDS))); + uint32 wiltTime = VANADAYS_TO_WILT + PChar->getMod(Mod::GARDENING_WILT_BONUS); bool wasExamined = PPotItem->wasExamined(); if ((!wasExamined && (stageDuration > wiltTime || (stageDuration + daysSinceStageChange > wiltTime))) || daysSinceStageChange > VANADAYS_TO_GUARANTEE_WILT + wiltTime) diff --git a/src/map/utils/itemutils.cpp b/src/map/utils/itemutils.cpp index ad788756d5f..bd85f51d854 100644 --- a/src/map/utils/itemutils.cpp +++ b/src/map/utils/itemutils.cpp @@ -35,6 +35,7 @@ #include "entities/battleentity.h" #include "enums/item_types.h" +#include "items/item_flowerpot.h" #include "items/item_furnishing.h" #include "items/item_general.h" #include "items/item_linkshell.h" @@ -150,6 +151,12 @@ auto clone(const CItem& source) -> std::unique_ptr return std::make_unique(static_cast(source)); } + // Flowerpot check has to go before Furnishing because isType is a bitwise check and flowerpots are a child class + if (source.isType(ITEM_FLOWERPOT)) + { + return std::make_unique(static_cast(source)); + } + if (source.isType(ITEM_FURNISHING)) { return std::make_unique(static_cast(source)); @@ -244,6 +251,8 @@ void LoadItemList() return std::make_unique(itemId); case ItemType::Currency: return std::make_unique(itemId); + case ItemType::FlowerPot: + return std::make_unique(itemId); default: ShowErrorFmt("LoadItemList({}): Unknown item type {}", itemId, static_cast(itemType)); return std::make_unique(itemId);