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; + } +}