From 1acb57e53f99e7f3f006c5e46bd2b66898ebc3b5 Mon Sep 17 00:00:00 2001
From: MobiusDevelopment <8391001+MobiusDevelopment@users.noreply.github.com>
Date: Fri, 30 Apr 2021 16:29:22 +0000
Subject: [PATCH] Addition of VIP system. Contributed by marciox25.
---
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 60 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/29500-29599.xml | 60 ++-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/55300-55399.xml | 20 +
.../dist/game/data/vip.xml | 58 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 78 +++-
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 60 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/29500-29599.xml | 56 ++-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/55300-55399.xml | 20 +
.../dist/game/data/vip.xml | 58 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 78 +++-
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 60 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/29500-29599.xml | 56 ++-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/55300-55399.xml | 20 +
.../dist/game/data/vip.xml | 58 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 78 +++-
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 60 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/29500-29599.xml | 56 ++-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/55300-55399.xml | 20 +
.../dist/game/data/vip.xml | 58 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 75 ++-
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 60 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/29500-29599.xml | 56 ++-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/55300-55399.xml | 20 +
.../dist/game/data/vip.xml | 58 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 75 ++-
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 26 ++
.../dist/game/data/PrimeShop.xml | 72 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/71100-71199.xml | 73 ++-
.../game/data/stats/items/71200-71299.xml | 20 +-
.../game/data/stats/items/71300-71399.xml | 32 +-
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/56000-56099.xml | 10 +
.../game/data/stats/skills/59100-59199.xml | 20 +
.../dist/game/data/vip.xml | 62 +++
.../dist/game/data/xsd/PrimeShop.xsd | 3 +
.../dist/game/data/xsd/vip.xsd | 26 ++
.../java/org/l2jmobius/Config.java | 28 ++
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/PrimeShopData.java | 25 +-
.../gameserver/data/xml/VipData.java | 156 +++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 77 ++++
.../model/actor/templates/NpcTemplate.java | 76 ++-
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/itemcontainer/Inventory.java | 2 +
.../model/itemcontainer/PlayerInventory.java | 76 +++
.../model/primeshop/PrimeShopGroup.java | 22 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 82 ++++
.../gameserver/model/vip/VipManager.java | 212 +++++++++
.../gameserver/network/ExIncomingPackets.java | 9 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 131 +++++-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../vip/RequestVipProductList.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../vip/ReceiveVipProductList.java | 90 ++++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 22 +
.../dist/game/data/PrimeShop.xml | 51 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/71100-71199.xml | 73 ++-
.../game/data/stats/items/71200-71299.xml | 20 +-
.../game/data/stats/items/71300-71399.xml | 76 +--
.../game/data/stats/items/99000-99099.xml | 57 +++
.../game/data/stats/skills/55000-55099.xml | 291 ++++++++++++
.../game/data/stats/skills/56000-56099.xml | 10 +
.../game/data/stats/skills/59100-59199.xml | 20 +
.../game/data/stats/skills/59700-59799.xml | 327 ++++++++++++-
.../dist/game/data/vip.xml | 245 ++++++++++
.../dist/game/data/xsd/PrimeShop.xsd | 2 +
.../dist/game/data/xsd/vip.xsd | 24 +
.../java/org/l2jmobius/Config.java | 22 +
.../org/l2jmobius/gameserver/GameServer.java | 6 +-
.../gameserver/data/xml/VipData.java | 152 ++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 61 +++
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/primeshop/PrimeShopGroup.java | 15 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 60 +++
.../gameserver/model/vip/VipManager.java | 202 ++++++++
.../gameserver/network/ExIncomingPackets.java | 6 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../RequestPurchaseLimitShopItemBuy.java | 7 +-
.../primeshop/RequestBRBuyProduct.java | 44 +-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
.../dist/game/config/AttendanceRewards.ini | 4 +
.../dist/game/config/Custom/PcCafe.ini | 3 +
.../dist/game/config/Custom/VipSystem.ini | 22 +
.../dist/game/data/PrimeShop.xml | 51 ++-
.../scripts/handlers/EffectMasterHandler.java | 1 +
.../handlers/effecthandlers/VipUp.java | 60 +++
.../game/data/stats/items/71100-71199.xml | 73 ++-
.../game/data/stats/items/71200-71299.xml | 20 +-
.../game/data/stats/items/71300-71399.xml | 76 +--
.../game/data/stats/items/99000-99099.xml | 57 +++
.../game/data/stats/skills/55000-55099.xml | 431 ++++++++++++++++++
.../game/data/stats/skills/56000-56099.xml | 10 +
.../game/data/stats/skills/59100-59199.xml | 20 +
.../game/data/stats/skills/59700-59799.xml | 327 ++++++++++++-
.../dist/game/data/vip.xml | 245 ++++++++++
.../dist/game/data/xsd/PrimeShop.xsd | 2 +
.../dist/game/data/xsd/vip.xsd | 24 +
.../java/org/l2jmobius/Config.java | 22 +
.../org/l2jmobius/gameserver/GameServer.java | 4 +
.../gameserver/data/xml/VipData.java | 152 ++++++
.../instancemanager/DailyTaskManager.java | 21 +
.../instancemanager/PcCafePointsManager.java | 5 +
.../model/actor/instance/PlayerInstance.java | 61 +++
.../gameserver/model/events/EventType.java | 2 +
.../impl/creature/player/OnPlayerLoad.java | 45 ++
.../model/primeshop/PrimeShopGroup.java | 15 +
.../model/variables/AccountVariables.java | 29 ++
.../gameserver/model/vip/VipInfo.java | 60 +++
.../gameserver/model/vip/VipManager.java | 202 ++++++++
.../gameserver/network/ExIncomingPackets.java | 6 +-
.../attendance/RequestVipAttendanceCheck.java | 5 +
.../RequestPurchaseLimitShopItemBuy.java | 5 +
.../primeshop/RequestBRBuyProduct.java | 44 +-
.../primeshop/RequestBRPresentBuyProduct.java | 11 +
.../clientpackets/vip/ExRequestVipInfo.java | 37 ++
.../vip/RequestVipLuckGameInfo.java | 37 ++
.../serverpackets/ExBRNewIconCashBtnWnd.java | 41 ++
.../serverpackets/ExBrPremiumState.java | 2 +-
.../network/serverpackets/ExWorldChatCnt.java | 2 +-
.../serverpackets/vip/ReceiveVipInfo.java | 60 +++
.../vip/ReceiveVipLuckyGameInfo.java | 48 ++
331 files changed, 16039 insertions(+), 487 deletions(-)
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/VipSystem.ini
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/dist/game/data/vip.xml
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/vip.xsd
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/VipData.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipManager.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
create mode 100644 L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/PrimeShop.xml
index 53ce59d410..b4c2e6699a 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/PrimeShop.xml
@@ -1,3 +1,61 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/EffectMasterHandler.java
index a2a0997bae..770b0ba3f3 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -377,6 +377,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/items/29500-29599.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/items/29500-29599.xml
index 6501ae38f3..fb9f4b965f 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/items/29500-29599.xml
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/items/29500-29599.xml
@@ -78,50 +78,70 @@
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55000-55099.xml
index bb14ec8fca..f854d192d7 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55300-55399.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55300-55399.xml
index 51de226476..9a0ea18ebc 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55300-55399.xml
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/stats/skills/55300-55399.xml
@@ -741,21 +741,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 1
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 10
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 100
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 280
+
+
A1
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/vip.xml b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/vip.xml
new file mode 100644
index 0000000000..1154e204af
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/vip.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/Config.java
index 2a74d75080..42a6513a0a 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1231,6 +1233,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1238,6 +1241,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1525,6 +1535,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3196,6 +3207,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3224,6 +3236,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/GameServer.java
index 17ca9749c0..25d7983aae 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/GameServer.java
@@ -101,6 +101,7 @@ import org.l2jmobius.gameserver.data.xml.StaticObjectData;
import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -147,6 +148,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -274,6 +276,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -291,6 +294,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index 8954243ced..dd1abc002c 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index e5d518dfb3..3190272037 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -199,6 +201,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -269,6 +272,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -344,6 +348,7 @@ import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
@@ -846,7 +851,7 @@ public class PlayerInstance extends Playable
private boolean _hasCharmOfCourage = false;
private final Set _whisperers = ConcurrentHashMap.newKeySet();
-
+ private byte _vipTier = 0;
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -2950,6 +2955,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -6615,6 +6636,8 @@ public class PlayerInstance extends Playable
return null;
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
+
if (player.isGM())
{
final long masks = player.getVariables().getLong(COND_OVERRIDE_KEY, PlayerCondOverride.getAllExceptionsMask());
@@ -6711,6 +6734,7 @@ public class PlayerInstance extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
+
}
catch (Exception e)
{
@@ -9989,6 +10013,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -13983,4 +14008,55 @@ public class PlayerInstance extends Playable
getVariables().set(ATTENDANCE_INDEX_VAR, rewardIndex);
}
}
+
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index 827115a4dd..e6b3a6e1ed 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -45,6 +45,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -701,7 +702,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -718,15 +718,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -774,9 +767,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/EventType.java
index eebca64a89..f10b1095c8 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -88,6 +88,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -257,6 +258,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 7ef1a47825..5edbf35476 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -80,6 +80,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 6792706c97..c416f0ab58 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 838672e8ff..3d0edcc1e0 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -85,6 +85,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -346,11 +349,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x107, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x108, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x10A, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10B, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x10A, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10B, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10C, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10D, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10E, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10E, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10F, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x110, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x111, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_2.0_Saviors/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/PrimeShop.xml
index 53ce59d410..b4c2e6699a 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/PrimeShop.xml
@@ -1,3 +1,61 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/EffectMasterHandler.java
index a2a0997bae..770b0ba3f3 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -377,6 +377,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/items/29500-29599.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/items/29500-29599.xml
index 9cf5cc85ee..7a292f52eb 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/items/29500-29599.xml
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/items/29500-29599.xml
@@ -73,46 +73,70 @@
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55000-55099.xml
index 70d619807b..9941e26537 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55300-55399.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55300-55399.xml
index 312711f3fa..d10b5f5aa3 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55300-55399.xml
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/stats/skills/55300-55399.xml
@@ -741,21 +741,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 1
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 10
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 100
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 280
+
+
A1
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/vip.xml b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/vip.xml
new file mode 100644
index 0000000000..1154e204af
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/vip.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/Config.java
index b3cc117028..5ad193bde5 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1235,6 +1237,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1242,6 +1245,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1529,6 +1539,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3202,6 +3213,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3230,6 +3242,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/GameServer.java
index 17ca9749c0..25d7983aae 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/GameServer.java
@@ -101,6 +101,7 @@ import org.l2jmobius.gameserver.data.xml.StaticObjectData;
import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -147,6 +148,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -274,6 +276,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -291,6 +294,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index f0bcd601a9..e2b12db0f0 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -199,6 +201,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -269,6 +272,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -344,6 +348,7 @@ import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
@@ -846,7 +851,7 @@ public class PlayerInstance extends Playable
private boolean _hasCharmOfCourage = false;
private final Set _whisperers = ConcurrentHashMap.newKeySet();
-
+ private byte _vipTier = 0;
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -2950,6 +2955,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -6615,6 +6636,8 @@ public class PlayerInstance extends Playable
return null;
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
+
if (player.isGM())
{
final long masks = player.getVariables().getLong(COND_OVERRIDE_KEY, PlayerCondOverride.getAllExceptionsMask());
@@ -6711,6 +6734,7 @@ public class PlayerInstance extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
+
}
catch (Exception e)
{
@@ -9989,6 +10013,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -13983,4 +14008,55 @@ public class PlayerInstance extends Playable
getVariables().set(ATTENDANCE_INDEX_VAR, rewardIndex);
}
}
+
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index 827115a4dd..e6b3a6e1ed 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -45,6 +45,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -701,7 +702,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -718,15 +718,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -774,9 +767,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/EventType.java
index eebca64a89..f10b1095c8 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -88,6 +88,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -257,6 +258,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 7ef1a47825..5edbf35476 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -80,6 +80,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 6792706c97..c416f0ab58 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index a45ee6476d..832172d8a8 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -88,6 +88,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -350,11 +353,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x107, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x108, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x10A, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10B, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x10A, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10B, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10C, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10D, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10E, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10E, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10F, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x110, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x111, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_2.1_Zaken/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/PrimeShop.xml
index 53ce59d410..b4c2e6699a 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/PrimeShop.xml
@@ -1,3 +1,61 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/EffectMasterHandler.java
index 7146f13915..9e292c0bb9 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -378,6 +378,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/items/29500-29599.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/items/29500-29599.xml
index 11d5158104..8b76de0fd2 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/items/29500-29599.xml
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/items/29500-29599.xml
@@ -73,46 +73,70 @@
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55000-55099.xml
index b25169a7a6..4e75d28158 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55300-55399.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55300-55399.xml
index b4da4aca6e..732718feba 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55300-55399.xml
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/stats/skills/55300-55399.xml
@@ -741,21 +741,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 1
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 10
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 100
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 280
+
+
A1
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/vip.xml b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/vip.xml
new file mode 100644
index 0000000000..1154e204af
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/vip.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/Config.java
index b3cc117028..5ad193bde5 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1235,6 +1237,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1242,6 +1245,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1529,6 +1539,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3202,6 +3213,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3230,6 +3242,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/GameServer.java
index 3800ba7ee3..3d39a231ef 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/GameServer.java
@@ -102,6 +102,7 @@ import org.l2jmobius.gameserver.data.xml.StaticObjectData;
import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -148,6 +149,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -276,6 +278,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -293,6 +296,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 044bc59da9..ca8b75ff20 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -199,6 +201,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -268,6 +271,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -342,6 +346,7 @@ import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
@@ -844,7 +849,7 @@ public class PlayerInstance extends Playable
private boolean _hasCharmOfCourage = false;
private final Set _whisperers = ConcurrentHashMap.newKeySet();
-
+ private byte _vipTier = 0;
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -2948,6 +2953,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -6601,6 +6622,8 @@ public class PlayerInstance extends Playable
return null;
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
+
if (player.isGM())
{
final long masks = player.getVariables().getLong(COND_OVERRIDE_KEY, PlayerCondOverride.getAllExceptionsMask());
@@ -6697,6 +6720,7 @@ public class PlayerInstance extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
+
}
catch (Exception e)
{
@@ -9975,6 +9999,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -13968,4 +13993,55 @@ public class PlayerInstance extends Playable
getVariables().set(ATTENDANCE_INDEX_VAR, rewardIndex);
}
}
+
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index 827115a4dd..e6b3a6e1ed 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -45,6 +45,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -701,7 +702,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -718,15 +718,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -774,9 +767,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/EventType.java
index eebca64a89..f10b1095c8 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -88,6 +88,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -257,6 +258,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index f74c60bf12..f10b1c7634 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -83,6 +83,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 0236dae45b..0e978d19bf 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 8863d43c90..31ad6c8e8e 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -88,6 +88,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -351,11 +354,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x107, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x108, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x10A, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10B, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x10A, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10B, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10C, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10D, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10E, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10E, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10F, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x110, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x111, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_2.2_Antharas/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/PrimeShop.xml
index 53ce59d410..b4c2e6699a 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/PrimeShop.xml
@@ -1,3 +1,61 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
index e0272bb4b8..03b1447e4f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -382,6 +382,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/items/29500-29599.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/items/29500-29599.xml
index f953fd9138..3692602f1b 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/items/29500-29599.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/items/29500-29599.xml
@@ -73,46 +73,70 @@
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55000-55099.xml
index ab00c09755..774e70a223 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55300-55399.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55300-55399.xml
index 48eda10dc9..08632f6293 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55300-55399.xml
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/stats/skills/55300-55399.xml
@@ -741,21 +741,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 1
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 10
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 100
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 280
+
+
A1
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/vip.xml b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/vip.xml
new file mode 100644
index 0000000000..1154e204af
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/vip.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/Config.java
index a94687f70d..7524966270 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1235,6 +1237,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1242,6 +1245,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1529,6 +1539,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3203,6 +3214,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3231,6 +3243,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
index 9d557dc902..b20cf540c6 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/GameServer.java
@@ -103,6 +103,7 @@ import org.l2jmobius.gameserver.data.xml.StaticObjectData;
import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -149,6 +150,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -278,6 +280,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -295,6 +298,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 619efb2e30..2f570f1826 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -272,6 +274,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -346,6 +349,7 @@ import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
@@ -404,7 +408,7 @@ public class PlayerInstance extends Playable
// Character Shortcut SQL String Definitions:
private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE charId=? AND class_index=?";
- // Character Recipe List Save:
+ // Character Recipe List Save
private static final String DELETE_CHAR_RECIPE_SHOP = "DELETE FROM character_recipeshoplist WHERE charId=?";
private static final String INSERT_CHAR_RECIPE_SHOP = "REPLACE INTO character_recipeshoplist (`charId`, `recipeId`, `price`, `index`) VALUES (?, ?, ?, ?)";
private static final String RESTORE_CHAR_RECIPE_SHOP = "SELECT * FROM character_recipeshoplist WHERE charId=? ORDER BY `index`";
@@ -855,6 +859,8 @@ public class PlayerInstance extends Playable
private ElementalSpirit[] _spirits;
private ElementalType _activeElementalSpiritType;
+ private byte _vipTier = 0;
+
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -2959,6 +2965,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -14018,6 +14040,57 @@ public class PlayerInstance extends Playable
}
}
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
+
public void initElementalSpirits()
{
tryLoadSpirits();
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index c302df57c8..e168e7199c 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -716,7 +717,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -733,15 +733,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -789,9 +782,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
index 51c19667fd..8cf9f32b70 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -90,6 +90,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -259,6 +260,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 7a66a6031c..29ba4c70fc 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -83,6 +83,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 0236dae45b..0e978d19bf 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index c5db652387..eefd47d443 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -98,6 +98,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -361,11 +364,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x107, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x108, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x10A, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10B, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x10A, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10B, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10C, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10D, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10E, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10E, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10F, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x110, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x111, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_2.3_SevenSigns/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/PrimeShop.xml
index 53ce59d410..b4c2e6699a 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/PrimeShop.xml
@@ -1,3 +1,61 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
index e0272bb4b8..03b1447e4f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -382,6 +382,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/items/29500-29599.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/items/29500-29599.xml
index f953fd9138..3692602f1b 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/items/29500-29599.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/items/29500-29599.xml
@@ -73,46 +73,70 @@
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55000-55099.xml
index e230db43cd..9386d59e78 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55300-55399.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55300-55399.xml
index bb22f9cd5e..7d88998a98 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55300-55399.xml
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/stats/skills/55300-55399.xml
@@ -741,21 +741,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 1
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 10
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 100
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 280
+
+
A1
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/vip.xml b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/vip.xml
new file mode 100644
index 0000000000..1154e204af
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/vip.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/Config.java
index c002ef6edc..b79e592c45 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1240,6 +1242,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1247,6 +1250,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1534,6 +1544,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3212,6 +3223,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3240,6 +3252,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
index 19f8f32197..ac3816bbe1 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/GameServer.java
@@ -104,6 +104,7 @@ import org.l2jmobius.gameserver.data.xml.StaticObjectData;
import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -150,6 +151,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -280,6 +282,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -297,6 +300,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 27e54e11d0..69d3708d99 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -272,6 +274,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -346,6 +349,7 @@ import org.l2jmobius.gameserver.network.serverpackets.UserInfo;
import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.PlayerAutoSaveTaskManager;
import org.l2jmobius.gameserver.taskmanager.PvpFlagTaskManager;
@@ -404,7 +408,7 @@ public class PlayerInstance extends Playable
// Character Shortcut SQL String Definitions:
private static final String DELETE_CHAR_SHORTCUTS = "DELETE FROM character_shortcuts WHERE charId=? AND class_index=?";
- // Character Recipe List Save:
+ // Character Recipe List Save
private static final String DELETE_CHAR_RECIPE_SHOP = "DELETE FROM character_recipeshoplist WHERE charId=?";
private static final String INSERT_CHAR_RECIPE_SHOP = "REPLACE INTO character_recipeshoplist (`charId`, `recipeId`, `price`, `index`) VALUES (?, ?, ?, ?)";
private static final String RESTORE_CHAR_RECIPE_SHOP = "SELECT * FROM character_recipeshoplist WHERE charId=? ORDER BY `index`";
@@ -855,6 +859,8 @@ public class PlayerInstance extends Playable
private ElementalSpirit[] _spirits;
private ElementalType _activeElementalSpiritType;
+ private byte _vipTier = 0;
+
private final List _questTimers = new ArrayList<>();
private final List> _timerHolders = new ArrayList<>();
@@ -2959,6 +2965,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -14018,6 +14040,57 @@ public class PlayerInstance extends Playable
}
}
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
+
public void initElementalSpirits()
{
tryLoadSpirits();
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index c302df57c8..e168e7199c 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -716,7 +717,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -733,15 +733,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -789,9 +782,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
index 51c19667fd..8cf9f32b70 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -90,6 +90,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -259,6 +260,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 7a66a6031c..29ba4c70fc 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -83,6 +83,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 0236dae45b..0e978d19bf 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 8aab1ab8c9..a1d577a435 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -99,6 +99,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -362,11 +365,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x107, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x108, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x10A, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10B, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x10A, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10B, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10C, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10D, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10E, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10E, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10F, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x110, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x111, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_2.4_SecretOfEmpire/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..07217248b5
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,26 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWnd=true
+# -> needs to be true
+# Prime shop needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# Drop Amount of Silver coins if the Vip Tier allows it
+VipSilverDropMin = 1
+VipSilverDropMax = 5
+
+# Drop Amount of Golden coins if the Vip Tier allows it
+VipGoldenDropMin = 1
+VipGoldenDropMax = 5
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/PrimeShop.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/PrimeShop.xml
index 53ce59d410..b199f0e849 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/PrimeShop.xml
@@ -1,3 +1,73 @@
-
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/EffectMasterHandler.java
index f9dca4b930..b32ecec476 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -384,6 +384,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71100-71199.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71100-71199.xml
index c0557c551c..a10f5031fe 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71100-71199.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71100-71199.xml
@@ -758,84 +758,129 @@
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71200-71299.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71200-71299.xml
index 81e55ba07f..3bf252fce4 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71200-71299.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71200-71299.xml
@@ -716,24 +716,36 @@
-
-
+
+
+
+
-
+
+
+
+
-
-
+
+
+
+
-
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71300-71399.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71300-71399.xml
index 36fc5006c3..d40970f205 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71300-71399.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/items/71300-71399.xml
@@ -155,46 +155,70 @@
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/55000-55099.xml
index 7e69ca409f..7a2fe07d58 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/56000-56099.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/56000-56099.xml
index a3e4202eda..f1d17e3636 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/56000-56099.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/56000-56099.xml
@@ -546,11 +546,21 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 27
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 273
+
+
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/59100-59199.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/59100-59199.xml
index eade9ccfd6..c74069f2a0 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/59100-59199.xml
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/stats/skills/59100-59199.xml
@@ -139,21 +139,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 800
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 2400
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 80
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 240
+
+
A1
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/vip.xml b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/vip.xml
new file mode 100644
index 0000000000..c557eb6238
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/vip.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..530eeae8ab 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,9 @@
+
+
+
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..9e4f92a626
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/Config.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/Config.java
index c563c27c41..ad3825e01c 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/Config.java
@@ -132,6 +132,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -154,6 +155,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1243,6 +1245,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1250,6 +1253,13 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
+ public static int VIP_SYSTEM_GOLD_DROP_MIN;
+ public static int VIP_SYSTEM_GOLD_DROP_MAX;
+ public static int VIP_SYSTEM_SILVER_DROP_MIN;
+ public static int VIP_SYSTEM_SILVER_DROP_MAX;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1537,6 +1547,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3217,6 +3228,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3245,6 +3257,22 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ VIP_SYSTEM_SILVER_DROP_MIN = vipSystem.getInt("VipSilverDropMin", 1);
+ VIP_SYSTEM_SILVER_DROP_MAX = vipSystem.getInt("VipSilverDropMax", 5);
+ VIP_SYSTEM_GOLD_DROP_MIN = vipSystem.getInt("VipGoldenDropMin", 1);
+ VIP_SYSTEM_GOLD_DROP_MAX = vipSystem.getInt("VipGoldenDropMax", 5);
+ if (VIP_SYSTEM_MAX_TIER > 7)
+ {
+ VIP_SYSTEM_MAX_TIER = 7;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/GameServer.java
index 42956c9069..54fb7b5630 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/GameServer.java
@@ -106,6 +106,7 @@ import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TimedHuntingZoneData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -153,6 +154,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -283,6 +285,7 @@ public class GameServer
CommissionManager.getInstance();
LuckyGameData.getInstance();
AttendanceRewardData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -300,6 +303,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
index 3fac6f419a..a14c93d054 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/PrimeShopData.java
@@ -42,8 +42,10 @@ import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRProductInfo;
public class PrimeShopData implements IXmlReader
{
private static final Logger LOGGER = Logger.getLogger(PrimeShopData.class.getName());
+ private static final int VIP_GIFT_INIT_ID = 100000;
private final Map _primeItems = new LinkedHashMap<>();
+ private final Map _vipGifts = new LinkedHashMap<>(10);
protected PrimeShopData()
{
@@ -109,8 +111,15 @@ public class PrimeShopData implements IXmlReader
items.add(new PrimeShopItem(itemId, count, item.getWeight(), item.isTradeable() ? 1 : 0));
}
}
-
- _primeItems.put(set.getInt("id"), new PrimeShopGroup(set, items));
+ PrimeShopGroup group = new PrimeShopGroup(set, items);
+ if (group.isVipGift())
+ {
+ _vipGifts.put(set.getInt("id"), group);
+ }
+ else
+ {
+ _primeItems.put(set.getInt("id"), group);
+ }
}
}
}
@@ -131,7 +140,12 @@ public class PrimeShopData implements IXmlReader
public PrimeShopGroup getItem(int brId)
{
- return _primeItems.get(brId);
+ PrimeShopGroup item = _primeItems.get(brId);
+ if (item == null)
+ {
+ item = _vipGifts.get(brId);
+ }
+ return item;
}
public Map getPrimeItems()
@@ -148,4 +162,9 @@ public class PrimeShopData implements IXmlReader
{
protected static final PrimeShopData INSTANCE = new PrimeShopData();
}
+
+ public PrimeShopGroup getVipGiftOfTier(byte tier)
+ {
+ return _vipGifts.get(VIP_GIFT_INIT_ID + tier);
+ }
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..243c3d285d
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ final float silverChance = Float.parseFloat(c.getAttributes().getNamedItem("silverChance").getNodeValue());
+ final float goldChance = Float.parseFloat(c.getAttributes().getNamedItem("goldChance").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ vipInfo.setSilverCoinChance(silverChance);
+ vipInfo.setGoldCoinChance(goldChance);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index f033cf2f76..5a1c9dfb55 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -39,7 +39,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -68,6 +70,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetRecommends();
resetWorldChatPoints();
resetTrainingCamp();
+ resetVip();
}
@ScheduleTarget
@@ -254,6 +257,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index d9c5c12e20..f8752df2d0 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -206,6 +208,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -280,6 +283,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -356,6 +360,7 @@ import org.l2jmobius.gameserver.network.serverpackets.ValidateLocation;
import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySettingSend;
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
@@ -867,6 +872,8 @@ public class PlayerInstance extends Playable
private ElementalSpirit[] _spirits;
private ElementalType _activeElementalSpiritType;
+ private byte _vipTier = 0;
+
private final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
@@ -2882,6 +2889,22 @@ public class PlayerInstance extends Playable
return _inventory.getAdena();
}
+ /**
+ * @return the Gold Coin amount of the PlayerInstance.
+ */
+ public long getGoldCoin()
+ {
+ return _inventory.getGoldCoin();
+ }
+
+ /**
+ * @return the Silver Coin of the PlayerInstance.
+ */
+ public long getSilverCoin()
+ {
+ return _inventory.getSilverCoin();
+ }
+
/**
* @return the Ancient Adena amount of the PlayerInstance.
*/
@@ -6567,6 +6590,8 @@ public class PlayerInstance extends Playable
return null;
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
+
if (player.isGM())
{
final long masks = player.getVariables().getLong(COND_OVERRIDE_KEY, PlayerCondOverride.getAllExceptionsMask());
@@ -9944,6 +9969,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -14010,6 +14036,57 @@ public class PlayerInstance extends Playable
}
}
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
+
public void initElementalSpirits()
{
tryLoadSpirits();
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
index c302df57c8..e168e7199c 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/actor/templates/NpcTemplate.java
@@ -46,6 +46,7 @@ import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.model.stats.Stat;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.util.Util;
/**
@@ -716,7 +717,6 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
final List dropList = new ArrayList<>(getDropList(dropType));
-
// randomize drop order
Collections.shuffle(dropList);
@@ -733,15 +733,8 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
}
// check level gap that may prevent drop this item
- final double levelGapChanceToDrop;
- if (dropItem.getItemId() == Inventory.ADENA_ID)
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
- else
- {
- levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
- }
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+
if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
{
continue;
@@ -789,9 +782,72 @@ public class NpcTemplate extends CreatureTemplate implements IIdentifiable
calculatedDrops.add(new ItemHolder(Config.CHAMPION_REWARD_ID, Config.CHAMPION_REWARD_QTY));
}
+ if (dropType == DropType.DROP)
+ {
+ processVipDrops(calculatedDrops, victim, killer);
+ }
+
return calculatedDrops;
}
+ private void processVipDrops(Collection items, Creature victim, Creature killer)
+ {
+ final List dropList = new ArrayList<>();
+ if (killer.getActingPlayer() != null)
+ {
+ float silverCoinChance = VipManager.getInstance().getSilverCoinDropChance(killer.getActingPlayer());
+ float rustyCoinChance = VipManager.getInstance().getRustyCoinDropChance(killer.getActingPlayer());
+
+ if (silverCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.SILVER_COIN, Config.VIP_SYSTEM_SILVER_DROP_MIN, Config.VIP_SYSTEM_SILVER_DROP_MAX, silverCoinChance));
+ }
+
+ if (rustyCoinChance > 0)
+ {
+ dropList.add(new DropHolder(DropType.DROP, Inventory.GOLD_COIN, Config.VIP_SYSTEM_GOLD_DROP_MIN, Config.VIP_SYSTEM_GOLD_DROP_MAX, rustyCoinChance));
+ }
+ }
+
+ for (DropHolder dropItem : dropList)
+ {
+ final ItemHolder drop = calculateDropWithLevelGap(dropItem, victim, killer);
+ if (drop == null)
+ {
+ continue;
+ }
+
+ items.add(drop);
+ }
+ }
+
+ private ItemHolder calculateDropWithLevelGap(DropHolder dropItem, Creature victim, Creature killer)
+ {
+ final int levelDifference = victim.getLevel() - killer.getLevel();
+ final double levelGapChanceToDrop = calculateLevelGapChanceToDrop(dropItem, levelDifference);
+ if ((Rnd.nextDouble() * 100) > levelGapChanceToDrop)
+ {
+ return null;
+ }
+
+ return calculateDrop(dropItem, victim, killer);
+ }
+
+ private double calculateLevelGapChanceToDrop(DropHolder dropItem, int levelDifference)
+ {
+ final double levelGapChanceToDrop;
+
+ if (dropItem.getItemId() == Inventory.ADENA_ID)
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ADENA_MAX_LEVEL_DIFFERENCE, -Config.DROP_ADENA_MIN_LEVEL_DIFFERENCE, Config.DROP_ADENA_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ else
+ {
+ levelGapChanceToDrop = Util.map(levelDifference, -Config.DROP_ITEM_MAX_LEVEL_DIFFERENCE, -Config.DROP_ITEM_MIN_LEVEL_DIFFERENCE, Config.DROP_ITEM_MIN_LEVEL_GAP_CHANCE, 100.0);
+ }
+ return levelGapChanceToDrop;
+ }
+
/**
* All item drop chance calculations are done by this method.
* @param dropItem
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/EventType.java
index 51c19667fd..8cf9f32b70 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -90,6 +90,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -259,6 +260,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
index 19bc1c5300..0502e5bf64 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/Inventory.java
@@ -83,6 +83,8 @@ public abstract class Inventory extends ItemContainer
// Common Items
public static final int ADENA_ID = 57;
+ public static final int SILVER_COIN = 29983;
+ public static final int GOLD_COIN = 29984;
public static final int ANCIENT_ADENA_ID = 5575;
public static final int BEAUTY_TICKET_ID = 36308;
public static final int AIR_STONE_ID = 39461;
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
index 0236dae45b..0e978d19bf 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/itemcontainer/PlayerInventory.java
@@ -53,6 +53,8 @@ public class PlayerInventory extends Inventory
private final PlayerInstance _owner;
private ItemInstance _adena;
+ private ItemInstance _goldCoin;
+ private ItemInstance _silverCoin;
private ItemInstance _ancientAdena;
private ItemInstance _beautyTickets;
private Collection _blockItems = null;
@@ -93,6 +95,16 @@ public class PlayerInventory extends Inventory
return _adena != null ? _adena.getCount() : 0;
}
+ public long getGoldCoin()
+ {
+ return _goldCoin != null ? _goldCoin.getCount() : 0;
+ }
+
+ public long getSilverCoin()
+ {
+ return _silverCoin != null ? _silverCoin.getCount() : 0;
+ }
+
public ItemInstance getAncientAdenaInstance()
{
return _ancientAdena;
@@ -403,6 +415,14 @@ public class PlayerInventory extends Inventory
{
_adena = addedItem;
}
+ else if ((addedItem.getId() == SILVER_COIN) && !addedItem.equals(_silverCoin))
+ {
+ _silverCoin = addedItem;
+ }
+ else if ((addedItem.getId() == GOLD_COIN) && !addedItem.equals(_goldCoin))
+ {
+ _goldCoin = addedItem;
+ }
else if ((addedItem.getId() == ANCIENT_ADENA_ID) && !addedItem.equals(_ancientAdena))
{
_ancientAdena = addedItem;
@@ -467,6 +487,14 @@ public class PlayerInventory extends Inventory
{
_adena = item;
}
+ else if ((item.getId() == SILVER_COIN) && !item.equals(_silverCoin))
+ {
+ _silverCoin = item;
+ }
+ else if ((item.getId() == GOLD_COIN) && !item.equals(_goldCoin))
+ {
+ _goldCoin = item;
+ }
else if ((item.getId() == ANCIENT_ADENA_ID) && !item.equals(_ancientAdena))
{
_ancientAdena = item;
@@ -515,6 +543,18 @@ public class PlayerInventory extends Inventory
{
final ItemInstance item = super.transferItem(process, objectId, count, target, actor, reference);
+ if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
+ {
+ _adena = null;
+ }
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_adena != null) && ((_adena.getCount() <= 0) || (_adena.getOwnerId() != getOwnerId())))
{
_adena = null;
@@ -573,6 +613,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && (_silverCoin.getCount() <= 0))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && (_goldCoin.getCount() <= 0))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && (_ancientAdena.getCount() <= 0))
{
@@ -637,6 +685,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
@@ -671,6 +727,16 @@ public class PlayerInventory extends Inventory
_adena = null;
}
+ if ((_silverCoin != null) && ((_silverCoin.getCount() <= 0) || (_silverCoin.getOwnerId() != getOwnerId())))
+ {
+ _silverCoin = null;
+ }
+
+ if ((_goldCoin != null) && ((_goldCoin.getCount() <= 0) || (_goldCoin.getOwnerId() != getOwnerId())))
+ {
+ _goldCoin = null;
+ }
+
if ((_ancientAdena != null) && ((_ancientAdena.getCount() <= 0) || (_ancientAdena.getOwnerId() != getOwnerId())))
{
_ancientAdena = null;
@@ -720,6 +786,14 @@ public class PlayerInventory extends Inventory
{
_adena = null;
}
+ else if (item.getId() == SILVER_COIN)
+ {
+ _silverCoin = null;
+ }
+ else if (item.getId() == GOLD_COIN)
+ {
+ _goldCoin = null;
+ }
else if (item.getId() == ANCIENT_ADENA_ID)
{
_ancientAdena = null;
@@ -771,6 +845,8 @@ public class PlayerInventory extends Inventory
{
super.restore();
_adena = getItemByItemId(ADENA_ID);
+ _silverCoin = getItemByItemId(SILVER_COIN);
+ _goldCoin = getItemByItemId(GOLD_COIN);
_ancientAdena = getItemByItemId(ANCIENT_ADENA_ID);
_beautyTickets = getItemByItemId(BEAUTY_TICKET_ID);
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..e9d87771f6 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,9 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
+ private final int _silverCoin;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +76,10 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+ _silverCoin = set.getInt("silverCoin", 0);
+
_items = items;
}
@@ -196,8 +203,23 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
}
+
+ public int getSilverCoin()
+ {
+ return _silverCoin;
+ }
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbce4c8eea..1e8c85d8fc 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,10 +37,15 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -143,4 +148,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..f8fdb7d546
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private float _silverCoinChance;
+ private float _goldCoinChance;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+
+ public void setSilverCoinChance(float silverCoinChance)
+ {
+ _silverCoinChance = silverCoinChance;
+ }
+
+ public float getSilverCoinChance()
+ {
+ return _silverCoinChance;
+ }
+
+ public void setGoldCoinChance(float goldCoinChance)
+ {
+ _goldCoinChance = goldCoinChance;
+ }
+
+ public float getGoldCoinChance()
+ {
+ return _goldCoinChance;
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..85fe139b05
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ public float getSilverCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getSilverCoinChance();
+ }
+
+ public float getRustyCoinDropChance(PlayerInstance player)
+ {
+ return getVipInfo(player).getGoldCoinChance();
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 75fe43b953..377a123b92 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -109,6 +109,9 @@ import org.l2jmobius.gameserver.network.clientpackets.shuttle.MoveToLocationInSh
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOff;
import org.l2jmobius.gameserver.network.clientpackets.shuttle.RequestShuttleGetOn;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipProductList;
/**
* @author Sdw
@@ -379,11 +382,11 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_VIP_ATTENDANCE_CHECK(0x106, RequestVipAttendanceCheck::new, ConnectionState.IN_GAME),
REQUEST_ITEM_ENSOUL(0x107, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x108, null, ConnectionState.IN_GAME),
- REQUEST_VIP_PRODUCT_LIST(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10A, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_PRODUCT_LIST(0x109, RequestVipProductList::new, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10A, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10B, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10C, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10D, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10D, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10E, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x10F, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x110, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..dedfb5758e 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -17,6 +17,8 @@
package org.l2jmobius.gameserver.network.clientpackets.primeshop;
import java.util.Calendar;
+import java.util.LinkedList;
+import java.util.List;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
@@ -24,9 +26,11 @@ import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.gameserver.data.xml.PrimeShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
+import org.l2jmobius.gameserver.model.holders.ItemHolder;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -72,39 +76,68 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
if (validatePlayer(item, _count, player))
{
- final int price = (item.getPrice() * _count);
- final int paymentId = validatePaymentId(item, price);
- if (paymentId < 0)
+
+ boolean hasItems = true;
+ // First loop to validate all items
+ for (ItemHolder itemHolder : validatePaymentId(item))
+ {
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId < 0)
+ {
+ hasItems = false;
+ }
+ else if (paymentId > 0)
+ {
+ if (player.getInventory().getInventoryItemCount(paymentId, 0) < price)
+ {
+ hasItems = false;
+ }
+ }
+ else
+ { // this is always 0
+ if (player.getPrimePoints() < price)
+ {
+ hasItems = false;
+ }
+ }
+ }
+
+ if (!hasItems)
{
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
player.removeRequest(PrimeShopRequest.class);
return;
}
- else if (paymentId > 0)
+
+ // Second loop, only if all criteria has been met!
+ // this should always be reached if player has all the coins needed for the purchase
+ for (ItemHolder itemHolder : validatePaymentId(item))
{
- if (!player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true))
+ final int paymentId = itemHolder.getId();
+ final long price = itemHolder.getCount() * _count;
+ if (paymentId > 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.destroyItemByItemId("PrimeShop-" + item.getBrId(), paymentId, price, player, true);
}
- }
- else if (paymentId == 0)
- {
- if (player.getPrimePoints() < price)
+ else if (paymentId == 0)
{
- player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.LACK_OF_POINT));
- player.removeRequest(PrimeShopRequest.class);
- return;
+ player.setPrimePoints(player.getPrimePoints() - (int) price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
- player.setPrimePoints(player.getPrimePoints() - price);
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +202,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,23 +227,71 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
- private static int validatePaymentId(PrimeShopGroup item, long amount)
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
{
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
+ private static List validatePaymentId(PrimeShopGroup item)
+ {
+
+ List temp = new LinkedList<>();
switch (item.getPaymentType())
{
case 0: // Prime points
{
- return 0;
+ if (item.getVipTier() > 0)
+ {
+ if (item.getPrice() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.GOLD_COIN, item.getPrice()));
+ }
+ if (item.getSilverCoin() > 0)
+ {
+ temp.add(new ItemHolder(Inventory.SILVER_COIN, item.getSilverCoin()));
+ }
+ }
+ else
+ {
+ temp.add(new ItemHolder(0, item.getPrice())); // prime points
+ }
+ return temp;
}
case 1: // Adenas
{
- return Inventory.ADENA_ID;
+ temp.add(new ItemHolder(Inventory.ADENA_ID, item.getPrice())); // Is this even used????
+ return temp;
}
case 2: // Hero coins
{
- return HERO_COINS;
+ temp.add(new ItemHolder(HERO_COINS, item.getPrice())); // Is this even used????
+ return temp;
}
}
- return -1;
+ temp.add(new ItemHolder(-1, -1));
+ return temp;
}
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
new file mode 100644
index 0000000000..b2b90dd2ae
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipProductList.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipProductList;
+
+public class RequestVipProductList implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipProductList(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..ff7dc4754c
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+ private final static int LCOIN_ID = 91663; // FIXME: Does not exist in client.
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ ItemInstance item = _player.getInventory().getItemByItemId(LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
new file mode 100644
index 0000000000..7076033288
--- /dev/null
+++ b/L2J_Mobius_Classic_3.0_TheKamael/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipProductList.java
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.util.Collection;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.data.xml.PrimeShopData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
+import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipProductList implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipProductList(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ final Collection products = PrimeShopData.getInstance().getPrimeItems().values();
+ final PrimeShopGroup gift = PrimeShopData.getInstance().getVipGiftOfTier(_player.getVipTier());
+
+ OutgoingPackets.RECIVE_VIP_PRODUCT_LIST.writeId(packet);
+ packet.writeQ(_player.getAdena());
+ packet.writeQ(_player.getGoldCoin()); // Gold Coin Amount
+ packet.writeQ(_player.getSilverCoin()); // Silver Coin Amount
+ packet.writeC(1); // Show Reward tab
+
+ if (gift != null)
+ {
+ packet.writeD(products.size() + 1);
+ writeProduct(gift, packet);
+ }
+ else
+ {
+ packet.writeD(products.size());
+ }
+
+ for (PrimeShopGroup product : products)
+ {
+ writeProduct(product, packet);
+ }
+ return true;
+ }
+
+ private void writeProduct(PrimeShopGroup product, PacketWriter buffer)
+ {
+ buffer.writeD(product.getBrId());
+ buffer.writeC(product.getCat());
+ buffer.writeC(product.getPaymentType());
+ buffer.writeD(product.getPrice()); // L2 Coin | Gold Coin seems to use the same field based on payment type
+ buffer.writeD(product.getSilverCoin());
+ buffer.writeC(product.getPanelType()); // NEW - 6; HOT - 5 ... Unk
+ buffer.writeC(product.getVipTier());
+ buffer.writeC(10);
+
+ buffer.writeC(product.getItems().size());
+ for (PrimeShopItem item : product.getItems())
+ {
+ buffer.writeD(item.getId());
+ buffer.writeD((int) item.getCount());
+ }
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..7478c3c477
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,22 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWndAden=false
+# -> needs to be true
+# Prime shop Aden needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# When purchasing from the L Shop, the price amount will add to your vip points
+# P.S. this will only affect the purchases made with L Coin and not Adena!
+LShopAffectPoints = true
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/PrimeShop.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/PrimeShop.xml
index ae71392918..fa123b95a4 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/PrimeShop.xml
@@ -18,7 +18,56 @@
-
- -
+
-
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/EffectMasterHandler.java
index 6d49c69d18..349a12aa17 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -390,6 +390,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71100-71199.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71100-71199.xml
index 0bf3cd4a53..6ec0582d07 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71100-71199.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71100-71199.xml
@@ -740,84 +740,129 @@
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71200-71299.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71200-71299.xml
index c31d9ca69e..42df366bd1 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71200-71299.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71200-71299.xml
@@ -678,24 +678,36 @@
-
-
+
+
-
+
+
+
+
+
+
-
-
+
+
-
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71300-71399.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71300-71399.xml
index 9a3a51fef9..6f2da9ae86 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71300-71399.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/71300-71399.xml
@@ -154,50 +154,70 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/99000-99099.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/99000-99099.xml
index 6ef070550b..1bbe211e80 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/99000-99099.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/items/99000-99099.xml
@@ -9,4 +9,61 @@
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/55000-55099.xml
index d1d6fda4d9..63cb551cdb 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,327 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 3
+
+
+ 3
+
+
+ 50
+ PER
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 7
+
+
+ 7
+
+
+ 150
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 3
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 20
+ PER
+
+
+ 250
+ PER
+
+
+ 5
+ DIFF
+
+
+ -15
+ PER
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 20
+ PER
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 20
+ PER
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 5
+ PER
+
+
+ 20
+ PER
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/56000-56099.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/56000-56099.xml
index a3e4202eda..f1d17e3636 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/56000-56099.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/56000-56099.xml
@@ -546,11 +546,21 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 27
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 273
+
+
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59100-59199.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59100-59199.xml
index eade9ccfd6..c74069f2a0 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59100-59199.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59100-59199.xml
@@ -139,21 +139,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 800
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 2400
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 80
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 240
+
+
A1
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59700-59799.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59700-59799.xml
index d406b8184b..fa49b7fea1 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59700-59799.xml
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/stats/skills/59700-59799.xml
@@ -241,20 +241,323 @@
icon.skill0000
A1
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip8
+ P
+ 500
+
+
+ 35
+
+
+ 35
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -30
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 50
+ DIFF
+
+
+ 50
+ DIFF
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
+ 100
+ DIFF
+
+
+ 100
+ DIFF
+
+
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip9
+ P
+ 500
+
+
+ 40
+
+
+ 40
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -40
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 13
+ PER
+
+
+ 13
+ PER
+
+
+ 13
+ PER
+
+
+ 80
+ DIFF
+
+
+ 80
+ DIFF
+
+
+ 3
+ STR
+
+
+ 3
+ INT
+
+
+ 3
+ CON
+
+
+ 3
+ DEX
+
+
+ 3
+ MEN
+
+
+ 3
+ WIT
+
+
+ 200
+ DIFF
+
+
+ 200
+ DIFF
+
+
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip10
+ P
+ 500
+
+
+ 50
+
+
+ 50
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -50
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 100
+ DIFF
+
+
+ 100
+ DIFF
+
+
+ 4
+ STR
+
+
+ 4
+ INT
+
+
+ 4
+ CON
+
+
+ 4
+ DEX
+
+
+ 4
+ MEN
+
+
+ 4
+ WIT
+
+
+ 500
+ DIFF
+
+
+ 500
+ DIFF
+
+
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/vip.xml b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/vip.xml
new file mode 100644
index 0000000000..a797c36aab
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/vip.xml
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..8556f5ed3f 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,8 @@
+
+
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..bb2b4f589a
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/Config.java
index 30f30d9c96..20e99e426a 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/Config.java
@@ -134,6 +134,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -156,6 +157,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1261,6 +1263,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1268,6 +1271,10 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static boolean VIP_SYSTEM_L_SHOP_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1555,6 +1562,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3259,6 +3267,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3287,6 +3296,19 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_L_SHOP_AFFECT = vipSystem.getBoolean("LShopAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ if (VIP_SYSTEM_MAX_TIER > 10)
+ {
+ VIP_SYSTEM_MAX_TIER = 10;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
index d58f25365d..f2c5e1d59a 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/GameServer.java
@@ -80,8 +80,8 @@ import org.l2jmobius.gameserver.data.xml.InitialEquipmentData;
import org.l2jmobius.gameserver.data.xml.InitialShortcutData;
import org.l2jmobius.gameserver.data.xml.ItemCrystallizationData;
import org.l2jmobius.gameserver.data.xml.KarmaData;
-import org.l2jmobius.gameserver.data.xml.LimitShopData;
import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
import org.l2jmobius.gameserver.data.xml.LuckyGameData;
import org.l2jmobius.gameserver.data.xml.MagicLampData;
import org.l2jmobius.gameserver.data.xml.MultisellData;
@@ -110,6 +110,7 @@ import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TimedHuntingZoneData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -157,6 +158,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -291,6 +293,7 @@ public class GameServer
AttendanceRewardData.getInstance();
MagicLampData.getInstance();
RandomCraftData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -308,6 +311,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..f5321c909d
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index 3d1883674b..b4f79804eb 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -43,7 +43,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -73,6 +75,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetWorldChatPoints();
resetTrainingCamp();
resetVitality();
+ resetVip();
}
@ScheduleTarget
@@ -324,6 +327,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index 6bf49d433d..847b79431d 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -206,6 +208,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -283,6 +286,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -363,6 +367,7 @@ import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySetting
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
import org.l2jmobius.gameserver.network.serverpackets.limitshop.ExBloodyCoinCount;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
@@ -885,6 +890,8 @@ public class PlayerInstance extends Playable
private ElementalSpirit[] _spirits;
private ElementalType _activeElementalSpiritType;
+ private byte _vipTier = 0;
+
private final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
@@ -6673,6 +6680,7 @@ public class PlayerInstance extends Playable
}
}
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
}
}
@@ -6776,6 +6784,7 @@ public class PlayerInstance extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
+
}
catch (Exception e)
{
@@ -10073,6 +10082,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -14247,6 +14257,57 @@ public class PlayerInstance extends Playable
}
}
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
+
public void initElementalSpirits()
{
tryLoadSpirits();
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/EventType.java
index 51c19667fd..8cf9f32b70 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -90,6 +90,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -259,6 +260,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..b41635fc4d 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,8 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +75,9 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+
_items = items;
}
@@ -196,6 +201,16 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbb4b300bd..019fd7b35b 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,12 +37,17 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
public static final String LCOIN_SHOP_PRODUCT_TIME = "LCSTime";
public static final String LCOIN_SHOP_PRODUCT_COUNT = "LCSCount";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -145,4 +150,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..6c1121eb92
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..9e427b6e91
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index ad33458411..1acd9fe562 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -131,6 +131,8 @@ import org.l2jmobius.gameserver.network.clientpackets.teleports.ExRequestTelepor
import org.l2jmobius.gameserver.network.clientpackets.teleports.ExTeleportToRaidPosition;
import org.l2jmobius.gameserver.network.clientpackets.teleports.RequestRaidTeleportInfo;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
/**
* @author Sdw
@@ -402,10 +404,10 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_ITEM_ENSOUL(0x107, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x108, null, ConnectionState.IN_GAME),
REQUEST_VIP_PRODUCT_LIST(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10A, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10A, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10B, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10C, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10D, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10D, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10E, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x10F, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x110, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
index 308e6d0711..c61f55c841 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
@@ -19,11 +19,12 @@ package org.l2jmobius.gameserver.network.clientpackets.limitshop;
import java.util.ArrayList;
import java.util.List;
+import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.commons.util.Rnd;
-import org.l2jmobius.gameserver.data.xml.LimitShopData;
import org.l2jmobius.gameserver.data.xml.LimitShopCraftData;
+import org.l2jmobius.gameserver.data.xml.LimitShopData;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
import org.l2jmobius.gameserver.model.holders.LimitShopProductHolder;
@@ -173,6 +174,10 @@ public class RequestPurchaseLimitShopItemBuy implements IClientIncomingPacket
{
player.destroyItemByItemId("LCoinShop", _product.getIngredientIds()[i], _product.getIngredientQuantities()[i] * _amount, player, true);
}
+ if (Config.VIP_SYSTEM_L_SHOP_AFFECT)
+ {
+ player.updateVipPoints(_amount);
+ }
}
// Reward.
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..71ac7c2f4e 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -27,6 +27,7 @@ import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -98,13 +99,20 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +177,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,6 +202,34 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
private static int validatePaymentId(PrimeShopGroup item, long amount)
{
switch (item.getPaymentType())
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..807f938c81
--- /dev/null
+++ b/L2J_Mobius_Essence_4.0_DwellingOfSpirits/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ final ItemInstance item = _player.getInventory().getItemByItemId(Inventory.LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/AttendanceRewards.ini b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/AttendanceRewards.ini
index e4a80348fd..4047e00b6c 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/AttendanceRewards.ini
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/AttendanceRewards.ini
@@ -13,6 +13,10 @@ EnableAttendanceRewards = False
# Default: False
PremiumOnlyAttendanceRewards = False
+# Enable the Attendance Reward system only for Vip accounts.
+# Default: False
+VipOnlyAttendanceRewards = False
+
# Make rewards sharable in the same account.
# Default: False (Each character will receive its own rewards.)
AttendanceRewardsShareAccount = False
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/PcCafe.ini b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/PcCafe.ini
index 6dbccdc44a..446f64c1fd 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/PcCafe.ini
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/PcCafe.ini
@@ -9,6 +9,9 @@ PcCafeEnabled = False
# Allow only players with a Premium account.
PcCafeOnlyPremium = False
+# Allow only players with a Vip Tier account.
+PcCafeOnlyVip = False
+
# Max points that player may have.
# Limited by int limit.
MaxPcCafePoints = 200000
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/VipSystem.ini b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/VipSystem.ini
new file mode 100644
index 0000000000..7478c3c477
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/config/Custom/VipSystem.ini
@@ -0,0 +1,22 @@
+# ---------------------------------------------------------------------------
+# VIP System
+# ---------------------------------------------------------------------------
+
+# VIP System Enabled.
+# l2.ini
+# [VipSystem]
+# UseVipInfoWndAden=false
+# -> needs to be true
+# Prime shop Aden needs to be true aswell!
+# Check vip.xml for more info!
+VipEnabled = False
+
+# Max vip level that can be reached (Client Limitations, lv 8 -> 10 Doesn't exist. If u want to use, make it yourself!)
+MaxVipLevel = 7
+
+# When purchasing from the Prime Shop, the price amount will add to your vip points
+PrimeAffectPoints = true
+
+# When purchasing from the L Shop, the price amount will add to your vip points
+# P.S. this will only affect the purchases made with L Coin and not Adena!
+LShopAffectPoints = true
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/PrimeShop.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/PrimeShop.xml
index ae71392918..fa123b95a4 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/PrimeShop.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/PrimeShop.xml
@@ -18,7 +18,56 @@
-
- -
+
-
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/EffectMasterHandler.java b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/EffectMasterHandler.java
index 9339cb51e0..351519611a 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/EffectMasterHandler.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/EffectMasterHandler.java
@@ -391,6 +391,7 @@ public class EffectMasterHandler
EffectHandler.getInstance().registerHandler("Untargetable", Untargetable::new);
EffectHandler.getInstance().registerHandler("VampiricAttack", VampiricAttack::new);
EffectHandler.getInstance().registerHandler("VampiricDefence", VampiricDefence::new);
+ EffectHandler.getInstance().registerHandler("VipUp", VipUp::new);
EffectHandler.getInstance().registerHandler("VitalityExpRate", VitalityExpRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointsRate", VitalityPointsRate::new);
EffectHandler.getInstance().registerHandler("VitalityPointUp", VitalityPointUp::new);
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/effecthandlers/VipUp.java b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
new file mode 100644
index 0000000000..8c7a503e35
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/scripts/handlers/effecthandlers/VipUp.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.effecthandlers;
+
+import org.l2jmobius.gameserver.model.StatSet;
+import org.l2jmobius.gameserver.model.actor.Creature;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.effects.AbstractEffect;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.model.skills.Skill;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipUp extends AbstractEffect
+{
+ private final long _amount;
+
+ public VipUp(StatSet params)
+ {
+ _amount = params.getLong("amount", 0L);
+ }
+
+ @Override
+ public boolean isInstant()
+ {
+ return true;
+ }
+
+ @Override
+ public void instant(Creature effector, Creature effected, Skill skill, ItemInstance item)
+ {
+ if (effected == null)
+ {
+ return;
+ }
+
+ final PlayerInstance player = effected.getActingPlayer();
+ if (player == null)
+ {
+ return;
+ }
+
+ player.updateVipPoints(_amount);
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71100-71199.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71100-71199.xml
index 0bf3cd4a53..6ec0582d07 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71100-71199.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71100-71199.xml
@@ -740,84 +740,129 @@
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71200-71299.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71200-71299.xml
index c31d9ca69e..42df366bd1 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71200-71299.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71200-71299.xml
@@ -678,24 +678,36 @@
-
-
+
+
-
+
+
+
+
+
+
-
-
+
+
-
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71300-71399.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71300-71399.xml
index 9a3a51fef9..6f2da9ae86 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71300-71399.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/71300-71399.xml
@@ -154,50 +154,70 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/99000-99099.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/99000-99099.xml
index 6ef070550b..1bbe211e80 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/99000-99099.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/items/99000-99099.xml
@@ -9,4 +9,61 @@
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/55000-55099.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/55000-55099.xml
index 88a91169b4..e79fe434f7 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/55000-55099.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/55000-55099.xml
@@ -283,36 +283,467 @@
BranchIcon.Icon.g_skill_vip1
P
+ 500
+
+
+ 5
+
+
+ 5
+
+
+ 50
+ PER
+
+
+ 1
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip2
P
+ 500
+
+
+ 10
+
+
+ 10
+
+
+ 150
+ PER
+
+
+ 6
+ DIFF
+
+
BranchIcon.Icon.g_skill_vip3
P
+ 500
+
+
+ 15
+
+
+ 15
+
+
+ 200
+ PER
+
+
+ 6
+ DIFF
+
+
+ -10
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
+ 3
+ PER
+
+
BranchIcon.Icon.g_skill_vip4
P
+ 500
+
+
+ 25
+
+
+ 25
+
+
+ 250
+ PER
+
+
+ 10
+ DIFF
+
+
+ -20
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ DIFF
+
+
+ 10
+ DIFF
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip5
P
+ 500
+
+
+ 30
+
+
+ 30
+
+
+ 250
+ PER
+
+
+ 20
+ DIFF
+
+
+ -20
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 15
+ DIFF
+
+
+ 15
+ DIFF
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip6
P
+ 500
+
+
+ 35
+
+
+ 35
+
+
+ 250
+ PER
+
+
+ 20
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 2.5
+ PER
+
+
+ 2.5
+ PER
+
+
+ 2.5
+ PER
+
+
+ 20
+ DIFF
+
+
+ 20
+ DIFF
+
+
+ 1
+ STR
+
+
+ 1
+ INT
+
+
+ 1
+ CON
+
+
+ 1
+ DEX
+
+
+ 1
+ MEN
+
+
+ 1
+ WIT
+
+
BranchIcon.Icon.g_skill_vip7
P
+ 500
+
+
+ 35
+
+
+ 35
+
+
+ 250
+ PER
+
+
+ 40
+ DIFF
+
+
+ -20
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 10
+ PER
+
+
+ 30
+ DIFF
+
+
+ 30
+ DIFF
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/56000-56099.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/56000-56099.xml
index a3e4202eda..f1d17e3636 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/56000-56099.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/56000-56099.xml
@@ -546,11 +546,21 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 27
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 273
+
+
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59100-59199.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59100-59199.xml
index eade9ccfd6..c74069f2a0 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59100-59199.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59100-59199.xml
@@ -139,21 +139,41 @@
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 800
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 2400
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 80
+
+
BranchIcon.Icon.g_bm_vip_potion_i00
A1
1000
+
+
+ 240
+
+
A1
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59700-59799.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59700-59799.xml
index 1f5119dc94..2a44e334cf 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59700-59799.xml
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/stats/skills/59700-59799.xml
@@ -241,20 +241,323 @@
icon.skill0000
A1
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip8
+ P
+ 500
+
+
+ 35
+
+
+ 35
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -30
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 12
+ PER
+
+
+ 50
+ DIFF
+
+
+ 50
+ DIFF
+
+
+ 2
+ STR
+
+
+ 2
+ INT
+
+
+ 2
+ CON
+
+
+ 2
+ DEX
+
+
+ 2
+ MEN
+
+
+ 2
+ WIT
+
+
+ 100
+ DIFF
+
+
+ 100
+ DIFF
+
+
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip9
+ P
+ 500
+
+
+ 40
+
+
+ 40
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -40
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 13
+ PER
+
+
+ 13
+ PER
+
+
+ 13
+ PER
+
+
+ 80
+ DIFF
+
+
+ 80
+ DIFF
+
+
+ 3
+ STR
+
+
+ 3
+ INT
+
+
+ 3
+ CON
+
+
+ 3
+ DEX
+
+
+ 3
+ MEN
+
+
+ 3
+ WIT
+
+
+ 200
+ DIFF
+
+
+ 200
+ DIFF
+
+
-
-
- icon.skill0000
- A1
+
+
+ BranchIcon.Icon.g_skill_vip10
+ P
+ 500
+
+
+ 50
+
+
+ 50
+
+
+ 300
+ PER
+
+
+ 50
+ DIFF
+
+
+ -50
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 15
+ PER
+
+
+ 100
+ DIFF
+
+
+ 100
+ DIFF
+
+
+ 4
+ STR
+
+
+ 4
+ INT
+
+
+ 4
+ CON
+
+
+ 4
+ DEX
+
+
+ 4
+ MEN
+
+
+ 4
+ WIT
+
+
+ 500
+ DIFF
+
+
+ 500
+ DIFF
+
+
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/vip.xml b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/vip.xml
new file mode 100644
index 0000000000..a797c36aab
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/vip.xml
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/PrimeShop.xsd b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/PrimeShop.xsd
index 44a4e34fbe..8556f5ed3f 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/PrimeShop.xsd
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/PrimeShop.xsd
@@ -34,6 +34,8 @@
+
+
diff --git a/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/vip.xsd b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/vip.xsd
new file mode 100644
index 0000000000..bb2b4f589a
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/dist/game/data/xsd/vip.xsd
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/Config.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/Config.java
index 4223a2c10e..548d226ecf 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/Config.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/Config.java
@@ -134,6 +134,7 @@ public class Config
private static final String CUSTOM_OFFLINE_TRADE_CONFIG_FILE = "./config/Custom/OfflineTrade.ini";
private static final String CUSTOM_PASSWORD_CHANGE_CONFIG_FILE = "./config/Custom/PasswordChange.ini";
private static final String CUSTOM_PC_CAFE_CONFIG_FILE = "./config/Custom/PcCafe.ini";
+ private static final String CUSTOM_VIP_CONFIG_FILE = "./config/Custom/VipSystem.ini";
private static final String CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE = "./config/Custom/PremiumSystem.ini";
private static final String CUSTOM_PRIVATE_STORE_RANGE_CONFIG_FILE = "./config/Custom/PrivateStoreRange.ini";
private static final String CUSTOM_PVP_ANNOUNCE_CONFIG_FILE = "./config/Custom/PvpAnnounce.ini";
@@ -156,6 +157,7 @@ public class Config
public static boolean ENABLE_ATTENDANCE_REWARDS;
public static boolean PREMIUM_ONLY_ATTENDANCE_REWARDS;
+ public static boolean VIP_ONLY_ATTENDANCE_REWARDS;
public static boolean ATTENDANCE_REWARDS_SHARE_ACCOUNT;
public static int ATTENDANCE_REWARD_DELAY;
public static boolean ATTENDANCE_POPUP_START;
@@ -1261,6 +1263,7 @@ public class Config
public static boolean PREMIUM_ONLY_FISHING;
public static boolean PC_CAFE_ENABLED;
public static boolean PC_CAFE_ONLY_PREMIUM;
+ public static boolean PC_CAFE_ONLY_VIP;
public static int PC_CAFE_MAX_POINTS;
public static boolean PC_CAFE_ENABLE_DOUBLE_POINTS;
public static int PC_CAFE_DOUBLE_POINTS_CHANCE;
@@ -1268,6 +1271,10 @@ public class Config
public static boolean PC_CAFE_RANDOM_POINT;
public static boolean PC_CAFE_REWARD_LOW_EXP_KILLS;
public static int PC_CAFE_LOW_EXP_KILLS_CHANCE;
+ public static boolean VIP_SYSTEM_ENABLED;
+ public static boolean VIP_SYSTEM_PRIME_AFFECT;
+ public static boolean VIP_SYSTEM_L_SHOP_AFFECT;
+ public static int VIP_SYSTEM_MAX_TIER;
public static boolean SELLBUFF_ENABLED;
public static int SELLBUFF_MP_MULTIPLER;
public static int SELLBUFF_PAYMENT_ID;
@@ -1555,6 +1562,7 @@ public class Config
final PropertiesParser Attandance = new PropertiesParser(ATTENDANCE_CONFIG_FILE);
ENABLE_ATTENDANCE_REWARDS = Attandance.getBoolean("EnableAttendanceRewards", false);
PREMIUM_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("PremiumOnlyAttendanceRewards", false);
+ VIP_ONLY_ATTENDANCE_REWARDS = Attandance.getBoolean("VipOnlyAttendanceRewards", false);
ATTENDANCE_REWARDS_SHARE_ACCOUNT = Attandance.getBoolean("AttendanceRewardsShareAccount", false);
ATTENDANCE_REWARD_DELAY = Attandance.getInt("AttendanceRewardDelay", 30);
ATTENDANCE_POPUP_START = Attandance.getBoolean("AttendancePopupStart", true);
@@ -3259,6 +3267,7 @@ public class Config
final PropertiesParser PcCafe = new PropertiesParser(CUSTOM_PC_CAFE_CONFIG_FILE);
PC_CAFE_ENABLED = PcCafe.getBoolean("PcCafeEnabled", false);
PC_CAFE_ONLY_PREMIUM = PcCafe.getBoolean("PcCafeOnlyPremium", false);
+ PC_CAFE_ONLY_VIP = PcCafe.getBoolean("PcCafeOnlyVip", false);
PC_CAFE_MAX_POINTS = PcCafe.getInt("MaxPcCafePoints", 200000);
if (PC_CAFE_MAX_POINTS < 0)
{
@@ -3287,6 +3296,19 @@ public class Config
PC_CAFE_LOW_EXP_KILLS_CHANCE = 100;
}
+ final PropertiesParser vipSystem = new PropertiesParser(CUSTOM_VIP_CONFIG_FILE);
+ VIP_SYSTEM_ENABLED = vipSystem.getBoolean("VipEnabled", false);
+ if (VIP_SYSTEM_ENABLED)
+ {
+ VIP_SYSTEM_PRIME_AFFECT = vipSystem.getBoolean("PrimeAffectPoints", false);
+ VIP_SYSTEM_L_SHOP_AFFECT = vipSystem.getBoolean("LShopAffectPoints", false);
+ VIP_SYSTEM_MAX_TIER = vipSystem.getInt("MaxVipLevel", 7);
+ if (VIP_SYSTEM_MAX_TIER > 10)
+ {
+ VIP_SYSTEM_MAX_TIER = 10;
+ }
+ }
+
// Load PremiumSystem config file (if exists)
final PropertiesParser PremiumSystem = new PropertiesParser(CUSTOM_PREMIUM_SYSTEM_CONFIG_FILE);
PREMIUM_SYSTEM_ENABLED = PremiumSystem.getBoolean("EnablePremiumSystem", false);
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
index a34d920cb8..931130e54c 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/GameServer.java
@@ -111,6 +111,7 @@ import org.l2jmobius.gameserver.data.xml.TeleporterData;
import org.l2jmobius.gameserver.data.xml.TimedHuntingZoneData;
import org.l2jmobius.gameserver.data.xml.TransformData;
import org.l2jmobius.gameserver.data.xml.VariationData;
+import org.l2jmobius.gameserver.data.xml.VipData;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.handler.ConditionHandler;
import org.l2jmobius.gameserver.handler.DailyMissionHandler;
@@ -158,6 +159,7 @@ import org.l2jmobius.gameserver.model.World;
import org.l2jmobius.gameserver.model.events.EventDispatcher;
import org.l2jmobius.gameserver.model.olympiad.Hero;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.votereward.VoteSystem;
import org.l2jmobius.gameserver.network.ClientNetworkManager;
import org.l2jmobius.gameserver.network.NpcStringId;
@@ -293,6 +295,7 @@ public class GameServer
AttendanceRewardData.getInstance();
MagicLampData.getInstance();
RandomCraftData.getInstance();
+ VipData.getInstance();
printSection("Characters");
ClassListData.getInstance();
@@ -310,6 +313,7 @@ public class GameServer
CharSummonTable.getInstance().init();
BeautyShopData.getInstance();
MentorManager.getInstance();
+ VipManager.getInstance();
if (Config.FACTION_SYSTEM_ENABLED)
{
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/VipData.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/VipData.java
new file mode 100644
index 0000000000..f5321c909d
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/data/xml/VipData.java
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.data.xml;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.util.IXmlReader;
+import org.l2jmobius.gameserver.model.vip.VipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipData implements IXmlReader
+{
+ private static final Logger LOGGER = Logger.getLogger(VipData.class.getName());
+
+ private final Map _vipTiers = new HashMap<>();
+
+ protected VipData()
+ {
+ load();
+ }
+
+ @Override
+ public void load()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ _vipTiers.clear();
+ parseDatapackFile("data/vip.xml");
+ LOGGER.info(getClass().getSimpleName() + ": Loaded " + _vipTiers.size() + " vips.");
+ }
+
+ @Override
+ public void parseDocument(Document doc, File f)
+ {
+ for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
+ {
+ if ("list".equalsIgnoreCase(n.getNodeName()))
+ {
+ VIP_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
+ {
+ if ("vip".equalsIgnoreCase(d.getNodeName()))
+ {
+ final NamedNodeMap attrs = d.getAttributes();
+ Node att;
+ byte tier = -1;
+ int required = -1;
+ int lose = -1;
+
+ att = attrs.getNamedItem("tier");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing tier for vip, skipping");
+ continue;
+ }
+ tier = Byte.parseByte(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-required");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-required for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ required = Integer.parseInt(att.getNodeValue());
+
+ att = attrs.getNamedItem("points-lose");
+ if (att == null)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Missing points-lose for vip: " + tier + ", skipping");
+ continue;
+ }
+
+ lose = Integer.parseInt(att.getNodeValue());
+
+ final VipInfo vipInfo = new VipInfo(tier, required, lose);
+
+ for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
+ {
+ if ("bonus".equalsIgnoreCase(c.getNodeName()))
+ {
+ final int skill = Integer.parseInt(c.getAttributes().getNamedItem("skill").getNodeValue());
+ try
+ {
+ vipInfo.setSkill(skill);
+ }
+ catch (Exception e)
+ {
+ LOGGER.severe(getClass().getSimpleName() + ": Error in bonus parameter for vip: " + tier + ", skipping");
+ continue VIP_FILE;
+ }
+ }
+ }
+ _vipTiers.put(tier, vipInfo);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the single instance of VipData.
+ * @return single instance of VipData
+ */
+ public static VipData getInstance()
+ {
+ return SingletonHolder.INSTANCE;
+ }
+
+ /**
+ * The Class SingletonHolder.
+ */
+ private static class SingletonHolder
+ {
+ protected static final VipData INSTANCE = new VipData();
+ }
+
+ public int getSkillId(byte tier)
+ {
+ return _vipTiers.get(tier).getSkill();
+ }
+
+ public Map getVipTiers()
+ {
+ return _vipTiers;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
index 3d1883674b..b4f79804eb 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/DailyTaskManager.java
@@ -43,7 +43,9 @@ import org.l2jmobius.gameserver.model.eventengine.ScheduleTarget;
import org.l2jmobius.gameserver.model.holders.SkillHolder;
import org.l2jmobius.gameserver.model.holders.SubClassHolder;
import org.l2jmobius.gameserver.model.olympiad.Olympiad;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.network.serverpackets.ExVoteSystemInfo;
import org.l2jmobius.gameserver.network.serverpackets.ExWorldChatCnt;
@@ -73,6 +75,7 @@ public class DailyTaskManager extends AbstractEventManager>
resetWorldChatPoints();
resetTrainingCamp();
resetVitality();
+ resetVip();
}
@ScheduleTarget
@@ -324,6 +327,24 @@ public class DailyTaskManager extends AbstractEventManager>
}
}
+ private void resetVip()
+ {
+ // Delete all entries for received gifts
+ AccountVariables.deleteVipPurchases(AccountVariables.VIP_ITEM_BOUGHT);
+
+ // Checks the tier expiration for online players
+ // offline players get handled on next time they log in.
+ for (PlayerInstance player : World.getInstance().getPlayers())
+ {
+ if (player.getVipTier() > 0)
+ {
+ VipManager.getInstance().checkVipTierExpiration(player);
+ }
+
+ player.getAccountVariables().restoreMe();
+ }
+ }
+
private void resetDailyMissionRewards()
{
DailyMissionData.getInstance().getDailyMissionData().forEach(DailyMissionDataHolder::reset);
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
index e8dc9a0a23..ff8a8584e4 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/instancemanager/PcCafePointsManager.java
@@ -39,6 +39,11 @@ public class PcCafePointsManager
return;
}
+ if (Config.PC_CAFE_ONLY_VIP && (player.getVipTier() <= 0))
+ {
+ return;
+ }
+
if (player.getPcCafePoints() >= Config.PC_CAFE_MAX_POINTS)
{
final SystemMessage message = new SystemMessage(SystemMessageId.YOU_HAVE_EARNED_THE_MAXIMUM_NUMBER_OF_PA_POINTS);
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
index f01a0619b3..6c09567cb4 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/actor/instance/PlayerInstance.java
@@ -21,6 +21,8 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -206,6 +208,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerFameCh
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaAdd;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerHennaRemove;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemEquip;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeStatus;
@@ -283,6 +286,7 @@ import org.l2jmobius.gameserver.model.stats.MoveType;
import org.l2jmobius.gameserver.model.stats.Stat;
import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.model.variables.PlayerVariables;
+import org.l2jmobius.gameserver.model.vip.VipManager;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.model.zone.ZoneType;
import org.l2jmobius.gameserver.model.zone.type.WaterZone;
@@ -363,6 +367,7 @@ import org.l2jmobius.gameserver.network.serverpackets.autoplay.ExAutoPlaySetting
import org.l2jmobius.gameserver.network.serverpackets.commission.ExResponseCommissionInfo;
import org.l2jmobius.gameserver.network.serverpackets.friend.FriendStatus;
import org.l2jmobius.gameserver.network.serverpackets.limitshop.ExBloodyCoinCount;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
import org.l2jmobius.gameserver.taskmanager.AttackStanceTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoPlayTaskManager;
import org.l2jmobius.gameserver.taskmanager.AutoUseTaskManager;
@@ -885,6 +890,8 @@ public class PlayerInstance extends Playable
private ElementalSpirit[] _spirits;
private ElementalType _activeElementalSpiritType;
+ private byte _vipTier = 0;
+
private final AutoPlaySettingsHolder _autoPlaySettings = new AutoPlaySettingsHolder();
private final AutoUseSettingsHolder _autoUseSettings = new AutoUseSettingsHolder();
@@ -6677,6 +6684,7 @@ public class PlayerInstance extends Playable
}
}
}
+ EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLoad(player), player);
}
}
@@ -6780,6 +6788,7 @@ public class PlayerInstance extends Playable
player.setOnlineStatus(true, false);
PlayerAutoSaveTaskManager.getInstance().add(player);
+
}
catch (Exception e)
{
@@ -10077,6 +10086,7 @@ public class PlayerInstance extends Playable
}
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerLogin(this), this);
+
if (isMentee())
{
// Notify to scripts
@@ -14261,6 +14271,57 @@ public class PlayerInstance extends Playable
}
}
+ public byte getVipTier()
+ {
+ return _vipTier;
+ }
+
+ public void setVipTier(byte vipTier)
+ {
+ _vipTier = vipTier;
+ }
+
+ public long getVipPoints()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_POINTS, 0L);
+ }
+
+ public long getVipTierExpiration()
+ {
+ return getAccountVariables().getLong(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+
+ public void setVipTierExpiration(long expiration)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, expiration);
+ }
+
+ public void updateVipPoints(long points)
+ {
+ if (points == 0)
+ {
+ return;
+ }
+ final int currentVipTier = VipManager.getInstance().getVipTier(getVipPoints());
+ getAccountVariables().set(AccountVariables.VIP_POINTS, getVipPoints() + points);
+ final byte newTier = VipManager.getInstance().getVipTier(getVipPoints());
+ if (newTier != currentVipTier)
+ {
+ _vipTier = newTier;
+ if (newTier > 0)
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ VipManager.getInstance().manageTier(this);
+ }
+ else
+ {
+ getAccountVariables().set(AccountVariables.VIP_EXPIRATION, 0L);
+ }
+ }
+ getAccountVariables().storeMe(); // force to store to prevent falty purchases after a crash.
+ sendPacket(new ReceiveVipInfo(this));
+ }
+
public void initElementalSpirits()
{
tryLoadSpirits();
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/EventType.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/EventType.java
index 51c19667fd..8cf9f32b70 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/EventType.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/EventType.java
@@ -90,6 +90,7 @@ import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemPi
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemTransfer;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerItemUnequip;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLevelChanged;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogout;
import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerMenteeAdd;
@@ -259,6 +260,7 @@ public enum EventType
ON_PLAYER_LEVEL_CHANGED(OnPlayerLevelChanged.class, void.class),
ON_PLAYER_LOGIN(OnPlayerLogin.class, void.class),
ON_PLAYER_LOGOUT(OnPlayerLogout.class, void.class),
+ ON_PLAYER_LOAD(OnPlayerLoad.class, void.class),
ON_PLAYER_PK_CHANGED(OnPlayerPKChanged.class, void.class),
ON_PLAYER_PRESS_TUTORIAL_MARK(OnPlayerPressTutorialMark.class, void.class),
ON_PLAYER_MOVE_REQUEST(OnPlayerMoveRequest.class, void.class, TerminateReturn.class),
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
new file mode 100644
index 0000000000..ae746647f8
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/events/impl/creature/player/OnPlayerLoad.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.events.impl.creature.player;
+
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.IBaseEvent;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class OnPlayerLoad implements IBaseEvent
+{
+ private final PlayerInstance _player;
+
+ public OnPlayerLoad(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ public PlayerInstance getPlayer()
+ {
+ return _player;
+ }
+
+ @Override
+ public EventType getType()
+ {
+ return EventType.ON_PLAYER_LOAD;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
index d1efd49454..b41635fc4d 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/primeshop/PrimeShopGroup.java
@@ -47,6 +47,8 @@ public class PrimeShopGroup
private final int _maxBirthday;
private final int _restrictionDay;
private final int _availableCount;
+ private final boolean _isVipGift;
+ private final int _vipTier;
private final List _items;
public PrimeShopGroup(StatSet set, List items)
@@ -73,6 +75,9 @@ public class PrimeShopGroup
_maxBirthday = set.getInt("maxBirthday", 0);
_restrictionDay = set.getInt("restrictionDay", 0);
_availableCount = set.getInt("availableCount", 0);
+ _isVipGift = set.getBoolean("isVipGift", false);
+ _vipTier = set.getInt("vipTier", 0);
+
_items = items;
}
@@ -196,6 +201,16 @@ public class PrimeShopGroup
return _availableCount;
}
+ public boolean isVipGift()
+ {
+ return _isVipGift;
+ }
+
+ public int getVipTier()
+ {
+ return _vipTier;
+ }
+
public List getItems()
{
return _items;
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
index dbb4b300bd..019fd7b35b 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/variables/AccountVariables.java
@@ -37,12 +37,17 @@ public class AccountVariables extends AbstractVariables
private static final String SELECT_QUERY = "SELECT * FROM account_gsdata WHERE account_name = ?";
private static final String DELETE_QUERY = "DELETE FROM account_gsdata WHERE account_name = ?";
private static final String INSERT_QUERY = "INSERT INTO account_gsdata (account_name, var, value) VALUES (?, ?, ?)";
+ private static final String DELETE_QUERY_VAR = "DELETE FROM account_gsdata where var = ?";
// Public variable names
public static final String HWID = "HWID";
public static final String HWIDSLIT_VAR = " ";
public static final String LCOIN_SHOP_PRODUCT_TIME = "LCSTime";
public static final String LCOIN_SHOP_PRODUCT_COUNT = "LCSCount";
+ public static final String VIP_POINTS = "VipPoints";
+ public static final String VIP_TIER = "VipTier";
+ public static final String VIP_EXPIRATION = "VipExpiration";
+ public static final String VIP_ITEM_BOUGHT = "Vip_Item_Bought";
private final String _accountName;
@@ -145,4 +150,28 @@ public class AccountVariables extends AbstractVariables
}
return true;
}
+
+ /**
+ * Delete all entries for an requested var
+ * @param var
+ * @return success
+ */
+ public static boolean deleteVipPurchases(String var)
+ {
+ try (Connection con = DatabaseFactory.getConnection())
+ {
+ // Clear previous entries.
+ try (PreparedStatement st = con.prepareStatement(DELETE_QUERY_VAR))
+ {
+ st.setString(1, var);
+ st.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ LOGGER.log(Level.WARNING, "AccountVariables: Couldn't delete vip variables!", e);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
new file mode 100644
index 0000000000..6c1121eb92
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class VipInfo
+{
+ private final byte _tier;
+ private final long _pointsRequired;
+ private final long _pointsDepreciated;
+ private int _skill;
+
+ public VipInfo(byte tier, long pointsRequired, long pointsDepreciated)
+ {
+ _tier = tier;
+ _pointsRequired = pointsRequired;
+ _pointsDepreciated = pointsDepreciated;
+ }
+
+ public byte getTier()
+ {
+ return _tier;
+ }
+
+ public long getPointsRequired()
+ {
+ return _pointsRequired;
+ }
+
+ public long getPointsDepreciated()
+ {
+ return _pointsDepreciated;
+ }
+
+ public int getSkill()
+ {
+ return _skill;
+ }
+
+ public void setSkill(int skill)
+ {
+ _skill = skill;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipManager.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipManager.java
new file mode 100644
index 0000000000..9e427b6e91
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/model/vip/VipManager.java
@@ -0,0 +1,202 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.model.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.function.Consumer;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.gameserver.data.xml.SkillData;
+import org.l2jmobius.gameserver.data.xml.VipData;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.events.Containers;
+import org.l2jmobius.gameserver.model.events.EventType;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLoad;
+import org.l2jmobius.gameserver.model.events.impl.creature.player.OnPlayerLogin;
+import org.l2jmobius.gameserver.model.events.listeners.ConsumerEventListener;
+import org.l2jmobius.gameserver.model.skills.Skill;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
+import org.l2jmobius.gameserver.network.serverpackets.ExBRNewIconCashBtnWnd;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public final class VipManager
+{
+ private static final byte VIP_MAX_TIER = (byte) Config.VIP_SYSTEM_MAX_TIER;
+
+ private final ConsumerEventListener _vipLoginListener = new ConsumerEventListener(null, EventType.ON_PLAYER_LOGIN, (Consumer) this::onVipLogin, this);
+
+ private VipManager()
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return;
+ }
+ Containers.Global().addListener(new ConsumerEventListener(Containers.Global(), EventType.ON_PLAYER_LOAD, (Consumer) this::onPlayerLoaded, this));
+ }
+
+ private void onPlayerLoaded(OnPlayerLoad event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ player.setVipTier(getVipTier(player));
+ if (player.getVipTier() > 0)
+ {
+ manageTier(player);
+ player.addListener(_vipLoginListener);
+ }
+ else
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ }
+
+ private boolean canReceiveGift(PlayerInstance player)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ return player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0) <= 0;
+ }
+
+ private void onVipLogin(OnPlayerLogin event)
+ {
+ final PlayerInstance player = event.getPlayer();
+ if (canReceiveGift(player))
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 1));
+ }
+ else
+ {
+ player.sendPacket(new ExBRNewIconCashBtnWnd((byte) 0));
+ }
+ player.removeListener(_vipLoginListener);
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ public void manageTier(PlayerInstance player)
+ {
+ if (!checkVipTierExpiration(player))
+ {
+ player.sendPacket(new ReceiveVipInfo(player));
+ }
+
+ if (player.getVipTier() > 1)
+ {
+ final int oldSkillId = VipData.getInstance().getSkillId((byte) (player.getVipTier() - 1));
+ if (oldSkillId > 0)
+ {
+ final Skill oldSkill = SkillData.getInstance().getSkill(oldSkillId, 1);
+ if (oldSkill != null)
+ {
+ player.removeSkill(oldSkill);
+ }
+ }
+ }
+
+ final int skillId = VipData.getInstance().getSkillId(player.getVipTier());
+ if (skillId > 0)
+ {
+ final Skill skill = SkillData.getInstance().getSkill(skillId, 1);
+ if (skill != null)
+ {
+ player.addSkill(skill);
+ }
+ }
+ }
+
+ public byte getVipTier(PlayerInstance player)
+ {
+ return getVipInfo(player).getTier();
+ }
+
+ public byte getVipTier(long points)
+ {
+ byte temp = getVipInfo(points).getTier();
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return temp;
+ }
+
+ private VipInfo getVipInfo(PlayerInstance player)
+ {
+ return getVipInfo(player.getVipPoints());
+ }
+
+ private VipInfo getVipInfo(long points)
+ {
+ for (byte i = 0; i < VipData.getInstance().getVipTiers().size(); i++)
+ {
+ if (points < VipData.getInstance().getVipTiers().get(i).getPointsRequired())
+ {
+ byte temp = (byte) (i - 1);
+ if (temp > VIP_MAX_TIER)
+ {
+ temp = VIP_MAX_TIER;
+ }
+ return VipData.getInstance().getVipTiers().get(temp);
+ }
+ }
+ return VipData.getInstance().getVipTiers().get(VIP_MAX_TIER);
+ }
+
+ public long getPointsDepreciatedOnLevel(byte vipTier)
+ {
+ return VipData.getInstance().getVipTiers().get(vipTier).getPointsDepreciated();
+ }
+
+ public long getPointsToLevel(byte level)
+ {
+ if (VipData.getInstance().getVipTiers().containsKey(level))
+ {
+ return VipData.getInstance().getVipTiers().get(level).getPointsRequired();
+ }
+ return 0;
+ }
+
+ public boolean checkVipTierExpiration(PlayerInstance player)
+ {
+ final Instant now = Instant.now();
+ if (now.isAfter(Instant.ofEpochMilli(player.getVipTierExpiration())))
+ {
+ player.updateVipPoints(-getPointsDepreciatedOnLevel(player.getVipTier()));
+ player.setVipTierExpiration(Instant.now().plus(30, ChronoUnit.DAYS).toEpochMilli());
+ return true;
+ }
+ return false;
+ }
+
+ public static VipManager getInstance()
+ {
+ return Singleton.INSTANCE;
+ }
+
+ private static class Singleton
+ {
+ private static final VipManager INSTANCE = new VipManager();
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
index 922bfbd13f..cb67b9cd28 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/ExIncomingPackets.java
@@ -131,6 +131,8 @@ import org.l2jmobius.gameserver.network.clientpackets.teleports.ExRequestTelepor
import org.l2jmobius.gameserver.network.clientpackets.teleports.ExTeleportToRaidPosition;
import org.l2jmobius.gameserver.network.clientpackets.teleports.RequestRaidTeleportInfo;
import org.l2jmobius.gameserver.network.clientpackets.training.NotifyTrainingRoomEnd;
+import org.l2jmobius.gameserver.network.clientpackets.vip.ExRequestVipInfo;
+import org.l2jmobius.gameserver.network.clientpackets.vip.RequestVipLuckGameInfo;
/**
* @author Sdw
@@ -402,10 +404,10 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_ITEM_ENSOUL(0x107, RequestItemEnsoul::new, ConnectionState.IN_GAME),
REQUEST_CASTLE_WAR_SEASON_REWARD(0x108, null, ConnectionState.IN_GAME),
REQUEST_VIP_PRODUCT_LIST(0x109, null, ConnectionState.IN_GAME),
- REQUEST_VIP_LUCKY_GAME_INFO(0x10A, null, ConnectionState.IN_GAME),
+ REQUEST_VIP_LUCKY_GAME_INFO(0x10A, RequestVipLuckGameInfo::new, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_ITEM_LIST(0x10B, null, ConnectionState.IN_GAME),
REQUEST_VIP_LUCKY_GAME_BONUS(0x10C, null, ConnectionState.IN_GAME),
- EX_REQUEST_VIP_INFO(0x10D, null, ConnectionState.IN_GAME),
+ EX_REQUEST_VIP_INFO(0x10D, ExRequestVipInfo::new, ConnectionState.IN_GAME),
REQUEST_CAPTCHA_ANSWER(0x10E, null, ConnectionState.IN_GAME),
REQUEST_REFRESH_CAPTCHA_IMAGE(0x10F, null, ConnectionState.IN_GAME),
REQUEST_PLEDGE_SIGN_IN_FOR_OPEN_JOINING_METHOD(0x110, RequestPledgeSignInForOpenJoiningMethod::new, ConnectionState.IN_GAME),
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
index 79380f3bfa..3b5f49ea1f 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/attendance/RequestVipAttendanceCheck.java
@@ -61,6 +61,11 @@ public class RequestVipAttendanceCheck implements IClientIncomingPacket
player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
return;
}
+ else if (Config.VIP_ONLY_ATTENDANCE_REWARDS && (player.getVipTier() <= 0))
+ {
+ player.sendPacket(SystemMessageId.YOUR_VIP_RANK_IS_TOO_LOW_TO_RECEIVE_THE_REWARD);
+ return;
+ }
// Check login delay.
if (player.getUptime() < (Config.ATTENDANCE_REWARD_DELAY * 60 * 1000))
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
index ded9410a2e..020206bdc3 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/limitshop/RequestPurchaseLimitShopItemBuy.java
@@ -19,6 +19,7 @@ package org.l2jmobius.gameserver.network.clientpackets.limitshop;
import java.util.ArrayList;
import java.util.List;
+import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.commons.util.Chronos;
import org.l2jmobius.commons.util.Rnd;
@@ -193,6 +194,10 @@ public class RequestPurchaseLimitShopItemBuy implements IClientIncomingPacket
{
player.destroyItemByItemId("LCoinShop", _product.getIngredientIds()[i], _product.getIngredientQuantities()[i] * _amount, player, true);
}
+ if (Config.VIP_SYSTEM_L_SHOP_AFFECT)
+ {
+ player.updateVipPoints(_amount);
+ }
}
// Reward.
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
index 1e8aba6d16..71ac7c2f4e 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRBuyProduct.java
@@ -27,6 +27,7 @@ import org.l2jmobius.gameserver.model.actor.request.PrimeShopRequest;
import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopGroup;
import org.l2jmobius.gameserver.model.primeshop.PrimeShopItem;
+import org.l2jmobius.gameserver.model.variables.AccountVariables;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.primeshop.ExBRBuyProduct;
@@ -98,13 +99,20 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
for (PrimeShopItem subItem : item.getItems())
{
player.addItem("PrimeShop", subItem.getId(), subItem.getCount() * _count, player, true);
}
-
+ if (item.isVipGift())
+ {
+ player.getAccountVariables().set(AccountVariables.VIP_ITEM_BOUGHT, Calendar.getInstance().getTimeInMillis());
+ }
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
player.sendPacket(new ExBRGamePoint(player));
}
@@ -169,6 +177,12 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return false;
}
+ if ((item.getVipTier() > player.getVipTier()) || (item.isVipGift() && !canReceiveGift(player, item)))
+ {
+ player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SOLD_OUT));
+ return false;
+ }
+
final int weight = item.getWeight() * count;
final long slots = item.getCount() * count;
if (player.getInventory().validateWeight(weight))
@@ -188,6 +202,34 @@ public class RequestBRBuyProduct implements IClientIncomingPacket
return true;
}
+ /**
+ * Check if player can receive Gift from L2 Store
+ * @param player player in question
+ * @param item requested item.
+ * @return true if player can receive gift item.
+ */
+ private static boolean canReceiveGift(PlayerInstance player, PrimeShopGroup item)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+ if (player.getVipTier() <= 0)
+ {
+ return false;
+ }
+ else if (item.getVipTier() != player.getVipTier())
+ {
+ player.sendMessage("This item is not for your vip tier!");
+ return false;
+ }
+ else
+ {
+ long timeBought = player.getAccountVariables().getLong(AccountVariables.VIP_ITEM_BOUGHT, 0L);
+ return timeBought <= 0;
+ }
+ }
+
private static int validatePaymentId(PrimeShopGroup item, long amount)
{
switch (item.getPaymentType())
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
index 9c076a29a5..189fb14f54 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/primeshop/RequestBRPresentBuyProduct.java
@@ -88,6 +88,13 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
player.addRequest(new PrimeShopRequest(player));
final PrimeShopGroup item = PrimeShopData.getInstance().getItem(_brId);
+
+ if (item.isVipGift())
+ {
+ player.sendMessage("You cannot gift a Vip Gift!");
+ return;
+ }
+
if (validatePlayer(item, _count, player))
{
final int price = (item.getPrice() * _count);
@@ -116,6 +123,10 @@ public class RequestBRPresentBuyProduct implements IClientIncomingPacket
return;
}
player.setPrimePoints(player.getPrimePoints() - price);
+ if (Config.VIP_SYSTEM_PRIME_AFFECT)
+ {
+ player.updateVipPoints(price);
+ }
}
player.sendPacket(new ExBRBuyProduct(ExBrProductReplyType.SUCCESS));
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
new file mode 100644
index 0000000000..2fb7f915e8
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/ExRequestVipInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipInfo;
+
+public class ExRequestVipInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
new file mode 100644
index 0000000000..d248722d3d
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/clientpackets/vip/RequestVipLuckGameInfo.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.clientpackets.vip;
+
+import org.l2jmobius.commons.network.PacketReader;
+import org.l2jmobius.gameserver.network.GameClient;
+import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
+import org.l2jmobius.gameserver.network.serverpackets.vip.ReceiveVipLuckyGameInfo;
+
+public class RequestVipLuckGameInfo implements IClientIncomingPacket
+{
+ @Override
+ public boolean read(GameClient client, PacketReader packet)
+ {
+ return true;
+ }
+
+ @Override
+ public void run(GameClient client)
+ {
+ client.sendPacket(new ReceiveVipLuckyGameInfo(client.getPlayer()));
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
new file mode 100644
index 0000000000..5046567b90
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBRNewIconCashBtnWnd.java
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ExBRNewIconCashBtnWnd implements IClientOutgoingPacket
+{
+ private final short _active;
+
+ public ExBRNewIconCashBtnWnd(short active)
+ {
+ _active = active;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.EX_BR_NEW_ICON_CASH_BTN_WND.writeId(packet);
+ packet.writeH(_active);
+ return true;
+ }
+}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
index 951739da07..6b5d6bf393 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExBrPremiumState.java
@@ -38,7 +38,7 @@ public class ExBrPremiumState implements IClientOutgoingPacket
OutgoingPackets.EX_BR_PREMIUM_STATE.writeId(packet);
packet.writeD(_player.getObjectId());
- packet.writeC(_player.hasPremiumStatus() ? 0x01 : 0x00);
+ packet.writeC(_player.hasPremiumStatus() || (_player.getVipTier() > 0) ? 0x01 : 0x00);
return true;
}
}
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
index 3cef4b3bcd..ccbbcbdf70 100644
--- a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/ExWorldChatCnt.java
@@ -30,7 +30,7 @@ public class ExWorldChatCnt implements IClientOutgoingPacket
public ExWorldChatCnt(PlayerInstance player)
{
- _points = player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
+ _points = (player.getLevel() < Config.WORLD_CHAT_MIN_LEVEL) || (player.getVipTier() <= 0) ? 0 : Math.max(player.getWorldChatPoints() - player.getWorldChatUsed(), 0);
}
@Override
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
new file mode 100644
index 0000000000..1f0c48549f
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipInfo.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import org.l2jmobius.Config;
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.vip.VipManager;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+public class ReceiveVipInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ if (!Config.VIP_SYSTEM_ENABLED)
+ {
+ return false;
+ }
+
+ final VipManager vipManager = VipManager.getInstance();
+ final byte vipTier = _player.getVipTier();
+ final int vipDuration = (int) ChronoUnit.SECONDS.between(Instant.now(), Instant.ofEpochMilli(_player.getVipTierExpiration()));
+
+ OutgoingPackets.RECIVE_VIP_INFO.writeId(packet);
+ packet.writeC(vipTier);
+ packet.writeQ(_player.getVipPoints());
+ packet.writeD(vipDuration);
+ packet.writeQ(vipManager.getPointsToLevel((byte) (vipTier + 1)));
+ packet.writeQ(vipManager.getPointsDepreciatedOnLevel(vipTier));
+ packet.writeC(vipTier);
+ packet.writeQ(vipManager.getPointsToLevel(vipTier));
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
new file mode 100644
index 0000000000..807f938c81
--- /dev/null
+++ b/L2J_Mobius_Essence_5.0_Sylph/java/org/l2jmobius/gameserver/network/serverpackets/vip/ReceiveVipLuckyGameInfo.java
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.l2jmobius.gameserver.network.serverpackets.vip;
+
+import org.l2jmobius.commons.network.PacketWriter;
+import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
+import org.l2jmobius.gameserver.model.itemcontainer.Inventory;
+import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
+import org.l2jmobius.gameserver.network.OutgoingPackets;
+import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
+
+/**
+ * @author Gabriel Costa Souza
+ */
+public class ReceiveVipLuckyGameInfo implements IClientOutgoingPacket
+{
+ private final PlayerInstance _player;
+
+ public ReceiveVipLuckyGameInfo(PlayerInstance player)
+ {
+ _player = player;
+ }
+
+ @Override
+ public boolean write(PacketWriter packet)
+ {
+ OutgoingPackets.RECIVE_VIP_LUCKY_GAME_INFO.writeId(packet);
+ packet.writeC(1); // enabled
+ packet.writeH((int) _player.getAdena());
+ final ItemInstance item = _player.getInventory().getItemByItemId(Inventory.LCOIN_ID);
+ packet.writeH(item == null ? 0 : (int) item.getCount()); // L Coin count
+ return true;
+ }
+}