diff --git a/dCommon/dEnums/eReplicaComponentType.h b/dCommon/dEnums/eReplicaComponentType.h index 83acbf89..2b991dfb 100644 --- a/dCommon/dEnums/eReplicaComponentType.h +++ b/dCommon/dEnums/eReplicaComponentType.h @@ -106,7 +106,7 @@ enum class eReplicaComponentType : uint32_t { INTERACTION_MANAGER, DONATION_VENDOR, COMBAT_MEDIATOR, - COMMENDATION_VENDOR, + ACHIEVEMENT_VENDOR, GATE_RUSH_CONTROL, RAIL_ACTIVATOR, ROLLER, diff --git a/dCommon/dEnums/eVendorTransactionResult.h b/dCommon/dEnums/eVendorTransactionResult.h new file mode 100644 index 00000000..e61ee0ee --- /dev/null +++ b/dCommon/dEnums/eVendorTransactionResult.h @@ -0,0 +1,15 @@ +#ifndef __EVENDORTRANSACTIONRESULT__ +#define __EVENDORTRANSACTIONRESULT__ + +#include + +enum class eVendorTransactionResult : uint32_t { + SELL_SUCCESS = 0, + SELL_FAIL, + PURCHASE_SUCCESS, + PURCHASE_FAIL, + DONATION_FAIL, + DONATION_FULL +}; + +#endif // !__EVENDORTRANSACTIONRESULT__ diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp index 8862b1db..97dcde9f 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.cpp @@ -79,7 +79,6 @@ void CDMissionsTable::LoadValuesFromDatabase() { entries.push_back(entry); tableData.nextRow(); } - tableData.finalize(); Default.id = -1; @@ -118,3 +117,12 @@ const CDMissions& CDMissionsTable::GetByMissionID(uint32_t missionID, bool& foun return Default; } +const std::set CDMissionsTable::GetMissionsForReward(LOT lot) { + std::set toReturn {}; + for (const auto& entry : GetEntries()) { + if (lot == entry.reward_item1 || lot == entry.reward_item2 || lot == entry.reward_item3 || lot == entry.reward_item4) { + toReturn.insert(entry.id); + } + } + return toReturn; +} diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h index 6ba7b19e..5067f2e2 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDMissionsTable.h @@ -70,6 +70,9 @@ class CDMissionsTable : public CDTable> const CDMissions& GetByMissionID(uint32_t missionID, bool& found) const; + const std::set GetMissionsForReward(LOT lot); + + static CDMissions Default; }; diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 269b4cc4..bb932991 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -82,6 +82,7 @@ #include "CollectibleComponent.h" #include "ItemComponent.h" #include "GhostComponent.h" +#include "AchievementVendorComponent.h" // Table includes #include "CDComponentsRegistryTable.h" @@ -615,6 +616,8 @@ void Entity::Initialize() { AddComponent(); } else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) { AddComponent(); + } else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ACHIEVEMENT_VENDOR, -1) != -1)) { + AddComponent(); } if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) { @@ -1191,6 +1194,11 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType donationVendorComponent->Serialize(outBitStream, bIsInitialUpdate); } + AchievementVendorComponent* achievementVendorComponent; + if (TryGetComponent(eReplicaComponentType::ACHIEVEMENT_VENDOR, achievementVendorComponent)) { + achievementVendorComponent->Serialize(outBitStream, bIsInitialUpdate); + } + BouncerComponent* bouncerComponent; if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) { bouncerComponent->Serialize(outBitStream, bIsInitialUpdate); diff --git a/dGame/dComponents/AchievementVendorComponent.cpp b/dGame/dComponents/AchievementVendorComponent.cpp new file mode 100644 index 00000000..10a0ca29 --- /dev/null +++ b/dGame/dComponents/AchievementVendorComponent.cpp @@ -0,0 +1,72 @@ +#include "AchievementVendorComponent.h" +#include "MissionComponent.h" +#include "InventoryComponent.h" +#include "eMissionState.h" +#include "CDComponentsRegistryTable.h" +#include "CDItemComponentTable.h" +#include "eVendorTransactionResult.h" +#include "CheatDetection.h" +#include "UserManager.h" +#include "CDMissionsTable.h" + +bool AchievementVendorComponent::SellsItem(Entity* buyer, const LOT lot) { + auto* missionComponent = buyer->GetComponent(); + if (!missionComponent) return false; + + if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)){ + return true; + } + + CDMissionsTable* missionsTable = CDClientManager::GetTable(); + const auto missions = missionsTable->GetMissionsForReward(lot); + for (const auto mission : missions) { + if (missionComponent->GetMissionState(mission) == eMissionState::COMPLETE) { + m_PlayerPurchasableItems[buyer->GetObjectID()].insert(lot); + return true; + } + } + return false; +} + +void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) { + // get the item Comp from the item LOT + CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable(); + CDItemComponentTable* itemComponentTable = CDClientManager::GetTable(); + int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM); + CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID); + uint32_t costLOT = itemComp.commendationLOT; + + if (costLOT == -1 || !SellsItem(buyer, lot)) { + auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress()); + CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT()); + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + + auto* inventoryComponent = buyer->GetComponent(); + if (!inventoryComponent) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + + if (costLOT == 13763) { // Faction Token Proxy + auto* missionComponent = buyer->GetComponent(); + if (!missionComponent) return; + + if (missionComponent->GetMissionState(545) == eMissionState::COMPLETE) costLOT = 8318; // "Assembly Token" + if (missionComponent->GetMissionState(556) == eMissionState::COMPLETE) costLOT = 8321; // "Venture League Token" + if (missionComponent->GetMissionState(567) == eMissionState::COMPLETE) costLOT = 8319; // "Sentinels Token" + if (missionComponent->GetMissionState(578) == eMissionState::COMPLETE) costLOT = 8320; // "Paradox Token" + } + + const uint32_t altCurrencyCost = itemComp.commendationCost * count; + if (inventoryComponent->GetLotCount(costLOT) < altCurrencyCost) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + + inventoryComponent->RemoveItem(costLOT, altCurrencyCost); + inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR); + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS); + +} \ No newline at end of file diff --git a/dGame/dComponents/AchievementVendorComponent.h b/dGame/dComponents/AchievementVendorComponent.h new file mode 100644 index 00000000..bffd3983 --- /dev/null +++ b/dGame/dComponents/AchievementVendorComponent.h @@ -0,0 +1,23 @@ +#ifndef __ACHIEVEMENTVENDORCOMPONENT__H__ +#define __ACHIEVEMENTVENDORCOMPONENT__H__ + +#include "VendorComponent.h" +#include "eReplicaComponentType.h" +#include +#include + +class Entity; + +class AchievementVendorComponent final : public VendorComponent { +public: + static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR; + AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {}; + bool SellsItem(Entity* buyer, const LOT lot); + void Buy(Entity* buyer, LOT lot, uint32_t count); + +private: + std::map> m_PlayerPurchasableItems; +}; + + +#endif //!__ACHIEVEMENTVENDORCOMPONENT__H__ diff --git a/dGame/dComponents/CMakeLists.txt b/dGame/dComponents/CMakeLists.txt index ac509e11..21fe9207 100644 --- a/dGame/dComponents/CMakeLists.txt +++ b/dGame/dComponents/CMakeLists.txt @@ -1,4 +1,5 @@ set(DGAME_DCOMPONENTS_SOURCES + "AchievementVendorComponent.cpp" "ActivityComponent.cpp" "BaseCombatAIComponent.cpp" "BouncerComponent.cpp" diff --git a/dGame/dComponents/VendorComponent.cpp b/dGame/dComponents/VendorComponent.cpp index afa3d013..9e9428f7 100644 --- a/dGame/dComponents/VendorComponent.cpp +++ b/dGame/dComponents/VendorComponent.cpp @@ -8,6 +8,11 @@ #include "CDLootMatrixTable.h" #include "CDLootTableTable.h" #include "CDItemComponentTable.h" +#include "InventoryComponent.h" +#include "Character.h" +#include "eVendorTransactionResult.h" +#include "UserManager.h" +#include "CheatDetection.h" VendorComponent::VendorComponent(Entity* parent) : Component(parent) { m_HasStandardCostItems = false; @@ -151,3 +156,60 @@ void VendorComponent::HandleMrReeCameras(){ m_Inventory.push_back(SoldItem(camera, 0)); } } + + +void VendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) { + + if (!SellsItem(lot)) { + auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress()); + CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT()); + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + + auto* inventoryComponent = buyer->GetComponent(); + if (!inventoryComponent) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable(); + CDItemComponentTable* itemComponentTable = CDClientManager::GetTable(); + int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM); + CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID); + + // Extra currency that needs to be deducted in case of crafting + auto craftingCurrencies = CDItemComponentTable::ParseCraftingCurrencies(itemComp); + for (const auto& [crafintCurrencyLOT, crafintCurrencyCount]: craftingCurrencies) { + if (inventoryComponent->GetLotCount(crafintCurrencyLOT) < (crafintCurrencyCount * count)) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + } + for (const auto& [crafintCurrencyLOT, crafintCurrencyCount]: craftingCurrencies) { + inventoryComponent->RemoveItem(crafintCurrencyLOT, crafintCurrencyCount * count); + } + + + float buyScalar = GetBuyScalar(); + const auto coinCost = static_cast(std::floor((itemComp.baseValue * buyScalar) * count)); + + Character* character = buyer->GetCharacter(); + if (!character || character->GetCoins() < coinCost) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + + if (Inventory::IsValidItem(itemComp.currencyLOT)) { + const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * buyScalar) * count; + if (inventoryComponent->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) { + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL); + return; + } + inventoryComponent->RemoveItem(itemComp.currencyLOT, altCurrencyCost); + } + + character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR); + inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR); + GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS); + +} \ No newline at end of file diff --git a/dGame/dComponents/VendorComponent.h b/dGame/dComponents/VendorComponent.h index 48b766d2..9025148b 100644 --- a/dGame/dComponents/VendorComponent.h +++ b/dGame/dComponents/VendorComponent.h @@ -47,6 +47,7 @@ class VendorComponent : public Component { m_DirtyVendor = true; } + void Buy(Entity* buyer, LOT lot, uint32_t count); private: void SetupMaxCustomVendor(); diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index c38ef880..a62bf382 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -78,6 +78,7 @@ #include "LevelProgressionComponent.h" #include "DonationVendorComponent.h" #include "GhostComponent.h" +#include "AchievementVendorComponent.h" // Message includes: #include "dZoneManager.h" @@ -97,6 +98,7 @@ #include "ePetAbilityType.h" #include "ActivityManager.h" #include "PlayerManager.h" +#include "eVendorTransactionResult.h" #include "CDComponentsRegistryTable.h" #include "CDObjectsTable.h" @@ -1323,15 +1325,14 @@ void GameMessages::SendVendorStatusUpdate(Entity* entity, const SystemAddress& s SEND_PACKET; } -void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr) { +void GameMessages::SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr, eVendorTransactionResult result) { CBITSTREAM; CMSGHEADER; - int iResult = 0x02; // success, seems to be the only relevant one bitStream.Write(entity->GetObjectID()); bitStream.Write(eGameMessageType::VENDOR_TRANSACTION_RESULT); - bitStream.Write(iResult); + bitStream.Write(result); SEND_PACKET; } @@ -4664,94 +4665,27 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream* inStream, Entity* enti if (!user) return; Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar()); if (!player) return; - - auto* propertyVendorComponent = static_cast(entity->GetComponent(eReplicaComponentType::PROPERTY_VENDOR)); - - if (propertyVendorComponent != nullptr) { - propertyVendorComponent->OnBuyFromVendor(player, bConfirmed, item, count); - + + // handle buying normal items + auto* vendorComponent = entity->GetComponent(); + if (vendorComponent) { + vendorComponent->Buy(player, item, count); return; } - const auto isCommendationVendor = entity->GetLOT() == 13806; - - auto* vend = entity->GetComponent(); - if (!vend && !isCommendationVendor) return; - - auto* inv = player->GetComponent(); - if (!inv) return; - - if (!isCommendationVendor && !vend->SellsItem(item)) { - LOG("User %llu %s tried to buy an item %i from a vendor when they do not sell said item", player->GetObjectID(), user->GetUsername().c_str(), item); + // handle buying achievement items + auto* achievementVendorComponent = entity->GetComponent(); + if (achievementVendorComponent) { + achievementVendorComponent->Buy(player, item, count); return; } - CDComponentsRegistryTable* compRegistryTable = CDClientManager::GetTable(); - CDItemComponentTable* itemComponentTable = CDClientManager::GetTable(); - - int itemCompID = compRegistryTable->GetByIDAndType(item, eReplicaComponentType::ITEM); - CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID); - - Character* character = player->GetCharacter(); - if (!character) return; - - // Extra currency that needs to be deducted in case of crafting - auto craftingCurrencies = CDItemComponentTable::ParseCraftingCurrencies(itemComp); - for (const auto& craftingCurrency : craftingCurrencies) { - inv->RemoveItem(craftingCurrency.first, craftingCurrency.second * count); - } - - if (isCommendationVendor) { - if (itemComp.commendationLOT != 13763) { - return; - } - - auto* missionComponent = player->GetComponent(); - - if (missionComponent == nullptr) { - return; - } - - LOT tokenId = -1; - - if (missionComponent->GetMissionState(545) == eMissionState::COMPLETE) tokenId = 8318; // "Assembly Token" - if (missionComponent->GetMissionState(556) == eMissionState::COMPLETE) tokenId = 8321; // "Venture League Token" - if (missionComponent->GetMissionState(567) == eMissionState::COMPLETE) tokenId = 8319; // "Sentinels Token" - if (missionComponent->GetMissionState(578) == eMissionState::COMPLETE) tokenId = 8320; // "Paradox Token" - - const uint32_t altCurrencyCost = itemComp.commendationCost * count; - - if (inv->GetLotCount(tokenId) < altCurrencyCost) { - return; - } - - inv->RemoveItem(tokenId, altCurrencyCost); - - inv->AddItem(item, count, eLootSourceType::VENDOR); - } else { - float buyScalar = vend->GetBuyScalar(); - - const auto coinCost = static_cast(std::floor((itemComp.baseValue * buyScalar) * count)); - - if (character->GetCoins() < coinCost) { - return; - } - - if (Inventory::IsValidItem(itemComp.currencyLOT)) { - const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * buyScalar) * count; - - if (inv->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) { - return; - } - - inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost); - } - - character->SetCoins(character->GetCoins() - (coinCost), eLootSourceType::VENDOR); - inv->AddItem(item, count, eLootSourceType::VENDOR); + // Handle buying properties + auto* propertyVendorComponent = entity->GetComponent(); + if (propertyVendorComponent) { + propertyVendorComponent->OnBuyFromVendor(player, bConfirmed, item, count); + return; } - - GameMessages::SendVendorTransactionResult(entity, sysAddr); } void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { @@ -4785,7 +4719,10 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID); // Items with a base value of 0 or max int are special items that should not be sold if they're not sub items - if (itemComp.baseValue == 0 || itemComp.baseValue == UINT_MAX) return; + if (itemComp.baseValue == 0 || itemComp.baseValue == UINT_MAX) { + GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::SELL_FAIL); + return; + } float sellScalar = vend->GetSellScalar(); if (Inventory::IsValidItem(itemComp.currencyLOT)) { @@ -4793,11 +4730,9 @@ void GameMessages::HandleSellToVendor(RakNet::BitStream* inStream, Entity* entit inv->AddItem(itemComp.currencyLOT, std::floor(altCurrency), eLootSourceType::VENDOR); // Return alt currencies like faction tokens. } - //inv->RemoveItem(count, -1, iObjID); inv->MoveItemToInventory(item, eInventoryType::VENDOR_BUYBACK, count, true, false, true); character->SetCoins(std::floor(character->GetCoins() + (static_cast(itemComp.baseValue * sellScalar) * count)), eLootSourceType::VENDOR); - //Game::entityManager->SerializeEntity(player); // so inventory updates - GameMessages::SendVendorTransactionResult(entity, sysAddr); + GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::SELL_SUCCESS); } void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { @@ -4839,16 +4774,16 @@ void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* const auto cost = static_cast(std::floor(((itemComp.baseValue * sellScalar) * count))); if (character->GetCoins() < cost) { + GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_FAIL); return; } if (Inventory::IsValidItem(itemComp.currencyLOT)) { const uint32_t altCurrencyCost = std::floor(itemComp.altCurrencyCost * sellScalar) * count; - if (inv->GetLotCount(itemComp.currencyLOT) < altCurrencyCost) { + GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_FAIL); return; } - inv->RemoveItem(itemComp.currencyLOT, altCurrencyCost); } @@ -4856,7 +4791,7 @@ void GameMessages::HandleBuybackFromVendor(RakNet::BitStream* inStream, Entity* inv->MoveItemToInventory(item, Inventory::FindInventoryTypeForLot(item->GetLot()), count, true, false); character->SetCoins(character->GetCoins() - cost, eLootSourceType::VENDOR); //Game::entityManager->SerializeEntity(player); // so inventory updates - GameMessages::SendVendorTransactionResult(entity, sysAddr); + GameMessages::SendVendorTransactionResult(entity, sysAddr, eVendorTransactionResult::PURCHASE_SUCCESS); } void GameMessages::HandleParseChatMessage(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) { diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index a96bbf60..9604d261 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -38,6 +38,7 @@ enum class eUseItemResponse : uint32_t; enum class eQuickBuildFailReason : uint32_t; enum class eQuickBuildState : uint32_t; enum class BehaviorSlot : int32_t; +enum class eVendorTransactionResult : uint32_t; namespace GameMessages { class PropertyDataMessage; @@ -135,7 +136,7 @@ namespace GameMessages { void SendVendorOpenWindow(Entity* entity, const SystemAddress& sysAddr); void SendVendorStatusUpdate(Entity* entity, const SystemAddress& sysAddr, bool bUpdateOnly = false); - void SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr); + void SendVendorTransactionResult(Entity* entity, const SystemAddress& sysAddr, eVendorTransactionResult result); void SendRemoveItemFromInventory(Entity* entity, const SystemAddress& sysAddr, LWOOBJID iObjID, LOT templateID, int inventoryType, uint32_t stackCount, uint32_t stackRemaining); void SendConsumeClientItem(Entity* entity, bool bSuccess, LWOOBJID item); diff --git a/dNet/AuthPackets.cpp b/dNet/AuthPackets.cpp index 25ccc902..54c28299 100644 --- a/dNet/AuthPackets.cpp +++ b/dNet/AuthPackets.cpp @@ -82,7 +82,7 @@ void AuthPackets::SendHandshake(dServer* server, const SystemAddress& sysAddr, c if (serverType == ServerType::Auth) bitStream.Write(ServiceId::Auth); else if (serverType == ServerType::World) bitStream.Write(ServiceId::World); else bitStream.Write(ServiceId::General); - bitStream.Write(774909490); + bitStream.Write(215523405360); server->Send(&bitStream, sysAddr, false); }