diff --git a/src/client/const.h b/src/client/const.h index 7fce38ee29..8ce0f766f2 100644 --- a/src/client/const.h +++ b/src/client/const.h @@ -739,6 +739,27 @@ namespace Otc SUPPLY_STASH_ACTION_WITHDRAW = 3 }; + enum CyclopediaHouseState_t : uint8_t + { + CYCLOPEDIA_HOUSE_STATE_AVAILABLE = 0, + // 1 ? + CYCLOPEDIA_HOUSE_STATE_RENTED = 2, + CYCLOPEDIA_HOUSE_STATE_TRANSFER = 3, + CYCLOPEDIA_HOUSE_STATE_MOVEOUT = 4, + }; + + enum CyclopediaHouseAuctionType_t : uint8_t + { + CYCLOPEDIA_HOUSE_TYPE_NONE = 0, + CYCLOPEDIA_HOUSE_TYPE_BID = 1, + CYCLOPEDIA_HOUSE_TYPE_MOVEOUT = 2, + CYCLOPEDIA_HOUSE_TYPE_TRANSFER = 3, + CYCLOPEDIA_HOUSE_TYPE_CANCEL_MOVEOUT = 4, + CYCLOPEDIA_HOUSE_TYPE_CANCEL_TRANSFER = 5, + CYCLOPEDIA_HOUSE_TYPE_ACCEPT_TRANSFER = 6, + CYCLOPEDIA_HOUSE_TYPE_REFECT_TRANSFER = 7, + }; + enum CyclopediaCharacterInfoType_t : uint8_t { CYCLOPEDIA_CHARACTERINFO_BASEINFORMATION = 0, diff --git a/src/client/game.cpp b/src/client/game.cpp index 8866e0d7a1..f48776f170 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1917,6 +1917,14 @@ void Game::requestSendCharacterInfo(const uint32_t playerId, const Otc::Cycloped m_protocolGame->sendCyclopediaRequestCharacterInfo(playerId, characterInfoType, entriesPerPage, page); } +void Game::requestSendCyclopediaHouseAuction(const Otc::CyclopediaHouseAuctionType_t type, const uint32_t houseId, const uint32_t timestamp, const uint64_t bidValue, const std::string_view name) +{ + if (!canPerformGameAction()) + return; + + m_protocolGame->sendCyclopediaHouseAuction(type, houseId, timestamp, bidValue, name); +} + void Game::requestBosstiaryInfo() { if (!canPerformGameAction()) diff --git a/src/client/game.h b/src/client/game.h index 64ba1ee92a..9df762b91f 100644 --- a/src/client/game.h +++ b/src/client/game.h @@ -784,6 +784,7 @@ class Game void requestBestiarySearch(uint16_t raceId); void requestSendBuyCharmRune(uint8_t runeId, uint8_t action, uint16_t raceId); void requestSendCharacterInfo(uint32_t playerId, Otc::CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage = 0, uint16_t page = 0); + void requestSendCyclopediaHouseAuction(Otc::CyclopediaHouseAuctionType_t type, uint32_t houseId, uint32_t timestamp = 0, uint64_t bidValue = 0, std::string_view name = ""); void requestBosstiaryInfo(); void requestBossSlootInfo(); void requestBossSlotAction(uint8_t action, uint32_t raceId); diff --git a/src/client/luafunctions.cpp b/src/client/luafunctions.cpp index 30fa5a0674..fed4e057e9 100644 --- a/src/client/luafunctions.cpp +++ b/src/client/luafunctions.cpp @@ -379,6 +379,7 @@ void Client::registerLuaFunctions() g_lua.bindSingletonFunction("g_game", "requestBossSlootInfo", &Game::requestBossSlootInfo, &g_game); g_lua.bindSingletonFunction("g_game", "requestBossSlotAction", &Game::requestBossSlotAction, &g_game); g_lua.bindSingletonFunction("g_game", "sendStatusTrackerBestiary", &Game::sendStatusTrackerBestiary, &g_game); + g_lua.bindSingletonFunction("g_game", "sendCyclopediaHouseAuction", &Game::requestSendCyclopediaHouseAuction, &g_game); g_lua.bindSingletonFunction("g_game", "getWalkTurnDelay", &Game::getWalkTurnDelay, &g_game); g_lua.bindSingletonFunction("g_game", "getWalkFirstStepDelay", &Game::getWalkFirstStepDelay, &g_game); diff --git a/src/client/protocolcodes.h b/src/client/protocolcodes.h index a6c2c1492d..44efc3248f 100644 --- a/src/client/protocolcodes.h +++ b/src/client/protocolcodes.h @@ -169,6 +169,9 @@ namespace Proto GameServerFloorChangeUp = 190, GameServerFloorChangeDown = 191, GameServerLootContainers = 192, + GameServerCyclopediaHouseAuctionMessage = 195, + GameServerCyclopediaHousesInfo = 198, + GameServerCyclopediaHouseList = 199, GameServerChooseOutfit = 200, GameServerSendUpdateImpactTracker = 204, GameServerSendItemsPrice = 205, @@ -301,6 +304,7 @@ namespace Proto ClientOpenOwnChannel = 170, ClientInviteToOwnChannel = 171, ClientExcludeFromOwnChannel = 172, + ClientCyclopediaHouseAuction = 173, ClientBosstiaryRequestInfo = 174, ClientBosstiaryRequestSlotInfo = 175, ClientBosstiaryRequestSlotAction = 176, diff --git a/src/client/protocolgame.h b/src/client/protocolgame.h index cd266d4f39..84099490c2 100644 --- a/src/client/protocolgame.h +++ b/src/client/protocolgame.h @@ -141,6 +141,7 @@ class ProtocolGame final : public Protocol void sendRequestBestiarySearch(uint16_t raceId); void sendBuyCharmRune(uint8_t runeId, uint8_t action, uint16_t raceId); void sendCyclopediaRequestCharacterInfo(uint32_t playerId, Otc::CyclopediaCharacterInfoType_t characterInfoType, uint16_t entriesPerPage, uint16_t page); + void sendCyclopediaHouseAuction(Otc::CyclopediaHouseAuctionType_t type, uint32_t houseId, uint32_t timestamp, uint64_t bidValue, std::string_view name); void sendRequestBosstiaryInfo(); void sendRequestBossSlootInfo(); void sendRequestBossSlotAction(uint8_t action, uint32_t raceId); @@ -293,6 +294,10 @@ class ProtocolGame final : public Protocol void parseTaskHuntingData(const InputMessagePtr& msg); void parseExperienceTracker(const InputMessagePtr& msg); void parseLootContainers(const InputMessagePtr& msg); + void parseCyclopediaHouseAuctionMessage(const InputMessagePtr& msg); + void parseCyclopediaHousesInfo(const InputMessagePtr& msg); + void parseCyclopediaHouseList(const InputMessagePtr& msg); + void parseSupplyStash(const InputMessagePtr& msg); void parseSpecialContainer(const InputMessagePtr& msg); void parsePartyAnalyzer(const InputMessagePtr& msg); diff --git a/src/client/protocolgameparse.cpp b/src/client/protocolgameparse.cpp index 61c6384abc..4604e0fe31 100644 --- a/src/client/protocolgameparse.cpp +++ b/src/client/protocolgameparse.cpp @@ -430,6 +430,15 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg) case Proto::GameServerLootContainers: parseLootContainers(msg); break; + case Proto::GameServerCyclopediaHouseAuctionMessage: + parseCyclopediaHouseAuctionMessage(msg); + break; + case Proto::GameServerCyclopediaHousesInfo: + parseCyclopediaHousesInfo(msg); + break; + case Proto::GameServerCyclopediaHouseList: + parseCyclopediaHouseList(msg); + break; case Proto::GameServerChooseOutfit: parseOpenOutfitWindow(msg); break; @@ -3789,6 +3798,120 @@ void ProtocolGame::parseLootContainers(const InputMessagePtr& msg) g_lua.callGlobalField("g_game", "onQuickLootContainers", quickLootFallbackToMainContainer, lootList); } +void ProtocolGame::parseCyclopediaHouseAuctionMessage(const InputMessagePtr& msg) +{ + msg->getU32(); // houseId + const uint8_t typeValue = msg->getU8(); + if (typeValue == 1) { + msg->getU8(); // 0x00 + } + msg->getU8(); // index + // TO-DO Lua - Otui +} + +void ProtocolGame::parseCyclopediaHousesInfo(const InputMessagePtr& msg) +{ + msg->getU32(); // houseClientId + msg->getU8(); // 0x00 + + msg->getU8(); // accountHouseCount + + msg->getU8(); // 0x00 + + msg->getU8(); // 3 + msg->getU8(); // 3 + + msg->getU8(); // 0x01 + + msg->getU8(); // 0x01 + msg->getU32(); // houseClientId + + const uint16_t housesList = msg->getU16(); // g_game().map.houses.getHouses() + for (auto i = 0; i < housesList; ++i) { + msg->getU32(); // getClientId + } + // TO-DO Lua // Otui +} + +void ProtocolGame::parseCyclopediaHouseList(const InputMessagePtr& msg) +{ + const uint16_t housesCount = msg->getU16(); // housesCount + for (auto i = 0; i < housesCount; ++i) { + msg->getU32(); // clientId + msg->getU8(); // 0x00 = Renovation, 0x01 = Available + + const auto type = static_cast(msg->getU8()); + switch (type) { + case Otc::CYCLOPEDIA_HOUSE_STATE_AVAILABLE: { + std::string bidderName = msg->getString(); + const auto isBidder = static_cast(msg->getU8()); + msg->getU8(); // disableIndex + + if (!bidderName.empty()) { + msg->getU32(); // bidEndDate + msg->getU64(); // highestBid + if (isBidder) { + msg->getU64(); // bidHolderLimit + } + } + break; + } + case Otc::CYCLOPEDIA_HOUSE_STATE_RENTED: { + msg->getString(); // ownerName + msg->getU32(); // paidUntil + + const auto isRented = static_cast(msg->getU8()); + if (isRented) { + msg->getU8(); // unknown + msg->getU8(); // unknown + } + break; + } + case Otc::CYCLOPEDIA_HOUSE_STATE_TRANSFER: { + msg->getString(); // ownerName + msg->getU32(); // paidUntil + const auto isOwner = static_cast(msg->getU8()); + if (isOwner) { + msg->getU8(); // unknown + msg->getU8(); // unknown + } + msg->getU32(); // bidEndDate + msg->getString(); // bidderName + msg->getU8(); // unknown + msg->getU64(); // internalBid + + const auto isNewOwner = static_cast(msg->getU8()); + if (isNewOwner) { + msg->getU8(); // acceptTransferError + msg->getU8(); // rejectTransferError + } + + if (isOwner) { + msg->getU8(); // cancelTransferError + } + break; + } + case Otc::CYCLOPEDIA_HOUSE_STATE_MOVEOUT: { + msg->getString(); // ownerName + msg->getU32(); // paidUntil + + const auto isOwner = static_cast(msg->getU8()); + if (isOwner) { + msg->getU8(); // unknown + msg->getU8(); // unknown + msg->getU32(); // bidEndDate + msg->getU8(); // unknown + } else { + msg->getU32(); // bidEndDate + } + + break; + } + } + } + // TO-DO Lua - Otui +} + void ProtocolGame::parseSupplyStash(const InputMessagePtr& msg) { const uint16_t itemsCount = msg->getU16(); diff --git a/src/client/protocolgamesend.cpp b/src/client/protocolgamesend.cpp index 8cea01e1a4..9a93dd66ae 100644 --- a/src/client/protocolgamesend.cpp +++ b/src/client/protocolgamesend.cpp @@ -1056,6 +1056,47 @@ void ProtocolGame::sendCyclopediaRequestCharacterInfo(const uint32_t playerId, c send(msg); } +void ProtocolGame::sendCyclopediaHouseAuction(const Otc::CyclopediaHouseAuctionType_t type, const uint32_t houseId, const uint32_t timestamp, const uint64_t bidValue, const std::string_view name) +{ + const auto& msg = std::make_shared(); + msg->addU8(Proto::ClientCyclopediaHouseAuction); + msg->addU8(type); + + switch (type) { + case Otc::CYCLOPEDIA_HOUSE_TYPE_NONE: + msg->addString(name); // townName + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_BID: + msg->addU32(houseId); + msg->addU64(bidValue); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_MOVEOUT: + msg->addU32(houseId); + msg->addU32(timestamp); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_TRANSFER: + msg->addU32(houseId); + msg->addU32(timestamp); + msg->addString(name); // newOwner + msg->addU64(bidValue); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_CANCEL_MOVEOUT: + msg->addU32(houseId); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_CANCEL_TRANSFER: + msg->addU32(houseId); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_ACCEPT_TRANSFER: + msg->addU32(houseId); + break; + case Otc::CYCLOPEDIA_HOUSE_TYPE_REFECT_TRANSFER: + msg->addU32(houseId); + break; + } + + send(msg); +} + void ProtocolGame::sendRequestBosstiaryInfo() { const auto& msg = std::make_shared();